Pay for MCP tool calls
How an MCP client pays for a priced tool call with x402 or DNA.
A site on DNA can price the tools on its MCP server. Connecting, listing tools
and every other message stay free; a priced tools/call, resources/read or
prompts/get without payment gets a tool result asking for it, as the
x402 MCP transport
specifies.
The exchange
- Call the tool. You get a normal JSON-RPC result with
isError: true. - Read the terms from
structuredContent, pick one entry fromacceptsand sign it, as for x402. - Call the tool again with the signed payment in
params._meta["x402/payment"]. - The result carries the receipt in
_meta["x402/payment-response"].
{
"isError": true,
"structuredContent": {
"x402Version": 2,
"accepts": [{ "scheme": "exact", "network": "eip155:8453", "...": "..." }],
"extensions": {
"dna.d3.com/pay": { "payUrl": "https://dna.d3.com/pay?handoff=…", "handoff": {}, "methods": [] }
}
},
"content": [
{ "type": "text", "text": "{…the same JSON…}" },
{ "type": "text", "text": "…" }
]
}The first text item repeats structuredContent, for a client that reads text
only. The second says what to do, in words a model can act on.
Pay with DNA instead
extensions["dna.d3.com/pay"] is the body of a Pay with DNA 402:
show the person payUrl. Once they approve, send the same call to
handoff.fetchUrl, the server's URL with the handoff attached, and it is served
and charged. A client that does not know this extension ignores it.
Why the answer is a 200, not a 402
The result rides an HTTP 200, as the binding requires. A client that pays only
on an HTTP 402 sees a tool error; an MCP client that implements the binding
pays as above.