MCP:工具的标准化接口

7/6/2026 AI AgentMCPModel Context Protocol

# MCP:工具的标准化接口

本章讲解 MCP(Model Context Protocol)协议的设计理念、通信模型以及工具调用流程。

本章核心问题: 假设我们要给 AI Agent 加上"天气预报"和"发送邮件"两个工具。不同的大模型对工具的描述格式不同(OpenAI 用 JSON Schema,Anthropic Claude 有自己的格式),同时不同工具的实现方式也不同(有的调用 HTTP API,有的读取本地文件,有的需要 OAuth 认证)。如果每对接一个大模型就重写一遍工具代码,显然会陷入"适配器地狱"。MCP 的解决方案是:让工具提供方按照统一协议封装工具,让模型消费方也按照统一协议发现和调用工具,从而解耦。

# 7.1 为什么需要 MCP

在过去的大模型应用中,工具调用面临以下痛点:

  • 格式不统一:不同模型对工具描述参数的要求不同,需要为每个模型适配。
  • 安全风险:用户下载的第三方工具代码可能带来安全隐患。
  • 生态割裂:每个 Agent 框架都有自己的工具定义方式,工具无法跨框架复用。

MCP(Model Context Protocol)由 Anthropic 提出,旨在标准化 AI 应用与外部工具/数据源的交互方式。它参考了 LSP(Language Server Protocol,语言服务器协议)的设计思路,采用客户端-服务器架构。

# 7.1.1 MCP 的三大设计目标

  1. 可替换性:前端(LLM 应用)和后端(工具/数据源)可以独立开发和替换,只需遵循 MCP 协议即可对接。
  2. 安全性:工具运行在独立的 MCP Server 进程中,与 LLM 应用进程隔离。MCP Server 可以运行在本地(子进程)或远程(独立服务),通过能力声明和权限控制实现最小权限原则。
  3. 生态互通:任何符合 MCP 规范的工具都可以在任何支持 MCP 的客户端中使用。

# 7.1.2 MCP 的核心概念

概念 说明
MCP Host 需要访问数据的 LLM 应用程序(如 Claude Desktop、IDE 插件、自定义 Agent)
MCP Client 与 MCP Server 建立一对一连接的协议客户端
MCP Server 通过标准协议对外暴露特定能力的轻量级服务程序
Transport 传输层,定义客户端与服务器之间的通信机制(stdio、SSE 等)
Capability 能力声明,Server 在初始化时告知 Client 自己支持哪些功能
Resource 数据资源,类似 GET 接口,用于获取静态或动态数据(文件内容、数据库记录等)
Tool 工具,类似 POST 接口,用于执行操作(发送邮件、调用 API 等)
Prompt 提示模板,Server 可以提供可复用的提示模板供 Client 使用
Sampling 采样请求,Server 可以反向请求 LLM 生成文本(反向调用)
Roots 根目录列表,Client 告知 Server 可访问的项目根目录

# 7.2 MCP 的通信模型

MCP 采用客户端-服务器架构,通信协议基于 JSON-RPC 2.0。

# 7.2.1 JSON-RPC 2.0 基础

JSON-RPC 2.0 是一种轻量级的远程过程调用协议,使用 JSON 格式进行数据交换。MCP 中的每个请求和响应都遵循 JSON-RPC 2.0 规范。

请求格式示例:

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "get_weather",
    "arguments": {
      "city": "北京"
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11

成功响应:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "北京当前温度 26°C,晴,湿度 45%"
      }
    ],
    "isError": false
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13

错误响应:

