Pi Ships Zero Lines of MCP. Codex Ships 53,713.

Pi Ships Zero Lines of MCP. Codex Ships 53,713.

One harness treats MCP as core infrastructure and spends tens of thousands of lines on it. The other refuses it on principle and tells the agent to write its own tools instead. Both positions are coherent, and the disagreement is not about capability. It is about who owns the schema, what a stable boundary is worth, and what you pay for it in tokens and attack surface on every single request.

September 18, 2026
Harrison Guo
8 min read
AI Engineering Architecture

Pi contains no MCP support. I grepped the entire source tree for it: three hits, all incidental, one of them inside a vendored syntax highlighter.

Codex contains 53,713 lines of it, across three crates. That was true on 2026-09-01:

cratelines
rmcp-client28,230
codex-mcp21,316
mcp-server4,167
total53,713
crate rmcp-client
lines 28,230
crate codex-mcp
lines 21,316
crate mcp-server
lines 4,167
crate total
lines 53,713

I re-ran that count a week later, on 2026-09-08, and the answer had already moved: 55,418, across two crates. rmcp-client had grown to 32,687, codex-mcp to 22,731, and mcp-server had been deleted outright.

Keep that in view for the rest of this piece. A number this size, moving three percent in a week with a whole crate disappearing, is not a fact about MCP. It is a fact about how much surface a team takes on when it decides a protocol is infrastructure, and about who is going to keep paying for that surface after the decision feels finished.

For scale, that is more code than Pi’s entire agent package and terminal UI put together. Two teams looked at the same protocol and one of them decided it was infrastructure while the other decided it was a mistake.

Both of them are right about something, and the thing they disagree about is not capability.

What Pi is actually arguing

The easy summary is that Pi refuses MCP for minimalism. That is not the argument.

Pi’s position is that the interesting form of extensibility is an agent extending itself through code, rather than acquiring capability by downloading it. So Pi ships four tools and a TypeScript extension host: extensions load from the project, hot reload, register new tools with the model, persist state into the session, and render their own terminal components. The system prompt tells the agent where its own extension documentation lives, which is 268 tokens I complained about in the last piece and which exists precisely so the agent can look up how to extend itself and then do it.

Run that forward. You need the agent to query your internal service. Under MCP you find or write a server, configure it, and the tool appears. Under Pi you tell the agent to write an extension, it reads the docs it already has a path to, writes TypeScript, hot reloads, and the tool appears.

