Skip to main content

MCP Gateway

A generic, subclassable Model Context Protocol gateway whose tools are registered and executed asynchronously by connected providers over WebSocket.

MCP Client ⇄ Streamable HTTP ⇄ Gateway ⇄ WebSocket ⇄ Provider

CI PyPI Python: 3.12, 3.13, 3.14 License: MIT


The gateway never knows the capabilities ahead of time. A provider — typically a browser app — connects, publishes its own MCP tools, resources, prompts and more, and executes them when an MCP client calls them. The gateway only registers, publishes and routes, staying completely domain agnostic.

It is a small, installable library. You build a real application by subclassing Gateway and overriding hooks. The handlers themselves are written in JavaScript. This library never prescribes a specific frontend — the Provider SDK guide teaches the JS side generically.

📦 Install

pip install mcp-gtw
# or
uv add mcp-gtw

🚀 The smallest gateway

from mcpgtw.gateway import Gateway

app = Gateway().create_app()
uv run python -m mcpgtw.main

This publishes a real MCP endpoint at /mcp, a private provider WebSocket at /provider and a health check at /health. It exposes whatever capabilities the connected provider registers.

☁️ One-click deploy

The image runs production-ready as a non-root process. Deploy it to any host that keeps a persistent server (the /provider WebSocket needs one — serverless like Vercel does not work):

Deploy to Render

Render, Railway and Fly.io run the Dockerfile as-is (they inject PORT, which the gateway reads); on a VPS (Hostinger, …) use Docker Compose. Full guide, including reverse proxy and TLS: deployment.

🧩 Extending it

Subclass Gateway and override the hooks to attach your own domain logic:

from mcpgtw.channel import Channel
from mcpgtw.gateway import Gateway


class MyGateway(Gateway):
    mcp_server_name = "my-app"

    async def on_provider_connected(
        self, channel: Channel
    ) -> None: ...  # a provider session just came online

    def register_routes(self, app) -> None:
        super().register_routes(app)
        ...  # add your own HTTP and WebSocket routes


app = MyGateway().create_app()

Every behaviour is a swappable strategy with a secure default — authentication, tokens, origins, expiry and the wire codec. Change one by setting a *_class attribute or injecting an instance, without touching the transport. See the Gateway library guide for every override point, Extensibility for the strategy contracts, and Auth recipes for token, username/password and client-supplied-token models.

📚 Documentation

Guide What it covers
Architecture Components, transports and request flows.
Quick start Install, run and connect an MCP client.
Gateway library The Gateway class and every override point.
Extensibility The swappable strategies, their contracts and the invariants.
Auth recipes Token, username/password and client-supplied-token models.
Configuration Every setting and environment variable.
Provider protocol The private gateway ⇄ provider message protocol.
Provider SDK Writing the JavaScript provider and registering tools.
Browser console Turn any open page into a provider from DevTools.
MCP clients Connecting Claude Code, generic clients and the Inspector.
Admin dashboard The optional monitoring dashboard and its stats API.
Security The security model, tokens, origins and hardening.
Testing Running the suite and the 100% coverage gate.
Deployment Docker, reverse proxies and scaling.

🗂️ Layout

.
├── src/mcpgtw/     # the library
├── tests/               # unit and integration tests (100% coverage)
└── docs/                # the guides linked above

✅ Requirements

  • Python 3.12+ — tested on 3.12, 3.13 and 3.14 in CI (3.12 is the pinned local version; Docker uses 3.14)
  • Any MCP client (Claude Code, Cursor, the MCP Inspector, …)

💜 Support

If this project saved you time, consider supporting it: GitHub Sponsors · Ko-fi.

Made with care by Paulo Coutinho.

Licensed under MIT.

OAuth client authorization

Public MCP OAuth is opt-in and requires explicit channel grants. Provider WebSocket credentials remain separate. See OAuth configuration, extension contracts, transport gates and deployment limits. Embedded OAuth requires an injected durable authorization server; the demo game supplies local account login and consent, including client-initiated authorization before browser login.

Embedded consent permits the validated client callback through its form security policy, including cross-origin clients. Real-browser approval, denial and tampered-destination tests run in CI and before publication. See browser verification.

MCP clients start authorization from the MCP endpoint through discovery. Embedded login and consent use responsive pages with compact field hints and expandable connection details.

Embedded login and consent allow ten minutes by default, independently of the short-lived authorization code. Account creation is only offered when the identity strategy enables it.

The detailed OAuth acceptance checklist tracks protocol, security, game, SDK, host and upgrade evidence. Local verification and external host checks are reported separately. The OAuth strategy contracts describe the final extension API, including read-only consent validation and scope-bearing grants.

Metadata

Release files for mcp-gtw 0.0.11

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for mcp-gtw 0.0.11
File Size Uploaded
mcp_gtw-0.0.11.tar.gz 517.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for mcp-gtw 0.0.11
File Interpreter ABI Platform
mcp_gtw-0.0.11-py3-none-any.whl Python 3 none any Details

Total release size: 638.9 kB

Release files / mcp_gtw-0.0.11.tar.gz

Download URL mcp_gtw-0.0.11.tar.gz
Size 517.2 kB
Tags Source
SHA-256 checksum
How to use checksums
1b88da886cd5705f0c47496ee0f92a71951295349b5c6c2d962859430ddd9230
BLAKE2b-256 checksum
How to use checksums
9d241e15d3a77dcce9dfff2471bea113295298eb1e8fbe544fbb1d71f6a88d34
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.0 {"installer":{"name":"uv","version":"0.13.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / mcp_gtw-0.0.11-py3-none-any.whl

Download URL mcp_gtw-0.0.11-py3-none-any.whl
Size 121.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
40842ecfb377dd8a43ca0ead034d37f1de1752f36ee9b502ee850d5e7ad3421d
BLAKE2b-256 checksum
How to use checksums
b1c105611e989cf29fc2c3555d437760cc6ae4e3ce34198ebadefb649da932a0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.0 {"installer":{"name":"uv","version":"0.13.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

0.0.12

2 release files

This release

0.0.11 This release

2 release files

0.0.10

2 release files

0.0.9

2 release files

0.0.8

2 release files

0.0.7

2 release files

0.0.6

2 release files

0.0.5

2 release files

0.0.4

2 release files

0.0.3

2 release files

0.0.2

2 release files

0.0.1

2 release 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