{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32603,
    "message": "Internal error",
    "data": {
      "details": "API 请求超时"
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11

# 7.2.2 传输层(Transport)

MCP 支持两种传输方式:

stdio 传输:客户端将 MCP Server 作为子进程启动,通过标准输入/输出进行通信。

  • 适用于本地工具、开发环境。
  • 进程级隔离,安全性较好。
  • 启动快,无需网络配置。

SSE(Server-Sent Events)传输:客户端通过 HTTP 与远程 MCP Server 通信。

  • 适用于远程服务、生产环境。
  • 支持跨网络访问。
  • 需要处理认证和授权。

# 7.2.3 生命周期

MCP 连接的生命周期分为三个阶段:

  1. 初始化:Client 和 Server 互相交换能力信息,确认协议版本。
  2. 运行:进行工具调用、资源访问、提示模板获取等操作。
  3. 关闭:终止连接,释放资源。

# 7.3 MCP Server 开发实战

下面通过一个完整的天气预报 MCP Server 示例,展示如何使用 Node.js 开发 MCP Server。

# 7.3.1 环境准备

# 创建项目目录
mkdir mcp-weather-server
cd mcp-weather-server

# 初始化项目
npm init -y

# 安装 MCP SDK
npm install @modelcontextprotocol/sdk

# 安装 TypeScript 相关依赖
npm install typescript @types/node ts-node --save-dev
1
2
3
4
5
6
7
8
9
10
11
12

# 7.3.2 实现 MCP Server

TypeScript 实现:

import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
  CallToolRequestSchema,
  ListToolsRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";

// 创建 Server 实例
const server = new Server(
  {
    name: "weather-server",
    version: "1.0.0",
  },
  {
    capabilities: {
      tools: {},
    },
  }
);

// 声明工具列表
server.setRequestHandler(ListToolsRequestSchema, async () => {
  return {
    tools: [
      {
        name: "get_weather",
        description: "获取指定城市的天气预报",
        inputSchema: {
          type: "object",
          properties: {
            city: {
              type: "string",
              description: "城市名称,如:北京、上海",
            },
          },
          required: ["city"],
        },
      },
    ],
  };
});

// 处理工具调用
server.setRequestHandler(CallToolRequestSchema, async (request) => {
  const { name, arguments: args } = request.params;
  if (name === "get_weather") {
    const weather = await fetchWeather(args.city);
    return {
      content: [{ type: "text", text: weather }],
    };
  }
  throw new Error(`Unknown tool: ${name}`);
});

// 启动服务器
const transport = new StdioServerTransport();
await server.connect(transport);
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

Python 实现(使用 MCP Python SDK):

from mcp.server import Server
from mcp.server.stdio import stdio_server
from mcp.types import Tool, TextContent

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

@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"],
            },
        )
    ]

@server.call_tool()
async def call_tool(name: str, arguments: dict) -> list[TextContent]:
    if name == "get_weather":
        weather = await fetch_weather(arguments["city"])
        return [TextContent(type="text", text=weather)]
    raise ValueError(f"Unknown tool: {name}")

async def main():
    async with stdio_server() as (read_stream, write_stream):
        await server.run(read_stream, write_stream)
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

# 7.3.3 配置与运行

在 Claude Desktop 中配置:

