Skip to content
Gains Summary
Main Navigation 首页 / Home
C++ 编程 / C++ Programming
系统与高性能 / Systems & Performance
Web 开发 / Web Development
人工智能 / Artificial Intelligence
工业软件 / Industrial Software
其他内容 / Other Topics
C++ 编程 / C++系统与性能 / SystemsWeb 开发 / Web人工智能 / AI工业软件 / Industrial

外观

Sidebar Navigation

← 人工智能 / Artificial Intelligence

智能体工程 / Agent Engineering

1. Agent 工程体系全景 / Agent Engineering System Overview

2. Function Calling - 让 LLM 具备行动能力 / Function Calling for Giving LLMs the Ability to Act

3. Agent 框架演进 - 从裸 SDK 到 LangGraph / The Evolution of Agent Frameworks from Raw SDKs to LangGraph

4. RAG 基础 - 让 Agent 拥有"知识" / Retrieval-Augmented Generation Fundamentals for Agent Knowledge

5. 记忆管理 - Agent 的大脑 / Memory Management as the Brain of an Agent

6. Agent 工作流 - 从单步到复杂的执行编排 / Agent Workflows from Single Steps to Complex Orchestration

7. 多 Agent 系统 - 多个 Agent 协作 / Multi-Agent Systems and Agent Collaboration

8. RAG 进阶 - 企业级知识库实战 / Advanced RAG for Enterprise Knowledge Bases

9. 真实 Agent 应用场景 / Real-World AI Agent Applications

10. Structured Output - 让 LLM 输出可控的结构化数据 / Structured Output for Controllable, Machine-Readable LLM Responses

11. Tools Design Best Practices - AI Agent 工具设计最佳实践 / Tools Design Best Practices for AI Agents

12. Agent 架构模式 - 从单 Agent 到多 Agent 的工程范式 / Agent Architecture Patterns

13. Agent Modes — 编程 Agent 的交互模式设计 / Designing Interaction Modes for Coding Agents

14. Agent Workflow 编排:从循环到持久化执行的演进

15. Context Engineering - 从 Prompt 设计到上下文编排 / Context Engineering: From Prompt Design to Context Orchestration

16. Agent 缓存工程:从 KV Cache、Prompt Cache 到语义缓存 / Agent Caching Engineering

17. Harness Engineering, Skills, and Loop Engineering — 从信任模型到验证系统 / From Trusting Models to Verifying Systems

18. MCP 协议 - AI 工具的"USB 接口" / Model Context Protocol for AI Tool Integration

19. Agent 评估与测试 — 如何衡量一个"不可预测"的系统 / Agent Evaluation and Testing — How to Measure an "Unpredictable" System

20. 安全沙箱 - Agent 的安全边界 / Secure Sandboxes as Agent Safety Boundaries

21. 权限与门卫 - Agent 的安全控制中枢 / Permissions and Policy Gates for Agent Control

22. API Key 管理与安全 - Agent 的密钥生命周期的管理 / API Key Lifecycle Management and Security for Agents

23. 提示词注入防护 - Agent 的防御前沿 / Prompt Injection Defense for AI Agents

24. 可观测性与调试 - Agent 运行的透明度保障 / Observability and Debugging for Transparent Agent Operations

25. 模型路由 - 让正确的模型做正确的事 / Model Routing for Matching Models to Tasks

26. OpenClaw 设计深度分析 - 为什么它让人觉得"活"了 / OpenClaw Design Analysis and the Illusion of Liveliness

27. Claude Code 泄露源码深度分析 - 512,000 行代码揭示的生产级 Agent 架构 / Claude Code Source Analysis and Production Agent Architecture

28. LobeChat 设计深度分析 - 全栈 Agent Chat 应用工程实践 / LobeChat Design Analysis and Full-Stack Agent Chat Engineering

29. 编程 Agent 全面对比:从 Claude Code 到 Pi 的设计哲学 / Coding Agents Comparison: Design Philosophies from Claude Code to Pi

30. 领域 Agent 的确定性工具编译与延迟执行——从自然语言规格到单次 CAE 提交

31. Agent 工程学习指南 / An AI Agent Engineering Learning Guide

本页目录

MCP 协议 - AI 工具的"USB 接口" / Model Context Protocol for AI Tool Integration ​

📅 创建时间:2026-07-28 🏷️ 标签:#MCP #ModelContextProtocol #ToolIntegration #Agent 📚 前置知识:[[01-function-calling]] [[00-agent-overview]]


📋 本章目标 ​

  • 理解 MCP 要解决的核心问题:N×M 集成困境
  • 掌握 MCP 的数据流:Client/Server 架构、Transport 层、JSON-RPC 消息
  • 理解 MCP 的四大核心概念:Resources、Tools、Prompts、Sampling
  • 能够从零构建一个简单的 MCP Server
  • 理解 MCP 与传统 Function Calling 的本质区别
  • 了解 MCP 的生态现状:哪些应用已经支持 MCP

第0部分:MCP 解决什么问题? ​

0.1 一个所有人都遇到过的困境 ​

假设你正在构建一个 AI 助手应用。用户问:"帮我查一下今天 GitHub 上 Python 项目的 trending,然后总结到 Notion 里。"

你的第一反应:这不难,我有 Function Calling。

┌───────────────────────────────────────────────────────────┐
│                    实现这个需求需要什么?                    │
├───────────────────────────────────────────────────────────┤
│                                                           │
│  1. 学习 GitHub API       →  OAuth、REST、rate limit     │
│  2. 学习 Notion API       →  token、blocks 格式、分页    │
│  3. 在代码里分别集成      →  两个完全不同的 SDK/认证方式   │
│  4. 写工具定义给 LLM       →  两个 tools 的 JSON Schema   │
│  5. 测试、调试、维护      →  每个 API 版本更新都得改     │
│                                                           │
│  这就两个工具。如果还要加:                                │
│  Slack、Gmail、数据库、文件系统、Jira、Google Drive...    │
│                                                           │
└───────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14

问题暴露出来了:每接入一个新工具,你就要写一套全新的集成代码。 你的 AI 应用和 N 个外部工具之间是 M 个 AI 应用 × N 个工具的排列组合。

