Model Context Protocol 完全指南:AI Agent 开发者必读
深入解析 Model Context Protocol(MCP)的核心架构、工作原理和实战应用,帮助 AI Agent 开发者全面掌握这一革命性协议。
Model Context Protocol(MCP)正在重新定义 AI Agent 与外部世界交互的方式。如果你正在开发 AI Agent 应用,理解 MCP 不是可选项——它是你技术栈中不可或缺的一环。
这篇文章将从零开始,带你深入理解 MCP 的每一个关键概念,并通过实际代码示例展示如何构建你的第一个 MCP 生态应用。
什么是 Model Context Protocol
Model Context Protocol 是 Anthropic 于 2024 年底发布的开放标准协议,旨在为大语言模型提供统一的方式来连接外部数据源、工具和服务。你可以把它理解为 AI 领域的 USB-C 接口——一个通用的连接标准,让任何 LLM 应用都能无缝对接任何外部服务。
在 MCP 出现之前,每个 AI 应用都需要为每个外部服务编写定制化的集成代码。假设你要让一个 AI Agent 同时访问 GitHub、Slack 和数据库,你需要为每个服务编写不同的连接器。MCP 统一了这个过程。
核心设计哲学
MCP 的设计遵循了几个重要原则:
协议优先——MCP 定义的是一套通信协议,而非具体的实现。任何符合协议规范的服务都可以被任何支持 MCP 的客户端调用。
能力发现——MCP Server 在启动时会声明自己提供的所有能力(Tools、Resources、Prompts),Client 无需硬编码就能动态发现和使用这些能力。
安全隔离——MCP 在 LLM 和外部服务之间建立了一层隔离,Client 可以对所有工具调用进行权限控制和审计。
MCP 的架构模型
MCP 采用经典的客户端-服务器架构,但有其独特之处。
┌─────────────────┐
│ LLM 应用 │
│ (Host 应用) │
│ │
│ ┌───────────┐ │
│ │MCP Client│ │
│ └─────┬─────┘ │
└────────┼────────┘
│ JSON-RPC 2.0
│
┌─────┴─────┐
│MCP Server │
│ │
│ Tools │
│ Resources │
│ Prompts │
└─────┬─────┘
│
┌─────┴─────┐
│外部服务 │
│(API/DB/FS)│
└───────────┘
MCP Server 的三种能力
**Tools(工具)**是 LLM 可以调用的操作。比如 search_files、send_email、query_database。Tool 的定义包含名称、描述和 JSON Schema 格式的参数规范。LLM 根据上下文决定何时调用哪个工具。
**Resources(资源)**是 LLM 可以读取的数据。与 Tool 不同,Resource 是被动的数据提供者,不执行任何操作。比如文件内容、数据库记录、API 响应等。
**Prompts(提示模板)**是预定义的交互模式,帮助 LLM 更好地使用 Server 提供的能力。它们类似于 API 的使用说明,可以引导 LLM 以正确的方式调用工具。
通信协议
MCP 使用 JSON-RPC 2.0 作为消息格式。所有通信都是请求-响应模式,支持以下消息类型:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "read_file",
"arguments": {
"path": "/home/user/document.txt"
}
}
}
Server 的响应同样遵循 JSON-RPC 格式:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"content": [
{
"type": "text",
"text": "文件内容..."
}
]
}
}
传输层:MCP 如何通信
MCP 支持两种标准传输机制:
stdio 传输
stdio 是最简单的传输方式——MCP Server 作为子进程运行,通过标准输入输出与 Client 通信。这种方式适合本地工具集成,比如文件系统访问、本地数据库查询等。
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
const server = createServer();
const transport = new StdioServerTransport();
await server.connect(transport);
HTTP+SSE 传输
对于远程服务,MCP 支持基于 HTTP 的 Server-Sent Events 传输。Client 通过 HTTP POST 发送请求,Server 通过 SSE 流式返回响应。这种方式适合云端部署和多客户端场景。
import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
const transport = new SSEServerTransport('/messages', response);
await server.connect(transport);
快速上手:构建你的第一个 MCP Server
让我们用 TypeScript 构建一个实用的 MCP Server——一个能读写文件、搜索内容的文件管理工具。
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { z } from 'zod';
import * as fs from 'fs/promises';
import * as path from 'path';
const server = new McpServer({
name: 'file-manager',
version: '1.0.0',
});
// 定义工具:读取文件
server.tool(
'read_file',
'读取指定路径的文件内容',
{ filePath: z.string().describe('文件的绝对路径') },
async ({ filePath }) => {
try {
const content = await fs.readFile(filePath, 'utf-8');
return {
content: [{ type: 'text', text: content }],
};
} catch (error) {
return {
content: [{ type: 'text', text: `错误:无法读取文件 ${filePath}` }],
isError: true,
};
}
}
);
// 定义工具:写入文件
server.tool(
'write_file',
'将内容写入指定路径的文件',
{
filePath: z.string().describe('文件路径'),
content: z.string().describe('要写入的内容'),
},
async ({ filePath, content }) => {
try {
await fs.mkdir(path.dirname(filePath), { recursive: true });
await fs.writeFile(filePath, content, 'utf-8');
return {
content: [{ type: 'text', text: `成功写入文件 ${filePath}` }],
};
} catch (error) {
return {
content: [{ type: 'text', text: `错误:写入失败` }],
isError: true,
};
}
}
);
// 定义资源:文件列表
server.resource(
'file-list',
'file://list',
async (uri) => {
const files = await fs.readdir(process.cwd());
return {
contents: [
{
uri: uri.href,
text: files.join('\n'),
},
],
};
}
);
// 启动服务
const transport = new StdioServerTransport();
await server.connect(transport);
这个 Server 提供了三个能力:读取文件、写入文件和列出当前目录的文件。
MCP Client:连接 LLM 与 Server
Client 端的职责是发现 Server 的能力并将 LLM 的意图转化为工具调用:
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
const client = new Client({ name: 'my-agent', version: '1.0.0' });
const transport = new StdioClientTransport({
command: 'node',
args: ['file-manager-server.js'],
});
await client.connect(transport);
// 发现工具
const { tools } = await client.listTools();
console.log('可用工具:', tools.map(t => t.name));
// 调用工具
const result = await client.callTool({
name: 'read_file',
arguments: { filePath: '/etc/hostname' },
});
console.log('文件内容:', result.content[0].text);
MCP 与 AI Agent 工作流
MCP 的真正价值在于它与 AI Agent 工作流的无缝集成。当你在 Claude 或其他 LLM 中使用 MCP 时,整个流程是这样的:
- 用户提问——“帮我看看这个项目的 README”
- LLM 分析——决定需要调用
read_file工具 - MCP Client 调用——将 LLM 的决定转化为 MCP 请求
- MCP Server 执行——读取文件并返回内容
- LLM 总结——基于文件内容生成回答
这个循环可以在一次对话中多次迭代,让 Agent 能够自主完成复杂的多步骤任务。
常见问题(FAQ)
MCP 和 Function Calling 有什么区别?
Function Calling 是 LLM 厂商提供的工具调用能力,而 MCP 是一个独立的协议标准。Function Calling 的工具定义通常与特定 LLM 绑定,MCP 的工具定义是通用的——同一个 MCP Server 可以被 Claude、GPT、Gemini 等任何支持 MCP 的客户端使用。
MCP Server 可以用哪些语言开发?
官方 SDK 支持 TypeScript 和 Python。由于 MCP 基于 JSON-RPC 协议,你也可以用任何语言实现 Server,只要遵循协议规范即可。社区已经有 Go、Rust、Java 等语言的非官方实现。
MCP 的安全性如何保障?
MCP 本身不定义安全策略,而是将安全控制交给 Client 实现。Client 可以对工具调用进行权限验证、速率限制和审计日志。对于 stdio 传输,操作系统级别的进程隔离提供了额外的安全层。
一个 Client 可以同时连接多个 Server 吗?
可以。这是 MCP 的核心优势之一——一个 LLM 应用可以同时连接多个 MCP Server,每个 Server 提供不同的能力。比如一个 Agent 可以同时使用文件管理 Server、数据库 Server 和邮件 Server。
总结
Model Context Protocol 为 AI Agent 开发提供了一个标准化的工具集成框架。它的价值不仅在于统一了通信协议,更在于建立了一个可扩展的生态系统——开发者可以为任何服务构建 MCP Server,而这些 Server 可以被任何支持 MCP 的 AI 应用使用。
在接下来的文章中,我们将深入探讨 MCP Server 的高级开发技巧、MCP Client 的实现细节,以及如何在生产环境中部署和优化 MCP 应用。