专栏第6篇 :第五篇我们讲了工具调用的四层防御机制,以及 Function Calling 如何让 LLM 输出结构化的工具调用意图。但 Function Calling 有一个局限:它是模型厂商的私有协议------OpenAI 的格式、Anthropic 的格式、Google 的格式各不相同。如果我想让同一个工具被不同模型调用,难道要为每个模型写一套适配代码?今天我们要聊的 MCP(Model Context Protocol),正是为了解决这个"N 个模型 × M 个工具"的碎片化问题。
目录
- [一、Function Calling 的局限性:N 个模型 × M 个工具](#一、Function Calling 的局限性:N 个模型 × M 个工具)
- [二、MCP 是什么?](#二、MCP 是什么?)
- [三、MCP 的三层架构:Host / Client / Server](#三、MCP 的三层架构:Host / Client / Server)
- [四、MCP 与 Function Calling 的本质区别](#四、MCP 与 Function Calling 的本质区别)
- [五、传输类型:stdio vs HTTP](#五、传输类型:stdio vs HTTP)
- [六、开发一个 MCP Server](#六、开发一个 MCP Server)
- [七、MCP 在 Agent 生态中的定位](#七、MCP 在 Agent 生态中的定位)
- 八、总结
一、Function Calling 的局限性:N 个模型 × M 个工具
第五篇我们讲了 Function Calling:LLM 根据工具描述,输出结构化的 JSON,表示"需要调用哪个工具、传什么参数"。这套机制在单个模型内部工作得很好,但当你需要对接多个模型时,问题就来了。
1.1 每个模型的 Function Calling 格式都不一样
OpenAI 的格式:
{"name": "get_weather", "arguments": {"city": "北京"}}
Anthropic 的格式:
{"tool": "get_weather", "input": {"city": "北京"}}
Google 的格式:
{"function": {"name": "get_weather"}, "parameters": {"city": "北京"}}
同样的工具、同样的参数,三个模型输出三种不同的 JSON 结构。这意味着:
- 每对接一个新模型,就要重写一套解析逻辑
- 工具开发者要为每个模型维护不同的描述格式
- 切换模型时,工具代码要跟着改
1.2 工具的"碎片化"
假设你开发了一个"查天气"工具:
给 OpenAI 用 → 按 OpenAI 的 Schema 格式写描述
给 Claude 用 → 按 Anthropic 的格式写描述
给本地模型用 → 可能根本不支持 Function Calling,得用 ReAct 文本解析
结果:同一个工具,写了 3 套不同的"说明书"
这就是 Function Calling 的核心痛点:它是模型厂商的私有协议,不是跨模型的通用标准。
二、MCP 是什么?
MCP(Model Context Protocol) 是 Anthropic 于 2024 年底推出的开放协议,目标是标准化 LLM 与外部系统(工具、数据、提示词)的交互方式。
💡 一句话理解:Function Calling 是"某个模型怎么表达调用意图",MCP 是"外部系统怎么向模型暴露能力"的通用标准。
2.1 为什么叫"Model Context Protocol"?
拆解一下这个名字:
- Model(模型):指 LLM,是协议的"消费者"
- Context(上下文):指模型需要的外部信息------不只是工具,还包括数据、提示词等
- Protocol(协议):标准化的交互规则
"Context"这个词是关键。MCP 的原始设计意图不只是"工具调用协议",而是要让外部系统能向模型提供各种形式的"上下文":
| MCP 能力类型 | 说明 | 示例 |
|---|---|---|
| Tools(工具) | 可执行的函数,模型可以调用 | 天气查询、计算器、文件操作 |
| Resources(资源) | 只读的数据,模型可以读取 | 数据库记录、知识库内容、文件内容 |
| Prompts(提示词) | 预定义的 Prompt 模板 | 代码审查模板、翻译模板、总结模板 |
也就是说,MCP 最初想解决的是一个更宏大的问题:如何让外部系统(数据源、工具集、模板库)以标准化的方式,成为 LLM 的"上下文提供者"。
2.2 为什么现在主要被当作"工具调用协议"?
虽然 MCP 设计了三类能力,但目前生态中90% 的使用场景都是 Tools。原因很简单:
- Tools 是最刚性的需求:Agent 必须能执行操作,否则只是聊天机器人
- Resources 部分被 RAG 替代:很多数据检索场景直接用向量数据库 + RAG 实现
- Prompts 部分被系统提示词替代:预定义模板通常直接写在代码里
💡 现状:MCP 的协议框架支持三种能力,但生态发展不均衡,Tools 一枝独秀。不过随着生态成熟,Resources 和 Prompts 的使用也在增长。
2.3 MCP 的核心思想:解耦
- 工具开发者:只按 MCP 标准写一次能力描述和实现
- 模型/Agent 开发者:只按 MCP 标准对接一次协议
- 结果:任何支持 MCP 的模型,都能使用任何支持 MCP 的外部系统
#mermaid-svg-q6xkJG73zA5jCQAq{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-q6xkJG73zA5jCQAq .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-q6xkJG73zA5jCQAq .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-q6xkJG73zA5jCQAq .error-icon{fill:#552222;}#mermaid-svg-q6xkJG73zA5jCQAq .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-q6xkJG73zA5jCQAq .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-q6xkJG73zA5jCQAq .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-q6xkJG73zA5jCQAq .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-q6xkJG73zA5jCQAq .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-q6xkJG73zA5jCQAq .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-q6xkJG73zA5jCQAq .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-q6xkJG73zA5jCQAq .marker{fill:#333333;stroke:#333333;}#mermaid-svg-q6xkJG73zA5jCQAq .marker.cross{stroke:#333333;}#mermaid-svg-q6xkJG73zA5jCQAq svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-q6xkJG73zA5jCQAq p{margin:0;}#mermaid-svg-q6xkJG73zA5jCQAq .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-q6xkJG73zA5jCQAq .cluster-label text{fill:#333;}#mermaid-svg-q6xkJG73zA5jCQAq .cluster-label span{color:#333;}#mermaid-svg-q6xkJG73zA5jCQAq .cluster-label span p{background-color:transparent;}#mermaid-svg-q6xkJG73zA5jCQAq .label text,#mermaid-svg-q6xkJG73zA5jCQAq span{fill:#333;color:#333;}#mermaid-svg-q6xkJG73zA5jCQAq .node rect,#mermaid-svg-q6xkJG73zA5jCQAq .node circle,#mermaid-svg-q6xkJG73zA5jCQAq .node ellipse,#mermaid-svg-q6xkJG73zA5jCQAq .node polygon,#mermaid-svg-q6xkJG73zA5jCQAq .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-q6xkJG73zA5jCQAq .rough-node .label text,#mermaid-svg-q6xkJG73zA5jCQAq .node .label text,#mermaid-svg-q6xkJG73zA5jCQAq .image-shape .label,#mermaid-svg-q6xkJG73zA5jCQAq .icon-shape .label{text-anchor:middle;}#mermaid-svg-q6xkJG73zA5jCQAq .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-q6xkJG73zA5jCQAq .rough-node .label,#mermaid-svg-q6xkJG73zA5jCQAq .node .label,#mermaid-svg-q6xkJG73zA5jCQAq .image-shape .label,#mermaid-svg-q6xkJG73zA5jCQAq .icon-shape .label{text-align:center;}#mermaid-svg-q6xkJG73zA5jCQAq .node.clickable{cursor:pointer;}#mermaid-svg-q6xkJG73zA5jCQAq .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-q6xkJG73zA5jCQAq .arrowheadPath{fill:#333333;}#mermaid-svg-q6xkJG73zA5jCQAq .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-q6xkJG73zA5jCQAq .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-q6xkJG73zA5jCQAq .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-q6xkJG73zA5jCQAq .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-q6xkJG73zA5jCQAq .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-q6xkJG73zA5jCQAq .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-q6xkJG73zA5jCQAq .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-q6xkJG73zA5jCQAq .cluster text{fill:#333;}#mermaid-svg-q6xkJG73zA5jCQAq .cluster span{color:#333;}#mermaid-svg-q6xkJG73zA5jCQAq div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-q6xkJG73zA5jCQAq .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-q6xkJG73zA5jCQAq rect.text{fill:none;stroke-width:0;}#mermaid-svg-q6xkJG73zA5jCQAq .icon-shape,#mermaid-svg-q6xkJG73zA5jCQAq .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-q6xkJG73zA5jCQAq .icon-shape p,#mermaid-svg-q6xkJG73zA5jCQAq .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-q6xkJG73zA5jCQAq .icon-shape .label rect,#mermaid-svg-q6xkJG73zA5jCQAq .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-q6xkJG73zA5jCQAq .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-q6xkJG73zA5jCQAq .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-q6xkJG73zA5jCQAq :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 没有MCP的碎片化世界
私有格式
私有格式
ReAct文本
OpenAI
天气工具A
Claude
天气工具B
本地模型
天气工具C
#mermaid-svg-hIAka3kEtXTyHa8V{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-hIAka3kEtXTyHa8V .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-hIAka3kEtXTyHa8V .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-hIAka3kEtXTyHa8V .error-icon{fill:#552222;}#mermaid-svg-hIAka3kEtXTyHa8V .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-hIAka3kEtXTyHa8V .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-hIAka3kEtXTyHa8V .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-hIAka3kEtXTyHa8V .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-hIAka3kEtXTyHa8V .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-hIAka3kEtXTyHa8V .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-hIAka3kEtXTyHa8V .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-hIAka3kEtXTyHa8V .marker{fill:#333333;stroke:#333333;}#mermaid-svg-hIAka3kEtXTyHa8V .marker.cross{stroke:#333333;}#mermaid-svg-hIAka3kEtXTyHa8V svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-hIAka3kEtXTyHa8V p{margin:0;}#mermaid-svg-hIAka3kEtXTyHa8V .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-hIAka3kEtXTyHa8V .cluster-label text{fill:#333;}#mermaid-svg-hIAka3kEtXTyHa8V .cluster-label span{color:#333;}#mermaid-svg-hIAka3kEtXTyHa8V .cluster-label span p{background-color:transparent;}#mermaid-svg-hIAka3kEtXTyHa8V .label text,#mermaid-svg-hIAka3kEtXTyHa8V span{fill:#333;color:#333;}#mermaid-svg-hIAka3kEtXTyHa8V .node rect,#mermaid-svg-hIAka3kEtXTyHa8V .node circle,#mermaid-svg-hIAka3kEtXTyHa8V .node ellipse,#mermaid-svg-hIAka3kEtXTyHa8V .node polygon,#mermaid-svg-hIAka3kEtXTyHa8V .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-hIAka3kEtXTyHa8V .rough-node .label text,#mermaid-svg-hIAka3kEtXTyHa8V .node .label text,#mermaid-svg-hIAka3kEtXTyHa8V .image-shape .label,#mermaid-svg-hIAka3kEtXTyHa8V .icon-shape .label{text-anchor:middle;}#mermaid-svg-hIAka3kEtXTyHa8V .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-hIAka3kEtXTyHa8V .rough-node .label,#mermaid-svg-hIAka3kEtXTyHa8V .node .label,#mermaid-svg-hIAka3kEtXTyHa8V .image-shape .label,#mermaid-svg-hIAka3kEtXTyHa8V .icon-shape .label{text-align:center;}#mermaid-svg-hIAka3kEtXTyHa8V .node.clickable{cursor:pointer;}#mermaid-svg-hIAka3kEtXTyHa8V .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-hIAka3kEtXTyHa8V .arrowheadPath{fill:#333333;}#mermaid-svg-hIAka3kEtXTyHa8V .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-hIAka3kEtXTyHa8V .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-hIAka3kEtXTyHa8V .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-hIAka3kEtXTyHa8V .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-hIAka3kEtXTyHa8V .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-hIAka3kEtXTyHa8V .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-hIAka3kEtXTyHa8V .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-hIAka3kEtXTyHa8V .cluster text{fill:#333;}#mermaid-svg-hIAka3kEtXTyHa8V .cluster span{color:#333;}#mermaid-svg-hIAka3kEtXTyHa8V div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-hIAka3kEtXTyHa8V .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-hIAka3kEtXTyHa8V rect.text{fill:none;stroke-width:0;}#mermaid-svg-hIAka3kEtXTyHa8V .icon-shape,#mermaid-svg-hIAka3kEtXTyHa8V .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-hIAka3kEtXTyHa8V .icon-shape p,#mermaid-svg-hIAka3kEtXTyHa8V .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-hIAka3kEtXTyHa8V .icon-shape .label rect,#mermaid-svg-hIAka3kEtXTyHa8V .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-hIAka3kEtXTyHa8V .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-hIAka3kEtXTyHa8V .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-hIAka3kEtXTyHa8V :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 有MCP的统一世界
MCP标准
MCP标准
MCP标准
OpenAI
天气工具
Claude
本地模型
三、MCP 的三层架构:Host / Client / Server
MCP 采用三层架构,但需要先明确一点:这三者是逻辑角色,不是三个独立的物理进程。一个应用可以同时承担多个角色。
#mermaid-svg-8AB96aAkn16HvuVZ{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-8AB96aAkn16HvuVZ .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-8AB96aAkn16HvuVZ .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-8AB96aAkn16HvuVZ .error-icon{fill:#552222;}#mermaid-svg-8AB96aAkn16HvuVZ .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-8AB96aAkn16HvuVZ .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-8AB96aAkn16HvuVZ .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-8AB96aAkn16HvuVZ .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-8AB96aAkn16HvuVZ .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-8AB96aAkn16HvuVZ .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-8AB96aAkn16HvuVZ .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-8AB96aAkn16HvuVZ .marker{fill:#333333;stroke:#333333;}#mermaid-svg-8AB96aAkn16HvuVZ .marker.cross{stroke:#333333;}#mermaid-svg-8AB96aAkn16HvuVZ svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-8AB96aAkn16HvuVZ p{margin:0;}#mermaid-svg-8AB96aAkn16HvuVZ .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-8AB96aAkn16HvuVZ .cluster-label text{fill:#333;}#mermaid-svg-8AB96aAkn16HvuVZ .cluster-label span{color:#333;}#mermaid-svg-8AB96aAkn16HvuVZ .cluster-label span p{background-color:transparent;}#mermaid-svg-8AB96aAkn16HvuVZ .label text,#mermaid-svg-8AB96aAkn16HvuVZ span{fill:#333;color:#333;}#mermaid-svg-8AB96aAkn16HvuVZ .node rect,#mermaid-svg-8AB96aAkn16HvuVZ .node circle,#mermaid-svg-8AB96aAkn16HvuVZ .node ellipse,#mermaid-svg-8AB96aAkn16HvuVZ .node polygon,#mermaid-svg-8AB96aAkn16HvuVZ .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-8AB96aAkn16HvuVZ .rough-node .label text,#mermaid-svg-8AB96aAkn16HvuVZ .node .label text,#mermaid-svg-8AB96aAkn16HvuVZ .image-shape .label,#mermaid-svg-8AB96aAkn16HvuVZ .icon-shape .label{text-anchor:middle;}#mermaid-svg-8AB96aAkn16HvuVZ .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-8AB96aAkn16HvuVZ .rough-node .label,#mermaid-svg-8AB96aAkn16HvuVZ .node .label,#mermaid-svg-8AB96aAkn16HvuVZ .image-shape .label,#mermaid-svg-8AB96aAkn16HvuVZ .icon-shape .label{text-align:center;}#mermaid-svg-8AB96aAkn16HvuVZ .node.clickable{cursor:pointer;}#mermaid-svg-8AB96aAkn16HvuVZ .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-8AB96aAkn16HvuVZ .arrowheadPath{fill:#333333;}#mermaid-svg-8AB96aAkn16HvuVZ .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-8AB96aAkn16HvuVZ .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-8AB96aAkn16HvuVZ .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-8AB96aAkn16HvuVZ .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-8AB96aAkn16HvuVZ .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-8AB96aAkn16HvuVZ .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-8AB96aAkn16HvuVZ .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-8AB96aAkn16HvuVZ .cluster text{fill:#333;}#mermaid-svg-8AB96aAkn16HvuVZ .cluster span{color:#333;}#mermaid-svg-8AB96aAkn16HvuVZ div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-8AB96aAkn16HvuVZ .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-8AB96aAkn16HvuVZ rect.text{fill:none;stroke-width:0;}#mermaid-svg-8AB96aAkn16HvuVZ .icon-shape,#mermaid-svg-8AB96aAkn16HvuVZ .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-8AB96aAkn16HvuVZ .icon-shape p,#mermaid-svg-8AB96aAkn16HvuVZ .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-8AB96aAkn16HvuVZ .icon-shape .label rect,#mermaid-svg-8AB96aAkn16HvuVZ .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-8AB96aAkn16HvuVZ .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-8AB96aAkn16HvuVZ .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-8AB96aAkn16HvuVZ :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Host 宿主应用
如 Agent 平台、IDE
Client
MCP 客户端
Host 内部的连接模块
Server
MCP 服务端
独立进程
工具/数据/能力
💡 关键理解 :Client 不是独立于 Host 的第三方应用,而是Host 内部负责连接 Server 的模块。就像浏览器(Host)内部有 HTTP 客户端(Client)用来连接 Web 服务器。
3.1 Host(宿主应用)
Host 是最终用户直接交互的终端应用,比如:
- 一个 Agent 平台(如 Claude Desktop、Cursor、openclaw、QoderWork等)
- 一个用 LangChain 搭建的聊天机器人 Web 服务
- 一个 IDE 插件或桌面客户端
💡 区分框架和 Host :LangChain、LlamaIndex 是框架(用来构建 Agent 的工具库),不是 Host。用 LangChain 写出来的那个"能跟用户聊天的应用"才是 Host。
Host 负责:
- 提供用户交互界面
- 管理内部 MCP Client 的生命周期
- 协调不同 Server 之间的工具调用
- 向用户展示最终答案
Host 本身也包含 Client:一个 Agent 平台作为 Host,其内部必然有 Client 模块来连接外部 Server。两者是"整体与部分"的关系,不是并列关系。
3.2 Client(MCP 客户端)
Client 是 Host 内部负责与 Server 通信的模块,每个 Client 实例对应一个 Server。
💡 关系澄清 :一个 Host 内部可以有多个 Client(连接不同的 Server),一个 Server 也可以被多个 Client 连接(比如一个公共的天气查询 Server 被多个用户的 Agent 平台同时调用)。标准实现是一个 Client 实例只连接一个 Server。
Client 负责:
- 与 Server 建立连接(stdio 或 HTTP)
- 将 Host 的请求转换为 MCP 标准消息
- 将 Server 的响应返回给 Host
python
# Client 的核心职责:协议转换
class MCPClient:
def __init__(self, server_command: str):
# 启动 Server 进程,建立连接
self.server = subprocess.Popen(server_command, ...)
def list_tools(self):
# 向 Server 请求工具列表
return self.send_request("tools/list")
def call_tool(self, tool_name: str, arguments: dict):
# 调用 Server 上的某个工具
return self.send_request("tools/call", {"name": tool_name, "arguments": arguments})
3.3 Server(MCP 服务端)
Server 是实际提供能力的"供应商",每个 Server 专注一类能力:
| Server 类型 | 提供的能力 | 示例 |
|---|---|---|
| 工具 Server | 可执行的函数 | 天气查询、计算器、文件操作 |
| 资源 Server | 只读的数据访问 | 数据库查询、知识库检索 |
| 提示词 Server | 预定义的 Prompt 模板 | 代码审查模板、翻译模板 |
Server 的核心职责:
- 按 MCP 标准暴露自己的能力列表
- 接收 Client 的请求并执行
- 返回标准化的响应
四、MCP 与 Function Calling 的本质区别
⚠️ 限定范围:以下对比仅针对**工具调用(Tools)**这一交集领域。MCP 还支持 Resources(资源读取)和 Prompts(提示词模板),Function Calling 则不涉及这两类能力。
| 维度 | Function Calling | MCP |
|---|---|---|
| 协议层级 | 模型输出层(LLM 怎么表达意图) | 工具描述层(工具怎么定义自己) |
| 标准归属 | 各模型厂商私有 | Anthropic 主导的开放标准 |
| 工具位置 | 工具代码在 Agent 内部 | 工具代码在独立的 Server 进程中 |
| 工具发现 | 启动时静态注册 | 运行时动态发现(Server 随时可增删) |
| 跨模型 | 每模型一套适配 | 一次适配,多模型通用 |
| 隔离性 | 工具和 Agent 同进程 | 工具和 Agent 隔离(Server 独立运行) |
4.1 最关键的区别:协议层级
Function Calling 解决的是"LLM 怎么告诉系统它需要调用工具"------这是模型输出格式的问题。
MCP 解决的是"工具怎么描述自己、系统怎么发现工具、怎么调用工具"------这是工具接口标准的问题。
两者不是替代关系,而是互补关系:
#mermaid-svg-0kTHLvj1OM4QXfph{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-0kTHLvj1OM4QXfph .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-0kTHLvj1OM4QXfph .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-0kTHLvj1OM4QXfph .error-icon{fill:#552222;}#mermaid-svg-0kTHLvj1OM4QXfph .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-0kTHLvj1OM4QXfph .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-0kTHLvj1OM4QXfph .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-0kTHLvj1OM4QXfph .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-0kTHLvj1OM4QXfph .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-0kTHLvj1OM4QXfph .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-0kTHLvj1OM4QXfph .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-0kTHLvj1OM4QXfph .marker{fill:#333333;stroke:#333333;}#mermaid-svg-0kTHLvj1OM4QXfph .marker.cross{stroke:#333333;}#mermaid-svg-0kTHLvj1OM4QXfph svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-0kTHLvj1OM4QXfph p{margin:0;}#mermaid-svg-0kTHLvj1OM4QXfph .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-0kTHLvj1OM4QXfph .cluster-label text{fill:#333;}#mermaid-svg-0kTHLvj1OM4QXfph .cluster-label span{color:#333;}#mermaid-svg-0kTHLvj1OM4QXfph .cluster-label span p{background-color:transparent;}#mermaid-svg-0kTHLvj1OM4QXfph .label text,#mermaid-svg-0kTHLvj1OM4QXfph span{fill:#333;color:#333;}#mermaid-svg-0kTHLvj1OM4QXfph .node rect,#mermaid-svg-0kTHLvj1OM4QXfph .node circle,#mermaid-svg-0kTHLvj1OM4QXfph .node ellipse,#mermaid-svg-0kTHLvj1OM4QXfph .node polygon,#mermaid-svg-0kTHLvj1OM4QXfph .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-0kTHLvj1OM4QXfph .rough-node .label text,#mermaid-svg-0kTHLvj1OM4QXfph .node .label text,#mermaid-svg-0kTHLvj1OM4QXfph .image-shape .label,#mermaid-svg-0kTHLvj1OM4QXfph .icon-shape .label{text-anchor:middle;}#mermaid-svg-0kTHLvj1OM4QXfph .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-0kTHLvj1OM4QXfph .rough-node .label,#mermaid-svg-0kTHLvj1OM4QXfph .node .label,#mermaid-svg-0kTHLvj1OM4QXfph .image-shape .label,#mermaid-svg-0kTHLvj1OM4QXfph .icon-shape .label{text-align:center;}#mermaid-svg-0kTHLvj1OM4QXfph .node.clickable{cursor:pointer;}#mermaid-svg-0kTHLvj1OM4QXfph .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-0kTHLvj1OM4QXfph .arrowheadPath{fill:#333333;}#mermaid-svg-0kTHLvj1OM4QXfph .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-0kTHLvj1OM4QXfph .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-0kTHLvj1OM4QXfph .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-0kTHLvj1OM4QXfph .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-0kTHLvj1OM4QXfph .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-0kTHLvj1OM4QXfph .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-0kTHLvj1OM4QXfph .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-0kTHLvj1OM4QXfph .cluster text{fill:#333;}#mermaid-svg-0kTHLvj1OM4QXfph .cluster span{color:#333;}#mermaid-svg-0kTHLvj1OM4QXfph div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-0kTHLvj1OM4QXfph .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-0kTHLvj1OM4QXfph rect.text{fill:none;stroke-width:0;}#mermaid-svg-0kTHLvj1OM4QXfph .icon-shape,#mermaid-svg-0kTHLvj1OM4QXfph .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-0kTHLvj1OM4QXfph .icon-shape p,#mermaid-svg-0kTHLvj1OM4QXfph .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-0kTHLvj1OM4QXfph .icon-shape .label rect,#mermaid-svg-0kTHLvj1OM4QXfph .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-0kTHLvj1OM4QXfph .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-0kTHLvj1OM4QXfph .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-0kTHLvj1OM4QXfph :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 用户提问
LLM 推理
Function Calling
LLM输出JSON表示
需要调用天气工具
MCP Client
按MCP协议调用Server
MCP Server
实际执行天气查询
结果返回LLM
LLM生成最终回答
实际流程:
- LLM 通过 Function Calling 输出"需要调用天气工具"
- Agent 框架(Host)把这个意图交给 MCP Client
- MCP Client 按 MCP 协议调用对应的 MCP Server
- MCP Server 执行实际的天气查询
- 结果返回,LLM 生成最终回答
4.2 为什么 MCP 需要独立的 Server 进程?
传统方式(无MCP):
Agent 代码 ──直接调用──→ 天气API
Agent 代码 ──直接调用──→ 数据库查询
Agent 代码 ──直接调用──→ 文件操作
问题:工具和 Agent 强耦合,代码混在一起
MCP 方式:
Agent 代码 ──MCP协议──→ 天气Server(独立进程)
Agent 代码 ──MCP协议──→ 数据库Server(独立进程)
Agent 代码 ──MCP协议──→ 文件Server(独立进程)
优势:
1. 工具和 Agent 解耦,可以独立开发、独立部署
2. 工具崩溃不影响 Agent
3. 不同语言实现的工具可以共存(Python Agent + Node.js Server)
五、传输类型:stdio vs HTTP
MCP 支持两种传输方式,适用于不同场景:
5.1 stdio(标准输入输出)
原理:Host 启动 Server 作为子进程,通过标准输入输出进行 JSON-RPC 通信。
Host 进程
└── 启动 Server 子进程(如 python weather_server.py)
└── 通过 stdin 发送请求
└── 通过 stdout 接收响应
适用场景:
- 本地开发、调试
- Server 和 Host 在同一台机器上
- 需要进程隔离(Server 崩溃不影响 Host)
- Agent 平台从 MCP 市场/广场安装的大部分插件(平台读取配置中的命令,在本地启动 Server 子进程)
优点:
- 简单,不需要网络配置
- 天然进程隔离
- 适合本地工具(文件操作、本地命令)
缺点:
- 只能本地通信
- 每个 Server 占用一个进程
5.2 HTTP(Streamable HTTP)
原理:Server 作为独立的服务运行,Host 通过 HTTP 请求与其通信。
Host 进程 ──HTTP请求──→ MCP Server(独立服务)
可以是本地服务或远程服务
消息格式 :HTTP 传输可以是普通的请求-响应模式 (一次 POST 发请求,一次返回完整 JSON),也可以使用 SSE(Server-Sent Events) 或 JSON Stream 进行流式通信(服务器实时推送增量数据)。具体用哪种取决于 Server 的实现和场景需求。
适用场景:
- Server 部署在远程服务器上
- 多个 Host 共享同一个 Server
- 需要高可用、负载均衡
优点:
- 支持远程部署
- 多个 Host 可以共享 Server
- 可以使用现有的 HTTP 基础设施(网关、鉴权等)
缺点:
- 需要网络配置
- 增加了延迟
- 需要处理连接管理和错误恢复
5.3 如何选择?
| 场景 | 推荐传输 | 原因 |
|---|---|---|
| 本地开发调试 | stdio | 简单,即开即用 |
| 本地文件/命令工具 | stdio | 本地资源访问,不需要网络 |
| 团队共享工具 | HTTP | 统一部署,多 Host 共享 |
| 云端服务 | HTTP | 远程访问,弹性伸缩 |
| 高安全要求 | stdio | 进程隔离,不暴露网络端口 |
六、开发一个 MCP Server
开发 MCP Server 的核心是:按 MCP 标准实现几个固定的接口。
6.1 Server 必须实现的接口
python
from mcp.server import Server
from mcp.types import Tool, TextContent
# 1. 创建 Server
server = Server("weather-server")
# 2. 注册工具列表接口(让 Client 知道你有什么工具)
@server.list_tools()
async def list_tools() -> list[Tool]:
return [
Tool(
name="get_weather",
description="查询指定城市的天气信息",
inputSchema={
"type": "object",
"properties": {
"city": {"type": "string", "description": "城市名称"}
},
"required": ["city"]
}
)
]
# 3. 注册工具调用接口(实际执行工具)
@server.call_tool()
async def call_tool(name: str, arguments: dict) -> list[TextContent]:
if name == "get_weather":
city = arguments["city"]
result = await query_weather_api(city) # 实际的天气查询逻辑
return [TextContent(type="text", text=result)]
raise ValueError(f"未知工具: {name}")
# 4. 启动 Server(stdio 模式)
if __name__ == "__main__":
server.run(transport="stdio")
6.2 Server 的"配置文件"
除了代码,MCP Server 还需要一个描述文件(通常是 package.json 或 mcp.json),告诉 Host 怎么连接它。
stdio 模式的配置(Host 在本地启动 Server 子进程):
json
{
"name": "weather-server",
"version": "1.0.0",
"command": "python",
"args": ["weather_server.py"],
"env": {
"WEATHER_API_KEY": "your-api-key"
}
}
HTTP 模式的配置(Host 连接一个已运行的远程/本地服务):
json
{
"name": "weather-server",
"version": "1.0.0",
"url": "http://localhost:3000/mcp",
"headers": {
"Authorization": "Bearer token"
}
}
如何区分两种配置?
| 特征 | stdio 模式 | HTTP 模式 |
|---|---|---|
| 配置中的关键字段 | command + args |
url |
| Server 由谁启动 | Host 启动子进程 | 已独立运行,Host 只负责连接 |
| 适用场景 | 本地工具、MCP 市场插件 | 远程服务、团队共享 Server |
Host 读取配置后,根据有无 command 字段判断用 stdio 还是 HTTP 方式连接。
6.3 工具的发现与调用流程
#mermaid-svg-hagihm7raeBrRIzm{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-hagihm7raeBrRIzm .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-hagihm7raeBrRIzm .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-hagihm7raeBrRIzm .error-icon{fill:#552222;}#mermaid-svg-hagihm7raeBrRIzm .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-hagihm7raeBrRIzm .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-hagihm7raeBrRIzm .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-hagihm7raeBrRIzm .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-hagihm7raeBrRIzm .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-hagihm7raeBrRIzm .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-hagihm7raeBrRIzm .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-hagihm7raeBrRIzm .marker{fill:#333333;stroke:#333333;}#mermaid-svg-hagihm7raeBrRIzm .marker.cross{stroke:#333333;}#mermaid-svg-hagihm7raeBrRIzm svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-hagihm7raeBrRIzm p{margin:0;}#mermaid-svg-hagihm7raeBrRIzm .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-hagihm7raeBrRIzm .cluster-label text{fill:#333;}#mermaid-svg-hagihm7raeBrRIzm .cluster-label span{color:#333;}#mermaid-svg-hagihm7raeBrRIzm .cluster-label span p{background-color:transparent;}#mermaid-svg-hagihm7raeBrRIzm .label text,#mermaid-svg-hagihm7raeBrRIzm span{fill:#333;color:#333;}#mermaid-svg-hagihm7raeBrRIzm .node rect,#mermaid-svg-hagihm7raeBrRIzm .node circle,#mermaid-svg-hagihm7raeBrRIzm .node ellipse,#mermaid-svg-hagihm7raeBrRIzm .node polygon,#mermaid-svg-hagihm7raeBrRIzm .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-hagihm7raeBrRIzm .rough-node .label text,#mermaid-svg-hagihm7raeBrRIzm .node .label text,#mermaid-svg-hagihm7raeBrRIzm .image-shape .label,#mermaid-svg-hagihm7raeBrRIzm .icon-shape .label{text-anchor:middle;}#mermaid-svg-hagihm7raeBrRIzm .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-hagihm7raeBrRIzm .rough-node .label,#mermaid-svg-hagihm7raeBrRIzm .node .label,#mermaid-svg-hagihm7raeBrRIzm .image-shape .label,#mermaid-svg-hagihm7raeBrRIzm .icon-shape .label{text-align:center;}#mermaid-svg-hagihm7raeBrRIzm .node.clickable{cursor:pointer;}#mermaid-svg-hagihm7raeBrRIzm .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-hagihm7raeBrRIzm .arrowheadPath{fill:#333333;}#mermaid-svg-hagihm7raeBrRIzm .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-hagihm7raeBrRIzm .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-hagihm7raeBrRIzm .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-hagihm7raeBrRIzm .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-hagihm7raeBrRIzm .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-hagihm7raeBrRIzm .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-hagihm7raeBrRIzm .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-hagihm7raeBrRIzm .cluster text{fill:#333;}#mermaid-svg-hagihm7raeBrRIzm .cluster span{color:#333;}#mermaid-svg-hagihm7raeBrRIzm div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-hagihm7raeBrRIzm .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-hagihm7raeBrRIzm rect.text{fill:none;stroke-width:0;}#mermaid-svg-hagihm7raeBrRIzm .icon-shape,#mermaid-svg-hagihm7raeBrRIzm .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-hagihm7raeBrRIzm .icon-shape p,#mermaid-svg-hagihm7raeBrRIzm .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-hagihm7raeBrRIzm .icon-shape .label rect,#mermaid-svg-hagihm7raeBrRIzm .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-hagihm7raeBrRIzm .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-hagihm7raeBrRIzm .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-hagihm7raeBrRIzm :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 调用执行
发现工具
初始化
stdio模式
HTTP模式
Host启动
读取配置
启动Server子进程
Client连接
请求tools/list
返回工具列表
传给LLM
LLM决定调用
发送tools/call
Server执行
结果返回LLM
生成回答
七、MCP 在 Agent 生态中的定位
把 MCP 放在整个 Agent 技术栈中看,它的位置如下:
#mermaid-svg-XxrTpjZYVWRn03c9{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-XxrTpjZYVWRn03c9 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-XxrTpjZYVWRn03c9 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-XxrTpjZYVWRn03c9 .error-icon{fill:#552222;}#mermaid-svg-XxrTpjZYVWRn03c9 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-XxrTpjZYVWRn03c9 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-XxrTpjZYVWRn03c9 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-XxrTpjZYVWRn03c9 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-XxrTpjZYVWRn03c9 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-XxrTpjZYVWRn03c9 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-XxrTpjZYVWRn03c9 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-XxrTpjZYVWRn03c9 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-XxrTpjZYVWRn03c9 .marker.cross{stroke:#333333;}#mermaid-svg-XxrTpjZYVWRn03c9 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-XxrTpjZYVWRn03c9 p{margin:0;}#mermaid-svg-XxrTpjZYVWRn03c9 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-XxrTpjZYVWRn03c9 .cluster-label text{fill:#333;}#mermaid-svg-XxrTpjZYVWRn03c9 .cluster-label span{color:#333;}#mermaid-svg-XxrTpjZYVWRn03c9 .cluster-label span p{background-color:transparent;}#mermaid-svg-XxrTpjZYVWRn03c9 .label text,#mermaid-svg-XxrTpjZYVWRn03c9 span{fill:#333;color:#333;}#mermaid-svg-XxrTpjZYVWRn03c9 .node rect,#mermaid-svg-XxrTpjZYVWRn03c9 .node circle,#mermaid-svg-XxrTpjZYVWRn03c9 .node ellipse,#mermaid-svg-XxrTpjZYVWRn03c9 .node polygon,#mermaid-svg-XxrTpjZYVWRn03c9 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-XxrTpjZYVWRn03c9 .rough-node .label text,#mermaid-svg-XxrTpjZYVWRn03c9 .node .label text,#mermaid-svg-XxrTpjZYVWRn03c9 .image-shape .label,#mermaid-svg-XxrTpjZYVWRn03c9 .icon-shape .label{text-anchor:middle;}#mermaid-svg-XxrTpjZYVWRn03c9 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-XxrTpjZYVWRn03c9 .rough-node .label,#mermaid-svg-XxrTpjZYVWRn03c9 .node .label,#mermaid-svg-XxrTpjZYVWRn03c9 .image-shape .label,#mermaid-svg-XxrTpjZYVWRn03c9 .icon-shape .label{text-align:center;}#mermaid-svg-XxrTpjZYVWRn03c9 .node.clickable{cursor:pointer;}#mermaid-svg-XxrTpjZYVWRn03c9 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-XxrTpjZYVWRn03c9 .arrowheadPath{fill:#333333;}#mermaid-svg-XxrTpjZYVWRn03c9 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-XxrTpjZYVWRn03c9 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-XxrTpjZYVWRn03c9 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-XxrTpjZYVWRn03c9 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-XxrTpjZYVWRn03c9 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-XxrTpjZYVWRn03c9 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-XxrTpjZYVWRn03c9 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-XxrTpjZYVWRn03c9 .cluster text{fill:#333;}#mermaid-svg-XxrTpjZYVWRn03c9 .cluster span{color:#333;}#mermaid-svg-XxrTpjZYVWRn03c9 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-XxrTpjZYVWRn03c9 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-XxrTpjZYVWRn03c9 rect.text{fill:none;stroke-width:0;}#mermaid-svg-XxrTpjZYVWRn03c9 .icon-shape,#mermaid-svg-XxrTpjZYVWRn03c9 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-XxrTpjZYVWRn03c9 .icon-shape p,#mermaid-svg-XxrTpjZYVWRn03c9 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-XxrTpjZYVWRn03c9 .icon-shape .label rect,#mermaid-svg-XxrTpjZYVWRn03c9 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-XxrTpjZYVWRn03c9 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-XxrTpjZYVWRn03c9 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-XxrTpjZYVWRn03c9 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 用户
Host Agent应用
LLM推理层
感知→规划→行动→反思
Function Calling
LLM输出调用意图
MCP Client
MCP Server A
天气查询
MCP Server B
数据库
MCP Server C
文件操作
外部API/本地资源
各层职责:
| 层级 | 代表技术 | 职责 |
|---|---|---|
| 推理层 | ReAct、Reflexion | 决定做什么、怎么做 |
| 意图表达层 | Function Calling | LLM 表达"需要调用什么工具" |
| 协议层 | MCP | 标准化工具的注册、发现、调用 |
| 执行层 | MCP Server | 实际执行工具逻辑 |
| 资源层 | API、数据库、文件 | 最终的数据和操作对象 |
MCP 的价值:
- 对工具开发者:写一次,到处用(任何支持 MCP 的 Agent 都能调用)
- 对 Agent 开发者:接一次,用所有工具(不需要为每个工具写适配代码)
- 对用户:Agent 的能力范围随 MCP Server 生态扩大而自动扩展
八、总结
本文从 Function Calling 的局限性出发,梳理了:
- 碎片化问题:N 个模型 × M 个工具,Function Calling 格式各不相同
- MCP 的定位:标准化的工具接口协议,解耦工具开发与 Agent 开发
- 三层架构:Host(应用)→ Client(Host 内部连接 Server 的模块)→ Server(能力提供)
- 与 Function Calling 的关系:互补而非替代------Function Calling 是 LLM 的"意图表达",MCP 是工具的"接口标准"
- 传输类型:stdio(本地、简单、隔离)vs HTTP(远程、共享、可扩展)
- Server 开发 :实现
list_tools和call_tool两个核心接口 - 生态价值:工具一次开发,多模型/多 Agent 复用
参考资源:
- Anthropic MCP Specification(官方协议文档)
- MCP SDK Documentation(Python/TypeScript SDK)
- 《Model Context Protocol: A Standard for Connecting AI Assistants to Data》(Anthropic, 2024)