Skip to content

/context "MCP Tools" reports the un-deferred tool-schema footprint, not the actual (deferred) cost sent to the model #4189

Description

@SqlBenjamin

Describe the bug

The interactive /context "MCP Tools" line reports (approximately) the full, un-deferred footprint of all configured MCP servers' tool schemas, rather than what is actually loaded into the model context after tool-search / deferred tool loading. When deferral is active, the model receives only a small fraction of that, so /context — the one command meant to show how full your context is — significantly overstates MCP usage.

In our test configuration the reported figure was ~20× the real deferred cost (98.8k reported vs ~5k actual). The exact multiplier will vary with how many tools each server exposes, but the qualitative defect — /context reflecting the registry footprint instead of the deferred cost the model actually sees — is independent of the specific config.

How this was found (test setup)

This was a deliberate experiment, not a production incident. To see what /context reports under tool-search, we added 16 MCP servers to a home-directory (non-repo) CLI config and compared the /context display against the real context cost, with tool-search enabled vs disabled.

Real cost was measured with non-interactive runs — copilot -p "Reply with only the word: ok" --allow-all-tools — reading the reported Tokens ↑ line, which reflects what is actually sent to the model (it changes when deferral is toggled, so it is a faithful measure of real context).

Evidence

Measured Tokens ↑ (total assembled context for a trivial prompt):

Run tool-search MCP servers Real total (Tokens ↑)
A enabled (TOOL_SEARCH=true) all 16 31.9k
B enabled none (all disabled) 26.9k
D disabled (TOOL_SEARCH_DISABLED=true) all 16 160.9k

Derived from the runs:

  • Real MCP cost with deferral (A − B) ≈ 5.0k.
  • Real MCP cost without deferral (D − B) ≈ 134k.
  • Interactive /context (tool-search enabled) reported MCP Tools = 98.8k.

So with deferral on, the model actually receives ~5k of MCP tokens, yet /context shows 98.8k — roughly the un-deferred footprint. It does not reflect the ~130k that deferral actually saves (proven by Run D ballooning to 160.9k once deferral is off).

Supporting signals:

  • Billed first-call input_tokens for a fresh interactive session ≈ 52k total (system prompt + built-in tools + instructions + memory + MCP + first message) — impossible if MCP alone were truly 98.8k in that session.
  • Telemetry embedding_retrieval_status: status: flag_off, eligible: false on this account. Sessions/users with the dynamic-retrieval arm enabled reportedly see a small, correct /context MCP number for the same real cost — suggesting the display path diverges based on that arm.

Note on the "does it depend on tool-search?" question: we confirmed the real context cost clearly does depend on tool-search (31.9k vs 160.9k). It is specifically the /context display that fails to reflect the deferral savings.

Likely cause (hypothesis)

When the dynamic-retrieval / embedding arm resolves to flag_off, the /context accounting appears to fall back to summing the full tool-schema registry rather than the deferred / actually-loaded set. The displayed figure then tracks the number and size of configured tools (few servers → small; 16 servers → ~99k) even though runtime deferral keeps the real cost roughly flat (~5k here).

Expected behavior

/context "MCP Tools" should reflect the tokens actually sent to the model (the deferred set), consistently, regardless of the dynamic-retrieval experiment arm — so users can trust it to reason about context pressure.

Steps to reproduce

  1. Configure ~16 MCP servers; set TOOL_SEARCH=true; account not in the dynamic-retrieval arm.
  2. Run /context → note the inflated "MCP Tools" figure (98.8k in our case).
  3. Run copilot -p "ok" --allow-all-tools and read Tokens ↑ (≈31.9k here).
  4. Run again with all MCP disabled (--disable-builtin-mcps + --disable-mcp-server <name> for each) → Tokens ↑ ≈26.9k. The delta (~5k) is the real MCP cost — far below what /context reported.
  5. (Optional) Re-run step 3 with TOOL_SEARCH_DISABLED=trueTokens ↑ jumps to ~160.9k, showing how much deferral actually saves and that /context was not reflecting it.

Impact

/context is the primary tool users rely on to reason about context pressure (when to compact, trim servers, etc.). An overstatement of this magnitude for a cohort of users undermines the command's purpose and pushes people to remove MCP servers they don't actually need to.

Environment

  • GitHub Copilot CLI 1.0.72-1
  • OS: Windows 11 (build 26200)
  • Model: claude-opus-4.8
  • 16 MCP servers configured; TOOL_SEARCH=true
  • Account not in the dynamic-retrieval arm (embedding_retrieval_status: status=flag_off)

Related


Attribution: All research, measurement, and analysis behind this report — the A/B token measurements, the CLI-internals investigation, and the drafting of this issue — were performed by GitHub Copilot CLI (v1.0.72-1) in an interactive session, at the user's direction.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:context-memoryContext window, memory, compaction, checkpoints, and instruction loadingarea:mcpMCP server configuration, discovery, connectivity, OAuth, policy, and registry

    Type

    Fields

    No fields configured for Bug.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions