MCP-DB-Server

MCP-DB-Server

Enables natural language querying of SQL databases with robust safety guarantees including read-only enforcement, AST validation, and row caps.

Category
访问服务器

README

<p align="center"> <img src="assets/banner.svg" alt="mcp-db-server" width="100%"> </p>

<p align="center"> <a href="https://github.com/sujalsamkaria0066/mcp-db-server/actions/workflows/ci.yml"><img src="https://github.com/sujalsamkaria0066/mcp-db-server/actions/workflows/ci.yml/badge.svg" alt="CI"></a> <img src="https://img.shields.io/badge/python-3.11%2B-blue" alt="Python"> <img src="https://img.shields.io/badge/coverage-97%25-brightgreen" alt="Coverage"> <img src="https://img.shields.io/badge/license-MIT-green" alt="License"> <img src="https://img.shields.io/badge/MCP-server-8A2BE2" alt="MCP"> </p>

A production-grade MCP server that lets any LLM client (Claude Desktop, Cursor, …) query a SQL database in natural language — read-only, AST-validated, and capped.

The LLM writes the SQL. This server never trusts it. Every query is parsed to an abstract syntax tree and forced through a safety gate before it is allowed near a read-only database connection.

<p align="center"> <img src="assets/demo.svg" alt="Demo: list tables, query top customers, refused DROP" width="100%"> </p>

Why this exists

Letting an LLM run SQL against your database is powerful and terrifying in equal measure. The hard part isn't generating SQL — clients already do that well. The hard part is guaranteeing the generated SQL can't read what it shouldn't, can't write, and can't run away with your database. That guarantee is this project.

Safety guarantees

Every run_query call must pass the Safety Core before execution:

  • Read-only — only SELECT / WITH … SELECT survive; all DML/DDL is rejected at the AST level (not by keyword regex, so comment and casing tricks don't help).
  • Single statement — stacked queries (SELECT …; DROP …) are rejected.
  • Table access control — allow-list and deny-list enforced against the parsed tables.
  • Row caps — a LIMIT is injected/enforced at MCP_DB_MAX_ROWS.
  • Statement timeout — long queries are aborted.
  • Audit log — every attempt (allowed or blocked) is logged.

These aren't aspirations — each is pinned by an adversarial test in tests/test_safety.py (casing tricks, comment injection, stacked statements, SELECT … INTO, PRAGMA/ATTACH, and more). A second, independent layer is proven in tests/test_engine.py: even a write that somehow reached the engine is rejected by the read-only connection.

Tools

Tool Purpose
list_tables() Tables visible under the access policy
describe_table(name) Columns, types, keys
explain_query(sql) Explains a query (and engine plan) without returning rows
run_query(sql) Validated, capped, read-only result set

Examples

You ask in plain English; the client LLM writes the SQL; the server validates, caps, and runs it read-only. Real output from the bundled demo.db:

"What's total revenue by product category?"

SELECT p.category, ROUND(SUM(oi.quantity * oi.unit_price), 2) AS revenue
FROM products p JOIN order_items oi ON oi.product_id = p.id
GROUP BY p.category ORDER BY revenue DESC;
category revenue
Electronics 85746.19
Furniture 76442.0
Apparel 39219.91
Sports 18746.5
Home 12596.5
Stationery 1663.22

"How many orders are there by status?"

SELECT status, COUNT(*) AS orders FROM orders GROUP BY status ORDER BY orders DESC;
status orders
completed 206
cancelled 79
shipped 58
pending 57

"Which products have never been ordered?"

SELECT name, category FROM products
WHERE id NOT IN (SELECT DISTINCT product_id FROM order_items);
name category
Sticky Notes Stationery
Desk Planner Stationery
Highlighter Set Stationery

"Now delete the orders table."Query rejected by safety policy: only read-only SELECT queries are allowed.

Quickstart

git clone https://github.com/sujalsamkaria0066/mcp-db-server
cd mcp-db-server
pip install -e ".[dev]"
python scripts/seed_db.py     # creates demo.db (e-commerce sample data)

Try it in 30 seconds (no MCP client needed)

The bundled mcp-db-demo CLI drives the exact same service the MCP server exposes — so what you see here is what an LLM client gets:

mcp-db-demo tables
mcp-db-demo describe customers
mcp-db-demo query "SELECT country, COUNT(*) FROM customers GROUP BY country ORDER BY 2 DESC"

# the safety layer in action — every one of these is refused:
mcp-db-demo query "UPDATE products SET price = 0"
mcp-db-demo query "SELECT * FROM customers; DROP TABLE customers"

Use it in Claude Desktop

Add the server to your claude_desktop_config.json, then fully restart Claude Desktop.

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%\Claude\claude_desktop_config.json
{
  "mcpServers": {
    "db": {
      "command": "mcp-db-server",
      "env": {
        "MCP_DB_DATABASE_URL": "sqlite:///absolute/path/to/demo.db",
        "MCP_DB_MAX_ROWS": "1000"
      }
    }
  }
}

command must resolve to the installed mcp-db-server executable. If it isn't on Claude Desktop's PATH, use the absolute path (e.g. inside your virtualenv: .../.venv/Scripts/mcp-db-server.exe on Windows, .../.venv/bin/mcp-db-server on macOS/Linux).

Then just ask, in plain English:

"What tables are in the database?" · "Which five customers spent the most?" · "Delete the orders table" → politely refused.

Configuration

All knobs are environment variables (prefix MCP_DB_):

Variable Default Meaning
MCP_DB_DATABASE_URL sqlite:///./demo.db SQLAlchemy URL (SQLite or Postgres)
MCP_DB_MAX_ROWS 1000 Hard row cap
MCP_DB_STATEMENT_TIMEOUT_SECONDS 10 Abort slow queries
MCP_DB_ALLOWED_TABLES (empty) Allow-list; if set, only these tables
MCP_DB_DENIED_TABLES (empty) Deny-list
MCP_DB_AUDIT_LOG_PATH audit.log Audit log location

Architecture

Architecture

The client LLM does the natural-language → SQL reasoning. The server contributes the thing clients can't safely do themselves: a hard, enforced boundary around what that SQL is allowed to do. Two independent layers stand between a query and your data — the Safety Core (refuses to emit anything but a capped, read-only SELECT) and the engine (refuses to execute a write, regardless).

Project layout

src/mcp_db_server/
  config.py      # env-driven settings — every safety knob
  safety.py      # Safety Core: sqlglot AST validation (the heart)
  engine.py      # SQLAlchemy read-only access + introspection
  service.py     # shared logic behind both front-ends
  server.py      # MCP server (FastMCP, stdio)
  cli.py         # mcp-db-demo: same service, no MCP client needed
  formatting.py  # result rendering
  audit.py       # JSONL audit log
scripts/seed_db.py   # reproducible demo database
tests/               # 73 tests, 97% coverage

Development

pip install -e ".[dev]"
pytest                       # 73 tests
pytest --cov=mcp_db_server   # coverage

Optional Postgres support: pip install -e ".[postgres]" and point MCP_DB_DATABASE_URL at a postgresql://… URL.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选