This guide outlines requirements, configurations, and migration paths for deploying the Model Context Protocol (MCP) Router Gateway into production environments.
You can spin up the gateway container with zero environment variables or with secure Docker/Kubernetes file secrets without exposing plaintext secrets in process tables:
The gateway resolves the 256-bit Master Encryption Key (used for AES-256-GCM application-level database envelope encryption) in the following order:
- Auto-Generated Persistent Keyfile (
./data/.master.key) (Default): If no environment variable is provided on first boot, the router automatically generates a cryptographically secure 256-bit key, writes it to./data/.master.keywith restricted permissions (chmod 0600), and logs a startup notice. As long as./datais mounted to persistent storage, the key is preserved across container restarts with zero manual configuration. - Docker / Kubernetes File Secret (
ROUTER_MASTER_KEY_FILE): PointROUTER_MASTER_KEY_FILEat a mounted secret file (e.g.,ROUTER_MASTER_KEY_FILE=/run/secrets/router_master_key). The gateway also automatically checks standard Docker secret paths (/run/secrets/router_master_key,/run/secrets/master_key). - Explicit Environment Variable (
ROUTER_MASTER_KEYorROUTER_SECRET): Pass a 256-bit base64-encoded key directly viaROUTER_MASTER_KEY=<base64-key>if preferred. - Windows DPAPI (IIS / Windows Service): When deploying natively to Windows IIS, the gateway can leverage Windows DPAPI machine keys, requiring zero configuration keys.
Tip
Zero Plaintext Secrets: Using the auto-generated persistent keyfile (./data/.master.key) or ROUTER_MASTER_KEY_FILE prevents secret leakage via docker inspect or /proc/<pid>/environ.
When no environment variables or configuration files are provided:
| Subsystem | Automatic Safe Default |
|---|---|
| 🗄️ Database | • Defaults to DB_PROVIDER=sqlite.• Automatically creates ./data/mcp_router.db.• Runs schema migrations and seeds baseline tables ( Servers, Settings, AppKeys, AccessPolicies, GroupMappings, SecretProviders, AuthProviderConfigs, AuditLogs). |
| 🔒 Secret Storage | • Uses the Built-in Master Secret Provider (AES-256-GCM). • All backend server credentials are encrypted in SQLite using your resolved master key (no external Vault or DPAPI needed). |
| 👤 Authentication | • Detects that no external Identity Provider (LDAP or OIDC forward-auth) is active. • Standalone Mode engages automatically. • Local loopback ( 127.0.0.1, ::1) is trusted as Administrator for Web UI access without requiring an SSO login. |
| 🔑 Pre-Seeded Admin Key | • Seeds a default system Admin AppKey into the database: mcp-global-admin-default-cli-key-99.• Has username admin and scope ["all", "admin"].• Enables remote AI coding agents and CLI scripts to authenticate to /admin and /admin/sse immediately. |
| 🐳 Docker Discovery | • If -v /var/run/docker.sock:/var/run/docker.sock is mounted, background discovery immediately registers containers labeled mcp.enabled=true. |
- Dashboard Web UI:
http://localhost:8080/(Full administrative dashboard) - Health Probe:
http://localhost:8080/health({"status":"healthy","service":"McpRouter","version":"4.34.0"}) - Meta-Mode MCP Gateway:
http://localhost:8080/sse(Exposessearch_toolsandexecute_tool) - Admin MCP Server:
http://localhost:8080/admin/sse(orPOST /adminfor direct JSON-RPC tool dispatch)
From this blank-slate container, an autonomous AI agent (using the mcp-router-admin skill) or a DevOps script can connect to /admin using mcp-global-admin-default-cli-key-99 to configure Authentik, Keycloak, Entra ID, Active Directory, HashiCorp Vault, semantic search embeddings, backend MCP servers, and personal AppKeys without restarting the container or editing static files.
Production environments can be locked down to prevent spoofing, unauthorized access, and credential leakage.
| Configuration Key | Environment Variable Equivalent | Type | Description / Behavior |
|---|---|---|---|
ROUTER_MASTER_KEY |
ROUTER_MASTER_KEY or ROUTER_MASTER_KEY_FILE |
Optional | High-entropy 256-bit key or file path. If unset, automatically generated and stored in ./data/.master.key. |
DB_PROVIDER |
DB_PROVIDER |
Optional | Supported: sqlite, mssql, mysql. Defaults to sqlite. |
ConnectionStrings:DefaultConnection |
ConnectionStrings__DefaultConnection |
Mandatory | Connection string for the chosen database provider. |
CORS_ALLOWED_ORIGINS |
CORS_ALLOWED_ORIGINS |
Mandatory | Comma/semicolon/whitespace-separated list of allowed origins. Unconfigured/empty locks out browser access in production. |
OpenIddict:CertificatePath |
OpenIddict__CertificatePath |
Mandatory | Filepath to the PFX/PKCS#12 certificate used to sign OAuth tokens in production. Unconfigured fallbacks reset on application restart, invalidating active client sessions. |
Oidc:TrustedProxies |
Oidc__TrustedProxies |
Highly Recommended | List of upstream reverse proxy IP addresses trusted by the gateway. Defaults strictly to loopback-only (127.0.0.1 / ::1) if unconfigured. |
Admin:GroupSid |
Admin__GroupSid |
Optional | Active Directory Group SID designated for Administrators. Defaults to S-1-5-32-544 (Local Administrators). |
In previous releases, the trusted-proxy fallback trusted IPs in standard container subnets (10.0.0.0/8, 172.16.0.0/12).
Starting in version 4.5.5, the unconfigured default is loopback-only (127.0.0.1 and ::1).
💡 Important Deployment Action: If your reverse proxy (e.g., Caddy, Nginx, Traefik, IIS) runs on a bridge network, you MUST configure
Oidc:TrustedProxieswith the proxy's IP address. If left unset, proxy-passed SSO headers from remote hosts will be stripped, degrading authentication to guest access.
SQLite requires no manual schema steps: on first start the gateway creates tables and applies migrations automatically via the built-in seeder. This is the recommended path for single-node deployments.
- .NET 10 runtime on the host (or use the container image).
- Active Directory SID resolution is fully cross-platform via LDAP. Native
WindowsIdentityis automatically used as a fast-path on Windows hosts. Header-based (reverse-proxy) identity also works cross-platform. - A reverse proxy (IIS/Nginx/Caddy/Traefik) terminating TLS and injecting identity headers, if using header auth.
ROUTER_MASTER_KEY encrypts downstream credentials at rest (AES-GCM). Generate a 256-bit key:
openssl rand -base64 32Production fails closed if no certificate is configured (tokens would otherwise reset every restart):
openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 3650 -nodes -subj "/CN=mcp-router"
openssl pkcs12 -export -out openiddict.pfx -inkey key.pem -in cert.pem -passout pass:Point OpenIddict:CertificatePath at the resulting openiddict.pfx.
Copy .env.example to .env (or use appsettings.Production.json.example) and set at minimum:
ASPNETCORE_ENVIRONMENT=Production
ROUTER_MASTER_KEY=<from step 1>
DB_PROVIDER=sqlite # default; may be omitted
ConnectionStrings__DefaultConnection=Data Source=/data/mcprouter.db
CORS_ALLOWED_ORIGINS=https://mcp.internal.example.com
OpenIddict__CertificatePath=/data/openiddict.pfx
Oidc__TrustedProxies=10.20.30.40 # your reverse proxy IP (loopback-only if unset)
Admin__GroupSid=S-1-5-21-... # your AD admins group SIDThe SQLite .db file (and the PFX) must live on persistent storage. In containers, mount a volume at the directory referenced by Data Source (e.g. -v mcprouter-data:/data). Losing the file loses all servers, keys, policies, and audit history.
# from a published build
dotnet mcp-router.dll
# or the container image, with the data volume and env file
docker run --env-file .env -v mcprouter-data:/data -p 8080:8080 <image>- The gateway logs
Initializing database via Dapper...and creates the schema on first boot. - Liveness:
GET /healthreturns healthy (note: this is a static liveness probe — a true readiness probe is on the observability backlog). - Confirm audit capture by making an authenticated call and reading it back via
GET /api/audit.
⚠️ Scope note: Only the SQLite path is exercised in the current CI/test suite (159 tests, SQLite). The SQL Server / MySQL provider paths, real AD/LDAP, and Vault integration are implemented but have not been validated end-to-end in this repo — verify those in your own environment before relying on them.
The MCP Router supports SQL Server, MySQL/MariaDB, and SQLite. For comprehensive dialect specifications, envelope encryption details, fail-closed validation contracts, and Docker Compose configurations, see the Database Provider Support & Deployment Matrix Guide.
When configuring MS SQL Server or MySQL, execute the database scripts in the exact sequence described below to initialize the database and stored procedures.
01_tables.sql: Renders database tables, constraints, and indexes.02_procedures.sql: Renders model access evaluation, audit logging, and JIT secret retrieval stored procedures.
- MS SQL Server:
scripts/db/mssql/ - MySQL / MariaDB:
scripts/db/mysql/
When upgrading existing deployments, you must apply versioned delta migration scripts sequentially.
The migration 003_add_appkeys_ownersid.sql introduces an optional OwnerSid field to the AppKeys table and updates stored procedures (sp_SaveAppKey and sp_GetAppKeys) to track app key owners dynamically.
Run the corresponding delta migration script against your database using standard CLI tools.
- MS SQL Server:
sqlcmd -S localhost -U sa -P Password123! -i scripts/db/mssql/migrations/003_add_appkeys_ownersid.sql - MySQL / MariaDB:
mysql -u root -p McpEnterpriseDb < scripts/db/mysql/migrations/003_add_appkeys_ownersid.sql
For quick integration, copy .env.example to .env or copy appsettings.Production.json.example to appsettings.Production.json directly into your container/server configuration.
For detailed information on supported combinations of hosting environments, authentication providers, and downstream delegation methods (e.g., Docker vs IIS, OIDC vs AppKey), please refer to the Deployment & Authentication Support Matrix.