Claude学院

MCP Server 怎么搭建?Python 从零开发一个服务器

搭建一个 MCP Server,本质上就是用官方的 mcp Python SDK 写几个被装饰器标注的函数,再通过 stdio 把它暴露给 Claude 客户端。最快路径是:pip install "mcp[cli]" 安装 SDK,用 FastMCP 实例注册工具,运行 mcp.run(),最后在 Claude Desktop 或 Claude Code 的配置里加一条 server 记录即可。下面给出从零到可调用的完整步骤。

MCP Server 是什么,为什么要自己写

MCP(Model Context Protocol,模型上下文协议)是 Anthropic 主导的开放标准,让模型以统一的方式连接外部工具和数据源。如果你还不清楚协议本身,建议先读 MCP 是什么?一篇讲清 Claude 模型上下文协议 打底。简单说,MCP Server 是「能力提供方」,Claude(客户端)通过它去读文件、查数据库、调内部 API。官方虽然提供了文件系统、GitHub 等现成 Server,但当你要接公司内部系统时,就得自己写。

一个 MCP Server 主要对外暴露三类东西:

  • Tools(工具):模型可以主动调用的函数,类似 Tool Use 里的工具,但由 Server 托管。
  • Resources(资源):可被读取的数据,用 URI 标识,比如 config://appfile://...
  • Prompts(提示模板):预置好的提示词模板,供用户在客户端里一键调用。

第一步:环境准备与安装 SDK

建议 Python 3.10 以上。先建虚拟环境,再装带命令行工具的完整版:

python -m venv venv
# Windows: venv\Scripts\activate ;macOS/Linux: source venv/bin/activate
pip install "mcp[cli]"

mcp[cli] 会附带一个 mcp 命令行,用于本地调试(后面会用到 mcp dev)。如果你只想要运行时,去掉 [cli] 也行。

第二步:用 FastMCP 写最小可运行的 Server

新建 server.pyFastMCP 是 SDK 提供的高层封装,用装饰器声明工具,类型注解会自动转成 JSON Schema 让模型识别参数:

from mcp.server.fastmcp import FastMCP

mcp = FastMCP("demo-server")

@mcp.tool()
def add(a: int, b: int) -> int:
    """计算两个整数的和。"""
    return a + b

@mcp.tool()
def get_weather(city: str) -> str:
    """根据城市名返回天气(示例数据)。"""
    data = {"北京": "晴 26℃", "上海": "多云 24℃"}
    return data.get(city, f"暂无 {city} 的天气数据")

@mcp.resource("config://app")
def app_config() -> str:
    """返回应用配置。"""
    return '{"version": "1.0", "env": "prod"}'

@mcp.prompt()
def summarize(text: str) -> str:
    """生成一个总结指令。"""
    return f"请用三句话总结下面内容:\n\n{text}"

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

注意三点:函数的 docstring 会成为工具描述,模型靠它判断何时调用,务必写清楚;类型注解必须写全,否则参数 Schema 不完整;mcp.run() 默认用 stdio 传输,这正是 Claude Desktop / Claude Code 接本地 Server 的标准方式。

第三步:本地调试,不连 Claude 也能测

写完先别急着接客户端。SDK 自带 Inspector,可以在浏览器里手动点工具、看返回:

mcp dev server.py

它会启动一个 Web UI,你能看到注册的所有 Tools / Resources / Prompts,逐个填参数测试。这一步能把「函数本身有没有写错」和「客户端接没接上」两类问题彻底分开,强烈建议每次改完都先跑一遍。

第四步:在 Claude 客户端里接入

调试没问题后接入真实客户端。Claude Desktop 的配置文件路径:Windows 在 %APPDATA%\Claude\claude_desktop_config.json,macOS 在 ~/Library/Application Support/Claude/claude_desktop_config.json。加入下面这段(用绝对路径):

{
  "mcpServers": {
    "demo-server": {
      "command": "python",
      "args": ["E:/path/to/server.py"]
    }
  }
}

保存后完全退出再重启 Claude Desktop,输入框附近会出现工具图标。桌面版的连接器细节可参考 Claude MCP 怎么配置?桌面版连接器设置教程

如果你用命令行的 Claude Code,更简单,一条命令即可注册:

claude mcp add demo-server -- python E:/path/to/server.py

claude mcp list 可查看已连接的 Server 状态。完整流程见 Claude Code 配置 MCP 服务器完整步骤

进阶:环境变量与外部 API 调用

真实 Server 往往要访问带密钥的外部服务。不要把密钥写死在代码里,用环境变量传入,配置里通过 env 字段注入:

{
  "mcpServers": {
    "demo-server": {
      "command": "python",
      "args": ["E:/path/to/server.py"],
      "env": { "MY_API_KEY": "sk-xxxx" }
    }
  }
}

代码里用 os.environ["MY_API_KEY"] 读取即可。如果工具内部要调用网络接口,建议用 httpx 并把工具函数写成 async defFastMCP 原生支持异步工具,不会阻塞其他调用。

传输方式:stdio 还是 HTTP

本地开发用 stdio(默认)最方便,进程由客户端拉起。如果 Server 要部署到远程、给多个用户共享,则改用可流式的 HTTP 传输,启动时指定即可:

传输方式适用场景启动方式
stdio本地单机,客户端托管进程mcp.run()
Streamable HTTP远程部署、多用户共享mcp.run(transport="streamable-http")

远程部署时务必加上鉴权和访问控制,MCP Server 等于把能力开放给模型,权限边界一定要收紧。

常见问题

Claude 客户端里看不到我的工具怎么办?

按顺序排查:一是确认 mcp dev server.py 本地能跑通,排除代码问题;二是检查配置文件里 command 和路径,python 最好换成解释器绝对路径(虚拟环境尤其重要),args 用脚本绝对路径;三是改完配置必须完全退出客户端再重启。Claude Code 用户可用 claude mcp list 看连接状态,failed 状态通常是命令或路径错了。

工具的参数和描述模型识别不准?

MCP 工具的 Schema 完全来自函数签名和 docstring。务必给每个参数写类型注解,docstring 第一行写清这个工具「做什么、什么时候用」。这和写普通 函数调用 的描述是一个道理——描述越具体,模型调用越准。复杂参数可以用 Pydantic 模型做结构化定义。

MCP Server 和直接写 Tool Use 有什么区别?

直接用 Messages API 的 Tool Use,工具定义和执行逻辑都在你自己的应用代码里,适合单个应用内部。MCP 则把工具抽象成独立、可复用的标准化服务,一次写好,能被 Claude Desktop、Claude Code 等任意支持 MCP 的客户端复用,也方便团队共享。需要跨应用复用、或要接入官方客户端时,优先选 MCP。

Projects 与 MCP