mcp-gtw

mcp-gtw

A generic Model Context Protocol gateway. It publishes a real MCP endpoint whose tools, resources and prompts are registered and run at runtime by providers over WebSocket.

MCP Client ⇄ Streamable HTTP ⇄ Gateway ⇄ WebSocket ⇄ Provider
pip install mcp-gtw npm i mcp-gtw-provider
mcp-gtw routing MCP capabilities from providers to clients over WebSocket

What it is

mcp-gtw is a generic, installable Model Context Protocol gateway. It publishes a real MCP endpoint over Streamable HTTP, but it never decides in advance what that endpoint can do. A connected provider — a browser app or any WebSocket client — registers its own tools, resources and prompts at runtime, and the gateway relays every call to it and streams the result back.

That inversion is the whole point: the capabilities live where your product already runs, so a web app can expose its own actions to any MCP client without shipping a separate server. You build a real application by subclassing the gateway, never by editing the package.

How it works

Two transports meet in the middle. MCP clients speak the standard Streamable HTTP protocol at /mcp. Providers open a private WebSocket at /provider and publish their capabilities over a small, versioned relay protocol.

Each session is a channel holding two independent tokens — one for the client, one for the provider — so neither side can act as the other. When a client calls a tool, the gateway validates the input against that channel's schema, forwards the request to the provider, applies a timeout, and streams the result back. The provider can even call back into the client for sampling and elicitation.

The full MCP surface

Every capability, not just tools

Tools

Callable actions with JSON-Schema-validated inputs and structured outputs.

Resources

Readable resources and RFC 6570 templates, served straight from the provider.

Prompts

Reusable prompt templates the client can list and fetch on demand.

Completion

Argument autocompletion for tools and prompts as the user types.

Logging

Structured log messages streamed to the client and filtered per level.

Progress

Live progress updates for long-running calls.

Sampling

Call back into the client's own LLM from inside a handler.

Elicitation

Ask the user for structured input in the middle of a flow.

Built for production

Boring where it counts

Subclassable library

You build a real app by subclassing the gateway and overriding hooks — never by editing the package. Swap the channel, registry or settings classes when you need to.

Fully async

Everything runs on a single event loop with no blocking IO on the request or WebSocket paths, so one process serves many channels at once.

Validated & bounded

Inputs are validated per channel against the registered schema, and every limit — payload size, tool count, JSON depth, pending calls — is enforced and checked at startup.

Secure by default

Two independent tokens per channel, constant-time comparisons, origin checks, and an optional admin dashboard gated by its own key.

100% branch coverage

A hard test gate across the gateway, the JavaScript provider and the demo — the whole surface is exercised, not sampled.

Open source, MIT

Three focused repositories, published to PyPI and npm, ready to install and extend.

Get started

Two sides, a few lines

The gateway — Python

pip install mcp-gtw

# app.py
from mcp_gtw.gateway import Gateway

app = Gateway().create_app()

The provider — JavaScript

import { McpGtwProvider } from "mcp-gtw-provider";

const provider = new McpGtwProvider({ url: PROVIDER_URL });
provider.registerTool({ name: "greet" }, () => "hello");
await provider.connect();

Open source

Three repositories

The gateway, a framework-agnostic browser provider, and a complete game that runs entirely on it.