Deployment
MCPHUB_CREDENTIAL_ENCRYPTION_KEY is optional for a single instance. When it is absent, the first binding save generates 32 random bytes and atomically creates <MCPHUB_SETTING_PATH>.credentials.key next to the settings file (or next to the default settings file). The key file has mode 0600 and is reused after restart. It is excluded from configuration exports, Git, and the Docker build context. The settings directory must be writable; failure to persist the key stops the save.
An explicitly set environment variable takes precedence and must contain 32 random bytes encoded as base64, for example generated with openssl rand -base64 32. Invalid environment values or key files fail instead of being silently replaced. If the key file is missing while encrypted bindings already exist, restore the original file or environment key; MCPHub will not generate a replacement that makes old bindings unreadable.
Back up the key separately and persist the settings directory in Docker; mounting only the JSON settings file does not persist its sibling key file. Multiple instances sharing a database must use the same environment key or the same shared key file, rather than generating independent keys. Keep the key outside server definitions. The environment variable is removed from child-process environments.
Bindings use AES-256-GCM with the server name and username authenticated as associated data. JSON mode stores ciphertext in <MCPHUB_SETTING_PATH>.credentials.json (or next to the default settings file), with mode 0600 and atomic replacement. Database mode stores ciphertext in credential_bindings. The normal configuration export excludes bindings. File-to-database migration copies ciphertext; retain the same encryption key. JSON mode assumes a single writer process; use database mode for multiple hub processes.
Declare slots
Useenv slots for stdio and headers slots for SSE, Streamable HTTP, and OpenAPI. Values are literal strings, without environment-variable expansion. Supply the entire header value, including Bearer when required. Declared personal headers override static, passthrough, and OpenAPI tool-parameter headers. Templates contain only target, name, and an optional label (maximum 32 slots).
--api-key argument takes precedence over its environment variable.
For an HTTP server, declare {"target":"headers","name":"Authorization"} instead. Shared upstream OAuth cannot be combined with a personal credential template.
Manage a binding through the API
Use dashboard authentication (JWT inx-auth-token, an OIDC/session login, or a user OAuth access token). User-level MCP bearer keys remain MCP-only credentials; system bearer keys and anonymous dashboard mode cannot manage personal bindings. No endpoint accepts a target username.
Example PUT body:
Runtime behavior
- MCP session/OIDC users resolve their own binding; user-level bearer keys resolve their live owner user. A route name or caller-supplied username never selects a credential.
- Every request checks the current binding. Missing values fail with an instruction to bind credentials in Credentials; there is no implicit organization fallback.
- Templated servers start on first discovery or invocation. A stdio child is keyed by
(server, user), shared across that user’s MCP sessions, and hidden from the server list. This takes precedence overperSessionClient. - Active requests hold their runtime. After the last request finishes,
idleTimeoutMs(default five minutes) recycles it. Updates/deletes invalidate the local runtime immediately; other hub processes observe the new binding on their next request. - HTTP clients are isolated per user too and replaced when bindings change. Personal tools, prompts, and resources are not added to shared embedding caches; ordinary routing works, while vector-based smart search does not index personal catalogs.
- Personal upstream connection errors and stderr are withheld because they may contain credential values. Normal server definitions retain their existing behavior.