Cloudflare named code mode in September 2025, resting it on one line: "LLMs are better at writing code to call MCP, than at calling MCP directly." The follow-up post put a number on it β an entire 2,500-endpoint API in about 1,000 tokens.
I wanted my own number, on my own data, for a task I actually had.
fetch all linear tickets in progress (full body for each) and count the amount of times we say 'mcp' across all of it
39 tickets. Nothing exotic β the kind of thing you ask an agent on a Tuesday.
There are two ways an agent can do this.
As tool calls. One list_issues
, then a get_issue
for each ticket. Every ticket body travels into the model, because the model is the thing holding the running total. Forty round trips, each one waiting on the model to decide what to ask next.
As a script. The agent writes ten lines, runs them once, and reads back a number. The bodies never enter its context at all.
| into the model | round trips | |
|---|---|---|
| as tool calls | ~65,500 tokens (262,159 chars) | 40, in sequence |
| as one script | ~226 tokens (903 chars) | 1 |
290Γ less into context. 99.66% saved.
The token figures use the rough four-characters-per-token heuristic β the character counts are the exact measurement, and the ratio is the part that survives different data. Yours will differ with your tickets.
And ~65,500 is the floor, not the ceiling. In a tool-call loop, context is re-read on every subsequent turn. The script pays once.
Two things, and I think both matter more than the headline ratio.
Latency. Forty sequential tool calls each wait for a model to decide what to ask next. The script issues the same forty HTTP requests without stopping to think between them. The token saving is money; the round-trip saving is the thing you actually sit through.
Correctness. Counting occurrences of a substring across a quarter of a million characters of prose is something a model does approximately. A script does it exactly. So the tool-call path doesn't just cost 65,500 tokens β it spends them and still hands back a number you can't fully trust. This is the part that surprised me: I expected code mode to be a cost optimisation, and it turns out to also be an accuracy one, for any task with counting, joining, or set logic in it.
Here's where it got annoying, and where I ended up writing something.
Every code mode implementation I looked at makes you supply credentials before the first call. Cloudflare's sandbox takes bindings you configure. VoidMCP wants tokens registered via CLI. mcp-use
and LangChain's MultiServerMCPClient
read a config with your API keys. MCPorter β the closest thing to what I wanted, and more mature than what I built β imports server definitions from Cursor, Claude, Codex, Windsurf, OpenCode and VS Code, but keeps its own vault and makes you authenticate again.
Meanwhile my coding agent was already logged into all of them.
Claude Code stores an OAuth token for every MCP server you've ever logged into. On macOS that's a single Keychain item, service Claude Code-credentials
, whose mcpOAuth
map is keyed <serverName>|<urlHash>
. claude mcp
can add servers, list them, and log into them β it just can't call them. So the OAuth dance is already done and the result sits unused.
So I wrote agent-codemode, which reads those tokens and speaks Streamable HTTP MCP directly:
npm install -g agent-codemode
agent-codemode servers # who has a live token
agent-codemode types --all # typed TS for every server you're logged into
js
import { mcp } from "agent-codemode";
const [issues, events, channel] = await Promise.all([
mcp.linear.listIssues({ assignee: "me", limit: 50 }),
mcp.axiom.queryDataset({ apl: "['prod'] | where _time > ago(24h) | summarize count()" }),
mcp.slack.slackSearchChannels({ query: "general" }),
]);
Three servers, three different auth mechanisms, one await
, and no .env
β because there is nothing to put in it.
types --all
generates a TypeScript module per server from its live tools/list
. Each generated module declaration-merges into an McpServers
interface, so importing it is the whole setup and mcp.linear.listIssues({ bogus: 1 })
is a compile error, with no cast at the call site.
Almost none of this. Multi-server scripting isn't new. Typed clients aren't new. Reading other editors' MCP config isn't new. The only thing I did was skip the credential step, and that's a narrow difference.
It's also, I think, the difference that decides whether the script gets written. An agent mid-task reaches for what works right now. It does not stop and ask you to go complete an OAuth flow.
A script needs one more thing to happen: the agent has to know the option exists. Left alone it does what it knows, one tool call at a time.
So the repo ships a skill. Drop it in ~/.claude/skills/
and the behaviour changes by default. That's the actual mechanism behind the two rows in the table β not the library, the fact that the agent reaches for it.
~/.claude/.credentials.json
, but nobody has confirmed a full run yet.unsupported
.MIT, on npm as agent-codemode
.