返回文章
NO.
047
DATE
READ
~8 min
KIND
笔记
STATUS
原文

TAGS: AI 协作 工具

Pi 接入 MCP:读文件成功,权限却比预期大

在 WSL 的 Pi 中接入文件系统 MCP,记录真实工具调用、Roots 覆盖目录参数的复核,以及商业 SEO MCP 的权限和计费边界。

这次想弄清楚 MCP(Model Context Protocol)在 Coding Agent 里是怎么工作的,没有从 Semrush 或 DataForSEO 这类商业数据服务开始,而是选了一个最容易核对的实验:让 Pi 通过文件系统 MCP 读取一行中文。

文件读出来了。但后来检查目录权限时,发现一个比“连接成功”更值得记录的问题:启动参数只指定了 files 子目录,服务实际允许访问的却是上一级项目目录。

本文以当时的实验记录为依据,复盘配置、工具调用和只读权限对照。商业 SEO MCP 部分来自截至 2026 年 10 月 21 日的官方文档,没有实际发起付费 API 请求。

为什么要绕一圈 MCP 读文件

Pi 本来就能通过内置 read 和 bash 访问本地文件。只要目标是读取一个文本文件,直接用内置工具更简单。

这次用 MCP,是为了验证另一条调用链:

用户 → Pi → 模型
        ↓   ↑
      MCP Client
        ↕
      文件系统 MCP Server
        ↕
      WSL Ubuntu 文件

Pi 是管理会话和工具的宿主应用;文件系统 MCP Server 是另一个进程,负责真正执行文件操作。模型根据工具定义提出调用,结果经 Pi 返回给模型,再生成回答。

本次使用的是 stdio 传输:Pi 启动本地子进程,通过标准输入、标准输出交换 JSON-RPC 消息,不需要为它开放网络端口。但本地执行不代表文件内容一定留在本地:工具返回的文本通常还会进入当前模型服务的上下文。

最小实验:配置之外,还要看到工具调用

实验环境是 Windows 11 的 WSL Ubuntu。记录中的版本为 Node.js v24.18.0、npx 11.16.0、Pi 1.1.0;当时缓存的文件系统服务包为 2.0.0。这些是本次实验的版本,不是所有环境必须使用的固定组合。

先创建独立目录和一行测试文本:

mkdir ~/mcp-demo &&
cd ~/mcp-demo &&
mkdir files &&
printf '%s\n' '你好,这是我的第一个 MCP 测试文件。' > files/hello.txt

然后在该目录登记项目级 MCP 连接:

pi mcp add filesystem --local --exposure direct -- \
  npx -y @modelcontextprotocol/server-filesystem "$HOME/mcp-demo/files"

--local 的意思是将连接信息写进项目内的 .pi/mcp.json,不是说 MCP 只能访问本地资源;--exposure direct 则让连接中的工具直接提供给模型。这里的 npx -y 还可能自动下载软件包,不应把它理解成对后续所有工具操作的授权。

首次加载项目配置时,Pi 提示项目尚未被信任。确认这是自己创建的练习目录后,允许加载配置,再进入 Pi 使用 /mcp 检查连接。实验记录显示:

filesystem · connected · 14 tools · direct · project

这一步证明服务连接成功,并且公开了 14 个工具,却不能证明目标文件已被读取。服务提供的工具还包括写入、编辑和移动文件,因此这不是一条只读连接。

为了排除 Pi 内置工具的干扰,测试时明确指定使用 mcp__filesystem__read_text_file,不能改用 read 或 bash。在实际调用记录中,出现的是:

filesystem/read_text_file
path="/home/<用户名>/mcp-demo/files/hello.txt"

其中用户名已匿名化。工具返回:

你好,这是我的第一个 MCP 测试文件。

Pi 通过文件系统 MCP 实际调用 read_text_file 并返回中文测试文件内容(路径已匿名化)

调用截图:工具名、参数与返回文本均来自实验记录,公开路径已匿名化。

确认成功的依据是工具名、调用参数与返回值三者能够对上,而不只是聊天窗口里出现了正确的一行文字。上面的调用记录是按实验材料转写的关键字段,不是协议报文抓包。

配置写的是 files,为什么实际范围变大了

原先传给文件系统服务的目录是:

/home/<用户名>/mcp-demo/files

按这条参数直觉判断,服务似乎只能访问 files。但随后的只读复核,使用相同版本组合下的 Pi 客户端库,对比了提供和不提供客户端 Roots 的两种情况:

复核条件服务实际允许的目录
客户端提供与 Pi 相同的 Roots~/mcp-demo
不提供客户端 Roots~/mcp-demo/files

复核还检查了 .pi/mcp.json 的文件元数据:第一种情况允许访问,第二种被拒绝;两种情况下,项目目录外的测试路径均被拒绝。这说明范围扩大到了项目目录,而不是整个家目录。

原因在于这次使用的旧协议连接。文件系统服务官方 README 说明:对于支持 Roots 的 2025 年版协议客户端,客户端提供的 Roots 可以替换服务从启动参数获取的允许目录。Pi 当时提供的是项目工作目录,因此服务最终采用了更大的范围。

这里还有一处版本边界:MCP 2026-07-28 已将 Roots 标为弃用,但并不意味着旧连接立刻无法使用;文件系统服务在新版协议连接下也采用不同的目录控制路径。所以这次观察不能推广成“所有 MCP 都会忽略启动参数”。