┌───────────────────────────────────────────────────────────┐
│                    现状:N×M 困境                          │
├───────────────────────────────────────────────────────────┤
│                                                           │
│      AI App 1  ──→ GitHub API    (集成代码 A1)            │
│                 ──→ Notion API    (集成代码 A2)            │
│                 ──→ Slack API     (集成代码 A3)            │
│                 ──→ Gmail API     (集成代码 A4)            │
│                 ──→ Database      (集成代码 A5)            │
│                                                           │
│      AI App 2  ──→ GitHub API    (集成代码 B1)            │
│                 ──→ Notion API    (集成代码 B2)            │
│                 ──→ Slack API     (集成代码 B3)            │
│                 ──→ Gmail API     (集成代码 B4)            │
│                 ──→ Database      (集成代码 B5)            │
│                                                           │
│      每个组合 = 一次独立开发。                              │
│      5 个工具 × 5 个应用 = 25 套集成代码。                 │
│                                                           │
└───────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

0.2 MCP 的思路:把"集成"标准化 ​

MCP 的想法非常朴素——这个问题是不是听着很耳熟?

在 MCP 出现之前,计算机历史上有一个完全同构的问题:硬件外设的连接。在 USB 出现之前,每种外设都要单独写驱动:打印机驱动、扫描仪驱动、键盘驱动、鼠标驱动。每种设备的驱动程序都跟操作系统强绑定。USB 协议出现后,所有设备只要遵循 USB 标准,插上去就能用。

MCP 对 AI 工具做的事,和 USB 对硬件外设做的事完全一样:

┌───────────────────────────────────────────────────────────┐
│            MCP = AI 工具集成领域的 "USB 协议"              │
├───────────────────────────────────────────────────────────┤
│                                                           │
│  没有 USB 时:                                             │
│    每台电脑 + 每种外设 = 独立驱动                          │
│    Windows × N台打印机 × M台扫描仪 = 无数种组合            │
│                                                           │
│  有了 USB 后:                                             │
│    外设遵循 USB 标准 → 任何电脑都能识别                     │
│    N 台设备 + M 台电脑 → 1 套协议就够了                    │
│                                                           │
│  ─────────────────────────────────────────────────────    │
│                                                           │
│  没有 MCP 时:                                             │
│    每个 AI 应用 + 每个外部工具 = 独立集成                  │
│    Claude × Slack, GPT × Slack, Gemini × Slack            │
│           = 3 套不同的 Slack 集成代码                      │
│                                                           │
│  有了 MCP 后:                                             │
│    写一次 MCP Server(如 Slack Server)→ 所有 AI 应用      │
│    只要实现了 MCP Client,就能直接发现和调用 Slack          │
│                                                           │
│    N 个工具 + M 个 AI 应用 → 写 N 个 MCP Server 就够      │
│                                                           │
└───────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

0.3 一句话定义 ​

MCP(Model Context Protocol)是一个开放协议,标准化了 AI 应用与外部工具/数据源之间的通信方式。它让你只需要写一次工具集成,就能被任何实现了 MCP Client 的 AI 应用使用。

它由 Anthropic 在 2024 年 11 月开源发布,现在已成为 AI 工具集成领域的事实标准。


第1部分:MCP 的数据流 ​

1.1 整体架构 ​

MCP 采用经典的 Client-Server 架构:

┌───────────────────────────────────────────────────────────┐
│                    MCP 架构全景                            │
├───────────────────────────────────────────────────────────┤
│                                                           │
│  ┌──────────────┐         ┌──────────────────┐           │
│  │  AI 应用      │         │  外部工具/数据源   │           │
│  │  (Claude      │         │                  │           │
│  │   Desktop)    │         │  Slack API       │           │
│  │              │         │  GitHub API      │           │
│  │  充当 MCP    │←───────→│  文件系统         │           │
│  │  Client      │  MCP   │  数据库           │           │
│  │              │ 协议   │  ...              │           │
│  │  发起请求    │         │                  │           │
│  │  消费结果    │         │  充当 MCP Server  │           │
│  │              │         │  响应请求        │           │
│  └──────────────┘         └──────────────────┘           │
│                                                           │
│  关键:Client 和 Server 是解耦的。                        │
│  一个 Server 可以被多个不同的 Client 使用。               │
│  一个 Client 可以连接多个不同的 Server。                  │
│                                                           │
└───────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

1.2 Transport 层:消息怎么传输? ​

MCP 协议定义在应用层,传输层有两种标准方式:

┌───────────────────────────────────────────────────────────┐
│                    MCP Transport 层                        │
├───────────────────────────────────────────────────────────┤
│                                                           │
│  方式一:stdio(标准输入输出)                              │
│  ┌───────────────────────────────────────────────────┐   │
│  │ • Client 启动 Server 为子进程                       │   │
│  │ • 通过 stdin/stdout 交换 JSON-RPC 消息              │   │
│  │ • 适用于本地工具(如文件系统、本地数据库)            │   │
│  │ • 零网络开销,无需端口管理                           │   │
│  │                                                     │   │
│  │   Client ──spawn──→ Server (子进程)                 │   │
│  │   stdin  ←  JSON-RPC request   →  stdout           │   │
│  └───────────────────────────────────────────────────┘   │
│                                                           │
│  方式二:HTTP + SSE(Server-Sent Events)                  │
│  ┌───────────────────────────────────────────────────┐   │
│  │ • Server 作为 HTTP 服务运行,监听端口               │   │
│  │ • Client 通过 HTTP POST 发送请求                    │   │
│  │ • Server 通过 SSE 流式推送响应                      │   │
│  │ • 适用于远程工具、多客户端共享、云端部署              │   │
│  │                                                     │   │
│  │   Client ──HTTP POST──→ Server (远程/本地端口)      │   │
│  │   Client ←──SSE──────── Server                      │   │
│  └───────────────────────────────────────────────────┘   │
│                                                           │
└───────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

两种方式的选择取决于部署场景:

场景Transport原因
本地文件系统工具stdio简单,无网络配置
企业内部 API 网关HTTP+SSE多客户端共享
个人开发工具stdio安全,本地即可
云端 SaaS 工具HTTP+SSE需要远程访问

1.3 JSON-RPC:协议消息的格式 ​

无论用哪种 transport,MCP 的消息体都是 JSON-RPC 2.0 格式。每条消息就是一个 JSON 对象:

JSON-RPC 消息的基本结构:

  请求(Client → Server):
  ┌─────────────────────────────────────────────────────────┐
  │ {                                                       │
  │   "jsonrpc": "2.0",                                     │
  │   "id": 1,                     ← 请求 ID,用于匹配响应   │
  │   "method": "tools/list",      ← 要执行的操作            │
  │   "params": {}                 ← 操作参数(可选)        │
  │ }                                                       │
  └─────────────────────────────────────────────────────────┘

  响应(Server → Client):
  ┌─────────────────────────────────────────────────────────┐
  │ {                                                       │
  │   "jsonrpc": "2.0",                                     │
  │   "id": 1,                     ← 匹配请求的 ID           │
  │   "result": {                  ← 返回结果                │
  │     "tools": [...]                                       │
  │   }                                                     │
  │ }                                                       │
  └─────────────────────────────────────────────────────────┘

  通知(任意方向,不需要响应):
  ┌─────────────────────────────────────────────────────────┐
  │ {                                                       │
  │   "jsonrpc": "2.0",                                     │
  │   "method": "notifications/initialized",                 │
  │   "params": {}                                          │
  │   // 注意:通知没有 "id" 字段,对方不回复                │
  │ }                                                       │
  └─────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

JSON-RPC 非常简单:它本质上就是一种约定——"你发一个 JSON 给我,我回一个 JSON 给你"。MCP 在这个基础上定义了标准的方法名(method)集合。

1.4 一次完整的会话:从连接到调用 ​

下面展示一个 MCP Client 与 MCP Server 之间的真实消息序列。这是整个 MCP 协议的核心——一旦理解了这段交换,MCP 的全貌就清楚了。

阶段一:初始化握手

┌───────────────────────────────────────────────────────────┐
│  阶段一:Client 连接 Server,协商能力                       │
├───────────────────────────────────────────────────────────┤
│                                                           │
│  Step 1: Client 发送 initialize                          │
│  ─────────────────────────────────────────────────────    │
│  Client → Server:                                         │
│  {                                                       │
│    "jsonrpc": "2.0",                                     │
│    "id": 1,                                              │
│    "method": "initialize",                               │
│    "params": {                                           │
│      "protocolVersion": "2024-11-05",                    │
│      "capabilities": {                                   │
│        "roots": {"listChanged": true},                   │
│        "sampling": {}                                    │
│      },                                                  │
│      "clientInfo": {                                     │
│        "name": "my-ai-app",                              │
│        "version": "1.0.0"                                │
│      }                                                   │
│    }                                                     │
│  }                                                       │
│                                                           │
│  Step 2: Server 回复自己的能力                            │
│  ─────────────────────────────────────────────────────    │
│  Server → Client:                                         │
│  {                                                       │
│    "jsonrpc": "2.0",                                     │
│    "id": 1,                                              │
│    "result": {                                           │
│      "protocolVersion": "2024-11-05",                    │
│      "capabilities": {                                   │
│        "tools": {"listChanged": true},                   │
│        "resources": {"subscribe": true,                  │
│                       "listChanged": true}               │
│      },                                                  │
│      "serverInfo": {                                     │
│        "name": "weather-server",                         │
│        "version": "1.0.0"                                │
│      }                                                   │
│    }                                                     │
│  }                                                       │
│                                                           │
│  Step 3: Client 发送 initialized 通知                    │
│  ─────────────────────────────────────────────────────    │
│  Client → Server:                                         │
│  {                                                       │
│    "jsonrpc": "2.0",                                     │
│    "method": "notifications/initialized"                 │
│  }                                                       │
│                                                           │
│  至此握手完成,双方知道了彼此的能力。                       │
│                                                           │
└───────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55

阶段二:发现工具并调用

┌───────────────────────────────────────────────────────────┐
│  阶段二:Client 发现工具,用户触发调用                      │
├───────────────────────────────────────────────────────────┤
│                                                           │
│  Step 4: Client 列出可用工具                              │
│  ─────────────────────────────────────────────────────    │
│  Client → Server:                                         │
│  {                                                       │
│    "jsonrpc": "2.0",                                     │
│    "id": 2,                                              │
│    "method": "tools/list",                               │
│    "params": {}                                          │
│  }                                                       │
│                                                           │
│  Step 5: Server 返回工具列表                              │
│  ─────────────────────────────────────────────────────    │
│  Server → Client:                                         │
│  {                                                       │
│    "jsonrpc": "2.0",                                     │
│    "id": 2,                                              │
│    "result": {                                           │
│      "tools": [                                          │
│        {                                                 │
│          "name": "get_weather",                          │
│          "description": "获取指定城市的实时天气",          │
│          "inputSchema": {                                │
│            "type": "object",                             │
│            "properties": {                               │
│              "city": {                                   │
│                "type": "string",                         │
│                "description": "城市名称"                  │
│              }                                           │
│            },                                            │
│            "required": ["city"]                          │
│          }                                               │
│        }                                                 │
│      ]                                                   │
│    }                                                     │
│  }                                                       │
│                                                           │
│  Step 6: Client 调用工具                                  │
│  ─────────────────────────────────────────────────────    │
│  Client → Server:                                         │
│  {                                                       │
│    "jsonrpc": "2.0",                                     │
│    "id": 3,                                              │
│    "method": "tools/call",                               │
│    "params": {                                           │
│      "name": "get_weather",                              │
│      "arguments": {"city": "北京"}                        │
│    }                                                     │
│  }                                                       │
│                                                           │
│  Step 7: Server 返回执行结果                              │
│  ─────────────────────────────────────────────────────    │
│  Server → Client:                                         │
│  {                                                       │
│    "jsonrpc": "2.0",                                     │
│    "id": 3,                                              │
│    "result": {                                           │
│      "content": [                                        │
│        {                                                 │
│          "type": "text",                                 │
│          "text": "北京当前温度 28°C,晴,湿度 35%"        │
│        }                                                 │
│      ]                                                   │
│    }                                                     │
│  }                                                       │
│                                                           │
│  至此,Client 获得了工具执行的结果。                        │
│  Client 把这个结果交给 LLM → LLM 整合成回答 → 返回给用户。 │
│                                                           │
└───────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73

1.5 整个数据流的"全景图" ​

把上面的两个阶段串起来,MCP 的完整数据流就是:

┌───────────────────────────────────────────────────────────┐
│                MCP 完整数据流(端到端)                     │
├───────────────────────────────────────────────────────────┤
│                                                           │
│  ┌─────────┐         ┌──────────┐        ┌───────────┐  │
│  │  用户    │         │AI App    │        │MCP Server │  │
│  │         │         │(Client)  │        │(Tool)     │  │
│  └────┬────┘         └────┬─────┘        └─────┬─────┘  │
│       │                   │                    │         │
│       │ 1. "北京天气?"    │                    │         │
│       │──────────────────→│                    │         │
│       │                   │                    │         │
│       │                   │ 2. initialize     │         │
│       │                   │───────────────────→│         │
│       │                   │ ←── capabilities  │         │
│       │                   │                    │         │
│       │                   │ 3. tools/list     │         │
│       │                   │───────────────────→│         │
│       │                   │ ←── tool schemas  │         │
│       │                   │                    │         │
│       │                   │ 4. 把 tool schemas 转成     │
│       │                   │    Function Calling 格式    │
│       │                   │    发给 LLM                 │
│       │                   │                    │         │
│       │                   │ 5. LLM 返回 tool_call:      │
│       │                   │    get_weather("北京")      │
│       │                   │                    │         │
│       │                   │ 6. tools/call      │         │
│       │                   │───────────────────→│         │
│       │                   │                    │         │
│       │                   │    7. Server 真正   │         │
│       │                   │       调用天气 API  │         │
│       │                   │       ← 28°C, 晴  │         │
│       │                   │ ←── result        │         │
│       │                   │                    │         │
│       │                   │ 8. 把结果返回给 LLM          │
│       │                   │    LLM 生成最终回答           │
│       │                   │                    │         │
│       │ 9. "北京今天 28°C, 晴"               │         │
│       │←──────────────────│                    │         │
│       │                   │                    │         │
└───────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

关键观察:MCP Server 从不直接跟 LLM 通信。它只做一件事——暴露工具并执行。LLM 由 MCP Client(你的 AI 应用)自己管理。MCP Server 不知道也不关心是哪种 LLM 在调用它。


第2部分:MCP 的四大核心概念 ​

MCP 协议定义了四种"原语"(primitives),Server 可以按需实现其中任意组合:

┌───────────────────────────────────────────────────────────┐
│                  MCP 四大核心原语                           │
├───────────────────────────────────────────────────────────┤
│                                                           │
│  ┌─────────────────────────────────────────────────┐     │
│  │  📁 Resources  — 暴露数据/文件                    │     │
│  │  "我需要读这个文件"  "这个数据库里有什么?"       │     │
│  │  URI 标识,支持读取、订阅变更                      │     │
│  └─────────────────────────────────────────────────┘     │
│                                                           │
│  ┌─────────────────────────────────────────────────┐     │
│  │  🔧 Tools  — 暴露可执行操作                       │     │
│  │  "帮我查天气"  "帮我发邮件"  "帮我搜文档"         │     │
│  │  有输入参数(JSON Schema),有返回结果              │     │
│  └─────────────────────────────────────────────────┘     │
│                                                           │
│  ┌─────────────────────────────────────────────────┐     │
│  │  💬 Prompts  — 暴露预定义提示词模板                │     │
│  │  "用这个模板帮我写代码审查"                       │     │
│  │  可包含参数,Server 告诉 Client "你可以这样问我"   │     │
│  └─────────────────────────────────────────────────┘     │
│                                                           │
│  ┌─────────────────────────────────────────────────┐     │
│  │  🧠 Sampling  — Server 反向请求 LLM              │     │
│  │  "我需要在执行过程中让 LLM 帮我做判断"            │     │
│  │  唯一让 Server 主动发起 LLM 调用 的机制            │     │
│  └─────────────────────────────────────────────────┘     │
│                                                           │
└───────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

2.1 Resources(资源)——"我能给你什么数据" ​

Resources 让 MCP Server 暴露结构化或非结构化的数据。每个 Resource 有一个唯一的 URI,Client 可以通过这个 URI 读取数据。

┌───────────────────────────────────────────────────────────┐
│                    Resources 概念示意                      │
├───────────────────────────────────────────────────────────┤
│                                                           │
│  类比:Resources 相当于 REST API 的 GET 端点。             │
│  但它是结构化和协商过的——Server 告诉 Client               │
│  "我有这些数据,格式是这样的,需要的时候来读"。             │
│                                                           │
│  典型资源:                                               │
│  • file:///home/user/docs/report.md                       │
│  • postgres://database/users/table                       │
│  • slack://workspace/channels/general                     │
│                                                           │
│  Client 可以:                                            │
│  • resources/list    → 列出所有可用资源                    │
│  • resources/read    → 读取指定资源                        │
│  • resources/subscribe → 订阅资源变更通知                  │
│                                                           │
└───────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

代码示例——Server 端注册一个资源:

python
# MCP Server 注册资源
@server.list_resources()
async def list_resources() -> list[Resource]:
    return [
        Resource(
            uri="file:///home/user/docs/readme.md",
            name="项目 README",
            description="项目的说明文档",
            mimeType="text/markdown"
        ),
        Resource(
            uri="db://users/table",
            name="用户数据表",
            description="所有注册用户的信息",
            mimeType="application/json"
        )
    ]

@server.read_resource()
async def read_resource(uri: str) -> str:
    if uri == "file:///home/user/docs/readme.md":
        with open("/home/user/docs/readme.md") as f:
            return f.read()
    elif uri == "db://users/table":
        return json.dumps(fetch_users_from_db())
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

2.2 Tools(工具)——"我能帮你做什么" ​

Tools 是 MCP 最核心、最常用的原语。它跟 Function Calling 的工具定义几乎完全对应,区别是:它运行在 MCP Server 进程里,而不是你的 AI 应用进程里。

MCP Tool 的定义结构:

┌───────────────────────────────────────────────────────────┐
│                    MCP Tool 的结构                         │
├───────────────────────────────────────────────────────────┤
│                                                           │
│  {                                                       │
│    "name": "get_weather",        ← 工具名称               │
│    "description": "...",         ← 给 LLM 看的说明        │
│    "inputSchema": {              ← 参数 JSON Schema       │
│      "type": "object",                                    │
│      "properties": {                                      │
│        "city": {"type": "string", "description": "..."}   │
│      },                                                   │
│      "required": ["city"]                                 │
│    }                                                      │
│  }                                                       │
│                                                           │
│  注意:和 Function Calling 的 tool 定义几乎一样!          │
│  MCP 在协议层把这个定义标准化了。                          │
│                                                           │
└───────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

MCP Client(你的 AI 应用)拿到 Tool 定义后,直接将其转换为 LLM 的 Function Calling 格式发给 LLM。当 LLM 返回 tool_calls 时,Client 不做任何变化,而是通过 MCP 的 tools/call 发送给 Server 执行。Client 只是"转手"——它不执行工具,它把执行委托给 Server。

2.3 Prompts(提示词模板)——"你可以这样跟我对话" ​

Prompts 是 MCP 的一个独特设计:Server 可以定义一组"推荐提问方式",让用户或 AI 应用选择使用。

