抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

MCP(Model Context Protocol,模型上下文协议)是Anthropic推出的开放协议,用于标准化LLM应用与外部数据源和工具的连接方式。就像USB-C为设备提供了统一的连接标准一样,MCP为AI应用提供了连接各种数据源和工具的标准化方式。本文详细介绍MCP的架构设计、核心概念和实践方法。

为什么需要MCP

LLM应用的集成困境

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
┌─────────────────────────────────────────────────────────────────┐
│ 传统集成方式的问题 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 每个LLM应用都需要单独实现各种集成: │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Claude │ │ ChatGPT │ │ 其他LLM │ │
│ │ Desktop │ │ App │ │ 应用 │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
│ │ │ │ │
│ ┌────┴────┐ ┌────┴────┐ ┌────┴────┐ │
│ │自定义 │ │自定义 │ │自定义 │ │
│ │集成代码 │ │集成代码 │ │集成代码 │ │
│ └────┬────┘ └────┬────┘ └────┬────┘ │
│ │ │ │ │
│ └────────────────┼────────────────┘ │
│ │ │
│ ┌───────┬───────┬───┴───┬───────┬───────┐ │
│ ▼ ▼ ▼ ▼ ▼ ▼ │
│ ┌───┐ ┌───┐ ┌───┐ ┌───┐ ┌───┐ ┌───┐ │
│ │DB │ │Git│ │API│ │File│ │Slack│ │...│ │
│ └───┘ └───┘ └───┘ └───┘ └───┘ └───┘ │
│ │
│ 问题: │
│ 1. 每个应用重复实现相同的集成 │
│ 2. 不同实现质量参差不齐 │
│ 3. 难以维护和更新 │
│ 4. 安全性难以保证 │
│ │
└─────────────────────────────────────────────────────────────────┘

MCP的解决方案

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
┌─────────────────────────────────────────────────────────────────┐
│ MCP标准化连接 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 所有LLM应用通过统一的MCP协议连接: │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Claude │ │ IDE │ │ 其他LLM │ │
│ │ Desktop │ │ 插件 │ │ 应用 │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
│ │ │ │ │
│ └────────────────┼────────────────┘ │
│ │ │
│ MCP Protocol │
│ │ │
│ ┌───────────────────┼───────────────────┐ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │MCP │ │MCP │ │MCP │ │
│ │Server A │ │Server B │ │Server C │ │
│ └────┬────┘ └────┬────┘ └────┬────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────┐ ┌─────┐ ┌──────┐ │
│ │ DB │ │ Git │ │ APIs │ │
│ └─────┘ └─────┘ └──────┘ │
│ │
│ 优势: │
│ 1. 一次开发,处处可用 │
│ 2. 标准化的安全和权限模型 │
│ 3. 易于切换LLM提供商 │
│ 4. 社区共建的集成生态 │
│ │
└─────────────────────────────────────────────────────────────────┘

MCP核心架构

整体架构

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
┌─────────────────────────────────────────────────────────────────┐
│ MCP架构 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Host(宿主应用) │ │
│ │ Claude Desktop / IDE / AI Tools │ │
│ │ │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ MCP Client │ │ MCP Client │ │ MCP Client │ │ │
│ │ │ A │ │ B │ │ C │ │ │
│ │ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │ │
│ └─────────┼────────────────┼────────────────┼─────────────┘ │
│ │ │ │ │
│ │ MCP Protocol │ MCP Protocol │ MCP Protocol │
│ │ │ │ │
│ ┌─────────┼────────────────┼────────────────┼─────────────┐ │
│ │ ▼ ▼ ▼ │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ MCP Server │ │ MCP Server │ │ MCP Server │ │ │
│ │ │ Database │ │ Git │ │ Slack │ │ │
│ │ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │ │
│ │ │ │ │ │ │
│ │ ▼ ▼ ▼ │ │
│ │ ┌─────┐ ┌─────┐ ┌─────┐ │ │
│ │ │ DB │ │Repo │ │ API │ │ │
│ │ └─────┘ └─────┘ └─────┘ │ │
│ │ Server Processes │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ 角色说明: │
│ - Host:LLM应用程序,如Claude Desktop、IDE │
│ - Client:维护与Server的1:1连接,在Host内部 │
│ - Server:轻量级程序,通过MCP暴露特定能力 │
│ │
└─────────────────────────────────────────────────────────────────┘

