Skip to main content
A shared server can declare required personal credential slots. Each authenticated user binds their own values in Credentials or from the server card. Server owners and administrators manage the declaration; users can only replace or delete their own binding. Shared users see slot names and labels without seeing the server’s connection configuration.

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

Use env 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).
The environment variables follow the upstream Tavily configuration and Context7 developer guide. Remove any credential-bearing CLI arguments when migrating: Context7’s --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 in x-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:
All slots are required; undeclared slots are rejected. Inputs stay blank when revisiting the dashboard. Deleting a server or user removes the corresponding bindings. Renaming a server removes bindings under its old name, so users must bind again. Adding a required slot also requires users to replace their binding with values for all slots.

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 over perSessionClient.
  • 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.
For staging, bind different Alice/Bob keys, call both services concurrently using each user’s bearer key, replace/delete Alice’s binding, and verify Bob’s calls remain unaffected. Test idle recycling and email-style OIDC usernames as well. The automated integration suite covers real local stdio, HTTP, and OpenAPI servers; real Tavily/Context7 API calls require your staging credentials.