┌───────────────────────────────────────────────────────────┐
│                    Prompts 示意                            │
├───────────────────────────────────────────────────────────┤
│                                                           │
│  一个 MCP Server 可以暴露 Prompts:                        │
│                                                           │
│  {                                                       │
│    "name": "code_review",                                │
│    "description": "对选中的代码进行代码审查",              │
│    "arguments": [                                        │
│      {                                                   │
│        "name": "language",                               │
│        "description": "编程语言",                         │
│        "required": true                                  │
│      }                                                   │
│    ]                                                     │
│  }                                                       │
│                                                           │
│  Client 获取这个 Prompt 后,组合成消息:                   │
│  "请使用 [language] 的最佳实践,审查以下代码:..."         │
│                                                           │
│  Prompts 本质上就是"预制的 system prompt 模板"。           │
│  它让工具作者可以告诉用户 "我的工具最好这样用"。           │
│                                                           │
└───────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

2.4 Sampling(采样)——Server 反向调用 LLM ​

这是 MCP 协议中最特殊的能力。通常情况下是 Client 调用 Server;但 Sampling 允许 Server 主动请求 Client 帮它调用 LLM。

┌───────────────────────────────────────────────────────────┐
│                    Sampling 流程                           │
├───────────────────────────────────────────────────────────┤
│                                                           │
│  正常流程:                                               │
│    Client ──tools/call──→ Server ──result──→ Client       │
│                                                           │
│  Sampling 流程(Server 需要 LLM 帮忙):                   │
│    Client ──tools/call──→ Server                          │
│                            │                              │
│                            │ "这个数据太复杂了,             │
│                            │  我需要 LLM 帮我做判断"        │
│                            │                              │
│    Client ←──sampling request── Server                    │
│      │                                                    │
│      │ Client 把 Server 的请求发给 LLM                     │
│      │ LLM 返回结果                                       │
│      │                                                    │
│    Client ──sampling result──→ Server                     │
│                            │                              │
│                            │ Server 用 LLM 的判断          │
│                            │ 继续处理,最终返回结果          │
│                                                           │
│  适用场景:                                               │
│  • Server 内部处理复杂文本,需要 LLM 做摘要               │
│  • Server 需要 LLM 帮你做决策(如"这个文件应该分类到哪?")│
│                                                           │
│  注意:Client 有权拒绝 Server 的 sampling 请求。           │
│  Server 不能假设 LLM 一定可用。                            │
│                                                           │
└───────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

第3部分:构建一个具体的 MCP Server ​

3.1 场景:天气查询 MCP Server ​

假设我们要写一个 MCP Server,封装一个天气查询 API。任何实现了 MCP Client 的 AI 应用(Claude Desktop、Cursor、Continue)都能自动发现并使用它。

用 Python MCP SDK 来写:

python
"""
weather_server.py — 天气查询 MCP Server
这是一个完整的、可运行的 MCP Server 示例。
"""

import asyncio
import httpx
from mcp.server import Server, NotificationOptions
from mcp.server.models import InitializationCapabilities
from mcp.server.stdio import stdio_server

# Step 1: 创建 Server 实例
server = Server("weather-server")


# Step 2: 定义工具列表
@server.list_tools()
async def list_tools() -> list:
    """
    Client 调用 tools/list 时触发。
    返回这个 Server 提供的所有工具定义。
    """
    return [
        {
            "name": "get_current_weather",
            "description": (
                "获取指定城市的实时天气信息。"
                "返回温度、湿度、天气状况和风速。"
            ),
            "inputSchema": {
                "type": "object",
                "properties": {
                    "city": {
                        "type": "string",
                        "description": "城市名称,例如 '北京'、'上海'、'东京'"
                    },
                    "unit": {
                        "type": "string",
                        "enum": ["celsius", "fahrenheit"],
                        "description": "温度单位,默认 celsius"
                    }
                },
                "required": ["city"]
            }
        },
        {
            "name": "get_weather_forecast",
            "description": (
                "获取指定城市未来 3 天的天气预报。"
                "返回每天的最高温、最低温和天气状况。"
            ),
            "inputSchema": {
                "type": "object",
                "properties": {
                    "city": {
                        "type": "string",
                        "description": "城市名称"
                    },
                    "days": {
                        "type": "integer",
                        "description": "预报天数,1-7,默认 3",
                        "minimum": 1,
                        "maximum": 7
                    }
                },
                "required": ["city"]
            }
        }
    ]


# Step 3: 实现工具调用
@server.call_tool()
async def call_tool(name: str, arguments: dict) -> list:
    """
    Client 调用 tools/call 时触发。
    name: LLM 决定的工具名
    arguments: LLM 决定的参数
    """
    if name == "get_current_weather":
        city = arguments["city"]
        unit = arguments.get("unit", "celsius")

        # 真实项目中这里调用天气 API
        weather_data = await fetch_weather_from_api(city, unit)

        # 返回结果 —— 必须是 content 数组
        return [{
            "type": "text",
            "text": (
                f"🏙️  {city}\n"
                f"🌡️  温度: {weather_data['temp']}°{unit[0].upper()}\n"
                f"💧  湿度: {weather_data['humidity']}%\n"
                f"☁️  天气: {weather_data['condition']}\n"
                f"🌬️  风速: {weather_data['wind_speed']} m/s"
            )
        }]

    elif name == "get_weather_forecast":
        city = arguments["city"]
        days = arguments.get("days", 3)

        forecast = await fetch_forecast_from_api(city, days)

        lines = [f"📅 {city} 未来 {days} 天天气预报:\n"]
        for day in forecast:
            lines.append(
                f"  {day['date']}: "
                f"{day['high']}° / {day['low']}°, "
                f"{day['condition']}"
            )
        return [{"type": "text", "text": "\n".join(lines)}]

    else:
        raise ValueError(f"Unknown tool: {name}")


# Step 4: 模拟 API 调用(真实项目替换为实际 HTTP 请求)
async def fetch_weather_from_api(city: str, unit: str) -> dict:
    """模拟天气 API 调用。真实项目用 httpx.get()"""
    # 真实代码:
    # async with httpx.AsyncClient() as client:
    #     resp = await client.get(
    #         "https://api.weather.com/v1/current",
    #         params={"city": city, "unit": unit},
    #         headers={"Authorization": f"Bearer {API_KEY}"}
    #     )
    #     return resp.json()
    return {
        "temp": 28,
        "humidity": 45,
        "condition": "晴朗",
        "wind_speed": 3.4
    }


async def fetch_forecast_from_api(city: str, days: int) -> list:
    """模拟天气预报 API 调用"""
    return [
        {"date": "2026-07-29", "high": 32, "low": 24, "condition": "晴"},
        {"date": "2026-07-30", "high": 30, "low": 23, "condition": "多云"},
        {"date": "2026-07-31", "high": 28, "low": 22, "condition": "小雨"},
    ]


