Pi 코딩 에이전트, MCP 지원 시작: Codemode와 Jev로 도구 호출을 코드로 묶는다

Pi 코딩 에이전트가 MCP를 코어에서 지원합니다. Codemode는 도구 호출을 코드로 묶고, Jev는 Linear 이슈의 감정 분류를 맡습니다.

Huuush발행 2026.10.01 · 5분 read에디터: Jay Kim

3줄 요약

  1. Pi가 MCP를 코어에서 지원하기 시작했습니다. 도구 연결의 컨텍스트 비용과 결과 조합의 어려움은 Codemode로 다룹니다.
  2. Codemode는 QuickJS 샌드박스에서 도구 호출을 코드로 묶어 실행하고 최종 결과만 대화로 돌려보냅니다.
  3. Jev가 열린 Linear 이슈 167개를 분류한 예시에서 156개는 중립, 11개는 약한 짜증, 심한 짜증은 0개였습니다.
유리 샌드박스 안에서 여러 도구 블록이 선으로 연결되고 밖에는 요약 카드 하나가 놓인 정물

강력한 코딩 에이전트 하네스 Pi가 그동안 거부하던 MCP를 이제 지원합니다. 대신 Codemode와 Jev를 내세웁니다. MCP의 약점인 컨텍스트 낭비와 조합의 어려움은 Codemode가 코드로 풀고, 대량으로 읽고 판단하는 일은 분류 전용 모델 Jev가 맡습니다.

Pi가 2026년 9월 30일 오전 2시 51분(KST) 공식 X 계정으로 MCP를 코어에 넣었다고 알렸습니다. 같은 날 Pi를 만드는 Earendil이 입장을 바꾼 배경을 담은 글 You Said No MCP!를 냈습니다.

X 게시물을 불러오는 중입니다.

X 게시물을 불러오지 못했습니다. 잠시 후 다시 시도해 주세요.

X에서 원문 보기

출처: X @pidotdev

Pi가 MCP를 거부했던 두 가지 이유

그동안 Pi는 MCP를 지원하지 않았습니다. Pi를 만든 Mario Zechner가 MCP에 회의적이었기 때문입니다. MCP는 피그마·노션·지메일 같은 서비스를 Claude Code나 Codex에 연결하는 오픈소스 규격으로, Anthropic이 제안했습니다. 자세한 뜻은 MCP 용어 페이지에서 볼 수 있습니다.

첫째는 컨텍스트 비용입니다. Mario Zechner의 /context 화면에서는 Chrome DevTools MCP 서버 하나, 도구 26개가 18.0k 토큰을 차지합니다. 전체 컨텍스트의 9%입니다. 일을 시작하기도 전입니다.

Claude Code 컨텍스트 화면에서 MCP 도구가 18.0k 토큰, 9.0%를 차지하는 모습
Claude Code /context 화면. MCP 도구가 18.0k 토큰(9.0%)을 차지합니다. 출처: Mario Zechner 블로그

둘째는 결과 조합입니다. 도구 결과가 모두 에이전트의 컨텍스트를 거쳐야 하면 여러 단계를 이어 붙이기 어렵습니다. 그래서 그는 MCP 대신 Bash와 코드를 택했습니다.

1년 만에 바뀐 입장

그런데 Pi가 입장을 바꿨습니다. MCP도 1년 새 달라졌고, 기존 입장에 매여 있을 이유가 없다는 것입니다. 처음에는 pi-mcp-adapter 확장으로 연결했지만 이제 MCP 지원을 Pi 코어에 넣었습니다.

Earendil은 세상이 정적이지 않다는 맥락에서 Armin Ronacher의 2016년 글 Be careful about what you dislike를 인용합니다. Pi가 MCP를 받아들인 뒤에도 도구를 조합하는 문제는 남습니다. 그 부분을 Codemode가 풉니다.

Codemode: 도구 호출을 코드로 묶는다

Codemode에서는 모델이 코드를 작성해 여러 도구 호출을 묶습니다. 병렬 처리와 반복, 분기는 코드가 맡고 최종 결과만 대화로 돌아옵니다.

Anthropic은 이 방식을 2025년 11월 Programmatic Tool Calling(PTC)이라는 이름으로 API에 먼저 선보였습니다. Claude가 Python 코드를 작성하면 Anthropic의 샌드박스 컨테이너에서 실행됩니다.

