一、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");  // 输出到stderr

九、最佳实践

安全考虑

  • 验证所有输入参数
  • 限制资源访问范围
  • 实施权限控制
  • 敏感操作需要确认

错误处理

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应用的重要基础设施。