协议层

MCP使用JSON-RPC 2.0作为消息格式:

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
// 四种消息类型

// 1. Request(请求)- 期望响应
interface Request {
jsonrpc: "2.0";
id: string | number;
method: string;
params?: { ... };
}

// 2. Result(结果)- 成功响应
interface Result {
jsonrpc: "2.0";
id: string | number;
result: { ... };
}

// 3. Error(错误)- 失败响应
interface Error {
jsonrpc: "2.0";
id: string | number;
error: {
code: number;
message: string;
data?: unknown;
};
}

// 4. Notification(通知)- 单向消息,不期望响应
interface Notification {
jsonrpc: "2.0";
method: string;
params?: { ... };
}

传输层

MCP支持多种传输机制:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
┌─────────────────────────────────────────────────────────────────┐
│ 传输层选项 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. Stdio传输(本地通信) │
│ ├── 使用标准输入/输出进行通信 │
│ ├── 适合本地进程 │
│ └── 简单高效 │
│ │
│ Host ◀──stdin/stdout──▶ Server Process │
│ │
│ 2. HTTP + SSE传输(远程通信) │
│ ├── Server→Client:Server-Sent Events │
│ ├── Client→Server:HTTP POST │
│ └── 适合网络环境 │
│ │
│ Client ──HTTP POST──▶ Server │
│ Client ◀────SSE────── Server │
│ │
└─────────────────────────────────────────────────────────────────┘

连接生命周期

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
┌─────────────────────────────────────────────────────────────────┐
│ 连接生命周期 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. 初始化阶段 │
│ │
│ Client Server │
│ │ │ │
│ │──── initialize request ──────▶│ │
│ │ (protocol version, │ │
│ │ capabilities) │ │
│ │ │ │
│ │◀─── initialize response ─────│ │
│ │ (protocol version, │ │
│ │ capabilities) │ │
│ │ │ │
│ │──── initialized notification─▶│ │
│ │ │ │
│ │ 连接就绪,开始工作 │ │
│ │
│ 2. 消息交换阶段 │
│ - Request-Response:请求-响应模式 │
│ - Notifications:单向通知 │
│ │
│ 3. 终止阶段 │
│ - 调用close()清理关闭 │
│ - 传输层断开 │
│ - 错误条件 │
│ │
└─────────────────────────────────────────────────────────────────┘

MCP三大原语

MCP定义了三种核心原语,用于不同的场景:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
┌─────────────────────────────────────────────────────────────────┐
│ MCP三大原语 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 原语 │ 控制方 │ 用途 │
│ ──────────┼──────────┼────────────────────────────────────── │
│ Resources │ 应用控制 │ 暴露数据和内容给LLM │
│ Tools │ 模型控制 │ 让LLM执行操作 │
│ Prompts │ 用户控制 │ 可复用的提示模板 │
│ │
│ 控制方说明: │
│ - 应用控制:客户端应用决定何时使用 │
│ - 模型控制:AI模型自动决定何时调用 │
│ - 用户控制:用户显式选择使用 │
│ │
└─────────────────────────────────────────────────────────────────┘

1. Resources(资源)

Resources让Server向Client暴露数据和内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 资源定义
interface Resource {
uri: string; // 唯一标识符,如 file:///path/to/file
name: string; // 人类可读名称
description?: string; // 可选描述
mimeType?: string; // MIME类型
}

// 资源内容
interface ResourceContent {
uri: string;
mimeType?: string;
text?: string; // 文本内容
blob?: string; // 二进制内容(base64编码)
}

资源类型:

  • 文本资源:源代码、配置文件、日志、JSON/XML
  • 二进制资源:图片、PDF、音视频文件

资源发现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 直接资源列表
server.setRequestHandler(ListResourcesRequestSchema, async () => {
return {
resources: [
{
uri: "file:///logs/app.log",
name: "Application Logs",
mimeType: "text/plain"
},
{
uri: "postgres://db/users",
name: "Users Table",
mimeType: "application/json"
}
]
};
});

// 资源模板(动态资源)
{
uriTemplate: "file:///logs/{date}.log",
name: "Daily Logs",
description: "Access logs by date"
}

读取资源:

