npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@collage-dam/mcp-server

v0.4.1

Published

Model Context Protocol (MCP) server for the Collage Digital Asset Management platform. Exposes Collage workspaces — assets, folders, Collages, share links, audit prompts — to AI clients (Claude Desktop, Cursor, ChatGPT) through a typed tool surface.

Readme

@collage-dam/mcp-server

npm

MCP server for the Collage Digital Asset Management platform. Lets MCP clients (Claude Desktop, Cursor, etc.) read and operate on a Collage workspace through a typed tool surface.

The package name on npm is @collage-dam/mcp-server; the CLI binary it installs is collage-mcp.

Status: pre-1.0. Phase 1 ships read-only smoke tools. Mutating tools arrive once the dry-run framework spec lands.


Requirements

  • Node.js >= 20
  • A Collage account with API access (see "Getting credentials" below)
  • Redis (only required when running the streamable-HTTP transport — docker compose up redis is provided)

Search now flows through Collage's Nuxt /typesense/search proxy on app.collage.inc. No separate Typesense credentials are needed — the existing Collage Bearer token is the only auth required.


Quickstart (install from npm)

For end users who just want to run the server:

# One-shot via npx (no install — pulls latest)
COLLAGE_API_KEY=... \
COLLAGE_WORKSPACE_ID=... \
MCP_CONFIRMATION_SECRET=... \
npx @collage-dam/mcp-server

# Or install globally and run as `collage-mcp`
npm install -g @collage-dam/mcp-server
collage-mcp

See Getting credentials below for the env vars, and Wiring into Claude Desktop for client config snippets.

Quickstart (local development)

For contributing to the server or running unreleased code:

git clone https://github.com/southleft/collage-mcp.git
cd collage-mcp
npm install
cp .env.example .env
# fill in COLLAGE_API_KEY, COLLAGE_WORKSPACE_ID, MCP_CONFIRMATION_SECRET
npm run dev          # stdio transport against the configured workspace

Getting credentials

COLLAGE_API_KEY

Collage does not have a dedicated "API Keys" UI. The token is the JWT issued by POST /api/v1/login and stored client-side after a normal web sign-in. To extract it:

  1. Sign into app.collage.inc with a workspace user account.
  2. Open DevTools → Network tab.
  3. Click any request to damapi.collage.inc/api/v1/....
  4. Copy the Authorization header value and strip the leading Bearer .
  5. The remainder is the raw JWT — paste it into COLLAGE_API_KEY.

Alternative: DevTools → Application → Local Storage → https://app.collage.incauth._token.local (Nuxt-Auth default). Same value, also prefixed with Bearer .

⚠️ JWT caveat. This token is bound to the signed-in user, not a dedicated service account. It expires when the user's session does and rotates on every fresh login. For long-lived MCP deployments, use a dedicated workspace user whose session you control. The MCP server redacts the token from its own logs; anything that imports your .env directly is on its own — use redactSensitiveFields() if you log request bodies.

COLLAGE_WORKSPACE_ID

The numeric workspace ID from any URL inside the Collage admin — https://app.collage.inc/<workspace_id>/dam-dashboard. The BREZ demo workspace is 6307594138.

COLLAGE_SEARCH_BASE (optional)

Search no longer requires Typesense credentials. The MCP server POSTs to the Nuxt /typesense/search proxy on app.collage.inc, which verifies the inbound COLLAGE_API_KEY Bearer token via Laravel's /user endpoint and resolves the workspace scope server-side.

The default base URL is https://app.collage.inc. Override only for staging or self-hosted Collage deployments where the frontend is on a different host.

MCP_CONFIRMATION_SECRET

Any high-entropy string (32+ bytes recommended). Used to HMAC-sign dry-run confirmation tokens. Rotate by changing the value; in-flight confirmations are invalidated by design.

openssl rand -hex 32   # generate one

Smoke test (stdio)

After filling .env, run:

npm run dev

The server connects over stdio and waits for an MCP client. Logs go to stderr; stdout is reserved for MCP framing.

Wiring into Claude Desktop

Add the following to your Claude Desktop config file (macOS: ~/Library/Application Support/Claude/claude_desktop_config.json):

{
  "mcpServers": {
    "collage": {
      "command": "npx",
      "args": ["-y", "@collage-dam/mcp-server"],
      "env": {
        "COLLAGE_API_KEY": "...",
        "COLLAGE_WORKSPACE_ID": "1927483178",
        "MCP_CONFIRMATION_SECRET": "..."
      }
    }
  }
}