flowchart LR
  subgraph P["Pi: the agent grows the tool"]
    direction LR
    p1["agent"] --> p2["writes a TypeScript
extension in your repo"] --> p3["hot reload"] --> p4["tool exists"] p4 -.- p5["schema lives in your repo.
changes in the same commit."] end subgraph C["Codex: the tool lives behind a contract"] direction LR c1["agent"] -. "MCP" .-> c2["separate process,
any language, own creds"] --> c3["tool exists"] c3 -.- c4["schema owned by whoever
runs the server.
can change without you."] end P ~~~ C

The second path has no protocol, no separate process, no versioning story and no registry. For a tool that lives inside your repository and is used by one team, it is genuinely simpler, and the simplicity is not superficial. There is no serialisation boundary to get wrong.

That is a real argument, and it gets stronger every time models get better at writing code.

What Codex is buying

Codex’s answer is visible in a sentence from the app-server README that most people skim past:

Similar to MCP, codex app-server supports bidirectional communication using JSON-RPC 2.0 messages.

Codex did not merely adopt MCP. It built its own primary interface in the same idiom. That tells you what the team believes: the boundary is the product. Threads and turns and items are wire types precisely so that the thing on the other side does not have to be theirs, or Rust, or even in the same process.

Once that is your worldview, MCP is not an add-on. It is the same idea pointed outward instead of inward. The app-server lets other people drive Codex; MCP lets Codex drive other people. Fifty thousand lines and climbing is what it costs to mean it in both directions.

And they mean it. rmcp-client alone is 28,230 lines, which is not what you write to tick a feature box.

The trade nobody states

So the disagreement is not “can the agent do the thing.” Both can. It is a question about schemas, and it has three parts.

Who owns the schema. An extension’s schema is defined where the extension lives, in the same repository, changed in the same commit. An MCP tool’s schema is defined by whoever runs the server, and it can change without you. That is the actual difference. Everything else follows from it.

Whether the boundary has to survive independent deploys. If the tool and the harness always ship together, a protocol buys you nothing and costs you serialisation. If they ship separately, you need a versioned contract, and if you do not use an existing one you will write a worse one.

Whether you can cross the boundary at all. Pi’s extension host is TypeScript because Pi is TypeScript. If your capability lives in a Python service, behind credentials your agent process should not hold, or in another team’s system, the extension answer is not available. There is no amount of model capability that makes a language and trust boundary disappear.

Which produces a rule that is easier than the debate suggests. Ask who owns the schema. If it is you, and it lives in your repository, write the tool in your harness and skip the protocol. If it is somebody else, that is what protocols are for.

The costs that never make it into the comparison

Two of them, and neither shows up in a feature matrix.

Tokens. I measured Pi’s per-request floor at 1,138 tokens: 550 of system prompt and 588 of tool schemas for four tools. Every MCP server you connect adds its tool schemas to that floor, on every request, for the whole session. Connect three servers exposing six tools each and you have plausibly doubled your fixed overhead, and it will not appear in any number anyone advertises, because “system prompt size” and “tool schema size” are different fields in the API and only one of them is famous.

This is the same measurement boundary error I keep running into. The API’s field boundary is not the cost boundary.

Attack surface. Codex is explicit about this in a way that is easy to miss. Its GranularApprovalConfig has five independent booleans, and one of them is mcp_elicitations. An MCP server can prompt your user. That is a capability, and Codex treats it as something you may want to switch off separately from everything else.

Think about what that implies. A connected MCP server can put text in front of a human who is in the habit of approving things. That is a social engineering surface reachable over a protocol, and it exists in addition to the obvious concern about what the server’s tools can do.

Pi has none of this because Pi has no MCP. It also has no sandbox, so I would not read that as a security win, just a different set of doors.

Where I think this lands

I do not think MCP is a mistake, and I do not think Pi is behind.

Some of MCP’s value exists because agents were bad at authoring their own tools. A registry of pre-built capabilities is worth a great deal when the alternative is that the agent cannot write the integration. That portion of the value is on a timer, and Pi is betting on the timer.

The rest of it is boundary work, and boundary work does not expire. Credentials that should not be in the agent’s process. Services in languages your harness does not speak. Contracts that have to survive a deploy you do not control. Those are the same reasons we had APIs before any of this, and a better model does not dissolve them.

So the honest read is that the two positions are optimised for different distances. Pi is excellent at short distances, inside your own repository, in your own language, where the schema is yours. Codex is built for long distances, where the thing on the other end is not yours and you need a contract with it.

Most teams have both problems, which is why most teams will end up wanting both mechanisms and should stop treating it as a choice of camp.

The check to run this week

Open your agent’s configuration and count the tools the model can actually see. Not the servers, the tools.

Then work out what those schemas cost you in tokens, on every request, and ask which of them earned it. In my experience the answer is that a third of them have never been called and are there because connecting a server was one line in a config file.

The reason to have four tools was never that four is a nice number. It was that every tool in the schema is a choice the model makes on every turn, and most confident mistakes are a plausible wrong tool rather than a failed task. Shrinking that surface is the point, and a protocol that makes adding tools frictionless is a protocol that makes growing that surface frictionless too.

MCP did not create that problem. It just removed the last bit of friction that was accidentally protecting you from it.


Line counts measured 2026-09-01 against github.com/openai/codex and github.com/earendil-works/pi at that day’s HEAD, including test files. The Pi MCP figure is from a case-insensitive grep across packages/*/src, which returned three matches, none of them an MCP implementation.

🎧 More Ways to Consume This Content

I occasionally advise small teams on backend reliability, Go performance, and production AI systems. Learn more: /services

Comments

This space is waiting for your voice.

Comments will be supported shortly. Stay connected for updates!

Preview of future curated comments

This section will display user comments from various platforms like X, Reddit, YouTube, and more. Comments will be curated for quality and relevance.