«Вы сказали: нет MCP!» — почему Earendil передумала и встроила MCP в ядро Pi

· 2 мин чтения
mcp opinion tools design harness
«Вы сказали: нет MCP!» — почему Earendil передумала и встроила MCP в ядро Pi

Ещё недавно на pi.dev висела гордая декларация: Pi не поддерживает MCP. В подкастах, где выступала команда Earendil, звучали откровенно пренебрежительные высказывания о протоколе. В частности, пост Марцио Цехнера был посвящён ровно этому вопросу. И тем не менее после обновления Pi поддержка MCP оказалась встроенной в ядро. Что произошло?

Мир не статичен

Первое, что стоит помнить: мир не статичен. Earendil следила за MCP последний год, и MCP сегодня — это не тот MCP, что был раньше. Само по себе это ещё не повод тащить протокол в ядро. У Pi большая экосистема расширений, и логично было бы сделать MCP расширением. Можно было бы даже выпустить расширение, рекомендованное Earendil.

И да, это замечание верное: MCP действительно мог быть расширением. Такое расширение существовало — pi-mcp-adapter. То, что MCP оказался в ядре, — результат того, что команда собралась вместе и переосмыслила подход.

Что именно изменилось

Причина переноса MCP в ядро не только в том, что сам протокол изменился. Оказалось, что изменения, которых потребует MCP, полезны сами по себе. Например, правки в MCP сильнее упростили использование Jev внутри Pi. В итоге то, что нужно Pi, очень похоже на то, что нужно MCP: песочница на базе интерпретатора, где можно экспериментировать.

При этом многое в MCP улучшилось, но кое-что так и не улучшилось. Главная проблема MCP осталась прежней: его трудно комбинировать. Даже Codemode — компактная песочница, которая позволяет составлять вызовы инструментов, — не решает эту задачу полностью. Но сейчас это уже скорее проблема самих MCP-серверов и разных подходов к работе с ними в harness.

Многие MCP-серверы до сих пор сделаны для harness-ов, которые просто выкладывают инструменты в контекст и оптимизируют расход токенов у себя на стороне, возвращая текст. Как Earendil теперь смотрит на MCP: это должно быть гораздо ближе к OpenAPI с умным поиском инструментов. Инструменты должны возвращать структурированные данные. Инструменты должны находиться по своей документации и описанию.

CLI работают так хорошо потому, что агент и модель просто связывают всё эффективными приёмами в bash. Фундаментальной причины, по которой так нельзя делать с MCP, нет. В Pi инструменты MCP доступны JavaScript-песочнице — примерно так же, как это сделано в других harness-ах, например в Codex.

Почему нельзя было просто сделать Codemode без MCP

Вопрос закономерный: если всё решает Codemode, зачем тогда вообще MCP? Отчасти ответ связан с тем, как сейчас устроены инструменты в Pi. В последние месяцы команда проделала много работы, чтобы Pi понимал новые модели: отложенную загрузку инструментов, системные сообщения в середине диалога и изменения уровня рассуждения. Но набор инструментов Pi ещё не перестроен под эти новые возможности.

В мире Codemode нужно решить, доступен инструмент самой LLM или только той её части, которая работает в режиме Codemode. Обычному MCP-расширению не хватает метаданных из набора инструментов Pi, чтобы этот опыт работал хорошо. Значит, инструменты должны настраиваться так, чтобы их можно было либо отложить, либо объявить специфичными для Codemode.

Можно было просто связать нужные метаданные и дать хорошим MCP-расширениям больше возможностей. Но команда считает, что MCP вместе с Codemode закрывает многие проблемы, которые раньше были с ним связаны. Лучший способ повлиять на что-то — принять это и поработать с ним. Современный MCP, по мнению Earendil, находится в гораздо лучшем состоянии, чем раньше. Но серверы и паттерны всё ещё оставляют место для улучшений. Поэтому команда хочет быть частью этого разговора и помочь привести MCP к рабочему виду в маленьких harness-ах, а не наблюдать со стороны.

Что такое Codemode

Про Codemode в посте сказано много, поэтому стоит объяснить, что это такое. Инструменты можно выполнять в двух разных местах: там, где работает bash, и там, где работает цикл агента harness-а. Уровень доверия к этим местам сильно разный. Цикл harness-а часто работает в доверенном окружении. А вот инструменты, которые он запускает, обычно работают внутри песочницы, которой нельзя особо доверять.

Особенность Codemode в том, что он работает там же, где работает harness. Проще всего представить его как механизм для организации вызовов инструментов. Это песочница, которая позволяет агенту вызывать инструменты гибче, решая сам, в каком порядке их вызывать. Она же позволяет агенту комбинировать вызовы с помощью JavaScript. И поскольку Codemode работает на стороне harness-а, его состояние хранится в транскрипте сессии, а не в файловой системе.

Теоретически подойдёт любой язык. Но JavaScript привлекателен: уменьшенные версии JavaScript можно поставлять как WASM-бинарники, и это даёт разумный уровень защиты.

В Pi Codemode подключается автоматически, как только настроен MCP. Его также можно добавить в конфигурацию как инструмент по умолчанию. Достаточно попросить Pi перенастроить себя так, чтобы Codemode был включён. Дальше его можно использовать для самых разных задач, а не только для MCP. Например, если вы вошли в провайдер, который даёт Jev:

Используй typesafe/jev через codemode, найди 20 самых раздражённых комментаторов в нашем трекере задач

И Pi сам сообразит, как скомбинировать Linear MCP и Jev для такого анализа — прямо внутри Pi и вообще без расхода контекста.

Как выглядит такой сеанс

Внутри Codemode агент пишет обычный JavaScript. Он забирает открытые задачи из Linear, подгружает модель-классификатор, вручную перечисляет допустимые ответы, а затем распараллеливает обработку.

// Fetch open issues from Linear
const { issues } = await tools.mcp__linear__list_issues({
  team: "Pi", state: "open", limit: 250,
});

// Load the frustration classifier
const jev = await models.getModelOfType(
  "classifier", "cloudflare-workers-ai", "typesafe/jev",
);

const questions = {
  frustration: {
    type: "choice",
    instructions: "Judge ONLY the emotional tone of the people writing. " +
      "Ignore how severe the bug is.",
    criteria: {
      none: "Neutral, factual, or friendly, even about a serious bug",
      mild: "Explicit annoyance, impatience, or disappointment",
      high: "Clearly angry, exasperated, sarcastic, or fed up",
    },
  },
};

// Process four issues in parallel
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);

// Aggregate verdicts
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}`),
};

Результат по трекеру: 167 открытых задач, 156 из них Jev оценил как нейтральные, 11 — как слегка раздражённые, и ни одной как сильно раздражённой. Самые явные случаи:

  • PI-6907 — в README нет раздела про установку («это раздражает»)
  • PI-10031 — Pi зависает на «Working...» после нажатия Esc во время размышления
  • PI-4714 — просьба добавить команду /update («боль в заднице»)
  • PI-7730 — высокая нагрузка на CPU на macOS в длинных сессиях

Вердикт по каждой задаче сохранён в Codemode под ключом frustration. Поэтому к любой из них можно вернуться позже, не запрашивая задачи заново.

Команда обещает вернуться к Jev и Codemode в следующих постах. А этот пост — пример того, как Earendil продолжает внимательно переделывать Pi по мере того, как меняется мир.

Источник: https://earendil.com/posts/you-said-no-mcp/