{
  "mcpServers": {
    "weather": {
      "command": "node",
      "args": ["path/to/weather-server/index.js"],
      "env": {
        "API_KEY": "your-api-key-here"
      }
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11

# 7.4 MCP 工具调用的完整流程

下图展示了从用户提问到工具调用返回的完整流程:

用户提问 → LLM 分析 → 需要调用工具
                         ↓
            Host 请求 Client 获取工具列表
                         ↓
            Client 向 Server 发送 ListTools 请求
                         ↓
            Server 返回工具列表(名称、描述、参数 Schema)
                         ↓
            Client 将工具列表传递给 Host
                         ↓
            Host 将工具描述注入 LLM 的 Prompt
                         ↓
            LLM 返回工具调用请求(函数名 + 参数)
                         ↓
            Host 将调用请求交给 Client
                         ↓
            Client 向 Server 发送 CallTool 请求
                         ↓
            Server 执行具体操作并返回结果
                         ↓
            Client 将结果返回 Host
                         ↓
            Host 将结果注入 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

# 7.4.1 关键协议方法

MCP 定义了以下核心协议方法:

生命周期方法:

方法 方向 说明
initialize Client → Server 初始化连接,协商能力
initialized Client → Server 通知 Server 初始化完成
ping 双向 心跳检测
notifications/initialized Client → Server 初始化完成通知

工具相关方法:

方法 方向 说明
tools/list Client → Server 获取可用工具列表
tools/call Client → Server 调用指定工具

资源相关方法:

方法 方向 说明
resources/list Client → Server 列举可用的资源 URI
resources/read Client → Server 读取指定资源
resources/subscribe Client → Server 订阅资源变更通知
resources/unsubscribe Client → Server 取消订阅

提示模板相关方法:

方法 方向 说明
prompts/list Client → Server 获取提示模板列表
prompts/get Client → Server 获取指定模板的内容

# 7.5 MCP 的高级特性

# 7.5.1 资源模板(Resource Templates)

资源模板允许 Server 声明动态资源 URI 的模式,例如 file://{path} 可以匹配任意文件路径。

server.setRequestHandler(ListResourceTemplatesRequestSchema, async () => ({
  resourceTemplates: [
    {
      uriTemplate: "file://{path}",
      name: "Project File",
      description: "访问项目中的任意文件",
    },
  ],
}));
1
2
3
4
5
6
7
8
9

# 7.5.2 提示模板(Prompts)

Server 可以提供可复用的提示模板,包含动态参数。

server.setRequestHandler(ListPromptsRequestSchema, async () => ({
  prompts: [
    {
      name: "code_review",
      description: "代码审查提示模板",
      arguments: [
        {
          name: "language",
          description: "编程语言",
          required: true,
        },
      ],
    },
  ],
}));
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 7.5.3 Roots(根目录列表)

Client 在初始化时可以告知 Server 允许访问的根目录列表,实现沙箱化的文件访问。

{
  "roots": [
    {
      "uri": "file:///home/user/projects/my-app",
      "name": "My App"
    }
  ]
}
1
2
3
4
5
6
7
8

# 7.5.4 Sampling(反向采样)

MCP 允许 Server 反向请求 LLM 生成文本。这为工具提供了"主动思考"的能力。例如,一个代码分析工具在发现代码异味时,可以请求 LLM 生成改进建议。Sampling 请求会经过 Client,Client 可以执行内容安全策略(如敏感信息过滤)。

// Server 端发起 Sampling 请求
const response = await server.requestSampling({
  messages: [
    {
      role: "user",
      content: {
        type: "text",
        text: "分析这段代码中的设计模式",
      },
    },
  ],
  maxTokens: 1000,
});
1
2
3
4
5
6
7
8
9
10
11
12
13

# 7.5.5 通知机制

MCP 支持资源变更通知。当资源发生变化时,Server 可以主动通知 Client,Client 再决定是否需要重新获取。

// Server 端发送通知
server.sendResourceUpdated("file:///config.json");
1
2

# 7.6 开发与调试工具

# MCP Inspector

MCP Inspector 是官方提供的可视化调试工具,可以连接到 MCP Server 并进行交互式测试。

npx @modelcontextprotocol/inspector node path/to/server.js
1

该工具提供:

  • 工具列表查看
  • 工具调用测试
  • 资源浏览
  • 实时日志查看

# MCP 的开发原则

  1. 单一职责:每个 MCP Server 专注于一个领域的能力,避免大而全的"上帝服务"。
  2. 明确的能力声明:在初始化时清晰地声明支持的能力,方便 Client 进行调度决策。
  3. 完善的错误处理:通过错误码和错误信息提供可操作的反馈,而不是简单的 "Error occurred"。
  4. 安全的参数校验:对输入参数进行严格的校验和清理,防止注入攻击。
  5. 幂等性设计:对于可能重复执行的工具调用(如发送邮件),设计为幂等操作或提供去重机制。
  6. 恰当的缓存策略:对于耗时的资源读取操作,实现合适的缓存机制。

# 补充八股

Q:MCP 与 Function Calling 有什么关系?

A: Function Calling 是大模型本身的能力,指模型能够理解并输出结构化的函数调用参数。而 MCP 是工具调用流程的标准化协议,它包括了工具发现、调用、结果返回的完整流程。两者是互补关系:Function Calling 解决"模型如何理解工具",MCP 解决"工具如何被调用和管理"。

Q:MCP 如何保证安全?

A: MCP 通过多层机制保障安全:第一层是进程隔离,工具运行在独立的 Server 进程中;第二层是 Roots 机制限制文件系统访问范围;第三层是 Sampling 请求经过 Client 的内容安全策略过滤;第四层是 Server 的能力声明机制让 Client 能够精确控制开放的能力。

Q:MCP 和普通 API 有什么区别?

A: 普通 API 是静态的、预定义的接口,需要开发者手动集成和调用。MCP 提供了动态发现能力,LLM 应用可以在运行时动态获取工具列表和调用方式,同时 MCP 还提供了标准化的生命周期管理、安全隔离、通知机制等能力,更适合 AI Agent 场景。

Q:MCP Server 可以调用其他 MCP Server 吗?

A: 可以。MCP Server 可以同时作为另一个 MCP Server 的 Client,形成服务链。这种架构适合需要组合多个工具能力的场景,但需要注意循环调用和性能问题。

Q:MCP 的 Resource 和 Tool 有什么区别?

A: Resource 主要用于读取数据,是只读的,类似于 RESTful 中的 GET 请求。Tool 用于执行操作,可以修改状态,类似于 POST 请求。Resource 通过 URI 标识和访问,支持订阅变更通知;Tool 通过名称调用,可以接受参数并返回执行结果。

# 面试八股

Q:MCP 的通信协议基于什么标准?

A: MCP 基于 JSON-RPC 2.0 协议,所有请求和响应都遵循 JSON-RPC 2.0 规范。支持 stdio 和 SSE 两种传输方式,分别适用于本地和远程场景。

Q:MCP 的核心概念有哪些?

A: MCP Host(LLM 应用)、MCP Client(协议客户端)、MCP Server(工具服务)、Transport(传输层,stdio/SSE)、Capability(能力声明)、Resource(数据资源)、Tool(工具)、Prompt(提示模板)、Sampling(反向采样)、Roots(根目录列表)。

Q:MCP 连接的生命周期包括哪些阶段?

A: 三个阶段:初始化(交换能力信息、确认协议版本)、运行(工具调用、资源访问等操作)、关闭(终止连接、释放资源)。

Q:MCP Server 如何声明支持的能力?

A: 在初始化时通过 capabilities 字段声明,包括 tools、resources、prompts 等能力。Client 可以根据 Server 的能力声明来决定如何使用该 Server。

Q:MCP 中的 Sampling 机制是什么?

A: Sampling 允许 Server 反向请求 LLM 生成文本,为工具提供"主动思考"的能力。该请求会经过 Client,Client 可以执行内容安全策略过滤。Server 在调用 sampling 时可以提供 system prompt、messages、模型参数等。

Q:MCP 如何实现资源变更通知?

A: 通过 resources/subscriberesources/unsubscribe 方法实现。Client 可以订阅特定资源的变更通知,当资源发生变化时 Server 会主动发送通知给 Client。

# 课后练习

# 第 1 题(单选)

MCP 协议基于以下哪种协议标准?

A. RESTful API B. GraphQL C. JSON-RPC 2.0 D. gRPC

答案与解析

答案:C

解析: MCP 协议基于 JSON-RPC 2.0 标准。JSON-RPC 2.0 是一种轻量级的远程过程调用协议,使用 JSON 格式进行数据交换。MCP 中的每个请求和响应都遵循 JSON-RPC 2.0 规范,包括固定的字段结构(jsonrpc、id、method、params 等)。

# 第 2 题(单选)

以下哪项不是 MCP 支持的传输方式?

A. stdio(标准输入输出) B. SSE(Server-Sent Events) C. WebSocket D. gRPC

答案与解析

答案:D

解析: MCP 支持两种传输方式:stdio 和 SSE。stdio 适用于本地工具和开发环境,通过进程间通信实现;SSE 适用于远程服务和生产环境,基于 HTTP 协议。gRPC 和 WebSocket 目前不是 MCP 标准支持的传输方式。

# 第 3 题(多选)

MCP 中的核心概念包括哪些?

A. MCP Host B. MCP Client C. MCP Server D. MCP Router

答案与解析

答案:A、B、C

解析: MCP 的核心概念包括 MCP Host(需要访问数据的 LLM 应用程序)、MCP Client(与 MCP Server 建立一对一连接的协议客户端)、MCP Server(通过标准协议对外暴露特定能力的轻量级服务程序)。MCP Router 不是 MCP 规范中的核心概念。

# 第 4 题(单选)

在 MCP 中,以下哪种机制用于限制文件系统访问范围?

A. Capability B. Roots C. Sampling D. Transport

答案与解析

答案:B

解析: Roots(根目录列表)是 MCP 中用于实现沙箱化文件访问的机制。Client 在初始化时可以告知 Server 允许访问的根目录列表,Server 只能访问这些指定目录中的文件,从而实现安全隔离。

# 第 5 题(多选)

以下哪些属于 MCP 定义的协议方法?

A. tools/list B. tools/call C. tools/execute D. tools/register

答案与解析

答案:A、B

解析: MCP 定义了 tools/list 用于获取可用工具列表,tools/call 用于调用指定工具。tools/executetools/register 不是 MCP 协议标准方法。

# 第 6 题(单选)

MCP 连接的生命周期顺序是?

A. 运行 → 初始化 → 关闭 B. 初始化 → 关闭 → 运行 C. 初始化 → 运行 → 关闭 D. 运行 → 关闭 → 初始化

答案与解析

答案:C

解析: MCP 连接的生命周期分为三个阶段:初始化(交换能力信息,确认协议版本)、运行(进行工具调用、资源访问等操作)、关闭(终止连接,释放资源)。

# 第 7 题(单选)

MCP 中,Sampling 机制的主要作用是?

A. 提高工具调用性能 B. 允许 Server 反向请求 LLM 生成文本 C. 实现负载均衡 D. 缓存工具调用结果

答案与解析

答案:B

解析: Sampling 机制允许 MCP Server 反向请求 LLM 生成文本,为工具提供了"主动思考"的能力。例如,代码分析工具在发现代码问题时,可以请求 LLM 生成改进建议。Sampling 请求会经过 Client,由 Client 执行内容安全策略过滤。

# 第 8 题(单选)

MCP 中 Resource 和 Tool 的主要区别是?

A. Resource 只读,Tool 可执行操作 B. Resource 更快,Tool 更慢 C. Resource 用于本地,Tool 用于远程 D. 没有区别

答案与解析

答案:A

解析: Resource 主要用于读取数据,是只读的,类似于 RESTful 中的 GET 请求。Tool 用于执行操作,可以修改状态,类似于 POST 请求。Resource 通过 URI 标识和访问,支持订阅变更通知;Tool 通过名称调用,可以接受参数并返回执行结果。

# 第 9 题(多选)

MCP 支持的安全机制包括?

A. 进程隔离 B. Roots 目录限制 C. Sampling 内容过滤 D. 能力声明机制

答案与解析

答案:A、B、C、D

解析: MCP 通过多层机制保障安全:进程隔离(工具运行在独立的 Server 进程中)、Roots 机制(限制文件系统访问范围)、Sampling 内容过滤(Client 执行内容安全策略)、能力声明机制(Client 精确控制开放的能力)。这些都是 MCP 安全体系的重要组成部分。

# 第 10 题(单选)

MCP Server 的初始化顺序是?

A. Client 先声明能力,Server 再声明能力 B. Server 先声明能力,Client 再声明能力 C. Client 和 Server 同时声明能力 D. 不需要能力声明

答案与解析

答案:B

解析: 在 MCP 的初始化阶段,Client 先发送 initialize 请求,Server 回复自己的能力信息(包括协议版本、支持的功能等),然后 Client 确认并发送 initialized 通知,之后 Client 再声明自己的能力。这种顺序确保了连接的建立和能力的协商是清晰、有序的。