In dit artikel legt Earendil Engineering uit waarom Pi nu toch het Model Context Protocol (MCP) in de core heeft geïntegreerd, ondanks eerdere terughoudendheid. De belangrijkste redenen zijn de evolutie van MCP zelf en het feit dat de benodigde infrastructurele aanpassingen ook andere functionaliteiten verbeteren.
Een centraal onderdeel van deze update is Codemode. Dit is een JavaScript-sandbox die draait aan de zijde van de harness, waardoor de AI-agent tool-aanroepen kan orkestreren, combineren en coördineren zonder direct context te verspillen. In tegenstelling tot standaard MCP-extensies, biedt Codemode meer flexibiliteit in de volgorde van uitvoering en statusbewaring.
Het artikel illustreert de kracht van Codemode met een praktijkvoorbeeld: het combineren van de Linear MCP (voor issue-tracking) met een classifier genaamd 'Jev' om automatisch de meest gefrustreerde gebruikers op een issue tracker te identificeren en te analyseren.
“Je zei geen MCP!”
Als je in het verleden naar pi.dev bent gegaan, ben je waarschijnlijk gestuit op een trotse verklaring dat Pi geen MCP ondersteunt. Als je naar onze podcasts hebt geluisterd, heb je meer dan één afwijzende uitspraak over MCP van ons gehoord, inclusief een bericht van Mario hierover. En toch, als je Pi nu upgradet, zul je merken dat MCP inmiddels een ondersteunde functionaliteit is. Wat is er gebeurd?
Dingen veranderen
Het eerste dat men moet onthouden is dat de wereld niet statisch is.
We hebben het afgelopen jaar MCP nauwgezet gevolgd en de MCP van vandaag is niet de MCP van weleer. Dat alleen zou echter geen voldoende reden zijn om het in de core te integreren. Zoals je weet, heeft Pi een geweldig ecosysteem van extensies; MCP had immers ook een extensie kunnen zijn, wellicht zelfs een door Earendil ondersteunde extensie. En inderdaad, MCP had een extensie kunnen blijven, zoals het aanvankelijk ook was. Dat MCP nu onderdeel is van de core, is het resultaat van gezamenlijk overleg en een heroverweging van onze aanpak.
Wat is er precies veranderd?
De reden waarom we MCP naar de core hebben gebracht, heeft niet alleen te maken met hoe MCP is veranderd, maar ook met het feit dat we ontdekten dat de vereiste wijzigingen over het algemeen nuttig waren. Zo maken de aanpassingen die we voor MCP hebben doorgevoerd het ook eenvoudiger om Jev binnen Pi te gebruiken. Uiteindelijk heeft Pi iets nodig dat sterk lijkt op wat MCP nodig heeft: een sandbox om in te werken in de vorm van een interpreter.
Hoewel veel zaken bij MCP zijn verbeterd, is dat niet voor alles het geval. Het grootste probleem met MCP blijft dat het moeilijk te componeren is. Zelfs met codemode — een handige kleine sandbox om het componeren van tool-aanroepen mogelijk te maken — levert MCP hier niet volledig in. Maar op dit punt is dat minder een probleem van MCP zelf, en meer een probleem van de beschikbare MCP-servers en de verschillende benaderingen van de harnesses die ermee werken.
Veel MCP-servers zijn nog steeds gebouwd voor harnesses die tools simpelweg in de context dumpen en aan hun kant proberen de token-efficiëntie te optimaliseren door tekst terug te geven. De manier waarop wij nu over MCP denken, is dat het veel dichter bij OpenAPI zou moeten liggen, met intelligente tool-ontdekking. Dat betekent dat tools gestructureerde data moeten retourneren en dat tools vindbaar moeten zijn via hun documentatie en beschrijving.
De reden waarom CLI's zo functioneel zijn, is dat de agent en het model zaken simpelweg met efficiënte bashisms aan elkaar knopen. Er is echter geen fundamentele reden waarom dat niet ook met MCP kan. MCP in Pi is simpelweg gebouwd op het ontsluiten van die tools naar een JavaScript-sandbox, vergelijkbaar met hoe andere harnesses zoals Codex dat doen.
MCP in een modern LLM
Dit roept de vraag op waarom we niet gewoon voor Codemode hebben gekozen zonder MCP. Een deel van het antwoord heeft te maken met hoe tools vandaag de dag in Pi worden uitgedrukt. We hebben de afgelopen maanden veel werk verricht om Pi compatibel te maken met nieuwe modellen die uitgestelde tool-laadfuncties (deferred tool loading), systeemmeldingen midden in een gesprek en wijzigingen in het redeneringsniveau (reasoning level changes) toestaan. We hadden onze tool-loadout echter nog niet geüpgraded om beter te schalen naar deze nieuwe mogelijkheden.
In een Codemode-wereld moet men beslissen of een tool beschikbaar is voor het LLM, of alleen voor het codemode-gedeelte van het LLM. Een normale MCP-extensie beschikt niet over voldoende metadata vanuit de tool-loadout van Pi om die ervaring goed te laten werken. We moesten er dus voor zorgen dat tools geconfigureerd kunnen worden om óf uitgesteld te worden, óf een specifiek Codemode-onderdeel te zijn.
Hoewel we de metadata simpelweg hadden kunnen koppelen om betere MCP-extensies mogelijk te maken, geloven we ook dat MCP in combinatie met Codemode een aantal van de traditionele problemen oplost. We geloven dat de beste manier om iets positief te beïnvloeden, is door het te omarmen. Hoewel we denken dat de moderne MCP in een veel betere positie verkeert dan ooit, laten de servers en patronen nog ruimte voor verbetering. Daarom willen we deel uitmaken van dat gesprek en helpen het vorm te geven zodat het goed werkt in kleine harnesses, in plaats van vanaf de zijlijn toe te kijken.
Wat is Codemode?
Omdat we zoveel over Codemode hebben gesproken, is het waardevol om uit te leggen wat dit precies is. Wanneer een harness tools uitvoert, heeft het grotendeels twee zijden: het kan gebeuren waar bash draait, of waar de harness agent-loop draait. Het vertrouwensniveau aan beide zijden is zeer verschillend. De harness-loop draait vaak in een omgeving die wordt vertrouwd, terwijl de tools die het uitvoert vaak draaien binnen een sandbox die niet echt volledig vertrouwd is.
Codemode is bijzonder omdat het draait waar de harness draait. Het kan het best worden begrepen als een mechanisme om tool-aanroepen te orkestreren en te coördineren. Het is een sandbox die een agent in staat stelt tool-aanroepen te doen op een manier die meer flexibiliteit biedt in de volgorde waarin dit gebeurt, en het stelt de agent in staat om JavaScript te gebruiken om ze te combineren. Omdat Codemode ook aan de harness-zijde draait, wordt de status ervan bewaard als onderdeel van het sessie-transcript in plaats van op het bestandssysteem.
In theorie zou elke taal kunnen werken, maar JavaScript is zeer aantrekkelijk omdat kleine versies van JavaScript als WASM-binaries kunnen worden verzonden en een redelijk niveau van bescherming bieden.
In Pi wordt Codemode automatisch geladen wanneer MCP is geconfigureerd, of het kan als standaardtool aan de configuratie worden toegevoegd. Je kunt Pi simpelweg vragen zichzelf te reconfigureren om codemode in te schakelen. Je kunt het vervolgens gebruiken voor interessante zaken die verder gaan dan alleen MCP. Wanneer je bijvoorbeeld bent ingelogd bij een provider die "Jev" aanbiedt, kun je dit doen:
"Gebruik typesafe/jev via codemode om de 20 meest gefrustreerde commentatoren op onze issue tracker te vinden."
Pi zal dan slim zaken als de Linear MCP en Jev combineren om die analyse uit te voeren, direct vanuit Pi, zonder context te verspillen.
Voorbeeld van een interactie:
Gebruiker: Gebruik typesafe/jev via codemode om de meest gefrustreerde mensen op onze issue tracker te vinden.
Pi: Ik haal de openstaande issues op uit Linear en laat Jev de toon van elke thread beoordelen, vier per keer.
Codemode uitvoering:
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: "Beoordeel UITSLUITEND de emotionele toon van de schrijvers. " +
"Negeer hoe ernstig de bug is.",
criteria: {
none: "Neutraal, feitelijk, of vriendelijk, zelfs bij een ernstige bug",
mild: "Expliciete ergernis, ongeduld, of teleurstelling",
high: "Duidelijk boos, geëxaspereerd, sarcastisch, of klaar ermee",
},
},
};
const results = [];
let next = 0;
async function worker() {
while (next < issues.length) {
const issue = 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 score = (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}`),
};
Logoutput:
... (331 eerdere aanroepen)
✓ 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 after /reload does not follows custom tool's re…",
"PI-9566 context size defaults to 128k despite the real size…",
"PI-10031 Pi sporadically stuck in \"Working...\" when thinking…",
"PI-4714 [feature] /update TUI command instead of pi update",
"PI-5916 Support provider extensions with model aliases and…",
"PI-7547 [Windows] [sink-thread] How do you use Pi on window…",
"PI-6907 Add an Installation section to the README",
"PI-6212 Proposal: Bedrock path should honor `compat.forceAd…",
"PI-9932 before_agent_start: forced system prompt keeps tool…",
"PI-7730 High CPU usage on Mac OS with long session",
"PI-6600 pi update --extensions and npm scripts: npm 11.16.0…"
]
}
Analyse: Het grootste deel van de tracker is kalm. Jev beoordeelde 156 van de 167 openstaande issues als neutraal, 11 als mild gefrustreerd en geen enkele als zeer gefrustreerd.
De duidelijkste gevallen:
- PI-6907: geen installatiesectie in de README (“Het is frustrerend”)
- PI-10031: Pi blijft hangen op “Working...” na het indrukken van Esc tijdens het nadenken
- PI-4714: een verzoek voor een /update-commando (“een pain in the butt”)
- PI-7730: hoog CPU-gebruik op macOS in lange sessies
De oordelen per issue zijn opgeslagen in codemode onder 'frustration', zodat ik in elk van deze zaken kan duiken zonder de issues opnieuw op te halen.
We zullen later meer vertellen over zaken als Jev en Codemode, maar we hopen dat dit bericht dient als voorbeeld van hoe we Pi zorgvuldig blijven aanpassen en updaten terwijl de wereld blijft evolueren.
EARENDIL INC.
“Je zei geen MCP!”
Als je in het verleden naar pi.dev bent gegaan, ben je waarschijnlijk gestuit op een trotse verklaring dat Pi geen MCP ondersteunt. Als je naar onze podcasts hebt geluisterd, heb je meer dan één afwijzende uitspraak over MCP van ons gehoord, inclusief een bericht van Mario hierover. En toch, als je Pi nu upgradet, zul je merken dat MCP inmiddels een ondersteunde functionaliteit is. Wat is er gebeurd?
Dingen veranderen
Het eerste dat men moet onthouden is dat de wereld niet statisch is.
We hebben het afgelopen jaar MCP nauwgezet gevolgd en de MCP van vandaag is niet de MCP van weleer. Dat alleen zou echter geen voldoende reden zijn om het in de core te integreren. Zoals je weet, heeft Pi een geweldig ecosysteem van extensies; MCP had immers ook een extensie kunnen zijn, wellicht zelfs een door Earendil ondersteunde extensie. En inderdaad, MCP had een extensie kunnen blijven, zoals het aanvankelijk ook was. Dat MCP nu onderdeel is van de core, is het resultaat van gezamenlijk overleg en een heroverweging van onze aanpak.
Wat is er precies veranderd?
De reden waarom we MCP naar de core hebben gebracht, heeft niet alleen te maken met hoe MCP is veranderd, maar ook met het feit dat we ontdekten dat de vereiste wijzigingen over het algemeen nuttig waren. Zo maken de aanpassingen die we voor MCP hebben doorgevoerd het ook eenvoudiger om Jev binnen Pi te gebruiken. Uiteindelijk heeft Pi iets nodig dat sterk lijkt op wat MCP nodig heeft: een sandbox om in te werken in de vorm van een interpreter.
Hoewel veel zaken bij MCP zijn verbeterd, is dat niet voor alles het geval. Het grootste probleem met MCP blijft dat het moeilijk te componeren is. Zelfs met codemode — een handige kleine sandbox om het componeren van tool-aanroepen mogelijk te maken — levert MCP hier niet volledig in. Maar op dit punt is dat minder een probleem van MCP zelf, en meer een probleem van de beschikbare MCP-servers en de verschillende benaderingen van de harnesses die ermee werken.
Veel MCP-servers zijn nog steeds gebouwd voor harnesses die tools simpelweg in de context dumpen en aan hun kant proberen de token-efficiëntie te optimaliseren door tekst terug te geven. De manier waarop wij nu over MCP denken, is dat het veel dichter bij OpenAPI zou moeten liggen, met intelligente tool-ontdekking. Dat betekent dat tools gestructureerde data moeten retourneren en dat tools vindbaar moeten zijn via hun documentatie en beschrijving.
De reden waarom CLI's zo functioneel zijn, is dat de agent en het model zaken simpelweg met efficiënte bashisms aan elkaar knopen. Er is echter geen fundamentele reden waarom dat niet ook met MCP kan. MCP in Pi is simpelweg gebouwd op het ontsluiten van die tools naar een JavaScript-sandbox, vergelijkbaar met hoe andere harnesses zoals Codex dat doen.
MCP in een modern LLM
Dit roept de vraag op waarom we niet gewoon voor Codemode hebben gekozen zonder MCP. Een deel van het antwoord heeft te maken met hoe tools vandaag de dag in Pi worden uitgedrukt. We hebben de afgelopen maanden veel werk verricht om Pi compatibel te maken met nieuwe modellen die uitgestelde tool-laadfuncties (deferred tool loading), systeemmeldingen midden in een gesprek en wijzigingen in het redeneringsniveau (reasoning level changes) toestaan. We hadden onze tool-loadout echter nog niet geüpgraded om beter te schalen naar deze nieuwe mogelijkheden.
In een Codemode-wereld moet men beslissen of een tool beschikbaar is voor het LLM, of alleen voor het codemode-gedeelte van het LLM. Een normale MCP-extensie beschikt niet over voldoende metadata vanuit de tool-loadout van Pi om die ervaring goed te laten werken. We moesten er dus voor zorgen dat tools geconfigureerd kunnen worden om óf uitgesteld te worden, óf een specifiek Codemode-onderdeel te zijn.
Hoewel we de metadata simpelweg hadden kunnen koppelen om betere MCP-extensies mogelijk te maken, geloven we ook dat MCP in combinatie met Codemode een aantal van de traditionele problemen oplost. We geloven dat de beste manier om iets positief te beïnvloeden, is door het te omarmen. Hoewel we denken dat de moderne MCP in een veel betere positie verkeert dan ooit, laten de servers en patronen nog ruimte voor verbetering. Daarom willen we deel uitmaken van dat gesprek en helpen het vorm te geven zodat het goed werkt in kleine harnesses, in plaats van vanaf de zijlijn toe te kijken.
Wat is Codemode?
Omdat we zoveel over Codemode hebben gesproken, is het waardevol om uit te leggen wat dit precies is. Wanneer een harness tools uitvoert, heeft het grotendeels twee zijden: het kan gebeuren waar bash draait, of waar de harness agent-loop draait. Het vertrouwensniveau aan beide zijden is zeer verschillend. De harness-loop draait vaak in een omgeving die wordt vertrouwd, terwijl de tools die het uitvoert vaak draaien binnen een sandbox die niet echt volledig vertrouwd is.
Codemode is bijzonder omdat het draait waar de harness draait. Het kan het best worden begrepen als een mechanisme om tool-aanroepen te orkestreren en te coördineren. Het is een sandbox die een agent in staat stelt tool-aanroepen te doen op een manier die meer flexibiliteit biedt in de volgorde waarin dit gebeurt, en het stelt de agent in staat om JavaScript te gebruiken om ze te combineren. Omdat Codemode ook aan de harness-zijde draait, wordt de status ervan bewaard als onderdeel van het sessie-transcript in plaats van op het bestandssysteem.
In theorie zou elke taal kunnen werken, maar JavaScript is zeer aantrekkelijk omdat kleine versies van JavaScript als WASM-binaries kunnen worden verzonden en een redelijk niveau van bescherming bieden.
In Pi wordt Codemode automatisch geladen wanneer MCP is geconfigureerd, of het kan als standaardtool aan de configuratie worden toegevoegd. Je kunt Pi simpelweg vragen zichzelf te reconfigureren om codemode in te schakelen. Je kunt het vervolgens gebruiken voor interessante zaken die verder gaan dan alleen MCP. Wanneer je bijvoorbeeld bent ingelogd bij een provider die "Jev" aanbiedt, kun je dit doen:
"Gebruik typesafe/jev via codemode om de 20 meest gefrustreerde commentatoren op onze issue tracker te vinden."
Pi zal dan slim zaken als de Linear MCP en Jev combineren om die analyse uit te voeren, direct vanuit Pi, zonder context te verspillen.
Voorbeeld van een interactie:
Gebruiker: Gebruik typesafe/jev via codemode om de meest gefrustreerde mensen op onze issue tracker te vinden.
Pi: Ik haal de openstaande issues op uit Linear en laat Jev de toon van elke thread beoordelen, vier per keer.
Codemode uitvoering:
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: "Beoordeel UITSLUITEND de emotionele toon van de schrijvers. " +
"Negeer hoe ernstig de bug is.",
criteria: {
none: "Neutraal, feitelijk, of vriendelijk, zelfs bij een ernstige bug",
mild: "Expliciete ergernis, ongeduld, of teleurstelling",
high: "Duidelijk boos, geëxaspereerd, sarcastisch, of klaar ermee",
},
},
};
const results = [];
let next = 0;
async function worker() {
while (next < issues.length) {
const issue = 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 score = (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}`),
};
Logoutput:
... (331 eerdere aanroepen)
✓ 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 after /reload does not follows custom tool's re…",
"PI-9566 context size defaults to 128k despite the real size…",
"PI-10031 Pi sporadically stuck in \"Working...\" when thinking…",
"PI-4714 [feature] /update TUI command instead of pi update",
"PI-5916 Support provider extensions with model aliases and…",
"PI-7547 [Windows] [sink-thread] How do you use Pi on window…",
"PI-6907 Add an Installation section to the README",
"PI-6212 Proposal: Bedrock path should honor `compat.forceAd…",
"PI-9932 before_agent_start: forced system prompt keeps tool…",
"PI-7730 High CPU usage on Mac OS with long session",
"PI-6600 pi update --extensions and npm scripts: npm 11.16.0…"
]
}
Analyse: Het grootste deel van de tracker is kalm. Jev beoordeelde 156 van de 167 openstaande issues als neutraal, 11 als mild gefrustreerd en geen enkele als zeer gefrustreerd.
De duidelijkste gevallen:
- PI-6907: geen installatiesectie in de README (“Het is frustrerend”)
- PI-10031: Pi blijft hangen op “Working...” na het indrukken van Esc tijdens het nadenken
- PI-4714: een verzoek voor een /update-commando (“een pain in the butt”)
- PI-7730: hoog CPU-gebruik op macOS in lange sessies
De oordelen per issue zijn opgeslagen in codemode onder 'frustration', zodat ik in elk van deze zaken kan duiken zonder de issues opnieuw op te halen.
We zullen later meer vertellen over zaken als Jev en Codemode, maar we hopen dat dit bericht dient als voorbeeld van hoe we Pi zorgvuldig blijven aanpassen en updaten terwijl de wereld blijft evolueren.
EARENDIL INC.