Restart Claude Desktop, then ask it to call list_workspaces. A successful response returns a single workspace with has_access: true.

Troubleshooting — "Server disconnected" / Cannot find module 'node:path'. Claude Desktop does not inherit your interactive shell's PATH, so the npx above resolves node from whatever the app sees first. If that happens to be a Node older than the required v20, npx crashes before the server starts (the node: module scheme didn't exist until Node 14.18/16), and Claude Desktop reports the server as disconnected.

Fix: make sure the node on your login PATH is ≥ 20 (node --version). If you use a version manager (nvm, asdf, volta) and still hit this, point the config at an explicit modern node instead of bare npx:

{
  "command": "/absolute/path/to/node",
  "args": ["/absolute/path/to/npm/bin/npx-cli.js", "-y", "@collage-dam/mcp-server"]
}

— or install globally on a Node ≥ 20 runtime and use "command": "collage-mcp".

If you've cloned the repo for local development, point Claude Desktop at the built file instead:

{
  "mcpServers": {
    "collage": {
      "command": "node",
      "args": ["/absolute/path/to/collage-mcp/dist/index.js"],
      "env": { "...": "..." }
    }
  }
}

…or run the TypeScript source directly via tsx:

{
  "command": "npx",
  "args": ["tsx", "/absolute/path/to/collage-mcp/src/index.ts"]
}

Wiring into Cursor

Cursor reads MCP servers from ~/.cursor/mcp.json (or <project>/.cursor/mcp.json for project-scoped servers). The shape is identical to Claude Desktop:

{
  "mcpServers": {
    "collage": {
      "command": "npx",
      "args": ["-y", "@collage-dam/mcp-server"],
      "env": {
        "COLLAGE_API_KEY": "...",
        "COLLAGE_WORKSPACE_ID": "1927483178",
        "MCP_CONFIRMATION_SECRET": "..."
      }
    }
  }
}

Restart Cursor after editing. Tools appear under the chat composer.

Wiring into raw stdio (any MCP client)

For any MCP client that spawns a server over stdio, the canonical command after npm run build:

node /absolute/path/to/collage-mcp/dist/index.js

The server reads its config from environment variables — set them in the parent shell or via your client's config block. Logs go to stderr (fd 2); stdout is reserved for MCP framing. Anything that writes to stdout in the server process WILL corrupt the protocol.

Wiring via npx (after publish)

Once published to npm:

npx @collage-dam/mcp-server

The CLI binary is named collage-mcp, so you can also install globally and invoke directly:

npm install -g @collage-dam/mcp-server
collage-mcp

The same env vars are read from the parent shell.


Invoking guided workflows

Four MCP prompts ship as named guided workflows — they orchestrate the underlying tools and resources end-to-end so a user can trigger a complex flow by name instead of stitching tool calls themselves:

| Prompt | What it does | | --- | --- | | library_health_audit | Workspace-wide audit (metadata / tags / structure). Returns a scored report with non-executed mutation proposals. | | collection_audit | Single-collection deep-dive (with pattern-derived suggestions) or portfolio-wide overview. | | create_distribution | Conversational "build a share link for an audience" workflow. | | usage_insights | Engagement summary across share links and assets (degraded MVP slice). |

How to invoke

The MCP protocol exposes prompts via prompts/list + prompts/get, and the server registers all four correctly. However, current Claude Desktop builds do not surface MCP prompts in the slash menu or + attachment menu — a UI gap on the client side. Until Anthropic ships prompt UI, two fallback paths cover the same workflows:

Path A — start_* tool aliases (recommended for Claude Desktop)

Each prompt has a thin wrapper tool that re-emits the same playbook body through the standard tool surface (which Claude Desktop does surface):

  • start_library_health_audit
  • start_collection_audit
  • start_create_distribution
  • start_usage_insights

In a fresh Claude Desktop chat: "Run the start_library_health_audit tool with default arguments." Claude approves, calls the tool, gets the playbook back, and walks the orchestration. Tool descriptions are explicitly marked TEMPORARY FALLBACK so the sunset path is clear.

Path B — npm run prompt -- <name> CLI helper

For local QA or copy-paste into any MCP client:

npm run prompt                                          # list available prompts
npm run prompt -- library_health_audit                  # default args, copy to clipboard (macOS)
npm run prompt -- create_distribution '{"audience":"Q2 dealer kit"}'
npm run prompt -- usage_insights --no-copy              # print only

Output goes to stdout. On macOS the playbook is copied to the system clipboard via pbcopy — paste into a fresh chat to seed the workflow.

