
1. Pi 1.0 原生 MCP 到底解决了什么问题Pi 1.0 发布后最值得关注的变化是 MCP 从扩展层搬进了核心。这件事的意义不在于多了一个功能开关而在于工具加载方式、调用方式和上下文占用方式被重新设计了。如果你之前用过 Pi 的 MCP 扩展应该记得那种别扭工具声明一股脑塞给模型工具一多光看声明就吃掉大量上下文真正干活的空间被压缩。原生支持之后Pi 引入了 direct、deferred、codemode、hidden 四种提供方式模型不必在开局就读完所有工具说明书。MCP 是什么一句话它是一套让模型调用外部工具的标准协议服务端暴露工具客户端负责发现和调用。Pi 1.0 把客户端能力做进核心意味着你不需要再装扩展、不用再担心扩展拿不到完整工具元数据。适合谁适合手上已经有若干 MCP 服务端文件系统、项目管理、数据库查询等又希望 Agent 在大量返回数据里先做筛选再交给模型的人。Codemode 是这次配套的重点。它允许模型写 JavaScript 来编排工具调用脚本跑在 QuickJS 沙箱里工具返回的原始数据可以先留在脚本中做 filter、map、合并、统计只把整理后的结果text()出去。举个直观对比查两个项目共 12 条 issue要高优先级且无负责人的编号和标题。传统做法是把 12 条完整记录含描述、标签、评论、时间全塞进上下文让模型逐条判断Codemode 做法是脚本里判断priority high assignee null模型最后只读到 3 条。规则明确的筛选交给代码需要语义理解的判断留给模型这是整篇文章的主线。我试过在 Mac 上接 filesystem MCP 跑这套流程中间踩了两个坑变量重名、把 MCP 返回的 content 当字符串直接 JSON.parse。下面把完整路径、可复制配置和排错过程都写出来你可以照着走一遍自己判断 MCP 在 Pi 生态里到底可不可用。2. 接入前的准备TaoToken 统一 Key 与 Pi 环境先说通道。Pi 里调用模型需要 Base URL、API Key、Model ID 三件套我这次统一走 TaoToken 的 API 通道好处是一个 Key 覆盖多家模型切换模型只改 Model ID不用来回换 Key。官网入口在 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 根地址是 https://taotoken.net/api 注意这个地址后面不加任何查询参数。拿 Key 的路径很直接登录后进控制台在 API Keys 页面创建一枚新 Key复制出来存到本地环境变量里别写进会提交到 git 的配置文件。控制台地址是 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsole_setuputm_campaignrewrite API Keys 页面是 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapikeys_setuputm_campaignrewrite 。模型对话页面可以用来先验证 Key 是否可用 https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentchat_verifyutm_campaignrewrite 。环境侧需要三样东西。第一是 Pi 本体装好后终端里能执行pi命令第二是 Node 运行时filesystem MCP 服务端一般通过 npx 拉起第三是一个放演示数据的目录。我用的目录是~/Downloads/pi-mcp-demo里面放两个 JSON 文件模拟两个项目的问题列表。先确认 Pi 的 MCP 子命令存在pi --version pi mcp --helppi mcp --help会列出 add、remove、status、login 等子命令同时说明全局配置和项目配置的位置。全局配置一般在用户目录下的 Pi 配置文件夹里项目配置则在当前项目根目录优先级是项目覆盖全局。这一点很关键演示用的 filesystem 服务端我只想在当前项目生效所以走项目级配置不污染全局。环境变量这样设写进~/.zshrc或当前 shell 会话都行export TAOTOKEN_API_KEYsk-你的Key export TAOTOKEN_BASE_URLhttps://taotoken.net/api然后验证一下变量确实生效echo $TAOTOKEN_BASE_URL输出应该是https://taotoken.net/api末尾没有斜杠也没有多余参数。如果输出为空说明当前 shell 没加载到重新 source 一次配置文件。这一步看着琐碎但后面 401 报错十有八九是这里没设对先排除掉能省很多时间。演示数据我准备了 12 条 issue分在projectA.json和projectB.json两个文件里字段包括 id、title、priority、assignee、description。其中 3 条符合高优先级且无负责人A-01、A-06、B-04。数据是虚构的但结构贴近真实项目管理工具的返回方便后面演示筛选逻辑。3. 可复制配置Pi 的 MCP 服务端与模型通道这一节给两份配置一份是 Pi 的 MCP 服务端声明一份是模型通道的 settings 片段。两份都要能直接复制粘贴路径按你自己的实际目录改。先看 MCP 服务端。Pi 的项目级配置放在项目根目录的配置文件里格式是 JSON。filesystem 服务端通过 npx 拉起参数里指定允许访问的目录{ mcpServers: { filesystem: { command: npx, args: [ -y, modelcontextprotocol/server-filesystem, /Users/你的用户名/Downloads/pi-mcp-demo ], provider: codemode } } }这里provider字段就是前面说的四种提供方式之一。我选codemode因为这次的重点就是让模型写脚本调工具。如果你想先看工具声明再决定可以改成direct工具特别多、想按需加载用deferred。hidden一般用于内部工具不暴露给模型。注意 args 里的目录必须是你真实存在的绝对路径写错了服务端启动会直接失败/mcp面板里会显示未连接。路径里不要带~npx 拉起的进程不一定能正确展开波浪号。再看模型通道。Pi 的模型配置同样走 settings 文件把 Base URL、Key、Model ID 三件套填进去{ models: { taotoken: { baseUrl: https://taotoken.net/api, apiKey: ${TAOTOKEN_API_KEY}, model: claude-sonnet-4-5, provider: anthropic } }, defaultModel: taotoken }apiKey用${TAOTOKEN_API_KEY}引用环境变量避免明文落盘。model字段填你在 TaoToken 控制台里确认可用的 Model ID不同模型 ID 不一样填错会报模型不存在。provider按模型实际协议填Claude 系列走 anthropic 协议OpenAI 系列走 openai 协议。如果你用的是 Claude Code 风格的配置等价片段长这样放在~/.claude/settings.json里{ env: { ANTHROPIC_BASE_URL: https://taotoken.net/api, ANTHROPIC_AUTH_TOKEN: sk-你的Key, ANTHROPIC_MODEL: claude-sonnet-4-5 } }三件套齐全Base URL 指向 TaoToken 的 API 根地址Key 用控制台创建的那枚Model ID 与上面一致。Cline 的 MCP 配置则是另一套结构服务端部分和 Pi 类似模型部分在 Cline 自己的 provider 设置里填同样的三件套这里不展开核心是 Base URL 和 Key 不要填错位置。配置写完后在项目根目录启动 Pi进/mcp面板检查连接状态。正常的话能看到 filesystem 已连接工具数量在 14 个左右提供方式显示 codemode配置来源显示当前项目。如果显示未连接先手动跑一遍 npx 命令看报错npx -y modelcontextprotocol/server-filesystem /Users/你的用户名/Downloads/pi-mcp-demo进程能起来并停在等待输入的状态说明服务端本身没问题问题在 Pi 的配置路径或参数上。4. 验证请求从直连调用到 Codemode 脚本配置就绪后先做最小验证让 Pi 通过 MCP 读一个文件。在对话里输入用 filesystem 工具列出 pi-mcp-demo 目录下的文件观察它是否真的调用了工具而不是凭空回答。成功的话会返回两个 JSON 文件名。这一步验证的是 MCP 通道本身通不通。接着验证模型通道。单独发一句你好回复你的模型名称能正常返回说明 Base URL、Key、Model ID 三件套都对。如果这里就报错先别往下走回到第 5 节排错。两个通道都通之后跑正式任务让 Pi 读取两个 JSON 文件找出高优先级且无负责人的 issue输出编号和标题。第一次我用 direct 方式让它直接调工具模型把 12 条记录全读进上下文再判断结果正确返回 A-01、A-06、B-04 三条。但你能感觉到上下文里塞了不少用不上的描述字段。然后切到 Codemode让模型写脚本完成同样任务。脚本大致长这样const a await callTool(filesystem, read_file, { path: /Users/你的用户名/Downloads/pi-mcp-demo/projectA.json }); const b await callTool(filesystem, read_file, { path: /Users/你的用户名/Downloads/pi-mcp-demo/projectB.json }); const parse (res) JSON.parse(res.content[0].text); const projectA parse(a); const projectB parse(b); const selected [...projectA, ...projectB] .filter(issue issue.priority high issue.assignee null) .map(({ id, title }) ({ id, title })); text(selected);这段不是一次跑通的。第一次报变量重名因为模型在脚本里重复声明了selected改掉之后又报 JSON 解析错误原因是它把 MCP 返回的整个 content 对象当字符串直接JSON.parse。实际返回结构是{ content: [{ type: text, text: ... }] }文本在content[0].text里。改成先取文本块再解析脚本跑通text(selected)输出三条记录和 direct 方式结果一致。这里要诚实说一句调试过程中模型打印过返回对象来检查结构所以不能把整个过程描述成模型始终只看到三条结果。最终成功那次脚本确实完成了筛选和字段提取但我没有做 Token 和耗时的对照测试不能据此说 Codemode 更快或更省。你要评估收益得自己在同一任务上跑两组对比。脚本里用到的callTool、text、searchTools、describeTool都是 Codemode 提供的接口。工具多的时候先用searchTools(file)找到相关工具describeTool看参数再调用比开局读全部声明省上下文。5. 常见报错排查401、连接失败与解析错误这一节按真实报错对照都是我在接入过程中实际遇到或高频出现的。401 Unauthorized。最常见九成是 Key 没生效。检查顺序环境变量是否在当前 shell 可见echo $TAOTOKEN_API_KEY输出是否为空、settings 里引用变量名是否拼错、Key 是否在控制台被删除或过期。还有一种隐蔽情况Base URL 末尾多了斜杠或带了查询参数导致请求路径拼接错误服务端返回 401 而不是 404。确认 Base URL 严格是https://taotoken.net/api。local proxy failed / 连接被拒绝。这类报错通常出现在 MCP 服务端启动阶段不是模型通道问题。原因多是 npx 拉包失败、目录路径不存在、Node 版本过低。手动执行第 3 节那条 npx 命令看具体错误。如果提示找不到包检查网络能否访问 npm 源如果提示目录不存在把 args 里的路径改成真实绝对路径。reading choices of undefined。这是模型响应结构不符合预期时的典型报错一般发生在 provider 协议填错的情况。比如模型实际走 OpenAI 协议你却在配置里写了 anthropic客户端按 anthropic 的结构解析响应取不到choices字段。核对 Model ID 对应的协议改provider字段。OAuth 相关报错。部分 MCP 服务端要求登录授权pi mcp login子命令就是干这个的。如果服务端声明了 OAuth 但你没登录调用时会报授权失败。按pi mcp --help里的说明执行登录流程凭据会存到配置目录。filesystem 这类本地服务端不需要 OAuth遇到这类报错先确认你接的是不是远程服务端。JSON 解析错误。就是第 4 节踩的坑。MCP 工具返回的是 content 数组文本在content[0].text不是直接可解析的字符串。写脚本时先打印一次返回结构确认字段路径再写解析逻辑。不同服务端的返回结构可能略有差异别假设所有工具都长一样。工具调用成功但结果为空。检查筛选条件字段名是否和服务端返回一致。我演示数据里用assignee真实项目管理工具可能叫assignee_id或owner。先用describeTool看工具的参数和返回 schema或者让脚本先text(projectA[0])打印一条样本确认字段名再写 filter。排错时有个通用技巧把大任务拆成最小步骤先验证 MCP 通道读一个文件再验证模型通道回一句话最后才跑组合任务。任何一步失败就停在那一步排查不要带着未知错误往下走否则报错会层层叠加很难定位根因。6. 继续用下去Coding Plan 与文档入口跑通之后如果你打算把 Pi 加 MCP 这套组合用在日常编码或 Agent 任务上可以考虑 TaoToken 的 Coding Plan长期编码场景下比按次调用更划算入口在 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcodingplan_ctautm_campaignrewrite 。接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdoc_ctautm_campaignrewrite 里面有各协议的 Base URL 和参数说明配置前扫一眼能少踩坑。Claude Code 相关的接入说明在 https://taotoken.net/claudecode-anthropic?utm_sourcetaotoken_aicg_blog_endutm_contentcc_ctautm_campaignrewrite 如果你同时用 Claude Code两边的 Key 可以复用同一枚。回到标题那个问题MCP 已死吗从 Pi 1.0 的动作看恰恰相反MCP 被放到了更核心的位置只是调用方式从全量声明塞给模型变成了按需发现加脚本编排。Codemode 不是替代 MCP而是补上了中间结果处理这一环。真正要判断的是你的任务形态规则明确、返回数据量大的筛选统计适合交给脚本需要理解语义、比较影响的判断还是得把相关信息留给模型。先拿一个只读的小任务试核对有没有漏查、筛选对不对、最终交给模型的内容够不够回答问题再决定要不要用到更复杂的流程里。