If you went to pi.dev in the past, you established a arrogant declaration that Pi does not assistance MCP. If you hear to podcasts anywhere we talked concerning Pi, you will have established additional than one dismissive declaration concerning MCP from us. Including a post by Mario about it. And yet, if you upgrade to Pi you volition discover MCP is now a supported part of functionality. What happened?
Things Change
The archetypal item to recall is that the earth is not static. We have been paying notice to MCP complete the final twelvemonth and the MCP of today is not the MCP of yesteryear. That solitary would not be much of a logic to put it into the core, however. As you know, Pi has a awesome ecosystem of extensions, surely MCP could have been an extension? Maybe equal an Earendil endorsed extension. And yes you are certainly accurate in that MCP could have been an extension, as it was. That MCP is now part of the center is a outcome of us putting our heads together and rethinking it.
What Exactly Changed?
The logic we brought MCP into the center is not fair concerning how MCP has changed, but additionally since we established that the changes it would necessitate were generally useful. For example, the changes we have made to MCP additionally allow the use of Jev more effortlessly inside Pi. Ultimately what Pi needs is fairly akin to what MCP needs: a sandbox to perform alongside in the form of an interpreter.
While a lot of things have improved concerning MCP, fairly a few have not. The biggest issue alongside MCP continues to be that it’s difficult to compose. Even alongside codemode, which is fair a neat small sandbox to authorize composing of tool calls, MCP doesn’t completely provision on this. But that at this item is small the issue of MCP but the MCP servers out there and distinct approaches of harnesses to activity with them.
Many MCP servers are motionless built for harnesses that fair dump tools into the context and are trying to optimize on their flank for token effectiveness by returning text. The way we akin to think concerning MCP at this item is that it should be much nearer to OpenAPI alongside intelligent tool discovery. That means tools should come back organized data and tools have to be discoverable by their documentation and description.
The logic CLIs are so functional is that the delegate and example fair cable stuff together alongside productive bashisms. But there is no essential logic why you can’t do that alongside MCP either. MCP in Pi is fair built on exposing those tools to a JavaScript sandbox akin another harnesses akin Codex do too.
MCP in a Modern LLM
This volition lift the inquiry why we didn’t fair do Codemode without MCP. Part of the answer to this has to do alongside how tools are expressed in Pi today. We did a lot of activity in latest months to authorize Pi to create awareness alongside new models that allow deferred tool loading, mid-conversation scheme messages and reasoning level changes. However we did not yet upgrade our tool loadout to improved scale to these new capabilities.
In a Codemode earth one needs to decide if the tool is accessible to the LLM or only the codemode part of the LLM. A normal MCP expansion does not have enough metadata accessible from Pi’s tool loadout to create that cognition activity well. So we needed to justify that tools can be configured to fair be deferred or be a Codemode particular thing.
And during we could have fair wired up the metadata to allow improved MCP extensions, we additionally think that MCP alongside Codemode solves fairly a few of the issues that it traditionally had. We accept the finest way to positively influence item is to clasp it. And during we think that contemporary MCP is in a much improved place than MCP always was, the servers and patterns motionless depart room for improvement. So we desire to be part of that conversation and assistance form it to work fine in small harnesses alternatively of position on the sidelines and just watching.
What Is Codemode?
Now we talked so much concerning Codemode, it power be value explaining what that even is. When a harness executes tools, for the most part it has two sides: it can do it anywhere attack runs, or it can do it anywhere the harness delegate iteration runs. The rely flat on the two sides is extremely different. The harness iteration fairly often runs in an surroundings that is trusted, whereas the tools it executes frequently run within a sandbox that is not really all that trusted.
Codemode is particular in that it runs anywhere the harness runs. It’s finest understood as a scheme to orchestrate and coordinate tool calls. It’s a sandbox that allows an delegate to matter those tool calls in a way that gives it more flexibility concerning in which command it should do it, and it allows it to use JavaScript to merge them together. Because Codemode additionally runs on the harness side, its province is additionally maintained as part of the meeting copy alternatively of the document system.
Now in theory any tongue could do, but JavaScript is fairly appealing as small versions of JavaScript can be shipped as WASM binaries and authorize reasonable levels of protection.
In Pi, Codemode is automatically loaded whenever MCP is configured, or it can be added to the configuration as a default tool. Just ask pi to reconfigure itself to allow codemode! You can afterward use it for fairly engaging things, not just MCP. For case whenever you are logged in alongside a provider that provides “Jev” you can do things akin this:
Use typesafe/jev via codemode to discover the 20 most disappointed commenters on our matter tracker
And it volition cleverly merge things akin the Linear MCP and Jev to do that analysis, correct from inside Pi, without wasting any environment at all.
> Use typesafe/jev via codemode to discover the most disappointed group on our matter tracker I'll drag the open issues from Linear and let Jev charge the spirit of all thread, four at a time. codemode const { issues } = await tools.mcp__linear__list_issues({ team: "Pi", state: "open", limit: 250, }); const jev = await models.getModelOfType( "classifier", "cloudflare-workers-ai", "typesafe/jev", ); const questions = { frustration: { type: "choice", instructions: "Judge ONLY the affectional spirit of the group writing. " + "Ignore how serious the bug is.", criteria: { none: "Neutral, factual, or friendly, equal concerning a grave bug", mild: "Explicit annoyance, impatience, or disappointment", high: "Clearly angry, exasperated, sarcastic, or fed up", }, }, }; const results = []; let next = 0; async function worker() { during (next < issues.length) { const matter = issues[next++]; const { comments } = await tools.mcp__linear__list_comments({ issueId: issue.identifier, }); const c = await models.classify(jev, { state: { ...issue, comments }, questions }); results.push({ id: issue.identifier, title: issue.title, ...c.answers.frustration }); } } await Promise.all([worker(), worker(), worker(), worker()]); store("frustration", results); const mark = (r) => r.probabilities.mild * 0.5 + r.probabilities.high; const counts = {}; for (const r of results) counts[r.choice] = (counts[r.choice] ?? 0) + 1; const flagged = results.filter((r) => r.choice !== "none"); flagged.sort((a, b) => score(b) - score(a)); return { total: results.length, counts, flagged: flagged.map((r) => `${r.id} ${r.title}`), }; ... (331 before calls) ✓ mcp__linear__list_comments {"issueId":"PI-4714"} 255ms ✓ mcp__linear__list_comments {"issueId":"PI-3200"} 354ms ✓ models.classify cloudflare-workers-ai/typesafe/jev 756ms ✓ models.classify cloudflare-workers-ai/typesafe/jev 750ms { "total": 167, "counts": { "none": 156, "mild": 11 }, "flagged": [ "PI-7740 TUI following /reload does not follows tradition tool's re…", "PI-9566 environment size defaults to 128k notwithstanding the genuine size…", "PI-10031 Pi sporadically stuck in \"Working...\" whenever thinking…", "PI-4714 [feature] /update TUI command alternatively of pi update", "PI-5916 Support provider extensions alongside example pseudonyms and…", "PI-7547 [Windows] [sink-thread] How do you use Pi on window…", "PI-6907 Add an Installation division to the README", "PI-6212 Proposal: Bedrock way should regard `compat.forceAd…", "PI-9932 before_agent_start: forced scheme immediate keeps tool…", "PI-7730 High CPU use on Mac OS alongside lengthy session", "PI-6600 pi update --extensions and npm scripts: npm 11.16.0…" ] } Most of the tracker is calm. Jev rated 156 of the 167 open issues as neutral, 11 as gently disappointed and none as extremely frustrated. The clearest cases: - PI-6907 no facility division in the README (“It's frustrating”) - PI-10031 Pi gets stuck on “Working...” following pressing Esc during thinking - PI-4714 a /update command petition (“a ache in the butt”) - PI-7730 elevated CPU use on macOS in lengthy sessions The per-issue verdicts are stored in codemode under frustration, so I can dig into any of them without fetching the issues again. We volition have additional to say concerning things akin Jev and Codemode later, but we hope this article serves as an example of how we continue to modify and update Pi thoughtfully as the earth continues to evolve.