zeromcp
纯Python中最小的MCP服务器实现。
一种轻量级的手工实现 模型上下文协议 专注于大多数用户实际需要的东西:使用干净的Python类型注释公开工具。
特性
- ✨ 零依赖 -纯Python,仅标准库
- 🎯 类型安全 -所有内容的原生Python类型注释
- 🚀 快速 -开销最小,性能最高
- 🛠️ 手工制作的 -由人类书写1,根据规范进行验证
- 🌐 HTTP/SSE传输 -可简化的响应
- 📡 标准运输 -对于传统客户
- 📦 微小 -少于1000行代码
安装
pip install zeromcp或者使用紫外线:
uv add zeromcp快速开始
from typing import Annotated
from zeromcp import McpServer
mcp = McpServer("my-server")
@mcp.tool
def greet(
name: Annotated[str, "Name to greet"],
age: Annotated[int | None, "Age of person"] = None
) -> str:
"""Generate a greeting message"""
if age:
return f"Hello, {name}! You are {age} years old."
return f"Hello, {name}!"
if __name__ == "__main__":
mcp.serve("127.0.0.1", 8000)然后使用手动测试您的MCP服务器 检查员:
npx -y @modelcontextprotocol/inspector一旦一切正常,您就可以配置 mcp.json:
{
"mcpServers": {
"my-server": {
"type": "http",
"url": "http://127.0.0.1:8000/mcp"
}
}
}标准运输
对于仅支持stdio传输的MCP客户端:
from zeromcp import McpServer
mcp = McpServer("my-server")
@mcp.tool
def greet(name: str) -> str:
"""Generate a greeting"""
return f"Hello, {name}!"
if __name__ == "__main__":
mcp.stdio()然后在中配置 mcp.json (每个客户都不一样):
{
"mcpServers": {
"my-server": {
"command": "python",
"args": ["path/to/server.py"]
}
}
}类型注解
zeromcp使用原生Python Annotated 用于模式生成的类型:
from typing import Annotated, Optional, TypedDict, NotRequired
class GreetingResponse(TypedDict):
message: Annotated[str, "Greeting message"]
name: Annotated[str, "Name that was greeted"]
age: Annotated[NotRequired[int], "Age if provided"]
@mcp.tool
def greet(
name: Annotated[str, "Name to greet"],
age: Annotated[Optional[int], "Age of person"] = None
) -> GreetingResponse:
"""Generate a greeting message"""
if age is not None:
return {
"message": f"Hello, {name}! You are {age} years old.",
"name": name,
"age": age
}
return {
"message": f"Hello, {name}!",
"name": name
}联合类型
工具可以接受多种输入类型:
from typing import Annotated, TypedDict
class StructInfo(TypedDict):
name: Annotated[str, "Structure name"]
size: Annotated[int, "Structure size in bytes"]
fields: Annotated[list[str], "List of field names"]
@mcp.tool
def struct_get(
names: Annotated[list[str], "Array of structure names"]
| Annotated[str, "Single structure name"]
) -> list[StructInfo]:
"""Retrieve structure information by names"""
return [
{
"name": name,
"size": 128,
"fields": ["field1", "field2", "field3"]
}
for name in (names if isinstance(names, list) else [names])
]错误处理
from zeromcp import McpToolError
@mcp.tool
def divide(
numerator: Annotated[float, "Numerator"],
denominator: Annotated[float, "Denominator"]
) -> float:
"""Divide two numbers"""
if denominator == 0:
raise McpToolError("Division by zero")
return numerator / denominator资源
通过URI模式公开只读数据。资源被序列化为JSON。
from typing import Annotated
@mcp.resource("file://data.txt")
def read_file() -> dict:
"""Get information about data.txt"""
return {"name": "data.txt", "size": 1024}
@mcp.resource("file://{filename}")
def read_any_file(
filename: Annotated[str, "Name of file to read"]
) -> dict:
"""Get information about any file"""
return {"name": filename, "size": 2048}鼓励
公开具有类型化参数的可重用提示模板。
from typing import Annotated
@mcp.prompt
def code_review(
code: Annotated[str, "Code to review"],
language: Annotated[str, "Programming language"] = "python"
) -> str:
"""Review code for bugs and improvements"""
return f"Please review this {language} code:\n\n```{language}\n{code}\n```"跨域资源共享
默认情况下,zeromcp允许来自本地主机的CORS请求(localhost, 127.0.0.1, ::1)on 任何端口。这允许MCP检查器或本地AI工具等工具与您的MCP服务器通信。
from zeromcp import McpServer
mcp = McpServer("my-server")
# Default: allow localhost on any port
mcp.cors_allowed_origins = mcp.cors_localhost
# Allow all origins (use with caution)
mcp.cors_allowed_origins = "*"
# Allow specific origins
mcp.cors_allowed_origins = [
"http://localhost:3000",
"https://myapp.example.com",
]
# Disable CORS (blocks all browser cross-origin requests)
mcp.cors_allowed_origins = None
# Custom logic
mcp.cors_allowed_origins = lambda origin: origin.endswith(".example.com")注意:CORS仅影响基于浏览器的请求。非浏览器客户端,如 curl 或MCP桌面应用程序不受此设置的影响。
支持的客户
以下客户端已经过测试:
_备注_:一般来说 /mcp 端点是首选,但并非所有客户端都正确支持它。
1README和Claude编写的一些测试
