Skip to main content

ZeroMCP — Python

Drop a .py file in a folder, get a sandboxed MCP server. Stdio out of the box, zero dependencies.

Getting started

# tools/hello.py — this is a complete MCP server
tool = {
    "description": "Say hello to someone",
    "input": {"name": "string"},
}

async def execute(args, ctx):
    return f"Hello, {args['name']}!"
python3 -m zeromcp serve ./tools

That's it. Stdio transport works immediately. Drop another .py file to add another tool. Delete a file to remove one. No server object, no decorators, no main block.

vs. the official SDK

The official Python SDK (FastMCP) requires a server object, decorators, and a __main__ block. Adding a tool means editing server code and restarting. ZeroMCP is file-based — each tool is its own file, discovered automatically.

In benchmarks, ZeroMCP Python handles 12,936 requests/second over stdio versus the official SDK's 1,018 — 12.7x faster with 59% less memory. Over HTTP (Starlette), ZeroMCP serves 2,623 rps at 27 MB versus the official SDK's 635 rps at 80-87 MB. ZeroMCP uses only the standard library. The official SDK pulls in pydantic, httpx, uvicorn, and starlette just for stdio.

Python passes all 10 conformance suites and survives 21/22 chaos monkey attacks.

The official SDK has no sandbox. ZeroMCP enforces per-tool network allowlists and credential isolation at runtime, plus static auditing for filesystem and exec access.

HTTP / Streamable HTTP

ZeroMCP doesn't own the HTTP layer. You bring your own framework; ZeroMCP gives you an async handler that takes a JSON-RPC dict and returns a response dict (or None for notifications).

from zeromcp import create_handler

handler = await create_handler("./tools")
# handler(request: dict) -> dict | None

Flask

from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route("/mcp", methods=["POST"])
async def mcp():
    response = await handler(request.get_json())
    if response is None:
        return "", 204
    return jsonify(response)

FastAPI

from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse

app = FastAPI()

@app.post("/mcp")
async def mcp(req: Request):
    response = await handler(await req.json())
    if response is None:
        return JSONResponse(status_code=204, content=None)
    return response

Requirements

  • Python 3.10+
  • No external dependencies (stdlib only)

Install

pip install -e .

Defining tools

# tools/add.py
tool = {
    "description": "Add two numbers together",
    "input": {"a": "number", "b": "number"},
}

async def execute(args, ctx):
    return {"sum": args["a"] + args["b"]}

Input types

Shorthand strings: "string", "number", "boolean", "object", "array".

Returning values

Return a string or a dict. ZeroMCP wraps it in the MCP content envelope for you.

Sandbox

The Python implementation sandboxes network access at runtime and audits filesystem/exec access statically.

Network allowlists

tool = {
    "description": "Fetch from our API",
    "input": {"endpoint": "string"},
    "permissions": {
        "network": ["api.example.com", "*.internal.dev"],
    },
}

async def execute(args, ctx):
    res = await ctx.fetch(f"https://api.example.com/{args['endpoint']}")
    return res["body"]

ctx.fetch validates the hostname against the allowlist. Unlisted domains are blocked and logged.

Credential injection

Tools receive secrets via ctx.credentials, configured per namespace. Tools never call os.environ directly.

Filesystem and exec control

Declaring fs or exec in a tool's permissions gets logged as an elevated-permission request when the tool loads. Enforcement is static, not runtime: python3 -m zeromcp audit ./tools scans tool files for raw open(), subprocess, os.system, os.popen, and os.environ calls and reports them as violations. Unlike ctx.fetch, there's no sandboxed proxy for filesystem or exec access — route network calls through ctx.fetch and keep filesystem/exec code auditable.

Directory structure

Tools are discovered recursively. Subdirectory names become namespace prefixes:

tools/
  hello.py          -> tool "hello"
  math/
    add.py          -> tool "math_add"

Configuration

Optional zeromcp.config.json in the working directory. See the root README for the full schema.

Testing

python3 -m pytest

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

antidrift_zeromcp-0.3.0.tar.gz (25.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

antidrift_zeromcp-0.3.0-py3-none-any.whl (19.7 kB view details)

Uploaded Python 3

File details

Details for the file antidrift_zeromcp-0.3.0.tar.gz.

File metadata

  • Download URL: antidrift_zeromcp-0.3.0.tar.gz
  • Upload date:
  • Size: 25.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for antidrift_zeromcp-0.3.0.tar.gz
Algorithm Hash digest
SHA256 510bc88a828773a29a20e6e6940b01ab9517e49c1f1909eca9c8255a5d776d43
MD5 7e4639b6a63057fff20094dea74dd047
BLAKE2b-256 832980f2d4a4c87a928daf76b6575ac4df589d8fed1165cc8a48762ac0bc6429

See more details on using hashes here.

Provenance

The following attestation bundles were made for antidrift_zeromcp-0.3.0.tar.gz:

Publisher: publish-python.yml on antidrift-dev/zeromcp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file antidrift_zeromcp-0.3.0-py3-none-any.whl.

File metadata

File hashes

Hashes for antidrift_zeromcp-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 721fb28d35a916e70449a81a4e6ebcd3cc3103390100222dbffa466ebcf69d5d
MD5 71ac9cbb12d65073caba1c16a2862d06
BLAKE2b-256 b5355a811818cd4f6cd8cc44d88f8a0d9aef63abc54d5dd0473dd5e4fe892d84

See more details on using hashes here.

Provenance

The following attestation bundles were made for antidrift_zeromcp-0.3.0-py3-none-any.whl:

Publisher: publish-python.yml on antidrift-dev/zeromcp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.3.0 This release

2 files

0.2.2

2 files

0.2.0

2 files

0.1.1

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page