MCP 协议详解与开发方法
Claude Code 学习笔记
一、MCP 协议概述
MCP(Model Context Protocol)是 Anthropic 推出的一种开放标准协议,旨在为 AI 模型(LLM)与外部工具、数据源、服务之间建立统一的通信接口。可以将其理解为"AI 应用的 USB-C 接口"——它提供了一种标准化的方式,让 AI 应用能够发现、调用和交互各种外部能力。
一句话定义:MCP 是一种 JSON-RPC 协议,定义了 AI 模型与外部系统之间进行工具调用、资源访问和提示词交互的标准化接口。通过 MCP,Claude Code 等 AI 客户端可以像调用内置函数一样操作外部服务。
1.1 为什么需要 MCP
在 MCP 出现之前,让 AI 模型与外部系统交互的方式是零散的、非标准化的:有的使用函数调用(Function Calling),有的使用插件(Plugin),有的直接生成代码执行。每种方式都有各自的接口定义、认证机制和通信协议,导致开发者需要为每个 AI 平台编写不同的集成代码。
MCP 解决了以下核心问题:
- 标准化:统一的接口定义和通信协议,一次开发,多处可用
- 可发现性:客户端可以动态发现服务器提供的工具、资源和能力
- 安全性:通过传输层隔离和权限控制,AI 模型不会直接暴露在外部网络中
- 模块化:工具和资源以服务器形式独立部署,可以单独更新和维护
- 互操作性:任何 MCP 客户端都可以与任何 MCP 服务器交互
MCP 类比:AI 的"USB-C"标准
就像 USB-C 统一了各种设备的连接方式一样,MCP 统一了 AI 模型与外部工具的连接方式。无论后端是数据库、API、文件系统还是第三方服务,MCP 服务器都提供一致的接口。这种标准化带来了巨大的生态优势:社区可以共享和复用 MCP 服务器实现。
1.2 客户端-服务器架构
MCP 采用典型的客户端-服务器(Client-Server)架构:
- MCP 客户端(Host):是 AI 应用程序本身(如 Claude Code、Claude Desktop)。它负责与用户交互,并协调 MCP 服务器的调用。客户端通过 MCP 协议发现服务器的能力,并在需要时调用工具或访问资源。
- MCP 服务器(Server):是封装特定功能的独立进程。每个服务器暴露一组工具(Tools)、资源(Resources)和提示词(Prompts),通过 MCP 协议与客户端通信。服务器可以运行在本地(stdio 传输)或远程(HTTP/SSE 传输)。
- 通信通道:客户端与服务器之间通过传输层(Transport Layer)交换 JSON-RPC 消息。MCP 目前支持三种传输方式:stdio、HTTP + SSE、Streamable HTTP。
1.3 JSON-RPC 协议
MCP 基于 JSON-RPC 2.0 规范作为消息交换格式。JSON-RPC 是一种轻量级的远程过程调用协议,使用 JSON 格式编码请求和响应。
基本消息格式
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list",
"params": {}
}
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"tools": [
{
"name": "get_weather",
"description": "获取指定城市的天气信息",
"inputSchema": {
"type": "object",
"properties": {
"city": { "type": "string" }
}
}
}
]
}
}
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32603,
"message": "Internal error",
"data": { "details": "..." }
}
}
{
"jsonrpc": "2.0",
"method": "notifications/cancelled",
"params": {
"requestId": 1,
"reason": "用户取消了操作"
}
}
标准错误码
| 错误码 | 含义 | 说明 |
| -32700 | Parse Error | JSON 解析错误 |
| -32600 | Invalid Request | 请求格式无效 |
| -32601 | Method Not Found | 方法不存在 |
| -32602 | Invalid Params | 参数无效 |
| -32603 | Internal Error | 服务器内部错误 |
| -32000 ~ -32099 | Server Error | 服务器自定义错误 |
1.4 传输层(Transport Layer)
MCP 支持三种传输方式,适用于不同的部署场景:
| 传输方式 | 通信机制 | 适用场景 | 特点 |
| stdio | 标准输入/输出 | 本地子进程模式 | 最简单,MCP 服务器作为 Claude Code 的子进程运行;通过 stdin 发送请求,stdout 读取响应;适合开发和本地使用 |
| HTTP + SSE | HTTP POST + Server-Sent Events | 远程服务器模式 | 客户端通过 HTTP POST 发送请求,服务器通过 SSE 推送响应;适合远程部署和团队共享;支持跨网络访问 |
| Streamable HTTP | HTTP 流式传输 | 远程服务器模式 | 最新的传输方式,在标准 HTTP 基础上支持流式响应;兼容现有的 HTTP 基础设施和工具(如 curl、浏览器);推荐用于生产环境 |
传输选型建议
开发阶段使用 stdio 模式最为简单——不需要启动 HTTP 服务器,不需要处理端口和网络配置。生产环境推荐 Streamable HTTP 模式,兼容性更好,且能利用现有的基础设施(负载均衡、反向代理、认证网关等)。
二、MCP 核心概念
MCP 协议定义了三大核心原语(Primitives):Tools(工具)、Resources(资源)、Prompts(提示词),以及一个可选的高级能力 Sampling(采样)。
| 原语 | 方向 | 描述 | 类比 |
| Tools | 模型 -> 服务器 | AI 模型调用的可执行函数,用于执行操作 | 类比 API 的 POST/PUT/DELETE |
| Resources | 服务器 -> 模型 | 模型可读取的结构化数据,用于获取信息 | 类比 API 的 GET |
| Prompts | 服务器 -> 模型 | 预定义的提示词模板,用于引导模型行为 | 类比 API 的模板/预设 |
| Sampling | 服务器 -> 模型 | 服务器请求模型生成文本(反向调用) | 类比回调函数 |
2.1 Tools(工具)
Tools 是 MCP 中最核心、最常用的原语。它们是由 MCP 服务器定义的可执行函数,AI 模型可以在对话过程中自动发现并调用。每个工具都有名称、描述和输入参数模式(JSON Schema)。
工具发现:tools/list
客户端通过 tools/list 方法获取服务器提供的所有工具列表。这是 MCP 握手的第一个步骤。
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list",
"params": {}
}
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"tools": [
{
"name": "get_weather",
"description": "获取指定城市的天气信息",
"inputSchema": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "城市名称"
},
"units": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"default": "celsius"
}
},
"required": ["city"]
}
}
]
}
}
工具调用:tools/call
客户端通过 tools/call 方法实际调用工具,并传递参数。
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "get_weather",
"arguments": {
"city": "北京",
"units": "celsius"
}
}
}
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"content": [
{
"type": "text",
"text": "北京当前天气:晴,25°C,湿度40%,微风"
}
]
}
}
工具 vs 函数调用的区别
MCP 的 Tool 概念比传统 API 的"函数调用"更高级:
- 动态发现:客户端可以在运行时发现工具列表,无需提前硬编码
- 自描述:每个工具通过 JSON Schema 完整描述其输入,客户端可自动生成调用
- 结果灵活:工具返回的结果是内容数组,可以包含文本、图像、嵌入资源等多种格式
- 错误处理:工具执行结果和错误信息分离,模型可以正确处理异常情况
2.2 Resources(资源)
Resources 是 MCP 服务器暴露给模型的结构化数据。与 Tools 不同,Resources 不是由模型主动调用的,而是由服务器推送给客户端的。Resources 通过 URI 标识,支持文本和二进制内容。
资源列表:resources/list
{
"jsonrpc": "2.0",
"id": 1,
"method": "resources/list",
"params": {}
}
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"resources": [
{
"uri": "file:///data/report.pdf",
"name": "Q4报告",
"mimeType": "application/pdf",
"description": "第四季度业务报告"
}
]
}
}
资源读取:resources/read
{
"jsonrpc": "2.0",
"id": 2,
"method": "resources/read",
"params": {
"uri": "file:///data/report.pdf"
}
}
Resources 的典型用途:
- 文件系统中的文档、配置文件、日志文件
- 数据库中的查询结果(以资源形式暴露)
- API 返回的数据缓存
- 项目中的代码文件、文档、图片
- 环境信息和配置数据
2.3 Prompts(提示词)
Prompts 是服务器预定义的提示词模板,用于指导 AI 模型的行为。它们像是可复用的"交互模式",帮助模型更好地完成特定类型的任务。
{
"name": "code_review",
"description": "代码审查提示词模板",
"arguments": [
{
"name": "language",
"description": "编程语言",
"required": true
}
]
}
{
"name": "code_review",
"arguments": {
"language": "python"
}
}
2.4 Sampling(采样)
Sampling 是一种反向调用机制——服务器可以请求 LLM 生成文本。这实现了服务器与 AI 模型的双向通信,使服务器能够利用模型的自然语言理解能力来辅助完成任务。
Sampling 的安全注意事项
Sampling 赋予服务器主动向 LLM 请求生成的能力,因此需要谨慎实现:
- 始终在配置中明确允许 Sampling 功能
- 对生成的内容进行审核和过滤
- 避免将敏感数据传输给 Sampling 请求
- 设置合理的 token 限制,防止滥用
三、开发环境搭建
开发 MCP 服务器需要准备相应的语言运行环境和工具链。MCP 官方提供了 Python 和 TypeScript 两个版本的 SDK。
3.1 Python 环境准备
Python MCP 开发推荐使用 FastMCP 框架(基于 MCP Python SDK 封装),它提供了更简洁的 API。
curl -LsSf https://astral.sh/uv/install.sh | sh
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
uv pip install mcp fastmcp
pip install mcp fastmcp
python -c "import mcp; print(mcp.__version__)"
3.2 TypeScript/Node.js 环境准备
node --version
npm --version
mkdir my-mcp-server
cd my-mcp-server
npm init -y
npm install @modelcontextprotocol/sdk
npm install typescript @types/node ts-node
npx tsc --init
3.3 项目结构规范
推荐的 MCP 服务器项目结构:
my-mcp-server/
├── pyproject.toml
├── src/
│ └── my_server/
│ ├── __init__.py
│ ├── tools.py
│ ├── resources.py
│ └── utils.py
└── tests/
└── test_tools.py
my-mcp-server/
├── package.json
├── tsconfig.json
├── src/
│ ├── index.ts
│ ├── tools.ts
│ └── types.ts
└── tests/
└── tools.test.ts
使用 npx -y 快速运行
对于基于 npm 包发布的 MCP 服务器,可以使用 npx -y 包名 直接运行,无需手动安装。Claude Code 的 MCP 配置中广泛使用了这种方式。例如:npx -y @modelcontextprotocol/server-filesystem。
四、Python MCP 服务器开发
Python 是开发 MCP 服务器最常用的语言之一,得益于 FastMCP 框架的简洁设计,开发者可以快速创建功能完善的 MCP 服务器。
4.1 FastMCP 框架入门
FastMCP 是 MCP Python SDK 的高层封装,提供了类似 FastAPI 的开发体验——通过装饰器和类型注解即可定义工具。
from fastmcp import FastMCP
mcp = FastMCP("my-tool-server")
@mcp.tool()
def add(a: int, b: int) -> int:
"""计算两个数字的和"""
return a + b
@mcp.tool()
def get_weather(city: str) -> str:
"""获取指定城市的天气信息"""
return f"{city}的天气:晴,25°C"
if __name__ == "__main__":
mcp.run()
4.2 定义复杂工具
FastMCP 支持 Pydantic 模型定义复杂参数结构:
from pydantic import BaseModel
from typing import Optional, List
from fastmcp import FastMCP
mcp = FastMCP("advanced-tools")
class SearchParams(BaseModel):
query: str
max_results: Optional[int] = 10
tags: Optional[List[str]] = None
class SearchResult(BaseModel):
title: str
url: str
snippet: str
score: float
@mcp.tool()
def search_documents(params: SearchParams) -> List[SearchResult]:
"""搜索文档数据库,返回匹配结果列表"""
return [
SearchResult(
title="MCP 协议介绍",
url="https://example.com/mcp-intro",
snippet="MCP 协议是 AI 模型与外部工具交互的标准",
score=0.95
)
]
4.3 异步工具
FastMCP 原生支持异步工具定义,适合 I/O 密集型操作:
import httpx
from fastmcp import FastMCP
mcp = FastMCP("async-tools")
@mcp.tool()
async def fetch_url(url: str) -> str:
"""获取指定 URL 的页面内容"""
async with httpx.AsyncClient() as client:
response = await client.get(url, timeout=30)
response.raise_for_status()
return response.text
4.4 定义 Resources
from fastmcp import FastMCP
mcp = FastMCP("resource-server")
@mcp.resource("config://app")
def get_config() -> str:
"""获取应用配置信息"""
return "{\"version\": \"1.0\", \"debug\": false}"
@mcp.resource("doc://{path}")
def get_document(path: str) -> str:
"""获取文档内容,路径格式如:readme、changelog"""
import os
doc_path = os.path.join("./docs", f"{path}.md")
if os.path.exists(doc_path):
with open(doc_path, "r") as f:
return f.read()
return "文档不存在"
@mcp.resource_notifier("doc://*")
def notify_doc_change():
pass
4.5 错误处理
from fastmcp import FastMCP
from mcp.types import ErrorData, INTERNAL_ERROR, INVALID_PARAMS
mcp = FastMCP("robust-server")
@mcp.tool()
def divide(a: float, b: float) -> float:
"""安全的除法运算"""
if b == 0:
raise ValueError("除数不能为零")
return a / b
@mcp.error_handler()
def handle_error(error: Exception) -> ErrorData:
if isinstance(error, ValueError):
return ErrorData(
code=INVALID_PARAMS,
message=str(error)
)
return ErrorData(
code=INTERNAL_ERROR,
message="服务器内部错误"
)
4.6 测试服务器
python server.py
npx @modelcontextprotocol/inspector python server.py
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' | python server.py
FastMCP 优势总结:
- 装饰器风格 API,类似 FastAPI 的开发体验
- 自动类型推断和 JSON Schema 生成
- 原生支持同步和异步工具
- 内置资源管理和通知机制
- 完善的错误处理框架
- 自动处理 JSON-RPC 协议的细节
FastMCP vs 原生 MCP SDK
FastMCP 是对 MCP Python SDK 的高层封装,推荐用于大多数场景。如果需要更底层的控制(如自定义传输层、精细管理会话状态),可以直接使用 mcp.server.Server 类。MCP SDK 提供了完整的底层 API,包括请求处理、会话管理、传输抽象等。
五、TypeScript MCP 服务器开发
TypeScript MCP 服务器使用官方 @modelcontextprotocol/sdk 包进行开发。与 Python 的 FastMCP 不同,TypeScript SDK 提供了更贴近协议底层的 API,适合需要精细控制的场景。
5.1 创建基础服务器
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
CallToolRequestSchema,
ListToolsRequestSchema,
Tool,
} from "@modelcontextprotocol/sdk/types.js";
const GREET_TOOL: Tool = {
name: "greet",
description: "向用户问好",
inputSchema: {
type: "object",
properties: {
name: {
type: "string",
description: "用户名",
},
},
required: ["name"],
},
};
const server = new Server(
{
name: "example-server",
version: "1.0.0",
},
{
capabilities: {
tools: {},
},
}
);
server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [GREET_TOOL],
}));
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
if (name === "greet") {
return {
content: [
{
type: "text",
text: `你好,`${args.name}`!欢迎使用 MCP 服务器。`,
},
],
};
}
throw new Error(`未知工具: `${name}`);
});
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("MCP 服务器已启动(stdio 模式)");
}
main().catch(console.error);
5.2 package.json 配置
{
"name": "my-mcp-server",
"version": "1.0.0",
"type": "module",
"bin": {
"my-mcp-server": "./dist/index.js"
},
"scripts": {
"build": "tsc",
"start": "node ./dist/index.js",
"inspector": "npx @modelcontextprotocol/inspector node ./dist/index.js"
},
"dependencies": {
"@modelcontextprotocol/sdk": "^1.0.0"
},
"devDependencies": {
"@types/node": "^20.0.0",
"typescript": "^5.0.0"
}
}
5.3 注册多个工具
import { z } from "zod";
const WeatherArgs = z.object({
city: z.string().describe("城市名称"),
units: z.enum(["celsius", "fahrenheit"]).optional().default("celsius"),
});
const WEATHER_TOOL: Tool = {
name: "get_weather",
description: "获取城市天气",
inputSchema: {
type: "object",
properties: {
city: { type: "string", description: "城市名称" },
units: {
type: "string",
enum: ["celsius", "fahrenheit"],
default: "celsius",
},
},
required: ["city"],
},
};
const CALC_TOOL: Tool = {
name: "calculate",
description: "执行数学运算",
inputSchema: {
type: "object",
properties: {
expression: {
type: "string",
description: "数学表达式,如 2 + 3 * 4",
},
},
required: ["expression"],
},
};
server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [WEATHER_TOOL, CALC_TOOL],
}));
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
switch (name) {
case "get_weather": {
const { city, units } = WeatherArgs.parse(args);
return {
content: [{ type: "text", text: `${city}` 天气:晴,25°${units === "celsius" ? "C" : "F"` }],
};
}
case "calculate": {
try {
const result = Function(`'use strict'; return (`${args.expression}`)`)();
return {
content: [{ type: "text", text: `结果: ${result}` }],
};
} catch {
return {
content: [{ type: "text", text: "表达式无效" }],
isError: true,
};
}
}
default:
throw new Error(`未知工具: ${name}`);
}
});
5.4 HTTP 传输模式
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { HttpServerTransport } from "@modelcontextprotocol/sdk/server/http.js";
const server = new Server(
{ name: "http-server", version: "1.0.0" },
{ capabilities: { tools: {} } }
);
async function main() {
const transport = new HttpServerTransport({
port: 3000,
endpoint: "/mcp",
});
await server.connect(transport);
console.log("MCP HTTP 服务器已启动,端口: 3000");
}
main().catch(console.error);
TypeScript vs Python 开发选择
选择 Python(FastMCP):开发速度更快,代码更简洁,适合快速原型和中小型 MCP 服务器。Pydantic 类型系统简化了参数校验。
选择 TypeScript:更底层的 API,控制更精细,适合需要自定义传输层、复杂状态管理或与现有的 Node.js 生态集成的场景。TypeScript 的类型安全在大项目中优势明显。
六、MCP 服务器配置
MCP 服务器通过 Claude Code 的配置文件进行注册和管理。配置方式有三种:命令行管理、手动编辑 JSON 配置文件、以及环境变量注入。
6.1 配置文件位置
| 作用域 | 配置文件路径 | 生效范围 |
| 全局 | ~/.claude/settings.json | 所有 Claude Code 会话 |
| 项目 | 项目根目录/.claude/settings.json | 仅当前项目 |
| 本地(不提交) | 项目根目录/.claude/settings.local.json | 仅当前设备,可包含敏感信息 |
6.2 配置文件格式
{
"mcpServers": {
"my-python-server": {
"command": "uvx",
"args": ["my-mcp-server"]
},
"my-ts-server": {
"command": "npx",
"args": ["-y", "@myorg/mcp-server"]
},
"local-dev": {
"command": "python",
"args": ["-m", "my_server"]
},
"weather-server": {
"command": "node",
"args": ["./dist/server.js"],
"env": {
"API_KEY": "your-api-key",
"BASE_URL": "https://api.weather.com"
}
},
"remote-server": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-remote"],
"env": {
"MCP_REMOTE_URL": "https://mcp.example.com/mcp"
}
}
}
}
6.3 claude mcp 命令
Claude Code 提供了一组 claude mcp 子命令,用于管理 MCP 服务器配置:
claude mcp list
claude mcp get 服务器名称
claude mcp add my-server -- python -m my_server
API_KEY="xxx" claude mcp add my-server -- python -m my_server
claude mcp remove 服务器名称
claude mcp test 服务器名称
claude mcp logs 服务器名称
6.4 多服务器配置
Claude Code 支持同时运行多个 MCP 服务器。每个服务器提供不同的工具集合,Claude Code 会自动合并所有服务器的能力。
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/allowed/dir"]
},
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_TOKEN": "你的GitHub令牌"
}
},
"database": {
"command": "python",
"args": ["-m", "db_mcp_server"]
}
}
}
多服务器注意事项:
- 每个服务器启动独立的进程,消耗系统资源
- 工具名称需要在所有服务器间唯一,避免冲突
- 服务器启动顺序不影响功能,Claude Code 会自动发现所有工具
- 建议将常用的、稳定的服务器配置在全局 settings.json 中
- 项目特定的服务器配置在项目级 settings.json 中
6.5 settings.local.json 使用
{
"mcpServers": {
"db-server": {
"command": "python",
"args": ["-m", "db_server"],
"env": {
"DB_HOST": "localhost",
"DB_PORT": "5432",
"DB_USER": "admin",
"DB_PASSWORD": "your-password"
}
}
}
}
安全警告
API Key、令牌、密码等敏感信息:
- 优先放在 settings.local.json 中(已被 .gitignore 忽略)
- 不要在 settings.json 中硬编码敏感信息
- 或者通过环境变量注入:API_KEY=xxx claude mcp add ...
- 使用系统密钥管理工具(如 1Password、Bitwarden、系统密钥链)管理敏感信息
七、高级开发技术
本章介绍 MCP 服务器开发中的高级主题,包括认证、流式响应、进度报告、日志记录和无状态模式等。
7.1 认证(OAuth)
对于远程 MCP 服务器,OAuth 2.1 是推荐的认证方式。MCP 协议内置了 OAuth 授权流程的支持。
from fastmcp import FastMCP
from authlib.integrations.httpx_client import OAuth2Client
mcp = FastMCP("oauth-server")
class OAuthMiddleware:
def __init__(self):
self.client = OAuth2Client(
client_id="your-client-id",
client_secret="your-client-secret",
token_endpoint="https://auth.example.com/token"
)
async def get_token(self) -> str:
if not self.client.token:
token = await self.client.fetch_token()
return token["access_token"]
return self.client.token["access_token"]
auth = OAuthMiddleware()
@mcp.tool()
async def get_user_data(user_id: str) -> dict:
"""获取用户数据(需要 OAuth 认证)"""
token = await auth.get_token()
return {"user_id": user_id, "data": "..."}
7.2 流式响应
MCP 支持流式传输结果,适用于长时间运行的操作或大量数据的返回。流式响应允许服务器在生成结果的过程中逐步发送数据,而不必等待全部完成。
from fastmcp import FastMCP
import asyncio
mcp = FastMCP("streaming-server")
@mcp.tool()
async def stream_logs(lines: int) -> str:
"""流式返回日志内容"""
result = []
for i in range(lines):
await asyncio.sleep(0.1)
result.append(f"日志行 {i + 1}: 处理完成")
return "\n".join(result)
async function* streamProcessor(items: string[]) {
for (const item of items) {
await processItem(item);
yield { type: "text", text: `已处理: ${item}` };
}
}
7.3 进度报告
对于耗时较长的工具调用,MCP 支持进度通知机制,服务器可以向客户端发送进度更新。
from fastmcp import FastMCP
import asyncio
mcp = FastMCP("progress-server")
@mcp.tool()
async def batch_process(items: list[str]) -> str:
"""批量处理数据,每处理一项发送进度通知"""
total = len(items)
for i, item in enumerate(items):
await asyncio.sleep(0.5)
progress = (i + 1) / total * 100
await mcp.report_progress(
progress=progress,
message=f"正在处理第 {i + 1}/{total} 项"
)
return f"成功处理 {total} 项数据"
7.4 日志记录
MCP 服务器可以使用标准日志框架进行日志记录。对于 stdio 模式的服务器,日志应输出到 stderr,避免干扰 stdout 上的 JSON-RPC 通信。
import logging
import sys
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s [%(levelname)s] %(message)s",
stream=sys.stderr
)
logger = logging.getLogger("mcp-server")
const logger = {
info: (msg: string) => console.error(`[INFO] ${msg}`),
error: (msg: string) => console.error(`[ERROR] ${msg}`),
debug: (msg: string) => console.error(`[DEBUG] ${msg}`),
};
7.5 无状态模式(Stateless Mode)
无状态模式适用于容器化和 Serverless 部署。在这种模式下,每个请求都是独立的,服务器不维护会话状态。
from fastmcp import FastMCP
mcp = FastMCP(
"stateless-server",
stateless=True
)
{
"mcpServers": {
"my-server": {
"command": "uvx",
"args": ["my-server", "--stateless"]
}
}
}
高级特性最佳实践:
- OAuth 认证:始终使用 OAuth 2.1 标准流程,避免自己实现认证逻辑
- 流式响应:对于大数据量返回(如日志、搜索结果),优先使用流式响应
- 进度报告:耗时超过 5 秒的操作应提供进度通知,提升用户体验
- 日志:始终使用 stderr 输出日志,stdio 只用于 JSON-RPC 通信
- 无状态:优先设计无状态服务器,便于水平扩展和容器化部署
stderr 日志的重要性
这是 MCP 开发中最常见的错误之一。MCP 使用 stdout(标准输出)传输 JSON-RPC 消息,任何不应出现在 stdout 上的输出都会破坏协议通信。所有日志、调试信息、控制台输出都必须使用 stderr(标准错误)。在 Python 中,这意味着始终使用 logging 库或 print(..., file=sys.stderr)。
八、最佳实践与设计模式
本章总结开发 MCP 服务器时的最佳实践和常用设计模式,帮助开发者创建高质量、易维护、安全的 MCP 服务器。
8.1 工具命名规范
| 规范 | 说明 | 示例 |
| 使用下划线命名 | 工具名称使用 snake_case | get_weather, search_files |
| 动词开头 | 以动词开头描述操作 | create_document, delete_user |
| 名称空间前缀 | 多个服务时使用前缀避免冲突 | gmail_search, drive_list_files |
| 描述清晰 | 详细描述工具功能和参数作用 | description 字段使用中文完整说明 |
| 参数精简 | 每个工具参数不超过 5 个 | 复杂参数使用嵌套对象 |
8.2 错误处理模式
良好的错误处理是 MCP 服务器质量的衡量标准。以下是推荐的错误处理模式:
from fastmcp import FastMCP
from typing import Union, Dict
mcp = FastMCP("robust-server")
class ToolError(Exception):
"""自定义工具错误,带有用户友好的错误信息"""
def __init__(self, message: str, code: str = "UNKNOWN"):
self.message = message
self.code = code
super().__init__(message)
@mcp.tool()
def process_data(data: str) -> Union[str, Dict]:
"""处理数据并返回结果"""
try:
if not data.strip():
raise ToolError("数据不能为空", "INVALID_INPUT")
result = do_processing(data)
return {"status": "success", "result": result}
except ToolError as e:
return {
"status": "error",
"code": e.code,
"message": e.message
}
except Exception as e:
logger.exception("处理数据时发生未预期错误")
return {
"status": "error",
"code": "INTERNAL",
"message": "服务器内部错误,请稍后重试"
}
8.3 资源发现设计模式
资源发现是 MCP 的重要能力。合理设计资源 URI 结构,可以帮助 AI 模型更有效地发现和使用资源。
8.4 安全设计原则
MCP 服务器安全清单
- 最小权限原则:工具只授予完成任务所需的最小权限,避免暴露危险操作
- 输入验证:所有工具参数必须经过严格的类型和范围校验
- 路径安全:涉及文件操作时,防止路径遍历攻击(Path Traversal)
- 命令注入防护:避免将用户输入直接传递给 shell 命令
- 速率限制:对敏感操作(如发送邮件、删除数据)实施速率限制
- 确认机制:对不可逆操作(如删除、发送)提供二次确认
- 审计日志:记录所有工具调用及其参数,便于追责和问题排查
- 环境隔离:不将服务器私密信息(密钥、密码)暴露给 AI 模型
8.5 设计模式总结
| 设计模式 | 适用场景 | 实现方式 |
| 外观模式 | 将复杂 API 封装为简单工具 | MCP 工具作为复杂后端服务的前端接口 |
| 适配器模式 | 适配现有系统到 MCP 协议 | 在 MCP 工具内部调用现有 API 或 SDK |
| 验证器模式 | 在调用前校验参数 | 使用 Pydantic/Zod 做输入校验 |
| 重试模式 | 处理临时性故障 | 在工具内部实现指数退避重试 |
| 缓存模式 | 提高重复查询性能 | 对只读工具的结果进行缓存 |
| 断路器模式 | 防止级联故障 | 在依赖的外部服务不可用时快速失败 |
| 确认模式 | 防止误操作 | 在危险操作前要求客户端确认 |
九、调试与测试
MCP 服务器的调试和测试有专用的工具和技巧。本章介绍最常用的调试方法。
9.1 MCP Inspector
MCP Inspector 是官方提供的图形化调试工具,可以在浏览器中交互式地测试 MCP 服务器。
npx @modelcontextprotocol/inspector python my_server.py
npx @modelcontextprotocol/inspector node dist/index.js
9.2 手动测试
使用 stdio 模式,可以通过管道发送 JSON-RPC 请求进行手动测试:
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' | python my_server.py
echo '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"get_weather","arguments":{"city":"北京"}}}' | python my_server.py
echo '{"jsonrpc":"2.0","id":1,"method":"resources/list","params":{}}' | python my_server.py
9.3 单元测试
对 MCP 服务器的核心逻辑编写单元测试,确保工具的正确行为:
import pytest
from my_server.tools import add, get_weather
class TestTools:
def test_add(self):
assert add(1, 2) == 3
assert add(-1, 1) == 0
assert add(0, 0) == 0
def test_add_invalid(self):
with pytest.raises(TypeError):
add("a", "b")
def test_get_weather(self):
result = get_weather("北京")
assert "北京" in result
assert "天气" in result
import { describe, it, expect } from "vitest";
import { add } from "../src/tools";
describe("add", () => {
it("should add two positive numbers", () => {
expect(add(1, 2)).toBe(3);
});
it("should handle negative numbers", () => {
expect(add(-1, 1)).toBe(0);
});
});
9.4 常见问题排查
| 问题 | 可能原因 | 解决方案 |
| claude mcp list 显示 disconnected | 服务器启动失败或配置路径错误 | 检查命令路径是否正确;手动运行启动命令测试;查看日志 |
| "MCP server exited unexpectedly" | 依赖缺失或运行时错误 | 检查 Python/Node.js 版本;重新安装依赖;运行 claude mcp logs |
| 工具调用无响应 | 工具内部阻塞或异常 | 添加超时机制;使用 Inspector 单独测试工具 |
| JSON-RPC parse error | 协议消息格式错误 | 使用 Inspector 检查消息格式;确保 JSON 语法正确 |
| 工具找不到 | tools/list 未正确实现 | 检查 ListToolsRequestSchema 处理函数;确认工具已注册 |
| 参数校验失败 | Schema 定义与实现不匹配 | 检查 inputSchema 与工具函数参数是否一致 |
| Node.js 版本不兼容 | 使用过旧的 Node.js | 升级到 Node.js 18+ 或 20+ LTS 版本 |
| Windows 路径问题 | 路径格式不正确 | 使用正斜杠或双反斜杠;使用 path 模块处理路径 |
| stdout 被污染 | 不小心在 stdout 上打印了非 JSON 内容 | 确保所有日志输出到 stderr;检查是否有 print() 语句 |
快速排错流程
遇到 MCP 服务器问题时,按以下顺序排查:
- claude mcp list -- 检查服务器是否已注册及状态
- claude mcp logs 服务器名 -- 查看服务器日志
- npx @modelcontextprotocol/inspector ... -- 使用 Inspector 图形化调试
- 手动发送 JSON-RPC 请求 -- 绕过 Claude Code 直接测试协议
- 重新添加服务器 -- claude mcp remove && claude mcp add
- 重启 Claude Code -- 解决大部分临时性问题
十、生态与资源
MCP 协议自发布以来,社区迅速构建了丰富的生态。本章汇总主流的 MCP 服务器、工具和资源。
10.1 官方 MCP 服务器
Anthropic 官方维护的 MCP 服务器(在 @modelcontextprotocol 命名空间下):
| 服务器名称 | 功能 | 包名 |
| Filesystem | 安全的文件系统操作 | @modelcontextprotocol/server-filesystem |
| GitHub | GitHub API 集成 | @modelcontextprotocol/server-github |
| Git | Git 仓库操作 | @modelcontextprotocol/server-git |
| PostgreSQL | 数据库查询和执行 | @modelcontextprotocol/server-postgres |
| SQLite | SQLite 数据库管理 | @modelcontextprotocol/server-sqlite |
| Puppeteer | 浏览器自动化 | @modelcontextprotocol/server-puppeteer |
| Slack | Slack 工作空间集成 | @modelcontextprotocol/server-slack |
| Google Maps | 地图和位置服务 | @modelcontextprotocol/server-google-maps |
| Memory | 知识图谱记忆系统 | @modelcontextprotocol/server-memory |
| Brave Search | 网络搜索集成 | @modelcontextprotocol/server-brave-search |
| Sequential Thinking | 增强推理能力 | @modelcontextprotocol/server-sequential-thinking |
10.2 热门社区 MCP 服务器
| 服务器名称 | 功能 | 技术栈 |
| Google Workspace MCP | 12 项 Google 服务集成(Gmail、Drive、Calendar 等) | Python (FastMCP) |
| gmail-multi-mcp | 零配置 Gmail 多账号管理 | TypeScript |
| gmail-autoauth-mcp | 精细 OAuth 控制的 Gmail 集成 | TypeScript |
| Composio | 850+ 应用集成的托管 MCP 平台 | Python/托管 |
| Nylas | 跨邮件提供商(Gmail+Outlook) | Python/托管 |
| Coogle | 守护进程模式的多会话 Google 服务 | Python |
| MCPHub | MCP 服务器发现和管理的中心化平台 | Python |
| Blender MCP | 通过自然语言操控 Blender 3D | Python |
| Docker MCP | Docker 容器管理 | TypeScript |
| Kubernetes MCP | K8s 集群管理 | TypeScript |
| Cloudflare MCP | Cloudflare 服务管理 | TypeScript |
| Jira MCP | Jira 项目管理 | TypeScript |
| Notion MCP | Notion 页面操作 | TypeScript |
| Obsidian MCP | Obsidian 知识库交互 | Python |
| Playwright MCP | Playwright 浏览器自动化 | TypeScript |
10.3 社区工具与平台
- MCPHub(github.com/gr4vy/mcphub):MCP 服务器集中发现和管理平台,可以在线搜索和浏览 MCP 服务器
- MCP Inspector:官方 MCP 调试工具,支持图形化界面测试
- Smithery:MCP 服务器注册表和自动配置服务
- mcp-get:MCP 服务器的命令行安装工具
- mcp-cli:MCP 协议的命令行客户端,用于测试和开发
10.4 官方资源
生态展望:MCP 生态正在快速增长。随着更多开发者和企业加入,MCP 正在成为 AI 模型与外部系统交互的事实标准。截至 2026 年,社区已开发超过 1000 个 MCP 服务器,覆盖从开发工具到企业服务的几乎所有领域。掌握 MCP 开发方法,将成为 AI 应用开发的核心技能。
核心要点总结
- MCP 是 AI 模型与外部世界的标准化接口:采用 JSON-RPC 协议,基于客户端-服务器架构,支持 Tools(工具)、Resources(资源)、Prompts(提示词)三大核心原语,以及 Sampling(采样)反向调用能力。
- 三种传输方式适配不同场景:stdio 适合本地开发和子进程模式,HTTP+SSE 适合远程部署,Streamable HTTP 是推荐的生产环境传输方式。
- Python FastMCP 是最快的开发方式:装饰器风格 API、自动类型推断、JSON Schema 生成,让开发者可以快速创建功能完善的 MCP 服务器。适合快速原型和中小型项目。
- TypeScript SDK 提供更底层的控制:适合需要精细控制传输层、状态管理或深度集成 Node.js 生态的场景。类型安全在大项目中优势明显。
- 配置管理三渠道:全局 settings.json、项目 settings.json 和本地 settings.local.json 三级配置体系,支持命令行(claude mcp)和手动编辑两种管理方式。
- 高级特性提升服务器质量:OAuth 认证、流式响应、进度报告、stderr 日志记录、无状态模式——这些高级特性将简易服务器升级为生产级系统。
- 安全是开发的第一原则:最小权限、输入验证、路径安全、命令注入防护、速率限制、二次确认——MCP 服务器的每个工具都应该是安全的。
- MCP Inspector 是调试利器:图形化界面让调试变得直观。配合手动 JSON-RPC 测试和单元测试,形成完整的测试体系。
- 生态正在爆发式增长:官方 10+ 服务器、社区 1000+ 服务器、覆盖开发工具到企业服务。Google Workspace、GitHub、数据库、文件系统等常见场景都有成熟的 MCP 实现。
- MCP 正在成为 AI 集成的标准协议:掌握 MCP 开发方法,就是掌握 AI 应用开发的核心技能。标准化意味着一次开发、多处部署——这是未来 AI 工具开发的基石。
MCP 开发的学习路径建议
- 先理解协议:深入理解 JSON-RPC 消息格式、三种原语的用途和生命周期
- 从 Python FastMCP 入手:用最少的代码创建你的第一个 MCP 服务器,体会开发流程
- 掌握配置部署:学会将 MCP 服务器配置到 Claude Code 中,理解三种配置文件的区别
- 深入研究 TypeScript SDK:当需要更精细的控制时,切换到 TypeScript 开发
- 应用高级特性:逐步引入认证、流式、进度报告等高级功能
- 关注生态:定期浏览 MCPHub 和官方仓库,了解新的 MCP 服务器和最佳实践
- 贡献社区:发布自己的 MCP 服务器到 npm 或 PyPI,成为 MCP 生态的贡献者