自然语言转SQL代理

一个提供自然语言转SQL功能并具备列级访问控制的MCP服务器,适用于数据查询和管理场景。

  • by adityasudhakar
  • Python
  • 本地部署
  • 1 星标
  • 更新于
在 GitHub 查看 adityasudhakar/text2sql-access-control

使用说明

具有列级访问控制的SQL代理文本

一个MCP服务器,提供具有列级访问控制的自然语言到SQL功能。作为一个学习项目,与克劳德一起探索代理模式。

它做什么

  • 将自然语言问题转换为BigQuery SQL
  • 使用确定性SQL重写强制列级访问控制
  • 使用sqlglot解析SQL以进行精确的列检测(无子字符串匹配)
  • 通过外键检测自动查找连接路径

建筑

User Query: "What are total sales?"
                │
                ▼
┌─────────────────────────────────────────────────────────────┐
│  Main LLM (generates SQL)                                   │
│  Output: SELECT SUM(amount) FROM sales                      │
└─────────────────────┬───────────────────────────────────────┘
                      │
                      ▼
┌─────────────────────────────────────────────────────────────┐
│  Access Control Check (sqlglot)                             │
│  • Parse SQL, extract column references                     │
│  • Check: is sales.amount in restricted columns?            │
│  • YES → apply rule                                         │
└─────────────────────┬───────────────────────────────────────┘
                      │
                      ▼
┌─────────────────────────────────────────────────────────────┐
│  Deterministic SQL Rewriting                                │
│  • Find join path: sales → ae_territories → account_execs   │
│  • Add JOINs and WHERE clause                               │
│  Output:                                                    │
│    SELECT SUM(amount) FROM sales                            │
│    INNER JOIN ae_territories ON sales.territory = ...       │
│    INNER JOIN account_execs ON ae_territories.ae_id = ...   │
│    WHERE account_execs.ae_email = 'bob@acme.com'            │
└─────────────────────┬───────────────────────────────────────┘
                      │
                      ▼
                ┌───────────┐
                │ BigQuery  │
                └───────────┘

关键改进

  • 执行路径中没有LLM -SQL重写是确定性的,不是基于LLM的
  • 精确列匹配 - amount 不匹配 amount_ytd (使用SQL解析器)
  • FK自动检测 -通过分析列名查找连接路径
  • 多跳加入 -支持 sales → territories → account_execs

设置

  1. 安装依赖项

    python -m venv venv
    source venv/bin/activate
    pip install -r requirements.txt
    
  2. 配置凭据

    • 将您的BigQuery服务帐户JSON设置为 mcp_server/service_account.json
    • 创建 .env 使用您的Anthropic API密钥:
      ANTHROPIC_API_KEY=sk-ant-...
      

用法

独立聊天模式

python terminal_chat.py

注: 聊天模式使用 Claude代理SDK 这需要 克劳德代码 待安装。

作为MCP服务器(适用于Claude Desktop或其他MCP客户端)

添加 ~/Library/Application Support/Claude/claude_desktop_config.json:

{
  "mcpServers": {
    "text2sql": {
      "command": "python",
      "args": ["/path/to/mcp_server/mcpserver.py"]
    }
  }
}

设置访问控制

1.配置数据集和用户表

> configure dataset myproject.mydataset
> configure users_table account_execs

2.检测外键(或手动设置)

> detect_foreign_keys
Detected:
  sales.territory -> ae_territories.territory
  ae_territories.ae_id -> account_execs.ae_id

> set_foreign_key sales territory ae_territories territory  # if needed

3.设置访问规则

> set_access_rule sales.amount account_execs.ae_email
Access rule set for 'sales.amount':
  Controlled by: account_execs.ae_email
  User field: ae_email
  Join path: sales.territory = ae_territories.territory -> ae_territories.ae_id = account_execs.ae_id

4.作为用户进行测试

> manage_identity set bob@acme.com
Now simulating: Bob (ae_email: bob@acme.com)

> what are total sales?
[Access control applied: sales.amount filtered by account_execs.ae_email='bob@acme.com']
SQL: SELECT SUM(amount) FROM sales
     INNER JOIN ae_territories ON sales.territory = ae_territories.territory
     INNER JOIN account_execs ON ae_territories.ae_id = account_execs.ae_id
     WHERE account_execs.ae_email = 'bob@acme.com'

可用工具

工具 目的
read_context 阅读模式/示例草稿栏
write_context 添加到草稿栏
run_query 使用访问控制执行SQL
preview_query 预览访问控制而不执行
list_schema_columns 列出所有表和列
detect_foreign_keys 自动检测FK关系
set_foreign_key 手动设置FK关系
set_access_rule 添加访问控制规则
list_access_rules 显示所有规则
remove_access_rule 删除规则
manage_identity 切换模拟用户
configure_dataset 设置BigQuery数据集

运作原理

  1. 管理员设置规则: sales.amount 被控制 account_execs.ae_email
  2. FK检测:系统从以下位置查找路径 sales 到 account_execs
  3. 查询到达: SELECT SUM(amount) FROM sales
  4. 立柱检查:sqlglot解析SQL,查找 sales.amount (完全匹配)
  5. SQL重写:确定性地添加JOIN+WHERE(无LLM)
  6. 执行:修改后的SQL对BigQuery运行

文件

文件 目的
mcp_server/mcpserver.py 基于sqlglot访问控制的MCP服务器
mcp_server/config.json 访问规则和FK定义
mcp_server/context.md 用于模式/示例的Scratchpad
terminal_chat.py 独立终端聊天界面
test_access_control.py 门禁单元测试

局限性

这是一个 学习原型,未准备好生产:

  • FK检测使用命名约定(可能会错过关系)
  • 仅限单值筛选器(无IN子句)
  • 在受限列检查中不支持子查询

对于生产,请考虑:

  • BigQuery行级安全策略
  • 每个角色的视图
  • 显式FK元数据

许可证

麻省理工学院