Skip to main content
Everything your connections publish is callable from the terminal. A tool is one operation a connected app publishes — searching a mailbox, listing the issues in a repository — and receipt tools lists the ones your workspace can use, shows what one takes, and runs it. receipt mcp points another client — Codex, or anything that speaks MCP over stdio — at the same set, without writing a credential into that client’s configuration. Both are scoped by the workspace bound into your session token, so switching workspaces changes which tools appear. The gateway behind them is the aggregate MCP server at POST /connect/mcp; the aggregate server explains what it publishes and why.

receipt tools

The subcommand defaults to list, so a bare receipt tools lists. Anything else answers receipt tools supports list, describe, and call.

Identity

Identity comes from either your saved session — optionally selected with --target <name> — or from the environment: RECEIPT_CONNECT_GATEWAY_URL (or RECEIPT_CONNECT_PUBLIC_GATEWAY_URL) plus RECEIPT_CONNECT_TOKEN and RECEIPT_CONNECT_ORGANIZATION_ID. --server-url <url> overrides the gateway. With neither, it fails with:
That message says receipt mcp: even when you ran receipt tools. Sign in with receipt setup.
The saved session wins here, and the environment is only the fallback. That is the opposite of the receipt connect list|tools|call family, where the environment wins outright.

Flags

--json on receipt tools is the tool-argument payload, not an output switch. Output is always JSON, whether or not you pass it. Use --json only to give a tool its arguments; anything that is not a JSON object fails with --json must be a JSON object.
--server-url on receipt tools and receipt mcp replaces the gateway but keeps sending your saved session token, and nothing checks that the new host is the one you signed in to. The receipt connect commands reuse a saved session only when the gateway host matches; this path has no such check. Point --server-url only at a host you would hand that token to.

The output envelope

Every result is JSON, shaped as the tool’s own result merged into an envelope with a workspace identity block:
For a legacy session with no workspace id, the block reads {"kind": "organization-default", "id": "<orgId>", "organizationId": "<orgId>"} instead. The block exists so you can always tell which scope answered.

Tool names are opaque aliases

Aggregate tool names look like receipt_google_mail_work_search_messages_4c1e0b7a9d2f36581bca — the provider, the connection’s name and the upstream tool, followed by a 20-character digest. The digest binds the name to one exact stored connection and one reviewed upstream tool, which is why two connections for the same provider never collide.
Copy tool names from receipt tools list. Never construct or edit one. The gateway’s own instructions to MCP clients say so: “Tool names from tools/list are opaque; use them exactly and never construct aliases.”
The same instructions cover two more rules worth repeating: read-only annotations are authoritative, and you should re-list tools after switching workspaces or reconnecting.

What shows up in tools list

The aggregate list includes only connections in your token’s workspace that are valid, and:
  • Connectors with a typed manifest publish their manifest tools. Connectors without one publish a single GET-only read-provider-resource tool.
  • Provider-native MCP connectors are excluded from the aggregate list. They remain reachable through receipt tools --connection <connection>.
  • Connectors that authenticate with a local CLI credential rather than a stored one — AWS and Jira API Token — are excluded from it too.
  • A tool appears only while it is on the connection’s allowlist. A write tool additionally needs an owner or admin to have enabled writes for that connection, plus a token carrying connect:write; there is no per-action approval prompt in this release (tools and permissions).
  • A connection whose tool surface cannot be discovered is skipped and logged on the server, rather than failing the whole listing.

A successful envelope does not mean the provider succeeded

When a provider-side call fails on an aggregate call, the gateway returns it as a normal MCP result carrying an error flag and error text. The CLI still prints ok: true.
ok: true reports that the gateway answered, not that the provider did the thing. Read the result body before treating a call as successful.
Failures at the JSON-RPC level do throw, and you will see them as errors: Unknown or unavailable tool, Invalid params, Receipt MCP discovery failed. HTTP-level failures surface as unauthorized, workspace_membership_required or Receipt MCP returned HTTP <n>. The narrowed /connect/tools and /connect/call routes have two failures of their own: Receipt could not authenticate this task. Its runtime access token must be renewed before retrying. means the token has to be refreshed, and Receipt could not authorize this task to use the connection. This is a task permission problem; reconnecting the account will not fix it. means the token lacks the scope — reconnecting the provider will not help.