如果下次在真实项目中配置文件系统 MCP,我会先做三件事:

  1. 调用 list_allowed_directories,查看服务实际认为哪些目录可以访问。
  2. 在不修改文件的前提下,检查一个预期允许的路径和一个预期拒绝的路径。
  3. 如涉及真实敏感资料,使用单独用户、操作系统权限或只读挂载进一步隔离,而不只依赖工具描述和提示词。

尤其要注意:要求模型“只读取”,不是把含写入能力的工具变成了只读工具;服务层的路径限制,也不是对运行该进程的操作系统账户进行沙盒隔离。

限流报错与 MCP 故障不是一回事

实验中还出现过 exceeded token rate limit,随后切换到 deepseek-flash 才完成工具调用。

这条报错来自模型服务的 token 速率或配额限制,不能据此认定文件系统 MCP 连接失败。排查时可以按层区分:项目不受信任,先查配置加载;/mcp 连接失败,查服务进程与通信;工具返回 Access denied,查路径权限;模型报 token rate limit,则查模型侧限额和上下文。

direct 模式会把工具定义提供给模型,存在一定上下文开销。但仅凭这次截图,无法证明“14 个工具造成了限流”。这两件事没有做过控制变量的对照测试。

换成 Semrush、DataForSEO,真正变化的是什么

MCP 的共同作用是让模型发现并调用外部能力。不同服务之间更有意义的差别,是它们连接到什么数据、提供哪些操作,以及谁承担权限和费用。

本次文件系统 MCPSemrush MCPDataForSEO MCP
数据从哪来指定目录里的已有文件Semrush 报告与项目数据DataForSEO 的各类 API
主要调用方式直接操作文件发现报告、获取参数结构、执行报告查文档、调用通用 API 请求工具
主要风险文件访问与写入权限账户权限、API units 消耗API 任务量、请求参数与余额
本次是否实测已验证文件读取,记录了权限对照未调用未调用

Semrush 官方 MCP 使用远程 Streamable HTTP,支持 OAuth 或 API Key;当前文档把 Projects API v3 的 MCP 操作限定为只读。使用 MCP 本身不另收一笔 MCP 服务费,但相关报告仍按 API units 消耗额度,且具体访问资格依赖套餐。

DataForSEO 新版服务的核心工具只有 docs_index、docs_list_sections、docs_search 和 api_request 四个。它没有把几十种业务端点都直接摆成同级工具,而是让 Agent 先查文档,再构造请求。本地 stdio 和远程 HTTP 都可以使用;即使 MCP 在本地运行,业务请求仍可能访问远程付费 API。

DataForSEO 当前采用按量付费。官方列有新账户 1 美元试用额度及 Sandbox,最低充值金额为 50 美元。50 美元是充值门槛,不是一次 MCP 调用的费用;实际费用应按所选端点、模式和参数核算。

这也解释了为什么不能用工具数比较业务能力:本次文件系统 MCP 有 14 个工具,而 DataForSEO 的四个通用工具背后覆盖大量 API。接口数量与底层数据覆盖完全不是同一个指标。

真要用于 SEO 工作,先决定是否需要 MCP

如果只是分析已经导出的 GSC、关键词 CSV 或 Site Audit 报表,先用文件读取和现有分析脚本,不需要为了使用 MCP 而再接一层。任务固定、参数明确、需要批量重复执行时,直接 API 脚本通常更容易测试和估算费用。

MCP 更适合交互过程中需要动态选择工具,或者希望在多个兼容 AI 客户端之间复用同一套服务的情况。

至于商业 SEO 数据,我会把费用控制放在连接之前:

  • 默认不允许 Agent 自行调用新的付费端点;首次放行前确认端点、单价、任务数和预期上限。
  • 能用 Sandbox 或不计费的文档工具验证调用流程,就先不碰真实数据请求。
  • 在服务商账户侧设置可用的消费限制,关闭不需要的自动充值;必要时用网关限制允许的端点和参数。
  • 限制任务数、返回行数、分页、并发和重试。一次自然语言提问可能触发多次工具调用,甚至一个工具调用也可能提交多个计费任务。
  • 对超时请求保留任务 ID 与消费记录,不在无法确认是否已计费时无限重试。

这些措施中,提示词只能约束 Agent 的行为倾向,不能当作可靠的费用硬上限。只读不代表免费,限速也不等于限额。

边界

这次真正验证的是:在记录所示版本的 WSL、Pi 与文件系统服务组合中,模型经 MCP 工具成功读取了测试文本;原复盘还留有 Roots 影响允许目录的只读对照结果。本轮撰稿没有重新连接该电脑,也没有运行 Semrush 或 DataForSEO 的业务 API。

没有验证的内容包括:其他 Pi 版本是否具有相同 Roots 行为、文件系统服务的生产环境安全性、两家商业 MCP 的实际稳定性和账单消耗。

如果以后继续接入新的 MCP,我会先看真实工具调用和实际授权范围,再决定开放哪些数据和能力。连接状态变绿只是第一步。

写作说明:GPT-6 根据实验记录和资料起草;作者提供截图并确认发布。

评论 →

CC BY-NC-SA 4.0

评论

评论由 GitHub Discussions 提供。登录 GitHub 后即可评论。 前往对应 Discussion