# MCP Server Cost Optimization: Toolset Size, Caching Hints, and Fan-Out

> How the token cost of an MCP server's tool list, the 2026-07-28 spec's ttlMs/cacheScope caching hints, fan-out from callers you do not control, and per-tool-name cost visibility each shape what a production MCP server actually costs to run.

Guide: MCP in practice — part 8
Published: 2026-08-15 · Updated: 2026-08-15 · 1498 words
Canonical: https://changegamer.ai/articles/mcp-server-cost-optimization
JSON: https://changegamer.ai/api/articles/mcp-server-cost-optimization.json
Pillar: https://changegamer.ai/articles/mcp-server-in-production.md

## In short

- A tool list re-injected into an agent's context on every session carries a token cost proportional to the number of tools registered, so a fifty-tool MCP server imposes roughly ten times the standing token tax of an equivalent five-tool server, independent of how often any individual tool actually gets called.
- The 2026-07-28 MCP spec revision added ttlMs and cacheScope parameters to list and resource results as an explicit, server-declared basis for client-side caching, which a client can use to skip re-fetching tools/list within the declared window instead of re-fetching by default.
- Setting a caching TTL longer than how often an MCP server's tool catalog actually changes per user or per session risks a client acting on a stale tool list — this is a reasoned caution about the caching hints, not a documented spec warning.
- From a single MCP server's vantage point, fan-out multiplies load the operator did not architect and cannot fix by changing their own code, because the calling side's sub-agent count and retry behavior are decisions made entirely outside the server.
- Tracking token cost per tool name, the same way per-tool-name latency and error-rate dashboards catch one degrading tool inside a healthy-looking average, prevents one expensive MCP tool from hiding inside a server-wide cost figure that still looks reasonable.

---

The pillar's [cost section](/articles/mcp-server-in-production) names three levers in one paragraph each — keep the toolset small, exploit `ttlMs`/`cacheScope`, watch fan-out — and points to [agent cost and latency optimization](/resources/agent-cost-latency-optimization) for the underlying compounding model. This article goes deeper on exactly those three, plus a fourth angle the pillar does not cover at all: attributing cost to a specific tool rather than to a server-wide total.

## How much does a large tool list actually cost, in tokens?

A tool list costs tokens every time it is fetched and placed into an agent's context, and that cost scales with how many tools are registered, not with how many of them ever get called. The compounding-cost model behind this site's cost guidance states it generally: **Cost ≈ tokens_per_call × price_per_token × N**, where N is the number of calls in a trajectory ([agent cost and latency optimization](/resources/agent-cost-latency-optimization)). Applied to an MCP server's tool list specifically, the relevant substitution is:

- Let **k** = the number of tools registered on the server.
- Let **t** = the average number of tokens a single tool definition costs to describe (name, description, input schema).
- The token cost of the list alone, per fetch, is approximately **k × t**.
- If that list gets re-fetched and re-injected **N** times across a session or a fleet of sessions, the standing token tax is **(k × t) × price_per_token × N** — the same shape as the general formula, with the tool list substituted for a single call's payload.

Holding t, price_per_token, and N constant, a server exposing 50 tools instead of 5 carries roughly ten times the standing token tax per fetch that the 5-tool server does — an illustrative ratio, not a fixed number, since actual descriptions vary in length and some clients cache the list rather than refetching it every time (the next section covers exactly when that caching kicks in). The practical implication is the one the pillar already states as a rule — keep the toolset small — but the mechanism is worth seeing explicitly: it is not an abstract "audit surface" argument, it is a line item that scales linearly with k on every fetch that is not served from cache.

## What do ttlMs and cacheScope actually change on the wire?

The `ttlMs`/`cacheScope` parameters, added to list and resource results in the 2026-07-28 MCP spec revision, give a server "an explicit, server-declared basis for client-side caching" ([MCP goes stateless](/resources/mcp-2026-spec-revision)) — a signal a client can act on, not a caching layer the protocol builds for you. What changes with the hint set versus unset is a difference in default behavior, not a difference in what data is returned:

- **Without the hint set**, a client has no server-declared basis to assume a previous `tools/list` result is still valid, so the conservative default is to re-fetch it — paying the `k × t` token cost from the previous section again on every session or reconnection, even if the tool catalog has not actually changed.
- **With `ttlMs`/`cacheScope` set**, a compliant client may skip that re-fetch and reuse the previously fetched list for the declared duration and scope, which is what actually removes the repeated token cost rather than just moving it around.

This article's own reasoned caution, not a documented spec warning: setting a TTL longer than how often the underlying tool catalog genuinely changes risks a client acting on a stale list. A server whose available tools vary by user tier, by feature flag, or by session state — rather than staying fixed for every caller — should set a short TTL or a narrow `cacheScope` deliberately, because a client that skips a re-fetch it should have made will act on tool definitions that no longer describe what the server actually does. Treat the caching hint as a trade a server operator makes explicitly, not a default to maximize blindly for token savings.

## Fan-out cost, from the server operator's side

