sql-steward

sql-steward

A governed SQL gateway that exposes typed tools to AI agents, compiling safe read-only queries from a semantic layer while blocking PII before execution, supporting SQL Server, Postgres, and SQLite.

Category
访问服务器

README

sql-steward

License Python

Part of the Governed Agent Stack: free, on-prem building blocks for an AI agent you can point at a real database and audit.

A governed SQL gateway for AI agents, exposed over the Model Context Protocol. The agent never gets a connection string and never writes SQL. It calls typed tools; sql-steward compiles every query from a semantic layer you control, refuses blocked PII before the query runs, and returns rows. Same tools across SQL Server, Postgres and SQLite.

Most SQL MCP servers hand the model a run_sql tool and try to catch the bad queries on the way out. sql-steward removes the tool. There is no path from a prompt to raw SQL at your database, because the only thing the agent can do is name an entity or a metric and pick from allow-lists you wrote.

Three guarantees

  1. Read-only by construction. There is no run_sql, query, or execute tool. The compiler can only ever build a SELECT, so a write isn't blocked, it's unrepresentable.
  2. PII refused before retrieval. Every field can carry a PII tag. If a request touches a category your policy blocks, sql-steward refuses with a structured reason before any SQL is compiled or run.
  3. Auditable. Every call, refusal and error can be recorded in a tamper-evident, hash-chained log via agent-blackbox, with audit-verify to prove nothing was rewritten.

See it in 10 seconds

pip install sql-steward      # or: pipx install sql-steward
sql-steward demo            # zero config, no API key, no agent, SQLite
1) get_metric('mrr_total', dimensions=['plan'])  -> safe aggregate
   compiled: SELECT subscriptions.plan, SUM(subscriptions.mrr) AS mrr_total
             FROM subscriptions GROUP BY subscriptions.plan LIMIT 1000
   {'plan': 'pro', 'mrr_total': 297.0}
   {'plan': 'team', 'mrr_total': 598.0}

2) get_metric('mrr_total', dimensions=['customers.country'])  -> auto-join
   compiled: ... INNER JOIN customers ON subscriptions.customer_id = customers.id ...

3) get_records('customers', fields=['id','email'])  -> PII refusal
   refused: {"kind": "pii_blocked", "detail": "Field 'customers.email' is tagged
             EMAIL_ADDRESS, which this policy refuses."}

The semantic layer

This YAML is the entire contract between the agent and your database. Review it like code.

dialect: postgres

entities:
  customers:
    table: customers
    fields:
      id: {type: int}
      name: {type: text, pii: PERSON}
      email: {type: text, pii: EMAIL_ADDRESS}
      country: {type: text}
  subscriptions:
    table: subscriptions
    fields:
      customer_id: {type: int}
      plan: {type: text}
      mrr: {type: numeric}

joins:                              # nothing reachable that isn't listed here
  - left: subscriptions
    right: customers
    on: subscriptions.customer_id = customers.id

metrics:
  mrr_total:                        # the aggregation is fixed; the agent only
    entity: subscriptions           # chooses dimensions/filters from the lists
    aggregate: sum
    field: mrr
    dimensions_allowed: [plan, status, customers.country]
    filters_allowed: [status, customers.country]

policy:
  block_pii: [EMAIL_ADDRESS, CREDIT_CARD]
  max_rows: 1000

Ask for a join that isn't defined and you get unreachable_entity, not an invented relationship. Ask to group a metric by a dimension that isn't listed and you get dimension_not_allowed.

Tools exposed to the agent

Tool Purpose
list_entities() What can be read, plus the available metrics
describe_entity(entity) Fields, types and PII tags (blocked ones flagged)
list_metrics() Metrics and the dimensions/filters each allows
get_records(entity, fields, filters, order_by, limit) Read rows from one entity
get_metric(metric, dimensions, filters, limit) Compute a pre-approved aggregate
semantic_search(entity, query, k, filters) pgvector nearest-neighbour search over an entity's embedding column
audit_verify() Verify the tamper-evident audit chain

Filters are {field, op, value}; operators are =, !=, <, <=, >, >=, like, in, not in, is null, is not null. Values are always bound parameters, never inlined.

Wire it into an MCP client

servers.yaml lives wherever you point SQL_STEWARD_LAYER. Claude Desktop (claude_desktop_config.json):

{
  "mcpServers": {
    "sql-steward": {
      "command": "sql-steward",
      "env": {
        "SQL_STEWARD_LAYER": "/full/path/to/semantic.yaml",
        "SQL_STEWARD_DB_URL": "postgresql+psycopg://readonly@db.internal/warehouse"
      }
    }
  }
}

SQL_STEWARD_DB_URL is a SQLAlchemy URL, so the same server reads SQL Server (mssql+pyodbc://...), Postgres (postgresql+psycopg://...) or SQLite (sqlite:///path.db). Install the matching driver with the extras: pip install "sql-steward[postgres]" or "[mssql]".

Optional: the rest of the stack

The semantic layer is the primary control. These are extra layers, all opt-in, and no-ops if the library isn't installed:

pip install "sql-steward[rbac,mask,audit]"

export SQL_STEWARD_POLICY=/path/to/policy.yaml   # query-warden second-pass role check
export SQL_STEWARD_ROLE=analyst
export SQL_STEWARD_MASK=1                         # pii-veil masks anything left in results
export SQL_STEWARD_AUDIT_DB=logs/steward.db       # agent-blackbox audit chain (on if installed)
export SQL_STEWARD_QUERY_BUDGET=200               # hard cap on queries per role per session
export SQL_STEWARD_EMBED_URL=http://localhost:11434/api/embeddings  # local embeddings for semantic_search
export SQL_STEWARD_EMBED_MODEL=nomic-embed-text

Semantic search (pgvector)

Give an entity a search block pointing at a pgvector column and the agent gets a semantic_search tool, governed exactly like everything else (PII refused, results masked, calls audited):

entities:
  documents:
    table: documents
    fields:
      id: {type: int}
      title: {type: text}
      embedding: {type: vector}
    search:
      vector_column: embedding
      dim: 768
      returns: [id, title]

The query text is embedded locally (set SQL_STEWARD_EMBED_URL to a local Ollama endpoint, so nothing leaves the building), and matched with pgvector's <=> operator. PostgreSQL only. The embedding column is never returned.

  • query-warden re-checks the compiled SQL against a role policy.
  • pii-veil masks any PII that survives into result rows.
  • agent-blackbox records every call in a hash-chained ledger; sql-steward audit-verify checks it.

How this is different

A typical SQL MCP validates arbitrary SQL the model wrote (a blocklist: catch what's bad). sql-steward compiles SQL from definitions you wrote (an allow-list: only what's described exists). The read-only and PII guarantees hold by construction rather than by inspection, and the query surface is the same across three engines.

Develop

git clone https://github.com/Pawansingh3889/sql-steward
cd sql-steward
pip install -e ".[dev]"
pytest -q

License

MIT

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选