使用说明
安全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://<your-index>/simple"
cat > .env <<'EOF'
DATABASE_URL=sqlite+aiosqlite:///./example.db
ALLOWED_POLICY_FILE=./policy/allowed_policy.txt
MAX_ROWS=100
QUERY_TIMEOUT=30
LOG_LEVEL=INFO
EOF
mkdir -p policy
cat > policy/allowed_policy.txt <<'EOF'
customers:id,email
orders:*
EOF
# Create tables for local testing (optional)
sqlite3 example.db <<'SQL'
CREATE TABLE IF NOT EXISTS customers (id INTEGER PRIMARY KEY, email TEXT NOT NULL, ssn TEXT);
CREATE TABLE IF NOT EXISTS orders (id INTEGER PRIMARY KEY, total NUMERIC);
INSERT OR IGNORE INTO customers (id, email) VALUES (1, 'test@example.com');
INSERT OR IGNORE INTO orders (id, total) VALUES (1, 19.99);
SQL
uv venv
source .venv/bin/activate
uv pip install -e .
python -m secure_sql_mcp.server
快速入门(Docker)
git clone https://github.com/jrhuerta/secure-sql-mcp.git
cd secure-sql-mcp
mkdir -p policy
cat > policy/allowed_policy.txt <<'EOF'
customers:id,email
orders:*
EOF
cat > .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.pytests/test_query_validator_security.pytests/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.mdCODE_OF_CONDUCT.mdSECURITY.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. ...
