dst
Officialdata serve tool (dst)
dst는 여러분의 웨어하우스를 AI에 서비스하고, 그 전 과정에서 엔지니어링 모범 사례를 적용합니다. AI가 일상 언어로 질문하면, dst는 팀이 작성한 정의를 바탕으로 답을 하고, 답을 만들어 낸 SQL, 신뢰 등급, 그리고 영수증을 함께 제공합니다.
문제
AI를 웨어하우스에 연결하면 무엇이든 답합니다. 결코 답하지 못하는 일이 없는데, 그 자체가 실패 모드입니다: 잘못된 답은 답이 없는 것보다 나쁩니다.
"수익"이 무엇을 의미하는지 추측하고, 반환하는 숫자는 정답처럼 보입니다.
맥락만으로는 고쳐지지 않습니다. AI는 비결정적이며, 다른 팀, 다른 모델, 다른 분기에 통하는 방법이 여러분에게도 통하리라는 보장은 없습니다.
아는 유일한 방법은 여러분의 데이터로 계속 테스트해 보는 것입니다.
솔루션
선언합니다. 데이터를 서빙하는 방식을 버전 관리되는 파일로 선언합니다.
테스트합니다:**실제로 여러분에게 통하는 것을 테스트합니다. 승인된 모든 답은 회귀 테스트가 되고, 파이프라인의 모든 변수는 전환해 다시 측정할 수 있습니다.
배포합니다:** 승인된 것만 게이트를 통과해서 배포합니다. 게이트는 반드시 명확하게 실패합니다.
감사합니다:** 서빙된 모든 것을 감사합니다: 누가 물었는지, 무엇이 실행됐는지, 비용이 얼마였는지. 모든 실수는 다시 새로운 테스트로 피드백됩니다.
실무자가 실무를 위해 만들었습니다: 파일, 풀 리퀘스트, CI, 종료 코드가 중심이며, 새로운 워크플로우는 아닙니다.
테스트: 핵심 엔진
생성은 근본적으로 비결정적이므로, dst는 테스트를 나중에 붙이는 부가 요소가 아니라 제품 그 자체로 다룹니다.
승인된 모든 답변은 회귀 테스트가 됩니다. 인증된 답변은 어떤 사람이 보증한 질문→SQL 쌍입니다.
dst test는 실제 생성 파이프라인을 통해 같은 질문을 다시 물어, 저장된 SQL과 생성된 SQL을 모두 웨어하우스에서 실행하고 결과를 비교합니다.동작 방식도 고정됩니다.
evals/cases.yaml의 케이스는 응답의 형태를 단정합니다:expect: clarify | refuse | answer. 답변 가능한 질문을 거부하기 시작하거나, 명확히 묻는 대신 추측하는 렌즈는 테스트 수트에서 실패합니다.모든 결과가 기록됩니다. 테스트 실행은 데이터베이스에 저장되므로 정확도는 움직임을 볼 수 있는 숫자가 되고, 배포가 이를 기준으로 규제합니다: 지난 배포보다 점수가 나빠진 변경은 거부됩니다.
파이프라인은 렌즈별로 조정할 수 있고(답변의 엄격함, 자기 복구, 답변별 판정, 게이트 수위), 모든 조정은 측정 가능합니다: 하나를 바꾸고 dst test를 실행하면 알 수 있습니다. 그리고 여러분의 질문에서 어떤 부분이 충분한 가치를 만드는지 알고 싶을 때, 번들로 포함된 실험장(proving ground)은 파이프라인을 거쳐 여러분의 질문 세트를 기능을 하나씩 제거하는 상태로 실행합니다:
python -m services.benchmark --data ./data --strip <feature>. 전체 조정 표면은 구성 참조에 있습니다.
Related MCP server: RunContext
배포: 게이트를 통해서
렌즈는 파일입니다. 답변의 의미를 바꾸는 것은 단순 편집이 아니라 배포입니다:
edit files → dst plan (dry run) → dst apply (gated, atomic)dst plan은 변경이 초래할 결과를 보여주고, apply가 rejection으로 끝나면 1로 종료합니다: plan은 apply를 예측합니다. dst apply는 하나의 트랜잭션입니다: 연결을 검사하고, 오래된 인증된 답변을 라이브 생성에 맞춰 재실행하며, 어떤 것이 실패하면 아무것도 배포하지 않습니다; 이전 버전이 계속 서빙됩니다.
버전: 모든 배포는 렌즈의 버전을 스냅샷으로 남깁니다.
dst lens log는 무엇이, 언제, 누구에 의해 변경됐는지 보여줍니다 (human:ana@corp/token:ci). 롤백은git revert+dst apply입니다.환경은 시도해 보는 곳입니다. 각 환경은 별도의 dst입니다: 노트북, 공유 샌드박스, 프로덕션. 샌드박스를 다른 모델, 다른 온도, 다른 테이블, 바꿔 쓴 정의에 연결하고
dst test를 실행한 후 점수를 비교하세요 — 샌드박스는 이미 운영 중인 서버 하나에dst bootstrap한 번이면 됩니다. 배포는 프로덕션에 동일한 git 커밋을 적용하는 것이고, 환경 간에 복사되는 것은 없고, 파일도 동기화해야 하는 환경별 섹션을 담지 않습니다.CI는 여러분이 쓰는 것과 같은 명령을 실행합니다. 종료 코드가 인터페이스입니다. PR 작업은
dst plan을 실행하고, merge는dst apply --require-gates를 실행하고, 스케줄 작업은dst test --all및dst drift를 실행합니다. GitHub Actions 예제는 환경 가이드에 있습니다.
감사: 모든 답변에 가격과 서명
영수증. 모든 데이터 답변은 HMAC 서명이 있고 이식 가능한 영수증입니다: 요청 ID, 렌즈, 인증, 그리고 정확한 SQL의 해시. 나중에 API 또는
verify_receiptMCP 도구를 통해 검증할 수 있습니다. 거부는 영수증을 갖지 않습니다: 데이터에 대한 주장을 하지 않기 때문입니다.장부.
dst watch는 "누가 이를 사용해 왔고, 무엇에 썼는가"를 답합니다: 질문, SQL, 결과, 그리고 두 미터(AI/웨어하우스)의 비용을 포함한 모든 호출. 답변, 거부, 오류는 각각 구분해 집계됩니다. 관리되는 거부는 오류가 아니라 하나의 결과입니다.접근, 양방향. 모든 허용과 모든 거부는 추가 전용 감사 로그에 배치되고, 호출자, 렌즈, 사유가 함께 기록됩니다.
웨어하우스가 관찰됩니다.
dst drift는 라이브 스키마를 커밋된 베이스라인과 비교하여, 변경된 테이블을 읽는 정의와 엔터티와 각 변경을 교차 참조합니다. 종료 코드:0별 변동,2변경 있음,1변경으로 인해 선언된 것( 결정한 것)을 깨는 경우,4베이스라인이 아직 없음.**불확실성은 1급 입력입니다.**모든 호출자는 답을 검토에 보낼 수 있고, 낮은 신뢰도의 답변은 자체로 표시할 수 있습니다 (
auto_review). AI 판사가 전체 추적을 분류합니다. 인간이 판결합니다. 수정은 파일과 새로운 테스트 로 들어옵니다. 루프가 끝나는 곳입니다:
---
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로 서빙되고, 그 테스트는 모든 apply 때마다 다시 실행됩니다. 자세한 내용: 수정 루프.
모델
렌즈 (Lens): 서빙의 단위입니다. 사용 사례(고객 이탈, 매출 커미션, 이사회 지표)가 공유된 시멘틱 자산, 접근 규칙, 그리고 자신의 시간대 위에 대해 선택을 받아 선언됩니다. 에이전트가 자연 스럽게 질문을 하면, 근거 있고 인용된 답을 얻습니다.
시멘틱 파일 (semantic files): 엔티티와 비즈니스 정의는 파일로 한 번 작성되고, 그를 선택하는 모든 렌즈가 함께 공유합니다. 하나의 지표, 하나의 정의; 에이전트가 사용하는 단어가 변하지 의미가 변하지 않습니다.
선별된 컨텍스트 (curated context): 렌즈가 근거로 사용할 수 있는 검토된 문(明) 목록. 각 항목은 명확하고, 출지를 확인할 수 있고 렌즈와 함께 버전이 정해집니다.
인증된 정답 (certified answers): 검토된 질문에서 SQL 쌍으로, 일치 시 그대로 서빙되고 dst test와 모든 dst apply에서 매번 회귀 테스트로 다시 실행됩니다. 고쳐진 실수는 이들 중 하나가 되고, 그래서 계속 고쳐진 상태로 남습니다.
관리: 접근은 여러분이 선택한 방식으로 관리됩니다: 사람과 그룹의 렌즈별 허용 목록, 호출자별 API 키 (dst_…). 요율 제한, 데이터베이스에서 강제되는 테넌트 분리(Postgres RLS). 저장된 웨어하우스 자격 증명은 저장 시 암호화됩니다.
관찰: 모든 호출이 추적됩니다. 어떤 렌즈, 어떤 호출자, 질문, SQL, AI + 웨어하우스 비용, 그리고 결과가 기록되고, 답변/거부/오류를 구분합니다. 답변은 검토에 보낼 수 있습니다: AI 판사가 근거 사슬(추론 추적)을 감사하고 필요한 경우 사람에게 에스컬레이션합니다.
에이전트가 인터페이스입니다
조회 UI는 없습니다. 소비자는 에이전트입니다: 어떤 MCP 클라이언트든(Claude Desktop, Claude Code, Cursor, 제품 안의 에이전트) URL과 범위가 한정된 dst_… 키만으로 관리되는 MCP 서버 /mcp에 연결하세요 (services/mcp/README.md). 모든 질문은 동일한 관리 파이프라인을 거치므로, 어떤 에이전트가 물어도 답은 동일합니다.
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인간은 루프 안에 있되, 질의 경로 안에는 있지 않습니다: 대시보드는 파일이 선언한 것을 관리하고 관찰하는 콕핏입니다 — 검토 큐, 드리프트 감사, 접근, 비용. 렌즈 크리에이션은 파일에서 수행됩니다 (dst init → 편집 → plan/apply), UI에서 수행하는 경우는 없습니다. (REST 문이 자체 도구를 연결하기 위해 존재합니다. (REST door exists: API 참조.)
프로젝트의 모습
프로젝트는 파일입니다: 버전이 정해지고, PR에서 검토되고, 인프라처럼 적용됩니다. 아래 내용은 dst init이 실제로 생성하는(직접 생성하는) 것을 약간 요약한 것입니다. 생성의 데모 semantic asset은 examples/ 아래에 들어가므로, 벌크로 폴더를 삭제해도 됩니다; 데모 렌즈 자체는 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
---이 매핑이면 충분합니다: 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 ordersname: 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거부나 명확히 묻는 것도 오류가 아닌 하나의 결과입니다: dst는 추측하지 않고 묻습니다.
빠른 시작
패키지를 설치합니다. 필요 환경: Python 3.12+, Docker(dst가 자체 Postgres를 운영합니다), 그리고 한 MHz 이상 모델 제공자의 API 키: 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 웨어하우스 위에 프로젝트를 스캐치 늘려 놓으므로, 실제 웨어하우스를 연결하기 전에 apply와 query가 동작합니다. 출시된 wheel에는 마이그레이션과 대시보드가 포함되어 있어 dst dev 둘 다를 http://localhost:8000에서 제공합니다. 게시자 시작이 기본 경로이며, 그 경로를 계속 따라 여러분의 웨어하우스에 이릅니다.
소스에서 실행
기여자 경로: 체크아웃으로 저장소를 받고, 저장소 자체의 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_… 관리자 토큰을 붙여 넣어 조직을 관리하세요. 검토 큐, 드리프트 감사, 호출자, 비용을 확인할 수 있습니다. 렌즈 자체는 파일로 작성됩니다. uv run dst init은 번들로 포함된 jaffle DuckDB 웨어하우스 위에 렌즈 하나를 스캐폴딩하므로, 실제 웨어하우스를 연결하기 전에도 uv run dst apply와 uv run dst query가 동작합니다. 소스를 체크아웃한 환경에는 dst가 PATH에 등록되지 않습니다. 모든 명령은 uv run dst …로 실행되며, Makefile 타깃들이 바로 그렇게 동작합니다.
에이전트가 렌즈를 질의하게 하려면: Settings에서 호출자 키를 발급하고, 그 키를 lens.yaml에 있는 렌즈의 허용 목록(allow-list)에 추가한 다음 uv run dst apply를 실행하고, 에이전트를 MCP로 연결하세요.
설정
설정은 .env에서 로드됩니다(services/config.py 참조). 주요 키는 다음과 같습니다:
변수 | 필수 여부 | 용도 |
| 예, 최소 한 개 항목 | 모델 제공자. 이름을 키로 하는 JSON(BYOK 방식이며, 공급자 이름이 붙은 키 변수는 없음). 유형: |
embedding provider | 컨텍스트 기능용 | 임베딩 모델을 제공하는 |
| 선택 사항 |
|
| 자격 증명을 저장할 때 | 저장된 웨어하우스/컨텍스트 자격 증명을 암호화하는 Fernet 키입니다. |
| 로컬에서는 기본값으로 충분 | 앱(RLS 적용, 비슈퍼유저) 계정과 관리자(마이그레이션/시더) 계정을 위한 연결입니다. |
| 선택 사항 | 호스팅 대시보드 인증용입니다. 이 값 없이도 로컬 로그인 + 관리자 토큰은 동작합니다. |
웨어하우스와 컨텍스트 소스의 자격 증명은 환경 변수가 아닙니다. dst.yaml에 secret_env 참조로 연결을 선언하세요( quickstart 참고). .env.example은 services/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개발
명령 | 하는 일 |
| 로컬 Postgres(pgvector) 시작/중지 |
| DB 마이그레이션 적용( |
| 개발 조직(org) 및 관리자 토큰 시드 |
| :8000에서 reload 모드로 API 실행 |
|
|
| 자동 포맷 + 수정 |
| 백엔드 테스트( |
| :5173에서 대시보드 실행 |
아키텍처: Postgres + pgvector 위의 FastAPI 백엔드(렌즈 설정, 컨텍스트 벡터 저장소, 요청 트레이스, 리뷰)가 여러분의 웨어하우스에서 읽습니다. 결과 집합 자체는 저장되지 않습니다. 트레이스가 보관하는 것은 질문, SQL, 만든 합성된 답변과 그 인용들입니다. 처음 몇 개의 결과 행은 렌즈가 logging.log_samples를 선택하는 설명된 답변과 인용만 보관합니다. 웨어하우스 프로파일링은 추가로 열별 통계와 저카디널리티 값 목록을 저장하며, exclude_columns에 지정된 열은 형태만 파악하고 값은 절대 수집하지 않습니다. dst는 개인 데이터를 분류하거나 마스킹하지 않습니다. 그 값이 네트워크 너머로 나가는 것을 원하지 않는 열은 노출을 피하세요. 대시보드는 동일 출처(same-origin) 또는 분리형 React SPA입니다.
사용자 문서는 docs/에 있습니다(퀵스타트, 개념, 가이드, 레퍼런스)이며 https://www.dataservetool.com에 게시됩니다. 컨트리뷰터용 하위 시스템 지도는 ARCHITECTURE.md입니다.
라이선자
Apache-2.0. 기여: CONTRIBUTING.md · 취약점: SECURITY.md · 이슈 및 질문: github.com/get-dst/dst/issues.
This server cannot be installed
Maintenance
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
- FlicenseNot gradedqualityNot gradedmaintenanceEnables 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.
- AlicenseNot gradedqualityCmaintenanceEnables 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.2MIT
- AlicenseNot gradedqualityCmaintenanceEnables AI agents to search, explore data lineage, understand business context, and generate SQL queries across an organization's data ecosystem.Apache 2.0
- AlicenseAqualityFmaintenanceA 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.9MIT
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.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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