dbmole-mcp
A monorepo of stdio MCP servers for databases, built on one shared connection core. Each server exposes named connections, optional SSH tunnels, and runtime connection management: you add, edit, and remove connections through MCP tools without restarting the harness. Both ship as an npx package and a Docker image, so they run anywhere your MCP client does.
Packages
| Package | Backend | Install |
|---|---|---|
| dbmole-mcp | PostgreSQL, MySQL | npx -y dbmole-mcp |
| esmole-mcp | Elasticsearch 7.x and 8.x | npx -y esmole-mcp |
Each package README documents its tools, connection fields, and Docker image in full. This page covers what the two servers share.
Quick start
Add either server — or both — to your client's .mcp.json:
{
"mcpServers": {
"dbmole": { "command": "npx", "args": ["-y", "dbmole-mcp"] },
"esmole": { "command": "npx", "args": ["-y", "esmole-mcp"] }
}
}
That is enough to start a server. With no connections configured it still runs;
register one at runtime with add_connection, or supply connections up front
through one of the sources below.
Shared design
Both servers inherit the same connection model from @dbmole/core.
Connection sources. Connections merge from three layers, highest priority
first. The prefix is DBMOLE_ for dbmole and ESMOLE_ for esmole.
| Priority | Source | How to set | Mutable at runtime |
|---|---|---|---|
| High | <PREFIX>_CONNECTIONS env |
JSON array of connection objects | No (read-only) |
| Medium | Config file | --config <path> or <PREFIX>_CONFIG, shape { "connections": [...] } |
No (read-only) |
| Low | Persistent store | ~/.config/<server>/connections.json (mode 0600); override with <PREFIX>_STORE |
Yes (via tools) |
Reads resolve name collisions by layer priority, and list_connections reports
the source layer that won. The write tools — add_connection,
update_connection, remove_connection — touch only the store layer; editing a
connection from the env or a config file returns an error naming its source.
SSH tunnels. Any connection may carry an ssh block to reach a host through
a bastion. Authentication accepts a password, a private key (inline or by path,
with ~ expansion), or the SSH agent at SSH_AUTH_SOCK.
Readonly mode. A readonly: true connection blocks writes at the server, not
by trusting the caller. dbmole pins read-only transactions; esmole enforces an
HTTP method-and-path allowlist. Treat it as defence in depth — still connect with
a least-privilege user for a hard guarantee.
Persistent store. The store is a plaintext JSON file written with 0600
permissions; whoever can read it owns the credentials in it. It is re-read on
every operation, so instances sharing one store file see each other's changes at
once. For secrets you do not want the tools to persist, prefer the env or config
layer.
See each package README for the backend-specific tools, field reference, and defaults (ports, schemes, and so on).
Repository layout
packages/
core/ @dbmole/core — shared Manager, registry, SSH tunnels, MCP plumbing (private)
dbmole-mcp/ PostgreSQL and MySQL server
esmole-mcp/ Elasticsearch server
@dbmole/core is private and never published. Each leaf package bundles it at
build time, so the published artifacts have no @dbmole/core dependency.
Development
The repo is an npm workspace; run these from the root to cover every package:
npm run test:unit # fast unit tests (mocked IO)
npm run test:int # integration tests (needs Docker)
npm run coverage # unit tests with coverage
npm run typecheck # tsc across all packages
npm run lint # Biome check
npm run build # bundle each package to dist/
See AGENTS.md for the contributor style contract: code style, TypeScript discipline, testing rules, and commit conventions.