一、MCP概述
MCP(Model Context Protocol,模型上下文协议)是Anthropic提出的开放协议,用于连接AI模型和外部数据源、工具。
核心价值:
- 标准化接口
- 解耦模型和数据源
- 一次开发,多处使用
- 安全可控
解决的问题:
- 每个AI应用需要单独集成数据源
- 数据访问逻辑重复开发
- 安全和权限管理分散
二、MCP架构
核心概念
Host:AI应用,如Claude Desktop、IDE插件
Client:客户端,负责与Server通信
Server:服务器,提供资源和工具
Resource:资源,如文件、数据库记录
Tool:工具,可执行的操作
Prompt:提示模板
通信流程
1 2 3 4 5 6 7
| Host (Claude Desktop) ↓ Client ↓ JSON-RPC Server (MCP Server) ↓ Resource / Tool / Prompt
|
传输协议
Stdio:标准输入输出,本地进程通信
SSE:Server-Sent Events,HTTP长连接
三、MCP Server开发
项目结构
1 2 3 4 5
| my-mcp-server/ ├── src/ │ └── server.ts ├── package.json └── tsconfig.json
|
安装依赖
1 2 3
| npm init -y npm install @modelcontextprotocol/sdk npm install typescript @types/node -D
|
基本代码
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
| import { Server } from "@modelcontextprotocol/sdk/server/index.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
const server = new Server( { name: "my-mcp-server", version: "1.0.0" }, { capabilities: { resources: {}, tools: {} } } );
server.setRequestHandler(ListResourcesRequestSchema, async () => { return { resources: [ { uri: "file:///example.txt", name: "Example File", mimeType: "text/plain" } ] }; });
server.setRequestHandler(ReadResourceRequestSchema, async (request) => { const { uri } = request.params; return { contents: [ { uri, mimeType: "text/plain", text: "Hello from MCP" } ] }; });
server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ { name: "echo", description: "返回输入的文本", inputSchema: { type: "object", properties: { message: { type: "string", description: "要返回的消息" } }, required: ["message"] } } ] }; });
server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; if (name === "echo") { return { content: [ { type: "text", text: args.message } ] }; } throw new Error(`Unknown tool: ${name}`); });
const transport = new StdioServerTransport(); await server.connect(transport);
|
构建和运行
1 2
| npx tsc node build/server.js
|
四、提供资源
文件资源
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| server.setRequestHandler(ListResourcesRequestSchema, async () => { const files = await fs.readdir("./data"); return { resources: files.map(file => ({ uri: `file:///data/${file}`, name: file, mimeType: "text/plain" })) }; });
server.setRequestHandler(ReadResourceRequestSchema, async (request) => { const filePath = request.params.uri.replace("file://", ""); const content = await fs.readFile(filePath, "utf-8"); return { contents: [{ uri: request.params.uri, text: content }] }; });
|
数据库资源
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| server.setRequestHandler(ListResourcesRequestSchema, async () => { const tables = await db.query("SHOW TABLES"); return { resources: tables.map(table => ({ uri: `db:///table/${table.name}`, name: table.name, mimeType: "application/json" })) }; });
server.setRequestHandler(ReadResourceRequestSchema, async (request) => { const tableName = request.params.uri.split("/").pop(); const data = await db.query(`SELECT * FROM ${tableName} LIMIT 100`); return { contents: [{ uri: request.params.uri, mimeType: "application/json", text: JSON.stringify(data) }] }; });
|
五、提供工具
搜索工具
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
| server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ { name: "web_search", description: "搜索互联网", inputSchema: { type: "object", properties: { query: { type: "string", description: "搜索关键词" } }, required: ["query"] } } ] }; });
server.setRequestHandler(CallToolRequestSchema, async (request) => { if (request.params.name === "web_search") { const results = await searchEngine.search(request.params.arguments.query); return { content: [{ type: "text", text: JSON.stringify(results) }] }; } });
|
数据库操作工具
1 2 3 4 5 6 7 8 9 10 11
| { name: "query_database", description: "执行SQL查询", inputSchema: { type: "object", properties: { sql: { type: "string", description: "SQL语句" } }, required: ["sql"] } }
|
六、提供提示模板
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
| server.setRequestHandler(ListPromptsRequestSchema, async () => { return { prompts: [ { name: "analyze_data", description: "分析数据并生成报告", arguments: [ { name: "data_type", description: "数据类型", required: true } ] } ] }; });
server.setRequestHandler(GetPromptRequestSchema, async (request) => { if (request.params.name === "analyze_data") { return { messages: [ { role: "user", content: { type: "text", text: `请分析${request.params.arguments.data_type}类型的数据,生成详细报告` } } ] }; } });
|
七、配置Claude Desktop
编辑配置文件:
macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
Windows: %APPDATA%\Claude\claude_desktop_config.json
1 2 3 4 5 6 7 8
| { "mcpServers": { "my-server": { "command": "node", "args": ["/path/to/server.js"] } } }
|
八、调试MCP Server
使用MCP Inspector
1
| npx @modelcontextprotocol/inspector node build/server.js
|
打开 http://localhost:5173 查看和测试MCP Server。
日志调试
1
| console.error("Debug message");
|
九、最佳实践
安全考虑
- 验证所有输入参数
- 限制资源访问范围
- 实施权限控制
- 敏感操作需要确认
错误处理
1 2 3 4 5 6 7 8 9 10
| server.setRequestHandler(CallToolRequestSchema, async (request) => { try { } catch (error) { return { content: [{ type: "text", text: `Error: ${error.message}` }], isError: true }; } });
|
性能优化
- 缓存频繁访问的资源
- 分页返回大量数据
- 异步处理耗时操作
十、总结
MCP核心要点:
- 标准化协议连接AI和数据源
- 提供Resource、Tool、Prompt三种能力
- 使用TypeScript/Python开发Server
- 通过Stdio或SSE通信
- 注重安全和错误处理
MCP让AI应用可以安全、标准地访问外部数据和工具,是构建AI应用的重要基础设施。