用 Python MCP Server 把 LLM 接上你的真实数据

2026-05-26 22 预计阅读时间:1 分钟
来源:realpython.com AI 摘要 原文链接

免责声明:本文为 AI 摘要整理,建议结合原文阅读。摘要可能省略上下文、版本差异或边界条件,不作为官方说明。

预计阅读时间:7 分钟

大模型能聊天,但聊不了你的数据库、内部 API 和本地文件——直到 MCP(Model Context Protocol)出现。MCP 是 Anthropic 掐出的开放协议,定义了 LLM 如何与外部数据源和工具对接。对 Python 开发者来说,写一个 MCP Server 比想象中简单:几行代码就能让 Claude 或其他兼容客户端直接调用你定义的函数、读取你暴露的资源。

下面拆解 MCP 的四个核心概念,再给一个可以跑起来的完整示例。

MCP 的四个角色

Server 是你写的服务端,负责向 LLM 暴露能力。一个 Server 可以同时提供三类东西:

  • Tools(工具)——LLM 可以主动调用的函数,比如查库存、发邮件、跑脚本。
  • Resources(资源)——LLM 可以读取的数据,比如一份配置文件、一条数据库记录。资源是被动拉取的,由客户端决定什么时候读。
  • Prompts(提示模板)——预定义的对话模板,带可变参数,帮助用户快速进入特定场景。

Client 是 LLM 应用侧的连接器,负责发现 Server 提供的上述三类内容,并在对话中按需调用。Claude Desktop 就是一个内置了 MCP Client 的应用;你也可以用 SDK 自己写 Client。

一句话总结分工:Server 说"我能做什么",Client 说"我现在要用哪个"。

用 Python 写一个最小 MCP Server

官方提供了 mcp Python SDK,安装后就能快速起服务。以下示例暴露一个 Tool(查天气)和一个 Resource(城市列表),跑起来后 Claude Desktop 可以直接调用。

先装依赖:

pip install mcp

然后写 Server 代码,保存为 weather_server.py

from mcp.server.fastmcp import FastMCP

mcp = FastMCP("weather-demo")

# --- Tool: LLM 可主动调用的函数 ---
@mcp.tool()
def get_weather(city: str) -> str:
    """查询指定城市的当前天气(模拟数据)"""
    # 实际项目中替换为真实 API 调用
    mock_data = {
        "北京": "晴,气温 28°C",
        "上海": "多云,气温 25°C",
        "深圳": "阵雨,气温 30°C",
    }
    return mock_data.get(city, f"暂无 {city} 的天气数据")

# --- Resource: LLM 可被动读取的数据 ---
@mcp.resource("cities://list")
def list_cities() -> str:
    """返回支持查询的城市列表"""
    return "北京、上海、深圳"

# --- Prompt: 预定义的对话模板 ---
@mcp.prompt()
def weather_query(city: str) -> str:
    """生成天气查询的对话提示"""
    return f"请帮我查询 {city} 的天气情况,并给出穿衣建议。"

if __name__ == "__main__":
    mcp.run()

运行:

python weather_server.py

默认以 stdio 模式启动——Server 通过标准输入输出与 Client 通信,适合被 Claude Desktop 这类宿主进程拉起。

让 Claude Desktop 连上你的 Server

在 Claude Desktop 的配置文件中注册你的 MCP Server。配置文件路径:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%\Claude\claude_desktop_config.json

编辑配置:

{
  "mcpServers": {
    "weather-demo": {
      "command": "python",
      "args": ["weather_server.py"],
      "cwd": "/absolute/path/to/your/project"
    }
  }
}

重启 Claude Desktop,在对话中试试:

  • "帮我查一下北京的天气" → Claude 会调用 get_weather Tool
  • "你能查哪些城市?" → Claude 会读取 cities://list Resource
  • 使用 Prompt 模板时,Claude 会在 Prompt 列表中看到 weather_query,填入城市参数后直接进入对话

几个容易踩的坑

Tool 和 Resource 别搞混。 Tool 是 LLM 主动触发的动作(有副作用,比如写数据库),Resource 是被动读取的数据(无副作用)。把纯查询写成 Tool 也能跑,但语义不对,会让 LLM 在不该调用时反复调用。

参数类型要显式标注。 FastMCP 通过函数签名和 docstring 推断 Tool 的参数 schema。如果参数是 int 却没标注,LLM 可能传字符串进来,服务端报错。建议每个参数都写类型注解,docstring 也别省。

stdio vs SSE。 上面的示例用的是 stdio 传输,适合本地进程间通信。如果你要把 Server 部署到远程机器,改用 SSE 模式:

mcp.run(transport="sse")

Client 配置也要相应改成 url 字段指向远程地址。注意 SSE 模式下要自己处理认证和 CORS。

错误处理要返回字符串,不要抛异常。 MCP Tool 的返回值最终会作为文本喂给 LLM。如果函数内部抛了未捕获异常,Client 只能看到一个笼统的错误提示。建议在 Tool 函数里 try-catch,把错误信息以可读字符串返回,LLM 能据此向用户解释或重试。

上手路线建议

  1. 先跑通最小示例——用上面的天气 Server 在 Claude Desktop 里验证连通性。
  2. 接真实数据源——把 mock 数据替换成你的内部 API 或数据库查询,注意加权限控制。
  3. 逐步加 Resource 和 Prompt——让 LLM 不仅能"做事",还能"看数据"和"按模板对话"。
  4. 考虑部署模式——本地开发用 stdio,生产环境用 SSE + 认证中间件。
  5. 写测试——用 mcp SDK 自带的 Client 类写集成测试,确保 Tool/Resource/Prompt 的 schema 和返回值符合预期,不要依赖手动在 Claude Desktop 里点。

MCP 的核心价值不是协议本身有多复杂,而是它给了一个标准化的接缝:你只管写 Server 暴露能力,任何兼容 Client 的 LLM 应用都能直接用。先把一个 Server 跑起来,比读完整个 spec 有用得多。


相关推荐