安全SQL MCP服务器
具有严格表/列策略控制的只读SQL MCP服务器。
 
MCP客户端配置
要将此服务器与Cursor、Claude Desktop或其他MCP客户端一起使用,请将其添加到您的MCP配置中:
光标 (.cursor/mcp.json 或光标设置→ MCP):
{
"mcpServers": {
"secure-sql": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"--env-file", "/path/to/your/secrets",
"-v", "/path/to/your/policy:/run/policy:ro",
"ghcr.io/jrhuerta/secure-sql-mcp:latest"
]
}
}
}克劳德桌面版 (claude_desktop_config.json):结构相同 mcpServers.
这 --env-file 应指向包含以下内容的文件 DATABASE_URL 和 ALLOWED_POLICY_FILE=/run/policy/allowed_policy.txt (请参阅下面的环境变量)。该卷以只读方式装载策略目录。先拉图片: docker pull ghcr.io/jrhuerta/secure-sql-mcp:latest
安全模型
- 数据库凭据保持在服务器端(env-vars),从不出现在提示中。
- 只允许读取查询。
- 政策严格且基于文件:
- 一个必需的文件: ALLOWED_POLICY_FILE - 每条线都是 table:col1,col2,col3 或 table:*
- 如果表/列未被明确允许,则会被阻止。
已实施的安全控制
- 查询形状强制
- 每个请求只允许一个SQL语句。 - 非读取操作被阻止(INSERT, UPDATE, DELETE, DROP, ALTER, CREATE, TRUNCATE, GRANT, REVOKE, MERGE以及相关的命令表达式)。
- 严格的访问策略执行
- 默认情况下拒绝表和列。 - 访问检查适用于直接查询和组合查询(JOIN, UNION、子查询、别名)。 - SELECT * 除非表策略为 table:*. - 在严格模式下,多表查询中的不合格列将被拒绝。
- 运行时安全控制
- 查询超时和行上限在服务器端强制执行。 - 行上限截断在响应有效载荷中是明确的。
- 安全错误行为
- 验证和策略失败会返回可操作的补救提示。 - 对数据库执行失败进行清理,以避免泄露敏感的内部详细信息。
环境变量
| 变量 | 必填 | 默认 | 描述 |
|---|---|---|---|
DATABASE_URL | 是 | -- | 数据库URL。裸露 postgresql://, mysql://,以及 sqlite:// URL被接受并自动升级为异步驱动程序(+asyncpg, +aiomysql, +aiosqlite). |
ALLOWED_POLICY_FILE | 是 | -- | 策略文件的路径 |
MAX_ROWS | 否 | 100 | 每个查询返回的最大行数(1-10000) |
QUERY_TIMEOUT | 否 | 30 | 查询超时(秒)(1–300) |
LOG_LEVEL | 否 | 信息 | 日志记录级别(调试、信息、警告、错误) |
策略文件格式
allowed_policy.txt:
# table:columns
customers:id,email
orders:*规则:
table:*允许该表中的所有列。#允许注释和空白行。- 匹配不区分大小写。
代理可发现性
MCP服务器公开:
list_tables():
- 策略允许的表 - 每个表允许的列数(* 或明确列表) - 元数据验证状态(如果可以进行数据库自检)
describe_table(table):
- 策略中允许该表的列 - 数据库中的模式元数据(如果可用)
query(sql):
- 仅当查询为只读且在表/列策略范围内时执行
快速启动(uv)
git clone https://github.com/jrhuerta/secure-sql-mcp.git
cd secure-sql-mcp
# Optional: use a custom package index for uv/pip (e.g. corporate PyPI mirror)
# export PYTHON_INDEX_URL="https:///simple"
cat > .env policy/allowed_policy.txt policy/allowed_policy.txt .env <<'EOF'
DATABASE_URL=sqlite+aiosqlite:///./example.db
ALLOWED_POLICY_FILE=/run/policy/allowed_policy.txt
MAX_ROWS=100
QUERY_TIMEOUT=30
LOG_LEVEL=INFO
EOF
docker build -t secure-sql-mcp .
docker run -i --rm \
--env-file .env \
-v "$(pwd)/policy:/run/policy:ro" \
secure-sql-mcp快速入门(GHCR图像)
创建GitHub Release时会发布图像。每个版本都会同时推送版本标签(例如。 v0.1.0)以及 latest:
docker pull ghcr.io/jrhuerta/secure-sql-mcp:latest使用env文件和只读挂载策略运行:
docker run -i --rm \
--env-file .env \
-v "$(pwd)/policy:/run/policy:ro" \
ghcr.io/jrhuerta/secure-sql-mcp:latest或者使用Docker Compose(从本地Dockerfile构建):
docker compose up --build秘密最佳实践
- 仅将凭据放入
.env(或你的秘密经理),永远不要在提示中。 - 避免在shell历史记录中硬编码凭据。
- 以只读方式装载策略文件(
:ro)在Docker中。 - 保持
.env以及不受版本控制的策略文件。
开发工具
python -m pip install -e ".[dev]" # or: uv pip install -e ".[dev]"
pre-commit install
pre-commit run --all-files
ruff check .
ruff format .
ty check
python -m pytest -q安全测试套件
直接运行以安全为重点的套件:
python -m pytest -q \
tests/test_mcp_interface.py \
tests/test_query_validator_security.py \
tests/test_mcp_stdio_security.py这些套件验证了什么:
- 变异/特权SQL操作的只读强制
- 单语句验证和解析器强化
- 默认情况下严格拒绝表/列ACL检查,包括联接/联合/子查询路径
- MCP stdio传输上的协议级行为
- 超时、行上限截断和非泄漏的可操作数据库错误响应
CI安全门期望
对于受保护的分支,将这些检查视为合并阻止程序:
ruff check .
ty check
python -m pytest -q \
tests/test_mcp_interface.py \
tests/test_query_validator_security.py \
tests/test_mcp_stdio_security.py建议政策:
- 在上述安全套件中出现任何故障时进行块合并
- 更改查询验证、策略解析或MCP工具响应时需要测试更新
- 保持安全测试夹具的确定性(默认情况下没有共享状态,没有外部数据库依赖性)
贡献
- 阅读 贡献.md 在打开PR之前。
- 社区行为期望 代码_OF_CONDUCT.md.
- 许可条款在 许可证.
- 审查期望在以下方面得到执行
main:
- 需要拉取请求 - 至少1次批准审查 - 所需的CI检查(Lint, Type, Test 和 Docker Build) - 需要线性历史记录
- 安全报告应转到 安全.md 而不是公共问题。
安全快速审核清单
在合并安全敏感更改之前,请验证:
- 查询验证仍然对每个请求强制执行一条语句
- 变异/DDL/特权SQL操作被可操作的消息阻止
- 默认情况下,表和列访问仍为拒绝
ALLOWED_POLICY_FILE SELECT *除非策略明确允许,否则将被拒绝table:*- 多表查询仍然拒绝不合格的列,并强制执行别名感知ACL
- 超时和行上限保护仍处于活动状态并经过测试
- 数据库错误响应保持干净,不会暴露凭据/内部连接详细信息
- 安全套件通行证:
- tests/test_mcp_interface.py - tests/test_query_validator_security.py - tests/test_mcp_stdio_security.py
公开推出验证清单
合并工作流/文档更改后,请验证:
- 存储库可见性为
Public main分支保护处于活动状态,需要:
- 基于PR的合并 - 1审批审核 - 必要的检查 Lint, Type, Test 和 Docker Build - 线性历史,无强制推送,无删除
- CI工作流在PR和推送上运行
main - 当GitHub发布时,GHCR镜像发布成功
- GHCR牵引工作:
- docker pull ghcr.io/jrhuerta/secure-sql-mcp:latest
- 社区文档存在:
- CONTRIBUTING.md - CODE_OF_CONDUCT.md - SECURITY.md - .github/ISSUE_TEMPLATE/* - .github/PULL_REQUEST_TEMPLATE.md
阻止消息示例
- 突变被阻断:
- This server is configured for read-only access. The operation 'UPDATE' is not permitted. If you need to modify data, please escalate to a human operator.
- 策略阻止表:
- Access to table 'secrets' is restricted by the server access policy. ...
- 策略阻止列:
- Access to column(s) ssn on table 'customers' is restricted. ...
