Skip to main content
A published agent already runs inside your product. MCP export opens a second door on that same agent: your users can reach its tools from their own AI client — Cursor, Claude, ChatGPT — acting as themselves, with the permissions they already have. You do not run an MCP server. You do not write a second tool catalog. The tools are the ones you already wired, and the only thing you host is a login bridge so your users authenticate with you.

What travels through the door

The capabilities, not the assistant. The client already has a model, so we export no persona, no knowledge, no memory, and none of the built-in primitives. Nothing about your agent’s character crosses over.

The URL

The path carries the agent’s public id — the same string your threads name, pinning one exact published version. There is no secret in the URL and no query string; the client authenticates with a bearer token it obtains itself. Paste that URL into any client that speaks Streamable HTTP. For Cursor:
No headers block. The client discovers how to authenticate from our 401.

Turning it on

Two things, both of which you may already have:
1

Publish the agent

Publishing mints the public id, and the MCP URL exists from that moment. The dashboard shows it on the published agent with a paste-ready snippet.
2

Give its connection a login URL

Set MCP login URL on the connection the agent uses. That is your login bridge — the one page you host, which authenticates your user and hands us back a signed subject.
Until the connection carries that URL the door stays shut: discovery returns 404 and authorization is refused. Identity is the whole requirement — there is no MCP infrastructure for you to stand up.
The login URL lives on the connection, not the agent. Two agents pointing at different connections can serve different user pools; agents on the same connection share one.

Who the user is

You own identity. We run the OAuth machinery. Patchwork is both the resource server that hosts the MCP URL and the authorization server the client talks to. We never see your users’ credentials, and we never invent a user — the one step only you can do, proving who someone is, is the one step we hand back to you.
Step 4 is your entire surface. Everything else — discovery, client registration, consent, tokens, grants, revocation — is ours.

Discovery endpoints

A client follows these on its own; they are listed so you can see what it will touch.

Two consents, cleanly split

  • Which tenant am I, and may I be here at all — your bridge, your policy, baked into the subject.
  • May this client act as me on this agent — our consent screen, which records the grant.

What exports

tools/list is the agent’s wired tools, filtered, with each one projected like this: Tools come back sorted by key. Any @ mention in a title or description is rewritten to a plain label first, so the client’s model is never told to load knowledge it cannot reach or to call a tool absent from its own list. A tool is exported only if all of these hold:

Writes export, but only deliberately

A write is exported the same as a read, and it really runs — as the user, against your backend, under your own authorization. What stops a write from leaking out is the permission on the wiring.
Always ask does not export. A patch wired that way pauses a run for a human decision, and this door has no way to ask yet — so rather than run it unconfirmed, we leave it out of the catalog. A write reaches an MCP client only when you wire it Always allow.
Because risk can depend on arguments, a tool can pass the catalog filter and still escalate on a particular call. That call is refused with confirmation_required rather than run without a confirmation nobody can give.

Choosing a connection

A client that can send headers may name one per call:
A uuid or a name, as in relay. Without the header we use the connection pinned to the agent. A customer patch that resolves no connection fails that tool, not the session.

Every call is a run

A tools/call opens a run, dispatches the tool, and closes it. The conversation stayed in the client, so the run has no model turn — but everything else is the same spine you already read:
  • source is mcp on the run, and the dashboard badges it so it does not read as a broken chat.
  • The tool call is recorded with redacted arguments and result, risk, and timing, and GET /v1/loom/runs/:id/trace reads back as usual.
  • Events carry origin: "mcp", and a webhook endpoint can subscribe to that origin alone.
  • The subject on the run is the one your bridge asserted, so you can answer “what did this user do from their own client” without a second log.
Each call gets its own throwaway thread, because there is no conversation on our side to thread. Those are left out of GET /v1/loom/threads so your chat history stays chat history — read the runs instead.

Managing access

The grant lives with us, which is what makes revocation immediate. List and revoke with your workspace API key:
Revoking kills the grant and every access token issued against it, so the next call from that client fails at our door. See The MCP grant object. Build your own “connected apps” screen on these two endpoints — we ship no UI for your users.

Scopes

Consent asks for read and write, and the granted scopes are recorded on the grant for you to read back.
The exported catalog does not currently narrow with the scope. What a client can call is set by the agent’s wiring — the permission and risk filters above — not by what it asked for at consent. Wire the agent to the smallest set you want reachable.

Errors

Errors split cleanly in two. Anything about the door is an HTTP status, because the client has to do something about it: Anything about a tool comes back as a normal MCP result with isError: true and the code inside, so the client keeps its session and can try something else: Either way the trace holds the real detail — the arguments, the egress request, and the failure — which is where to look rather than at what the client printed.

What is not supported yet

  • Elicitation and confirmation. Hence no Always ask tools, and no proposed_action or handoff patches, which assume your frontend.
  • Refresh tokens. An access token lasts an hour; after that the client runs the authorization flow again.
  • API keys on this door. OAuth only — there is no paste-a-key path.
  • Custom domains. The URL is on our host.
  • Several connections per exported agent. One agent, one connection.
  • Prompts, resources, subscriptions, and server-pushed catalog changes.