Database Configuration for MCPHub
Overview
MCPHub supports storing configuration data in a PostgreSQL database as an alternative to themcp_settings.json file. Database mode provides enhanced persistence and scalability for production environments and enterprise deployments.
Why Use Database Configuration?
Core Benefits:- ✅ Better Persistence - Configuration stored in a professional database with transaction support and data integrity
- ✅ High Availability - Leverage database replication and failover capabilities
- ✅ Enterprise Ready - Meets enterprise data management and compliance requirements
- ✅ Backup & Recovery - Use mature database backup tools and strategies
Environment Variables
Required for Database Mode
Simplified Configuration: You only need to set
DB_URL to enable database mode. MCPHub will automatically detect and enable database mode when DB_URL is present. Use USE_DB=false to explicitly disable database mode even when DB_URL is set.Setup Instructions
1. Using Docker
Option A: Using External Database
If you already have a PostgreSQL database:Option B: Using PostgreSQL as a separate service
Create adocker-compose.yml:
2. Manual Setup
Step 1: Setup PostgreSQL Database
Step 2: Install MCPHub
Step 3: Set Environment Variables
Create a.env file:
Step 4: Run Migration (Optional)
If you have an existingmcp_settings.json file, migrate it:
Step 5: Start MCPHub
Migration from File-Based to Database
MCPHub provides automatic migration on first startup when database mode is enabled. However, you can also run the migration manually.Automatic Migration
When you start MCPHub withUSE_DB=true for the first time:
- MCPHub connects to the database
- Checks if any users exist in the database
- If no users found, automatically migrates from
mcp_settings.json - Creates all tables and imports all data
Personal credential bindings
Personal credentials and personal upstream OAuth bindings are imported from the settings file’s.credentials.json sidecar independently of user migration, including when database users already exist. Keep the original .credentials.key at the same settings path, or set its exact value as MCPHUB_CREDENTIAL_ENCRYPTION_KEY before switching modes. Do not generate a replacement key.
Before importing a new batch, MCPHub verifies that the new source bindings and all existing database bindings decrypt with the same configured key. Missing or incompatible keys abort startup before configuration migration; restore the original key and retry. Imports are transactional and never overwrite existing (serverName, username) bindings.
The internal credential_binding_imports table records processed ciphertext so retained source files do not restore bindings deleted later. Keep these receipts when clearing credential_bindings during recovery. Source files remain unchanged; back up the key separately from the database. See Credential Key Upgrade and Recovery.
Manual Migration
Run the migration script:- ✅ Create database tables if they don’t exist
- ✅ Import all users with hashed passwords
- ✅ Import all MCP server configurations
- ✅ Import all groups
- ✅ Import system configuration
- ✅ Import user-specific configurations
- ✅ Skip existing records (safe to run multiple times)
Configuration After Migration
Once running in database mode, all configuration changes are stored in the database:- User management via
/api/users - Server management via
/api/servers - Group management via
/api/groups - System settings via
/api/system/config
mcp_settings.json is used as a one-time seed when database mode is initialized. After the initial migration, PostgreSQL is the authoritative configuration source; later edits to mcp_settings.json are not imported automatically. Use the dashboard, API, or CLI to manage configuration in database mode, or opt into the startup sync below.
Declarative servers and groups (GitOps)
SetMCPHUB_SETTINGS_SYNC=upsert in database mode to reconcile mcpServers and groups from mcp_settings.json on every startup. MCPHUB_SETTING_PATH can point to a read-only ConfigMap mount. Update the file and restart MCPHub to apply changes; there is no file watcher or SIGHUP handler.
- Entries match by their globally unique names. Existing IDs are retained. The file wins even when the same-name entry was created or edited through the dashboard.
- The entire declared entry controls its configuration: omitted optional fields are cleared or reset to defaults. Servers default to enabled and private. Group memberships, aliases, selections, and pinned tools come from the declaration.
- On adoption, an omitted
ownerclears the existing owner, including a non-admin owner. Declareownerexplicitly to retain ownership. OmittedsharedWithUsersis cleared as well. Review these fields before enabling sync on an existing deployment. - In
upsertmode, entries absent from the file remain untouched. Removing or renaming an entry does not delete the old database entry. - In
upsertmode, only server/group declarations are reconciled. Users, bearer keys, MCPHub OAuth clients/tokens, personal credential bindings, system configuration, and other runtime data remain in the database. The existing first-boot seed migration still applies on an empty user table. - Upstream OAuth tokens and pending authorization supplied in the file are ignored by sync. Existing upstream OAuth state (including dynamically registered client credentials) is retained while the connection target and OAuth declaration are unchanged. Changes to either clear the old state and may require authorization again. A nullable internal
settingsSyncHashcolumn on servers detects declaration changes, including removed OAuth fields and expanded environment values, without storing resolved secrets. Fingerprints use PBKDF2-SHA256 with 600,000 iterations and a random salt per server; the existing salt is reused on subsequent startups. - On first adoption for an existing server, OAuth state is retained only if the target matches and every explicitly declared OAuth field matches its stored value. Undeclared discovered OAuth fields are retained until the declaration changes.
- Environment placeholders remain unexpanded in persisted declarations and use the existing runtime expansion. JSON must be valid; duplicate group names, malformed declarations, missing files, unsupported sync modes, or database errors fail startup. Server/group writes are applied in one transaction.
MCPHUB_SETTINGS_SYNC unset to retain the existing one-time seed behavior. This switch applies only in database mode. Sync never writes back to the settings file, including during the initial seed in this mode.
Server IDs and tool policies
Sync matches existing entries by name. Before using a server ID in a tool policy, retrievedata.config.id from GET /api/servers/:name and pin that exact value in the declaration:
time to clock, change the entry name but retain its id; update group references too. Without a pinned ID, the new name receives a different identity: old server-scoped deny rules no longer restrict it, and in prune mode the old entry and its runtime credentials are deleted. Pinning preserves the policy identity, not a promise to migrate name-bound personal credentials or other references; review those separately. A same-name declaration with a different id retains the database ID and logs a conflict warning. Startup logs missing policy references after sync; review those warnings before relying on the rules.
Pruning managed entries
SetMCPHUB_SETTINGS_SYNC=prune to upsert declarations and delete previously managed servers/groups that are no longer declared. This is opt-in; upsert and the unset mode retain their existing behavior.
- Both sync modes mark declared entries as internally managed, including same-name entries adopted from the dashboard. Dashboard edits do not release that ownership. Unmanaged entries remain untouched, so this is not a full database mirror.
- Omit
mcpServersorgroupsto leave that collection unpruned. ExplicitmcpServers: {}orgroups: []prunes all managed entries in that collection. Renaming a managed entry creates the new entry and deletes the old one, including its runtime credentials. - Servers synced by older versions are recognized by their existing declaration fingerprint. Older groups have no ownership marker: declare them once with either sync mode before removing them. Historical groups already removed from the file require manual deletion.
- Pruning removes personal credential bindings and server/tool embeddings for deleted servers, and removes their references from retained, undeclared groups. A declared group referencing a server being pruned fails startup instead of silently changing its declaration. Users, bearer-key scopes, MCPHub OAuth clients/tokens, and system configuration are not pruned.
- All upserts, deletions, reference updates, and credential/embedding cleanup share one transaction. Invalid declarations or database failures roll back that transaction and fail startup. Missing optional vector storage is skipped. Sync still runs only at startup and never writes to the settings file.
prune: deletion is permanent, and re-adding a server does not restore its credentials.
Database Schema
MCPHub creates the following tables:- users - User accounts and authentication
- servers - MCP server configurations
- groups - Server groups
- system_config - System-wide settings
- user_configs - User-specific settings
- vector_embeddings - Vector search data (for smart routing)
Backup and Restore
Backup
Restore
Switching Back to File-Based Config
If you need to switch back to file-based configuration:- Set
USE_DB=falseor removeDB_URLandUSE_DBenvironment variables - Restart MCPHub
- MCPHub will use
mcp_settings.jsonagain
Troubleshooting
Connection Refused
Authentication Failed
DB_URL environment variable.
Migration Failed
- Check that
mcp_settings.jsonexists and is valid JSON - Verify database connection
- Check logs for specific error messages
- Ensure database user has CREATE TABLE permissions
Tables Already Exist
Database tables are automatically created if they don’t exist. If you get errors about existing tables, check:- Whether a previous migration partially completed
- Manual table creation conflicts
- Run with
synchronize: falsein database config if needed
Environment Variables Reference
*Required for database mode. Simply setting
DB_URL enables database mode automatically
Security Considerations
- Database Credentials: Store database credentials securely, use environment variables or secrets management
- Network Access: Restrict database access to MCPHub instances only
- Encryption: Use SSL/TLS for database connections in production:
- Backup: Regularly backup your database
- Access Control: Use strong database passwords and limit user permissions
Performance
Database mode offers better performance for:- Multiple concurrent users
- Frequent configuration changes
- Large number of servers/groups
- Single user setups
- Read-heavy workloads with infrequent changes
- Development/testing environments