Skip to main content
Glama
get-dst

dst

Official
by get-dst

data serve tool (dst)

dst 把你的数据仓库服务给 AI,并为这件事的整个生命周期带来工程最佳实践。 AI 用自然语言提问;dst 根据你的团队写下的定义来回答,并附上产出答案的 SQL、一个置信度评级,以及一张收据。

问题

  • 把 AI 指向一个数据仓库,它就什么都会回答。它从不拒绝回答,而这正是失败模式:一个错误的答案比没有答案更糟。

  • 它去猜测“revenue”是什么意思,然后返回一个数字,看上去和正确答案别无二致。

  • 仅靠上下文无法解决这个问题的。AI 是不确定的,而其他团队、另一个模型,或另一个季度下有效的做法,在你这里未必有效。

  • 唯一知道答案的方法是:在你的数据上,持续地测试它。

解决方案

  • 声明:以版本控制中的文件形式声明你的数据如何被服务。

  • 测试:验证那些对你真正有效的做法。每一个被批准的答案都是一条回归测试,而管线中的每一个开关都可以翻转并重新测量。

  • 部署:只部署通过的内容,经过会大声失败的闸门。

  • 审计:审计所有已经被服务过的内容:谁问了、跑了什么、花了多少。每一个错误都会作为一个新测试自动回流。

由实践者构建,为实践者服务:文件、pull requests、CI 和退出码,而不是一套新工作流。


测试:引擎

生成过程的核心总是不确定的,因此 dst 把测试当成产品本身,而不是后补的环节。

  • 每一条被批准的答案,都是一条回归测试。 一条已认证的答案,就是一个被人担保的问题→SQL 配对。dst test 通过真实生成管线重新提出这个问题,然后把存储的 SQL 和生成的 SQL 都放到你的数据仓库中执行,并对结果。

  • 行为也被固定了。 evals/cases.yaml 里的用例断言响应的 形态expect: clarify | refuse | answer。如果一个 lens 开始拒绝明明可回答的问题,或者干脆用猜测代替澄清,它的套件就会失败。

  • 每个结果都会被记录。 测试运行都会落入数据库,所以准确率是一个你能看着它在变化的数字,并且每个发布都以它作为门闸:任何比上次发布分数还低的变更,都被拒绝。

管线可以按 lens 调整(答案严格度、自我修复、逐条判断、门控硬度),而每次翻转都可测量:改一处,跑一次 dst test,结果立刻可知。而如果你想知道在你自己的问题集上,哪些部分真正值得保留,内置的试验场会把你的问题集整套跑过管线,每次只剥离掉一个 feature:

python -m services.benchmark --data -./data --strip <feature>。完整的可调面见配置参考


Related MCP server: RunContext

部署:经过关卡

一个 lens 就是文件。改变一个答案的 diffuse;这就是一次部署,而不是一次编辑:

edit files → dst plan (dry run) → dst apply (gated, atomic)

dst plan 会显示一次变更会造成什么,如果 apply 会拒绝它,就以退出码 1 退出:plan 预测 apply 的结局。dst apply 就是一个单一事务:连接会被探测,每个过期的已认证答案都会重新对 live generation 运行,任何失败都意味着 什么都不用发布;之前的那个版本继续对外服务。

  • 版本:每次发布都会为一个 lens 版本做快照;dst lens log 会显示谁在什么时候改了什么(human:ana@corp / token:ci)。回滚就是 git revert + dst apply

  • 环境是用来出错的。 每种环境都是一套独立的 dst:你的笔记本、共享查沙盒、生产。让沙盒指向不同的模型、不同的 temperature、不同的数据表,或一套重新撰写定义的解释,跑 dst rotate test,然后比较得分——沙盒只需要在你已有的服务器上 dst bootstrap 一次。上线就是往生产里应用同一个 git commit;环境之间不会复制任何东西,文件中也没有需要逐环境同步的条款。

  • CI 只用你自己用的那组命令。 exit code 就是接口:PR 任务跑 dst plan;merge 脚本跑 dst apply --require-gates;定时任务跑 dst test --alldst drift。一份可直接使用的 GitHub Actions 示例在 环境与 CI 指南


