Skip to main content
MCPHub reads the following environment variables at startup. The authoritative list is whatever appears under process.env.* in src/; this page summarizes everything currently read by the code on main.

Core application

VariableDefaultDescription
PORT3000HTTP server port.
BASE_PATH''Mount-point prefix when MCPHub is served under a sub-path (e.g. /mcphub).
DEFAULT_REQUEST_TIMEOUT60000Default request timeout (ms) for upstream MCP server requests when a server does not set options.timeout.
INIT_TIMEOUT300000Initial timeout (ms) used when starting upstream MCP servers.
READONLYfalseReject mutating dashboard API requests. GET and ${basePath}/tools/* remain allowed.
DISABLE_WEBfalseSkip serving the bundled dashboard. The API and MCP transport routes still run.
TRUST_PROXYautoExpress trust proxy setting. Accepts true, false, a hop count (1, 2, …), or names like loopback,linklocal,uniquelocal. Defaults to 1 inside Docker/Kubernetes, false otherwise.
MCPHUB_SETTING_PATHmcp_settings.jsonOverride the path of the settings file used by file-mode storage.
NODE_ENVdevelopmentdevelopment / production / test.
DEBUGfalseSet to true to enable verbose startup logging for frontend-path discovery.

Authentication

VariableDefaultDescription
ADMIN_PASSWORDrandomPassword seeded for the bootstrap admin user when no users exist yet. If unset, a 24-character random password is generated and printed to the logs.
JWT_SECRETrandom per-processSecret used to sign JWTs issued by /api/auth/login. See the warning below — this must be set explicitly in any non-development deployment.
JWT_SECRET must be set to a persistent, high-entropy value (≥ 32 random bytes) in staging and production. If it is left unset, MCPHub generates a new random secret on every process start, which means: every restart invalidates all outstanding sessions and bearer tokens; horizontally-scaled instances cannot share sessions because each replica signs with its own secret; and CI / container restarts silently log everyone out. Generate one with openssl rand -hex 32 and store it in your secret manager. Treat it like any other long-lived cryptographic key — rotation requires invalidating outstanding JWTs.

Better Auth (optional social login)

Better Auth is initialized once at process startup in src/betterAuth.ts. Because of that, changing any Better Auth setting still requires a restart. For non-secret Better Auth settings, MCPHub resolves values in this order:
  1. BETTER_AUTH_* environment variables
  2. systemConfig.auth.betterAuth (from mcp_settings.json or the database-backed system config)
  3. Built-in defaults
Provider client credentials remain environment-variable only.
Better Auth currently requires PostgreSQL-backed storage in MCPHub. In practice that means DB_URL must be configured; file-only mode does not support Better Auth sessions.
VariableDescription
BETTER_AUTH_ENABLEDMaster switch for Better Auth. Better Auth is still disabled automatically when MCPHub is not in database mode or when no provider has the required credentials.
BETTER_AUTH_URLPublic base URL used to build Better Auth redirect URIs. This now takes precedence over systemConfig.install.baseUrl. Its origin is also auto-added to the trusted origin list.
BETTER_AUTH_BASE_PATHMount path for the Better Auth handler. Defaults to /api/auth/better.
BETTER_AUTH_TRUSTED_ORIGINSOptional additional origins allowed to start Better Auth login flows. Accepts a comma-separated list, whitespace-separated list, or JSON array. When omitted, MCPHub still auto-trusts the origins from BETTER_AUTH_URL and systemConfig.install.baseUrl.
BETTER_AUTH_GOOGLE_ENABLEDEnable or disable the Google provider after credentials are present. Defaults to true.
GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRETGoogle OAuth app credentials.
BETTER_AUTH_GITHUB_ENABLEDEnable or disable the GitHub provider after credentials are present. Defaults to true.
GITHUB_CLIENT_ID / GITHUB_CLIENT_SECRETGitHub OAuth app credentials.
BETTER_AUTH_OIDC_ENABLEDEnable or disable the generic OIDC provider. Defaults to false.
BETTER_AUTH_OIDC_PROVIDER_IDProvider identifier passed to Better Auth’s generic OAuth plugin. Defaults to oidc.
BETTER_AUTH_OIDC_DISCOVERY_URLDiscovery URL for a local OIDC issuer (for example Keycloak, Authentik, or Dex).
OIDC_DISCOVERY_URLLegacy alias for BETTER_AUTH_OIDC_DISCOVERY_URL. It is also still useful for ${OIDC_DISCOVERY_URL} interpolation inside mcp_settings.json.
BETTER_AUTH_OIDC_SCOPESOptional requested scopes for the local OIDC provider. Accepts a comma-separated list, whitespace-separated list, or JSON array. Defaults to openid profile email.
BETTER_AUTH_OIDC_PKCEEnable or disable PKCE for the local OIDC provider. Defaults to true.
BETTER_AUTH_OIDC_PROMPTOptional prompt parameter for the local OIDC provider (login, consent, select_account, etc.).
OIDC_CLIENT_ID / OIDC_CLIENT_SECRETClient credentials for a local OIDC provider such as Keycloak, Authentik, or Dex.
You can still store the non-secret Better Auth settings in systemConfig.auth.betterAuth, but BETTER_AUTH_* variables now override those values at startup. A full env-only local OIDC example looks like this:
BETTER_AUTH_ENABLED=true
BETTER_AUTH_URL=https://mcphub.example.com
BETTER_AUTH_BASE_PATH=/api/auth/better
BETTER_AUTH_TRUSTED_ORIGINS=https://dashboard.example.com,https://admin.example.com

BETTER_AUTH_OIDC_ENABLED=true
BETTER_AUTH_OIDC_PROVIDER_ID=local-oidc
BETTER_AUTH_OIDC_DISCOVERY_URL=https://auth.example.com/.well-known/openid-configuration
BETTER_AUTH_OIDC_SCOPES=openid,profile,email
BETTER_AUTH_OIDC_PKCE=true
BETTER_AUTH_OIDC_PROMPT=login
OIDC_CLIENT_ID=your-oidc-client-id
OIDC_CLIENT_SECRET=your-oidc-client-secret

Storage

MCPHub picks file or database storage at boot:
useDatabase = (USE_DB === 'true') OR (USE_DB unset AND DB_URL is set)
VariableDefaultDescription
USE_DBunsetForce database mode (true) or file mode (false).
DB_URLunsetPostgreSQL connection URL. Required for database mode.
USE_DAO_LAYERunsetForce the DAO layer on even in file mode (advanced; usually unnecessary).
DB_POOL_SIZE10Maximum TypeORM connection pool size.
DB_POOL_IDLE_TIMEOUT30000Idle pool connection timeout (ms).
DB_CONNECTION_TIMEOUT30000Initial connect timeout (ms).
DB_CONNECTION_RETRY_DELAY2000Base delay between connection retries (ms).
DB_MAX_CONNECTION_RETRIES5Maximum connection retry attempts at startup.
DB_ENABLE_HEALTH_CHECKtrueRun periodic DB health probes (consumed by /health).
DB_HEALTH_CHECK_INTERVAL30000Health-probe interval (ms).
See Database Configuration for end-to-end setup.

Smart Routing & embeddings

Smart Routing performs vector search over upstream tools to surface only the few most relevant tools for a given query. It requires Postgres + pgvector and an embedding endpoint.
VariableDefaultDescription
SMART_ROUTING_ENABLEDfalseMaster switch for smart routing.
SMART_ROUTING_EMBEDDING_PROVIDERopenaiEmbedding provider. Currently openai or azure_openai.
SMART_ROUTING_EMBEDDING_ENCODING_FORMATprovider defaultOverride the encoding_format passed to the embedding API.
SMART_ROUTING_BASE_PACING_DELAY_MS0Base delay (ms) applied between embedding requests to avoid rate limits.
SMART_ROUTING_PROGRESSIVE_DISCLOSUREunsetWhen set, expose progressively-disclosed tool metadata (see Smart Routing docs).
SMART_ROUTING_SERVER_DESCRIPTION_MODEnamesControl how search_tools lists available servers: names for server names only, full to include server descriptions/instructions when available.
EMBEDDING_MODELtext-embedding-3-smallEmbedding model name.
EMBEDDING_MAX_TOKENSper-modelOverride token truncation limit before embedding. Useful to match a local inference server’s batch size.

OpenAI

VariableDescription
OPENAI_API_KEYAPI key.
OPENAI_API_BASE_URLOverride the base URL (set this for any OpenAI-compatible endpoint, e.g. LocalAI).

Azure OpenAI

VariableDescription
AZURE_OPENAI_API_KEYAPI key.
AZURE_OPENAI_ENDPOINTResource endpoint (e.g. https://my-resource.openai.azure.com).
AZURE_OPENAI_API_VERSIONAPI version (e.g. 2024-02-01).
AZURE_OPENAI_EMBEDDING_DEPLOYMENTDeployment name.
AZURE_OPENAI_EMBEDDING_MODELThe underlying OpenAI model the deployment maps to (e.g. text-embedding-3-small). Used for tokenizer and limit selection.

MCPRouter (optional upstream catalog)

VariableDescription
MCPROUTER_API_KEYAPI key for the MCPRouter cloud catalog.
MCPROUTER_API_BASEOverride the API base URL (default https://api.mcprouter.to/v1).
MCPROUTER_REFEREROptional Referer header sent on MCPRouter requests.
MCPROUTER_TITLEOptional Title header sent on MCPRouter requests.

Configuration examples

Development

NODE_ENV=development
PORT=3000
JWT_SECRET=dev-secret-key

Production with database + Smart Routing

NODE_ENV=production
PORT=3000
BASE_PATH=
JWT_SECRET=replace-with-32+-random-bytes

USE_DB=true
DB_URL=postgresql://mcphub:secret@db:5432/mcphub

SMART_ROUTING_ENABLED=true
OPENAI_API_KEY=sk-...
EMBEDDING_MODEL=text-embedding-3-small

Loading order

MCPHub loads variables in this order; later sources override earlier ones:
  1. System environment variables.
  2. .env.local (gitignored).
  3. .env.{NODE_ENV} (e.g. .env.production).
  4. .env.
dotenv-expand is enabled, so ${VAR} interpolation works inside .env* files.

Security best practices

  1. Never commit secrets — .env* files are gitignored by default; keep it that way.
  2. Always set JWT_SECRET explicitly in production.
  3. Rotate bearer keys (/api/auth/keys) and OAuth client secrets periodically.
  4. Use Docker / Kubernetes secrets for container deployments instead of plain -e.