模型上下文协议(MCP)是一个开放标准,使AI应用程序能够安全地连接到数据源和工具。通过实现MCP服务器,开发者可以在保持安全性和标准化的同时,用自定义功能扩展AI能力。
MCP已经在很多场景中使用起来了,不过并不是所有同学都已经在使用,对于初学者来说,很有必要从最简单的部分开始,动手搭建自己的MCP Server,然后再搭建MCP Client调用自己搭建的以及第三方的MCP Server,从而进入MCP的世界。
在本教程中,我们将构建一个简单的天气信息MCP服务器,演示MCP的核心概念。这个实践示例将帮助你理解如何创建自己的MCP服务器并将其与AI应用程序集成。
前置条件
开始之前,请确保你有:
- 安装了Python 3.8或更高版本
- 对JSON-RPC协议有基本了解
- 熟悉Python开发
- 代码编辑器或IDE
你将构建什么
我们将创建一个最小的MCP服务器,它能够:
- 响应MCP协议初始化请求
- 提供天气信息工具
- 返回模拟天气数据用于演示
- 可以轻松扩展以连接到真实的天气API
服务器使用四个城市的模拟天气数据:
{
"Beijing": {"temperature": "22°C", "condition": "Sunny"},
"Shanghai": {"temperature": "25°C", "condition": "Cloudy"},
"Shenzhen": {"temperature": "28°C", "condition": "Light Rain"},
"Guangzhou": {"temperature": "27°C", "condition": "Overcast"}
}
架构概览
MCP架构遵循客户端-服务器模型,其中:
- MCP客户端:需要额外功能的AI应用程序或IDE
- MCP服务器:提供特定工具和数据的自定义服务器
- JSON-RPC:客户端和服务器之间的通信协议
┌─────────────┐ JSON-RPC ┌─────────────┐ API调用 ┌──────────────┐
│ MCP客户端 │ ◄──────────────►│ MCP服务器 │ ◄──────────────►│ 数据源 │
│ (AI应用) │ │ (天气) │ │ (天气API) │
└─────────────┘ └─────────────┘ └──────────────┘
这种模块化方法允许你:
- 在不修改AI应用程序的情况下扩展AI能力
- 在AI和数据源之间维护安全边界
- 在不同的AI应用程序中重用服务器
- 独立地扩展和更新功能
项目结构
hello-mcp/
├── weather_server.py # 主MCP服务器(只需要这一个文件!)
└── mcp.json # MCP配置
就是这样!我们只需要两个文件就能构建一个可工作的MCP服务器。Python的标准库提供了我们需要的一切。
步骤1:实现MCP服务器
创建weather_server.py - 这个单一文件包含我们整个MCP服务器:
#!/usr/bin/env python3
import asyncio
import json
import sys
class WeatherMCPServer:
def __init__(self):
# 简单的模拟数据 - 不需要外部依赖
self.weather_data = {
"Beijing": {"temperature": "22°C", "condition": "Sunny"},
"Shanghai": {"temperature": "25°C", "condition": "Cloudy"},
"Shenzhen": {"temperature": "28°C", "condition": "Light Rain"},
"Guangzhou": {"temperature": "27°C", "condition": "Overcast"}
}
async def handle_request(self, request):
"""主请求路由器 - 处理所有MCP协议方法"""
method = request.get("method")
if method == "initialize":
return self._handle_initialize(request)
elif method == "tools/list":
return self._handle_tools_list(request)
elif method == "tools/call":
return self._handle_tools_call(request)
else:
return self._error_response(request.get("id"), -32601, "Method not found")
MCP的美妙之处在于它的简单性 - 我们只需要Python的内置库!让我们分解每个部分:
1. 初始化处理器 - 服务器握手
def _handle_initialize(self, request):
"""告诉客户端这个服务器能做什么"""
return {
"jsonrpc": "2.0",
"id": request.get("id"),
"result": {
"protocolVersion": "2024-11-05",
"capabilities": {"tools": {}}, # 我们提供工具
"serverInfo": {"name": "weather-server", "version": "1.0.0"}
}
}
这就像握手一样 - 客户端问"你能做什么?",我们用我们的能力来回应。
2. 工具列表处理器 - 我们有什么工具?
def _handle_tools_list(self, request):
"""列出所有可用工具及其模式"""
return {
"jsonrpc": "2.0",
"id": request.get("id"),
"result": {
"tools": [{
"name": "get_weather",
"description": "获取指定城市的天气信息",
"inputSchema": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "城市名称",
"enum": ["Beijing", "Shanghai", "Shenzhen", "Guangzhou"]
}
},
"required": ["city"]
}
}]
}
}
这就像菜单一样 - 我们告诉客户端"这是我能做的以及如何请求它"。
3. 工具调用处理器 - 开始工作!
def _handle_tools_call(self, request):
"""执行请求的工具"""
tool_name = request["params"]["name"]
if tool_name == "get_weather":
city = request["params"]["arguments"]["city"]
weather = self.weather_data.get(city, {
"temperature": "Unknown",
"condition": "Data unavailable"
})
return {
"jsonrpc": "2.0",
"id": request.get("id"),
"result": {
"content": [{
"type": "text",
"text": f"Weather in {city}: Temperature {weather['temperature']}, Condition: {weather['condition']}"
}]
}
}
else:
return self._error_response(request.get("id"), -32601, f"Unknown tool: {tool_name}")
def _error_response(self, request_id, code, message):
"""错误响应的辅助函数"""
return {
"jsonrpc": "2.0",
"id": request_id,
"error": {"code": code, "message": message}
}
这里是魔法发生的地方 - 我们实际查找天气数据并返回它。
4. 主服务器循环 - 监听和响应
async def run(self):
"""主服务器循环 - 从stdin读取,写入stdout"""
while True:
try:
# 从stdin读取JSON-RPC请求
line = await asyncio.get_event_loop().run_in_executor(None, sys.stdin.readline)
if not line:
break
# 解析和处理请求
request = json.loads(line.strip())
response = await self.handle_request(request)
# 发送响应到stdout
print(json.dumps(response), flush=True)
except json.JSONDecodeError:
# 处理格式错误的JSON
error = self._error_response(None, -32700, "Parse error")
print(json.dumps(error), flush=True)
except Exception as e:
# 处理意外错误
error = self._error_response(None, -32603, f"Internal error: {str(e)}")
print(json.dumps(error), flush=True)
# 启动服务器
if __name__ == "__main__":
server = WeatherMCPServer()
asyncio.run(server.run())
就是这样! 整个MCP服务器在一个简单的Python文件中,只使用标准库模块。
步骤2:配置文件
创建mcp.json来告诉MCP客户端如何运行你的服务器:
{
"mcpServers": {
"weather": {
"command": "python",
"args": ["weather_server.py"]
}
}
}
就是这样!只需告诉它运行python weather_server.py就完成了。
步骤3:测试你的MCP服务器
快速测试
用简单的命令测试你的服务器:
# 测试1:初始化
echo '{"jsonrpc": "2.0", "id": 1, "method": "initialize", "params": {}}' | python weather_server.py
# 测试2:列出工具
echo '{"jsonrpc": "2.0", "id": 2, "method": "tools/list", "params": {}}' | python weather_server.py
# 测试3:获取天气
echo '{"jsonrpc": "2.0", "id": 3, "method": "tools/call", "params": {"name": "get_weather", "arguments": {"city": "Beijing"}}}' | python weather_server.py
如果一切正常,你会看到类似这样的响应:
// 初始化响应
{"jsonrpc": "2.0", "id": 1, "result": {"protocolVersion": "2024-11-05", "capabilities": {"tools": {}}, "serverInfo": {"name": "weather-server", "version": "1.0.0"}}}
// 天气响应
{"jsonrpc": "2.0", "id": 3, "result": {"content": [{"type": "text", "text": "Weather in Beijing: Temperature 22°C, Condition: Sunny"}]}}
为什么选择MCP而不是传统API?
与传统的REST API方法比较:
# 传统Flask API(需要pip install flask)
from flask import Flask, jsonify
app = Flask(__name__)
@app.route('/weather/<city>')
def get_weather(city):
# 相同的天气逻辑,但通过HTTP
return jsonify(weather_data.get(city))
app.run(port=5000) # 运行在http://localhost:5000
MCP的优势:
- 无需网络设置 - 只需stdin/stdout通信
- 自描述 - 工具自动告诉客户端如何使用它们
- AI原生 - 专为AI工具调用设计
- 安全 - 无开放网络端口,进程级隔离
- 简单 - 一个Python文件,无外部依赖
下一步是什么?
恭喜!你已经用两个文件和零外部依赖构建了你的第一个MCP服务器。以下是一些扩展想法:
简单增强
- 向天气数据添加更多城市
- 创建额外的工具(如
get_forecast或list_cities) - 为城市名称添加输入验证
真实世界集成
- 连接到实际的天气API(OpenWeatherMap等)
- 添加历史数据的数据库存储
- 实现缓存以减少API调用
示例:添加新工具
# 在你的_handle_tools_list方法中添加:
{
"name": "list_cities",
"description": "获取所有可用城市",
"inputSchema": {"type": "object", "properties": {}}
}
# 在你的_handle_tools_call方法中添加:
elif tool_name == "list_cities":
cities = list(self.weather_data.keys())
return {
"jsonrpc": "2.0",
"id": request.get("id"),
"result": {
"content": [{
"type": "text",
"text": f"可用城市:{', '.join(cities)}"
}]
}
}
总结
你刚刚用不到100行Python代码构建了一个完整的MCP服务器!无复杂设置,无外部依赖 - 只是让MCP工作的核心逻辑。
关键要点:
- MCP服务器出奇地简单 - 只是通过stdin/stdout的JSON-RPC
- 三个主要方法:
initialize、tools/list和tools/call - 自描述工具使AI集成无缝
- 非常适合用自定义功能扩展AI应用程序
MCP的美妙之处在于这个简单的模式可以从像这样的基本示例扩展到复杂的企业集成。你现在有了为任何用例构建MCP服务器的基础。
2万+

被折叠的 条评论
为什么被折叠?



