2025 年底 Anthropic 发布 Model Context Protocol(MCP)以来,这个协议已经迅速成为 AI 工具调用的事实标准——GitHub 上 MCP 相关仓库超过 5000 个,Cursor、Claude Desktop、Continue 等主流 AI 编程工具全部支持。MCP 协议定义了一套标准化的方式,让大模型(LLM)与外部工具、数据源进行交互,本质上是 AI 时代的"USB 接口"。如果你正在构建 AI Agent 或者想让自己的工具被 LLM 调用,理解 MCP 已经不是可选项,而是必修课。
🔐 一、MCP 架构原理与核心概念
1.1 为什么需要 MCP?
在 MCP 出现之前,每个 AI 应用都需要自己实现工具调用的集成逻辑。ChatGPT 用 Function Calling,Claude 用 Tool Use,各家格式不同、协议不同。这导致了一个严重的碎片化问题:你写了一个"读取数据库"的工具,要在 Claude Desktop 里用一套代码,换到 Cursor 里又要改一套。
📌 记住:MCP 的核心价值不是技术创新,而是标准化。它把"LLM 调用外部工具"这件事从各厂商的私有协议中抽离出来,形成一个开放标准。
MCP 采用经典的 Client-Server 架构:
- MCP Host:发起请求的 AI 应用(如 Claude Desktop、Cursor)
- MCP Client:Host 内部的协议客户端,负责与 Server 通信
- MCP Server:暴露工具(Tool)、资源(Resource)、提示模板(Prompt)的服务端
通信方式支持两种传输层:
| 传输方式 | 适用场景 | 连接模型 | 延迟 | 复杂度 |
|---|---|---|---|---|
| stdio | 本地进程 | 1:1 | 极低(进程间通信) | ⭐ 简单 |
| SSE (Streamable HTTP) | 远程服务 | 1:N | 中等(网络往返) | ⭐⭐⭐ 较复杂 |
⚠️ **警告:**MCP 规范在 2025 年 3 月移除了旧版
sse传输,统一为streamable-http。如果你看到教程还在用旧的 SSE 端点,说明内容已过时。
1.2 三大原语:Tool、Resource、Prompt
MCP 定义了三个核心原语,理解它们的区别是正确使用 MCP 的前提:
- ✅ Tool(工具):模型可以主动调用的函数,如搜索网页、执行 SQL、发送邮件。这是最常用的原语。
- ✅ Resource(资源):模型可以读取的数据源,如文件内容、数据库记录。由 Client 主动拉取,不是模型调用。
- ✅ Prompt(提示模板):预定义的提示词模板,如"代码审查"模板。由用户选择触发,不是模型自动调用。
💡 **提示:**大多数 MCP Server 只需要实现 Tool。Resource 和 Prompt 是可选的,适合需要暴露结构化数据或工作流的场景。
1.3 协议握手流程
MCP 使用 JSON-RPC 2.0 作为消息格式。一次完整的交互流程如下:
Client Server
| |
|--- initialize (能力协商) ----->|
|<-- initialize result ---------|
|--- initialized 通知 ---------->|
| |
|--- tools/list (发现工具) ----->|
|<-- tools/list result ---------|
| |
|--- tools/call (调用工具) ----->|
|<-- tools/call result ---------|
初始化阶段的核心是能力协商——Client 和 Server 互相告知自己支持哪些功能:
// Client 发送的 initialize 请求
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-03-26",
"capabilities": {
"roots": { "listChanged": true }
},
"clientInfo": {
"name": "my-client",
"version": "1.0.0"
}
}
}
🚀 二、从零构建 MCP Server 实战
2.1 项目初始化
我们用 TypeScript 构建一个实用的 MCP Server——JSON 处理工具集,提供 JSON 格式化、校验、路径提取等功能。这正好是开发者日常高频使用的操作。
# 初始化项目
mkdir mcp-json-tools && cd mcp-json-tools
npm init -y
npm install @modelcontextprotocol/sdk zod
npm install -D typescript @types/node
npx tsc --init --outDir dist --rootDir src
📌 记住:
@modelcontextprotocol/sdk是官方提供的 TypeScript SDK,是目前最成熟的 MCP 开发库。Python SDK 为mcp(PyPI 包名),但 TypeScript 版本生态更完善。
2.2 实现核心 Server
// src/server.ts
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
// 创建 MCP Server 实例
const server = new McpServer({
name: "json-tools",
version: "1.0.0",
});
// Tool 1: JSON 格式化
server.tool(
"format_json",
"将 JSON 字符串格式化为易读的缩进格式",
{
input: z.string().describe("要格式化的 JSON 字符串"),
indent: z.number().default(2).describe("缩进空格数,默认 2"),
},
async ({ input, indent }) => {
try {
const parsed = JSON.parse(input);
const formatted = JSON.stringify(parsed, null, indent);
return {
content: [{ type: "text", text: formatted }],
};
} catch (err) {
return {
content: [{ type: "text", text: `JSON 解析错误: ${(err as Error).message}` }],
isError: true,
};
}
}
);
// Tool 2: JSON Path 提取(从嵌套 JSON 中按路径取值)
server.tool(
"json_path_extract",
"从 JSON 中按点分路径提取值,如 user.address.city",
{
input: z.string().describe("JSON 字符串"),
path: z.string().describe("点分路径,如 data.users.0.name"),
},
async ({ input, path }) => {
try {
const obj = JSON.parse(input);
const keys = path.split(".");
let current: any = obj;
for (const key of keys) {
if (current === undefined || current === null) {
return {
content: [{ type: "text", text: `路径 "${path}" 不存在` }],
isError: true,
};
}
current = Array.isArray(current) ? current[Number(key)] : current[key];
}
return {
content: [{ type: "text", text: JSON.stringify(current, null, 2) }],
};
} catch (err) {
return {
content: [{ type: "text", text: `错误: ${(err as Error).message}` }],
isError: true,
};
}
}
);
// Tool 3: JSON Schema 生成(从样本数据推断 Schema)
server.tool(
"generate_schema",
"从 JSON 样本数据推断出 JSON Schema",
{
input: z.string().describe("JSON 样本数据"),
},
async ({ input }) => {
try {
const sample = JSON.parse(input);
const schema = inferSchema(sample);
return {
content: [{ type: "text", text: JSON.stringify(schema, null, 2) }],
};
} catch (err) {
return {
content: [{ type: "text", text: `错误: ${(err as Error).message}` }],
isError: true,
};
}
}
);
// Schema 推断辅助函数
function inferSchema(value: any): any {
if (value === null) return { type: "null" };
if (Array.isArray(value)) {
return {
type: "array",
items: value.length > 0 ? inferSchema(value[0]) : {},
};
}
if (typeof value === "object") {
const properties: Record<string, any> = {};
for (const [key, val] of Object.entries(value)) {
properties[key] = inferSchema(val);
}
return { type: "object", properties, required: Object.keys(value) };
}
const typeMap: Record<string, string> = {
string: "string", number: "number", boolean: "boolean",
};
return { type: typeMap[typeof value] || "string" };
}
// Resource:暴露一个示例 JSON Schema 参考
server.resource(
"json-schema-reference",
"schema://json-schema-reference",
async (uri) => ({
contents: [
{
uri: uri.href,
mimeType: "application/json",
text: JSON.stringify({
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"description": "JSON Schema 示例参考",
}, null, 2),
},
],
})
);
// 启动 Server(stdio 传输)
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("JSON Tools MCP Server 已启动");
}
main().catch(console.error);
2.3 配置 package.json
{
"name": "mcp-json-tools",
"version": "1.0.0",
"type": "module",
"main": "dist/server.js",
"scripts": {
"build": "tsc",
"start": "node dist/server.js"
}
}
编译并测试:
npm run build
# 用 MCP Inspector 测试(官方调试工具)
npx @modelcontextprotocol/inspector node dist/server.js
⚠️ **警告:**MCP Server 通过
console.error输出日志,因为stdout被用于 JSON-RPC 通信。绝对不要在 MCP Server 中使用console.log输出调试信息,否则会破坏协议消息。
2.4 在 Claude Desktop 中注册
编辑 claude_desktop_config.json:
{
"mcpServers": {
"json-tools": {
"command": "node",
"args": ["/absolute/path/to/mcp-json-tools/dist/server.js"]
}
}
}
重启 Claude Desktop 后,你会在工具列表中看到 format_json、json_path_extract、generate_schema 三个工具。直接对话"帮我格式化这个 JSON"即可触发调用。
💡 三、构建 MCP Client 与高级技巧
3.1 Client 端代码
如果你要构建自己的 AI 应用,需要在 Client 端连接 MCP Server:
// src/client.ts
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
async function main() {
// 创建 stdio 传输,启动 Server 子进程
const transport = new StdioClientTransport({
command: "node",
args: ["dist/server.js"],
});
const client = new Client({
name: "my-client",
version: "1.0.0",
});
// 连接到 Server
await client.connect(transport);
console.log("已连接到 MCP Server");
// 发现可用工具
const tools = await client.listTools();
console.log("可用工具:", tools.tools.map((t) => t.name));
// 调用 format_json 工具
const result = await client.callTool({
name: "format_json",
arguments: {
input: '{"name":"张三","age":30,"skills":["TypeScript","Go"]}',
indent: 4,
},
});
console.log("格式化结果:", result.content);
// 读取 Resource
const resource = await client.readResource({
uri: "schema://json-schema-reference",
});
console.log("Schema 参考:", resource.contents);
await client.close();
}
main().catch(console.error);
3.2 Streamable HTTP 远程传输
对于远程 MCP Server,使用 StreamableHTTPClientTransport:
// 远程 MCP Client 连接示例
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
const transport = new StreamableHTTPClientTransport(
new URL("https://your-server.com/mcp")
);
const client = new Client({ name: "remote-client", version: "1.0.0" });
await client.connect(transport);
Server 端对应的实现:
// 远程 MCP Server(Express + Streamable HTTP)
import express from "express";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
const app = express();
app.use(express.json());
app.post("/mcp", async (req, res) => {
const server = new McpServer({ name: "remote-tools", version: "1.0.0" });
// ... 注册 tools ...
const transport = new StreamableHTTPServerTransport({
sessionIdGenerator: undefined, // 无状态模式
});
await server.connect(transport);
await transport.handleRequest(req, res, req.body);
});
app.listen(3000, () => console.log("MCP Server 运行在 :3000/mcp"));
3.3 性能与安全避坑指南
在生产环境中使用 MCP,有几个关键的坑点需要注意:
❌ 错误写法:直接暴露危险工具
// 危险!允许执行任意 shell 命令
server.tool("run_shell", "执行 shell 命令", {
command: z.string(),
}, async ({ command }) => {
const result = execSync(command); // 任意代码执行!
return { content: [{ type: "text", text: result.toString() }] };
});
✅ 正确写法:白名单 + 参数校验
// 安全:白名单 + 超时 + 输出限制
import { execSync } from "child_process";
const ALLOWED_COMMANDS = ["ls", "cat", "wc", "du"];
server.tool("safe_shell", "执行受限制的 shell 命令", {
command: z.enum(ALLOWED_COMMANDS),
args: z.array(z.string()).max(10),
}, async ({ command, args }) => {
// 参数中禁止特殊字符
const sanitized = args.filter(a => /^[a-zA-Z0-9._/\-]+$/.test(a));
const full = `${command} ${sanitized.join(" ")}`;
const result = execSync(full, {
timeout: 5000, // 5 秒超时
maxBuffer: 1024 * 100, // 100KB 输出上限
});
return { content: [{ type: "text", text: result.toString() }] };
});
工具描述的质量直接决定 LLM 能否正确调用:
| 描述质量 | 示例 | LLM 调用准确率 |
|---|---|---|
| ❌ 模糊 | "处理数据" |
~30% |
| ⚠️ 一般 | "格式化 JSON" |
~70% |
| ✅ 精确 | "将 JSON 字符串格式化为带缩进的易读格式,支持自定义缩进空格数,默认 2 空格" |
~95% |
💡 **提示:**Tool 的
description是 LLM 决定是否调用该工具的唯一依据。把它写成你希望一个新手工程师读到的完整说明——包括功能、参数含义、返回值格式、使用限制。
3.4 调试与测试
MCP Inspector 是官方提供的可视化调试工具,可以单独测试每个 Tool:
# 启动 Inspector(会打开浏览器界面)
npx @modelcontextprotocol/inspector node dist/server.js
在 Inspector 中你可以:
- 查看 Server 声明的所有 Tool、Resource、Prompt
- 手动填写参数并调用 Tool
- 查看完整的 JSON-RPC 消息流
- 测试错误处理(传入非法参数)
📊 总结与工具推荐
MCP 协议的设计哲学是"简单但完备"——JSON-RPC + 三大原语 + stdio/HTTP 传输,覆盖了绝大多数 AI 工具集成场景。从零构建一个 MCP Server 的核心代码量不到 100 行,但要做好安全、描述、错误处理这些细节,需要对协议有深入理解。
⚡ **关键结论:**如果你正在构建 AI Agent 或工具链,MCP 是 2026 年最值得投入的协议标准。它的生态成熟度已经超过了大多数人的预期——从数据库查询到浏览器自动化,从代码搜索到 CI/CD 集成,几乎所有开发者常用工具都有对应的 MCP Server 实现。
推荐资源与工具:
- 🔧 MCP Official SDK (TypeScript) — 官方 TypeScript SDK
- 🔧 MCP Inspector — 可视化调试工具
- 🔧 MCP Server Registry — 官方 Server 仓库
- 🔧 Smithery — MCP Server 市场,一键安装
- 📖 MCP 规范文档 — 协议规范完整版
⚠️ **警告:**MCP 规范仍在快速演进中(当前版本 2025-03-26),关注规范更新是必做的功课。建议订阅 MCP 官方博客 获取变更通知。