🐎 第6章 海纳百川:MCP
📄 一句话概括

MCP 出问题的时候,现象往往只有「不行」两个字。 所以要先知道该看哪一处:五个故障,各有各的第一现场。 再加一笔输出的账:同一个查询,五行返回六十四 token,一千行返回一万三千。 上限不写在服务器里,就写在账单上。

📝 本章和前面几章的关系

前十节讲怎么把 MCP 接对,这一节讲它不对的时候怎么查。 这一节也是第 6 章的最后一篇,本章小结并在末尾。

一、五个故障,各自先看什么

连不上(服务器进程起不来):先手动跑一遍启动命令。命令本身报错,配置再对也没用。 连上了但工具列不出来:看 initialize 的回应。能力没声明 tools,后面什么都不会有。 调工具超时:看服务器日志和超时设置。任务太久或者没刷新缓冲,现象都是「卡住」。

工具名不存在:对比 tools/list 和实际调用。名字大小写、版本不一致,都会这样。 返回内容太大把窗口撑爆:数返回的 token。这多半是没加行数上限。 五个里三个是协议层的问题:起不来、列不出、名字对不上。 它们都能靠「手动跑一遍、把请求回应打出来」定位。

二、调试的两个动作

动作一:手动起服务器。把它当普通命令行程序跑起来,从键盘敲一行 JSON 进去,看它回什么。 这一步能排掉大部分「配置对不对」的疑问——因为配置的作用就是「把这条命令跑起来」。 动作二:把请求和回应都记下来。一行请求、一行回应,配上时间戳,写在文件里。

出问题时翻这个文件,比猜快十倍。 这两个动作和 5.10 节钩子那三板斧是一个思路:看不见的东西,必须有日志。

三、输出的账

演示里同一个查询三种行数:五行返回两百字符、六十四 token; 一百行四千零九十字符、一千二百九十三 token。 一千行是四万一千九百九十字符、一万三千一百九十八 token——一次调用就把窗口吃掉大半。 而这只是「查一下有多少条」。模型的真实意图往往是「看看有没有数据」,五行就够了。

所以工具侧必须带上限:默认五到二十行,需要更多让模型显式要。这个上限写在服务器里,不写在提示词里。

四、常见问题清单

「工具能列出来但一调就报错」——先看参数 schema 对不对,再看服务器有没有处理这个分支。 「有时候行有时候不行」——多半是状态问题:连接被复用了、或者上一次调用没结束。 「慢」——先分清是握手慢还是执行慢。握手慢就去查连接复用,执行慢就去查那条 SQL 或者那个接口。

「换台机器就不行」——路径、环境变量、版本,三样里必有一样。先比这三样,别比代码。 清单的价值不在覆盖全部,在于给出「先看哪一处」的顺序。顺序对了,剩下的就是耐心。

五、本章小结

第 6 章讲 MCP。十一节收在一句话上:它把「M 乘 N 的对接」变成了「M 加 N 的适配」。 6.1 标准化:边际成本从乘变成一,工具越多越划算。 6.2 协议:一行一个 JSON,三个方法就能转起来,id 负责配对。

6.3 传输:stdio 是进程内的工具,HTTP 是网络上的服务。 6.4 配置:能进版本库的放项目级,带密钥的放项目本地。 6.5 连数据库:只读、限行数、schema 要短。

6.6 自定义服务器:三十行能跑,难的是「暴露哪几个工具」。 6.7 生态:装之前算两笔账,常驻 token 和权限面。 6.8 安全:不能靠模型自觉,重心在服务器那端收窄。

6.9 与技能协作:MCP 给手,技能给菜谱。 6.10 企业部署:形态跟着「密钥要集中到什么程度」走。 6.11 调试:看不见的东西必须有日志,输出必须有上限。

六、动手 Demo:五个故障逐个诊断,再算一次输出的账

MCP 出问题的时候,现象往往只有「不行」两个字。所以要先知道该看哪一处。 五个故障逐个给第一现场,再算一笔输出的账。

FAULT = [(u"连不上:服务器进程起不来", u"先手动跑一遍启动命令"),
         (u"连上了但工具列不出来", u"看 initialize 的回应")]

for n in (5, 100, 1000):
    txt = json.dumps([{"id": i, "city": u"宜昌", "amount": 100 + i} for i in range(n)],
                     ensure_ascii=False)

实跑输出:

--------------------------------------------------------------------
五个故障逐个诊断,再算一次输出的账
--------------------------------------------------------------------

  MCP 出问题的时候,现象往往只有「不行」两个字。所以要先知道该看哪一处。

  ① 五个故障,各自先看什么
  --------------------------------------------------------------------
