Skip to main content
Glama

mcp-dbserver

一个自建的 MCP 服务器,让 AI 智能体——Claude Code、Claude Desktop,或任何兼容 MCP 的客户端——同时获得对三种数据库引擎的只读、安全范围受限的访问:PostgreSQL(含 pgvector)、DynamoDB 和 MongoDB Atlas(含 Atlas Vector Search)。这是一个个人项目,将 17 年以上的多云数据库架构工作经验延伸到 AI/智能体工具领域:目标不是“让智能体能够查询数据库”,而是展示生产级参考架构会要求的同样的最小权限与纵深防御纪律,只不过调用方是 LLM 而非服务。

本仓库中不出现任何雇主数据、模式或业务逻辑(无论当前还是以前的雇主)——只有专门为本项目生成的公开或合成数据。

架构

flowchart LR
    Client["MCP client<br/>(Claude Code / Claude Desktop)"]

    subgraph Server["mcp-dbserver (stdio)"]
        direction TB
        Tools["Fixed tool surface<br/>(no generic 'run query' tool)"]
        Guard["guardrails.py + allowlist.py<br/>read-only + row-limit re-check"]
        Tools --> Guard
    end

    Client -- "MCP tool calls" --> Tools

    Guard --> PG[("PostgreSQL + pgvector<br/>RDS, IAM or password auth")]
    Guard --> DDB[("DynamoDB<br/>fixed table-target registry")]
    Guard --> Mongo[("MongoDB Atlas + Vector Search<br/>fixed collection-target registry")]

每个指向数据库的箭头都是一个具名、列入白名单的操作——绝不是原始 SQL、原始的 MongoDB 筛选器或原始的 DynamoDB 键条件。完整设计见 ARCHITECTURE.md。

Related MCP server: Company Data MCP Server

安全模型

这部分是该项目与典型的“让智能体连上数据库”演示的区别所在。完整细节(包括两项不是靠设计而是通过实际测试护栏发现的问题)见 ARCHITECTURE.md——摘要如下:

  1. 只读,没有例外。 v1 中任何引擎都不存在写、更新或删除工具。如果将来出现支持写入的版本,那将是一个拥有自己威胁模型的独立项目。

  2. 通过测试发现、并有文档记录的安全边界。 “无写入工具”这一护栏约束的是智能体通过 MCP 协议能做的事。它无法约束一个具备代码能力的客户端(例如 Claude Code,不同于仅支持聊天的客户端如 Claude Desktop),如果该客户端能独立访问相同的凭据。在测试中,Claude Code 正确地发现没有删除工具——然后自己编写了一个 psycopg 脚本,绕过 MCP 服务器直接尝试删除。它之所以失败,仅仅是因为配置的数据库角色缺少写权限。这使得 数据库级/IAM 级的只读角色 成为对抗具备代码能力的客户端的真正最后一道防线,而不是此代码中缺少写入方法——这一点被明确记录,而非隐式假设。

  3. 不允许智能体发起原始查询。 每个操作都是具名、列入白名单的形态,带有类型化参数——固定的 SQL 模板(Postgres)、固定的表/集合目标注册表加类型化键(DynamoDB/MongoDB)——绝不采用由智能体输入构建的筛选文档、键条件表达式或 SQL 字符串。向量搜索工具的一个早期草稿曾将表/列名作为直接参数,在服务器接入真实客户端之前就被发现并修复(一个通过 f-string 插值形成的真实的 SQL 注入面)。

  4. 执行时的纵深防御。 即使是列入白名单的 Postgres 查询,在运行前也会由 guardrails.py 重新校验(拒绝任何不是 SELECT/WITH 的内容,拒绝堆叠语句,并且无论请求什么都会强制行数上限),同时每个连接都在数据库层面设置 default_transaction_read_only = on。

  5. 凭据:仅通过环境变量提供,绝不记录,绝不硬编码。支持 RDS IAM 数据库身份验证,并且它优先于存储的 Postgres 密码(通过 rds:GenerateDBAuthToken 为每个连接生成一个有效期约 15 分钟的新令牌,完全没有长期有效的数据库机密)。

支持的引擎与工具

引擎

工具

PostgreSQL + pgvector

query_postgres, list_postgres_queries, semantic_search_documents

DynamoDB

list_dynamodb_tables, get_dynamodb_item, list_dynamodb_items, count_dynamodb_items

MongoDB Atlas + Vector Search

list_mongodb_collections, get_mongodb_document, list_mongodb_documents, count_mongodb_documents, semantic_search_mongodb

每个工具的完整描述及其背后的理由见 ARCHITECTURE.md。semantic_search_documents 和 semantic_search_mongodb 针对同一演示数据集和同一本地嵌入模型运行,目的就是让 pgvector 和 Atlas Vector Search 的结果可以直接比较。

设置

python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
cp .env.example .env   # fill in your own, personal, non-work credentials

运行测试套件(无需真实数据库——护栏/白名单逻辑已针对全部三种引擎的假实现进行了单元测试):

