Skip to content

Configuration

MCP REST Bridge is configured with environment variables (Bun auto-loads a .env file in development). The repository's .env.example is a curated, commented starter set. The tables below cover the settings you'll reach for most often; the Advanced tuning section further down documents the operational knobs — timeouts, retries, circuit-breaker, rate-limit and capacity limits — that most deployments never touch. Every variable is range-validated at boot by src/config-schema.ts, which aborts startup (or logs a warning, depending on STRICT_CONFIG) on an out-of-range value.

First-boot & authentication

VariableDescription
BOOTSTRAP_ADMIN_USERNAMEUsername for the first admin user. Applied only once, while the users table is empty.
BOOTSTRAP_ADMIN_PASSWORDPassword for that first admin (min 12 chars). Remove after the user exists.
ADMIN_API_KEYSComma-separated static Bearer keys for the JSON admin API (/admin-api, /register). Optional — the Vue UI uses session login.
MCP_API_KEYSComma-separated keys MCP clients present to call tools. Empty = no key required (combine with per-tool guards as needed).
REQUIRE_MCP_AUTHtrue forces the MCP data plane to fail closed even before a key exists (otherwise, with no keys/JWT configured, the data plane is open and a boot warning is logged).
EXPOSE_DOCS_UNAUTHENTICATEDtrue serves /docs (Swagger UI + full OpenAPI spec) publicly. Off by default — /docs is admin-authenticated.
AUTH_DISABLEDtrue turns off all authentication (admin API, MCP, sessions). Development only — outside NODE_ENV=development the bridge refuses to start unless ALLOW_UNSAFE_AUTH_DISABLED=true is also set. Never set either in a real deployment.
ALLOW_UNSAFE_AUTH_DISABLEDOpt-out that lets AUTH_DISABLED=true take effect outside development. A deliberate footgun guard — leave unset.

Runtime & networking