| 现象 | 先看什么 | 常见原因 |
|---|---|---|
| 连不上:服务器进程起不来 | 先手动跑一遍启动命令 | 命令本身报错 |
| 连上了但工具列不出来 | 看 initialize 的回应 | 能力没声明 tools |
| 调工具超时 | 看服务器日志和超时设置 | 任务太久或没刷新缓冲 |
| 工具名不存在 | 对比 tools/list 和实际调用 | 名字大小写或版本不一致 |
| 返回内容太大把窗口撑爆 | 数返回的 token | 没加行数上限 |

  五个里三个是「协议层」的问题:起不来、列不出、名字对不上。
  它们都能靠「手动跑一遍服务器、把请求回应打出来」定位。

  ② 调试的两个动作
  --------------------------------------------------------------------
  动作一:手动起服务器。把它当普通命令行程序跑起来,从键盘敲一行 JSON 进去,看它回什么。
  这一步能排掉大部分「配置对不对」的疑问。
  动作二:把请求和回应都记下来。一行请求、一行回应,配上时间戳,写在文件里。
  出问题时翻这个文件,比猜快十倍。
  这两个动作和 5.10 节钩子那三板斧是一个思路:看不见的东西,必须有日志。

  ③ 输出的账:从五行到一千行
  --------------------------------------------------------------------
| 返回行数 | 字符数 | token |
|---|---:|---:|
| 5 行 | 200 | 64 |
| 100 行 | 4090 | 1293 |
| 1000 行 | 41990 | 13198 |

  一千行的返回 13198 token——一次调用就把窗口吃掉大半。而这只是「查一下有多少条」。
  所以工具侧必须带上限:默认五到二十行,需要更多让模型显式要。
  这个上限写在服务器里,不写在提示词里。

  ④ 本章小结
  --------------------------------------------------------------------
  第 6 章讲 MCP。十一节收在一句话上:它把「M 乘 N 的对接」变成了「M 加 N 的适配」。
  6.1 标准化:边际成本从乘变成一,工具越多越划算。
  6.2 协议:一行一个 JSON,三个方法就能转起来,id 负责配对。
  6.3 传输:stdio 是进程内的工具,HTTP 是网络上的服务。
  6.4 配置:能进版本库的放项目级,带密钥的放项目本地。
  6.5 连数据库:只读、限行数、schema 要短。
  6.6 自定义服务器:三十行能跑,难的是「暴露哪几个工具」。
  6.7 生态:装之前算两笔账,常驻 token 和权限面。
  6.8 安全:不能靠模型自觉,重心在服务器那端收窄。
  6.9 与技能协作:MCP 给手,技能给菜谱。
  6.10 企业部署:形态跟着「密钥要集中到什么程度」走。
  6.11 调试:看不见的东西必须有日志,输出必须有上限。
  下一章讲多智能体协作:单个会话已经装不下的大活,怎么拆给几个会话同时干。

①五个故障里三个是协议层的问题:起不来、列不出、名字对不上。 它们都能靠「手动跑一遍服务器、把请求回应打出来」定位。 ②调试的两个动作:手动起服务器(把它当普通命令行程序跑,敲一行 JSON 进去看它回什么)、 把请求和回应连时间戳记下来。 这两个动作和 5.10 节钩子那三板斧是一个思路:看不见的东西,必须有日志。 ③输出的账:五行六十四 token、一百行一千二百九十三、一千行一万三千一百九十八。 一次调用就能把窗口吃掉大半,而这只是「查一下有多少条」。 所以工具侧必须带上限:默认五到二十行,需要更多让模型显式要。上限写在服务器里,不写在提示词里。

30 秒实验

  1. 把返回内容从三个字段加到八个字段,重跑第 ③ 步。一千行那一格涨到多少? 这说明「字段数」和「行数」哪个更该管?
  2. 把上限从五改成二十,重跑一遍。它在什么场景下是合适的?这个场景怎么判断?
  3. 拿一个你正在用的工具,把它的返回按「五行」截一次,看模型还能不能答对。 如果还能,原来的全量返回就是白花的。

常见误区

  1. 看到「连不上」就去改配置。先手动跑一遍启动命令,很多时候是命令本身报错。
  2. 不记请求和回应,靠现象猜。现象只有「不行」两个字,猜不出原因。
  3. 工具返回不设上限。一次查询一千行就能吃掉大半个窗口。
  4. 把「慢」当成一个问题。先分清是握手慢还是执行慢,两者的修法完全不同。
  5. 换台机器不行就去比代码。先比路径、环境变量、版本这三样。
自测三问(点开对答案) 1. 「连上了但工具列不出来」该先看哪儿? —— 看 initialize 的回应。服务器没在能力里声明 tools,后面就列不出来。 2. 调试 MCP 的两个基本动作是什么? —— 手动起服务器(敲一行 JSON 看它回什么)、把请求和回应连时间戳记下来。 3. 工具返回为什么要设行数上限? —— 因为一千行能到一万三千 token,一次调用就吃掉大半个窗口。而模型判断「有没有数据」几行就够。

第 6 章到这里收尾。下一章讲多智能体协作:单个会话已经装不下的大活,怎么拆给几个会话同时干。

相关笔记