# Step 5: 启动 Server(stdio transport)
async def main():
    async with stdio_server() as (read_stream, write_stream):
        await server.run(
            read_stream,
            write_stream,
            InitializationCapabilities(
                sampling={},
                experimental={},
            ),
        )


if __name__ == "__main__":
    asyncio.run(main())
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160

3.2 在 Claude Desktop 中配置这个 Server ​

当你写完 MCP Server 后,下一步就是在 AI 应用中配置它。以 Claude Desktop 为例:

在 claude_desktop_config.json 中添加:

{
  "mcpServers": {
    "weather": {
      "command": "python",
      "args": ["/path/to/weather_server.py"]
    }
  }
}
1
2
3
4
5
6
7
8
9
10

Claude Desktop 启动时会自动执行 python /path/to/weather_server.py,把这个脚本作为子进程启动。之后通过 stdin/stdout 与它通信。用户跟 Claude 对话时,Claude 会:

  1. 调用 tools/list 获取 get_current_weather 和 get_weather_forecast 的定义
  2. 把这两个工具的定义转成 Function Calling 格式发给 Claude 模型
  3. 如果 Claude 决定调用 get_current_weather({"city": "北京"}),Claude Desktop 通过 tools/call 发给 MCP Server
  4. MCP Server 执行查询,返回天气结果
  5. Claude Desktop 把结果返回给 Claude 模型,让 Claude 整合成自然语言回答

3.3 线上的 JSON-RPC 消息(逐条展示) ​

下面是当你问 Claude Desktop "北京天气怎样?"时,实际在 stdin/stdout 上传输的完整 JSON-RPC 消息序列:

═══════════════════════════════════════════════════════════════
              完整 JSON-RPC 消息交换日志
═══════════════════════════════════════════════════════════════

[Client → Server] 握手 - 初始化

  {"jsonrpc":"2.0","id":1,"method":"initialize","params":{
    "protocolVersion":"2024-11-05",
    "capabilities":{"roots":{"listChanged":true}},
    "clientInfo":{"name":"claude-desktop","version":"0.8.0"}
  }}

[Server → Client]

  {"jsonrpc":"2.0","id":1,"result":{
    "protocolVersion":"2024-11-05",
    "capabilities":{"tools":{"listChanged":true}},
    "serverInfo":{"name":"weather-server","version":"1.0.0"}
  }}

[Client → Server] 通知 - 初始化完成

  {"jsonrpc":"2.0","method":"notifications/initialized"}

───────────────────────────────────────────────────────────────

