Deployment

Configuration

MCP Ambassador is configured via environment variables. All configuration has sensible defaults for development — production deployments should set secrets and TLS options explicitly.


Environment variables

Core

VariableDefaultDescription
NODE_ENVproductionproduction or development. The reference compose file sets production: no dev client key is auto-created, so create client keys in the UI, and a config-file load failure aborts startup. For a local trial, set NODE_ENV=development (it enables the dev client key bootstrap). It does not change logging (use MCP_AMBASSADOR_LOG_LEVEL=debug).
MCP_AMBASSADOR_LOG_LEVELinfodebug, info, warn, error. The reference compose file passes it from LOG_LEVEL (LOG_LEVEL=debug docker compose up -d).
MCP_AMBASSADOR_PORT8443Ambassador Client API port. The admin and user web UI listens on 9443; change the published host port in the compose ports mapping instead.
PUBLIC_URLempty in the reference composeSet PUBLIC_URL to the https URL users reach the web UI on (for example https://localhost:9443 for a local trial). In 0.10.0 the reference compose file passes it empty, which disables approval gates (gated calls fail closed and startup logs an error) and leaves the agent-endpoint issuer empty unless agent_endpoint.issuer_url is set. If set, it must be https, or http only on loopback.

Secrets

VariableDefaultDescription
ADMIN_SESSION_SECRETauto-generated32-byte hex secret for admin session HMAC. Auto-generated in development, persisted to ./data/. Must be set explicitly in production.
CREDENTIAL_MASTER_KEYauto-generated32-byte hex key for AES-256-GCM credential vault encryption. Auto-generated in development, persisted to ./data/credential_master_key. Must be set explicitly in production.
ADMIN_KEYauto-generatedAdmin API key (amb_ak_…). It is never logged; on first boot it is written to ./data/initial-credentials.txt.

TLS

VariableDefaultDescription
TLS_CERT_PATH/data/certs/server.crtPath to TLS certificate
TLS_KEY_PATH/data/certs/server.keyPath to TLS private key
TLS_DISABLEDfalseSet to true to disable TLS (for reverse proxy deployments)

Database

VariableDefaultDescription
DATABASE_URLSQLite at /data/ambassador.dbSQLite file path or PostgreSQL URL (Pro tier)

Session

VariableDefaultDescription
SESSION_TTL_SECONDS28800Client session token TTL (8 hours)
SESSION_HEARTBEAT_INTERVAL120Expected heartbeat interval in seconds
LOGIN_RATE_LIMIT_ATTEMPTS5Max login attempts per IP per window
LOGIN_RATE_LIMIT_WINDOW_SECONDS300Rate limit window (5 minutes)

Downstream MCP isolation

VariableDefaultDescription
MCP_AMBASSADOR_CHILD_UID_RANGE20000-20999min-max range of uids handed out to MCP instances (gid = uid). Minimum is 10000, at most 10000 ids, and it must not contain the server's uid or gid. The image creates passwd entries for the default range; the entrypoint warns if your range falls outside it.
MCP_AMBASSADOR_CHILD_NPROC256Per-instance process limit (RLIMIT_NPROC of the instance's own uid). It counts threads, so raise it for browser MCPs. 0 disables the limit. Never raised above a stricter hard limit the server already runs under.
MCP_AMBASSADOR_CHILD_UIDunsetLegacy single-uid mode: all MCPs share one uid. The image sets a default range, so to use this mode empty the range (MCP_AMBASSADOR_CHILD_UID_RANGE=). Setting both is an error and the entrypoint exits.

Never disable isolation in production

If MCP_AMBASSADOR_CHILD_UID_RANGE is emptied and MCP_AMBASSADOR_CHILD_UID is unset, isolation is off: MCP children run as the server's uid and can read /data (database, credential key, TLS keys). This is for local development only. Never clear the range in production.

If the container lacks the SETUID, SETGID and KILL capabilities (or setpriv/prlimit is missing), MCP children refuse to start and the server logs a clear message. See Docker for the required compose settings.


Data paths

Inside the container, all persistent data lives at /data/ (mounted as a Docker volume or bind mount, owned by uid 1000). Downstream MCP processes cannot read it.

/data/
  ambassador.db          # SQLite database (WAL mode)
  certs/
    server.crt           # TLS certificate (auto-generated or provided)
    server.key           # TLS private key
    ca.crt               # CA certificate (returned to Ambassador Clients)
  credential_master_key  # 32-byte hex master key (permissions 0600)
  child-uids.json        # uid assigned to each MCP instance (permissions 0600)

Mount these to a persistent volume:

volumes:
  ambassador-data:
    driver: local
services:
  ambassador:
    volumes:
      - ambassador-data:/data

Generating secrets

# Generate ADMIN_SESSION_SECRET
openssl rand -hex 32

# Generate CREDENTIAL_MASTER_KEY
openssl rand -hex 32

Full docker-compose.yml example

services:
  ambassador:
    image: mcpambassador-server:latest
    ports:
      - '8443:8443'
      - '9443:9443'
    volumes:
      - ambassador-data:/data
    environment:
      - NODE_ENV=production
      - ADMIN_SESSION_SECRET=your_64_char_hex_session_secret
      - CREDENTIAL_MASTER_KEY=your_64_char_hex_master_key
      - LOG_LEVEL=info
    restart: unless-stopped
    healthcheck:
      test: ['CMD', 'curl', '-fk', 'https://localhost:8443/health']
      interval: 30s
      timeout: 10s
      retries: 3

volumes:
  ambassador-data:

Log format

MCP Ambassador emits structured JSON logs to stdout:

{
  "level": "info",
  "timestamp": "2026-02-19T14:32:01.123Z",
  "correlation_id": "corr_uuid",
  "message": "Tool invocation completed",
  "user_id": "user_uuid",
  "tool": "github.search_code",
  "duration_ms": 234
}

Set LOG_LEVEL=debug to see verbose output including request details and MCP spawn events.


Timing and performance

MCP Ambassador's internal timers are tuned for production workloads with hundreds of concurrent sessions. You can adjust these in the YAML config file (ambassador-server.yaml) or via environment variables.

Server-side timing

SettingDefaultConfig PathDescription
Session TTL28800s (8h)session.ttl_secondsHow long a client session token is valid before the client must re-authenticate
Evaluation interval120ssession.evaluation_interval_secondsHow often the server evaluates sessions for idle timeout
Sweep interval1800s (30m)session.sweep_interval_secondsHow often the server purges expired sessions from memory
Heartbeat expected120ssession.heartbeat_expected_interval_secondsHow often the server expects a heartbeat from each client
Heartbeat rate limit1 per 10sHardcodedMaximum heartbeat frequency per client (prevents misconfigured clients from flooding)
Health check interval120000msmcp.health_check_interval_msHow often the server pings downstream MCPs to verify they are alive

Admin SPA polling

The web dashboard polls the server for live status updates. These intervals balance responsiveness with server load.

EndpointIntervalWhat it shows
Health status60sMCP instance health indicators
MCP list60sAdmin MCP catalog
Catalog60sUser marketplace
Logs30sMCP instance log stream

Client-side timing

The Ambassador Client (@mcpambassador/client) has its own performance settings. See the client documentation for details.

SettingDefaultDescription
Heartbeat interval120sHow often the client sends a heartbeat to keep the session alive
Cache TTL300sHow long the client caches the tool catalog before refreshing
Cache enabledtrueWhether tool catalog caching is active (recommended for production)

Deployment profiles

Choose the profile that matches your security and scale requirements.

ProfileSession TTLHeartbeatEval intervalBest for
Default8h120s120sMost production deployments
High-security4h60s60sRegulated environments, SOC2 compliance
Development24h30s30sLocal development and testing
High-scale8h180s180s1000+ concurrent sessions, minimize server load
Previous
Production Setup