1
2
3
4
5
6
7
8
9
10
11
12
13
@app.read_resource()
async def read_resource(uri: AnyUrl) -> str:
if str(uri).startswith("file:///logs/"):
# 读取日志文件
path = str(uri).replace("file://", "")
with open(path) as f:
return f.read()

if str(uri).startswith("postgres://"):
# 查询数据库
return await query_database(uri)

raise ValueError(f"Unknown resource: {uri}")

2. Tools(工具)

Tools让LLM能够执行实际操作:

1
2
3
4
5
6
7
8
9
10
// 工具定义
interface Tool {
name: string; // 工具名称
description?: string; // 功能描述
inputSchema: { // 参数Schema(JSON Schema)
type: "object",
properties: { ... },
required: [...]
}
}

实现示例:

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
from mcp.server import Server
import mcp.types as types

app = Server("tools-server")

@app.list_tools()
async def list_tools() -> list[types.Tool]:
return [
types.Tool(
name="execute_sql",
description="Execute a SQL query on the database",
inputSchema={
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "SQL query to execute"
},
"database": {
"type": "string",
"description": "Target database name"
}
},
"required": ["query", "database"]
}
),
types.Tool(
name="send_email",
description="Send an email",
inputSchema={
"type": "object",
"properties": {
"to": {"type": "string"},
"subject": {"type": "string"},
"body": {"type": "string"}
},
"required": ["to", "subject", "body"]
}
)
]

@app.call_tool()
async def call_tool(name: str, arguments: dict) -> list[types.TextContent]:
if name == "execute_sql":
result = await execute_query(
arguments["query"],
arguments["database"]
)
return [types.TextContent(type="text", text=str(result))]

if name == "send_email":
await send_email(
to=arguments["to"],
subject=arguments["subject"],
body=arguments["body"]
)
return [types.TextContent(type="text", text="Email sent successfully")]

raise ValueError(f"Unknown tool: {name}")

常见工具模式:

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
┌─────────────────────────────────────────────────────────────────┐
│ 常见工具类型 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. 系统操作 │
│ - 执行命令 │
│ - 文件操作 │
│ - 进程管理 │
│ │
│ 2. API集成 │
│ - GitHub操作(创建Issue、PR) │
│ - Slack消息 │
│ - 第三方服务调用 │
│ │
│ 3. 数据处理 │
│ - 数据库查询 │
│ - 数据转换 │
│ - 文件解析 │
│ │
│ 4. 计算任务 │
│ - 数学计算 │
│ - 代码执行 │
│ - 数据分析 │
│ │
└─────────────────────────────────────────────────────────────────┘

3. Prompts(提示)

Prompts提供可复用的提示模板:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 提示定义
interface Prompt {
name: string; // 提示名称
description?: string; // 描述
arguments?: [ // 可选参数
{
name: string;
description?: string;
required?: boolean;
}
]
}

// 提示结果
interface GetPromptResult {
description?: string;
messages: PromptMessage[];
}

实现示例:

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
PROMPTS = {
"git-commit": types.Prompt(
name="git-commit",
description="Generate a Git commit message",
arguments=[
types.PromptArgument(
name="changes",
description="Git diff or description of changes",
required=True
)
]
),
"code-review": types.Prompt(
name="code-review",
description="Review code for issues and improvements",
arguments=[
types.PromptArgument(
name="code",
description="Code to review",
required=True
),
types.PromptArgument(
name="language",
description="Programming language",
required=False
)
]
)
}

@app.list_prompts()
async def list_prompts() -> list[types.Prompt]:
return list(PROMPTS.values())

@app.get_prompt()
async def get_prompt(name: str, arguments: dict | None = None) -> types.GetPromptResult:
if name == "git-commit":
changes = arguments.get("changes", "") if arguments else ""
return types.GetPromptResult(
messages=[
types.PromptMessage(
role="user",
content=types.TextContent(
type="text",
text=f"Generate a concise commit message for:\n\n{changes}"
)
)
]
)

if name == "code-review":
code = arguments.get("code", "") if arguments else ""
lang = arguments.get("language", "unknown") if arguments else "unknown"
return types.GetPromptResult(
messages=[
types.PromptMessage(
role="user",
content=types.TextContent(
type="text",
text=f"Review this {lang} code:\n\n```{lang}\n{code}\n```"
)
)
]
)

