Code Execution with MCP
Exposing tools as code APIs so agents compose them programmatically instead of making one heavyweight call at a time.
The scaling problem with direct tool calls
MCP solves connection. But as connected servers multiply, two costs grow with them:
1. Definitions bloat the window. Every tool definition loads into context before the agent does anything. Connect five servers with 40 tools each and you've spent tens of thousands of tokens on possibilities, most never used.
2. Intermediate data flows through the window. Direct tool calls round-trip through the model. Fetch a 20,000-token document from Google Drive to post it to Salesforce, and those 20,000 tokens enter context — then get echoed back out in the next tool call's arguments. The model paid to read, hold, and retype data it never needed to think about.
Direct calls:
gdrive.getDocument -> 20k tokens INTO context
salesforce.updateRecord(...same 20k tokens back out...)
Each hop costs tokens, latency, and a fresh chance to garble the payload.
The pattern: tools as code APIs
The fix is to change what "using a tool" means. Instead of the model invoking tools one call at a time, you:
- Present MCP servers as code APIs — generate a filesystem tree of typed wrapper modules, one folder per server, one file per tool.
- Give the agent a code execution environment — a sandboxed runtime where it can write and run scripts.
- Let it write programs that import and compose those APIs.
The Google Drive → Salesforce workflow becomes a small script the agent writes:
import * as gdrive from "./servers/google-drive";
import * as salesforce from "./servers/salesforce";
const doc = await gdrive.getDocument({ documentId: "abc123" });
await salesforce.updateRecord({
objectType: "SalesMeeting",
recordId: "00Q5f000001abcXYZ",
data: { Notes: doc.content },
});
console.log("Transcript copied to Salesforce record.");
The 20,000-token document now travels through a variable, not the context window. Only the script (dozens of tokens) and the final console output (one line) touch the model's context.
The measured payoff
On one real workflow, Anthropic measured the switch from direct tool calls to code execution at ~150,000 tokens down to ~2,000 — a 98.7% reduction, with matching cost and latency wins. The saved tokens weren't reasoning; they were plumbing. Code execution moves plumbing out of the model.
Progressive disclosure comes free
The filesystem layout solves the definition-bloat problem too. Instead of holding every tool definition in context, the agent explores the tree on demand:
servers/
google-drive/ getDocument.ts search.ts ...
salesforce/ updateRecord.ts query.ts ...
slack/ postMessage.ts ...
It lists servers/ to see what's connected, opens only the two files it needs, and reads their typed signatures. Definitions for the other 198 tools cost zero tokens. This is progressive disclosure — the same principle behind just-in-time context retrieval, applied to tool definitions.
Why code, specifically
This pattern lands because code is what the Agent SDK guidance already says to prefer when output must be precise, composable, and reusable:
- Precise: a loop processes 500 records identically; 500 tool calls give 500 chances to drift.
- Composable: filter, transform, aggregate between tool calls — logic that direct calling would force through the model's context.
- Reusable: a working script can be saved and re-run; a transcript of tool calls cannot.
Control flow is the clearest win. "Fetch every open invoice, sum by customer, flag any over $10,000" is three lines of code — versus dozens of round trips with running totals held precariously in the model's working memory.
When to stay with direct calls
Direct tool calling still wins when:
- the task is one or two calls — a script adds ceremony for nothing,
- you want the model to see intermediate results and reason about them — judgment calls between steps are the one thing plumbing-through-variables removes,
- no sandbox is available or trusted — code execution requires an environment where agent-written code can run safely,
- the humans debugging prefer legible call-by-call traces over reading generated scripts.
The rule of thumb
Route data through variables and judgment through the model. If a step needs the model's reasoning about content, make it a direct call and let the result enter context. If a step just moves or reshapes bytes, that's plumbing — write code. Large payloads plus multiple hops plus no judgment in between is the signature: the moment you see it, reach for code execution.