English | 简体中文
A multi-database MCP server for Model Context Protocol (MCP), written in TypeScript.
It supports MySQL, PostgreSQL, Oracle, openGauss, and Redis, with lazy short-lived connections, read-oriented database tools, SQL plan analysis, config reload, and guarded write execution.
This project is intended for AI agents and MCP clients that need safe database discovery, querying, performance analysis, and controlled write operations.
Install from npm:
npm install -g @jadchene/mcp-database-service
mcp-database-service --config ./config/databases.example.jsonRun from source:
npm install
npm run build
node dist/index.js --config ./config/databases.example.jsonFor AI assistants (Codex / Gemini / similar agents), this repository includes a database MCP skill that improves workflow consistency and write safety.
- Skill path:
skills/database-mcp/SKILL.md - Benefits:
- Standardized database discovery and schema inspection flow
- Query-first defaults with safer result-size and column-selection behavior
- Clear two-step confirmation discipline for write operations
When your agent supports skills, load this skill before using database MCP tools for best results.
| Database | Query Tools | Metadata Tools | explain_query |
analyze_query |
Write Support |
|---|---|---|---|---|---|
| MySQL | Yes | Yes | Yes | Yes | Yes |
| PostgreSQL | Yes | Yes | Yes | Yes | Yes |
| openGauss | Yes | Yes | Yes | Yes | Yes |
| Oracle | Yes | Yes | Yes | No | Yes |
| Redis | Yes | Limited to Redis tools | No | No | No |
Notes:
- show_create_table currently supports MySQL and Oracle. PostgreSQL and openGauss currently return NOT_SUPPORTED.
- Operational tools such as
show_variables,find_long_running_queries,find_blocking_sessions, andshow_locksdepend on the visibility and privileges of the configured database account.
- MySQL
- Oracle
- PostgreSQL
- openGauss (via PostgreSQL protocol compatibility)
- Redis
- Multiple named database targets in a single config file
- Optional file logging with configurable output directory
- Manual config reload without restarting the MCP server
- Automatic config reload when the JSON file changes on disk
- Strict read-only enforcement for query tools
- Optional write execution with explicit MCP confirmation for writable targets
- Lazy connections with guaranteed cleanup after each request
- Metadata discovery tools for SQL databases
- Dedicated read tools for Redis
Provide the config path by one of these methods:
node dist/index.js --config ./config/databases.json- Set
MCP_DATABASE_CONFIG=/absolute/path/to/databases.json
The configuration file must be a JSON object with a required top-level databases array. Optional top-level sections such as logging and query may also be provided. Example:
{
"logging": {
"enabled": true,
"directory": "./logs"
},
"query": {
"timeoutMs": 5000
},
"databases": [
{
"key": "main-mysql",
"type": "mysql",
"readonly": true,
"connection": {
"host": "127.0.0.1",
"port": 3306,
"databaseName": "app_db",
"user": "root",
"password": "secret",
"connectTimeoutMs": 5000
}
}
]
}logging.enabled defaults to false. When enabled, logs are written to the system temporary directory by default. You can override that with logging.directory, and relative paths are resolved relative to the config file location. In the example above, logs are written under ./logs.
query.timeoutMs is optional. When set, the server applies a query timeout to database operations. In the example above, queries time out after 5000 milliseconds.
Oracle supports both Thin and Thick mode. Thick mode uses the same oracledb package, but requires Oracle Instant Client on the host machine. Example:
{
"key": "oracle-thick-example",
"type": "oracle",
"readonly": true,
"connection": {
"host": "127.0.0.1",
"port": 1521,
"serviceName": "XEPDB1",
"user": "system",
"password": "secret",
"clientMode": "thick",
"clientLibDir": "C:\\oracle\\instantclient_19_25"
}
}show_loaded_config: show the current in-memory config path, load time, and all configured database targetsreload_config: reload the JSON config file currently in use and atomically replace the in-memory configuration on successlist_databases: list all configured target keys and logical database names without opening database connectionsping_database: test connectivity for one configured targetlist_schemas: list schemas for one SQL targetlist_tables: list tables/views under one SQL schema or the default schemalist_views: list views under one SQL schema or the default schemadescribe_table: inspect columns before writing joins, reports, or optimization SQLshow_create_table: inspect exact database-side DDL when the current database supports itsearch_tables: search tables or views by partial namesearch_columns: search columns by partial name across a schemalist_indexes: inspect table indexes for performance analysisget_table_statistics: inspect approximate row counts, storage metrics, and database-specific table statisticsshow_variables: inspect database runtime configuration variablesfind_long_running_queries: inspect currently running sessions above a duration thresholdfind_blocking_sessions: inspect current blocking relationships between sessionsshow_locks: inspect current lock rows exposed by the databaseexecute_query: run one read-only SQL query; pass the original query SQL, not write SQLexplain_query: get the static execution plan for one read-only SQL query; pass the original query SQL, notEXPLAIN ...analyze_query: get runtime analysis for one read-only SQL query; pass the original query SQL, notEXPLAIN ANALYZE ...execute_statement: run one non-query SQL statement on a writable target after explicit manual confirmationredis_get: read one Redis string keyredis_hgetall: read one Redis hash keyredis_scan: cursor-scan Redis keys safely with an optional pattern
npm install
npm run build
node dist/index.js --config ./config/databases.example.jsonThis project exposes a CLI command named mcp-database-service through the package bin field.
Recommended options:
- Install from npm:
npm install -g @jadchene/mcp-database-service- Or install from the local source tree with the helper script:
pwsh -File .\scripts\install-global.ps1Or on Linux/macOS:
sh ./scripts/install-global.shThe helper scripts install dependencies, build the project, create a tarball with npm pack, install that tarball globally with npm install -g <tarball>, and then delete the temporary tarball. They do not use npm link.
- Or install the packed tarball manually:
npm pack
npm install -g .\jadchene-mcp-database-service-0.1.5.tgzThe package only publishes runtime files through the files field, so packaged installation includes dist and the runtime README/config example, not the whole source tree.
After installation, the command can be used like this:
mcp-database-service --config .\config\databases.example.jsonExample MCP server configuration:
{
"mcpServers": {
"database": {
"command": "mcp-database-service",
"args": [
"--config",
"C:\\path\\to\\databases.json"
]
}
}
}The following examples show how to register this MCP server in common AI clients. Replace the config path with your own local file path. To keep the setup portable, the examples below intentionally avoid absolute paths.
~/.codex/config.toml
[mcp_servers.database]
command = "mcp-database-service"
args = ["--config", "./config/databases.json"]~/.gemini/settings.json
{
"mcpServers": {
"database": {
"type": "stdio",
"command": "mcp-database-service",
"args": [
"--config",
"./config/databases.json"
]
}
}
}~/.claude.json
{
"mcpServers": {
"database": {
"type": "stdio",
"command": "mcp-database-service",
"args": [
"--config",
"./config/databases.json"
]
}
}
}- The server loads the JSON config file at startup and keeps a validated in-memory snapshot.
- The server also watches the same JSON file and automatically reloads it after on-disk changes are detected.
- Automatic reload is debounced to avoid reloading half-written files too aggressively.
- You can still use
reload_configto force a manual reload without restarting the process. - Reload is atomic: if the new file is invalid, the old in-memory configuration remains active.
show_loaded_configcan be used to inspect the current config path, load time, and configured database targets.show_loaded_configalso includes the current logging status, resolved log directory, and configured query timeout.show_loaded_configalso includes a sanitized connection summary for each target, such as host, port, databaseName or serviceName, user name, and Oracle client mode, but it never exposes passwords.
- Thin mode is the default when
clientModeis omitted. - Thick mode requires
clientMode: "thick"and a validclientLibDir. - All Oracle targets in one process must use the same client mode. Thick mode targets must also share the same
clientLibDir. analyze_queryis currently not supported for Oracle and will returnNOT_SUPPORTED.
execute_queryremains read-only and blocks non-query SQL.execute_statementis intended for writable SQL targets only.execute_statementrequiresreadonly: falseon the target database config.- Before executing a non-query SQL statement, the server asks the MCP client for explicit user confirmation through MCP elicitation when the client supports it.
- If the MCP client does not support elicitation,
execute_statementautomatically falls back to a two-step confirmation flow: the first call returns confirmation details and aconfirmationId, and the second call must resend the same SQL withconfirmationIdandconfirmExecution: trueafter the user confirms. execute_statementconfirmation includes SQL type, target object, SQL preview, parameter preview, and risk hints for dangerous statements.