审计:每条答案都有价格和签名

  • 回执。 每条数据答案都携带一份可移植、HMAC 签名的回执:请求 id、lens、certification、确切 SQL 的哈希。可在之后通过这些 API 在 verify_receipt MCP 工具中验证。拒绝里不带回执:因为拒绝声明明确不做任何数据主张。

  • 台账。 dst observe 的回答是“谁一直在用它,用它干什么”:每一个调用的题目、SQL、结果、在云计算的两种计价表(AI 和数据仓库)上的成本。已答复、已拒绝、出错分开计数;一次受管控的拒绝是一种结果,把一个错误。

  • 访问是被拒绝的。 每一个 allow * 和每一个 deny 都会落入 append-only 审计日志,包含调用者、lens 和原因。

  • 数据仓库的每个角落都在被监视。 dst drift 把现在的实况 schema 和已提交的基线做对比,而且把每次变更与读取被改表的全部定义、全体实体相互关联。之后是 exit code:0 干净、2 无变化,1 变更破坏已声明、4 还没有基线。

  • 的怀疑是一等输入。 Anyone 可以发一个问题来 review;低置信度的答案可以自己用 auto_review 标记。AI 法官会先做 triage 三角分类,人再裁判;repair 修复就变成一个文件加一个新测试,把整个闭环完成:

---
config:
  theme: base
  themeVariables:
    fontFamily: "ui-monospace, Menlo, monospace"
    fontSize: "14px"
    primaryColor: "#faf6ee"
    primaryBorderColor: "#b45309"
    primaryTextColor: "#292524"
    lineColor: "#b45309"
    edgeLabelBackground: "#faf6ee"
---
flowchart TD
    serve(["an answer is served,<br/>with its receipt"])
    doubt["someone doubts it"]
    test["it becomes a test:<br/>an approved answer + its check"]
    gate["it gates every deploy"]
    serve -- "flagged by the asker,<br/>or by dst itself" --> doubt
    doubt -- "AI drafts the fix,<br/>a person approves it" --> test
    test -- "commit + dst apply" --> gate
    gate -- "the corrected answer serves<br/>from then on, and the AI learns from it" --> serve

一次被修正的错误,就永远被修正,而且你能证明这一点:被纠正的问题从那个时刻起就被已被认证的 SQL 提供,并且它的测试在 release 每次都会被重跑。注意重点任务请看修正环


模型

Lens——服务的最小单位。一个使用场景(如流失、销售提成、董事会指标模式)会被描述成你共享的语义资产上的 selects,以及访问规则和自己的时钟。一个 agent 用 natural language 向一个 lens 提问,然后得到一份 grounded 且可引用的答复。

语义文件——实体 and 定义,是一次性写的文件,,每个选择它的 lens 共享。一个指标,一个定义;agent 使用的词是可以变化的,而含义从来不非遗。

在丰富上下文——“在上下文中”被 review 过的回答句就会被每个 lens 传播。entry 条目是刻意的、可追溯的,并且随 lens 一起版本化。

认证的回答——经 review 的 question-to-SQL 对,在匹配时逐句地原样,再由 dst test 当作回归测试重跑,并在每次 dst apply 中重跑。一次被修正确的错误就会成为到这样一个词,这样它就一直是 fixed 的。

治理——访问控制完全用你选择的方式:逐 lens 的 person/group 白名单、逐 caller 的 API key(dst_…)、rate limit、以及在数据库层面强制执行的 tenant 隔离(PostgreSQL RLS)。存储的 warehouse 凭据在 rest 时会被加密。

观测——每次调用都会自上而下被 trace。那个 lens,那个 caller,那个 question,那个 SQL,AI 一致性 + 直接的 warehouse 还分,并又被answered / declined / errored 分开数。答案还能被送去 review:AI 法官审查 reasoning trace,并在需要时快速汇报给人类。


Agents 才是 interface

