Skip to main content
Glama
faizzansiddiq

AetherServe

AetherServe

An operations layer for Model Context Protocol (MCP) servers.

License: MIT Python Tests

AetherServe wraps an MCP server built with the official Model Context Protocol Python SDK and adds the operational concerns that matter once that server leaves a notebook and goes into a real deployment: metrics, health checks, rate limiting, structured logging, and lifecycle hooks.

It is a small, dependency-light middleware layer, not a fork of the protocol or the SDK. You keep writing tools the normal way; AetherServe observes and governs the calls around them.


Why

The MCP SDK gives you the protocol. It does not give you an answer to questions every production deployment eventually asks:

  • Which tools are slow, and how slow, at the p50/p95/p99?

  • Is this server healthy enough to keep receiving traffic?

  • What stops one client from calling an expensive tool 500 times a second?

  • How do I correlate a log line with the tool call that produced it?

  • How do I run code exactly once at startup and exactly once at shutdown?

AetherServe answers all five with a small, composable API, without asking you to adopt a heavier framework or change how you write MCP tools.

Related MCP server: mcp-helmet

Installation

pip install aetherserve

This pulls in the mcp package as its only required runtime dependency.

For the bundled examples (which use Starlette/Uvicorn to expose HTTP health and metrics endpoints):

pip install "aetherserve[examples]"

Quickstart

from mcp.server.fastmcp import FastMCP
from aetherserve import AetherServer, AetherServeConfig

raw_server = FastMCP("weather-server")
server = AetherServer(raw_server, AetherServeConfig(service_name="weather-server"))

@server.tool()
def get_forecast(city: str) -> str:
    return f"Sunny in {city}"

if __name__ == "__main__":
    server.run()

Every call to get_forecast is now timed, counted, rate-limited against the server's default policy, wrapped in a trace span, and logged with a correlation id — without a single line of that logic living in get_forecast itself.

Core Concepts

Concern

Module

What you get

Metrics

aetherserve.observability.metrics

Counters, gauges, histograms; Prometheus text exposition

Logging

aetherserve.observability.logging_setup

JSON or text logs, automatic request-id correlation

Tracing

aetherserve.observability.tracing

Lightweight nested spans, pluggable exporter

Health

aetherserve.health

Named checks, critical vs. degraded aggregation, HTTP-status mapping

Rate limiting

aetherserve.ratelimit

Token-bucket limiter, global or per-client scope, per-tool overrides

Lifecycle

aetherserve.hooks.lifecycle

startup / shutdown / before_tool_call / after_tool_call / tool_call_error events

See ARCHITECTURE.md for how these pieces fit together around the AetherServer wrapper, and docs/ for a deeper dive into each subsystem.

Per-tool rate limits

from aetherserve.ratelimit.policies import RateLimitScope

server.set_rate_limit(
    "generate_image",
    capacity=2,
    refill_rate=0.1,          # ~1 token every 10 seconds
    scope=RateLimitScope.PER_CLIENT,
)

@server.tool(client_key=lambda client_id, prompt: client_id)
def generate_image(client_id: str, prompt: str) -> str:
    ...

Health checks

def database_ping() -> None:
    connection.execute("SELECT 1")  # raises on failure

server.add_health_check("database", database_ping, critical=True)

server.health.run_all() aggregates every registered check into a single healthy / degraded / unhealthy report; aetherserve.health.endpoint.health_response maps that straight into an HTTP status code your framework of choice can return.

Examples

Development

git clone https://github.com/faizansiddiq/aetherserve.git
cd aetherserve
pip install -e ".[dev]"
pytest
mypy src/aetherserve
ruff check .

See CONTRIBUTING.md for the full workflow and docs/testing.md for how the test suite is structured (including the in-repo fake MCP server used so unit tests don't require a live protocol connection).

Relationship to the MCP SDK

AetherServe is not a fork, rebrand, or replacement of the official Model Context Protocol Python SDK. It is an independent project that takes an mcp.server.fastmcp.FastMCP instance as a constructor argument and wraps it, in the same sense that a WSGI middleware wraps a WSGI app. Full attribution for the underlying SDK is in NOTICE.md.

License

MIT — see LICENSE. Copyright (c) 2026 Faizan Siddiq.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Production-ready MCP server starter with authentication, observability, and a plugin system for building and deploying MCP servers quickly.
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    A production middleware toolkit for MCP servers providing auth, health checks, graceful shutdown, and transport ergonomics, enabling rapid development of robust MCP servers.
    10 npm
    4
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    A production-ready, transport-independent foundation for building enterprise MCP servers in Python. Provides infrastructure, configuration, DI, logging, and tooling so downstream projects can focus on domain capabilities.
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Provides a reusable MCP server foundation with explicit tool registration, operation-mode separation, scope-based permissions, structured results, and built-in health/status tools.
    MIT