Claude가 Python 코드를 만들어 샌드박스 컨테이너에서 도구를 호출하고 결과를 받는 흐름
Programmatic Tool Calling 흐름. 출처: Anthropic

Pi는 하네스 안의 작은 JavaScript 샌드박스인 QuickJS에서 직접 실행합니다. 실행 상태는 세션 기록에 남습니다.

Codemode를 켜는 방법은 다음과 같습니다.

  • MCP를 설정하면 Codemode가 자동으로 켜집니다.
  • Pi에게 Codemode를 켜도록 다시 설정해 달라고 요청할 수 있습니다.
  • ~/.pi/agent/settings.json 또는 .pi/settings.json의 defaultTools에 +codemode를 추가합니다.
  • 한 번만 사용할 때는 pi --tools read,bash,edit,write,codemode로 실행합니다.
  • 파일시스템 MCP 서버는 pi mcp add filesystem -- npx -y @modelcontextprotocol/server-filesystem .로 추가합니다.

Jev를 붙이면: Linear 이슈 167개에서 짜증 난 사람 찾기

Jev는 TypeSafe가 9월에 공개한 분류 모델입니다. 글을 쓰지 않고 분류를 수행합니다. 9월 18일부터 Cloudflare AI Gateway에서 사용할 수 있으며 Workers AI 모델 ID는 typesafe/jev입니다. Cloudflare 문서는 선택 결과와 선택지별 확률을 함께 반환하는 방식을 안내합니다.

Earendil의 예시에서는 Pi에 아래 첫 줄처럼 요청하고, 모델이 Codemode 코드를 짜서 실행합니다.

> Use typesafe/jev via codemode to find the most frustrated people on our issue tracker

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 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",
    },
  },
};

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

최대 250개까지 가져오도록 요청했고, 실제로 받은 열린 이슈 167개를 분류했습니다. 156개는 중립, 11개는 약한 짜증, 심한 짜증은 0개였습니다. 전체 도구 호출은 330번이 넘지만 대화에는 요약만 남습니다.

가장 뚜렷한 사례 네 가지는 다음과 같습니다.

  • PI-6907: README에 설치 절이 없습니다.
  • PI-10031: 생각 중 Esc를 누르면 “Working...”에서 멈춥니다.
  • PI-4714: /update 명령을 요청합니다.
  • PI-7730: 긴 세션에서 macOS CPU 사용량이 높습니다.

Jev를 Cloudflare AI Gateway에 설정하는 과정은 Cloudflare Developers 영상으로 볼 수 있습니다.

X 게시물을 불러오는 중입니다.

X 게시물을 불러오지 못했습니다. 잠시 후 다시 시도해 주세요.

X에서 원문 보기

출처: X @CloudflareDev

이 조합의 강점 세 가지

첫째는 컨텍스트입니다. 330번이 넘는 호출의 중간 결과가 대화에 쌓이지 않습니다. 분석 결과는 store("frustration", results)로 세션에 저장해 다시 가져오지 않고 이어서 살펴볼 수 있습니다.

둘째는 비용과 속도입니다. 모든 이슈를 큰 언어 모델이 읽고 판단하는 대신 분류 전용 모델이 맡습니다.

셋째는 판단을 숫자로 다룬다는 점입니다. Jev는 선택지별 확률을 반환하고, 코드가 그 값을 점수(mild × 0.5 + high)로 바꿔 정렬합니다. 막연한 느낌 대신 순위가 나옵니다.

Jev의 속도·비용·정확도 수치는 TypeSafe가 발표한 값이며, 가중치는 공개되지 않았습니다.

자주 묻는 질문

네. Pi는 MCP를 코어에서 지원합니다. MCP 서버를 설정하면 Codemode도 사용할 수 있습니다.

모델이 도구 호출을 묶는 코드를 작성하고, 코드는 QuickJS 샌드박스에서 실행됩니다. 중간 결과는 대화에 모두 쌓지 않고 최종 결과를 반환합니다.

Jev는 글을 생성하는 대신 선택지에 따라 분류하고 판단 결과를 구조화해 반환하는 모델입니다.

최대 250개를 요청했고 실제로 받은 열린 이슈 167개를 분류했습니다. 156개가 중립, 11개가 약한 짜증, 0개가 심한 짜증으로 집계됐습니다.

함께 보면 좋은 글

출처

작성자 소개

제이킴유니버스

제이킴유니버스

AI 자동화와 홈페이지 제작으로 업무 시간을 줄이고 매출을 만듭니다.