raise ValueError(f"Unknown prompt: {name}")

实现MCP Server

Python实现

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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
import asyncio
from mcp.server import Server
from mcp.server.stdio import stdio_server
import mcp.types as types

# 创建Server实例
app = Server("my-mcp-server")

# 实现Resources
@app.list_resources()
async def list_resources() -> list[types.Resource]:
return [
types.Resource(
uri="config://app/settings",
name="App Settings",
description="Application configuration",
mimeType="application/json"
)
]

@app.read_resource()
async def read_resource(uri: str) -> str:
if uri == "config://app/settings":
return '{"debug": true, "log_level": "info"}'
raise ValueError(f"Unknown resource: {uri}")

# 实现Tools
@app.list_tools()
async def list_tools() -> list[types.Tool]:
return [
types.Tool(
name="get_weather",
description="Get weather for a city",
inputSchema={
"type": "object",
"properties": {
"city": {"type": "string", "description": "City name"}
},
"required": ["city"]
}
)
]

@app.call_tool()
async def call_tool(name: str, arguments: dict) -> list[types.TextContent]:
if name == "get_weather":
city = arguments["city"]
# 实际实现中调用天气API
weather = f"{city}: 晴,25°C"
return [types.TextContent(type="text", text=weather)]
raise ValueError(f"Unknown tool: {name}")

# 实现Prompts
@app.list_prompts()
async def list_prompts() -> list[types.Prompt]:
return [
types.Prompt(
name="summarize",
description="Summarize text",
arguments=[
types.PromptArgument(name="text", required=True)
]
)
]

@app.get_prompt()
async def get_prompt(name: str, arguments: dict | None) -> types.GetPromptResult:
if name == "summarize":
text = arguments.get("text", "") if arguments else ""
return types.GetPromptResult(
messages=[
types.PromptMessage(
role="user",
content=types.TextContent(
type="text",
text=f"Please summarize:\n\n{text}"
)
)
]
)
raise ValueError(f"Unknown prompt: {name}")

# 启动Server
async def main():
async with stdio_server() as streams:
await app.run(
streams[0],
streams[1],
app.create_initialization_options()
)

if __name__ == "__main__":
asyncio.run(main())

TypeScript实现

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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
ListResourcesRequestSchema,
ReadResourceRequestSchema,
ListToolsRequestSchema,
CallToolRequestSchema,
ListPromptsRequestSchema,
GetPromptRequestSchema
} from "@modelcontextprotocol/sdk/types.js";

// 创建Server
const server = new Server({
name: "my-mcp-server",
version: "1.0.0"
}, {
capabilities: {
resources: {},
tools: {},
prompts: {}
}
});

// 实现Resources
server.setRequestHandler(ListResourcesRequestSchema, async () => {
return {
resources: [
{
uri: "config://app/settings",
name: "App Settings",
mimeType: "application/json"
}
]
};
});

server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
if (request.params.uri === "config://app/settings") {
return {
contents: [
{
uri: request.params.uri,
mimeType: "application/json",
text: JSON.stringify({ debug: true, log_level: "info" })
}
]
};
}
throw new Error(`Unknown resource: ${request.params.uri}`);
});

// 实现Tools
server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: [
{
name: "get_weather",
description: "Get weather for a city",
inputSchema: {
type: "object",
properties: {
city: { type: "string", description: "City name" }
},
required: ["city"]
}
}
]
};
});

server.setRequestHandler(CallToolRequestSchema, async (request) => {
if (request.params.name === "get_weather") {
const city = request.params.arguments?.city;
return {
content: [
{
type: "text",
text: `${city}: Sunny, 25°C`
}
]
};
}
throw new Error(`Unknown tool: ${request.params.name}`);
});

// 实现Prompts
server.setRequestHandler(ListPromptsRequestSchema, async () => {
return {
prompts: [
{
name: "summarize",
description: "Summarize text",
arguments: [
{ name: "text", required: true }
]
}
]
};
});

server.setRequestHandler(GetPromptRequestSchema, async (request) => {
if (request.params.name === "summarize") {
return {
messages: [
{
role: "user",
content: {
type: "text",
text: `Please summarize:\n\n${request.params.arguments?.text}`
}
}
]
};
}
throw new Error(`Unknown prompt: ${request.params.name}`);
});

