# 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](packages/dbmole-mcp/README.md) | PostgreSQL, MySQL | `npx -y dbmole-mcp` | | [esmole-mcp](packages/esmole-mcp/README.md) | 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`: ```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 | `_CONNECTIONS` env | JSON array of connection objects | No (read-only) | | Medium | Config file | `--config ` or `_CONFIG`, shape `{ "connections": [...] }` | No (read-only) | | Low | Persistent store | `~/.config//connections.json` (mode `0600`); override with `_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: ```bash 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](AGENTS.md) for the contributor style contract: code style, TypeScript discipline, testing rules, and commit conventions. ## License [MIT](LICENSE)