没有 query UI。真正用你喂的是“agent”:把你的任意 MCP client(Claude Desktop、Claude Code、Cursor,或者你自己产品里面内置的 agent)连到指向 /mcp 的 guard 上的 /mcp,只需要一个 URL 和一个作用域受限的 dst_… key(见services/mcp/README.md)。每个问题都走同一条受治理的管线,所以无论哪个 agent 问,它得到答案都一样:

agent (Claude Desktop · Claude Code · Cursor · your product's agent)
        │  MCP — one scoped dst_… key per person
        ▼
   dst  ── lens: semantic model + context + access
        │   ground → SQL guard → execute → compose (cited)
        ▼
   your warehouse (BigQuery · Snowflake · Postgres · MySQL · DuckDB)
        │
   trace + cost + review  →  Observe

人类留在站守,而不是 query 处理路径里:dashboard 才是治理和观察那些 file 所“服务”的驾驶座:review queue,drift 审计、访问、成本。Lens 就是 files 写出来的(dst init → 编辑 → plan/apply),绝不会在 UI 里写。(如果想接 rest API 到 dst 里,也有 REST 门:API reference。)


项目长什么样

项目是这样一组文件:版本化、在 PR 里 review,像 infrastructure 一样地 apply。以下内容是从 dst init 真正生成的 scaffold 里精简略的(scaffold 会把演示语义资源放到 examples/ 下面,所以你可以整体删掉、整那个文件夹也别担忧;那个演示的 lens 本身在 lenses/customer_value/):

name: orders
description: One row per order.
source:
  connection: jaffle
  table: orders
default_time_field: order_date
primary_key: [order_id]
fields:
  - {name: order_id,    type: integer}
  - {name: customer_id, type: integer}
  - {name: order_date,  type: date}
  - {name: status,      type: string}
  - {name: amount,      type: number, description: Order total (USD).}
metrics:
  - {name: revenue,     agg: sum,   expr: orders.amount, format: currency}
  - {name: order_count, agg: count, expr: orders.order_id}
  - name: average_order_value
    type: ratio
    numerator: revenue
    denominator: order_count
    format: currency
joins:
  - {right: customers, on: customers.customer_id = orders.customer_id,
     type: left, relationship: many_to_one}

一次定义把业务术语绑定给 SQL:

---
metric: repeat_customer
sql: customers.number_of_orders > 1
---

A repeat customer has number_of_orders > 1.

而一个 模糊 的定义则会让 dst 去澄清,而不是猜测:

---
metric: value
status: ambiguous
possible_mappings:
  - lifetime value — customers.customer_lifetime_value
  - order amount — orders.amount
---

一下这些 mapping 就足够了:dst 在生成任何东西之前,会在代码里把它们直接长出的澄清,不需要更多配置。

name: customer_value
description: Customer lifetime value and order activity.
connections: [jaffle]
select:
  entities:
    - name: customers
    - name: orders
  definitions: [lifetime_value, repeat_customer, value]
model:
  temperature: 0.0
  answer_mode: balanced
instructions: Select explicit columns.
access:
  allow:
    - caller: alex        # deny-by-default; or `- group: everyone`
eval_gate: block          # a failing eval suite blocks the apply
auto_review: unverified   # low-confidence answers open review tickets
# Served VERBATIM on a match — and each one is a regression test:
# `dst test` re-asks the question and compares against this SQL's result.
- question: How many customers are repeat customers?
  sql: SELECT count(*) AS n FROM customers WHERE number_of_orders > 1
- question: What was total revenue?
  sql: SELECT sum(amount) AS revenue FROM orders
name: analytics

providers:
  anthropic:
    type: anthropic
    api_key_env: DST_API_KEY_ANTHROPIC
  # any openai-compatible endpoint works: deepseek, ollama, vllm, groq …

connections:
  jaffle:
    type: duckdb
    config: {path: fixtures/jaffle_shop.duckdb}
  wh:
    type: bigquery                  # or snowflake, postgres, mysql
    config: {project: my-gcp-project}
    secret_env: DST_API_KEY_WH      # an inline key is a parse error
$ dst query customer_value "How many customers are repeat customers?"
19 of the 100 customers are repeat customers.

sql: SELECT count(*) AS n FROM customers WHERE number_of_orders > 1
basis: A repeat customer has number_of_orders > 1.
confidence: verified · definition: repeat_customer

$ dst query customer_value "What is the average value of a customer?"
clarify: 'value' is ambiguous in this dataset — lifetime value (total
historical revenue per customer) or order amount (a single order's total)?
  - lifetime value — customers.customer_lifetime_value
  - order amount — orders.amount

拒绝和澄清都算是一种 result 而非 error:dst 更多是要发问,而不是猜。


快速开始

安装包。先决条件:Python 3.12+、Docker(dst 用它自己的 PostgreSQL 运行),以及至少一个 model provider 的 API key:Anthropic 或任何支持 openai 兼容端点的供应商(DeepSeek、Ollama、vLLM、Groq,以及大部分网关)。

pip install dst-core            # the CLI is `dst`
dst init analytics --warehouse demo --yes
cd analytics                    # put your provider key in the generated .env
dst dev                         # Postgres up + migrate + serve, one command

# in a second terminal, same directory
dst bootstrap --org me --email you@example.com
dst apply
dst query customer_value "How many customers are repeat customers?"

dst init 会在一个捆绑的 jaffle DuckDB warehouse 上搭建一整个项目,并且同时保留( applyquery 都可以在你连接真实仓库之前就能工作。这个 release wheel 已经带着 migrations 和 dashboard,所以你可以自己 run dst dev,两个都不动,都挂着后端 http://localhost:8000quickstart 是主路线,并会把这同一套路线引申到您自己的 warehouse。

从源码运行

贡献者的路径:一份源码检出(checkout)、仓库自带的 Makefile,以及由 Vite 构建(而非打包)的仪表盘。前提条件:以上内容,外加 uv、Node 22+ 和 pnpm。

# 1. Backend deps
make install                 # uv sync

# 2. Configure — create .env in the repo root (see "Configuration" below)
echo 'DST_PROVIDERS={"anthropic": {"type": "anthropic", "api_key": "sk-ant-..."}}' > .env
# openai-compatible works the same:
#   {"ollama": {"type": "openai-compatible", "base_url": "http://localhost:11434/v1", "api_key": "unused"}}

# 3. Start Postgres (pgvector), run migrations, seed an org + admin token
make up
make migrate
make seed                    # prints a dstadm_… admin token — copy it

# 4. Run the API (http://localhost:8000)
make dev

然后是仪表盘:

cd apps/web
pnpm install
pnpm dev                     # http://localhost:5173

打开仪表盘,将右上角的 dstadm_… 管理员令牌粘贴进去,即可治理该组织:审核队列、漂移审计、调用方、成本。Lens 本身以文件形式编写:uv run dst init 会在随附的 jaffle DuckDB 数据仓库上生成一个 Lens,因此在连接真实数据仓库之前,uv run dst applyuv run dst query 就能正常工作。源码检出不会把 dst 放到你的 PATH 上——每条命令都以 uv run dst … 的形式运行,Makefile 目标正是这样实现的。

如果要让某个 agent 查询某个 Lens:在 Settings 中签发一个 caller key,把它加入 lens.yaml 中该 Lens 的 allow-list,然后运行 uv run dst apply,最后通过 MCP 连接该 agent。


配置

设置从 .env 加载(见 services/config.py)。常用键:

变量

是否必填

用途

DST_PROVIDERS

是,至少一个条目

模型提供方,按名称组织 JSON(BYOK;不要使用以厂商命名的键变量)。类型:anthropicopenai-compatiblelocal。声明顺序就是层级/成本偏好顺序;grounding、组合、审核判定和路由都会通过它解析。

embedding provider

上下文功能需要

DST_PROVIDERS 中提供 embedding 模型的条目:任何 openai-compatible 端点,或免密钥的进程内 local 类型(uv sync --extra local-embed)。认证匹配就是基于该 embedding 的余弦匹配。没有可用的 embedder 时完全无法触发,这也是每个响应的 degraded 列表和 /readycertified_matching 所反映的。

FASTEMBED_CACHE_PATH

可选

local 层存放其 ONNX 权重的位置。默认为 ~/.cache/dst/fastembed(也支持 $XDG_CACHE_HOME),这是刻意不用 fastembed 自己的默认目录——它默认的是操作系统中 macOS 会从底下直接清掉的临时目录。在容器中请将它指向已挂载的卷。

DST_SECRET_KEY

需要存储凭据时

用于加密已存储的数据仓库/上下文凭据的 Fernet 密钥。dst init 会生成一个;也可手动生成:python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"

DATABASE_URL / DATABASE_ADMIN_URL

本地默认即可

应用(强制 RLS、非超级用户)和管理(迁移/种子)连接。

CLERK_SECRET_KEY / CLERK_PUBLISHABLE_KEY

可选

托管仪表盘的身份认证;没有它也不影响本地登录和管理员令牌。

数据仓库和检索源凭据不是环境变量:请在 dst.yaml 中用 secret_env 引用声明连接(见 quickstart)。.env.exampleservices/config.py 生成:它是一份完整、永不过时的配置表面。


项目布局

services/          FastAPI app (services.app:app)
  api/             control plane (/mgmt/*) + data plane (/v1/*)
  contracts/       lens config, semantic model, protocols
  connectors/      warehouse connectors
  context/         embedding providers + the serving error surface
  runtime/         the query pipeline (ground → guard → execute → compose)
  reviews/         AI-judge + human review queue
  governance/      access policy, credentials, rate limits, audit
  mcp/             remote + stdio MCP server (see its README)
apps/web/          React + Vite dashboard
migrations/        Alembic migrations
fixtures/          built-in jaffle DuckDB warehouse

开发

命令

作用

make up / make down

启动 / 停止本地 Postgres(pgvector)

make migrate

应用数据库迁移(dst migrate:schema + 应用角色密码同步)

make seed

填充一个开发组织和管理员令牌

make dev

在 :8000 上热重载运行 API

make lint

ruff + 格式检查 + mypy + UI 样式门禁

make fmt

自动格式化 + 修复

make test

后端测试(pytest

pnpm --dir apps/web dev

在 :5173 上运行仪表盘

架构:FastAPI 后端(lens 配置、context 向量存储、请求 trace、审核)架构基于 Postgres + pgvector,并从你的数据仓库读取数据;结果集本身不会被持久化。trace 保留的是问题、SQL、组合后的答案及其引用;只有 lens 通过 logging.log_samples 开启时,才会保存前几行结果。数据仓库 profiling 同样会存储每列的统计信息和低值列表;exclude_columns 中提到的列只读取其结构,值不会被收集。dst 不会自动分类或脱敏个人数据:不要暴露你不希望值离开你网络的列。仪表盘是一个同源或拆分的 React SPA。

用户文档位于 docs/(quickstart、概念、指南、参考),并发布在 https://www.dataservetool.com;贡献者子系统地图请见 ARCHITECTURE.md


许可证

Apache-2.0。贡献:CONTRIBUTING.md · 安全漏洞:SECURITY.md · 问题与反馈:github.com/get-dst/dst/issues

A
license - permissive license
Not graded
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
1Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • F
    license
    Not graded
    quality
    Not graded
    maintenance
    Enables natural language querying of Microsoft Fabric Data Warehouses with intelligent SQL generation, metadata exploration, and business-friendly result summarization. Features two-layer architecture with MCP-compliant server and agentic AI reasoning for production-ready enterprise data access.
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables AI agents to understand and query your database safely by providing a semantic layer of metadata, with tools to search, explain, validate, and generate safe SQL.
    2
    MIT
  • A
    license
    A
    quality
    F
    maintenance
    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.
    9
    MIT

View all related MCP servers

Related MCP Connectors

  • The grounded data layer for any LLM: governed SQL, metrics, lineage and catalog over your data.

  • Shared, permission-aware company context for AI agents, with provenance, approvals and audit.

  • Query PostgreSQL databases in plain English — LLM-generated, safety-validated SQL.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/get-dst/dst'

If you have feedback or need assistance with the MCP directory API, please join our Discord server