Content
# database-mcp
A Rust [MCP](https://modelcontextprotocol.io) server that lets a model talk to your relational databases (PostgreSQL, MySQL/MariaDB, SQLite) without giving it a footgun. Every statement is parsed before it runs, so a stray `DROP TABLE` from the LLM never reaches production.
## What it does
- **Multi-connection** — declare any number of databases in a single TOML; the LLM picks one by name.
- **Per-connection access modes** — `read_only` (SELECT/EXPLAIN), `read_write` (DML) or `admin` (DDL).
- **Real SQL parsing** with `sqlparser` — one statement per call, no stacking, no comment tricks.
- Configurable **row limit** and **statement timeout** (defaults: 1000 rows, 5 s).
- Schema **introspection** built-in (`list_tables`, `describe_table`).
## Tools
| Tool | Purpose |
|------|---------|
| `list_connections` | List configured connections + their access mode |
| `list_tables` | List tables/views in a connection |
| `describe_table` | Columns, types, nullability |
| `query` | Run a read statement (SELECT/EXPLAIN). Row-capped. |
| `execute` | Run a write statement (INSERT/UPDATE/DELETE/MERGE). Needs `read_write`+ |
## Install
Universal one-liner (Linux/macOS) — auto-detects your distro and uses the native package:
```sh
curl -fsSL https://github.com/SergioRibera/database-mcp/releases/latest/download/install.sh | sh
```
| Distro | Format | Installer used |
|-----------------------------------|-------------------|----------------|
| Debian / Ubuntu / derivatives | `.deb` | `apt-get install` |
| Fedora / RHEL / CentOS / Rocky | `.rpm` | `dnf install` |
| openSUSE / SLES | `.rpm` | `zypper install` |
| Arch / Manjaro / EndeavourOS | `.pkg.tar.zst` | `pacman -U` |
| Anything else | `tar.gz` | extract to `$HOME/.local/bin` |
Use `--format <fmt>` to override, `--uninstall` to remove. See `--help`.
Windows (PowerShell, installs the MSI service-wide):
```powershell
iwr https://github.com/SergioRibera/database-mcp/releases/latest/download/install.ps1 -OutFile install.ps1; .\install.ps1
```
Pass `-Format zip` for a portable `.exe` in `%LOCALAPPDATA%\Programs\database-mcp`. `-Uninstall` removes it.
From source:
```bash
cargo install --git https://github.com/SergioRibera/database-mcp
```
Reproducible via Nix (same flake CI uses):
```bash
nix build github:SergioRibera/database-mcp#linux-x86_64
nix build github:SergioRibera/database-mcp#windows-x86_64 # cross-compiled via mingw
nix build github:SergioRibera/database-mcp#release # full matrix + install scripts
```
## Configure
Drop a TOML at the default location (`/etc/database-mcp/config.toml` on Linux/macOS, `%PROGRAMDATA%\database-mcp\config.toml` on Windows) — or pass `--config <path>` / set `DATABASE_MCP_CONFIG`:
```toml
[server]
default_row_limit = 1000
statement_timeout_ms = 5000
max_pool_size = 5
[[connections]]
name = "prod"
url = "postgres://user:pass@host:5432/app"
mode = "read_only"
[[connections]]
name = "warehouse"
url = "mysql://user:pass@host:3306/dw"
mode = "read_write"
allowed_schemas = ["reporting"]
[[connections]]
name = "local"
url = "sqlite:./data.db"
mode = "admin"
```
URLs: `postgres://`, `postgresql://`, `mysql://`, `mariadb://`, `sqlite:` (incl. `sqlite::memory:`).
## Inline config (no file needed)
Every setting can be passed as flags, so the MCP client can declare connections without touching disk:
```
--connection NAME=URL[;mode=read_only|read_write|admin][;schema=a,b] (repeatable)
--row-limit N
--statement-timeout-ms MS
--max-pool-size N
```
Notes:
- `mode` defaults to `read_only`. Accepts `ro`/`rw` shortcuts.
- URLs cannot contain `;` (percent-encode if needed).
- If both `--config` and `--connection` are given, file is base and CLI connections are appended (duplicate names error out). Server flags override file values.
- If neither is given, the default config path is tried; if that file is missing too, the server exits with an explanatory error.
## Use with Claude Code
File-based:
```json
{
"mcpServers": {
"database": {
"command": "database-mcp",
"args": ["--config", "/etc/database-mcp/config.toml"]
}
}
}
```
Inline (no file):
```json
{
"mcpServers": {
"database": {
"command": "database-mcp",
"args": [
"--connection", "prod=postgres://user:pass@host/db;mode=read_only",
"--connection", "local=sqlite::memory:;mode=admin",
"--row-limit", "500"
]
}
}
}
```
## Remote mode (HTTP/TLS)
By default the server speaks JSON-RPC over stdio. Pass `--http <addr>` to expose it over HTTPS so a remote MCP client (or a hosted agent) can talk to it.
```bash
database-mcp \
--http 0.0.0.0:8443 \
--token "$(openssl rand -hex 32)" \
--tls-cert /etc/database-mcp/tls/cert.pem \
--tls-key /etc/database-mcp/tls/key.pem \
--connection 'prod=postgres://user:pass@db/app;mode=read_only'
```
- Transport: `POST /mcp` with a JSON-RPC body. TLS via rustls (ring, TLS 1.2+ and 1.3, ALPN `h2`/`http/1.1`).
- Auth: `Authorization: Bearer <token>` required. Token is read from `--token`, the `DATABASE_MCP_TOKEN` env var, or `http.token` in the TOML — empty tokens are rejected.
- Certificates: if `--tls-cert`/`--tls-key` aren't given, the server tries `/etc/database-mcp/tls/{cert,key}.pem`, then `/etc/ssl/certs/database-mcp.pem` + `/etc/ssl/private/database-mcp.key`. If none exist it refuses to start.
- `--insecure-http` serves plaintext — only safe behind a reverse proxy that terminates TLS.
Client side (any HTTP MCP client):
```json
{
"mcpServers": {
"database-remote": {
"url": "https://db-mcp.example.com:8443/mcp",
"headers": { "Authorization": "Bearer YOUR_TOKEN" }
}
}
}
```
## Run as a service
The `.deb`, `.rpm` and `.pkg.tar.zst` packages ship a hardened **systemd** unit; the `.msi` registers a **Windows service** (`DatabaseMcp`). Both are installed but **not auto-started** — you need to drop the config in place first.
```bash
# Linux: install the package, write the config, then start
sudo install -d /etc/database-mcp
sudo install -m 0600 config.toml /etc/database-mcp/config.toml
sudo systemctl enable --now database-mcp
```
```powershell
# Windows: drop config under ProgramData, then start the service
New-Item -ItemType Directory -Path "$env:PROGRAMDATA\database-mcp" -Force
Copy-Item config.toml "$env:PROGRAMDATA\database-mcp\config.toml"
Start-Service DatabaseMcp
```
Docker:
```bash
docker build -t database-mcp .
docker run -i --rm -v /etc/database-mcp:/etc/database-mcp:ro database-mcp
```
## Security
- The config file holds connection URLs — protect it (`chmod 0600`, restrict ACLs).
- `read_only` is the default if `mode` is omitted.
- Multi-statement input is rejected by the parser before any database is touched.
- The DB role in the URL is still your last line of defense — grant least privilege.
## License
MIT.
Connection Info
You Might Also Like
Train-in-Silence
The first Task-Aware MCP server and automated VRAM calculator for LLM...
stacklit
108,000 lines of code. 4,000 tokens of index. One command makes any repo...
AppClaw
AI-powered mobile automation agent — describe what you want in plain...
pdf-mcp
Production-ready MCP server for PDF processing with intelligent caching....
kotadb
Local-only code intelligence API for AI developer workflows (Bun +...
gemini-api-docs-mcp
A remote HTTP MCP server for searching Google Gemini API documentation.