MCP 是什么?为什么 Function Call 之后还需要它

MCP 是什么?为什么 Function Call 之后还需要它

本文以 OpenClaw 开源源码为例

(基于 2026.6.2 版本),结合实际代码说明 MCP 的工作原理和定位。

涉及源码路径均可在仓库中直接查阅。

如果你看过上一篇 Function Call 是什么?LLM 如何学会使用工具,应该已经

知道 LLM 怎么"用工具"了:开发者把工具的 JSON Schema 塞进请求,模型决定

调哪个、传什么参数,代码负责真正执行。

那为什么 2024 年 Anthropic 又搞了一个叫 MCP(Model Context Protocol)

的东西?它跟 Function Call 是同一个东西吗?还是说 Function Call 不够用?

本文回答这两个问题。


从一个老问题说起

先看一个跟 AI 没关系的故事。

2016 年微软在做 VSCode 的时候,碰到一个头疼的事:

scss 复制代码
  编辑器(M 个)         语言(N 种)
  ┌────────────┐      ┌──────────┐
  │ VSCode     │ ↔↔↔↔ │ Python   │
  │ Vim        │ ↔↔↔↔ │ Go       │
  │ Emacs      │ ↔↔↔↔ │ TypeScript│
  │ Sublime    │ ↔↔↔↔ │ Rust     │
  │ JetBrains  │ ↔↔↔↔ │ Java     │
  └────────────┘      └──────────┘

每个编辑器都要给每种语言写一遍"hover 显示类型"、"跳转到定义"、

"查找所有引用"、"实时报错"...M 个编辑器 × N 种语言 = M × N 份

重复实现。这显然不可持续。

微软的解法是 LSP(Language Server Protocol) :把语言能力抽出来

变成一个独立的服务器进程,编辑器跟服务器用一套标准协议通信:

javascript 复制代码
  ┌────────┐    LSP    ┌──────────────┐
  │ VSCode │ ←──JSON-RPC→│ tsserver     │  ← TypeScript
  └────────┘            └──────────────┘
  ┌────────┐            ┌──────────────┐
  │ Vim    │ ←──────────│ rust-analyzer│  ← Rust
  └────────┘            └──────────────┘

现在变成 M + N:每个编辑器实现一次 LSP client,每种语言实现一次

LSP server。rust-analyzer 一份能给所有支持 LSP 的编辑器用。

记住这个故事。


AI 工具集成的同样问题

现在回到 2024 年。当时已经有不少 AI 应用支持 Function Call,但每个

应用都在重复造轮子:

scss 复制代码
  AI 应用(M 个)         工具(N 种)
  ┌────────────────┐   ┌──────────────┐
  │ Claude Desktop │ ↔↔↔│ 读文件        │
  │ ChatGPT App    │ ↔↔↔│ 查数据库      │
  │ Cursor         │ ↔↔↔│ 调 GitHub API │
  │ Codex          │ ↔↔↔│ 操作 Notion   │
  │ 你的 agent     │ ↔↔↔│ 控制浏览器    │
  └────────────────┘   └──────────────┘

每个 AI 应用都要给每种工具写一遍 Function Call 的接入代码:

读文件、调 API、解析响应、错误处理。M × N 又来了。

你想要的是这样:把"读文件"这个能力写一次,Claude Desktop、Cursor、

你的 agent 都能用。

Anthropic 给的答案就是 MCP------它对 AI 工具集成做的事,跟 LSP 对
编辑器语言支持做的事是一模一样的


MCP 是什么

一句话:MCP 是一个开放协议,让任何 AI 应用都能用一套标准的方式
接入任何外部工具。

具体来说,MCP 定义了两个角色之间怎么通信:

  • Host (主机):跑 LLM 的那一侧------Claude Desktop、Cursor、你写的
    agent 框架
  • Server (服务器):提供工具的那一侧------可以是本地子进程
    (读文件、控浏览器),也可以是远端 HTTP 服务(Notion 集成、
    GitHub 集成)

通信用 JSON-RPC 2.0,跑在 stdio 或 HTTP 之上。MCP server 暴露三类能力:

  • tools:模型可以调的函数
  • resources:可读的数据源
  • prompts:可被引用的预制 prompt 模板

我们今天主要讲 tools。

跟 LSP 长得很像对吧?stdio + JSON-RPC + 服务器自报能力 ------某种意义上

MCP 就是 LSP 思路在 AI 时代的延续。


但是......Function Call 不是已经能干这件事了吗?

这是新手最容易卡住的地方。我们仔细看看。

Function Call 是什么层面

Function Call 是模型和应用之间的约定 :模型怎么"申请"调用一个

函数,应用怎么"执行"它再把结果回传。

sql 复制代码
┌─────────────────────────────┐
│  LLM (Claude / GPT 等)      │
│  输出 tool_use 请求         │ ← Function Call 层
└──────────────┬──────────────┘
               │
               ▼
┌─────────────────────────────┐
│  你的应用                   │
│  接到请求,跑函数,回传结果  │
└─────────────────────────────┘