Fan-out raises an MCP server's cost in a way the server operator cannot fix by changing anything about their own code, because the fan-out decision belongs entirely to whoever operates the calling agent. The pillar's fan-out bullet is written from the calling side: "if you are also the one operating the calling agent, the fix is architectural — fewer sub-agents, or a shared cache in front of your server." That fix is unavailable to a server operator who is not also the caller.

The underlying arithmetic is the same one that drives cost on the calling side — "a pipeline that spawns 5 sub-agents each making 10 calls multiplies spend by 50× relative to a single-agent 1-call solution" ([agent cost and latency optimization](/resources/agent-cost-latency-optimization)) — but from a server's vantage point that multiplication shows up as **aggregate request volume with no single visible cause**. One integrator's badly architected fan-out and five separate integrators each making a handful of calls can produce the same request-rate spike on the server side; from inside the server, both look identical: more calls, no way to tell from volume alone whether it is one caller's runaway fan-out or organic growth across many callers.

What a server operator can actually do, since the calling side's architecture is out of reach:

- **Per-key or per-client rate limiting**, so one caller's fan-out is capped without penalizing every other caller.
- **Coarser-grained tools** that let a caller accomplish in one call what previously took several, which reduces the call count a given task generates regardless of how many sub-agents dispatch it.
- **Usage quotas tied to identity**, where the server has an identity to attach a quota to — which is itself a real constraint: a server with no per-key tracking has no lever here at all, only the blunt option of rate-limiting by IP or capping total throughput server-wide.

## Track cost per tool name, not just per server

Aggregating token cost by tool name, the same way [MCP server observability with OpenTelemetry](/articles/mcp-server-observability-opentelemetry) already recommends aggregating latency and error rate by tool name, catches one expensive tool that a server-wide average would hide. That sub establishes per-tool-name p50/p95 latency and per-tool-name error rate as metrics distinct from per-call span logging, for the same structural reason cost hides too: any one tool's numbers get folded into an overall figure that a healthy majority of calls keeps looking fine, so the single outlier only shows up once it has already grown large enough to move that overall figure on its own.

The same logic applies directly to cost: a tool that returns a large payload, or one whose handler makes several model calls internally rather than a single deterministic lookup, can account for a disproportionate share of total token spend while the server's overall average still looks unremarkable. Aggregating cost by tool name surfaces that tool immediately instead of waiting for it to move the whole server's number. This reuses the same category of usage-tracking span attributes sub 6 already covers for latency and error rate — the addition here is grouping by tool name on the cost dimension specifically, not a new instrumentation mechanism.

Per-tool cost visibility also matters independently of whether a server can attribute cost to a specific caller. ChangeGamer's own `/mcp` endpoint is unauthenticated as of August 2026, gated only by a single `api_key` argument check with no per-key rate-limiting layer on top of it ([issuing API keys to AI agents](/articles/api-key-issuance-for-agents)) — which means it has no built-in way to attribute cost to a specific caller. It can still attribute cost to a specific tool, because that grouping depends only on which tool a call invoked, not on who called it. A server without caller-level attribution loses the fan-out mitigation the previous section describes, but per-tool cost tracking remains available regardless, which makes it worth building even on a server that cannot yet identify its callers individually.

## Where this leaves you

Treat a large tool list as a standing, session-repeated token cost that scales with how many tools are registered, not with how many actually get called, and cut the list before reaching for any other lever. Set `ttlMs`/`cacheScope` deliberately once the 2026-07-28 spec revision makes them available, short where the catalog genuinely varies by user or session and longer only where it demonstrably does not. Expect fan-out to show up as aggregate load with no single visible cause when the calling side's architecture is outside your control, and reach for per-key rate limits, coarser tools, or quotas instead of a fix that only works if you also operate the caller. And build cost aggregation by tool name alongside the per-tool latency and error-rate dashboards [MCP server observability with OpenTelemetry](/articles/mcp-server-observability-opentelemetry) already recommends, because a server-wide cost average hides exactly the kind of single expensive tool an operator most needs to find. For the full cost picture this article extends, see [MCP server in production](/articles/mcp-server-in-production) and [agent cost and latency optimization](/resources/agent-cost-latency-optimization); for the spec revision that introduced the caching hints, see [MCP goes stateless](/resources/mcp-2026-spec-revision).

## Frequently asked questions

### Does registering more tools on an MCP server actually cost more money?

Yes — every tool registered adds tokens to the tool list a client fetches and re-injects into context, so the total token cost of that list scales with the number of tools regardless of whether any given tool is ever invoked, which is why trimming a large toolset lowers cost even before considering call volume.

### What do the ttlMs and cacheScope parameters actually change for an MCP server's cost?

The ttlMs and cacheScope parameters, added in the 2026-07-28 MCP spec revision, let a server attach an expiry window and a reuse boundary to a tool-list response or a resource response, and a client that respects those values can serve its own cached copy for that window instead of issuing a fresh request on every session by default.

### How does fan-out raise cost for an MCP server if the server operator does not control the callers?

Fan-out on the calling side — several sub-agents or independent integrators each making repeated calls into one server — sums into aggregate load the server operator experiences as a request-rate problem with no single misbehaving caller to point at, since the fix of reducing sub-agent count belongs entirely to whoever operates the calling agent, not to the server.

