Skip to content

Pi.dev You Said No MCP: Hands-On Codemode Guide

Pi.dev crossed out No MCP in v0.99.0. Here's how MCP+Codemode actually works, how to set it up, and when you should skip it.

6 min readBeginner

Two ways to bolt MCP onto a coding agent

Approach B shipped in Pi 0.99.0. MCP stays the wire protocol; tools default to codemode exposure. The model writes JavaScript inside a QuickJS sandbox, fires tools in parallel, filters the junk, and only the distilled result re-enters context. Release line: v0.99.0 (29 Sep 2026).

Approach A is still what most stacks do: dump every tool schema into the model at session start. Mario Zechner’s Nov 2025 measurements – Playwright MCP ~13.7k tokens across 21 tools, Chrome DevTools MCP ~18k across 26 – land before you ask anything useful (Mario’s write-up).

Dimension Approach A (dump schemas) Approach B (Pi MCP+Codemode)
Tool schemas in context All of them, every turn Off model by default; listed for scripts
Multi-tool work One round-trip per call Parallel JS in sandbox
Huge tool payloads Land in the transcript Filter before the model sees them
Who chooses this Most agents historically Pi core as of 0.99.0

B is the day-to-day default for coding agents. A still fits tiny always-on tool packs – and Pi still offers direct exposure when you want that.

Think of codemode like a sous-chef: the model doesn’t taste every raw pan on the line. It writes a short ticket, the kitchen runs the heat, and only the plated note comes back. That’s the whole bet.

They didn’t stage a full apology tour either. Bloated servers still get called out. The shift was practical – shape the protocol from inside the agent instead of yelling from the sidelines (Earendil: You Said No MCP!).

Hands-on setup (Pi.dev after “You Said No MCP”)

Pi 0.99.0 is the cutover. Homepage copy flipped from “No MCP” to “Now with MCP+Codemode” on pi.dev. Older build? Upgrade first.

  1. Install or update (macOS/Linux installer, or npm on Node.js 22.19+ per the quickstart):
curl -fsSL https://pi.dev/install.sh | sh
# or
npm install -g --ignore-scripts @earendil-works/pi-coding-agent
pi --version
  1. Add a server. User-global writes ~/.pi/agent/mcp.json. Project-local needs -land a trusted project:
pi mcp add filesystem -- npx -y @modelcontextprotocol/server-filesystem .
pi mcp list
pi

Remote HTTP, straight from the official MCP docs:

pi mcp add docs --url https://example.com/mcp --bearer-token-env-var DOCS_TOKEN
  1. In-session: /mcp shows state, tool counts, exposure, OAuth, reconnect, enable/disable. Edit config outside the session? /reload or start fresh.
  2. Default exposure is already codemode (as of the 0.99 docs). Pi auto-enables the codemode tool when a codemode-style server connects. Want codemode with zero MCP servers? "defaultTools": ["+codemode"] in ~/.pi/agent/settings.json.
  3. OAuth-style servers: URL only in config, then pi mcp login <server> or Sign in from /mcp – no tokens pasted into JSON.

Config shape matches other clients, so Cursor/Claude mcpServers blocks often paste cleanly. Secrets stay ${ENV} or !command – never hardcoded tokens.

Pick the right exposure

This is the real control knob. Tools register as mcp__<server>__<tool>. Exposure decides whether the model ever sees them as first-class tools.

Exposure Model sees tools? Best for
codemode (default) No – scripts only (listed in codemode desc) Most MCP servers
codemode-deferred No – not even inline list; search by name Huge, rarely used servers
deferred After tool_search loads matches Large sets without codemode
direct Yes, like built-ins Tiny, always-needed tool packs
hidden Registered but unreachable Kill switches / partial enable via toolExposure

Per-tool overrides use toolExposure – exact names or * patterns. Docs pattern: search_code on direct, hide delete_*, leave the rest deferred. Codemode declarations share an inlineBudget (default ~3000 estimated tokens per Pi settings docs); overflow stays reachable with searchTools() inside scripts.

Common pitfalls

  • Old adapter still installed.pi-mcp-adapter (or anything that owns /mcp) replaces built-in MCP. Sessions stop reading mcp.json until you remove the extension – called out in the official MCP docs.
  • Project config ignored..pi/mcp.json loads only after project trust, because stdio servers execute commands. Personal creds belong in ~/.pi/agent/mcp.json.
  • SSE URLs. Legacy SSE is rejected. Prefer streamable HTTP; many servers that advertise /sse also speak HTTP at /mcp.
  • Shell-string commands.command is one executable; arguments go in args. Don’t paste a full shell line.
  • Forgot /reload. Outside edits need reload or a new session.
  • Slow startups. First prompt waits up to ~10s for connections; slower servers appear when ready. Default per-request timeout is 60s (progress pings reset it).

Server names: letters, digits, _, - only. Invalid entries get skipped; the rest still connect. pi mcp list exits 1 while anything’s wrong; tails live in ~/.pi/agent/mcp.log.

What codemode actually does

Not a toy REPL. Scripts call tools.<name>(args), can Promise.allSettled them, and return only what you text() / return. State rides the session transcript.

Why JS? Small engines ship as WASM with isolation that doesn’t feel like a science project – Earendil’s post is blunt about that tradeoff.

Model path: text over 20KB gets a middle-truncation marker plus a temp-file path for the full blob. Codemode scripts always receive the whole CallToolResult. Filter in the sandbox, or direct exposure will still lose the middle on huge payloads.

Honest gap: no official post-0.99.0 head-to-head publishes exact token savings for default codemode vs direct on Playwright/Chrome in live sessions. Mario’s 13.7k/18k numbers state the problem. They’re not a savings receipt for 0.99.0.

When you should not use this

Skip built-in MCP+Codemode when a thin CLI or Pi skill already covers the job. Mario’s original case still stands for browser automation you can express as a few bash scripts and a short README.

Pro tip: Start with zero MCP servers. Add one only when OAuth, shared schemas across agents, or a hosted service beats a local script. Already living in bash pipes? Stay there.

Also skip – or disable builtin:mcp in pi config – if you intentionally want old adapter behavior. Embedding via the SDK is opt-in; SDK sessions don’t auto-load built-in extensions the way the CLI does.

So is MCP the destination, or just a compatibility adapter you reach for when scripts stop scaling? Worth answering before you fill mcp.json.

FAQ

Did Pi fully reverse its “No MCP” stance?

No. MCP on their terms: default codemode, exposure controls, same criticism of bloated servers. Primary source: the Earendil post.

I added a server but the model never calls it – what now?

Check exposure first. On default codemode, the model shouldn’t invoke mcp__... tools directly – it should write a codemode script. If auto-enable is off and neither codemode nor tool_search is active, Pi warns once because nothing can reach undeclared tools.

Run /mcp, confirm connected, then prompt explicitly for a codemode script against that server. Two-tool pack you always want hot? Flip that server to direct.

Is this the same as the Pi Network crypto project?

No. Different product. This is the open-source terminal coding agent at pi.dev (Earendil), not minepi.com.

Next action: upgrade to 0.99.x, run pi mcp add filesystem -- npx -y @modelcontextprotocol/server-filesystem ., open /mcp, and ask Pi to list tools through codemode on a real file task. About five minutes. Real signal.