Skip to content
mcp-pay View on GitHub

← Back to writing

Why MCP servers need payment awareness, not paywalls

Neul Labs · ·
specdesign

A paywall is a wall. You hit it, you stop. The user either pulls out a card or closes the tab. The whole interaction is paused while a separate flow runs — a checkout page, a subscription form, sometimes a 402 status code that everyone agrees exists but few systems actually use.

When the caller is a human, this works. When the caller is an LLM agent stepping through a plan, it falls apart. Agents call tools fast. They retry on failure. They route around problems. A wall they hit mid-plan is not a UX inconvenience; it is a planning failure. The plan recompiles, the agent picks a different path, and the server that put up the wall earns nothing.

mcp-pay is a small attempt to fix that, by changing the framing. The right primitive for paid agentic tools is not a paywall — it is payment awareness. The server publishes a tiny static manifest that says “this tool costs $0.003 per call, and here are three rails I take payment over.” The agent reads that file before it dispatches the call, decides whether the tool is worth it, and arrives prepared. The 402 response, when it shows up, is a confirmation step, not a surprise.

What a paywall does to an agent’s planner

Imagine an MCP server with two tools: get_weather (free) and get_forecast (paid). An agent given a long-term planning task has to call several tools to assemble a result. With no payment awareness, here is what its planner sees:

get_weather  → returns data, fine
get_forecast → 402 Payment Required

The agent has three options. It can fail the step. It can try to construct a payment, hope the rail is supported, and retry. Or it can pick another tool on another server. In practice it does whichever has the highest expected value, and “construct a payment for a rail I might not support” usually loses to “find a free substitute”. The server with the paywall gets skipped.

Now imagine the same server has published /.well-known/mcp/pay.json ahead of time. The agent fetched it during MCP discovery. Before any call, it already knows:

  • get_weather is free
  • get_forecast is $0.003 per call, paid via x402 on Base or Lightning, settles in 2 seconds
  • The server commits to a refund-on-failure policy

The planner doesn’t need to discover anything mid-flight. It either has a wallet on Base or it doesn’t. If it does, it knows the call is worth it and budgets the cost into its remaining plan. If it doesn’t, it picks a different server — but it picks at planning time, when picking is cheap, not at call time, when picking is expensive.

The difference is the same difference between bouncing off a wall and reading a price tag.

Why this is metadata, not a flow

Most attempts to “add payments to APIs” focus on the flow: how does the client construct a payment, how does the server verify it, what’s in the response. Those are important problems and there are good answers to them — L402 has one, x402 has another, Tempo’s MPP has a third.

mcp-pay does not try to redo any of that. The flow is fine. The thing that’s missing is the declaration. There is no standard way for an MCP server to say “here is what I charge, and here are the rails I take.” Without that, an agent has to discover pricing the hard way: call the tool, get a 402, read whatever ad-hoc payload the server returned, and reverse-engineer the price from it. That works for one server. It doesn’t generalize across the registry.

So the v0.1 spec defines a JSON manifest at /.well-known/mcp/pay.json. The structure is small. There are three required things:

  1. A pricing object. A default rule plus optional per-tool, per-resource, and per-prompt rules. Each rule names a model (free, per_call, subscription, tiered, or metered) and an amount with a currency.
  2. An accepts array. Each entry names a rail (x402, mpp, lightning, card, ach, or custom) and the fields that rail needs — chain ID, asset, recipient address, LNURL, facilitator URL.
  3. A version string. mcp_pay: "0.1" for the current draft.

Everything else — payment SLA, optional stats, vendor extensions — is optional. The whole manifest fits on one screen, which is intentional. The smaller it is, the more servers will adopt it.

The discovery surface matters

A manifest is only useful if there’s an agreed place to put it. We took the obvious one: /.well-known/mcp/, the namespace being registered with IANA per SEP-2127 (the MCP Server Card draft). That puts pay.json directly next to server-card.json, and the relationship between them is explicit:

  • server-card.json describes what the server is — its identity, remotes, capabilities.
  • pay.json describes what it charges and which rails it takes.

They reference each other. Neither requires the other. A server that adopts the Server Card without mcp-pay is fine — it just doesn’t charge. A server that adopts mcp-pay without the Server Card is also fine — it just doesn’t surface its identity through the same path. The two specs cooperate, which is the right shape for two adjacent concerns.

This is the part where “payment awareness, not paywalls” becomes operational. An agent does not have to call your server to learn what you charge. It walks /.well-known/mcp/pay.json for every server in its plan, the same way it walks server-card.json to learn what they do. By the time it picks which servers to call, it knows the bill it would incur from each — and it can negotiate budget with whatever its wallet allows.

Why “rail-agnostic” is load-bearing

We are deliberate about the word agnostic. The schema lists five rails today, and a custom escape hatch for the sixth. The reference server implements x402 first because that path is shortest — Base + USDC + a public facilitator — but Lightning and MPP and card are first-class in the schema and roadmapped for the server.

That matters because the agent economy is not going to standardize on one rail. Some agents will have Lightning wallets. Some will have x402 facilitators wired up. Some will be SaaS-bound and pay with the card on file. A paywall picks one and excludes the others. A manifest lists all of them, and the agent picks per call.

The same server, with the same manifest, charges a Lightning-shaped agent over LNURL and an x402-shaped agent over USDC on Base. Neither agent had to know what the other supported. The discovery file was the thing that made them interoperable.

What this is not

mcp-pay does not custody payment. It is not a wallet, not a facilitator, not a settlement layer. The reference server delegates verification to whatever facilitator URL is in the manifest. Where the money moves is up to the rail.

It is also not an MCP registry. The MCP Registry is the right place for capability discovery. mcp-pay is the right place for pricing discovery. The whole point of /.well-known/mcp/ is that several small specs share the namespace without colliding.

And it is not a wall. The wall was always the wrong primitive for agents. The right one is a file the agent can read before it calls.