Config is the same across clients — only the file and path differ.
{
"mcpServers": {
"my-server": {
"url": "http://127.0.0.1:8000/mcp",
"type": "http"
}
}
}Are you the author?
Add this badge to your README to show your security score and help users find safe servers.
Minimal MCP server implementation in pure Python.
This server supports HTTP transport. Be the first to test it — help the community know if it works.
Five weighted categories — click any category to see the underlying evidence.
No known CVEs.
Checked zeromcp against OSV.dev.
Click any tool to inspect its schema.
read_fileGet information about data.txt
file://data.txt
read_any_fileGet information about any file
file://{filename}
code_reviewReview code for bugs and improvements
Be the first to review
Have you used this server?
Share your experience — it helps other developers decide.
Sign in to write a review.
Others in developer-tools
Context7 Platform -- Up-to-date code documentation for LLMs and AI code editors
XcodeBuildMCP provides tools for Xcode project management, simulator management, and app utilities.
Copy/paste detector for programming source code, supports 223 formats. AI-ready with token-efficient reporter, skill and MCP server.
A Model Context Protocol (MCP) server and CLI that provides tools for agent use when working on iOS and macOS projects.
MCP Security Weekly
Get CVE alerts and security updates for Zeromcp and similar servers.
Start a conversation
Ask a question, share a tip, or report an issue.
Sign in to join the discussion.
Minimal MCP server implementation in pure Python.
A lightweight, handcrafted implementation of the Model Context Protocol focused on what most users actually need: exposing tools with clean Python type annotations.
pip install zeromcp
Or with uv:
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)
Then manually test your MCP server with the inspector:
npx -y @modelcontextprotocol/inspector
Once things are working you can configure the mcp.json:
{
"mcpServers": {
"my-server": {
"type": "http",
"url": "http://127.0.0.1:8000/mcp"
}
}
}
For MCP clients that only support stdio transport:
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()
Then configure in mcp.json (different for every client):
{
"mcpServers": {
"my-server": {
"command": "python",
"args": ["path/to/server.py"]
}
}
}
zeromcp uses native Python Annotated types for schema generation:
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
}
Tools can accept multiple input types:
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
Expose read-only data via URI patterns. Resources are serialized as JSON.
... [View full README on GitHub](https://github.com/mrexodia/zeromcp#readme)