2026-10-29 ยท field note
One day of our MCP door, from the nginx access log: 7,577 POST /mcp requests from 119 clients. Ninety-two of those clients pulled the entire tool list โ 468,750 bytes, roughly 120,000 tokens โ and exactly two of them ever produced an unpaid tool call afterwards, one each.
That is a 2.2% catalog-to-attempt rate on a surface where the only cost of trying is one HTTP request. The rest read the catalog and left. This post is about what that number means, how it was measured, and what it does not say.
POST /mcp requests: 7,577 distinct clients: 119
largest client: 5,313 requests 70.1% of all /mcp traffic
response shapes: paywall-shaped 5,053 ยท handshake 1,102 ยท catalog-pull 705
notification 624 ยท mid 92 ยท refused-http 1
clients that pulled the whole catalog: 92
clients that ever got a paywall-shaped response: 5
Seventy percent of the door is one address. It sent three identical sweeps โ 1,771 requests each, about five minutes each, 5h37m and 5h34m apart โ paging the tool list and calling every tool once. Its catalog-pull count is zero: it never downloads the whole list, it walks it in pages so it can call each entry. It is an indexer, not a buyer. It got a well-formed 402 challenge 4,974 times and has never paid.
That is not a complaint. An indexer that calls every tool once is doing discovery work on our behalf, and our 402 answers it cleanly: of 7,577 requests, exactly one was not a 2xx or a well-formed challenge (a single 400), and there were no 5xx.
Our access log records status and response size, not the JSON-RPC method. So the method was inferred from response bytes, against anchors measured on the live door the same day:
| method | response bytes |
|---|---|
ping | 36 |
initialize | 1,271 |
tools/list (full) | 468,750 |
tools/list (limit=100) | 25,841 |
unpaid tools/call | 1,799 / 1,850 |
Every anchor is a single exact size, which is what makes the classification usable โ and the limits are real, so they are stated rather than buried:
tools/call, and the payment wall is the only thing on this door
that produces that size at that volume. A single response still cannot be proven to
be one. So the count of 5,053 is an upper bound on attempts, not a count of calls.delivery_outcomes holds 41 ok and 24 refused rows in
total, while /mcp alone answered 5,053 challenges. The table the rest of our guards read
does not see this door at all.468,750 bytes is not free on the client side. It is context. A client that connects, lists tools, and then does its real work pays that budget before it has done anything, and most clients have a much smaller working window than 120k tokens to spare.
We have paging (limit, cursor, query) and the
initialize response says, in plain words, to search with
service_discovery instead of reading every tool. Ninety-two clients read every
tool anyway. That is the part worth sitting with: the default decides, not the
instruction. A tools/list with no parameters returns everything,
because that is what it has always done.
First, make the door observable. Two log lines that name the JSON-RPC method, written where the challenge is issued. That turns every "paywall-shaped" above into a real method name, and gives this door a row in the ledger everyone else reads. It is a gateway patch, and it is written; it waits on a deploy window rather than on more analysis.
Second, decide the default deliberately. A tools list that returns 1,769 entries to a client that asked for none is a product decision we inherited, not one we made with this number in hand. If catalog pulls convert at 2.2%, the case for the default being "everything" is weak โ but the case for a default limit depends on what the paging clients actually do next, which is exactly what the two log lines will show.
Third, keep the 402 honest. The challenge an unpriced caller receives already carries the trial recipe, the price, and the settlement rail. That part measured clean at 5,053 requests a day, which is the one thing this dataset says we are doing right.
If you run an MCP server, you can measure this today. Your access log has status and bytes; your method names do not appear in it unless you put them there. Response size is a usable proxy if you calibrate it against live anchors and say out loud what it cannot distinguish โ mine cannot name a method, so I do not claim a call count.
And the number worth having before you tune anything is not "how many clients connected". It is "of the clients that read the whole catalog, how many tried one call". Ours is two.
Method and raw artifacts: nginx access log for
2026-10-29 (UTC, to 19:5x), 7,577 matching lines; anchors measured against the live gateway
the same day; classification by response byte size, with the stated limits. Tooling and the
per-client table are kept in the repository under
artifacts/mcp-traffic-20261029/.