Skip to main content

mcp-worker-sdk

Worker Protocol — Python runtime reference implementation. A universal MCP tool runtime SDK that turns plain Python functions into production-grade, AI-invocable tools.

Write a function, decorate it with @worker.tool, and automatically get schema generation, parameter validation, standardized errors, real bounded concurrency, queue backpressure, and rich runtime observability — with zero boilerplate endpoints.

mcp-worker-sdk is the Python binding of the language-agnostic Worker Protocol. It is Hub-agnostic: omit hub_url and run it standalone as a standard HTTP tool service that any aggregator (Hub / MCP gateway) can consume.


✨ Features

  • @worker.tool decorator — declare tools as plain functions; the SDK derives the JSON Schema from type hints + docstrings.
  • 6 adapters — Shell, DB (7 built-in drivers), Mac GUI, HTTP, MCP client, Custom.
  • Zero-boilerplate endpoints/health, /tools, /execute, /meta auto-assembled via FastAPI.
  • Real concurrency & backpressure — shared bounded executor (max_concurrency) + bounded queue (max_queue_length); a full queue replies 429 + Retry-After.
  • Rich runtime observability — three-tier /health (status / queue / performance) + health_metrics() returning the protocol HealthMetrics object.
  • Lifecycle hookson_start / on_health / on_stop / on_error.
  • HITL-ready — dangerous operations are kept out of /tools and exposed only as human REST endpoints.
  • Standardized errors — eight protocol error codes with HTTP mapping.

Installation

pip install mcp-worker-sdk

With all built-in database drivers:

pip install "mcp-worker-sdk[db]"

With resource metrics (psutil, for CPU/memory in /health):

pip install "mcp-worker-sdk[metrics]"

Import name uses an underscore: mcp_worker_sdk.


Quick start

# main.py
from mcp_worker_sdk import Worker
from mcp_worker_sdk.adapters import DBAdapter

worker = Worker(
    name="notes",
    adapter=DBAdapter("sqlite", ":memory:"),   # zero-config built-in driver
    # hub_url="https://hub.example.com",        # optional; omit to run standalone
    max_concurrency=10,
    max_queue_length=20,
)


@worker.tool(
    id="notes_search",
    title="Search notes",
    description="Search the notes library by keyword",
    tags=["notes", "search"],
)
def search(keyword: str, limit: int = 10):
    """Search the notes library.

    :param keyword: search keyword
    :param limit: max results to return
    """
    return {"keyword": keyword, "limit": limit}


if __name__ == "__main__":
    worker.run(port=9100)

Verify the auto-generated endpoints:

curl http://localhost:9100/health
curl http://localhost:9100/tools
curl -X POST http://localhost:9100/execute \
  -H "Content-Type: application/json" \
  -d '{"tool_id":"notes_search","params":{"keyword":"mcp"}}'

Project structure

Start small with a single file, then split per-domain as the tool count grows:

my-worker/
├── main.py            # entrypoint: register tools + worker.run()
├── worker.py          # Worker singleton (shared by all tool modules)
├── lifecycle.py       # on_start / on_health / on_stop / on_error
├── config.py          # env / config
└── tools/
    ├── __init__.py    # register_all()
    ├── notes.py       # one domain per file
    └── system.py

Since @worker.tool registers at import time, main.py just imports tools.register_all() once. See docs/mcp-worker-sdk/DELIVERY_INTEGRATION.md for the full two-tier layout (single-file vs decoupled).


Adapters

Adapter Purpose
ShellAdapter Command-line / sandbox / code execution
DBAdapter Relational / vector / graph / KV / document databases
MacAdapter macOS GUI / AppleScript / screenshots / mouse & keyboard
HTTPAdapter Cloud API forwarding (auth, signing hooks, pagination, JSONPath, SSE)
MCPClientAdapter Wrap a third-party MCP server
CustomAdapter Fully custom execution

Hardware workers? MacAdapter drives macOS GUI / AppleScript / screenshots; ShellAdapter wraps hardware CLIs (nvidia-smi, sensors, df, kubectl). See the integration guide for real examples.

DBAdapter built-in drivers

db_type Driver Capability
postgresql psycopg SQL query / connection pool
mysql pymysql SQL query / connection pool
sqlite sqlite3 lightweight SQL (stdlib)
qdrant qdrant-client vector search
neo4j neo4j graph query (Cypher)
redis redis key/value
mongodb pymongo document query

Lifecycle hooks

@worker.on_start
def on_start():
    connect_db()

@worker.on_health
def on_health():
    return {"db_connected": True}   # merged into /health["custom"]

