《Python实战:30分钟搭建你的第一个MCP服务器(附完整代码)》

2,847 阅读3分钟

🔍 为什么要手动实现MCP服务器?

大型语言模型(如Claude、GPT)虽能生成文本,但无法直接操作现实世界的数据和工具。MCP服务器就像AI的"双手",让模型能够:
✅ 查询数据库获取实时数据
✅ 调用API执行具体操作(如发送邮件)
✅ 访问本地文件系统

通过Simple-MCP-Server项目,开发者无需从零造轮子,可快速实现以下功能:

  • 标准化JSON-RPC 2.0协议通信
  • 自动工具发现与路由
  • 类型安全的参数校验

🛠️ 环境准备(3分钟)

1. 安装基础工具

# 创建虚拟环境
python -m venv mcp-env
source mcp-env/bin/activate  # Windows: mcp-env\Scripts\activate

# 安装依赖
pip install mcp-sdk requests  # 核心SDK+HTTP库

注:推荐Python 3.8+,避免SSL兼容性问题

2. 克隆示例项目

git clone https://github.com/ruslanmv/Simple-MCP-Server-with-Python.git
cd Simple-MCP-Server-with-Python

💻 核心代码解析(带优化建议)

1. 工具类定义(原始代码优化)

from mcp_sdk import Tool
import requests

class WeatherTool(Tool):
    """获取城市天气(优化版)"""
    def run(self, city: str) -> dict:
        """添加类型注解和错误处理"""
        try:
            url = f"https://api.weatherapi.com/v1/current.json?key=YOUR_KEY&q={city}"
            response = requests.get(url, timeout=5.0)
            data = response.json()
            return {
                "temperature": data["current"]["temp_c"],
                "condition": data["current"]["condition"]["text"]
            }
        except Exception as e:
            return {"error": f"Weather API failed: {str(e)}"}

优化点

  • 增加类型提示(city: str
  • 添加超时和异常处理
  • 返回结构化数据而非原始API响应

2. 服务器启动(支持热重载)

from mcp_sdk import MCP
from weather_tool import WeatherTool  # 导入自定义工具

mcp = MCP(port=8080, debug=True)  # 开启调试模式
mcp.register_tool(WeatherTool(), name="get_weather")

if __name__ == "__main__":
    mcp.start(auto_reload=True)  # 开发时自动重载

关键参数说明

  • port: 指定服务端口(默认8080)
  • auto_reload: 代码修改后自动重启

🌐 实战演示:查询天气

1. 启动服务器

python server.py
# 输出示例:MCP Server running on http://0.0.0.0:8080

2. 通过客户端调用

from mcp_sdk import MCPClient

client = MCPClient("http://localhost:8080")
result = client.call_tool("get_weather", {"city": "北京"})
print(result)  # 输出:{'temperature': 25, 'condition': '晴'}

3. 在AI应用中集成

配置Cursor/Claude Desktop连接本地MCP服务器:

  1. 打开设置 → MCP → 添加服务器
  2. 输入URL:http://localhost:8080
  3. 测试工具是否可见

🚀 进阶功能扩展

1. 添加数据库工具

@mcp.tool()
def query_users(limit: int = 10):
    """查询用户数据(SQLite示例)"""
    conn = sqlite3.connect('demo.db')
    cursor = conn.cursor()
    cursor.execute(f"SELECT * FROM users LIMIT {limit}")
    return cursor.fetchall()

注:生产环境应使用参数化查询防SQL注入

2. 异步处理高延迟操作

@mcp.tool()
async def async_fetch(url: str):
    """异步获取网页内容"""
    async with httpx.AsyncClient() as client:
        response = await client.get(url)
        return {"status": response.status_code, "content": response.text}

3. 安全加固(OAuth2示例)

from fastapi.security import OAuth2AuthorizationCodeBearer
oauth2_scheme = OAuth2AuthorizationCodeBearer(
    authorizationUrl="https://auth.example.com/auth",
    tokenUrl="https://auth.example.com/token"
)

@mcp.tool(dependencies=[Depends(oauth2_scheme)])
def secure_action():
    """需要认证的工具"""
    return {"status": "authorized"}

📊 性能监控方案

from prometheus_client import start_http_server, Counter

REQUEST_COUNT = Counter('mcp_requests', 'Total tool calls')

@mcp.tool()
def monitored_tool():
    REQUEST_COUNT.inc()  # 记录调用次数
    return {"data": "..."}

if __name__ == "__main__":
    start_http_server(9000)  # 暴露/metrics端点
    mcp.start()

访问http://localhost:9000/metrics查看监控数据


💡 常见问题排错

问题现象解决方案
Address already in use修改端口或执行kill -9 $(lsof -t -i:8080)
工具未出现在客户端检查register_tool的name参数是否匹配
返回数据被截断检查是否超过默认1MB大小限制

🎯 总结

通过Simple-MCP-Server项目,我们实现了:

  1. 标准化工具暴露:Weather/DB查询等能力
  2. 无缝AI集成:Claude/Cursor直接调用
  3. 生产级特性:异步/认证/监控