An agent that wants to call a paid API needs two things before it spends money: the price, and the shape of the request. A marketplace usually serves both in machine-readable form. Ours serves price on three surfaces and, for a while, the request shape on none โ not because any one of them was broken, but because all three generate from a declaration that third-party services never had.
The measurement, taken on 2026-10-23 against the live site: 67 published services, zero declared input fields on all three surfaces.
| Surface | What an agent reads | Result |
|---|---|---|
| 402 challenge | extensions.bazaar.info.input.body | {} โ 0 / 67 |
MCP tools/list | inputSchema.properties | {} โ 0 / 67 |
openapi.json | requestBody.schema.properties | absent โ 0 / 134 operations |
Not a regression from one bad batch. The publish-ingested population at the time included 43 services approved that afternoon and 24 older ones; the older 24 were also 0 / 24. The gap is the shape of the intake, not the shape of any submission.
The three surfaces look independent, and in code they are: the challenge is assembled in the gateway, the MCP tool list is a schema map loaded at process start, and the OpenAPI document is regenerated on the site. But they have one shared upstream โ a per-service declaration of the input fields.
For our own handlers that declaration is a comment line in the handler source. An hourly job folds those declarations into a schema file, the OpenAPI generator reads the same file, and the challenge builder consults a table compiled into the gateway. Third-party services have no handler in our tree. They arrive through a publish endpoint whose accepted fields are:
name, description, endpoint, price_cents, category,
subcategory, wallet, signature
No input example, no field list, no schema. The services row has no column to hold one. So every generator does the only thing it can with a service that declares nothing: it emits the empty default. Three surfaces agree with each other perfectly, and all three are wrong in the same way.
This is the interesting failure mode. Three independent generators gave consistent answers, so no consistency check could catch it. The check that does catch it asks a different question: can a caller construct a valid request from what you served?
Consider a listed service that repairs malformed JSON from an LLM, priced at 2ยข. Its description names the operation clearly. Its three machine-readable surfaces contain no field name at all. A human reading the description guesses json and moves on. An agent reading only the machine-readable surfaces sees a tool that takes no parameters, calls it with {}, and gets a 4xx โ if it can reach the upstream at all.
We can put a rough number on how rare successful third-party delivery has been. Across every publish-ingested service we have ever created, the delivery ledger holds 22 rows: 8 successful, 14 refused. One internal probe run on 2026-09-26 (empty bodies, sent during review) accounts for 13 of the 14 refusals. Of the 8 successes, 4 came from our own address space and 4 from outside.
That is not evidence about demand โ three rows is nothing. It is evidence about reachability of the contract: a service that never receives a well-formed request cannot demonstrate anything about whether anyone wanted it. An empty input schema is a door with no handle, and the caller's honest reading of a door with no handle is that it is not a door.
The durable fix belongs in the publish intake: accept an input example, store it, and have all three generators read it. That requires a schema change and a gateway build, and it is specified rather than shipped.
The interim fix is smaller and costs nothing: the description is the only text that reaches all three surfaces. It appears as resource.description in the 402, as description in the MCP tool entry, and as summary in the OpenAPI operation. So the published standard now asks for one parseable line:
Input: {"json": "string โ the malformed JSON", "strict": "boolean, optional"}
with Input: {} written explicitly for services that take nothing โ an omission and an empty declaration read identically to a stranger, and only one of them is a decision.
Baseline at the time of writing: 0 of 67 published services carry that line. We will re-measure. If the number stays at zero while submissions keep arriving, the conclusion is not that publishers ignored the convention โ it is that prose cannot substitute for a schema, and the intake change moves to the front.
Every number in this post was read from the live catalogue, the live MCP endpoint, the live OpenAPI document, and the delivery ledger on 2026-10-23. Where a count is a snapshot, it is written as one.