Skip to main content
Glama
Aiven-Labs

runtime-proxy-mcp

Official
by Aiven-Labs
README.md
# proxy-mcp-runtime

A two-container runtime: a [FastMCP](https://gofastmcp.com) application server,
and a reverse proxy sitting in front of it that enforces bearer-token auth
before traffic reaches the MCP server.

## Layout

```
mcp-app/         FastMCP server (Streamable HTTP transport, port 8000, internal-only)
proxy/           Caddy reverse proxy (bearer-token auth, port 8080, exposed)
docker-compose.yml
```

- **mcp-app** — a single-file `server.py` using [PEP 723 inline script
  metadata](https://peps.python.org/pep-0723/), run with `uv run server.py`.
  It's not published to the host network; only `proxy` can reach it, over
  the `mcp-net` compose network.
- **proxy** — Caddy checks the `Authorization: Bearer <token>` header against
  `MCP_PROXY_TOKEN` and rejects anything else with 401 before reverse-proxying
  to `mcp-app:8000`.

## Running it

```sh
cp .env.example .env
# edit .env and set MCP_PROXY_TOKEN to a real value, e.g.:
#   openssl rand -hex 32
docker compose up --build
```

The MCP endpoint is then available at `http://localhost:8080/mcp`, and requires:

```
Authorization: Bearer <MCP_PROXY_TOKEN>
```

Any request without a matching header gets a 401 from the proxy without ever
reaching the FastMCP app.

## Local dev without Docker

```sh
cd mcp-app
uv run server.py
```

This runs the FastMCP server directly (no proxy/auth) on `http://localhost:8000/mcp`.

## Notes

- The two example tools (`ping`, `echo`) are placeholders — replace them with
  real tools in `mcp-app/server.py`.
- `MCP_PROXY_TOKEN` is a shared secret for this local/dev setup. For anything
  beyond local dev, manage it with fnox and swap the Caddy static-token check
  for something stronger (OAuth, per-client tokens, etc.) before exposing it
  outside a trusted network.
- Lint with `ruff check .` from the repo root (config in `pyproject.toml`).

Maintenance

ActivityMaintained
ResponsivenessNo issues