Features
Everything MCP REST Bridge does, grouped by what you're trying to accomplish. Each group links to the guide that covers it in depth.
Connect anything
- OpenAPI / Swagger → MCP auto-discovery. Point at a spec URL; each operation becomes an MCP tool. Filter with
include_tags/exclude_operations. - GraphQL → MCP auto-discovery. Point at a GraphQL endpoint; the bridge introspects the schema and generates one tool per query/mutation.
- cURL / Postman import. Derive tools from a pasted
curlcommand or a Postman Collection v2.1 export when there's no spec. - MCP → MCP gateway / aggregator. Register existing MCP servers (Streamable HTTP or SSE) as upstreams and re-expose their tools through the same pipeline.
- Manual tool definitions when a backend has no spec.
- Two data-plane serving modes — per-client
/mcp/:nameand curated bundles/mcp-custom/:bundle(which may also include composite macros)./mcpitself is the control plane (system management + data retrieval), not a third data-serving mode — see Architecture. - Tool aliases & display names to present clean, client-friendly tool names.
- Tool tags — free-form tags across every registered client, browsable and filterable by tag from the admin UI.
- Composite / macro tools that run several steps as one call, each step through the full guard stack. Not reachable by default — add a composite to a bundle's
composites[]to serve it at that bundle's/mcp-custom/:bundleendpoint. - System control plane (
/mcp) — an LLM client connects here (not to a backend shard) to manage the gateway itself: list/register/enable clients, mint or revoke MCP keys, tail the audit log, reset a circuit breaker, and more. Fail-closed auth (no "unconfigured means open" fallback) plus a per-tool role tier (read/operate/admin) and step-up confirmation for sensitive actions. See Architecture. - Gateway prompts on
/mcp— the control plane also serves its own MCP prompts (prompts/list), so a host can offer them as slash-commands and the user's own assistant walks them through onboarding a backend, diagnosing a failing tool, or hardening a client. They carry no capability of their own: every step is an ordinarysys_*call that still passes the same gates. See API reference. GET /llms.txt— a public, unauthenticated, machine-readable self-description so an agent handed nothing but this gateway's URL can work out what it is and how to connect. It describes the API's shape only and deliberately names no registered backend, tool or bundle. See API reference.- GraphQL & WebSocket backends (per-tool) — wrap a call's arguments as a GraphQL
{ query, variables }request, or do an ephemeral request/response over a WebSocket, reusing the same guard stack as REST. - Dedicated WebSocket proxy targets — register a persistent backend WS endpoint (with connection-count, message-size and idle-timeout limits), and force-disconnect every active connection to one in bulk.
- Upstream resources & prompts — a per-client
/mcp/:nameendpoint pointed at an MCP server now passes through its resources and prompts, not only its tools. - MCP tool annotations (2025-06-18) — every advertised tool carries the standard governance/presentation hints (
readOnlyHint,destructiveHint,idempotentHint,openWorldHint, and a displaytitle), derived from its HTTP method and its sensitivity/approval gating; an MCP upstream's own declaredtitleand annotations are passed through faithfully. These are advisory hints a client may use to present or pre-gate a tool — they complement, never replace, the gateway's call-time enforcement. - Bundle install links — a shareable, revocable one-click link that mints a bundle-scoped MCP API key and resolves to a ready-to-paste connection snippet, so end users never need a manually provisioned key.
Govern & secure
See Security →, Guardrails & resilience →, and Access control →.
Network & content safety
- SSRF + DNS-rebinding protection on every backend URL, with the resolved IP pinned so a later DNS change can't redirect traffic.
- Guardrails — input deny-rules, secret detection, and prompt-injection sanitizing that wraps untrusted responses in a safe envelope.
- Per-tool policy — rate limits, timeouts, circuit-breaker overrides, and allowed-API-key restrictions, enforced at dispatch time before the circuit breaker.
Access & identity
- RBAC with
admin/operator/auditor/viewerroles. - Team multi-tenancy — scope clients to teams so tenants only see their own.
- Session-based admin login (argon2id via
Bun.password) plus a static Bearer key path for CI/automation, with CSRF protection on cookie-authenticated mutations. - Inbound OAuth2 / JWT (optional) — accept OAuth2/OIDC access tokens (RS256/ES256) verified against a JWKS endpoint, alongside static and DB-managed keys. No extra dependency (WebCrypto).
- Outbound OAuth2 client-credentials — the bridge mints and auto-refreshes a token from the backend's token endpoint and injects it, so the MCP caller never sees the real client secret.
Control & workflow
- Human-in-the-loop approval — high-risk tools can require an out-of-band admin approval; the call files a ticket bound to its exact arguments and is single-use once approved.
- Declarative request/response transforms — reshape a tool's args or JSON response (set / remove / rename / copy) without code and with no expression eval to exploit.
Operate with confidence
Admin UI & config
- Admin UI (Vue 3 SPA) — dashboard, servers, bundles, API keys, consumers, policies, usage, alerts, schedules, audit log, users, teams and config.
- Customizable widget dashboard — a Grafana-style Overview grid: add, resize and configure stat/chart/note widgets from a catalog, then export or import the whole layout.
- Config versioning + rollback, plus import/export of servers, per-tool policies, bundles, alert rules and consumer quotas (see Deployment for what is out of scope).
- Maintenance schedules via a built-in cron matcher (leader-gated, de-duplicated).
Resilience — see Guardrails & resilience →
- Health monitoring + auto-eviction of unhealthy backends, with a ping probe for MCP upstreams.
- Canary / failover — route to a validated secondary when a primary's breaker opens, without falsely closing the primary breaker.
- Response caching — per-tool TTL + LRU cache for idempotent
GETresponses, served after all guards but before the circuit breaker (a cache hit never burns a half-open probe). - N-way load balancing — spread a client's calls across a pool of upstream targets (round-robin / weighted / least-connections) with a per-target health cooldown, on top of the primary circuit breaker.
Data handling
- Auto-pagination — follow cursor / page / RFC-5988
Linkpagination and aggregate the pages into one response (same-host only, SSRF-safe). - Streaming normalization — turn an NDJSON or SSE response into a single aggregated JSON result.
- Mock / virtualization — serve a canned response (always, for contract-first development) or only as a fallback when the backend is unavailable.
Observe
See Observability & monitoring →.
- Prometheus
/metrics, includingmcp_tool_calls_total{outcome}. - OpenTelemetry (OTLP/HTTP) tracing — a span per tool call when an OTLP endpoint is set.
- Usage analytics and usage-anomaly / spike detection that fires alerts via webhooks.
- Tamper-evident audit log — every admin action is hash-chained (
hash = SHA256(JSON.stringify([prev_hash, …])), an injective JSON pre-image rather than a bare delimiter join) and can be verified; optionally streamed to a SIEM. - Traffic explorer + replay — opt-in per-call capture (arguments + a result preview) you can inspect and re-run from the admin API.
- Synthetic monitoring + schema-drift — periodically replay a saved example through a tool and flag failures, and detect when an upstream's input schema drifts from a captured baseline.
Scale (opt-in)
See Scaling & high availability →.
- Shared rate counters in SQLite for consistent limits across instances.
- Cross-instance registry reconciliation so registrations and removals propagate to peers.
- Leader election so background loops (alerts, schedules) run on exactly one instance.
Runs anywhere
Bun single process + bun:sqlite — no external database, no Kubernetes. See Deployment → for Docker, bare-metal and reverse-proxy setup.
- Zero-config first run — start the container with no admin env vars at all and the first boot generates an admin credential, printing it once to stdout. Only its argon2id hash is kept, so it is never shown again; see First-run admin credentials → for the recovery paths.