XAgent Blog

Home Blog Market Launch Store

MCP server explained: what changes when a tool costs money

An MCP server is simple to explain and harder to build once a tool has to be paid for. Four curl calls against a live merchant server, the header that hides your tools, and what x402 adds.

By XAgent Team · 2026-08-23

An MCP server is a small HTTP service that tells a model what it can do, in a format the model can read without being told. Most explanations stop there, which is enough to build one that returns the weather and not enough to build one that takes money. This is an MCP server explained from the wire — every request below was run against a live production server, and you can run them yourself.

The server is XAgent's own eSIM merchant. It sells travel data plans to AI agents and settles on-chain, so it has to do the part the tutorials skip: refuse a call until it has been paid.

MCP server explained: the four calls that matter

The protocol is JSON-RPC over HTTP. A client opens with initialize, and the server answers with what it supports:

curl -s -X POST https://xagentgo.com/api/esim/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize",
       "params":{"protocolVersion":"2025-06-18","capabilities":{},
                 "clientInfo":{"name":"probe","version":"1.0"}}}'
{"result":{"protocolVersion":"2025-06-18",
           "capabilities":{"tools":{"listChanged":true}},
           "serverInfo":{"name":"xagent-esim","version":"1.0.0"}}}

Two things are already settled by that response. The server speaks the 2025-06-18 revision of the spec, and it offers exactly one capability: tools. No prompts, no resources, no sampling. A merchant server does not need them.

tools/list then returns the menu. Ours has three entries: search_esim, buy_esim, get_esim_status. Each carries a JSON Schema for its arguments, which is the whole point of the protocol — the model does not need a prose integration guide, it reads the schema.

tools/call runs one. search_esim is free and answers immediately:

XAgent 自营旅行 eSIM — 11 国 / 44 档:

Japan (JP):
   • [1 GB 7 days] — 3.5 USDG
   • [3 GB 15 days] — 7.5 USDG
   • [10 GB 30 days] — 21.5 USDG
   • [20 GB 30 days] — 40.5 USDG

Four calls, and an agent that had never heard of us can price a Japanese eSIM. That is the part MCP genuinely solves.

The header that returns an empty tool list

The first time we probed this endpoint from outside, tools/list came back with zero tools. The server was healthy and the tools were there.

The request was missing half an Accept header. This server streams over Server-Sent Events, so a client that asks only for application/json gets nothing useful back. The working header is both:

Accept: application/json, text/event-stream

It is in the specification, and it is in almost no tutorial. If your client sees an empty tool list against a server you know has tools, check this before you check anything else.

Notice also what the response did not contain: an Mcp-Session-Id. This server is stateless — every call stands alone, and there is no server-side cart to resume. That is a deliberate design decision with real consequences for checkout, which we worked through separately in the stateless cart problem.

What changes when the tool costs money

search_esim returns data. buy_esim moves value, and the difference is not a matter of degree.

A paid tool cannot simply execute when called. It has to answer the first call with the terms — how much, in what currency, on what chain, to which address — and then wait. In our server the first buy_esim call returns x402 payment requirements rather than an eSIM. The agent signs an EIP-3009 transferWithAuthorization for that exact amount, calls again with the signed payment in _meta["x402/payment"], and only then does the tool do its work. The rail is XLayer, chain 196, in USDG or USDT.

Three things follow from that, and they are what a merchant MCP server is actually made of:

  • The quote must be binding. The agent signs against a number you gave it. If that number can drift between the two calls, the signature is worthless and the purchase fails at settlement.
  • Every declared currency must be the same currency. We found our own search_esim printing prices in USDC while buy_esim demanded USDG, because a field named retailUsdc outlived the rail it was named after. A human skims past that. A machine signs it.
  • Free and paid tools belong on the same server. search_esim costs nothing deliberately: an agent that has to pay to see a price will go somewhere else. Discovery is free, execution is paid.

What MCP does not give you

MCP standardises the request. It says nothing about who is allowed to spend, how a refund works, whether the merchant honours the quote, or what proof the buyer holds afterwards. Those are not protocol problems and no revision of the spec will solve them — they are operations, and they are the same operations whether the agent arrives speaking MCP, A2A, UCP or AP2.

That gap is the reason XAgent exists, and the longer argument for it is in what agentic commerce actually requires.

What's next

The eSIM server above is live. Point an MCP client at https://xagentgo.com/api/esim/mcp, list the tools, and call search_esim — it is free, and it is the shortest path to seeing what an agent sees. If you run a store and want it to answer the same way, that is what listing on XAgent does.

Read the MCP specification for the parts we skipped. Then decide which of your tools cost money, because that is the decision the protocol does not make for you.

Keep reading

  • When an agent payment is neither settled nor failed
  • x402 can now charge for what an agent actually used
  • x402 clients now refuse to sign payments over one dollar