上周深夜,我正准备演示一个新项目时,控制台突然弹出一行刺眼的红色报错:ConnectionError: timeout exceeded while connecting to MCP server。在场的同事们面面相觑,我的心跳瞬间加速——这可是演示前的最后十分钟。经历过无数次这种绝望时刻后,我决定写一篇完整的 MCP Server 开发教程,帮助大家避开我踩过的所有坑。

MCP Server 是什么?为什么你需要它

MCP(Model Context Protocol)是一个让 AI 模型与外部工具、数据源无缝对接的协议标准。简单来说,它就像是 AI 世界的「USB 接口」,让你的 Python 应用能够轻松调用各种 AI 能力。通过 HolySheep AI 的 API,你可以获得国内直连延迟小于 50ms 的优质体验,配合 ¥1=$1 的无损汇率政策,成本控制变得前所未有的简单。

在这个教程中,我将分享如何使用 Python SDK 开发自己的 MCP Server,包括认证配置、请求重试、流式响应处理等核心场景。所有的代码都经过生产环境验证,可以直接复制使用。

环境准备与 SDK 安装

首先确保你的 Python 版本 ≥ 3.8,然后安装必要的依赖包。我强烈建议使用虚拟环境来隔离项目依赖:

# 创建并激活虚拟环境
python -m venv mcp-project
source mcp-project/bin/activate  # Linux/Mac

mcp-project\Scripts\activate # Windows

安装 MCP Python SDK 和相关依赖

pip install mcp holysheep-sdk requests httpx

验证安装

python -c "import mcp; print('MCP SDK version:', mcp.__version__)"

接下来配置你的 API 凭证。建议使用环境变量而非硬编码密钥,这样更安全也更符合 12-Factor App 的最佳实践:

# 在项目根目录创建 .env 文件
HOLYSHEEP_API_KEY=YOUR_HOLYSHEEP_API_KEY
HOLYSHEEP_BASE_URL=https://api.holysheep.ai/v1

在 Python 代码中加载环境变量

from dotenv import load_dotenv import os load_dotenv() # 加载 .env 文件 API_KEY = os.getenv("HOLYSHEEP_API_KEY") BASE_URL = os.getenv("HOLYSHEEP_BASE_URL")

验证配置是否正确

if not API_KEY or API_KEY == "YOUR_HOLYSHEEP_API_KEY": raise ValueError("请先配置有效的 HolySheep API Key")

基础 MCP Server 开发

现在让我们创建一个最简单的 MCP Server。我当初第一次写的时候,在认证部分栽了大跟头——总是收到 401 错误,折腾了三小时才发现是 base_url 配置错了。所以让我带你一步步走通这个流程。

# mcp_server.py
import asyncio
from mcp.server import MCPServer
from mcp.types import Tool, CallToolResult
from holysheep_sdk import HolySheepClient
import httpx

初始化 HolySheep 客户端

class HolySheepMCPServer(MCPServer): def __init__(self, api_key: str, base_url: str = "https://api.holysheep.ai/v1"): super().__init__(name="holysheep-mcp-server", version="1.0.0") self.client = HolySheepClient( api_key=api_key, base_url=base_url, timeout=30.0, # 超时时间设为 30 秒 max_retries=3 # 最大重试次数 ) async def call_tool(self, tool_name: str, arguments: dict) -> CallToolResult: """处理工具调用请求""" if tool_name == "chat_completion": return await self._handle_chat_completion(arguments) elif tool_name == "embedding": return await self._handle_embedding(arguments) else: return CallToolResult(error=f"Unknown tool: {tool_name}") async def _handle_chat_completion(self, args: dict) -> CallToolResult: """处理聊天补全请求""" try: response = await self.client.chat.completions.create( model=args.get("model", "gpt-4o"), messages=args.get("messages", []), temperature=args.get("temperature", 0.7), max_tokens=args.get("max_tokens", 1000) ) return CallToolResult(content=str(response)) except httpx.TimeoutException: return CallToolResult(error="请求超时,请检查网络连接或增加超时时间") except Exception as e: return CallToolResult(error=f"API 调用失败: {str(e)}")

启动服务器

async def main(): server = HolySheepMCPServer( api_key=os.getenv("HOLYSHEEP_API_KEY"), base_url="https://api.holysheep.ai/v1" ) await server.start() print("✅ MCP Server 已启动,监听端口 8765") await asyncio.Event().wait() # 保持服务器运行 if __name__ == "__main__": asyncio.run(main())

运行上面的代码后,你应该能看到服务器成功启动。但在生产环境中,我遇到了一个很棘手的问题——当并发请求增多时,连接池耗尽导致大量 503 错误。下面是优化后的版本,加入了连接池管理和优雅的异常处理:

# mcp_server_production.py
import asyncio
from contextlib import asynccontextmanager
from mcp.server import MCPServer
from mcp.types import Tool, CallToolResult
import httpx
from tenacity import retry, stop_after_attempt, wait_exponential

class ProductionMCPserver(MCPServer):
    def __init__(self, api_key: str, base_url: str):
        super().__init__(name="holysheep-mcp-prod", version="2.0.0")
        # 配置连接池:最大连接数 100,保持连接活跃
        self.http_client = httpx.AsyncClient(
            base_url=base_url,
            headers={"Authorization": f"Bearer {api_key}"},
            limits=httpx.Limits(max_connections=100, max_keepalive_connections=20),
            timeout=httpx.Timeout(30.0, connect=5.0)
        )
        self._semaphore = asyncio.Semaphore(50)  # 限制并发数为 50
    
    @retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=2, max=10))
    async def _make_request(self, endpoint: str, data: dict) -> dict:
        """带重试机制的请求方法"""
        async with self._semaphore:  # 并发控制
            response = await self.http_client.post(endpoint, json=data)
            response.raise_for_status()
            return response.json()
    
    async def call_tool(self, tool_name: str, arguments: dict) -> CallToolResult:
        try:
            if tool_name == "analyze_text":
                result = await self._analyze_with_ai(arguments)
                return CallToolResult(content=result, is_error=False)
            return CallToolResult(error=f"Tool {tool_name} not implemented")
        except httpx.HTTPStatusError as e:
            if e.response.status_code == 429:
                return CallToolResult(error="请求频率超限,请稍后重试")
            return CallToolResult(error=f"HTTP 错误 {e.response.status_code}: {e.response.text}")
        except Exception as e:
            return CallToolResult(error=f"服务器内部错误: {str(e)}")
    
    async def _analyze_with_ai(self, args: dict) -> str:
        result = await self._make_request("/chat/completions", {
            "model": "claude-sonnet-4-20250514