Skip to main content

Scaffold a production-ready remote MCP (Model Context Protocol) server with OAuth, RFC 8414/9728 discovery, retry, telemetry, and tests — in one command. Zero runtime dependency on this package.

Project description

remote-mcp

One command to a production-ready remote MCP server.

PyPI Python CI License: MIT


Building a remote MCP (Model Context Protocol) server means solving the same hard problems every time: OAuth pass-through, RFC 8414/9728 discovery endpoints, middleware stack, telemetry, retry logic, Docker packaging, and a test suite that passes on day one.

remote-mcp scaffolds all of it. Generated projects have zero runtime dependency on this package — every file is yours to read, audit, and modify.

Install

pipx install remote-mcp   # recommended
# or
pip install remote-mcp

Usage

Interactive:

remote-mcp new my-project

Non-interactive (CI / scripts):

remote-mcp new my-project --yes --service-name "My Project" --into ./apps/my-project
  FastMCP Remote Server Generator

  Scaffolding my-project into my-project...
  ✓ Scaffold complete

  Done! Next steps:
    cd my-project
    python -m venv venv && source venv/bin/activate
    pip install -e ".[dev]"
    cp env.example .env
    uvicorn asgi:application --reload --port 8001 --lifespan on

Server is live at http://localhost:8001. MCP endpoint: http://localhost:8001/sse.

Also works as a module:

python -m remote_mcp new my-project

Commands

Command What it does
remote-mcp new <name> Scaffold a new project
remote-mcp add tool <name> Add a tool stub to an existing scaffolded project
remote-mcp --version Print version

new flags:

Flag Purpose
--yes / -y Skip prompts; use defaults / provided flags
--service-name / -s "Foo Bar" Human-readable service name
--into PATH Target directory (default ./<name>)

add tool flags:

Flag Purpose
--project-dir / -p PATH Target project (default .)

What you get

my-project/
├── src/
│   ├── server.py              # FastMCP("My Project") instance + tool mounts
│   ├── app.py                 # Starlette factory — routes, middleware, ASGI wiring
│   ├── config/settings.py     # Pydantic BaseSettings (lazy get_settings())
│   ├── core/
│   │   ├── auth.py            # extract_bearer_token() — OAuth pass-through
│   │   ├── errors.py          # MyProjectError hierarchy
│   │   ├── http_client.py     # api_get/post/patch/put/delete/upload + tenacity retry
│   │   ├── telemetry.py       # JSONL event log, HMAC-salted user-id hashing
│   │   ├── handlers.py        # @tool_handler decorator, get_client_and_token()
│   │   └── app_state.py       # lifespan: shared httpx.AsyncClient pool
│   ├── middleware/
│   │   ├── auth.py            # RequireAuthMiddleware — Bearer enforcement + probe
│   │   └── telemetry.py       # TelemetryMiddleware — auth failures, connections
│   ├── views/
│   │   ├── health.py          # GET /health
│   │   ├── oauth.py           # RFC 8414 + RFC 9728 discovery endpoints
│   │   └── root.py            # landing page at /
│   └── tools/example.py       # echo tool — your first tool, ready to replace
├── tests/
│   ├── test_auth.py           # extract_bearer_token edge cases
│   ├── test_middleware.py     # auth bypass, 401 on missing token
│   └── test_telemetry.py      # hash_token stability, record_event never raises
├── templates/index.html       # landing page served at /
├── Dockerfile                 # multi-stage, non-root, healthcheck
├── docker-compose.yml         # local dev parity
├── render.yaml                # Render Blueprint — one-click deploy
├── fly.toml                   # Fly.io app config
├── mcp.json                   # MCP Inspector preset
├── .dockerignore
├── .gitignore
├── asgi.py                    # production ASGI entrypoint
├── env.example                # all env vars with safe defaults
├── pyproject.toml             # hatchling build, ruff lint
├── README.md
└── DEPLOYMENT.md              # Render / Railway / Fly.io / Docker deploy guide

Included infrastructure

Module What it provides
core/auth.py extract_bearer_token(ctx) — forward Bearer token verbatim to your backend
core/http_client.py api_get, api_post, api_patch, api_put, api_delete, api_upload — pooled httpx client with tenacity retry
core/errors.py MyProjectError + Auth, Forbidden, Validation, Backend, RateLimit subclasses
core/telemetry.py Rotating JSONL log, user IDs hashed via HMAC-SHA256 (TELEMETRY_HASH_SALT)
core/handlers.py @tool_handler — catches errors, formats responses, records telemetry
middleware/auth.py CORS → Auth → optional backend token probe on SSE connect (reuses pooled client)
middleware/telemetry.py Connection-level events (auth failures, rate limits, SSE connects)
views/ Health, OAuth discovery (RFC 8414 + 9728), landing page — each in its own file
Dockerfile Multi-stage build, non-root app user, healthcheck, WORKERS env

Nothing is forced on you. Delete what you don't need.

Adding a tool

Quickest path:

remote-mcp add tool search

Then mount it in src/server.py:

from src.tools.search import search_router
mcp.mount(search_router)

Or write one by hand:

# src/tools/my_tool.py
from fastmcp import Context, FastMCP
from src.core.handlers import get_client_and_token, tool_handler

my_router = FastMCP("my-tool")

@my_router.tool()
@tool_handler
async def my_tool(param: str, ctx: Context) -> str:
    client, auth_header = await get_client_and_token(ctx)
    response = await client.get("/some/endpoint", headers={"Authorization": auth_header})
    return response.json()

Connecting to Claude

Claude.ai (web): Settings → Connectors → Add → Custom → Web

  • URL: https://your-server.example.com/mcp/sse

Claude Desktop (~/Library/Application Support/Claude/claude_desktop_config.json):

{
  "mcpServers": {
    "my-project": {
      "command": "npx",
      "args": ["-y", "mcp-remote@latest", "https://your-server.example.com/mcp/sse"]
    }
  }
}

Claude Code:

claude mcp add my-project --transport http https://your-server.example.com/mcp/sse

Local debugging with MCP Inspector

The scaffold ships an mcp.json preset:

npx @modelcontextprotocol/inspector --config ./mcp.json

Set a Bearer token in the Inspector UI to exercise authenticated tools without standing up a full OAuth flow.

Deployment

Docker / Compose

docker build -t my-project .
docker run --rm -p 8001:8001 --env-file .env my-project
# or
docker compose up --build

One-click platforms

The generated project ships pre-filled config:

  • Renderrender.yaml Blueprint; click the Deploy to Render button in your repo README.
  • Fly.iofly.toml; run fly launch --copy-config && fly deploy.
  • Railway — Dockerfile-based; point Railway at the repo.

DEPLOYMENT.md in the generated project covers env vars, workers, healthcheck, and hardening notes.

Configuration

Copy env.example to .env and edit. Key variables:

Variable Default Description
API_BASE_URL https://api.example.com Your upstream API
MCP_PUBLIC_URL http://localhost:8001/mcp Public MCP URL (shown in landing page)
OAUTH_ISSUER_URL http://localhost:8001 OAuth issuer for RFC 8414 discovery
OAUTH_AUTHORIZE_PATH /o/authorize/ OAuth authorize endpoint (relative or full URL)
OAUTH_TOKEN_PATH /o/token/ OAuth token endpoint
OAUTH_REGISTRATION_PATH /o/register/ Dynamic client registration endpoint
OAUTH_SCOPES_SUPPORTED read Comma-separated scope list
AUTH_PROBE_ENABLED false Validate token against backend on SSE connect
AUTH_PROBE_PATH /health/ Endpoint used for token probe
LOGO_URI `` Logo shown in OAuth discovery (optional)
ALLOWED_ORIGINS https://claude.ai,... CORS origins
TELEMETRY_ENABLED true Enable JSONL telemetry
TELEMETRY_HASH_SALT `` HMAC salt for user-id hashing (set per-deployment)
SUPPORT_EMAIL `` Shown as Get Help mailto link on the landing page; hidden when unset

Full variable list and deploy instructions in DEPLOYMENT.md.

How it works

remote-mcp renders Jinja2 templates into your project directory at scaffold time. After that, it's gone — no version pinning, no update command, no hidden runtime. You own every line.

Requirements

  • Python ≥ 3.10 (this CLI). Generated project supports the same range.
  • FastMCP ≥ 3.0 (installed in the generated project, not this package).

Contributing

See CONTRIBUTING.md. Security reports: SECURITY.md.

Changelog

See CHANGELOG.md.

License

MIT — see LICENSE.

Project details


Download files

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

Source Distribution

remote_mcp-0.2.1.tar.gz (33.2 kB view details)

Uploaded Source

Built Distribution

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

remote_mcp-0.2.1-py3-none-any.whl (43.6 kB view details)

Uploaded Python 3

File details

Details for the file remote_mcp-0.2.1.tar.gz.

File metadata

  • Download URL: remote_mcp-0.2.1.tar.gz
  • Upload date:
  • Size: 33.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for remote_mcp-0.2.1.tar.gz
Algorithm Hash digest
SHA256 4a9f1699963fbe88901ddb26f7ee1c413988b599d28609015c2284317a548d60
MD5 a0933dc8cbc668fc83429b051fd695ae
BLAKE2b-256 43497a18d90482e4896af2263c0a1d47b120029ddb165ad84cc47b25bdd1b001

See more details on using hashes here.

Provenance

The following attestation bundles were made for remote_mcp-0.2.1.tar.gz:

Publisher: publish.yml on pushpendra-tripathi/remote-mcp

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

File details

Details for the file remote_mcp-0.2.1-py3-none-any.whl.

File metadata

  • Download URL: remote_mcp-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 43.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for remote_mcp-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 39bbda80d103dc7b28368b58042868163c79adacb915161db3d135a583d52859
MD5 579a5111c14840ed638f08fd7bce09e2
BLAKE2b-256 96bff3cff4e4d3b26282393d13d3202f42ac7f47d514d0f8cdc0e3fdf286944d

See more details on using hashes here.

Provenance

The following attestation bundles were made for remote_mcp-0.2.1-py3-none-any.whl:

Publisher: publish.yml on pushpendra-tripathi/remote-mcp

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

Supported by

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