Protocol surfaces

MCP

Streamable HTTP at /mcp: resources become tools, payments ride in _payment or the rail's own _meta carrier.

RPC/mcppayment

MCP Streamable HTTP, revision 2026-07-28, served through @modelcontextprotocol/[email protected]. The SDK's stateless fallback also accepts 2025-era clients that send initialize; server/discover advertises only 2026-07-28. Resources with expose: [mcp] become tools. Mount path from protocols.mcp.mountPath.

tools/list

curl -s http://localhost:8080/mcp \
  -H 'content-type: application/json' \
  -H 'accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

The list is not paginated, so a cursor gets -32602. Under 2026-07-28 it carries ttlMs: 60000 and cacheScope: "public".

Tool fieldSource
namethe resource id
descriptionthe resource description; paid tools append the price and both proof carriers, and gated tools the authorization instructions
inputSchemathe resource input schema; paid tools gain an optional string _payment, and tools that require authorization an optional _authorization object

tools/call

json
{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/call",
  "params": {
    "name": "market_report",
    "arguments": { "_payment": "<base64 x402 proof>" }
  }
}
OutcomeResult
deliveredthe merchant response; delivery summary in _meta["agent-commerce/delivery"], plus the rail's settlement document (see below)
payment requiredisError: true, the payment envelope in structuredContent; for x402 the v2 PaymentRequired fields (x402Version, resource, accepts) sit beside it. With several offers, the message names no single destination
failureisError: true, the error envelope with a CommerceErrorCode; a refusal that offers a retry also carries the rail's fresh challenge

On payment-required and error results, content[0].text is a JSON copy of structuredContent and content[1].text is a sentence for readers. An unknown tool returns JSON-RPC -32602, and so do malformed tools/call params, such as a non-string name, on a request without modern MCP headers.

Payment carriers

A paid tool accepts a proof in the gateway's _payment argument or in the selected rail's own MCP _meta carrier, so x402 and MPP clients can pay in their native format. If both are present, the _meta proof wins, so a placeholder _payment cannot break a client wrapper's paid retry. The gateway reads payment _meta only inside params.

RailChallengeProofDelivered result
x402structuredContent, content[0].text and _meta["x402/error"]_meta["x402/payment"], a PaymentPayload object or its base64 JSON string_meta["x402/payment-response"]
MPP_meta["org.paymentauth/payment-required"]_meta["org.paymentauth/credential"], a credential object_meta["org.paymentauth/receipt"]

An x402 string proof that does not decode gets PAYMENT_INVALID and a fresh challenge. A refused x402 replay names the paid network's replay code in the challenge's error, as over HTTP. An x402 settlement failure, or a backend failure after settlement, also carries _meta["x402/payment-response"]. The MPP carriers follow draft-payment-transport-mcp-00; that draft uses JSON-RPC errors -32042 and -32043, but the gateway puts challenges and refusals in tool-result _meta, which mppx accepts.

Reserved arguments

_paymentstring
The proof answering a previous payment-required response: for x402 the value HTTP carries in PAYMENT-SIGNATURE, for MPP the complete Authorization: Payment … credential. For MPP the challenge is in payment.envelope.challenges, and payment.envelope.wwwAuthenticate holds its serialized header value.
_authorizationobject
The AP2 envelope { method: "ap2", payload }.

Both are stripped before validation and never reach the backend.

Limits

At most 8 concurrent tool calls plus a queue of 64; beyond that, GATEWAY_BUSY (retryable). Each protocol mount, A2A and ACP included, also takes at most 20 requests at once; more get HTTP 503 with the gateway's GATEWAY_BUSY envelope and Retry-After: 1. Bodies are capped at 256 KiB; a larger one gets 413. The gateway, not the MCP adapter, enforces Host and Origin checks.

Only revision 2025-03-26 has JSON-RPC batches. A batch whose MCP-Protocol-Version names another revision gets HTTP 400 and -32600; one sent without that header is served. The adapter's own transport errors use -32600 for a 405 or an unreadable body and -32603 for a 500 or 503.

Not implemented: resources, prompts, sampling, completions, elicitation, roots, logging, tool-list-change notifications and tasks — the adapter's descriptor.unsupported at runtime. There is also no MCP authorization, sessions, subscriptions, pagination or HTTP+SSE transport, and payment support is not advertised in the server capabilities.