[Client → Server] 请求工具列表

  {"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}

[Server → Client]

  {"jsonrpc":"2.0","id":2,"result":{"tools":[
    {"name":"get_current_weather","description":"获取指定城市...",
     "inputSchema":{"type":"object","properties":{
       "city":{"type":"string","description":"城市名称"},
       "unit":{"type":"string","enum":["celsius","fahrenheit"]}},
       "required":["city"]}},
    {"name":"get_weather_forecast","description":"获取指定城市未来...",
     "inputSchema":{"type":"object","properties":{
       "city":{"type":"string"},
       "days":{"type":"integer","minimum":1,"maximum":7}},
       "required":["city"]}}
  ]}}

───────────────────────────────────────────────────────────────
            此时 Claude Desktop 把工具定义发给 Claude 模型
            Claude 模型决定调用 get_current_weather({"city":"北京"})
───────────────────────────────────────────────────────────────

[Client → Server] 调用工具

  {"jsonrpc":"2.0","id":3,"method":"tools/call","params":{
    "name":"get_current_weather",
    "arguments":{"city":"北京","unit":"celsius"}
  }}

         Server 内部执行: fetch_weather_from_api("北京","celsius")
         Server 拿到真实天气数据

[Server → Client]

  {"jsonrpc":"2.0","id":3,"result":{"content":[
    {"type":"text","text":"🏙️  北京\n🌡️  温度: 28°C\n💧  湿度: 45%\n
     ☁️  天气: 晴朗\n🌬️  风速: 3.4 m/s"}
  ]}}

───────────────────────────────────────────────────────────────
            此时 Claude Desktop 把结果返回给 Claude 模型
            Claude 模型生成: "北京今天天气晴朗,温度 28°C..."
───────────────────────────────────────────────────────────────
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71

第4部分:MCP vs Function Calling ​

这是很多人最容易混淆的地方。两者都涉及"工具定义"和"工具调用",但它们解决的问题层次完全不同。

4.1 本质区别 ​

┌───────────────────────────────────────────────────────────┐
│              MCP vs Function Calling 本质对比               │
├───────────────────────────────────────────────────────────┤
│                                                           │
│  Function Calling:                                        │
│  ┌───────────────────────────────────────────────────┐   │
│  │  "告诉一个 LLM:在这次对话中,你有这些工具。"       │   │
│  │                                                    │   │
│  │  作用域:一次对话(一次 API 请求的 tools 参数)     │   │
│  │  谁定义工具:开发者(写在代码里的 Python dict)     │   │
│  │  谁执行工具:开发者的应用代码                        │   │
│  │  复用性:每个 AI 应用都要自己写一套                 │   │
│  │                                                    │   │
│  │  类比:每次出门前告诉你 "今天车上有地图、有扳手"    │   │
│  └───────────────────────────────────────────────────┘   │
│                                                           │
│  MCP:                                                     │
│  ┌───────────────────────────────────────────────────┐   │
│  │  "注册一个工具服务器:任何 AI 应用都能发现和使用。" │   │
│  │                                                    │   │
│  │  作用域:跨应用、跨会话、跨 LLM                     │   │
│  │  谁定义工具:工具作者(写一次,放那里)             │   │
│  │  谁执行工具:MCP Server 自己执行                    │   │
│  │  复用性:同一个 MCP Server 被多个 AI 应用共享      │   │
│  │                                                    │   │
│  │  类比:车上装好工具箱,钥匙给你——谁开车都能用       │   │
│  └───────────────────────────────────────────────────┘   │
│                                                           │
└───────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

4.2 协作关系 ​

MCP 和 Function Calling 不是替代关系,是协作关系:

┌───────────────────────────────────────────────────────────┐
│              MCP + Function Calling 协作流程                │
├───────────────────────────────────────────────────────────┤
│                                                           │
│  MCP 负责:                                               │
│    • 工具注册和发现(tools/list)                          │
│    • 工具的实际执行(tools/call → Server 执行)            │
│    • 跨应用复用(一个 Server 多处用)                      │
│                                                           │
│  Function Calling 负责:                                   │
│    • LLM 推理"该不该调用工具"                              │
│    • LLM 生成工具名和参数                                   │
│    • LLM 整合工具结果为自然语言                             │
│                                                           │
│  流程:                                                   │
│                                                           │
│  MCP Server ──tools/list──→ MCP Client                    │
│                              │                            │
│                              │ 转为 Function Calling 格式   │
│                              ↓                            │
│                            LLM                            │
│                              │                            │
│                              │ 返回 tool_calls             │
│                              ↓                            │
│  MCP Server ←──tools/call── MCP Client                    │
│      │                                                    │
│      │ 执行真实操作                                        │
│      ↓                                                    │
│  MCP Server ──result──→ MCP Client                       │
│                              │                            │
│                              │ 把结果返回 LLM              │
│                              ↓                            │
│                            LLM                            │
│                              │                            │
│                              │ 最终回答                    │
│                              ↓                            │
│                            用户                           │
│                                                           │
└───────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

4.3 一句话总结区别 ​

维度Function CallingMCP
层面LLM 推理能力工具集成协议
谁维护每个应用各自维护工具提供者维护一次
如何发现工具硬编码在代码里协议发现(tools/list)
如何执行工具应用代码里写死MCP Server 执行
跨应用复用不支持核心设计目标
需要 LLM 吗是(LLM 决定调哪个)否(纯协议层)
需要 MCP 吗否—

第5部分:为什么 MCP 重要? ​

5.1 它正在成为标准 ​

MCP 发布于 2024 年 11 月,不到一年时间已经获得了广泛支持:

┌───────────────────────────────────────────────────────────┐
│              已支持 MCP 的应用和平台                        │
├───────────────────────────────────────────────────────────┤
│                                                           │
│  AI 应用(作为 MCP Client):                              │
│  ┌───────────────────────────────────────────────────┐   │
│  │  • Claude Desktop    — Anthropic 官方,首发支持    │   │
│  │  • Cursor            — 最流行的 AI 编程 IDE       │   │
│  │  • Continue.dev      — 开源的 AI 编程助手         │   │
│  │  • Zed               — 高性能 AI 代码编辑器       │   │
│  │  • Sourcegraph Cody  — 代码理解 AI                │   │
│  │  • Goose             — Block 的 AI 开发助手       │   │
│  │  • Cline (VS Code)   — VS Code 的自主 Agent       │   │
│  │  • ChatGPT Desktop   — OpenAI 的桌面应用          │   │
│  └───────────────────────────────────────────────────┘   │
│                                                           │
│  工具和平台(作为 MCP Server):                            │
│  ┌───────────────────────────────────────────────────┐   │
│  │  • GitHub            — 代码仓库                    │   │
│  │  • Slack             — 即时通讯                    │   │
│  │  • Linear            — 项目管理                    │   │
│  │  • Notion            — 知识库                      │   │
│  │  • Figma             — 设计工具                    │   │
│  │  • PostgreSQL/SQLite — 数据库                      │   │
│  │  • Puppeteer         — 浏览器自动化                │   │
│  │  • 文件系统          — 原生 stdio MCP Server      │   │
│  │  • ...数百个社区 MCP Server                        │   │
│  └───────────────────────────────────────────────────┘   │
│                                                           │
└───────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

5.2 它对开发者的意义 ​

写一次,到处使用。 这是 MCP 最核心的价值主张。

你写一个 Slack MCP Server,任何支持 MCP 的 AI 应用都能自动获得 Slack 能力。不需要为 Claude Desktop 写一套 Slack 集成,再为 Cursor 写一套,再为 Continue 写一套。

5.3 它对用户的意义 ​

用户不需要理解"这个 AI 应用集成了哪些工具"。他们只需要:

  1. 找到一个 MCP Server(社区市场、官方列表)
  2. 在 AI 应用的配置文件里加一行配置
  3. 开始使用

就像你买一个 USB 鼠标——插上就能用,不用装驱动。

5.4 生态爆炸的加速度 ​

MCP 正在触发一个正向循环:

┌───────────────────────────────────────────────────────────┐
│                  MCP 生态正向循环                          │
├───────────────────────────────────────────────────────────┤
│                                                           │
│   更多 AI 应用支持 MCP                                     │
│        ↓                                                  │
│   更多开发者愿意写 MCP Server                              │
│   (因为他们写的 Server 能被很多应用使用)                  │
│        ↓                                                  │
│   工具生态更丰富                                           │
│        ↓                                                  │
│   更多用户选择支持 MCP 的 AI 应用                           │
│   (因为他们的工具都能用了)                                │
│        ↓                                                  │
│   更多 AI 应用被迫支持 MCP(竞争压力)                      │
│        ↓                                                  │
│        ↑ 循环加速 ←──┘                                    │
│                                                           │
└───────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

这个循环与当年 USB 取代 PS/2、串口、并口的逻辑完全一致——不是 USB 技术有多先进,而是标准化带来了网络效应。

5.5 MCP 的当前局限 ​

┌───────────────────────────────────────────────────────────┐
│                  MCP 的已知局限                            │
├───────────────────────────────────────────────────────────┤
│                                                           │
│  1. 协议仍在演进(当前版本 2024-11-05,可能有 breaking     │
│     changes)                                             │
│                                                           │
│  2. 安全性依赖 transport 层                               │
│     • stdio 很安全(本地进程)                             │
│     • HTTP+SSE 依赖 HTTPS + 认证(目前认证方案不成熟)     │
│                                                           │
│  3. Server 发现机制不成熟                                 │
│     • 目前主要靠手动配置 + 社区市场                        │
│     • 缺少类似 npm/pip 的官方 registry                     │
│                                                           │
│  4. 调试工具有限                                          │
│     • 排查 JSON-RPC 问题较困难                             │
│     • 社区正在构建 Inspector 等调测工具                    │
│                                                           │
│  5. 本地 vs 远程边界模糊                                  │
│     • Server 跑在本地还是云端?谁管理生命周期?            │
│     • 目前主要由 Client 负责管理                           │
│                                                           │
└───────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

核心总结 ​

总结1:MCP 解决 N×M 集成困境 ​

MCP = AI 工具集成领域的 USB 协议

写一次 MCP Server → 所有实现了 MCP Client 的 AI 应用都能用
从 N×M 的集成复杂度降到 N+M
1
2
3
4

总结2:MCP 架构三要素 ​

┌───────────────────────────────────────────────────────────┐
│                                                           │
│  MCP Client(你的 AI 应用)                                │
│        ↕  JSON-RPC over stdio 或 HTTP+SSE                  │
│  MCP Server(工具包装器)                                   │
│        ↕  原生 API                                       │
│  外部工具/数据源(GitHub, Slack, 数据库...)               │
│                                                           │
└───────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9

总结3:四大原语 ​

原语用途方向
Resources暴露数据(读文件、查数据库)Client 读 Server
Tools暴露可执行操作Client 调用 Server
Prompts暴露提示词模板Client 读取 Server
SamplingServer 反向请求 LLMServer 请求 Client

总结4:MCP vs Function Calling ​

  • Function Calling = 单次会话的工具推理能力(LLM 层面)
  • MCP = 跨应用的工具集成标准(协议层面)
  • 两者协作:MCP 负责工具的注册和执行,Function Calling 负责 LLM 的推理

总结5:一个 MCP Server 的要素 ​

python
# 最小化 MCP Server 的三个要素:
# 1. 工具定义(list_tools) — 告诉 Client "我能做什么"
# 2. 工具执行(call_tool)  — 实际执行,返回结果
# 3. Transport 启动         — 监听 stdio 或 HTTP 端口
1
2
3
4

章节测试 ​

测试1:概念理解 ​

MCP 解决的核心问题是什么?请用自己的话描述 N×M 困境。

测试2:协议消息 ​

一个完整的 MCP 会话中,Client 和 Server 之间交换哪些类型的 JSON-RPC 消息?按顺序列举。

测试3:四大原语 ​

MCP 定义了哪四种原语(primitives)?各自的作用是什么?

测试4:Transport 选择 ​

什么情况下应该使用 stdio transport,什么情况下应该使用 HTTP+SSE?

测试5:MCP vs Function Calling ​

以下说法正确的是? A. MCP 是 Function Calling 的替代品 B. MCP 和 Function Calling 在不同的层面工作,是协作关系 C. MCP 运行时也需要 LLM 做推理 D. Function Calling 可以替代 MCP 的工具注册和发现

测试6:Sampling 场景 ​

MCP 的 Sampling 原语的设计目的是什么?它和普通的 tools/call 有什么本质区别?

测试7:架构判断 ​

以下哪项说法是正确的? A. MCP Server 可以直接调用 LLM B. MCP Server 通过 Sampling 请求,让 MCP Client 代它调用 LLM C. MCP Server 必须在云端运行 D. MCP Client 必须是 Claude Desktop


参考答案 ​

测试1答案 ​

答案:MCP 解决的是 AI 应用与外部工具集成的 N×M 困境。在 MCP 出现之前,每个 AI 应用(M 个)要集成每个外部工具(N 个),需要 M×N 套独立的集成代码。MCP 通过标准化协议,把这个问题化简为 N+M:写 N 个 MCP Server,M 个 AI 应用通过实现 MCP Client 就能自动使用所有 N 个工具。


测试2答案 ​

答案:按顺序:

  1. initialize(请求) — Client 发起握手,声明协议版本和能力
  2. initialize(响应) — Server 回复自己的协议版本和能力
  3. notifications/initialized(通知) — Client 通知握手完成
  4. tools/list(请求) — Client 列出可用工具
  5. tools/list(响应) — Server 返回工具列表及 JSON Schema
  6. tools/call(请求) — Client 调用指定工具
  7. tools/call(响应) — Server 返回执行结果

测试3答案 ​

答案:

  • Resources:暴露数据/文件内容,通过 URI 标识,支持读取和订阅变更
  • Tools:暴露可执行的操作,有输入参数(JSON Schema)和返回结果
  • Prompts:暴露预定义的提示词模板,告诉 Client "你可以这样跟我对话"
  • Sampling:允许 Server 反向请求 Client 调用 LLM,用于 Server 内部需要 LLM 推理的场景

测试4答案 ​

答案:

  • stdio:本地工具(文件系统、本地数据库、个人脚本),零网络开销,无需端口管理,安全性好
  • HTTP+SSE:远程工具(云端 API、企业内部服务)、多客户端共享场景、SaaS 工具集成

测试5答案 ​

答案:B

解析:

  • A 错误:MCP 和 Function Calling 不是替代关系,是协作关系。MCP 负责注册/执行工具,Function Calling 负责 LLM 推理
  • C 错误:MCP 是纯协议层,它的 tools/list 和 tools/call 不需要 LLM 参与。只有把工具结果交给用户时才需要 LLM 做自然语言整合
  • D 错误:Function Calling 本身不提供工具注册和发现机制,那些都需要开发者硬编码

测试6答案 ​

答案:Sampling 允许 MCP Server 反向请求 MCP Client 调用 LLM。

与普通 tools/call 的本质区别:

  • tools/call 的方向是 Client → Server(Client 让 Server 做某事)
  • sampling 的方向是 Server → Client(Server 让 Client 调用 LLM 帮它做某事)

场景示例:MCP Server 在处理一个复杂文件时,需要 LLM 帮忙判断"这个文件的内容应该分类到哪个目录"。Server 本身不连接 LLM,所以它通过 sampling 请求 Client 代为调用。


测试7答案 ​

答案:B

解析:

  • A 错误:MCP Server 不能直接调用 LLM,它通过 Sampling 请求让 Client 代为调用
  • C 错误:MCP Server 可以在本地运行(stdio transport),不必须云端
  • D 错误:任何实现了 MCP Client 的应用都可以连接 MCP Server,包括 Cursor、Continue、ChatGPT Desktop 等

相关笔记 ​

  • [[01-function-calling]] - Function Calling 基础:LLM 如何决定调用工具
  • [[00-agent-overview]] - Agent 整体学习路线
  • [[02-framework-evolution]] - Agent 框架如何封装工具调用
  • [[05-agent-workflow]] - 工具调用在 Agent 工作流中的应用

下一步学习 ​

  • [ ] 动手:使用 Python MCP SDK 构建一个自己的 MCP Server
  • [ ] 尝试:在 Claude Desktop 或 Cursor 中配置一个 MCP Server
  • [ ] 探索:浏览 MCP 官方文档 和社区 Server 市场

学习状态:🟡 开始学习

最后更新于:

Pager
上一篇17. Harness Engineering, Skills, and Loop Engineering — 从信任模型到验证系统 / From Trusting Models to Verifying Systems
下一篇19. Agent 评估与测试 — 如何衡量一个"不可预测"的系统 / Agent Evaluation and Testing — How to Measure an "Unpredictable" System

持续记录,持续成长

Copyright © Tidenflow