mcpField
P
python-mcp-server-generator

python-mcp-server-generator

github.com/github开发40.5k10.4k 次安装1 天前更新
代码仓库

关于 python-mcp-server-generator

用于使用 MCP Python SDK v2 构建和测试 Python MCP 服务的技能,指导开发者完成项目设置、实现、测试与客户端配置,并聚焦 SDK v2 的用法。

主要功能

  1. 01设置 Python 服务项目
  2. 02生成带类型的工具与模式
  3. 03按需添加资源和提示词
  4. 04使用内存客户端测试工具
  5. 05配置 MCP 客户端

适用场景

  1. 01创建新的 Python MCP 服务
  2. 02测试工具行为与错误
  3. 03配置 VS Code 或 Claude Desktop

MCP 相关

指导使用 MCP Python SDK v2 创建 MCP 服务,默认采用 stdio,也介绍可选的 Streamable HTTP,并涵盖客户端配置。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/github/awesome-copilot --skill python-mcp-server-generator

安装后在 Claude Code 中输入/python-mcp-server-generator确认已加载。

附带文件references/streamable-http.md

详细介绍

Python MCP 服务生成器

使用官方 MCP Python SDK v2 在 Python 中创建 Model Context Protocol (MCP) 服务。SDK v2 支持 MCP 规范修订版 2026-07-28。同一个服务也可以为使用更早修订版的客户端提供服务。

工作流

复制此清单并跟踪你的进度:

  • 步骤 1:创建项目。
  • 步骤 2:编写服务。
  • 步骤 3:编写测试。
  • 步骤 4:运行测试,直到它们通过。
  • 步骤 5:配置客户端。
步骤 1:创建项目

运行以下命令:

uv init --app --no-package project-name
cd project-name
uv add "mcp[cli]>=2,<3"
uv add --dev pytest

然后删除 main.py。服务放在 server.py 中。

  • 如果不使用 --no-package,uv 会创建 src/ 包布局,测试将无法导入 server.py。
  • uv init 会创建 .gitignore 文件。不要另写一个。
步骤 2:编写服务

从这个模板开始:

from mcp.server import MCPServer
from mcp.server.mcpserver.exceptions import ToolError

mcp = MCPServer("Demo", version="0.1.0")


@mcp.tool()
def divide(a: float, b: float) -> float:
    """Divide a by b."""
    if b == 0:
        raise ToolError("b must not be zero.")
    return a / b


if __name__ == "__main__":
    mcp.run()  # stdio is the default transport

然后根据用户的请求修改模板:

  1. 将 divide 替换为用户需要的工具。
  2. 为每个工具提供完整的类型提示和 docstring。SDK 根据类型提示生成输入 schema。docstring 成为工具描述。
  3. 当客户端需要机器可读的数据时,返回 Pydantic 模型或 TypedDict。SDK 根据返回类型生成输出 schema。
  4. 对于 I/O 使用 async def。SDK 在工作线程上运行同步工具。
  5. 使用 @mcp.tool(annotations=ToolAnnotations(read_only_hint=True))(来自 mcp.types)标记只读工具。对于破坏性工具,使用 destructive_hint=True。
  6. 仅在用户要求时添加资源(@mcp.resource("users://{user_id}"))和提示词(@mcp.prompt())。

默认使用 stdio。仅在用户要求远程服务或 HTTP 服务时,阅读 references/streamable-http.md。

步骤 3:编写测试

将 test_server.py 放在 server.py 旁边。为每个工具和每个 ToolError 编写一个测试:

import pytest

from mcp import Client

from server import mcp


@pytest.mark.anyio
async def test_divide():
    async with Client(mcp) as client:
        result = await client.call_tool("divide", {"a": 6, "b": 3})
        assert result.structured_content == {"result": 2.0}


@pytest.mark.anyio
async def test_divide_by_zero():
    async with Client(mcp) as client:
        result = await client.call_tool("divide", {"a": 1, "b": 0})
        assert result.is_error
        assert "must not be zero" in result.content[0].text
  • 内存中的 Client 不需要子进程,也不需要端口。它使用 2026-07-28 修订版进行连接。
  • mcp 包会安装 anyio,它提供 anyio 标记。不要添加 pytest-asyncio。
步骤 4:运行测试,直到它们通过
  1. 运行 uv run pytest。
  2. 如果测试失败,阅读错误信息。修复服务或测试。
  3. 再次运行 uv run pytest。
  4. 仅当所有测试都通过时才继续。
步骤 5:配置客户端

对于 VS Code,编写 .vscode/mcp.json:

{
  "servers": {
    "demo": {
      "type": "stdio",
      "command": "uv",
      "args": ["--directory", "/absolute/path/to/project", "run", "server.py"]
    }
  }
}

对于 Claude Desktop,运行 uv run mcp install server.py。

告诉用户以下命令:

  • uv run server.py 启动 stdio 服务。服务在 stdin 上等待主机,并且不打印任何内容。
  • uv run mcp dev server.py 打开 MCP Inspector。Inspector 需要 Node.js。

注意事项

SDK v2 和 2026-07-28 修订版改变了许多 SDK v1 的用法模式。不要照搬 SDK v1 的示例。

  • SDK v2 移除了 FastMCP 和 mcp.server.fastmcp。使用 from mcp.server import MCPServer 导入服务类。
  • 从 mcp.server.mcpserver 导入 Context、Image、Audio、Resolve、Elicit、ElicitationResult、AcceptedElicitation、Message、UserMessage 和 AssistantMessage。
  • 将服务名作为 MCPServer 的第一个参数。将所有其他构造函数参数作为关键字参数传入。它们在 SDK v2 中的位置顺序发生了变化。
  • 设置 version。如果不设置,服务会报告空版本。
  • 将传输选项(transport、host、port、json_response、stateless_http、transport_security)传给 run(),而不是传给 MCPServer(...)。
  • SDK v2 类型使用 snake_case 字段,例如 read_only_hint、structured_content 和 is_error。
  • 对于模型必须读取的错误,抛出 ToolError。对于其他异常,模型只会收到一条通用错误消息。
  • 不要为工具失败抛出 MCPError。客户端会收到协议错误,而不是带有 is_error 的工具结果。许多宿主不会向模型显示此错误。
  • 在 stdio 服务中,stdout 是协议通道。不要调用 print()。使用 logging 模块记录到 stderr。
  • 不要使用 ctx.elicit()。它会在 2026-07-28 连接上失败。对于工具调用期间的用户输入,用 Resolve(fn) 标注参数。从 fn 返回 Elicit(message, Model)。
  • 使用 await ctx.notify_tools_changed() 发送列表变更通知。2026-07-28 连接会丢弃 ctx.session.send_tool_list_changed()。
  • 对于 stdio 和 HTTP,lifespan 在服务启动时运行一次。测试中的每个内存 Client(mcp) 都会再次运行 lifespan。使用 ctx.request_context.lifespan_context 读取其对象。
  • 2026-07-28 修订版弃用了以下功能(SEP-2577)。不要将它们添加到新服务中:
    • Sampling(ctx.session.create_message()):直接调用大模型提供商 API。
    • 协议日志(ctx.log()、ctx.info() 及类似方法):使用标准 logging 模块。
    • Roots(ctx.session.list_roots()):从工具参数、资源 URI 或服务配置中获取路径。
  • 2026-07-28 修订版没有 SSE 传输。请使用 Streamable HTTP。

评论

支持 Markdown