Docs

MCP server setup

AdminUpdated Sep 15, 2026

MCP server setup

@cookiemunch/mcp is a Model Context Protocol server that exposes the Cookie Munch Developer API as tools an AI agent (Claude Desktop, Claude Code, or any other MCP client) can call directly — list sites, read consent analytics, edit a banner flow, open a DSAR, manage webhooks, and more, all from a chat session. It's built directly on @cookiemunch/sdk (packages/mcp/src/index.ts imports createCookieMunch from it), so every tool maps to a documented /v1 route and the two stay in lock-step.

It speaks stdio, not HTTP — the transport MCP clients use to spawn local servers as a child process and talk MCP over its stdin/stdout (StdioServerTransport in packages/mcp/src/bin.ts).

1. Get an API key

Issue one from the dashboard, or POST /v1/keys / client.keys.issue() using an existing unscoped key. Keys look like fck_….

2. Run the server

npx -y @cookiemunch/mcp

npx resolves the package's single published binary (cookiemunch-mcp, built from packages/mcp/src/bin.ts) automatically. Two environment variables control it (read in bin.ts):

Variable

Required

Default

Description

COOKIEMUNCH_API_KEY

yes

Your fck_… API key. The process exits with an error immediately if unset.

COOKIEMUNCH_BASE_URL

no

http://localhost:8787

Your Cookie Munch server origin (/v1 is appended automatically, same as the SDK). Set this to your real API origin, e.g. https://api.cookiemunch.net, for anything other than local dev.

COOKIEMUNCH_API_KEY=fck_9e8d7c6b5a4f3e2d1c0b \
COOKIEMUNCH_BASE_URL=https://api.cookiemunch.net \
npx -y @cookiemunch/mcp

3. Configure an MCP client

Claude Desktop / Claude Code

Add an entry to your MCP client's config (claude_desktop_config.json, or .mcp.json for Claude Code — equivalently, claude mcp add):

{
  "mcpServers": {
    "cookiemunch": {
      "command": "npx",
      "args": ["-y", "@cookiemunch/mcp"],
      "env": {
        "COOKIEMUNCH_API_KEY": "fck_9e8d7c6b5a4f3e2d1c0b",
        "COOKIEMUNCH_BASE_URL": "https://api.cookiemunch.net"
      }
    }
  }
}

Restart the client, then ask it something like "list my Cookie Munch sites" or "open a GDPR access DSAR for [email protected]" — it will resolve and call the matching tool automatically.

From a local checkout

If you're developing against the repo rather than the published package:

pnpm --filter @cookiemunch/mcp build
{
  "mcpServers": {
    "cookiemunch": {
      "command": "node",
      "args": ["/absolute/path/to/packages/mcp/dist/bin.js"],
      "env": {
        "COOKIEMUNCH_API_KEY": "fck_your_key_here",
        "COOKIEMUNCH_BASE_URL": "https://cmp.example.com"
      }
    }
  }
}

Any other MCP client

Any client that supports stdio MCP servers works the same way: point it at npx -y @cookiemunch/mcp (or a globally-installed cookiemunch-mcp binary) with the two environment variables set:

npm install -g @cookiemunch/mcp
COOKIEMUNCH_API_KEY=fck_… COOKIEMUNCH_BASE_URL=https://api.cookiemunch.net cookiemunch-mcp

4. Programmatic use

Build and connect the server yourself — for example to inject a pre-built SDK client instead of an API key/base URL (useful for tests or custom auth):

import { createCookieMunchMcp } from '@cookiemunch/mcp';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';

const server = createCookieMunchMcp({
  apiKey: process.env.COOKIEMUNCH_API_KEY!,
  baseUrl: 'https://api.cookiemunch.net',
  // or: client: createCookieMunch({ apiKey, baseUrl, fetch: myFetch })
});
await server.connect(new StdioServerTransport());

createCookieMunchMcp (packages/mcp/src/index.ts) builds an McpServer named cookiemunch and registers every tool from registerTools before returning it — connecting a transport is the only thing left to do.

Security model

The MCP server has exactly the same authority as the API key you give it. Every write it can perform — editing a site's config, inviting a member, issuing a new key, crypto-erasing a subject's consent records — is scoped by that key's org and, if the key is scoped, by its scope list (consent:read, consent:write, sites:read, sites:write, dsar:read, dsar:write, vendors:read, vendors:write, ropa:read, ropa:write, receipt:read). Admin-only tools (invite_member, set_member_role, remove_member, issue_api_key) additionally require an unscoped key, exactly like the REST routes underneath them.

Give an agent a scoped key limited to what it actually needs, not an unscoped admin key — especially in an autonomous workflow where the agent's tool calls aren't reviewed one at a time. A read-only integration (a reporting bot, say) should hold a key with only *:read scopes; nothing stops an unscoped key from deleting sites or issuing more keys.

Troubleshooting

  • "COOKIEMUNCH_API_KEY is required" and the process exits — the env var wasn't passed through to the child process; double-check your client's env block (not your shell's).

  • Tool calls return isError: true with an SDK error message — every tool wraps the underlying client.* call in a try/catch and returns CookieMunchApiError's message as Error: <message> text content rather than crashing the session (packages/mcp/src/tools.ts's fail()). Check the message and status against SDK error handling.

  • A write tool 404s or 403s — the cbid/id you passed doesn't belong to the org tied to your API key. No tool accepts an orgId override; this is enforced server-side.

Next steps

  • Tools reference — every tool the server registers, grouped by area, with its inputs.

  • Client reference — the underlying SDK surface every tool calls into.

Was this page helpful?