关于 python-mcp-server-generator
用于使用 MCP Python SDK v2 构建和测试 Python MCP 服务的技能,指导开发者完成项目设置、实现、测试与客户端配置,并聚焦 SDK v2 的用法。
主要功能
- 01设置 Python 服务项目
- 02生成带类型的工具与模式
- 03按需添加资源和提示词
- 04使用内存客户端测试工具
- 05配置 MCP 客户端
适用场景
- 01创建新的 Python MCP 服务
- 02测试工具行为与错误
- 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
然后根据用户的请求修改模板:
- 将
divide替换为用户需要的工具。 - 为每个工具提供完整的类型提示和 docstring。SDK 根据类型提示生成输入 schema。docstring 成为工具描述。
- 当客户端需要机器可读的数据时,返回 Pydantic 模型或
TypedDict。SDK 根据返回类型生成输出 schema。 - 对于 I/O 使用
async def。SDK 在工作线程上运行同步工具。 - 使用
@mcp.tool(annotations=ToolAnnotations(read_only_hint=True))(来自mcp.types)标记只读工具。对于破坏性工具,使用destructive_hint=True。 - 仅在用户要求时添加资源(
@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:运行测试,直到它们通过
- 运行
uv run pytest。 - 如果测试失败,阅读错误信息。修复服务或测试。
- 再次运行
uv run pytest。 - 仅当所有测试都通过时才继续。
步骤 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 或服务配置中获取路径。
- Sampling(
- 2026-07-28 修订版没有 SSE 传输。请使用 Streamable HTTP。
评论
支持 Markdown