Hey, I was studying my agent's token usage and not...
# proj-agent-canvas
a
Hey, I was studying my agent's token usage and noticed something: because I had the default MCP integrations for Linear, GitHub, and Notion enabled, every single prompt was carrying ~140 tool definitions! About 52k tokens of overhead per call!! That's paid on every turn, whether I'm using those integrations or not. I ran a quick experiment comparing MCP vs direct API calls (using curl + the skill docs) on the same tasks, and the API path used 3.6-4x fewer tokens for the same results. I think I'm going to switch away from MCP to direct API calls for integration work, it seems like it'll be meaningfully more efficient, especially on longer tasks.
l
Yeah, we might want to think about some alternative options here. For instance maybe we just want to have an option to just show the function names and provide the additional info on request?
@fresh-machine-37269 how do the most popular open-source harnesses like Hermes, OpenCode, Pi, Codex handle MCP-based context bloat?
πŸ‘€ 1
f
πŸ€– On it! View progress here: oss-agent-canvas.ngrok.dev/conversations/…
a
(I think there is a newer trend towards just using APIs, the coding models are smart enough to use them, unless you really need the reliability of MCP) We should have more transparency for folks using MCP
l
Yeah, I think MCP’s main advantage is that at least in theory you don’t have to give your agent an API key
But context bloat is a big problem.
a
oh yea, i didn't think about that with the API key
f
βœ… Done! Here’s how each of them tackles it: Hermes β€” Per-server tool filtering with `include`/`exclude` lists, plus the ability to disable utility wrappers (
prompts: false
,
resources: false
). You can set
enabled: false
to skip a server entirely. The install catalog gives you an interactive checklist to pick exactly which tools you want. There's also a toolsets system for enabling/disabling groups of tools per platform, and a
/compress
command for context compaction. OpenCode β€” Explicit
enabled: true/false
per MCP server, plus wildcard-based permission control (
"mymcp_*": "deny"
). Their docs explicitly warn that MCP servers "add to your context" and call out GitHub's MCP server as a known token hog. They also support auto-compact for conversation history. Pi β€” The most architecturally interesting approach: dynamic tool activation. You register tools but keep them inactive by default, then activate them lazily via a "loader" tool. The loader can use keyword search, BM25, embeddings, or whatever you want to find the right tool. Tools use
promptSnippet
(a one-line entry in the tool list) instead of the full JSON schema, so only the loader tool's definition takes up space. Pi also supports native deferred loading for Anthropic and OpenAI providers, and falls back to sending the full tool list on the next request when the active set changes. Codex β€” Server-level enable/disable, namespace management via
non_prefixed_mcp_tool_servers
, orchestration control (
orchestrator_mcp_enabled
), and a
ToolSuggestConfig
system for discoverable tools. On the context side, Codex has
model_auto_compact_token_limit
for automatic compaction,
model_context_window
configuration, and prompt cache key mechanisms to reduce redundant computation. The common thread: opt-in, not opt-out. All four assume MCP servers should be selectively enabled rather than all-on-by-default, and all provide some mechanism to filter tools at the server level. Pi goes furthest with its lazy activation model β€” the LLM only sees full tool schemas for tools it's actually about to use, which is the closest thing to solving the "52K tokens of overhead" problem you described.
l
@fresh-machine-37269 are there any issues open or closed on OpenHands/OpenHands or OpenHands/software-agent-sdk regarding MCP token efficiency?
πŸ‘€ 1
f
βœ… Done! Yes β€” the relevant work lives mostly in the SDK repo (
OpenHands/software-agent-sdk
), which is where the agent/tool logic now lives.
OpenHands/OpenHands
has MCP issues too, but they're mostly UI/integration rather than token efficiency. Here's what's out there: Directly about MCP token efficiency β€’ #376 β€” "MCP Tool Integration: Selective tool registration and filtering" (closed) β€” The classic one. Describes the exact problem you hit ("receiving too many tools that aren't useful"), notes the existing
filter_tools_regex
is client-side-only and regex-crude, and proposes `include_tools`/`exclude_tools` per server plus selective registration at init. β€’ #4083 β€” "investigate Tool search / defer_loading on the Responses path (GPT-5.4+)" (closed) β€” Explicitly about token efficiency: "An OpenHands agent typically loads a fat toolset… those schemas are re-sent every turn… Deferring rarely-used tools (especially large MCP surfaces) behind tool search could materially cut input tokens." This is OpenAI's native `defer_loading`/tool-search mechanism (the same approach Pi uses). β€’ #4130 β€” "Feature: search_tool" (closed) β€” Notes "the number of tools grows, specially via MCPs, so including them in the system prompt is weighing it down… caching is affected too," and proposes a retrieval-style
search_tool
. Related token/cache work (MCP-adjacent) β€’ #2972 β€” "Investigate prompt-cache reuse across sub-agent conversations" (closed) β€’ #3445 β€” "count tools for condenser token limits" (closed) β€’ #1787 β€” "Proposal: Fork conversation when tools change" (closed) β€’ #3894 β€” "subscribe to tools/list_changed for progressive-disclosure servers" (closed) β€” lets servers expose only a small gateway toolset and add tools on demand, which is another way to keep the tool list lean. Practical tool-trimming issues (still useful for you) β€’ #4307 β€” "add MCPServer.enabled to switch a server off without removing it" (closed) β€” the enable/disable toggle (already shipped). β€’ #4184 β€” "[Bug] Runtime MCP tools bypass Agent.filter_tools_regex" (closed) β€” a bug where the regex filter didn't apply to runtime-materialized MCP tools. β€’ #4402 β€” "refresh tools for active conversations" (open) β€” still open. β€’ #2754 β€” "Auto-discover project-scoped `.mcp.json`" (closed) β€” scoping MCP servers per-project is a partial answer to "don't load Linear/GitHub/Notion everywhere." Net takeaway The most on-point, token-specific item is #4083 (native tool-search/defer-loading) and its predecessor #376 (selective registration). There's no single open issue in
OpenHands/OpenHands
tracking "MCP token bloat" as a first-class problem β€” the UI repo mostly has enable/disable UX (#16171) and catalog promotion (#11004) rather than efficiency work. If you want to push this forward, the SDK repo is the right place, and #4083's
defer_loading
+ a
search_tool
are the two mechanisms the maintainers are already circling.
l
@fresh-machine-37269 link me up
πŸ‘€ 1
f
βœ… Done! Here are all the links from that answer: MCP token efficiency (core) β€’ #376 β€” Selective tool registration & filtering: github.com/OpenHands/software-agent-sdk/issues/376 β€’ #4083 β€” Tool search /
defer_loading
on the Responses path: github.com/OpenHands/software-agent-sdk/issues/4083 β€’ #4130 β€” Feature: `search_tool`: github.com/OpenHands/software-agent-sdk/issues/4130 Token/cache (MCP-adjacent) β€’ #2972 β€” Prompt-cache reuse across sub-agents: github.com/OpenHands/software-agent-sdk/issues/2972 β€’ #3445 β€” Count tools for condenser token limits: github.com/OpenHands/software-agent-sdk/pull/3445 β€’ #1787 β€” Fork conversation when tools change: github.com/OpenHands/software-agent-sdk/issues/1787 β€’ #3894 β€”
tools/list_changed
progressive disclosure: github.com/OpenHands/software-agent-sdk/pull/3894 Tool-trimming / UX β€’ #4307 β€”
MCPServer.enabled
toggle: github.com/OpenHands/software-agent-sdk/pull/4307 β€’ #4184 β€” Runtime MCP tools bypass `filter_tools_regex`: github.com/OpenHands/software-agent-sdk/issues/4184 β€’ #4402 β€” Refresh tools for active conversations (open): github.com/OpenHands/software-agent-sdk/pull/4402 β€’ #2754 β€” Auto-discover project `.mcp.json`: github.com/OpenHands/software-agent-sdk/issues/2754 OpenHands/OpenHands (UI/integration) β€’ #16171 β€” Enable/disable MCP server from its card: github.com/OpenHands/OpenHands/pull/16171 β€’ #11004 β€” Promote popular MCPs (open): github.com/OpenHands/OpenHands/issues/11004 The two worth opening first if you want to follow the token-efficiency thread: #4083 (native tool search) and #376 (selective registration).
l
agreed, I re-opened the first two. i think this is worth thinking about.
@fresh-machine-37269 add comments to each of those regarding the reference materials that you found, including links to the source files that could be examined.
πŸ‘€ 1
f
βœ… Done! Done β€” I posted reference comments on all 13 issues/PRs, each one noting the relevant harness (Hermes/OpenCode/Pi/Codex) behavior and linking the specific source files to examine. What got posted (13 total):
OpenHands/software-agent-sdk
(11): β€’ #376 β€” Hermes per-server `include`/`exclude` ↔️
filter_tools_regex
(
agent/base.py
L152-166, L538-567;
mcp/utils.py
L44-73) β€’ #4083 β€” Pi loader + Codex
defer_loading
↔️
to_responses_tool
(
tool/tool.py
L769,
llm/llm.py
L1326,
mcp/tool.py
L461) β€’ #4130 β€” Pi
search_tool
/ Codex
tool_search
pattern β€’ #2972 β€” prompt-cache invalidation on tool-set change (
agent_context.py
, condenser) β€’ #3445 β€” tool-schema token counting (
condenser/utils.py
get_total_token_count
L8-49) β€’ #1787 β€” Pi's "additive is cache-safe" model (
agent/base.py
add_runtime_tools
L832) β€’ #3894 β€” Hermes
tools/list_changed
progressive disclosure (
mcp/utils.py
_ToolListChangedHandler
L263) β€’ #4307 β€” OpenCode
enabled
toggle ↔️
MCPServer.enabled
(
mcp/config.py
L514) β€’ #4184 β€” filter regex bypass bug β€’ #4402 β€” deferred loading needs mid-conversation refresh β€’ #2754 β€” project-scoped MCP config
OpenHands/OpenHands
(2): β€’ #16171 β€” UI enable/disable ↔️ backend
MCPServer.enabled
flag β€’ #11004 β€” token-footprint vs. discoverability tradeoff for popular MCPs Every comment includes a short AI-agent disclosure footer and points at real source paths I verified against
main
(the line numbers may drift slightly over time, but the file paths and function names are accurate).
l
@fresh-machine-37269 Delete the comments on all of them except 4083 and 376
πŸ‘€ 1
f
βœ… Done! Done. β€’ Deleted my comments on all 11 other issues/PRs (#4130, #2972, #3445, #1787, #3894, #4307, #4184, #4402, #2754, #16171, #11004) β€” each returned HTTP 204. β€’ Kept the comments on #4083 and #376, both verified still present. Note: I hit GitHub's secondary rate limit partway through, but the retry/backoff logic worked it out β€” no partial deletions, every target issue now has exactly zero of my comments except the two you asked to keep.