mcpField
Q
queryshield

queryshield

本地服务
github.com/bch1212数据库11 周前更新

关于 queryshield

QueryShield 是供 Agent 受控访问客户数据库和获准密钥的 SQL 代理与凭据库。它将问题转换为 SQL,执行 AST 校验和按 Agent 设置的行级规则,并仅记录审计元数据。

主要功能

  1. 01将自然语言问题转换为 SQL
  2. 02仅允许通过校验且带 LIMIT 的 SELECT
  3. 03实施架构、表及行级访问规则
  4. 04在加密凭据库中保存获准凭据
  5. 05记录查询尝试但不保存返回行

适用场景

  1. 01让 Agent 用自然语言查询数据库
  2. 02限制 Agent 只能访问获准的表和行
  3. 03向 Agent 提供明确授权的 API 密钥
  4. 04查看 Agent 最近的数据库访问尝试

MCP 相关

queryshield-mcp 包向 MCP 客户端提供数据库查询、凭据和审计日志工具。仓库还说明了基于 Python 模块的旧版 MCP 服务端。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"bch1212-queryshield": {
"command": "uvx",
"args": [
"queryshield-mcp"
],
"env": {
"QUERYSHIELD_API_KEY": "<QUERYSHIELD_API_KEY>",
"QUERYSHIELD_BASE_URL": "<QUERYSHIELD_BASE_URL>"
}
}
}
}
启动命令uvx queryshield-mcp
需要配置的环境变量
QUERYSHIELD_API_KEY密钥Agent API key issued by QueryShield.
QUERYSHIELD_BASE_URLOverride the default endpoint.

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
pypiqueryshield-mcp1.0.1

工具

3

收录的工具列表 · 更新于 2 周前

参数类型必填说明
max_rowsinteger否返回行数上限(默认 100,硬上限 5000)。
questionstring是自然语言问题。
database_aliasstring是此租户注册的数据库别名。

详细介绍

QueryShield

tests

Agent 安全套件。QueryShield 是核心产品:安全 SQL 代理和命名凭据保险库,一个 qs_ API 密钥、一个 Stripe 客户,以及这个文档站点。

Agent 使用自然语言(或结构化 SQL)调用单一端点。QueryShield 会:

  1. 通过 Claude 和提示词缓存将自然语言转换为 SQL。
  2. 在 AST 层级验证每条查询——只允许 SELECT,不允许堆叠语句或禁止的函数,并且必须包含 LIMIT。
  3. 应用逐 Agent 的行级安全策略:架构/表白名单和 WHERE 子句注入。
  4. 在客户的数据库上执行查询并返回行。
  5. 将每次尝试记录到仅追加审计表中——仅记录元数据,绝不记录行内容。

Agent 永远看不到连接字符串。

凭据保险库用于存储其他机密信息(Agent 获准使用的 API 令牌)。这是并入本服务的 AgentVault 产品。权限模式决定 Agent 可以读取哪些名称。数据库连接字符串存储在单独的加密存储中,无法通过保险库读取。

免费套餐/转化漏斗:InjectShield 会扫描不可信文本,检测提示词注入。它保留在自己的代码仓库(bch1212/injectshield)和自己的 API([api.injectshield.dev](https://api.injectshield.dev))中。可以从这里开始,然后在 Agent 需要数据库或保险库时创建一个 QueryShield 工作区。文档:injectshield.dev/docs。本服务上的套件页面:/suite。


快速入门

pip install -r requirements.txt
cp .env.example .env
# Set ANTHROPIC_API_KEY, DATABASE_URL, and VAULT_KEY in .env (see below).
# Do not commit .env. QueryShield reads secrets from the environment only.

python -m queryshield.start

为 VAULT_KEY 生成一次 Fernet 密钥,并妥善保管,切勿丢失。凭据加密和会话签名都需要 VAULT_KEY(或用于 Cookie 的 SESSION_KEY)。如果未设置这些密钥,相关操作会失败,而不会使用内置密钥:

python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"

端到端流程(curl)

# 1) Boot a tenant. Returns the admin API key — copy it.
curl -X POST localhost:8000/v1/tenants?name=Acme

# 2) Register the customer DB. Connection string is encrypted at rest.
curl -X POST localhost:8000/v1/databases \
  -H 'X-Admin-Key: qs_...' \
  -H 'Content-Type: application/json' \
  -d '{
    "alias": "prod",
    "db_type": "postgresql",
    "connection_string": "postgresql://READER:[email protected]:5432/app",
    "allowed_tables": ["users", "orders"]
  }'

# 3) Provision a scoped agent (different from admin) for your AI app.
curl -X POST localhost:8000/v1/agents \
  -H 'X-Admin-Key: qs_...' \
  -H 'Content-Type: application/json' \
  -d '{ "name": "reporting", "tenant_id": "<tenant>" }'

# 4) Set the agent's RLS policy.
curl -X POST localhost:8000/v1/policies \
  -H 'X-Admin-Key: qs_...' \
  -H 'Content-Type: application/json' \
  -d '{
    "agent_id": "<agent>",
    "database_alias": "prod",
    "allowed_tables": ["users", "orders"],
    "row_filters": { "users": "tenant_id = 42" }
  }'

# 4b) Store a named credential and let one agent read it.
#     The value is write-only on this call. Empty permissions grant nothing.
curl -X POST localhost:8000/v1/credentials \
  -H 'X-Admin-Key: qs_...' \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "openai_key",
    "provider": "openai",
    "value": "YOUR_SECRET"
  }'

