深入理解MCP协议:5步打造你的第一个AI工具服务器
引言:为什么MCP协议值得关注?
2024年底,Anthropic推出了Model Context Protocol(MCP),这是一个开放标准,旨在解决大语言模型与外部工具、数据源之间的连接问题。如果说Function Calling是"给AI一双巧手",那么MCP就是"给AI一套标准化的工具箱接口"。
在MCP出现之前,每接入一个新工具,都需要单独编写适配代码,维护成本极高。MCP的核心理念很简单:一次开发,到处使用——开发者只需按照MCP规范实现一个工具服务器,任何支持MCP的AI客户端都能直接调用。
本文将带你从零开始,5步打造一个完整的MCP工具服务器,让你真正理解MCP的工作原理。
一、MCP协议架构解析
MCP采用经典的客户端-服务器(Client-Server)架构,核心组件如下:
- MCP Host(宿主):发起连接的应用程序,如Claude Desktop、Cursor等AI客户端
- MCP Client(客户端):在Host内部运行,与Server保持1:1连接
- MCP Server(服务器):提供工具、资源、提示词等能力的轻量级服务
- 传输层:支持stdio(标准输入输出)和SSE(Server-Sent Events)两种通信方式
MCP定义了四大核心能力原语:
| 原语 | 说明 | 示例 |
|---|---|---|
| Tools | 可被LLM调用的函数 | 查询天气、执行代码 |
| Resources | 可被LLM读取的数据 | 文件内容、数据库记录 |
| Prompts | 预定义的提示模板 | 代码审查模板 |
| Sampling | Server向Host请求LLM推理 | 多步骤任务中的中间推理 |
理解了架构,我们开始动手实践!
二、第1步:环境准备与项目初始化
MCP Server的官方SDK支持TypeScript和Python,本文以Python为例(更易上手)。
首先安装MCP Python SDK:
# 创建项目目录
mkdir mcp-weather-server && cd mcp-weather-server
# 创建虚拟环境
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
# 安装MCP SDK
pip install mcp
项目结构如下:
mcp-weather-server/
├── venv/
├── weather_server.py # 主服务器文件
├── requirements.txt # 依赖列表
└── README.md
在requirements.txt中添加:
mcp>=1.0.0
httpx>=0.27.0
就这么简单,不需要复杂的框架和依赖。
三、第2步:编写MCP Server核心代码
接下来编写核心的服务器代码。我们将创建一个天气查询工具服务器,提供两个工具:
get_current_weather:查询指定城市的当前天气get_weather_forecast:获取未来3天的天气预报
from mcp.server import Server
from mcp.server.stdio import stdio_server
from mcp.types import Tool, TextContent
import httpx
import json
# 创建Server实例
app = Server("weather-server")
# 免费天气API(使用wttr.in,无需API Key)
WEATHER_API = "https://wttr.in"
@app.list_tools()
async def list_tools() -> list[Tool]:
"""注册可用工具列表"""
return [
Tool(
name="get_current_weather",
description="获取指定城市的当前天气信息,支持中文城市名",
inputSchema={
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "城市名称,如'北京'、'Shanghai'"
}
},
"required": ["city"]
}
),
Tool(
name="get_weather_forecast",
description="获取指定城市未来3天的天气预报",
inputSchema={
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "城市名称"
}
},
"required": ["city"]
}
)
]
关键点解析:
五、第4步:启动服务器与配置客户端
添加入口函数,启动stdio传输:
async def main():
"""启动MCP服务器"""
async with stdio_server() as (read_stream, write_stream):
await app.run(
read_stream,
write_stream,
app.create_initialization_options()
)
if __name__ == "__main__":
import asyncio
asyncio.run(main())
启动方式很简单:
python weather_server.py
但通常我们不需要手动启动,而是在AI客户端中配置。以Claude Desktop为例,编辑配置文件:
{
"mcpServers": {
"weather": {
"command": "python",
"args": ["C:/path/to/weather_server.py"],
"env": {}
}
}
}
配置文件位置:
重启Claude Desktop后,在对话中你就可以直接问"北京今天天气怎么样",AI会自动调用你的MCP工具服务器获取实时天气数据。
@app.list_tools()装饰器注册工具列表,当客户端连接时自动获取inputSchema使用JSON Schema定义参数,LLM据此生成正确的调用参数- description非常重要——LLM靠它判断何时调用这个工具,写得越精准越好
四、第3步:实现工具执行逻辑
工具列表注册好了,接下来实现实际的执行逻辑:
@app.call_tool() async def call_tool(name: str, arguments: dict) -> list[TextContent]: """处理工具调用请求""" city = arguments.get("city", "Beijing") if name == "get_current_weather": result = await fetch_weather(city, forecast=False) elif name == "get_weather_forecast": result = await fetch_weather(city, forecast=True) else: result = f"未知工具: {name}" return [TextContent(type="text", text=result)] async def fetch_weather(city: str, forecast: bool = False) -> str: """调用天气API获取数据""" params = {"format": "j1"} # JSON格式 url = f"{WEATHER_API}/{city}" try: async with httpx.AsyncClient(timeout=10) as client: resp = await client.get(url, params=params) resp.raise_for_status() data = resp.json() if not forecast: # 当前天气 current = data["current_condition"][0] return ( f"🏙️ {city} 当前天气\n" f"🌡️ 温度: {current['temp_C']}°C " f"(体感 {current['FeelsLikeC']}°C)\n" f"💧 湿度: {current['humidity']}%\n" f"🌬️ 风速: {current['windspeedKmph']} km/h\n" f"☁️ 天气: {current['weatherDesc'][0]['value']}" ) else: # 3天预报 lines = [f"📅 {city} 未来3天天气预报"] for day in data["weather"][:3]: lines.append( f" {day['date']}: " f"{day['mintempC']}°C ~ {day['maxtempC']}°C, " f"{day['hourly'][4]['weatherDesc'][0]['value']}" ) return "\n".join(lines) except httpx.HTTPError as e: return f"❌ 获取天气失败: {str(e)}"注意事项:
@app.call_tool()接收工具名和参数,返回TextContent列表- 返回内容尽量结构化且人类可读,因为LLM会基于这些内容回答用户
- 做好异常处理,网络请求随时可能失败
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json
六、第5步:调试技巧与最佳实践
开发MCP Server时,调试是个痛点——因为它通过stdio通信,不能直接print。以下是几个实用技巧:
技巧1:使用MCP Inspector调试
npx @modelcontextprotocol/inspector python weather_server.py
这会启动一个Web界面,让你可视化地测试每个工具、查看请求响应。
技巧2:日志写入文件
import logging
logging.basicConfig(
filename="/tmp/mcp-weather.log",
level=logging.DEBUG,
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
)
# 在关键位置添加日志
@app.call_tool()
async def call_tool(name, arguments):
logging.info(f"Tool called: {name}, args: {arguments}")
# ...
技巧3:错误码规范
MCP定义了标准错误码,建议遵循:
from mcp.types import McpError
# 参数错误
raise McpError(
code=-32602, # Invalid params
message=f"Missing required parameter: city"
)
# 内部错误
raise McpError(
code=-32603, # Internal error
message=f"Weather API unavailable: {str(e)}"
)
最佳实践总结:
description要精确——这是LLM理解工具的关键,模糊的描述会导致误调用 参数校验要严格——在call_tool中验证必填参数,避免LLM幻觉导致的异常 返回要结构化——使用换行、emoji、编号让返回内容清晰可读 超时要合理——外部API调用务必设置timeout,避免Server卡死 单一职责——一个Server专注于一个领域,不要把所有工具塞进一个服务
总结:MCP正在重塑AI工具生态
通过这5步,我们完成了一个完整的MCP工具服务器开发。回顾核心流程:
MCP的意义远不止于技术层面。它正在建立AI工具的"USB标准"——就像USB协议统一了设备连接一样,MCP统一了AI与外部世界的交互方式。截至2026年初,已有超过2000个MCP Server发布在各类平台上,覆盖数据库、文件系统、API集成、开发工具等领域。
未来,每个开发者都可能成为"MCP工具提供者",为AI生态贡献可被任何LLM调用的能力。这是一个值得投入的方向。
本文代码已开源,欢迎Star ⭐
如果你觉得有帮助,欢迎点赞收藏,有问题欢迎评论区交流!
- 安装SDK,初始化项目
- 使用
@app.list_tools()注册工具元信息 - 使用
@app.call_tool()实现执行逻辑 - 配置客户端,自动发现和调用
- 善用Inspector和日志进行调试
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)