MCP快速入门
理论说够了,这一篇我们用 Python 从零写一个最简单的 MCP Server,并在 Claude Desktop 中使用它。
1. 准备工作
安装 uv(推荐)
uv 是 Python 的快速包管理器,MCP 官方推荐使用。
# macOS / Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
# Windows
powershell -c "irm https://astral.sh/uv/install.ps1 | iex"
创建项目
mcp[cli] 包含了核心 SDK 和命令行工具。
也可以直接用 pip:
2. 第一个 MCP Server
新建 server.py:
from mcp.server.fastmcp import FastMCP
# 创建一个 MCP Server 实例
mcp = FastMCP("my-first-mcp")
@mcp.tool()
def add(a: int, b: int) -> int:
"""计算两个整数的和"""
return a + b
@mcp.tool()
def greet(name: str) -> str:
"""向某人打招呼"""
return f"你好,{name}!欢迎使用 MCP。"
if __name__ == "__main__":
mcp.run()
就这么简单!
FastMCP 是官方提供的高级 API,类似 FastAPI 的风格:
- 用
@mcp.tool()装饰器定义工具 - 函数文档字符串作为工具描述
- 类型注解自动转换为输入 schema
- 默认使用 stdio 传输
3. 测试 Server
用 inspector 调试(推荐)
mcp inspector 是官方的可视化调试工具:
或:
它会启动一个 Web 界面(默认 http://localhost:6274),你可以:
- 看到 Server 声明的所有 Tools / Resources / Prompts
- 手动调用工具,查看输入输出
- 实时看到 JSON-RPC 消息流
这是开发阶段最常用的调试工具。
命令行直接运行
Server 启动后会监听 stdin。这种模式主要给客户端启动用。
4. 在 Claude Desktop 中使用
Claude Desktop 是测试 MCP Server 最方便的客户端。
找到配置文件
| 操作系统 | 配置文件路径 |
|---|---|
| macOS | ~/Library/Application Support/Claude/claude_desktop_config.json |
| Windows | %APPDATA%\Claude\claude_desktop_config.json |
| Linux | ~/.config/Claude/claude_desktop_config.json |
注册 Server
编辑配置文件,加入你的 Server:
{
"mcpServers": {
"my-first-mcp": {
"command": "uv",
"args": [
"--directory",
"/Users/yourname/path/to/my-first-mcp",
"run",
"server.py"
]
}
}
}
字段说明:
command:启动 Server 的可执行命令args:命令行参数--directory:让 uv 在指定目录运行
如果不用 uv:
{
"mcpServers": {
"my-first-mcp": {
"command": "python",
"args": ["/absolute/path/to/server.py"]
}
}
}
重启 Claude Desktop
完全退出 Claude Desktop(不是关闭窗口,而是从 Dock 退出),然后重新打开。
验证
在 Claude Desktop 对话框右下角,你会看到一个 🔌 工具图标,点击后能看到 my-first-mcp 已连接,并列出 add 和 greet 两个工具。
试着发送消息:
"帮我算 23 + 45"
Claude 会自动调用 add 工具,返回 68。第一次调用时会弹出权限确认,点"允许本次"或"始终允许"。
5. 加入 Resources
Resources 是只读上下文,最适合提供配置、文档之类的数据。修改 server.py:
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("my-first-mcp")
@mcp.tool()
def add(a: int, b: int) -> int:
"""计算两个整数的和"""
return a + b
@mcp.resource("config://app")
def get_config() -> str:
"""获取应用配置"""
return """{
"version": "1.0.0",
"environment": "development",
"features": ["chat", "search"]
}"""
@mcp.resource("greeting://{name}")
def get_greeting(name: str) -> str:
"""生成问候语(带参数的资源)"""
return f"你好,{name}!今天是美好的一天。"
if __name__ == "__main__":
mcp.run()
资源的 URI 可以是任意 scheme(config://、greeting://、file://)。带 {name} 占位符的 URI 称为资源模板,可以动态生成内容。
6. 加入 Prompts
Prompts 是预制的提示词模板,用户在 Claude Desktop 中通过斜杠命令触发:
@mcp.prompt()
def code_review(code: str, language: str = "Python") -> str:
"""对代码进行严格的 Code Review"""
return f"""请对下面的 {language} 代码进行严格的 Code Review,重点关注:
1. 代码可读性
2. 性能问题
3. 潜在的 bug
4. 是否遵循最佳实践
5. 安全隐患
```{language.lower()}
{code}
```
请用中文给出详细的 review 报告。
"""
重启 Claude Desktop 后,在输入框输入 /,会出现 code_review 选项,选中后会要求输入 code 和 language 参数。
7. 完整的最终 Server
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("my-first-mcp")
# === Tools ===
@mcp.tool()
def add(a: int, b: int) -> int:
"""计算两个整数的和"""
return a + b
@mcp.tool()
def get_weather(city: str) -> str:
"""查询指定城市的天气情况"""
# 模拟数据,实际可以调用真实 API
fake_weather = {
"北京": "晴天,气温 22°C",
"上海": "多云,气温 25°C",
"广州": "小雨,气温 28°C",
}
return fake_weather.get(city, f"暂无 {city} 的天气数据")
# === Resources ===
@mcp.resource("config://app")
def get_config() -> str:
"""获取应用配置"""
return '{"version": "1.0.0"}'
@mcp.resource("greeting://{name}")
def greet_resource(name: str) -> str:
"""生成问候语"""
return f"你好,{name}!"
# === Prompts ===
@mcp.prompt()
def summarize(text: str) -> str:
"""将一段文字总结为三句话"""
return f"请将下面这段文字总结为三句话,要简洁、抓住核心:\n\n{text}"
if __name__ == "__main__":
mcp.run()
8. 调试技巧
看日志
Claude Desktop 的 MCP 日志位于:
| 操作系统 | 日志路径 |
|---|---|
| macOS | ~/Library/Logs/Claude/ |
| Windows | %APPDATA%\Claude\logs\ |
每个 Server 一个日志文件,名称为 mcp-server-<name>.log。
Server 中打印日志
不能用 print!因为 stdio 传输方式下,stdout 是协议通道,print 会破坏协议。
正确做法是用 logging 输出到 stderr:
import logging
import sys
logging.basicConfig(
level=logging.INFO,
stream=sys.stderr, # 输出到 stderr
format="%(asctime)s [%(levelname)s] %(message)s",
)
logger = logging.getLogger(__name__)
@mcp.tool()
def add(a: int, b: int) -> int:
"""计算两个整数的和"""
logger.info(f"调用 add: {a} + {b}")
return a + b
stderr 会被 Claude Desktop 收集到日志文件中。
用 inspector 单独测试
每次改完代码不要急着去 Claude Desktop 测,先在 mcp dev server.py 中验证,节省大量调试时间。
9. 常见错误
错误 1:Server 启动失败
检查配置文件中的路径是否为绝对路径,相对路径不会工作。
错误 2:Claude Desktop 看不到工具
- 确认完全退出后重启了 Claude Desktop
- 看日志文件中有没有错误
- 用
mcp dev先测试 Server 本身没问题
错误 3:工具调用失败
- 检查类型注解是否正确(
int、str、list[str]) - 函数内部异常会传给客户端,注意做好异常处理
总结
- 用
FastMCP+ 装饰器 3 行代码就能写一个 MCP Server mcp dev server.py启动可视化调试器- Claude Desktop 通过编辑
claude_desktop_config.json注册 Server,需重启生效 - 三种装饰器:
@mcp.tool()、@mcp.resource()、@mcp.prompt() - 调试时用
logging输出到 stderr,不能用 print