VariableDefaultDescription
PORT3000 (Docker) / 8790 (dev)Backend listen port.
GATEWAY_PUBLIC_URLPublic base URL the gateway advertises when generating client-connection configs (the admin UI's "Connect client" dialog / gateway connect). Optional — callers otherwise fall back to the browser origin or the CLI's --url.
SESSION_COOKIE_SECUREtrueKeep true in production (HTTPS). Set false only for local plain-HTTP dev.
ALLOW_UNSAFE_INSECURE_SESSION_COOKIEfalseOpt-out that lets SESSION_COOKIE_SECURE=false take effect outside development (admin session cookies sent over plain HTTP). Outside NODE_ENV=development the bridge refuses to start with an insecure cookie unless this is true. A deliberate footgun guard — leave unset.
NODE_ENVdevelopment relaxes startup guards for local dev. Never in production.
TRUST_PROXYfalseHop count (e.g. 1) or CIDR/preset list matching your reverse-proxy topology — never bare true, which trusts every hop in X-Forwarded-For and lets a client spoof its IP. See Deployment →.
ALLOW_PRIVATE_IPSfalseAllow registering backends on loopback/private IPs. Local dev only — never in production.
CORS_ORIGINSComma-separated origins allowed to call the admin API from a browser (CORS). Unset = no cross-origin admin access.
ALLOWED_ORIGINSComma-separated origins allowed to open an MCP session (Origin-header check on the data plane).
ALLOWED_HOSTSComma-separated Host header values the gateway accepts, rejecting others — anti-DNS-rebinding for the gateway itself.
STRICT_CONFIGproduction upgrades config-validation warnings to hard errors and aborts boot — recommended in production so a misconfiguration fails fast instead of only logging a warning.

Persistence

VariableDescription
DB_PATHSQLite file path (Docker default /app/data/mcp-bridge.db). Use :memory: for an ephemeral store.
SECRET_ENCRYPTION_KEYEnables encrypting per-client upstream credentials at rest (AES-256-GCM). Prefer base64 32 bytes (openssl rand -base64 32), used verbatim; any other string is treated as a passphrase and stretched with scrypt.

External secrets manager (optional)

Secrets at rest (OAuth2 client-credentials secrets, auto-provisioned MCP install-link keys) go through a pluggable SecretsProvider (src/secrets/), not SECRET_ENCRYPTION_KEY directly. Two backends are available:

  • local (default) — the built-in secret-box above. Zero extra infrastructure; this is what SECRET_ENCRYPTION_KEY configures.
  • vault — HashiCorp Vault's Transit secrets engine does the encrypt/decrypt instead, for operators required by policy to keep secret material in an external KMS. SECRET_ENCRYPTION_KEY is ignored in this mode.
VariableDefaultDescription
SECRETS_PROVIDERlocallocal or vault. Any other value fails fast at startup.
VAULT_ADDRVault server address (e.g. https://vault.example.com:8200). Required for vault.
VAULT_TOKENVault token sent as X-Vault-Token. Required for vault.
VAULT_TRANSIT_KEY_NAMEmcp-rest-bridgeName of the Vault Transit key used for encrypt/decrypt.

If Vault is unreachable or returns an error, the operation fails with a clear error — it never silently falls back to storing a secret in plaintext.

Feature flags & integrations

VariableDescription
ENABLE_SEARCH_TOOLToggle the synthetic search_tools meta-tool (default on).
AUDIT_SINK_URLStream every audit event to a SIEM/HTTP sink.
OTEL_EXPORTER_OTLP_ENDPOINTExport a trace span per tool call (OTLP/HTTP).
RATE_LIMIT_SHAREDtrue = SQLite-backed cross-instance rate counters (HA).
REGISTRY_SYNCtrue = reconcile the registry from SQLite across instances (HA).
AUTO_GATE_WRITE_METHODStrue = treat DELETE/PUT tools as sensitive by default, requiring step-up confirmation (per-tool overrides still win). Default false.

Proxy behavior

These tune the newer per-tool proxy features (caching, load balancing, traffic capture, approvals, synthetic monitoring). Each feature is opt-in per tool/client from the admin API; these are just the global knobs.

VariableDefaultDescription
CACHE_MAX_ENTRIES10000Max in-memory cached tool responses (LRU-evicted).
LB_TARGET_COOLDOWN_MS30000How long a load-balanced target is skipped after a failed call.
TRAFFIC_CAPTUREfalseCapture per-call args + result preview for the admin traffic explorer.
TRAFFIC_RETENTION_MS7 daysRetention window for captured traffic before pruning.
APPROVAL_WEBHOOK_URLFire-and-forget notification when a call is queued for human approval.
MONITOR_WEBHOOK_URLNotification when a synthetic monitor fails or detects schema drift.

Inbound JWT auth (optional)

Accept OAuth2/OIDC access tokens as an MCP credential, verified against a JWKS endpoint (RS256/ES256, via WebCrypto — no extra dependency). Additive to MCP_API_KEYS and DB-managed keys; setting JWT_JWKS_URL also locks the surface down (like minting a managed key).

VariableDescription
JWT_JWKS_URLJWKS endpoint. When set, MCP auth also accepts a valid RS256/ES256 JWT bearer.
JWT_ISSUERRequired iss claim (optional — rejected on mismatch when set).
JWT_AUDIENCERequired aud claim — token must list it. Mandatory in production when JWT_JWKS_URL is set (see warning).
ALLOW_UNSAFE_JWT_NO_AUDIENCEEscape hatch to run JWT_JWKS_URL without JWT_AUDIENCE outside development. Unsafe — see warning. Default false.

Audience binding is required in production

With JWT_JWKS_URL set but JWT_AUDIENCE empty, any token validly signed by that JWKS is accepted regardless of the audience it was minted for — in a shared IdP, a token issued for an unrelated app becomes a valid gateway credential (a cross-audience privilege grant). Outside development the bridge therefore refuses to start in this configuration unless you also set ALLOW_UNSAFE_JWT_NO_AUDIENCE=true. Set JWT_AUDIENCE to the gateway's own audience instead.

Advanced tuning

Operational knobs with sensible defaults — you rarely need to change any of them, but they're documented here so you don't have to read the source to find one. All durations are milliseconds; all rate limits are requests-per-minute per source unless noted. Values are range-validated at boot (src/config-schema.ts).

Timeouts, retries & response limits

VariableDefaultPurpose
TOOL_CALL_TIMEOUT_MS30000Per-tool-call timeout on the outbound backend request.
RETRY_MAX_ATTEMPTS2Retries for idempotent requests (total attempts = this + 1). 0 disables retries.
RETRY_BASE_DELAY_MS500Base delay for exponential backoff between retries.
RETRY_AFTER_MAX_MS30000Ceiling honoured from an upstream Retry-After header.
MAX_RESPONSE_BYTES10485760Max upstream response body (10 MiB); larger responses are rejected.
SHUTDOWN_FORCE_EXIT_MS10000Grace period before a SIGTERM shutdown force-exits.

Circuit breaker & health checks

VariableDefaultPurpose
CIRCUIT_BREAKER_WINDOW_MS60000Sliding window over which per-tool failures are counted.
CIRCUIT_BREAKER_FAILURE_THRESHOLD3Failures within the window that trip a breaker open.
CIRCUIT_BREAKER_RESET_TIMEOUT_MS30000How long an open breaker waits before a half-open probe.
CIRCUIT_BREAKER_HALF_OPEN_TIMEOUT_MS5000Timeout applied to the single half-open probe request.
MAX_CONSECUTIVE_FAILURES3Consecutive health-check failures before a client is auto-evicted.
HEALTH_CHECK_INTERVAL_MS30000Interval between background health-check passes.
HEALTH_CHECK_TIMEOUT_MS5000Per-client health-probe timeout.
HEALTH_CHECK_MAX_CONCURRENT20Max concurrent health checks per batch.

Rate limiting

The *_MAX_BUCKETS_* values cap the LRU maps that hold per-source counters — raise them only if you serve very many distinct source IPs and see bucket eviction churn.

VariableDefaultPurpose
RATE_LIMIT_MCP100Per-session limit on MCP data-plane calls.
RATE_LIMIT_REGISTER10Per-IP limit on POST /register.
RATE_LIMIT_GLOBAL1000Per-IP global request ceiling.
RATE_LIMIT_LOGIN10Per-IP limit on POST /admin-api/auth/login.
RATE_LIMIT_INSTALL_LINK20Per-IP limit on the public GET /install/:token route.
RATE_LIMIT_BACKUP5Per-IP limit on POST /admin-api/backup, which runs a synchronous VACUUM INTO.
RATE_LIMIT_SSO20Per-IP limit on the public GET /admin-api/auth/oidc/start and /callback routes. Both are unauthenticated by necessity and make outbound requests to the identity provider before they can reject a bogus call.
RATE_LIMIT_EXPENSIVE10Per-IP, per-route limit on the authenticated admin routes whose single-request cost is far above a normal read: PATCH /admin-api/auth/me/password (argon2id verify + hash), GET /admin-api/audit-log/verify (full hash-chain rehash) and GET /admin-api/audit-log/export. Each route has its own budget.
RATE_LIMIT_CLEANUP_INTERVAL_MS300000Interval between rate-limiter bucket-cleanup passes.
RATE_LIMIT_MAX_BUCKETS_GLOBAL50000Max LRU buckets in the global limiter map.
RATE_LIMIT_MAX_BUCKETS_MCP100000Max LRU buckets in the MCP-session limiter map.
RATE_LIMIT_MAX_BUCKETS_REGISTER10000Max LRU buckets in the register limiter map.
RATE_LIMIT_MAX_BUCKETS_TOOL20000Max LRU buckets in the per-tool guard limiter map.
RATE_LIMIT_MAX_BUCKETS_LOGIN5000Max LRU buckets in the login limiter map.
RATE_LIMIT_MAX_BUCKETS_INSTALL_LINK5000Max LRU buckets in the install-link limiter map.
RATE_LIMIT_MAX_BUCKETS_SSO5000Max LRU buckets in the SSO limiter map.
RATE_LIMIT_MAX_BUCKETS_EXPENSIVE5000Max LRU buckets in the expensive-route limiter map.

Capacity & sessions

VariableDefaultPurpose
MAX_TOOLS_PER_CLIENT100Max tools accepted in a single /register payload.
MAX_JSON_DEPTH32Max JSON nesting depth accepted in request bodies.
MAX_SESSIONS100Max concurrent in-memory MCP (Streamable HTTP) sessions.
SESSION_TTL_MS1800000Idle TTL for an MCP data-plane session (30 min).
SESSION_IDLE_TIMEOUT_MS1800000Sliding idle timeout for an admin session (30 min).
SESSION_ABSOLUTE_TTL_MS43200000Absolute cap on an admin session's lifetime (12 h).

Discovery (OpenAPI / GraphQL)

VariableDefaultPurpose
OPENAPI_DISCOVERY_TIMEOUT_MS10000Timeout for fetching/parsing an OpenAPI spec at registration.
GRAPHQL_DISCOVERY_TIMEOUT_MS10000Timeout for a GraphQL introspection query at registration.
GRAPHQL_MAX_TYPES2000Width cap on __schema.types during introspection.
GRAPHQL_SELECTION_MAX_DEPTH2Depth cap for auto-synthesized selection sets.
GRAPHQL_INPUT_MAX_DEPTH3Depth cap for mapping nested INPUT_OBJECT types to JSON Schema.

WebSocket proxy

VariableDefaultPurpose
WS_PROXY_MAX_GLOBAL_CONNECTIONS500Ceiling on concurrent proxied WebSocket connections.
WS_PROXY_DEFAULT_MAX_CONNECTIONS10Default per-target connection cap (overridable per target).
WS_PROXY_DEFAULT_MAX_MESSAGE_BYTES1048576Default max WS message size (1 MiB).
WS_PROXY_DEFAULT_IDLE_TIMEOUT_MS300000Default idle timeout before a proxied WS is closed (5 min).
WS_PROXY_DIAL_TIMEOUT_MS10000Timeout for dialing the upstream WebSocket.
WS_PROXY_REVALIDATE_INTERVAL_MS60000Interval for re-validating a target's pinned IP.

Tracing, metrics & data retention

VariableDefaultPurpose
METRICS_ENABLEDtrueSet false to disable the /metrics endpoint.
OTEL_SERVICE_NAMEmcp-rest-bridgeservice.name resource attribute on exported spans.
OTEL_MAX_BATCH128Spans buffered before a flush is forced.
OTEL_EXPORT_TIMEOUT_MS5000Timeout for an OTLP export POST.
TRACE_STORAGEfalsePersist spans to SQLite for the built-in trace viewer.
TRACE_RETENTION_MS86400000Retention for persisted spans (24 h).
USAGE_RETENTION_MS2592000000Retention for per-call usage rows (30 days).
TRAFFIC_MAX_BODY_BYTES8192Max chars stored per captured traffic result preview.

Alerts & anomaly detection

VariableDefaultPurpose
ALERT_INTERVAL_MS30000How often the leader evaluates alert rules.
ALERT_WEBHOOK_TIMEOUT_MS5000Timeout for an outbound alert-webhook delivery.
ALERT_ERROR_RATE_WINDOW_MS300000Sliding window for error-rate alert evaluation (5 min).
ANOMALY_RECENT_WINDOW_MS300000Recent window for usage-spike detection (5 min).
ANOMALY_BASELINE_WINDOW_MS3600000Baseline window for usage-spike detection (1 h).

Integration timeouts & HA

VariableDefaultPurpose
APPROVAL_WEBHOOK_TIMEOUT_MS5000Timeout for an approval-notification webhook.
MONITOR_WEBHOOK_TIMEOUT_MS5000Timeout for a monitor-notification webhook.
AUDIT_SINK_TIMEOUT_MS3000Timeout for an audit-sink (AUDIT_SINK_URL) delivery.
OAUTH_TOKEN_TIMEOUT_MS10000Timeout for an outbound OAuth2 client-credentials token request.
JWT_JWKS_CACHE_MS600000How long a fetched JWKS is cached (10 min).
JWT_JWKS_TIMEOUT_MS5000Timeout for a JWKS fetch.
VAULT_REQUEST_TIMEOUT_MS5000Timeout for a Vault Transit encrypt/decrypt request.
CONTEXT_BUDGET_LLM_TIMEOUT_MS15000Timeout for the opt-in per-tool llm_summarize compression call.
LEADER_LEASE_DURATION_MS15000Duration of the leader-election lease.
REGISTRY_SYNC_INTERVAL_MS15000Interval between registry reconciliation passes (needs REGISTRY_SYNC).
INSTANCE_IDrandom UUIDStable identity for this process in leader-election bookkeeping.

CORS fine-tuning & logging

VariableDefaultPurpose
CORS_MAX_AGE_SECONDS600Preflight cache duration (Access-Control-Max-Age).
CORS_ALLOW_CREDENTIALSfalseSend Access-Control-Allow-Credentials for allowlisted origins.
ALLOW_UNSAFE_CORS_WILDCARDfalsePermit a * in CORS_ORIGINS while auth is enabled (unsafe).
LOG_FORMATjsonjson or text structured-log output.

TIP

Generate keys/secrets with, e.g., openssl rand -hex 24 (API keys) or openssl rand -base64 32 (SECRET_ENCRYPTION_KEY). .env.example is a curated starter set; this page (plus Advanced tuning above) documents every variable, and src/config-schema.ts enforces the accepted range for each one at boot.

Next: Deployment → · Security →

Released under the MIT License · Built with Bun + Vue.