Skip to main content
Glama
README.md
# MCP Gateway

[![CI](https://github.com/KaryawanSurga/mcp-gateway/actions/workflows/ci.yml/badge.svg)](https://github.com/KaryawanSurga/mcp-gateway/actions/workflows/ci.yml)
[![Node](https://img.shields.io/badge/node-%3E%3D20-339933)](package.json)
[![License: MIT](https://img.shields.io/badge/license-MIT-green)](LICENSE)

**One local MCP endpoint for all your MCP servers.**

MCP Gateway sits between your MCP clients and your MCP servers. Configure it once, point every client at it, and manage everything in one place: namespaced tools, profiles, policy, context budgets, audit logs, and a local dashboard — over stdio or Streamable HTTP.

```text
Claude / Cursor / opencode / any MCP client
                  │ stdio or HTTP
                  ▼
          ┌───────────────────────────┐
          │        MCP Gateway        │  namespacing · profiles · policy
          │                           │  budget · audit · dashboard
          └─────────────┬─────────────┘
      ┌───────────┬─────┴─────┬───────────┐
      ▼           ▼           ▼           ▼
 filesystem    github     tokensaver   … more servers
```

## Why

Every MCP client keeps its own copy of every server configuration. Five clients times eight servers is forty places to update a token, a path, or a flag. And as servers accumulate, so do questions: which server exposes which tool, which ones are down, which tools may run, and what is eating the context window. The gateway answers all of it once.

## Features

- **Aggregation** — any number of stdio MCP servers behind one endpoint.
- **Namespacing** — stable `server__tool` names; no collisions, clear origin.
- **Profiles** — different server sets for different contexts (`work`, `docs`, `personal`).
- **Policy** — allow/deny rules with glob patterns, plus a read-only mode that blocks mutating tools.
- **Budgets** — token cost of aggregated tool schemas, ranked per server and per tool.
- **Audit** — JSONL log of every tool call with duration and outcome; `stats` summaries.
- **Health** — per-server timeouts; broken servers never block startup; `gateway_status` and `gateway_policy` tools.
- **Transports** — MCP over stdio, or Streamable HTTP with a local dashboard.

## Quick start

```sh
npx -y mcp-gateway init
npx -y mcp-gateway add filesystem -- npx -y @modelcontextprotocol/server-filesystem .
npx -y mcp-gateway add tokensaver -- npx -y tokensaver-mcp
npx -y mcp-gateway list
```

Point clients at the gateway:

```json
{
  "mcpServers": {
    "gateway": {
      "command": "npx",
      "args": ["-y", "mcp-gateway", "serve"]
    }
  }
}
```

HTTP mode with the dashboard:

```sh
npx -y mcp-gateway serve --http --port 8787
# MCP endpoint: http://127.0.0.1:8787/mcp
# Dashboard:    http://127.0.0.1:8787/
```

## Configuration

`mcp-gateway.json`:

```json
{
  "servers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "."]
    },
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": { "GITHUB_TOKEN": "..." }
    }
  },
  "profiles": {
    "default": { "servers": ["filesystem", "github"] },
    "docs": {
      "servers": ["filesystem"],
      "policy": { "readOnly": true }
    }
  },
  "activeProfile": "default",
  "policy": {
    "defaultAction": "allow",
    "readOnly": false,
    "rules": [
      { "server": "github", "tool": "delete_*", "action": "deny" },
      { "server": "github", "tool": "get_*", "action": "allow" }
    ]
  },
  "audit": { "enabled": true, "path": "mcp-gateway.audit.jsonl" }
}
```

Policy rules use glob patterns (`*`, `?`), first match wins, and read-only mode blocks tools whose names look mutating (`write_*`, `create_*`, `delete_*`, `run_*`, …). Profiles can override the global policy.

## CLI reference

| Command | Purpose |
| --- | --- |
| `init [--force]` | Write a starter config. |
| `add <name> -- <command> [args...]` | Add an upstream stdio server to a profile. |
| `remove <name>` | Remove a server everywhere. |
| `list [--json]` | Show servers, profiles, policy, and audit settings. |
| `budget [--json]` | Token cost of aggregated tool schemas (connects to upstreams). |
| `stats [--json]` | Summarize the audit log. |
| `logs [--tail <n>] [--json]` | Recent audit entries. |
| `serve [--http] [--port <n>] [--host <h>]` | Run the gateway (stdio by default). |

Global options: `--config <path>`, `--profile <name>`, `--audit`, `--audit-path <p>`, `--json`, `--force`.

Exit codes: `0` success, `1` config or runtime failure, `2` usage error.

## MCP tools exposed by the gateway

| Tool | Purpose |
| --- | --- |
| `server__tool` | Every allowed upstream tool, namespaced. |
| `gateway_status` | Upstream health, tool counts, policy summary, schema cost. |
| `gateway_policy` | Active policy: mode, rules, and blocked tools with reasons. |
| `gateway_budget` | Token cost of tool schemas ranked per server and tool. |

## Design principles

- **Local-first**: no network service, no telemetry; everything runs on your machine.
- **Transparent**: tool names show origin; blocked calls explain which rule denied them.
- **Bounded**: per-server timeouts, bounded startup, token estimates instead of tokenizers.
- **Safe by default**: audit disabled unless enabled; read-only mode available per profile.
- **Composable**: works with any stdio MCP server, including the TokenSaver family.

## Development

```sh
npm install
npm run typecheck
npm run build
npm test
```

The suite covers config parsing, upstream lifecycle, policy decisions, namespacing, budgets, audit logs, CLI flows, end-to-end stdio routing, and MCP over Streamable HTTP with a live dashboard API.

## License

MIT — see [LICENSE](LICENSE).