它的全部优势可以写成一行:N 乘 M 变成 N 加 M。 3 乘 4 只省 42%,10 乘 30 省掉 87%——价值随规模长,不随功能长。 所以规模小的时候用 MCP 是绕远路,这话得说在前面。
前两节讲了案例和历史,这一节换算账。 顺便把 MCP 和 Function Calling、OpenAPI 摆在一起,说清它们不在同一层。 最后给三张场景清单:哪类活适合接 MCP,哪类不该接。
一、先把账算一遍
假设有 N 个宿主、M 个服务。各写各的,要写 N 乘 M 份适配; 走 MCP,写 M 个 Server,宿主那边照协议连,一份不用写。 合计下来是 M 加 N。省下的比例就是 1 减去 (M+N) 除以 (N*M)。 3 个宿主配 4 个服务:12 份变 7 份,省 42%。这个数不好看,所以小规模的时候不该硬上 MCP。
10 个宿主配 30 个服务:300 份变 40 份,省 87%。同一套约定,规模差三倍,收益差一倍。 这也是为什么这东西先在平台侧火起来,而不是先在个人开发者手里火:平台天生就是多宿主、多服务。
二、它和 Function Calling 不在同一层
这两件事经常被混着说,其实分工很清楚。 Function Calling 解决的是「模型怎么把『我要调某个函数』这句话说出来」,格式由模型厂商定, 你有几个函数就注册几份定义。 MCP 解决的是「说出来之后,去哪儿调、怎么调、调完怎么回」。
所以它们不冲突,还能叠着用:宿主把 MCP 的工具表翻译成自己家的 Function Calling 格式,再交给模型。 演示第三段就是这件事的缩影。 一句话记:Function Calling 管「说」,MCP 管「接」。
三、四种接法,各自卡在哪一层
把常见的四种摆出来,差别一眼就清楚。
| 接法 | 谁定格式 | 换个宿主 | 换个服务 |
|---|---|---|---|
| 直接写死 | 你自己 | 重写 | 重写 |
| Function Calling | 模型厂商 | 照它的格式重写 | 加一份定义 |
| OpenAPI | 接口作者 | 宿主得支持 OpenAPI | 写一份 yaml |
| MCP | 协议本身 | 照协议连 | 写一个 Server |
OpenAPI 那一行值得多说一句:它跟 MCP 长得很像,都是一份自描述的接口清单。 区别在面向对象不同。OpenAPI 面向的是会写代码的人,MCP 面向的是会调工具的模型。 前者要你读文档拼请求,后者要模型自己看着描述选工具。
所以 MCP 的 schema 里,description 字段的位置比 OpenAPI 重要得多——那句话是写给模型看的, 第 3 章会讲它被投毒之后有多危险。
四、三个核心优势,按可靠性排序
第一,接口统一。同一份工具表,任何宿主都读得懂。这一条最硬,因为它不依赖任何一方的配合。 第二,能力可插拔。加一个工具不用动宿主,Server 推一条通知就行。 这一条依赖宿主愿意实现那个通知,所以打了点折扣。 第三,生态可复用。别人写好的 Server 你能直接用。 这一条最软——目录站上很多 Server 半年没更新,装上跑不起来是常事。
这三条按「不需要别人配合」排序。第一条自己就能实现,第三条要看别人脸色。 【判断一个优势靠不靠得住,就问一句:这件事需不需要第三方配合。】
五、什么时候不该用
只接一个服务、只用一个宿主,用 MCP 是多绕一层。中间多了一个进程、一套报文、一处可能出错的地方。 能力是固定的、一辈子不变的那种,写死更省事。省下的不是代码量,是心智负担。 需要极致低延迟的场景,也先别上。 演示里握手要 500 毫秒(解释器启动),每次往返 0.15 毫秒——单次调用比直接函数调用贵两个数量级。
还有一类最容易被忽略:要精确控制每一次调用的场景。走 MCP 之后,调不调、调几次由模型决定, 你只能看日志。 典型应用场景可以归成三堆:一是跨平台复用同一批能力,二是让非开发者也能给自己的助手加能力, 三是把内部系统包一层给 AI 用。第 8 章往后的九个案例,基本都落在第三堆里。
六、动手 Demo:N 乘 M 变成 N 加 M
四组规模各算一遍,看省下的比例怎么变。 然后把同一条工具定义装进两个不同宿主的形状里,看变的是什么、不变的是什么。
for n, m in [(3, 4), (4, 6), (6, 10), (10, 30)]:
hard = n * m # 各写各的
mcp = n + m # 写 Server + 照协议连
print(n, 'x', m, hard, mcp, '%d%%' % round((1 - mcp / hard) * 100))
# 同一条工具定义,装进两个宿主各自的形状
tool = {'name': 'weather.forecast',
'description': '查某城市某天的天气',
'inputSchema': {'type': 'object',
'properties': {'city': {'type': 'string'},
'day': {'type': 'string'}},
'required': ['city', 'day']}}
host_a = {'name': tool['name'], 'input_schema': tool['inputSchema']}
host_b = {'type': 'function',
'function': {'name': tool['name'],
'parameters': tool['inputSchema']}}
实跑输出:
--------------------------------------------------------------------
N 乘 M 变成 N 加 M
--------------------------------------------------------------------
① 先数一遍
--------------------------------------------------------------------
| 宿主 × 服务 | 各写各的 | 走 MCP | 少写 |
|---|---:|---:|---:|
| 3 × 4 | 12 | 7 | 省 42% |
| 4 × 6 | 24 | 10 | 省 58% |
| 6 × 10 | 60 | 16 | 省 73% |
| 10 × 30 | 300 | 40 | 省 87% |
3 乘 4 省得不多,10 乘 30 省掉 87%。【MCP 的价值随规模长,不随功能长。】
只接一个服务、只用一个宿主的人,用 MCP 反而是多绕一层。这话得说在前面。
② 四种接法,差在哪一层
--------------------------------------------------------------------
| 接法 | 谁定格式 | 换个宿主 | 换个服务 |
|---|---|---|---|
| 直接写死 | 你自己 | 重写 | 重写 |
| Function Calling | 模型厂商 | 照它的格式重写 | 加一份定义 |
| OpenAPI | 接口作者 | 宿主得支持 OpenAPI | 写一份 yaml |
| MCP | 协议本身 | 照协议连 | 写一个 Server |
Function Calling 和 MCP 不是一回事,也不冲突:前者是「模型怎么说出要调什么」,
后者是「说出来之后,去哪儿调、怎么调」。【它们在不同层。】
③ 同一份表,两个宿主各自装
--------------------------------------------------------------------
服务端吐出来的一条工具定义,长这样:
{
"name": "weather.forecast",
"description": "查某城市某天的天气",
"inputSchema": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "城市名"
},
"day": {
"type": "string",
"description": "今天/明天/后天"
}
},
"required": [
"city",
"day"
],
"additionalProperties": false
}
}
宿主 A 把它装进自己的形状(字段叫 input_schema):
{"name": "weather.forecast", "input_schema": {...}}
宿主 B 把它装成另一种(套一层 function,字段叫 parameters):
{"type": "function", "function": {"name": ..., "parameters": {...}}}
外层字段名两处不同,可里面装的 schema 一个字都没改。
【这就是「标准接口」的全部含义:变的是包装,不变的是内容。】
它保证的不是「功能更强」,是「不用为第二个宿主再干一遍」。
④ 一句话说清 MCP 是什么
--------------------------------------------------------------------
一个约定:把「能做什么」写成一张表(name + description + inputSchema),
用 JSON-RPC 2.0 收发,走 stdio 或 HTTP。就这些。
剩下的全是这句话的推论:既然只有一张表,谁都能读;既然只有一种报文,谁都能发。
! 下面十章都是在这句话上加东西:加安全、加调试、加部署、加九个案例。
①第一张表四行,看最后那一列的走势就够了:42、58、73、87。 规模每翻一倍,省下的比例往上涨一截,但涨得越来越慢。 ②3 乘 4 那一行只有 42%,这不是笔好买卖。 中间多了一个进程、一套报文、一处会出错的地方,换 42% 的代码量,很多项目不划算。 ③第二张表四行,讲的是四种接法卡在哪一层。 写死卡在宿主,Function Calling 卡在模型厂商,OpenAPI 卡在宿主支不支持,MCP 卡在协议本身。 ④第三段是本节最值得抄的一段:同一条工具定义,装进两个宿主的形状,外层字段名一个叫 input_schema、 一个叫 parameters,里面装的 schema 一个字没改。 ⑤【变的是包装,不变的是内容】——这就是「标准接口」的全部含义。 它保证的不是功能更强,是不用为第二个宿主再干一遍。
30 秒实验
- 把演示第一段加上 (2, 2) 和 (20, 50) 两组。哪一组的省下比例最低,为什么。
- 用一句话说清 Function Calling 和 MCP 各自管哪一段。说不清就再读一遍那张四行的表。
- 想一个你手上「只接一个服务、只用一个宿主」的场景。判断一下值不值得上 MCP。
常见误区
- 「MCP 比 Function Calling 先进。」两者不在同一层,一个管怎么说,一个管怎么接,能叠着用。
- 「用了 MCP 性能更好。」中间多一个进程、多一轮报文,单次调用比直接函数调用贵得多。 它省的是维护成本,不是延迟。
- 「规模小也该上 MCP,反正早晚要用。 」3 乘 4 只省 42%,先写死,等宿主或服务涨到两位数再抽出来,成本更低。
自测三问(点开对答案)
1. 10 个宿主、30 个服务,走 MCP 能省多少? —— 各写各的是 300 份,MCP 是 30 加 10 等于 40 份,省 87%。 2. Function Calling 和 MCP 各管哪一段? —— 前者管模型怎么把「我要调什么」说出来,格式由厂商定;后者管说出来之后去哪儿调、怎么调。 3. 三个核心优势里,哪一个最不依赖别人配合? —— 接口统一。它只要协议本身在就成立; 能力可插拔要宿主实现通知,生态可复用要看别人的 Server 还维护不维护。优势算完了,从下一章开始拆内部。 第 2 章会把 Host、Client、Server 三个角色摆开,再讲一条报文怎么从这头走到那头。
- ☐ (本篇完,下一篇 2.1 MCP 的基本功能)