首页 / 资讯中心 / 文章详情

Pi 1.0发布:原生MCP与Durable机制,终端编程代理的可靠进化

Pi 1.0发布:原生MCP与Durable机制,终端编程代理的可靠进化 ★ FEATURED ARTICLE
先交代一下背景。过去大半年我手里的主力开发环境已经从“编辑器加插件”慢慢变成了“终端加命令行代理”的组合。IDE 里的编程助手体验已经非常成熟但我一旦要同时操作多个仓库、跑批量修改、让 AI 独立执行一轮“发现问题、改代码、跑测试、提交”的流程还是更愿意回到终端里。我一直在用的终端编程代理项目 Pi最近发布了 1.0 正式版。这次更新的重头戏是两块原生支持 MCP、引入 Pi Durable。我前后用了一周多把配置、真实任务、断线恢复都试了一遍这篇就来聊聊 1.0 到底改了什么、实际用起来有没有宣称的那么好、以及有哪些坑需要注意。如果你是已经在用终端型编程代理的人或者一直好奇 MCP 和 Durable 这类机制到底怎么落地的这篇文章应该能帮你省不少折腾时间。1. 为什么版本号敢从 0.x 直接跳到 1.01.0 不是随便挑一个节点发出来的。终端编程代理和 IDE 插件最大的区别在于它把“对话”和“执行”彻底绑定在一个进程里还要长期占用你的 shell。这种形态暴露出来的问题远比我最初想象的更具体。1.1 旧版本最让人难受的三个场景第一工具接入靠“每条管道各写一个适配器”。想让代理查内部文档要给它写一个搜索接口的调用脚本想让它操作本地 Git又得单独接一套命令解析。每接一个新能力都要在代理内部手动实现一套加载、调用、错误返回逻辑。这种重复劳动在 0.x 时期几乎每周都在发生。第二长任务没有任何恢复能力。让 Pi 跑一次跨文件的重构跑到第几分钟终端不小心关了、SSH 断了、或者超时被系统杀掉整个任务直接归零。下一次还得把同样的话术重新说一遍文件检查、修改意图、半成品 diff 全部得重来。这也导致我一直只敢拿它做短平快操作不敢真正放养一个大任务。第三对话记忆和任务状态是两回事。当时的会话记录能吃满上下文窗口但任务本身没有结构化的“中间状态”。模型说“改完了”实际改了哪些文件、哪些还没动、哪些内容是需要用户确认后继续执行的这些信息没有落盘换个会话立刻失忆。1.2 1.0 给出的两个核心答案这次发布实际上是把 0.x 里一堆临时方案收敛成了两个长期机制。原生 MCP 解决的是工具接入和工具调用规范化的问题。MCP 是模型上下文协议它把“代理”与“外部工具”之间的关系定义成客户端和服务端。Pi 在 1.0 里直接实现了 MCP Host不再需要为每个工具单独写适配器只要对方提供一个符合协议的 server配置一行就能加载进来。Pi Durable 解决的是任务状态持久化的问题。它给每个长任务增加了 checkpoint 机制任务的执行进度、文件补丁、工具调用记录、用户审批记录都会落盘。进程崩了、终端关了、电脑重启了任务都能从上一个 checkpoint 继续跑不是从零开始。1.3 谁最该关注这个版本我觉得有这么三类人值得立刻升级试试一是已经在自建工具链、手头有内部服务想暴露给 AI 的开发者二是经常让代理执行多步骤代码改动的工程师比如从 issue 描述直接到 commit 的工作流三是团队里多人共用一台构建机或者远程开发环境、需要随时离线恢复的人。当然如果你只是偶尔用 AI 改个 bug那这个版本对你来说最大的感受可能是“响应变稳了”长期价值要等你真的放养大任务之后才体现得出来。2. 原生 MCP 支持从“能连工具”到“懂工具”MCP 这个词现在到处都在提但“支持 MCP”和“原生支持 MCP”差距很大。Pi 1.0 以前也能通过外部脚本间接调用一些 MCP 服务但那本质上是把协议包在一个可能随时坏掉的桥接层里。1.0 之后Pi 自己是 MCP Host这是架构层面的变化。2.1 原生支持到底改变了什么MCP 的核心是 JSON-RPC 消息模型定义了初始化、工具列表、资源列表、工具调用、返回结果这一整套消息流程。原生支持意味着 Pi 主进程负责和服务端做标准握手工具以统一格式注册进模型可调用的函数列表工具之间的名称不会冲突错误码也有统一规范。用生活类比来说以前让 Pi 接一个工具相当于给不同国家的电器各买一个转换插头麻烦而且接头标准不一。现在原生支持 MCP 相当于所有电器都换成了同一个国标插座只要一个插线板就全部搞定。具体到终端代理看上去的变化有三个。一是加载工具不再依赖插件系统的自定义格式配置一段 MCP server 描述即可。二是工具调用结果会以标准的tool_result消息返回模型能看到结构化输出而不是干巴巴的 stdout 文本。三是工具调用的权限可以在 host 层统一管理不用每个工具各自实现。2.2 配置文件长什么样老用户可能会关心怎么迁移。沿用~/.pi/config.json1.0 新增了mcpServers字段{ mcpServers: { local-git: { command: pi-fs-git, args: [--root, /srv/myrepo], env: { LOG_LEVEL: info }, transport: stdio }, docs-search: { url: https://docs.example.dev/mcp, transport: sse } } }stdio适合本地起一个子进程通过标准输入输出通信启动快、调试直观sse适合连接远程的 HTTP 服务比如内部的文档检索服务、代码索引服务。配置好之后用pi mcp list能查看所有服务是否成功握手。2.3 工具的组织和权限模型加载进来的工具会统一命名成mcp__server名称__工具名例如mcp__local-git__status。这样即使两个 server 暴露了同名的search在模型层面也不会混淆。1.0 还把工具暴露拆成了几个权限等级可以在配置里声明{ mcpServers: { local-git: { command: pi-fs-git, permissions: { readOnly: true } }, deploy-api: { command: pi-deploy, permissions: { confirmRequired: [delete, restart] } } } }我对这个设计的评价是它终于让“AI 能碰写操作”这件事从口头约定变成了强制拦截。只读服务默认连读写服务默认每步确认危险操作就算模型主动要调也会被 host 拦下来问用户。2.4 一个具体接入案例我有一次需要让 Pi 结合内部代码索引回答问题。代码索引服务本身暴露了一个 MCP endpoint返回给定符号的跨仓库引用情况。过去我可能要写一个 scrape 脚本把结果整理成文本再粘给模型。1.0 里我在配置里加了一行 server 描述重启之后任务进行中模型就能主动判断什么时候需要查引用、什么时候查定义。让我印象最深的是模型调用这种服务时明显更“懂”了。因为 MCP 工具描述里带有参数 schema模型可以填精确的符号名和范围参数返回结构也是可解析的 JSON而不是我手工处理过的格式化文本。区别就像是 API 接口文档和抓包日志的差别前者天然为消费方设计后者还要二次解析。3. Pi Durable为“跑一半的任务”做好的存档点如果说原生 MCP 是让 Pi 对外连接的肌肉那 Pi Durable 就是让任务能扛住意外的骨骼。我对这个功能的兴趣其实比对 MCP 更大。因为工具接入再花哨解决不了“任务中途断掉就白干”的根本问题。3.1 Durable 要解决的痛点编程代理本质上是一台状态机。它接收任务拆成子步骤每步可能调用工具、等确认、拿到结果后再决定下一步。旧版本的问题在于这个状态机只活在内存里进程一没就全没了。终端环境比 IDE 环境更容易出现“突然没”。SSH 会话被网络抖断、笔记本合盖、CI 服务器重启、命令超时被杀任何一个意外都会让一个跑了大半个小时的改动任务直接失效。Durable 的定位就是给这台状态机加外置的存档系统。3.2 任务状态机与 checkpoint 机制Pi 1.0 的 Durable 会把任务的执行抽象成这几个阶段pending、running、waiting_tools、waiting_confirm、completed、failed。每次状态迁移之前它都会写一个 checkpoint当前任务目标和尚未完成的子任务队列已经执行过的工具调用及其结果摘要工作区内已应用的文件补丁和 diff用户已经给过的确认记录对话上下文压缩后的 summary用于恢复后的记忆重建这些数据会写进~/.pi/durable/任务ID/元信息在 SQLite 里大文件以快照形式存盘。你可以把它类比成游戏存档。但和普通存档不同的是它还要保存“接下来该干嘛”的队列这样恢复之后不会只记得做了啥、忘了还剩啥。3.3 恢复流程是怎么串起来的恢复时 Pi 会做三件事。先校验工作区状态计算当前目录文件哈希和 checkpoint 时记录的快照哈希对比不一致就要先处理冲突不允许“稀里糊涂接着改”。然后加载 summary让模型快速重建对任务的认知。最后从最近的 checkpoint 继续执行待办子任务而不是回退到最早的对话重新推导。这一步很关键。和“上下文恢复”不同Durable 不是把历史消息全部塞回来而是用摘要加结构化队列重建上下文。前者是重放录像后者是直接载入存档。录像的问题在于重放到一半模型还是会糊涂存档则精确定位到任务进度。3.4 Durable 对工作流带来的变化实践下来最大的变化是我终于敢让 Pi 干“几个小时尺度”的活了。以前跑一个涉及两三百个文件的大规模代码风格统一我得坐在屏幕前盯日志。现在我可以直接放养中途去开会、合上盖子回来用一条命令恢复它会告诉我上次停在哪、还需要多久、有没有出现需要人工决策的点。这种确定感是普通会话保存给不了的。4. 完整实测安装、配置、跑通一次跨文件重构与断线恢复光看文档不够这一节是我实际跑通的全过程。环境是普通的 Linux 开发机仓库是一个中型 Python 项目。我会把关键命令和输出形态写清楚。4.1 安装与初始化我是直接用官方安装脚本装的另外它也支持 cargo 安装。两种方式任选# 方式一官方安装脚本 curl -sSL https://get.pi.example.dev | bash # 方式二cargo 安装 cargo install pi-cli这里有个提醒从网络跑安装脚本之前最好先下载下来看一眼内容确认没有奇怪行为。安装完之后运行pi doctor检查环境能帮你发现缺省配置。pi doctor它会检查默认模型配置、工作目录权限、MCP 配置是否合法。首次使用建议执行pi init按提示选择默认模型、设置任务存储目录。4.2 配置一个本地只读 MCP 服务我想让 Pi 能直接读取仓库里的文件信息所以先配了一个只读的本地文件系统服务。配置文件直接改~/.pi/config.json{ mcpServers: { repo-reader: { command: pi-fs, args: [--root, /home/me/work/example-project], transport: stdio, permissions: { readOnly: true } } } }然后执行pi mcp list正常情况下会看到repo-reader状态为connected后面跟一串可用的工具名比如mcp__repo-reader__read_file、mcp__repo-reader__list_dir。这个阶段有问题先别急着跑任务把连接问题清掉再继续。4.3 实操一个跨文件日志规范化任务我给 Pi 下的任务是检查src/utils/logger.py的当前日志格式把整个src目录下调用logger.info的地方统一改成带模块前缀的新格式并且不能改动测试文件的预期输出。命令pi 将仓库 src 目录下所有 logger.info 调用改为带模块前缀的形式模块前缀从文件路径推导。先检查 src/utils/logger.py 了解现有格式改完后给我一份改动文件清单。这个任务之所以危险是因为它涉及全局改动而且有“不能改测试预期输出”的约束。Pi 的处理过程大致分成几个阶段。先调用mcp__repo-reader__read_file读取 logger 实现再列出所有可能受影响的文件用 git diff 给出一份改动预览然后逐个应用修改最后回到终端让我确认是否提交。我注意到一个细节因为 MCP 工具注册进来了模型能够自主决定“先读配置、再搜调用点、再生成 patch”。整个过程里工具调用是有序的而不是一股脑把文件内容塞进上下文。这也降低了上下文被快速占满的风险。4.4 Pi Durable 挂起与恢复的真实场景同一段任务我故意做了一个测试。在任务执行到大约修改到第 40 个文件的时候直接关掉终端模拟断线。重新打开终端后pi durable list输出显示一个任务 ID 处于running转interrupted的状态。恢复命令pi durable resume 42它没有重新解析我原来的那句话而是告诉我“已从 checkpoint 恢复还有 15 个文件未处理”并继续输出新的改动。整个恢复过程用了大概 20 秒其中大部分时间花在重建摘要和校验工作区哈希上。对比如果是旧版本我大概率要重新组织一遍任务描述、重新确认改过的文件然后再等它从头把所有文件重读一遍。我特意验证了一下恢复后的结果最终 diff 和“一口气跑到底”的版本基本一致没有因为中断多改或者漏改。这说明 checkpoint 保存的文件补丁和任务队列是可靠的。5. 实测中踩到的坑与避坑经验1.0 总体是稳的但新机制也带来了一批新问题。这一节记录我实际踩过的坑每条都能帮你在自己的环境里少花冤枉时间。5.1 MCP 服务进程卡住或假死我在接一个内部 SSE 服务时遇到过工具调用一直“pending”的情况。表面看 Pi 没有报错但等了很久都没有工具结果返回。排查下来是服务端在长轮询场景下没有实现超时连接挂住不主动断开。建议在配置里给 MCP 调用加上超时约束{ mcpServers: { docs-search: { url: https://docs.example.dev/mcp, transport: sse, toolTimeoutMs: 15000 } } }如果工具是本地 startio 进程优先确认服务本身是不是每行输出都有 flush。很多子进程因为输出缓冲导致 Pi 等不到完整 JSON-RPC 消息。5.2 Durable 恢复时的工作区不一致有一次中断后我记不清当时改到一半的文件是否被我手动动过直接跑pi durable resume结果被拒绝工作区哈希与 checkpoint 不一致。最初我以为是 bug后来想明白了这是有意设计。checkpoint 里记录的文件状态只对你“没有改过文件”的情况有效。一旦工作区变了继续在这个基础之上应用后续 patch很可能把不一致扩散。正确的做法是如果你改过文件先git stash把改动收起来让工作区回到 checkpoint 对应的状态再恢复任务。如果不想保留手动改动可以直接用pi durable discard 42 1_old丢弃 checkpoint重新从当前状态发起新任务。千万别让 Pi“无视差异继续跑”后续 diff 一定会错位。5.3 权限模型造成的“假失败”这是个非常容易误判的坑。我给某个 MCP 服务配了写权限但工具列表里某些操作在 server 端被标记为需要确认Pi 这边又没声明confirmRequired执行阶段就会出现模型“调用被静默拒绝”。表面上看是工具调用失败实际是 host 层的权限策略拦掉了。排查命令是看任务日志里的permission_denied字段。确认之后要么放宽 server 声明要么在 Pi 配置里显式把风险操作放进confirmRequired。我更推荐后者宁可每次多一次确认也不要在生产仓库里被代理偷偷删了一个分支。5.4 模型上下文压缩与 Durable 的配合度Pi Durable 的恢复依赖上下文 summary。如果 summary 压缩过度模型恢复后可能忘了任务里的隐性约束比如“不能改动测试预期输出”这种话一旦被挤出摘要后续步骤就可能跑偏。我的经验是重要约束不要只靠对话上下文尽量写进任务描述本身或者直接用别名模板固化。例如pi alias save refactor-log 统一所有 logger 调用格式需保留测试预期输出完成后生成 diff 预览之后每次都用pi alias run refactor-log这样即便中途要恢复约束也会在任务重启时重新注入不依赖摘要是否完整。6. 适用场景、边界与我对 1.0 后续的想法这一版功能很明确但也不是万金油。结合我的体验说说它最适合干什么以及哪些地方暂时不建议硬上。6.1 最值得用 Durable MCP 的场景首先是批量代码改动。会有明显收益。当任务规模超过一百个文件或者需要跨仓库读取信息再回写Durable 的价值几乎是立刻显现的。其次是夜间跑任务。可以让 Pi 在无人值守的情况下修改、测试、生成报告第二天验收结果就行。第三是团队内部的“半自动运维开发”把内部 API、文档、代码索引全部用 MCP server 暴露给代理让它在终端里自由调度。6.2 暂时不建议的场景如果是高频交互式结对编程你更习惯每改一行都盯着编辑器里的内联 diff那 Pi 这种终端代理形态可能仍然不适合你。Durable 的恢复机制对“你已经确认过、但还没执行的子任务”支持不错但如果你是在和模型激烈讨论方案的阶段那种开放式的探索过程本身不适合做 checkpoint更适合用普通对话记录。另外团队共享同一份 durable 任务目录时要注意冲突它目前还没有做多人并发锁。建议一个任务只由一个终端进程负责。6.3 后续值得关注的方向我挺期待后续两个能力。一是 durable 任务的多人可见性允许团队看到“某个任务跑到哪了、卡在哪一步”这对远程协作很有用。二是 MCP 权限分组的粒度细化现在只能声明只读或写但如果能按目录、按分支、按命令条件做更细的策略生产环境的安全性还会上一个台阶。回到这一周多的使用感受我最喜欢的变化其实是心理上的。以前让代理做大任务总要留一份戒心怕它中途断了我还得收拾烂摊子。现在 CtrlC 断掉也没那么慌因为 Durable 已经把最脏的中间状态接住了。最后分享一个团队里的小约定我们执行长任务时会在进度里带上任务 ID虚机重启后直接pi durable resume id接着跑不用每个人重新解释自己在干嘛。这种确定性就是 1.0 最大的价值。
阅读完成 · 觉得有帮助?
咨询建站