Skip to main content
MCP endpoints are in beta.
To connect, an MCP client needs three things from you: the endpoint URL, a way to get a token for its principal, and its grant id. See Authentication and grants for how you issue them. The endpoint URL ends with the current publication revision. Read it after each push:
The URL is then https://<your deployment name>.bijection.site/mcp/<revision>. When you push a change, give clients the new URL.

Trying the endpoint

The endpoint is a stateless JSON-RPC endpoint over HTTP POST. You can list its tools with curl:
The response lists only the tools in your grant.

Read-only clients

Any MCP client that can send a bearer token to a remote HTTP server can discover tools and call query and status tools. Give it the endpoint URL and a token. Operation tools are different. Each operation call needs a request key that stays the same across retries, and a model can’t be trusted to invent one. A client that doesn’t supply the key and grant id can’t call operation tools; those calls fail with request_scope_mismatch.

Recoverable writes

The bijection/mcp/node module gives an agent host what it needs to call operation tools safely. It runs in your agent’s Node.js process, not in your deployment. Don’t import it from your bijection/ folder.
agent/connection.ts
  • publicationUrl is the endpoint URL. It must end with the revision and use HTTPS, or HTTP on a loopback address.
  • deploymentUrl is your deployment’s .bijection.cloud URL. It is used for recovery and status, which call your operation’s recovery functions directly and keep working after the endpoint URL changes.
  • getToken is called for every HTTP request, so tokens can be refreshed freely. Tokens are never written to the store.
  • store persists each write’s request before it is sent.
The connection has these methods: The call id must stay the same when your host replays a step, for example a persisted workflow step identity. Calling an operation tool again with the same id returns the same invocation.
A timeout, dropped connection or 5xx response doesn’t tell you whether a write was accepted. Call recover(id) or status(id) with the original call id. Never retry with a new id: that is a new request.

Request stores

McpRequestJournal is a small file-based store that syncs each record to disk before the request is sent. Put its directory on durable storage. For production hosts, implement the McpRequestStore interface on your own database:
prepare must atomically keep one immutable record per call ID, return the same request key when called again with the same input, and reject a call ID reused with different arguments, grant or endpoint. load must survive a process restart. Never store credentials in it.

Mastra

Pass the connection’s fetch to Mastra’s MCP client. Create one client per tool call ID:
agent/mastra.ts

Eve

Eve persists its own session and call identity. Use eveMcpRequest as a provided argument; Eve hides it from the model and adds it to each call:
agent/connections/tasks.ts
Keep each connection bound to one grant and one endpoint URL.

Other clients

If you build your own client, send the request identity in the tool call’s _meta, never in the model’s arguments:
Add "mode": "recover" to look up an earlier call with the same key and arguments without invoking the operation. Persist the key before sending the request.

Errors and deadlines

Each discovery, recover and status attempt, including getting a token, has a 10-second deadline. Set your MCP client’s own timeout for tool calls, as in the Mastra example above. Failures are thrown as McpRequestError with a kind of deadline, cancelled, unavailable, authorization or request_refused. None of them establishes whether a write committed.

Presenting status

presentMcpOutcome from bijection/mcp/outcome turns a status tool’s result into a fixed outcome and message for your users, such as pending, awaiting_review or unknown. Its external_effect_confirmed field is always false: delivery records alone don’t prove that an external system applied a change. Show these facts directly rather than a model’s summary of them.