Both paths emit the same playbook body; the underlying prompt is the source of truth in either case.


Available surface (Phase 1)

The server exposes three MCP primitives: tools (actions), resources (read-only URI-addressable state), and prompts (guided workflows).

Tools (30)

Read tools: list_workspaces, list_collages, get_collage, get_asset_details, list_custom_fields, list_folders, view_folder_contents, list_share_links, get_embed_code, search_assets, search_collages, audit_tagging_hygiene.

Mutating tools (each gated by the dry-run framework — see Mutation safety below): rename_asset, update_asset_metadata, bulk_set_tags, bulk_add_tags, bulk_remove_tags, create_collage, update_collage, add_to_collage, remove_from_collage, create_share_link, revoke_share_link, create_folder, rename_folder, move_asset.

Prompt tool-aliases (UI fallback — see Invoking guided workflows above): start_library_health_audit, start_collection_audit, start_create_distribution, start_usage_insights.

Resources (10)

collage://folders, collage://folders/{id}, collage://portals, collage://portals/{id}, collage://assets/recent, collage://dashboard, collage://assets/{id}, collage://collections, collage://collections/{id}, collage://custom-fields. All read-only and JSON-shaped, with cursor pagination and the shared 12K-token response budget applied to list shapes.

The folder tree resource walks sub-category-list recursively under the hood — upstream all-category-list returns roots only by design, so the resource flattens the full tree with parent_id per row.

Prompts (4)

library_health_audit, collection_audit, create_distribution, usage_insights. See the Invoking guided workflows section above.

More tools, resources, and prompts land as the remaining specs ship — see the project portal for the live roadmap.


Mutation safety

Every mutating tool (rename_asset, update_asset_metadata, bulk_*_tags, create_collection, add_to_collection, create_share_link, create_folder, rename_folder, move_asset, etc.) is gated by the dry-run framework:

  1. Plan. First call returns a structured preview — change list, risk flags, aggregates, plus a signed confirmation_token.
  2. Execute. Caller echoes the token back to actually perform the mutation. Tokens are single-use and HMAC-signed.

Confirmation token TTL

The token has two lifetimes:

| Window | Default | Behaviour | | --- | --- | --- | | Soft expiry (confirmation.ttl_seconds) | 15 min | Visible to the caller in the preview response. Past this window the framework re-plans before executing — see auto-refresh below. | | Memo expiry (plan-store TTL) | 60 min | The plan record itself stays in the ephemeral state store this long. Past this window the token is genuinely dead. |

Per-tool overrides go through confirmationTtlMs on the MutatingTool constructor — useful for very-long-running review workflows.

Auto-refresh

When an execute call arrives after the soft expiry but the plan record is still in the memo store, the framework:

  1. Re-runs plan(input) with the same input the caller supplied
  2. Computes a stable fingerprint of the new change list (sha256 over a canonicalised [id, operation, before, after] projection — sorted by id, tool-internal metadata excluded)
  3. Compares against the prior plan's fingerprint
  4. Match → emits a dry_run.auto_refresh log entry and continues execute on the prior plan (intent unchanged; no caller action needed)
  5. Mismatch → returns CONFIRMATION_STATE_DIVERGED with both plan summaries in error.cause.prior_plan and error.cause.new_plan. The calling LLM should re-run the preview and re-confirm with the user.

This means a normal preview-then-think-then-confirm pause is forgiving up to one hour, provided the underlying workspace state hasn't changed under the user. If someone else mutates the same asset/folder/collection in the gap, the divergence error catches it — no silent overwrite.


Verified endpoints

The complete list of upstream endpoints we have observed working against a real workspace lives in docs/verified-endpoints.md plus the much fuller reference doc at docs/api-field-verification.md (~22 endpoints with Admin-Frontend source citations and contract-test references). Anything not in those files is unproven — wrappers should only be written after a contract test passes against the live API.


Known limitations

Search facets are not currently surfaced

The Nuxt /typesense/search proxy that fronts Collage's Typesense node strips the facet_by parameter before forwarding to Typesense. Effect on search_assets:

  • facets.tags, facets.file_type, and facets.date_histogram always return empty arrays.
  • facets.score_distribution is hit-derived (synthesised from returned hits) and still works.
  • next_step_hints degrades gracefully — the untagged_assets_found hint logic falls back to per-hit countUntagged() and is independent of facet counts.

A proxy-side fix is requested upstream. The MCP surface is otherwise fully functional.

