{"slug": "one-tools-list-call-cost-529-kb", "title": "One tools/list call cost 529 KB", "summary": "A developer measured their MCP server's tools/list response at 529,287 bytes — roughly 132,000 tokens — for 1,859 tools, a payload that grew 90 KB in 20 days as 148 services were added. Because clients build the request themselves, opt-in pagination (limit, cursor, category, query) never helped, so the team changed the default so that a request with no limit, including no params at all, returns the first 100 tools plus a nextCursor. Usage data across 1,675 called services showed the first 100 tools cover 89.4% of usage rows, versus 84.5% for 50 and 93.1% for 200.", "body_md": "November 2026\n\nMCP clients do not ship a catalogue to the model once and cache it. They ask the server for `tools/list`, and whatever comes back is what the model gets to see — every session, as part of its context. For a server with a dozen tools that is a few kilobytes and nobody thinks about it. For a server that maps a marketplace — one tool per service — it is a different object entirely.\n\nOn 11 November 2026 we measured ours, on the live endpoint, with the request a stock client sends:\n\n```\nPOST /mcp  {\"jsonrpc\":\"2.0\",\"id\":2,\"method\":\"tools/list\",\"params\":{}}\n\n→ 200, 529,287 bytes, 1,859 tools, no nextCursor\n```\n\n529 KB, at roughly 4 bytes per token, is about **132,000 tokens** — before the system prompt, before the user's question, before a single tool is called. That is larger than the context window of a good number of the models these clients are wired to. On 22 October the same call was 439,656 bytes over 1,711 tools. It grew 90 KB in 20 days, because the catalogue grew by 148 services.\n\nNothing crashes. That is the problem. A client with a smaller budget truncates the list, or leaves it out, or the model sees the first few hundred tools and treats the rest as absent. The failure mode is not an error message — it is an agent that connected successfully, saw a partial catalogue, and called something else. From the server side that looks like \"nobody uses this\", and it is indistinguishable from having no demand.\n\nThe same thing happens at a much smaller scale whenever a tool's `inputSchema` is verbose. We once shipped an object-level description on every tool; it added **212 KB** to the payload — one sentence repeated 1,610 times. It was reverted the same day. Tool-list cost is the sum of per-tool costs, and per-tool costs are usually decided by whoever wrote the last schema.\n\nOur `tools/list` has accepted `limit`, `cursor`, `category` and `query` since 26 October, with the cursor bound to the filters that produced it (reusing a cursor after changing the filter is refused, not silently applied to another result set). Measured the same day:\n\n| params | bytes | tools returned | ≈ tokens | \n|---|---|---|---|\n| `{}` | 529,287 | 1,859 | ≈ 132,000 | \n| `{\"limit\":200}` | 53,008 | 202 | ≈ 13,000 | \n| `{\"limit\":100}` | 27,977 | 102 | ≈ 7,000 | \n| `{\"limit\":50}` | 14,427 | 52 | ≈ 3,600 | \n| `{\"limit\":20}` | 6,306 | 22 | ≈ 1,600 | \n\nSo the fix looked like it already existed. Except that the feature was strictly opt-in: a request without `params` returned the whole list, byte for byte as before, because that was the compatibility promise made when paging landed. The real decision — *what does a client get when it asks for nothing?* — was deferred, and \"deferred\" meant \"the 529 KB answer\".\n\nMCP hosts do not let a user say \"please pass `limit: 100`\". The client builds that request. A server that pages only on request is a server that pages only for callers who already knew to ask.\n\nWe are changing the default so that no `limit` — including no `params` at all — returns the first page of **100** service tools plus `nextCursor`, and the rest come from following the cursor. Explicit `limit` is unchanged, up to the existing 500 ceiling. Three properties keep this from being a downgrade:\n\n`trial_count DESC, id` since an earlier fix, so the ordering is already a popularity ranking.`tools/call` resolves a name against the active catalogue; it never checked whether that name appeared in the list you were served. A model can search, get an id from `service_discovery` (still the first tool in the list), and call it.\nWe measured how concentrated usage actually is, across the 1,675 services that have ever been called (50,393 usage rows):\n\n| first page | usage rows covered | share | \n|---|---|---|\n| 50 tools | 42,580 | 84.5% | \n| 100 tools | 45,060 | 89.4% | \n| 200 tools | 46,894 | 93.1% | \n\nGoing from 50 to 100 buys 4.9 points for about 14 KB; going from 100 to 200 buys 3.7 points for another 28 KB. 100 is where the curve bends. The row counts are not independent callers — bots and our own probes inflate them — but the decision needs the relative shape, and the shape is stable.\n\nThe honest cost of this change: a client that never follows `nextCursor` will now see 100 tools instead of 1,859. That is deliberate. Today that same client sees a 529 KB list that, in practice, it truncates anyway — except now the truncation is at a boundary we chose and the client can see, with a cursor that says there is more. We would rather be the server that says \"here is page one\" than the server that hands over a payload larger than the context and lets the client decide what to drop.\n\n`tools/list` bytes, not your tool count.\nThe change is written, reviewed against the deployed source, and covered by a test that seeds more services than the default page holds — so a future edit that raises the default, or removes it, fails instead of silently restoring the 529 KB answer. It is queued behind the gateway binary deploy; this post will be updated with the live before/after when it ships.\n\n*Originally published at [minia2a.uk](https://minia2a.uk/blog/mcp-tools-list-context-budget-november-2026).*", "url": "https://wpnews.pro/news/one-tools-list-call-cost-529-kb", "canonical_source": "https://dev.to/minia2a/one-toolslist-call-cost-529-kb-22c2", "published_at": "2026-11-11 07:52:29+00:00", "updated_at": "2026-11-11 07:58:21.407632+00:00", "lang": "en", "topics": ["ai-agents", "agent-protocols", "ai-tools", "large-language-models"], "entities": ["MCP", "tools/list", "tools/call", "service_discovery"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/one-tools-list-call-cost-529-kb", "markdown": "https://wpnews.pro/news/one-tools-list-call-cost-529-kb.md", "text": "https://wpnews.pro/news/one-tools-list-call-cost-529-kb.txt", "jsonld": "https://wpnews.pro/news/one-tools-list-call-cost-529-kb.jsonld"}}