MCP code mode: let the AI write code that calls tools, not one call at a time
Let the model write code that calls MCP tools instead of one JSON call at a time. Anthropic's 150,000 to 2,000 token example, Cloudflare's Code Mode, and the costs.
- Classic tool calling burns tokens twice, on every tool definition loaded up front and on every intermediate result passing through the model
- When the model writes code that calls tools, intermediate data stays in the runtime and the model sees only the final output; Anthropic's example went from 150,000 to 2,000 tokens
- The price is a sandbox for model-written code, with resource limits, no open network and monitoring
- Worth it with many tools or large intermediate data; with a few tools and small results, direct calls are simpler
Wire an AI agent to a few MCP servers and the same thing keeps happening: before any work starts, the context is full of tool definitions, and once work starts, every tool result flows through the model even when it only has to be handed to the next tool. Anthropic and Cloudflare independently proposed the same fix: let the model write code that calls the tools.
Facts checked against Anthropic’s Code execution with MCP (November 2025), Cloudflare’s Code Mode post (September 2025) and Cloudflare’s changelog, as of October 2026. The code here illustrates the idea; it is not any product’s API.
The problem: tokens leak two ways
If MCP itself is new to you, start with EP6 on MCP.
Leak one: tool definitions. Most clients load every tool’s name, description and schema into the context up front. Suppose you connect 10 servers with 10-20 tools each: the model reads a hundred-plus definitions before the user types a word.
Leak two: intermediate results. Take “download the meeting transcript from Google Drive and attach it to the lead in Salesforce”. With direct calls, the model calls the first tool, receives the whole transcript into its context, then writes the whole transcript out again as input to the second tool. The same text passes through the model twice, and the model never needed to think about it.
That is the example Anthropic uses: about 150,000 tokens with direct calls, about 2,000 tokens with code execution.
The idea: tools become code files
Instead of loading every definition, generate a wrapper per tool as a file, grouped by server:
servers/
├── google-drive/
│ ├── getDocument.ts
│ └── index.ts
├── salesforce/
│ ├── updateRecord.ts
│ └── index.ts
└── sheets/
├── getRows.ts
└── index.ts
The model lists the folders, opens only the tool files it needs and writes code. An illustration with a hypothetical sheets server:
// generated wrapper: one file per tool, calls the MCP server underneath
import { callMCPTool } from "../client";
export async function getRows(input: { sheetId: string }): Promise<Row[]> {
return callMCPTool<Row[]>("sheets__get_rows", input);
}
// what the model writes, run inside the sandbox
import * as sheets from "./servers/sheets";
const rows = await sheets.getRows({ sheetId: "abc123" });
const pending = rows.filter((r) => r.Status === "pending");
console.log(`${pending.length} pending of ${rows.length}`);
console.log(pending.slice(0, 5)); // the model sees only this
The 10,000 rows stay in the runtime. The model sees only what console.log prints.
Worked example
Anthropic’s numbers: 1 − 2,000 ÷ 150,000 = 1 − 0.0133 = 0.987, a 98.7% reduction, matching the article.
A 10,000-row sheet (assume about 40 tokens per row, a figure for the arithmetic only):
| Direct tool call | Code filters first | |
|---|---|---|
| Result entering the context | 10,000 × 40 = 400,000 tokens | 5 rows × 40 = 200 tokens + a summary line |
| Fits the context window? | Overflows many models’ windows | Easily |
| Passing it to the next tool | The model writes the data out again | Code passes it on; the model never sees it |
The saving grows with the size of the intermediate data. A task whose results are already small (read one temperature value) gains almost nothing.
Benefits beyond tokens
- Loops and conditions in code. Waiting for “deployment complete” in Slack becomes a loop with
setTimeoutinstead of dozens of alternating tool calls and sleep commands - Private data can skip the model. Intermediate results stay in the runtime by default. Anthropic also suggests the client replace values such as emails with tokens like
[EMAIL_1]before the model sees them, restoring the real values when data moves between tools - State and skills. Code can write results to files, and functions that work can be saved to a folder and reused
Cloudflare’s Code Mode
Cloudflare shipped the same idea in its Agents SDK as Code Mode (post of 26 September 2025 by Kenton Varda and Sunil Pai):
- The SDK fetches each MCP server’s schema and generates a TypeScript API, with types and doc comments taken from the schema descriptions
- The model sees one tool, “run TypeScript”, instead of dozens
- Code runs in a V8 isolate via the Worker Loader API; the post says an isolate starts in a few milliseconds and uses a few megabytes, so a fresh one per snippet is cheap
- No internet:
fetch()andconnect()throw. The code can reach MCP servers only through the bindings it is given - The code never holds keys. Bindings are already authorised; the supervisor adds the tokens
Status as of October 2026: Cloudflare’s changelog of 24 March 2026 put Dynamic Workers, the feature behind the Worker Loader, in open beta for paid Workers users, names Code Mode as the first use case and claims it “can save up to 80% in inference tokens and cost”. That is a vendor figure; pricing is in the linked changelog.
Code mode does not remove MCP. MCP is still the pipe and the permission layer; the model just talks to it in code.
What it costs
Both posts say it plainly: running model-written code needs a secure execution environment, and that is extra work.
| Direct tool calls | Model writes code | |
|---|---|---|
| Sandbox needed | No | Yes: isolated files, no open network, CPU/RAM/time limits |
| Tokens with large intermediate data | High | Low |
| Auditing | Every call is in the agent log | Also keep the executed code and sandbox logs |
| Failure modes | Model picks the wrong tool | Same, plus bugs in the code |
| Fits | Few tools, small results | Many tools, big data, multi-step jobs |
For sandboxing on a developer machine, see sandboxing an AI coding agent.
Common mistakes
- Running generated code with
evalornodeon a real server. Anyone who can get text into the context can now run code on your machine; see the prompt injection article - Leaving the sandbox network open “just in case”. Code that can read secrets and reach the internet is a ready-made leak. Allow only the MCP servers it needs
- Putting API keys in the sandbox environment. Let a component outside the sandbox attach credentials, as Cloudflare’s bindings do
- Logging the whole dataset.
console.log(rows)brings everything back into the context and the saving drops to zero - No time limit. A loop waiting for an event needs a timeout, or it hangs and eats resources
- Using it for everything. With three tools and small results, a sandbox is not worth it. Lessons on designing tools well in the first place are in real lessons from an 18-tool MCP server
Sources
FAQ
Does code mode replace MCP?
No. MCP still handles discovering tools, connecting to them and authorisation. What changes is how the model invokes them; instead of emitting one JSON call per tool it writes code against an API generated from the MCP schemas.
Why would a model write code better than it makes tool calls?
Cloudflare's argument is that models have seen huge amounts of real TypeScript in training but far fewer, mostly synthetic, tool-call examples. That is the authors' reasoning; their post gives no measurements for it.
Can I just run the generated code on my own machine?
Not directly on a machine or server that holds anything real. You need a sandbox that limits files, network, time and memory, and the code should never hold credentials itself.
Commands and settings were tested on sample systems. Try them on a test machine before production.