业州愚公在使用MCP的第三天,遇到了一个意外的情况,AI询问是否可以动某个数据夹,业州愚公在按下允许后才意识到自己从未设置过边界。这个事件让业州愚公开始学习MCP的三层权限、审批弹窗,还有使用官方Inspector排查错误的五步骤。业州愚公在这篇文章中分享了自己使用MCP的经验,包括装置MCP、串接服务器、撰写提示词等。这个事件也让业州愚公更加了解MCP的功能和设置,包括如何设置权限、审批和排查错误。
菜鸟之友系列:《AI 工具实操与提示词》・工具篇作者:业州愚公
前面四篇,我们一路把 MCP 装上、把几个服务器串起来、自己写了一个最小的、又补上了 resources 和 prompts。到这个阶段,AI 手上的活已经很实在了:能读报表、能写文件、能跑指令。
然后有一天,它弹出一行字问你:「即将执行某个操作,是否允许?」
大多数人的反应是看一眼、按允许,然后继续。我也是。直到有一次,它要动的是一个我早就不记得里面装了什么的数据夹,我才发现——这声「可以吗」是我最后一道门,而我根本没看清楚门后面是什么。
MCP 把「让 AI 做事」做得太顺了,顺到你会忘记:它做事,用的是你的权限。这一篇不谈怎么再多接一个工具,谈的是接之前怎么把边界画好,以及它不听话时怎么一步步查。
权限这件事,拆成三层看就清楚了:
| 层次 | 谁决定 | 管的是什么 | 出事的典型样子 |
|---|---|---|---|
| 系统层 | 你的作业系统账号 | 这个进程能碰哪些文件、能不能连外网 | 用管理员身分开客户端,服务器也跟着有 |
| 服务器层 | 启动时给的参数 | 它被允许处理哪个目录、连哪个数据库 | 只给了一个数据夹,它就只在那里活动 |
| 呼叫层 | 客户端的审批弹窗 | 每一次工具呼叫要不要放行 | 你按了「永远允许」,之后不再问你 |
三层是叠加的,不是三选一。系统层最宽,宽到你几乎不会察觉;服务器层是你唯一能真正收窄的地方;呼叫层则是最后的人工关卡。多数人只顾第三层——弹窗按得很勤,前两层开到最大。
弹窗是刹车,不是护栏——护栏得在安装时就立好。
具体怎么做?记住一个动作:只给它一个抽屉,不给整个房间。
以官方的 filesystem 服务器为例,启动时要把允许存取的目录当作参数传进去,它就只能在那个范围里读写,范围外的路径会被拒绝。这是 MCP 服务器设计里最值得学的一点:权限不是靠「它很乖」,是靠「它根本拿不到」。
很多教学为了省事,直接把整个家目录或整颗 D 槽丢进去。跑起来当然顺,什么都找得到;但这等于把家里所有钥匙串成一把交出去,真出事时你连它碰过什么都说不清。
实务上我自己是这样做的:
按任务开抽屉。 做报表的服务器只给报表目录,碰不到照片和合约。要处理另一批文件,就再开一个抽屉,而不是把抽屉换成整层楼。
抽屉要能随时收回。 专案结束就把那条设置注解掉或删掉。留着不用的服务器,等于留着一把没人管的钥匙。
能读就别给写。 只是查数据的场景,就别接一个有写入能力的服务器。真需要写,也尽量让它写到一个专门的输出目录。
另外,MCP 规格里还有一个叫 roots 的机制:客户端可以告诉服务器「我这次的工作范围是这几个目录」,服务器应该尊重这个边界。它比启动参数灵活,适合一个服务器服务多个专案。但别把它当成安全机制——它是约定,不是锁。真正的锁,还是启动时那个目录参数。
弹窗上通常显示工具名称、参数。新手最容易犯的错,是把「永远允许」当成省事按钮。
我的规矩很简单:凡是会改变东西的,一律不开永远允许。
什么算「会改变东西」?MCP 规格给工具加了几个标注:
readOnlyHint——只读,理论上不会改动任何东西,例如查汇率、读文件。
destructiveHint——可能造成破坏性改动,例如删档、覆盖、执行删除语句。
idempotentHint——重复执行结果一样,重试比较安全。
openWorldHint——会跟外部世界打交道,例如上网抓数据、呼叫第三方服务。
重点在最后这句:这些都只是 hint(提示),不是强制。 服务器可以标错,也可以干脆不标;客户端可以参考,也可以完全不理。所以看到「只读」两个字就放心按下去,是把安全寄托在别人的自觉上。
我自己的习惯是看参数,而不是看标签:这次呼叫带了路径吗?带了删除或覆盖这类动词吗?参数里有我没见过的网址吗?三个问题问完,通常三秒钟就有答案。
前面讲的都是「该怎么设」,真遇到问题,你需要的是「它到底怎么了」。官方有一个专门的排查工具,叫 MCP Inspector,不必装进日常用的客户端,可以单独跑起来,在浏览器里直接看它提供了什么、呼叫会不会出错。
最简单的用法是一行指令,把你要测的服务器指令接在后面:
npx @modelcontextprotocol/inspector node ./mcp-server/index.js
跑完之后,浏览器会打开一个介面。介面细节各版本略有不同,以官方最新版本为准,但大致的分区是固定的:
连线区。 填入启动指令、参数、环境变数。这一块等于把客户端里那条设置单独拿出来试,出问题时第一个要看的就是它。
能力列表。 左侧会列出这个服务器宣告的 tools、resources、prompts。这里有一个很实用的判断:如果列表是空的,问题不在 AI,而在服务器根本没把东西注册出去。
呼叫面板。 选一个工具、填好参数、按执行,直接看回传的内容。这一步能回答掉大部分「AI 说它不能用」的疑问:是服务器回错了,还是 AI 没选对工具,一眼就分晓。
通知与日志区。 服务器自己吐出来的讯息会显示在这里。这是最容易被忽略、却往往最有价值的一块。
有了它,你就不必在「改设置、重开客户端、问 AI、猜」这个循环里转。先让 Inspector 跑通,再接回客户端——顺序反了,你会同时面对两个未知。
| 症状 | 常见原因 | 怎么查 |
|---|---|---|
| 显示已连接,工具列表却是空的 | 服务器起来了但没注册任何能力,或初始化阶段就报错 | 用 Inspector 连一次,看能力列表与日志 |
| 一启动就退出,完全没讯息 | 启动指令或路径不对、相依套件没装 | 把同一行指令贴到终端机手动跑,看它自己报什么 |
| 明明连上了,一呼叫就断 | 程序往标准输出印了非协定内容 | 见下方单独说明 |
| 呼叫一直转圈,最后逾时 | 这次要做的事太久,超过客户端等待时间 | 拆成小步骤,先确认是不是单次耗时的问题 |
| 读到的文件乱码或缺字 | 编码不一致 | 换一个小文件对照,确认是内容问题还是传输问题 |
其中「一呼叫就断」值得单独说。stdio 这种传输方式下,标准输出就是协定通道,服务器与客户端之间的所有讯息都走这条线。所以你的程序只要往标准输出多印一行 console.log、一个启动横幅,整条协定就被这行杂讯污染,客户端解析失败,看起来就像「连上了但完全不理人」。
正解是把日志改走标准错误(stderr)。这条我在写最小服务器时踩过一次,排查了一下午——它看起来完全不像错误,只是「没有反应」。
踩过几次之后,我现在遇到「AI 说它不能用」,只做三件事,顺序固定:
第一步,先问它有没有那个能力。 让 AI 列出它看到的工具。如果连名字都没有,问题在连接层,不在 AI 的判断。
第二步,用 Inspector 直接呼叫一次。 同样的参数,绕过 AI 直接打。成功,代表是 AI 选错工具或参数填错;失败,代表服务器本身有问题,回头看日志。
第三步,把范围缩到最小。 换一个最简单的参数、一个最小的文件,能过就逐步加回去。这一步很笨,但几乎每次有效——大部分问题不是「坏了」,而是某个输入触发了没写好的分支。
这三步的共同点是:每次只改变一个变数。 一边改设置一边改参数,就算最后通了,你也不知道是哪一步通的。
回到最开始那个问题:怎么敢把钥匙交出去?
我的答案不是「找一个很安全的服务器」,而是三条自己守得住的规矩。
规矩一:一次只加一个服务器。 加完就跑一次 Inspector,确认能力列表、试一次呼叫。一次加三个,出问题连是哪个在捣乱都不知道。
规矩二:设置档里不放长期有效的密钥。 环境变数写在客户端设置里,本质上就是明文;设置档同步到云端或丢进版本库,等于把密钥一起送出去。能换短期凭证就换,不能就至少别让它进版本库。
规矩三:破坏性的工具单独开。 删档、改数据库、发送对外讯息这一类,能拆就拆成另一个服务器,平时不启用。真要用的时候再开,用完关掉——这比任何弹窗都可靠。
做完这三条,那个审批弹窗就不再是每次盲目按掉的干扰,而是一道你真的看得懂、也真的会拒绝的门。
权限这件事说到底并不复杂:能给一个抽屉就别给一整层楼,能让它读就别让它写,能每次问就别开永远允许。 剩下的,交给 Inspector 和日志。
工具推荐随身机器人(新用户免费试用 7 天)
照着做卡住的地方——服务器起不来、设置贴上去没反应、日志看半天看不出所以然——不用自己闷头查一下午。随身机器人可以直接帮你看报错、给你排查顺序,新用户免费试用 7 天。
下一篇预告: 换一台新电脑,半天重建整套工作环境——把 MCP 设置、专案知识和常用问法攒成一个可携带的入门包,复制过去就能开工。
业州愚公 | SY 视野(sylogs.com)原创内容,转载请注明出处。
编辑评论 / Editor's Note
这个事件凸显了人工智慧系统在实际应用中可能遇到的问题和挑战,尤其是在权限管理和使用者沟通方面。使用者在操作AI系统时,需要对系统的权限和限制有清晰的理解,以避免意外的结果。同时,这也反映出AI系统的设计和使用指南需要更加完善和易于理解。