Three resources are blocked on upstream endpoint design

  • collage://tags — Collage has no workspace-wide tag-listing endpoint; the closest (get-common-tag-list) returns the intersection of tags across a given asset list, not all tags. Awaiting Backend-API change.
  • collage://analyticsanalytics/summary is per-asset only, not a workspace overview. Awaiting Backend-API change or scope reframe.
  • collage://portals/{id}/users — endpoint TBD.

The MCP server registers 10 of the 13 specced resources; the three above will ship once upstream lands.

Thumbnail indexing race condition (search side)

When an asset is uploaded, its thumbnail URL may not appear in the Typesense index for up to ~24 hours after upload. Search hits returned during that window may have thumbnail_file: null or a stale value. This is upstream behaviour — the MCP server passes through whatever the index returns.

If you need a reliable thumbnail URL for a freshly-uploaded asset, fetch the asset directly via get_asset_details (POST view-detail) which reads from the live database rather than the search index.

Prompts UI not yet surfaced in Claude Desktop

MCP defines a prompts/list + prompts/get primitive that this server implements correctly. Current Claude Desktop builds do not yet surface prompts in their slash menu or attachment UI.

Two fallback paths cover the same workflows in the meantime — see the Invoking guided workflows section above. Both surface tool-aliases (start_*) that re-emit the same playbook body through the standard tool surface, which Claude Desktop does render.

Confirmation token TTLs

Mutation safety uses two TTL windows (soft expiry 15 min, memo expiry 60 min). If the calling LLM pauses for human review longer than the soft expiry, the framework auto-refreshes the plan when execute arrives — but only if the underlying workspace state hasn't changed. If another mutation has touched the same target in the gap, you'll get CONFIRMATION_STATE_DIVERGED with both plan summaries in error.cause for the LLM to reconcile. See Mutation safety above for the full lifecycle.

Streamable-HTTP transport requires Redis

The default stdio transport uses an in-memory state store and runs without external dependencies. The streamable-HTTP transport is multi-client capable but requires Redis for the dry-run plan store. Use docker compose up redis for local development; for production deployments, see docs/deployment-runbook.md for state-store provisioning guidance.

Running under streamable HTTP

# 1. Start local Redis (compose file lives at the repo root).
docker compose up -d redis

# 2. Export env and pick the transport. CLI flag wins over MCP_TRANSPORT.
export COLLAGE_API_KEY=...
export COLLAGE_WORKSPACE_ID=...
export MCP_CONFIRMATION_SECRET=...
export REDIS_URL=redis://127.0.0.1:6379
# Optional overrides — defaults shown.
export MCP_HTTP_HOST=127.0.0.1
export MCP_HTTP_PORT=3333

npm run dev -- --transport=http
# or, equivalently:
MCP_TRANSPORT=http npm run dev

The server logs collage-mcp ready (streamable-http) to stderr on success. From another shell you can poke initialize directly:

curl -sS -X POST http://127.0.0.1:3333/ \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "initialize",
    "params": {
      "protocolVersion": "2025-06-18",
      "capabilities": {},
      "clientInfo": {"name": "curl", "version": "0"}
    }
  }'

If REDIS_URL is unset while MCP_TRANSPORT=http, startup fails with a descriptive validation error pointing at this section.


Project layout

src/
  index.ts              MCP server entrypoint (stdio)
  client.ts             Collage REST HTTP client (Bearer JWT, rate limited)
  typesense.ts          Typesense Cloud direct client + admin-key guard
  types.ts              Phase-1 zod schemas (asset, category, collection, custom field)
  conventions/          Shared infra: env, errors, logger, pagination,
                        rate-limiter, response-budget, state store, etc.
  tools/                One file per registered MCP tool

tests/
  unit/                 Fast, hermetic. Run on every commit.
  contract/             Hits live API. Gated by INTEGRATION=1.
  integration/          End-to-end MCP transport tests (planned).

scripts/
  check-schema-version.ts   Schema-version drift guard.
docs/
  verified-endpoints.md     Source of truth for which upstream endpoints work.

Scripts

npm run dev               # stdio transport, hot-reload via tsx watch
npm run build             # tsc → dist/
npm start                 # run the built server
npm test                  # unit tests (fast, hermetic)
npm run test:integration  # contract tests (live API; needs INTEGRATION=1 + env)
npm run lint              # tsc --noEmit

Handoff

See docs/developer-handoff.md for the architecture map, capability surface, documentation index, open Collage-side dependencies, and the handoff sequence — the orientation doc for taking ownership.

Contributing

See CONTRIBUTING.md for the development workflow, testing conventions, and how to add a new tool / wrapper / contract test.