pytest

运行 MCP 服务器(stdio 传输,供 Claude Code / Claude Desktop 本地使用):

mcp-dbserver

只有设置了所需环境变量的引擎才会注册相应的工具——例如,仅设置 POSTGRES_DSN 时,只会出现 Postgres 工具。每个引擎所需的全部变量见 .env.example。

Postgres 演示数据集

data/demo_documents.jsonl 是一小组合成的约 30 条简短软件/基础设施说明片段(为本项目编写)。加载它并在本地生成嵌入(fastembed 的 ONNX 运行时——离线,无需外部 API 密钥,不依赖 torch/torchvision):

python scripts/load_demo_dataset.py
python scripts/smoke_test_postgres.py      # connectivity + read-only guardrail
python scripts/verify_demo_dataset.py      # row count + semantic search sanity check

DynamoDB

表不是通过环境变量配置的——可访问的表来自 engines/dynamodb.py 中的固定注册表(_TABLE_TARGETS)。设置 AWS_REGION(以及通过环境变量/配置文件/实例角色提供的标准 AWS 凭据,范围限定为已注册表 ARN 上的 dynamodb:GetItem/Scan/DescribeTable)即可启用 *_dynamodb_* 工具。

MongoDB Atlas 演示数据集

与 Postgres 的设置完全一致——相同的数据集、相同的嵌入模型——因此结果可以直接比较。设置 MONGODB_URI/MONGODB_DATABASE(Atlas 用户使用内置的 read 角色,而不是 readWrite),然后:

python scripts/load_demo_dataset_mongodb.py    # upserts data + creates the Atlas Vector Search index
python scripts/verify_demo_dataset_mongodb.py  # index builds asynchronously; re-run if search comes back empty

项目结构

src/mcp_dbserver/
  guardrails.py        # read-only + row-limit enforcement, engine-agnostic
  allowlist.py          # named, parameterized Postgres query registry
  config.py              # env-var credential loading, per engine
  engines/
    postgres.py           # allowlisted queries + pgvector semantic search
    dynamodb.py             # fixed table-target registry, get/scan/count
    mongodb.py                # fixed collection-target registry, get/list/count/$vectorSearch
  server.py             # MCP entrypoint, registers tools per configured engine
tests/                   # guardrail/allowlist/engine unit tests, all three engines (no live DB needed)
scripts/                 # demo dataset loaders/verifiers, Postgres smoke test

若面向生产规模,我会做哪些不同

明确说明 v1 刻意不解决哪些问题,比假装它已生产就绪更有意义:

  • 客户端 ↔ 服务器身份验证。 v1 通过 stdio 运行,由客户端直接作为子进程启动——操作系统进程边界就是信任边界,这对本地单用户使用没问题,对其他任何场景都不够。任何网络化部署(HTTP/SSE,可被多个客户端访问)都需要为每个客户端提供按引擎限定权限的 API 密钥,并在服务器前做 TLS 终止,否则它就只能算是一个演示。

  • 可观测性。 目前还没有查询日志或指标。在任何网络化部署之前,至少需要记录:哪个具名查询/操作被调用、何时调用、是否成功——刻意永远不记录参数值或行内容,以免在日志中悄悄形成数据的第二份副本。

  • 速率限制。 尚未实现;只有当服务器可被不止一个本地 stdio 客户端访问时才重要,但这是一个值得明确指出的缺口,而不是等到负载下才发现。

  • MySQL。 明确不在 v1 范围内。如果加入,将沿用与 Postgres 相同的白名单 + 护栏模式——无需新设计,只是第四个引擎所需的管道工作。

  • DynamoDB/MongoDB 的筛选形态问题最终比计划中更简单,而不是更复杂。 最初的设计考虑过为 DynamoDB/MongoDB 的每个列入白名单的筛选器提供类型化模式。最终发布的方案更精简:一个固定的目标注册表,加上每个引擎固定的一小组具名操作,完全没有通用的 find(filter) 或 query(key_condition) 工具。值得指出的是,构建验证 DSL 的本能是听起来更“厉害”的选择,而更简单的方案最终被证明能更可靠地填补同样的缺口——$where 或任意键条件没有宽松形态可藏身,因为根本没有这样的字段。

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Provides read-only access to PostgreSQL databases via MCP, enforcing least-privilege roles, row-level security, masked views, and SQL AST guardrails to prevent data leakage and unauthorized operations, enabling AI agents to safely query sensitive production data.
    MIT
  • F
    license
    Not graded
    quality
    C
    maintenance
    Enables read-only access to company data across PostgreSQL, MongoDB Atlas, and flat files through MCP tools, allowing AI assistants to query and retrieve information via natural language.
    -
  • A
    license
    Not graded
    quality
    A
    maintenance
    Provides fail-closed, read-only PostgreSQL and MongoDB access for AI agents via MCP, enabling structured data inspection and bounded queries without mutation capabilities.
    MIT