Which calls are recorded

receipt tools call --connection <connection> goes to POST /connect/call, which writes a tool.called receipt — plus a tool.observed receipt when the call succeeds — carrying the workspace, so the call appears on that workspace’s Gateway activity dashboard. A failed call records the tool.called receipt with its error.
Tool calls made through the MCP bridge are not yet recorded as receipts. receipt tools call without --connection, and every call an MCP client makes through receipt mcp serve, go to POST /connect/mcp and leave nothing on the Gateway activity dashboard — the aggregate server documents the gap. If you need a recorded trail for a specific call, make it with --connection.

receipt mcp

The subcommand defaults to status. An unrecognised one answers receipt mcp supports config, install, status, remove, and serve. Identity is resolved before any subcommand runs, so config, status, install and remove need a saved session; only serve accepts the environment fallback.

config — print a client configuration

receipt mcp config codex emits a TOML block:
Any other client name — receipt mcp config generic, or --client generic — emits a JSON descriptor instead. The JSON form carries the same launcher, and additionally reports the remote /connect/mcp URL and a workspace identity block:
remote.url is informational. The session token is never written into a generated config, and a guard checks every config the CLI generates or installs, refusing with refusing to install an MCP client config containing the Receipt session token or refusing to install an MCP client config containing credential material. Other flags: --name <n> sets the MCP server name (default receipt), --receipt-bin <path> sets the launcher command, and --json prints {ok, client, config, content, output}. With --output and no --json, it prints receipt mcp config: wrote <path>.
--output / --output-file on receipt mcp config replaces the whole target file. There is no merge with existing content. Never point it at a client’s live configuration file — write it somewhere new and copy the block in by hand.

install, status and remove support Codex only

Any other client is refused:
For Codex, the CLI shells out to codex mcp add|get|remove rather than editing the file itself, and protects the file around every mutation:
  • The config path is $CODEX_HOME/config.toml, defaulting to ~/.codex/config.toml. A different --client-config is rejected with Codex does not accept an arbitrary config path; expected <path>. Set CODEX_HOME before running Receipt if Codex uses another home.
  • It refuses to touch a symlink or non-regular file: refusing to modify non-regular client config: <path>.
  • It backs the file up before mutating it, and restores the backup on any failure — including post-condition failures such as codex did not report the installed Receipt MCP server; the prior config was restored.
  • A duplicate install is refused: Codex MCP server '<name>' is already installed; remove it first.
  • remove on something not installed reports {ok: true, removed: false, installed: false} rather than failing.
--client-bin <path> chooses the Codex executable (default codex). --dry-run on install and remove prints the plan — including the resolved configPath, command and launcher — and changes nothing. For every other client the supported path is receipt mcp config --client generic; install, status and remove throw.

serve — the stdio bridge

receipt mcp serve is what an installed client launches. It reads one JSON-RPC message per line on stdin, forwards it to <gateway>/connect/mcp with your session bearer token, and writes each response as a line on stdout. It forwards and remembers the Mcp-Session-Id header across messages. Each request gets 35 seconds. Failures come back as JSON-RPC errors, and notifications — messages with no id — never receive a response, even on failure. The gateway speaks MCP protocol versions 2025-11-25 and 2025-06-18; an unrecognised version negotiates to 2025-11-25.
The bridge reads your session file only when it starts. After receipt workspace use <workspace>, restart the MCP client and let it rediscover tools, or it keeps serving the previous workspace’s list.
Next step: capture Claude Code activity into Receipt.