### How do I find out which MCP tool is costing the most to run?

Aggregate token usage by tool name across the same spans already being emitted for tracing — the same practice already covered for latency and error-rate metrics — rather than relying on a single server-wide cost total, because a server-wide average can look healthy while one specific tool accounts for a disproportionate share of total spend.


---

## The rest of this guide

- [MCP Server in Production: How to Build, Ship and Run One](https://changegamer.ai/articles/mcp-server-in-production.md): The operator playbook for taking an MCP server past the quickstart: transport choice, OAuth 2.1 auth, tool design, versioning against a moving spec, testing across clients, distribution, observability, cost and the failure modes that show up once real clients connect.
- [stdio vs. Streamable HTTP for MCP Servers: A Decision Framework](https://changegamer.ai/articles/mcp-stdio-vs-streamable-http.md): Which MCP transport to build against and why: the single-client-vs-shared decision rule, how state works without a session handshake under the 2026-07-28 spec, the auth-model switching cost, and what actually breaks migrating off HTTP+SSE.
- [How to Implement OAuth 2.1 for an MCP Server](https://changegamer.ai/articles/mcp-oauth-implementation.md): A wire-level implementation walkthrough for OAuth 2.1 on a remote MCP server: what the discovery documents actually contain, CIMD vs. Dynamic Client Registration in your server code, per-SEP detail from the 2026-07-28 hardening set, and token-validation mechanics.
- [Defending MCP Clients Against Tool Description and Output Injection](https://changegamer.ai/articles/mcp-tool-description-injection.md): Two distinct MCP injection surfaces — a tool description at connect-time and a tool's return value at call-time — and the client-side architectural patterns (Dual LLM, Action-Selector, Context-Minimization) that contain each one.
- [How to Test an MCP Server in CI](https://changegamer.ai/articles/testing-mcp-servers-in-ci.md): The implementation mechanics below the three-layer test pyramid: what a mocked MCP transport actually replaces, what a Streamable HTTP cassette contains, a concrete CI job/trigger shape, and how to catch spec-version drift before it reaches production.
- [MCP Server Versioning and Spec Migration: An Operator Playbook](https://changegamer.ai/articles/mcp-server-versioning-and-spec-migration.md): A migration runbook for MCP server operators: feature-detecting via capabilities instead of hard protocolVersion branching, a dual-version fleet rollout with rollback triggers, a compatibility shim for legacy clients still sending initialize, and a deprecation calendar built off the 12-month SEP-2577 floor.
- [MCP Server Observability with OpenTelemetry: Spans, Metrics, and Trace Correlation](https://changegamer.ai/articles/mcp-server-observability-opentelemetry.md): Instrumenting an MCP server past the pillar's baseline: what to put on a tool-call span beyond gen_ai.tool.name, what replaces the deprecated Logging primitive in practice, per-tool-name latency and error-rate metrics, and how a trace ID actually survives the agent-to-upstream-API hop.
- [How to Publish an MCP Server to the Official Registry](https://changegamer.ai/articles/mcp-server-registry-publishing-playbook.md): A step-by-step walkthrough of the mcp-publisher CLI and the server.json manifest for publishing an MCP server to registry.modelcontextprotocol.io, how to republish after a version bump, and how the registry relates to aggregators, marketplaces, and direct distribution.
- [Common MCP Server Failure Modes and How to Fix Them](https://changegamer.ai/articles/mcp-server-failure-modes.md): A runtime playbook for the two MCP server failure modes with no dedicated deep-dive elsewhere: unrecoverable state after a mid-call crash, and malformed or hallucinated tool calls that reach the handler despite upstream validation.
- [MCP Tools vs Resources vs Prompts: How to Choose the Right Primitive](https://changegamer.ai/articles/mcp-resources-and-prompts-vs-tools.md): A decision procedure for MCP's three server-side primitives — who controls each one, a worked example of what it costs to expose a Resource as a Tool by mistake, and how Sampling and Elicitation fit as the client-side counterparts.
- [The MCP Server Production Launch Checklist](https://changegamer.ai/articles/mcp-server-production-launch-checklist.md): A phase-by-phase go/no-go checklist for launching an MCP server: checkable gate conditions for transport and auth, tool design, cross-client testing, publish readiness, observability, and ongoing operation — with links to the mechanics each gate depends on.
- [Zero-Touch Enterprise Authorization for MCP Servers: ID-JAG and SEP-990](https://changegamer.ai/articles/mcp-enterprise-sso-id-jag.md): How Enterprise-Managed Authorization (SEP-990) removes the per-server OAuth consent screen for MCP servers: the ID-JAG grant mechanism, its RFC 8693/7523 building blocks, named launch adopters as of August 2026, and how it layers on top of standard OAuth 2.1 rather than replacing it.

## Reference resources

- https://changegamer.ai/resources/agent-cost-latency-optimization.md
- https://changegamer.ai/resources/mcp-2026-spec-revision.md

All guides: https://changegamer.ai/api/articles.json · Reference corpus: https://changegamer.ai/llms.txt