@worker.on_error
def on_error(exc: Exception):
    logger.error("tool failed", exc_info=exc)

@worker.on_stop
def on_stop():
    disconnect_db()

Runtime observability

GET /health returns a rich three-tier payload instead of a bare alive flag:

{
  "status": "busy",
  "degraded_reason": "none",
  "active_tasks": 2,
  "queue_length": 5,
  "max_concurrency": 10,
  "max_queue_length": 20,
  "avg_task_duration_ms": 150,
  "p95_duration_ms": 420,
  "estimated_wait_ms": 250,
  "success_rate": 0.998,
  "cpu_percent": 40.0,
  "memory_percent": 61.2,
  "uptime_seconds": 3600,
  "version": "1.1.0",
  "custom": {"db_connected": true}
}
  • statusonline / busy / degraded (offline / crashed are derived by the Host Agent / Hub).
  • When the queue is full, /execute replies 429 RATE_LIMITED + Retry-After.
  • worker.health_metrics() returns a mcp_worker_protocol.HealthMetrics object (5 base + 6 rich fields) for zero-transformation heartbeat aggregation.

Error codes

Code HTTP Meaning
INVALID_PARAMS 422 Invalid parameters
NOT_FOUND 404 Tool or resource not found
TIMEOUT 504 Execution timeout
PERMISSION_DENIED 403 Not authorized
WORKER_OFFLINE 503 Worker offline
WORKER_ERROR 502 Worker internal error
INTERNAL_ERROR 500 Internal error
RATE_LIMITED 429 Queue full / rate limited

HITL (Human-in-the-loop)

Dangerous operations are never registered as MCP tools. Mount them as plain REST endpoints instead:

from mcp_worker_sdk.server import create_app

app = create_app(worker)   # auto-assembles /health /tools /execute /meta

@app.post("/hitl/merge-pr")
def merge_pr(owner: str, repo: str, index: int):
    """Human-only endpoint; never appears in /tools."""
    return gitea.merge(owner, repo, index)

For "same code, two permission surfaces" (e.g. merge visible to business but not auditors), register the tool conditionally via an environment variable — no SDK changes needed.


CLI scaffold

mcp-worker create my-worker              # default HTTPAdapter
mcp-worker create my-worker --adapter db

Documentation

  • Full integration guide (real code + best practices): docs/mcp-worker-sdk/DELIVERY_INTEGRATION.md
  • Authoritative spec: docs/mcp-worker-sdk/V1/01-SPEC.md
  • Cross-version shared contract: docs/mcp-worker-sdk/shared/00-TERMINOLOGY.md
  • Language-agnostic Worker Protocol: docs/worker-protocol/

Compatibility

  • Python 3.10+
  • Runtime dependencies: mcp-worker-protocol>=1.1.0, fastapi, uvicorn, httpx
  • Optional: [db] (database drivers), [metrics] (psutil)

License

Apache License 2.0

Download files

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

Source Distribution

mcp_worker_sdk-1.2.0.tar.gz (242.1 kB view details)

Uploaded Source

Built Distribution

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

mcp_worker_sdk-1.2.0-py3-none-any.whl (28.6 kB view details)

Uploaded Python 3

File details

Details for the file mcp_worker_sdk-1.2.0.tar.gz.

File metadata

  • Download URL: mcp_worker_sdk-1.2.0.tar.gz
  • Upload date:
  • Size: 242.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.14.6

File hashes

Hashes for mcp_worker_sdk-1.2.0.tar.gz
Algorithm Hash digest
SHA256 f85f18044c3c3deb237d612ffd408b9a76d5e01f083213d3837a3510e2478a1d
MD5 fe801b5431d35079d2697e83a987e73f
BLAKE2b-256 ad6521077ac1d3b26959f777efd4fd38253151ec7c69053059bfc8fcbe69ebfc

See more details on using hashes here.

File details

Details for the file mcp_worker_sdk-1.2.0-py3-none-any.whl.

File metadata

  • Download URL: mcp_worker_sdk-1.2.0-py3-none-any.whl
  • Upload date:
  • Size: 28.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.14.6

File hashes

Hashes for mcp_worker_sdk-1.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 526e4336ee879dfe95f55c079e51b8be0a381e46482fbf3a125ef506472f56b7
MD5 6ec987873391c2d8fbe406c970d6becc
BLAKE2b-256 da50113d4b7e191f832aa8f8324d667b6b8b9398e634e1cd174135b4b06a538e

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

1.2.0 This release

2 files

1.1.0

2 files

1.0.0

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page