// 启动Server
const transport = new StdioServerTransport();
await server.connect(transport);

安全考虑

传输安全

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
┌─────────────────────────────────────────────────────────────────┐
│ 安全最佳实践 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. 传输安全 │
│ ├── 远程连接使用TLS │
│ ├── 验证连接来源 │
│ └── 需要时实现认证 │
│ │
│ 2. 消息验证 │
│ ├── 验证所有输入消息 │
│ ├── 净化输入 │
│ ├── 检查消息大小限制 │
│ └── 验证JSON-RPC格式 │
│ │
│ 3. 资源保护 │
│ ├── 实现访问控制 │
│ ├── 验证资源路径(防止目录遍历) │
│ ├── 监控资源使用 │
│ └── 限制请求频率 │
│ │
│ 4. 工具安全 │
│ ├── 验证所有参数 │
│ ├── 净化文件路径和命令 │
│ ├── 防止命令注入 │
│ └── 实现适当的授权检查 │
│ │
└─────────────────────────────────────────────────────────────────┘

工具错误处理

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
@app.call_tool()
async def call_tool(name: str, arguments: dict):
try:
# 执行工具操作
result = await perform_operation(arguments)
return [types.TextContent(type="text", text=str(result))]
except ValidationError as e:
# 返回错误信息给LLM(不是协议级错误)
return types.CallToolResult(
isError=True,
content=[
types.TextContent(
type="text",
text=f"Validation error: {str(e)}"
)
]
)
except Exception as e:
return types.CallToolResult(
isError=True,
content=[
types.TextContent(
type="text",
text=f"Error: {str(e)}"
)
]
)

MCP与其他协议的关系

MCP vs A2A

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
┌─────────────────────────────────────────────────────────────────┐
│ MCP与A2A的区别 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ MCP(Model Context Protocol) │
│ ├── 定位:连接LLM与工具/数据源 │
│ ├── 场景:Agent获取外部能力 │
│ ├── 关系:Agent ←→ Tools/Data │
│ └── 类比:给Agent装上"手"和"眼" │
│ │
│ A2A(Agent-to-Agent Protocol) │
│ ├── 定位:Agent之间的通信协作 │
│ ├── 场景:多Agent协作系统 │
│ ├── 关系:Agent ←→ Agent │
│ └── 类比:让Agent能够"交流"和"协作" │
│ │
│ 组合使用: │
│ │
│ Agent A ◀────A2A────▶ Agent B │
│ │ │ │
│ │ MCP │ MCP │
│ ▼ ▼ │
│ MCP Server MCP Server │
│ (数据库) (API服务) │
│ │
└─────────────────────────────────────────────────────────────────┘

调试和测试

MCP Inspector

使用MCP Inspector工具测试Server:

1
2
3
4
5
# 安装Inspector
npm install -g @modelcontextprotocol/inspector

# 测试Server
mcp-inspector python /path/to/server.py

日志和监控

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import logging

logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger("mcp-server")

@app.call_tool()
async def call_tool(name: str, arguments: dict):
logger.info(f"Tool called: {name}, args: {arguments}")

try:
result = await execute_tool(name, arguments)
logger.info(f"Tool result: {result}")
return result
except Exception as e:
logger.error(f"Tool error: {e}", exc_info=True)
raise

总结

MCP核心要点

1
2
3
4
5
6
7
┌─────────────────────────────────────────────────────────────────┐
│ 1. 标准化协议:统一LLM与工具/数据源的连接方式 │
│ 2. 三大原语:Resources(数据)、Tools(操作)、Prompts(模板) │
│ 3. 灵活传输:支持Stdio(本地)和HTTP+SSE(远程) │
│ 4. JSON-RPC:使用成熟的JSON-RPC 2.0协议 │
│ 5. 生态丰富:大量预构建Server和SDK支持 │
└─────────────────────────────────────────────────────────────────┘

最佳实践

方面 建议
资源设计 使用清晰的URI,提供有用的描述
工具设计 详细的inputSchema,原子化操作
提示设计 参数化模板,支持动态内容
错误处理 返回有用的错误信息给LLM
安全性 验证输入,实现访问控制

相关资源

MCP为构建AI Agent提供了标准化的工具和数据集成方式,是构建功能强大、可扩展AI应用的重要基础设施。