这一层只回答了"模型怎么表达调用意图"。它没规定函数本身是怎么
来的、是谁写的、怎么真正执行

MCP 是什么层面

MCP 是应用和工具实现之间的协议 :这个函数从哪儿来,代码在哪个

进程里跑,参数怎么传过去。

sql 复制代码
┌─────────────────────────────┐
│  LLM                        │
│  输出 tool_use 请求         │ ← Function Call 层(没变)
└──────────────┬──────────────┘
               │
               ▼
┌─────────────────────────────┐
│  你的应用                   │
│  - 收 tool_use              │
│  - 转成 MCP 调用            │
└──────────────┬──────────────┘
               │ JSON-RPC over stdio/HTTP
               ▼
┌─────────────────────────────┐
│  MCP server (子进程/远端)   │  ← MCP 层
│  跑函数,回结果             │
└─────────────────────────────┘

注意:模型完全不知道 MCP 的存在 。它看到的还是一个普通的 tool 定义,

还是按 Function Call 的方式输出 tool_use。MCP 是中间那一层应用代码

的事------它把 tool 的"实现"从应用进程里挪到了独立的 MCP server 里。

一个类比

  • Function Call ≈ "我要打个电话"------这是个抽象动作
  • MCP ≈ "电话怎么拨通对方公司的总机,问到分机号,再接到具体的人"
    ------这是个具体协议

或者:

  • Function Call ≈ 函数调用这个概念本身
  • MCP ≈ gRPC / OpenAPI------让函数能跨进程跨语言被发现和调用的具体协议

MCP 不替代 Function Call,它给 Function Call 加了一个"工具供应链"。


MCP 实际带来了什么

讲了这么多概念,看看实际效果。

1. 工具一次写好,所有 AI 应用都能用

@modelcontextprotocol/server-filesystem 是社区的一个 MCP server,

让 AI 能读文件、列目录、搜文件。装一次:

bash 复制代码
npx @modelcontextprotocol/server-filesystem ~/Documents

然后 Claude Desktop、Cursor、OpenClaw 都能直接用上它,不用各自实现

一遍文件操作工具。这就是 M + N 而不是 M × N。

2. 工具的提供者跟 AI 应用作者解耦

Notion 想给 AI 助手提供集成?以前要等每家 AI 应用主动接入,或者发

SDK 给开发者集成。现在 Notion 自己跑一个 MCP server,任何支持 MCP

的应用都能用。

3. 工具能跨语言、跨进程

MCP server 可以是 Python、Go、Rust、任何能讲 JSON-RPC 的语言写的。

你的 AI 应用是 Node.js,但工具实现可以是 Python------只要双方说 MCP 就行。

4. 故障隔离

MCP server 跑在独立进程里(或者远端),一个 server 崩了不会拖死整个

AI 应用。可以单独重启、单独限流、单独配置超时。


看看 OpenClaw 怎么做的

OpenClaw(一个开源 AI agent 框架)的代码可以当作 MCP 的具体落地示例。

MCP server 怎么"加进来"

OpenClaw 不去网络扫描发现 MCP server,全靠声明式 config。两个来源:

1. 用户写在 ~/.openclaw/openclaw.json 里:

perl 复制代码
{
  "mcp": {
    "servers": {
      "filesystem": {
        "command": "npx",
        "args": ["@modelcontextprotocol/server-filesystem", "/home/user"]
      },
      "github": {
        "url": "https://mcp.github.com",
        "transport": "streamable-http",
        "auth": "oauth"
      }
    }
  }
}

2. 插件作者预置: 装一个 OpenClaw plugin 时,它可能自带几个

MCP server 配置(src/plugins/bundle-mcp.ts)。

两个来源在 src/agents/bundle-mcp-config.ts 里合并,用户 config
能覆盖 plugin 默认

什么时候真的连接 MCP server?

这是个有意思的设计选择。OpenClaw 的策略:进程启动时不连接、每次
模型轮次开始时连接

为什么?因为模型必须在请求里就看到全部 tool 才能决定调哪个,所以

连接不能拖到模型真的调用某个 tool 时再做(那时候 tool 列表都没

组装好)。但又没必要在 OpenClaw 启动时就把所有 MCP server 都拉起来

(可能配了 20 个,这次对话其实只用 2 个)。

折衷点是 agent 一轮模型请求开始时 :这时候必须把所有 MCP server

都 spawn、tools/list、拿到工具目录,然后把工具塞进发给模型的

tool 列表里。

scss 复制代码
// 简化版,真实代码在 src/agents/embedded-agent-runner/run/attempt.ts
const mcpRuntime = await materializeBundleMcpToolsForRun({...});
// 这里 MCP server 已经 spawn 完了,tool 也都拿到了

const tools = [...nativeTools, ...mcpRuntime.tools];
// 发给模型
sendRequest({ tools, ... });

模型看到的是什么

一个扁平的 tool 数组,跟 native tool 长得完全一样:

css 复制代码
[  { "name": "Read",                    "description": "...", "input_schema": {...} },  { "name": "Bash",                    "description": "...", "input_schema": {...} },  { "name": "filesystem__read_file",   "description": "...", "input_schema": {...} },  { "name": "github__list_issues",     "description": "...", "input_schema": {...} }]

注意 filesystem__read_file 这种 serverName__toolName 的命名是为了

防止重名。模型完全不知道哪些来自 MCP、哪些是 OpenClaw 写死的;它只

根据 description 和 schema 做语义匹配,挑一个最合适的。

模型调用时发生什么

模型返回 tool_use: filesystem__read_file,OpenClaw 在 tool 列表里

找到对应条目,它的 execute 函数会调 client.callTool("read_file", input),

通过早就建立好的 stdio 连接发给 MCP server,server 跑完返回结果,

OpenClaw 再把结果回传给模型。

整个过程模型一无所知------它只觉得自己"调了个工具,得到了结果"。


关键澄清:几个常见误解

误解 1:"MCP 是给模型用的协议"

不是。MCP 是给应用用的协议。 模型那一侧永远是 Function Call,

看到的就是普通 tool 定义。MCP 是应用怎么"获取这些 tool 定义、怎么

真正执行 tool"的事。

误解 2:"用了 MCP 就不用 Function Call 了"

Function Call 永远在用。 MCP server 提供的 tool,最终还是要包装

成 Function Call 的格式发给模型。两者不是 A 替代 B,而是 A 之上又加

了一层 B。

误解 3:"native tool 落后了,MCP 才是未来"

不一定。 跟应用深度耦合的工具(比如 OpenClaw 的 ReadBash)

做成 native tool 启动快、故障少、能直接用 host 内部能力;MCP 的优势在

跨应用复用可独立分发。两者各有适用场景。

OpenClaw 自己就同时有 native tool、plugin tool、MCP tool,模型看见

的是同一个扁平列表,不区分。


那 MCP 现在能用来干什么

一些实际的应用方向:

  • 本地工具 :文件系统、Git、Docker、SQLite------@modelcontextprotocol/server-*
    系列已经有不少现成的
  • 远端 SaaS 集成 :Notion、Linear、Slack、GitHub------越来越多 SaaS
    在做官方 MCP server
  • 企业内部工具 :把内部数据库查询、运维脚本包装成 MCP server,
    团队所有 AI 助手都能用
  • 跨工具协作 :同一个 agent 同时接文件系统 + GitHub + Notion 的 MCP server,
    可以读本地代码、查 issue、写文档

总结

回到开头的问题:MCP 跟 Function Call 是什么关系?

vbnet 复制代码
Function Call:模型 ←→ 应用 之间怎么调函数
MCP:           应用 ←→ 工具 之间怎么提供函数

Function Call 解决"模型怎么用工具"。MCP 解决"工具从哪儿来、怎么跨应用

复用"。两者各管一层,组合起来才是完整的故事。

LSP 当年解决了编辑器 × 语言的 M × N 问题,让 rust-analyzer 这种

高质量语言服务器能服务所有编辑器。MCP 试图解决 AI 应用 × 工具的同样

问题,让一个 MCP server 能服务所有 AI 助手。

它能不能像 LSP 那样成为事实标准,还要看生态------但思路是清晰的:

把工具实现从单个应用里抽出来,变成可复用的独立组件


想深入了解?

  • MCP 规范:modelcontextprotocol.io

  • 看 OpenClaw 怎么实现 MCP client 的:

    • 配置和发现机制
    • 何时连接、catalog 怎么暴露给模型
    • 缓存、失效、安全细节

    这部分在 OpenClaw 仓库的 src/agents/agent-bundle-mcp-*.ts,

    以及 notes/mcp-client-internals.md

相关推荐
宋哥转AI1 小时前
Spring AI Alibaba实战:通过MCP协议串联Graph编排与RAG检索
agent·mcp
付玉祥1 小时前
Agent Loop 的运行流程:从单体循环到三阶段 Pipeline
agent
卡卡罗特AI1 小时前
Codex复刻小米MiMoCode官网,丝滑融入项目,只需要3步!保姆级教程!
人工智能·ai编程
sunneo1 小时前
本周 AI 新动态精选(2026.06.08–06.14)
人工智能·aigc·ai编程·ai写作·ai-native
码流怪侠1 小时前
【GitHub】 Headroom 深度解析:AI Agent 上下文压缩层的完整技术拆解
人工智能·github·agent
leeyi2 小时前
Tool 组件:让 Agent 学会「动手」的统一接口
aigc·agent·ai编程
啾啾Fun2 小时前
【LLM应用可靠性】3-Agent 事故响应:当 AI 系统行为异常时的 SRE Runbook
ai·llm·agent·生产应用
Rain5092 小时前
2.3. 安全配置:环境变量与 API 密钥管理
前端·人工智能·后端·安全·ai·node.js·ai编程