引言
随着AI应用的快速发展,如何让大语言模型(LLM)安全、标准化地访问外部工具和数据源,成为了一个关键问题。
MCP(Model Context Protocol,模型上下文协议) 是Anthropic推出的开放协议,旨在为AI模型与外部系统之间建立标准化的通信接口。
什么是MCP?
核心定义
MCP是一个开放协议,它标准化了AI模型如何连接外部数据源和工具的方式。通过MCP,开发者可以:
- 为AI模型提供结构化工具
- 让模型安全地访问外部资源
- 实现跨平台的工具复用
类比理解
| 类比 | 说明 |
|---|---|
| USB接口 | 就像USB统一了外设连接标准 |
| HTTP协议 | 就像HTTP统一了Web通信标准 |
| SQL | 就像SQL统一了数据库查询标准 |
MCP正在成为AI工具连接的标准协议。
MCP vs Function Calling
对比分析
| 特性 | Function Calling | MCP |
|---|---|---|
| 厂商绑定 | 特定厂商(如OpenAI) | 开放标准 |
| 工具复用 | 难以跨平台复用 | 一次开发,到处使用 |
| 安全性 | 应用层自行实现 | 协议层标准化 |
| 能力协商 | 有限 | 完整的协商机制 |
| 生态 | 各自为政 | 统一生态 |
Function Calling 示例
# OpenAI Function Calling
functions = [
{
"name": "get_weather",
"description": "获取天气信息",
"parameters": {
"type": "object",
"properties": {
"location": {"type": "string"},
"unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
},
"required": ["location"]
}
}
]
response = openai.chat.completions.create(
model="gpt-4",
messages=messages,
functions=functions,
function_call="auto"
)
MCP 示例
{
"tools": [
{
"name": "get_weather",
"description": "获取天气信息",
"inputSchema": {
"type": "object",
"properties": {
"location": {"type": "string"},
"unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
},
"required": ["location"]
}
}
]
}
MCP的优势在于标准化和可移植性。
MCP架构概览
核心组件
┌─────────────────────────────────────────────────────────┐
│ MCP 架构 │
├─────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ MCP Client │◄───────►│ MCP Server │ │
│ │ (客户端) │ JSON-RPC │ (服务端) │ │
│ └──────┬───────┘ └──────┬───────┘ │
│ │ │ │
│ │ │ │
│ ▼ ▼ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ LLM │ │ 外部资源 │ │
│ │ (大模型) │ │ (工具/数据) │ │
│ └──────────────┘ └──────────────┘ │
│ │
└─────────────────────────────────────────────────────────┘
通信流程
1. 连接建立
Client ──► Server: initialize
Server ──► Client: initialize response
2. 能力协商
Client ──► Server: tools/list
Server ──► Client: 可用工具列表
3. 工具调用
Client ──► Server: tools/call
Server ──► Client: 执行结果
4. 资源访问
Client ──► Server: resources/read
Server ──► Client: 资源内容
MCP协议规范
1. 消息格式
MCP使用JSON-RPC 2.0作为通信协议:
// 请求消息
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "get_weather",
"arguments": {
"location": "北京",
"unit": "celsius"
}
}
}
// 响应消息
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"content": [
{
"type": "text",
"text": "北京今天晴,25°C"
}
],
"isError": false
}
}
2. 工具定义
{
"tools": [
{
"name": "search_documents",
"description": "搜索文档内容",
"inputSchema": {
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "搜索关键词"
},
"limit": {
"type": "number",
"description": "返回结果数量",
"default": 10
}
},
"required": ["query"]
}
}
]
}
3. 资源定义
{
"resources": [
{
"uri": "file:///docs/api-reference.md",
"name": "API参考文档",
"mimeType": "text/markdown",
"description": "完整的API接口文档"
}
]
}
实战:搭建MCP Server
1. 环境准备
# 创建项目
mkdir my-mcp-server
cd my-mcp-server
npm init -y
# 安装依赖
npm install @modelcontextprotocol/sdk zod
# TypeScript支持
npm install -D typescript @types/node
npx tsc --init
2. 基础Server实现
// server.ts
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
CallToolRequestSchema,
ListToolsRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
import { z } from "zod";
// 定义工具参数
const CalculatorArgs = z.object({
expression: z.string().describe("数学表达式"),
});
// 创建Server
const server = new Server(
{
name: "calculator-server",
version: "1.0.0",
},
{
capabilities: {
tools: {},
},
}
);
// 处理工具列表请求
server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: [
{
name: "calculate",
description: "计算数学表达式",
inputSchema: {
type: "object",
properties: {
expression: {
type: "string",
description: "数学表达式,如 '2 + 2'",
},
},
required: ["expression"],
},
},
],
};
});
// 处理工具调用请求
server.setRequestHandler(CallToolRequestSchema, async (request) => {
if (request.params.name === "calculate") {
const args = CalculatorArgs.parse(request.params.arguments);
try {
// 安全计算
const result = eval(args.expression);
return {
content: [
{
type: "text",
text: `结果: ${result}`,
},
],
};
} catch (error) {
return {
content: [
{
type: "text",
text: `计算错误: ${error}`,
},
],
isError: true,
};
}
}
throw new Error(`未知工具: ${request.params.name}`);
});
// 启动Server
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("Calculator MCP Server running on stdio");
}
main().catch(console.error);
3. 配置文件
// mcp-config.json
{
"mcpServers": {
"calculator": {
"command": "node",
"args": ["dist/server.js"],
"env": {
"NODE_ENV": "production"
}
}
}
}
MCP Client集成
Python Client示例
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
# 配置Server参数
server_params = StdioServerParameters(
command="python",
args=["server.py"],
env=None
)
async def use_mcp_server():
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write) as session:
# 初始化
await session.initialize()
# 获取工具列表
tools = await session.list_tools()
print(f"可用工具: {[tool.name for tool in tools.tools]}")
# 调用工具
result = await session.call_tool(
"calculate",
arguments={"expression": "2 + 2"}
)
print(f"结果: {result}")
与LangChain集成
from langchain_mcp_adapters.tools import load_mcp_tools
from langgraph.prebuilt import create_react_agent
# 加载MCP工具
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()
# 转换为LangChain工具
tools = await load_mcp_tools(session)
# 创建Agent
agent = create_react_agent(model, tools)
# 使用Agent
response = await agent.ainvoke(
{"messages": "计算 15 * 23"}
)
MCP工具生态
官方工具
| 工具 | 功能 | 链接 |
|---|---|---|
| Filesystem | 文件系统操作 | github.com/modelcontextprotocol/servers |
| GitHub | GitHub API集成 | github.com/modelcontextprotocol/servers |
| PostgreSQL | 数据库查询 | github.com/modelcontextprotocol/servers |
| Puppeteer | 浏览器自动化 | github.com/modelcontextprotocol/servers |
社区工具
| 工具 | 功能 | 作者 |
|---|---|---|
| Brave Search | 搜索功能 | community |
| Slack | Slack集成 | community |
| Notion | Notion集成 | community |
MCP最佳实践
1. 工具设计原则
// 好的工具设计
{
name: "search_code",
description: "在代码库中搜索特定模式。" +
"支持正则表达式和简单文本匹配。" +
"返回匹配的文件路径和行号。",
inputSchema: {
type: "object",
properties: {
pattern: {
type: "string",
description: "搜索模式,可以是正则或普通字符串"
},
fileType: {
type: "string",
description: "文件类型过滤,如 '.ts', '.py'",
optional: true
}
},
required: ["pattern"]
}
}
2. 错误处理
server.setRequestHandler(CallToolRequestSchema, async (request) => {
try {
const result = await executeTool(request.params);
return {
content: [{ type: "text", text: result }],
isError: false,
};
} catch (error) {
return {
content: [
{
type: "text",
text: `错误: ${error.message}`,
},
],
isError: true,
};
}
});
3. 安全性考虑
// 输入验证
const safeEval = (expression: string): number => {
// 只允许数字和基本运算符
if (!/^[\d+\-*/.()\s]+$/.test(expression)) {
throw new Error("非法字符");
}
return eval(expression);
};
// 权限控制
const checkPermission = (resource: string): boolean => {
const allowedPaths = ["/home/user/docs", "/tmp"];
return allowedPaths.some(path => resource.startsWith(path));
};
MCP的未来
发展趋势
- 标准化 - 成为AI工具连接的事实标准
- 生态繁荣 - 丰富的工具市场
- 多模态支持 - 支持图像、音频等资源
- 企业级特性 - 审计、监控、权限管理
与Agent的关系
MCP是Agent的基础设施:
Agent (决策层)
│
▼
MCP (协议层)
│
▼
Tools (执行层)
总结
MCP协议为AI工具连接提供了标准化解决方案:
✅ 开放标准 - 不绑定特定厂商
✅ 工具复用 - 一次开发,到处使用
✅ 安全可靠 - 协议层安全机制
✅ 生态丰富 - growing tool ecosystem
下一步学习建议:
本文最后更新于 2024-01-25,如有问题欢迎在社区讨论。