curl -X POST localhost:8000/v1/agents \
  -H 'X-Admin-Key: qs_...' \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "writer",
    "tenant_id": "<tenant>",
    "credential_permissions": ["openai_*"],
    "budget_daily": 5
  }'

# The agent uses the same qs_ key it uses for /v1/query.
curl -X POST localhost:8000/v1/vault/get/openai_key \
  -H 'X-API-Key: qs_...'

# 5) The agent queries.
curl -X POST localhost:8000/v1/query \
  -H 'X-API-Key: qs_...' \
  -H 'Content-Type: application/json' \
  -d '{
    "database_alias": "prod",
    "query": "how many active users do we have?",
    "mode": "nl",
    "max_rows": 10
  }'

MCP 集成

已作为 io.github.bch1212/queryshield 列入官方 MCP Registry。

安装客户端:

pip install queryshield-mcp

然后将以下内容添加到 Claude Desktop / Cursor / Agent 配置中:

{
  "queryshield": {
    "command": "queryshield-mcp",
    "env": { "QUERYSHIELD_API_KEY": "qs_..." }
  }
}

独立 PyPI 软件包的源代码位于 packages/queryshield-mcp/。

对于 Glama 等 MCP 目录评估器,代码仓库根目录还包含一个精简版 Dockerfile,用于启动已发布的 queryshield-mcp stdio 服务以进行工具检查。容器在 MCP 初始化/工具发现时无需 QUERYSHIELD_API_KEY;只有在实际调用已发现的工具、访问 QueryShield API 租户时才需要该密钥。

MCP 集成(旧版)

将以下内容添加到任何支持 MCP 的客户端(Claude Desktop、Cursor、自定义 Agent)中:

{
  "queryshield": {
    "command": "python",
    "args": ["-m", "queryshield.mcp_server"],
    "env": {
      "QUERYSHIELD_API_KEY": "qs_...",
      "QUERYSHIELD_BASE_URL": "https://api.queryshield.io"
    }
  }
}

提供的工具:

  • query_database(database_alias, question, max_rows) — 自然语言查询
  • query_database_sql(database_alias, sql, max_rows) — 预构建的 SELECT
  • list_credentials() — 列出此 Agent 可读取的名称
  • get_credential(name, cost) — 使用同一 API 密钥获取一个获准读取的机密
  • get_audit_log(limit) — 查看此 Agent 最近的尝试记录

PyPI 软件包 queryshield-mcp 将在下一个版本中加入保险库工具。在此之前,本代码仓库中的 python -m queryshield.mcp_server 已可提供这些工具。


安全模型

威胁防御
Agent 构造 DROP TABLEsqlglot AST 拒绝非 SELECT 语句
Agent 偷偷加入 ; 和第二条语句解析器拒绝 len(statements) > 1
Agent 使用 pg_sleep、xp_cmdshell 等在 AST 节点层级设置函数拒绝列表
Agent 读取其范围之外的表RLS 架构 + 表白名单
Agent 读取其他租户的行通过 AST .where() 注入 row_filters
连接字符串通过堆栈跟踪泄露使用 Fernet 加密,绝不会通过任何 API 返回
Agent 读取未获授权的机密fnmatch 权限;空列表采用默认拒绝策略
Vault 审计记录本身变成机密凭据访问日志只存储元数据
审计日志变成数据外泄渠道只存储元数据——绝不存储行数据
VAULT_KEY 轮换使用新密钥重新加密各行(由脚本驱动)

safety.py 是最重要的模块。每项新增到此模块的检查都应附带 tests/test_safety.py 中的测试。


定价

套餐月费数据库凭据每月查询次数备注
InjectShield免费———提示词注入漏斗,独立站点
Starter$5003251,000,000
Pro$1,5001010010,000,000审计导出
Enterprise$3,500不限不限不限SSO、SIEM webhook

QueryShield 套餐共用一个 Stripe 客户。InjectShield 注册仍通过 injectshield.dev 进行,直至将其账单整合进来。目标为 $32.5K MRR @ 15 customers (10 Pro + 5 Enterprise)。


部署

此代码库已准备好部署到 Railway。python -m queryshield.start 是入口点 (通过 os.getenv 读取 PORT,因为 Railway 启动命令时不会使用 shell)。在 Railway 的市场中配置 Postgres +(可选)Redis, 其余配置通过环境变量完成。

railway up

/health 是存活检查。若控制平面 数据库无法连接,/ready 会返回 503。


测试

pip install pytest
python -m pytest tests/

102 项测试涵盖原有的安全性、RLS、代理和 HTTP 测试套件,以及凭据保险库(加密、qs_ 密钥哈希、权限检查、配额、租户隔离、现有数据库的列迁移)和失败时默认拒绝的 VAULT_KEY / SESSION_KEY 检查。原有测试用例:

  • AST 安全性(24 项——直接 DDL、注释、编码关键字、多条 语句、禁止使用的函数、缺少 LIMIT)
  • RLS 引擎(6 项——白名单强制执行、WHERE 注入、与现有谓词 合取)
  • 针对 SQLite“客户数据库”的端到端代理测试(5 项——正常路径、 阻止 DML、RLS 行过滤、表白名单、缓存命中)
  • 通过 FastAPI TestClient 进行 HTTP 集成测试(7 项——完整的资源配置 → 查询流程、启用 RLS 的受限 Agent、认证失败)

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。