Agents over MCP¶
Point your agent at dst's MCP server instead of the warehouse's. An agent holding warehouse credentials authors its own SQL — a better-informed agent with the same unchecked reach. An agent holding a dst caller key gets the answer path: governed vocabulary, guarded read-only SQL, receipts, and a scope you set per agent.
Setup¶
Mint one key per caller — a person or an agent, never a shared team key — then register the server:
dst keys create --caller support-bot
claude mcp add dst http://localhost:8000/mcp --transport http \
--header "Authorization: Bearer dst_..."
The server is mounted at /mcp on the API itself (services/mcp/server.py:91); each
request carries its own bearer key, so any MCP client that speaks streamable HTTP works.
For a local stdio client, run the same module directly with the key in a DST_API_KEY
env var. Revoke a key with dst revoke-key or from the dashboard.
The tools¶
Eight tools (services/mcp/server.py):
| Tool | What it does |
|---|---|
route_query |
the default door — dst picks the lens or declines; on a decline you get covered: false with a reason and nearest miss, never a wrong-lens guess |
query |
ask a named lens |
list_lenses / describe_lens |
what this caller may see: schema, definitions, certified count |
search_certified |
similarity-ranked certified answers |
run_certified |
deterministic run of approved SQL — auto-resolves only at ≥0.95 similarity, otherwise returns no_exact_match plus near-misses |
send_for_review |
flag an answer; a note and corrected SQL become a correction the review loop turns into a fix |
review_status |
poll a ticket |
Plus a getting_started prompt. Every tool returns a uniform envelope — {"ok": true, …}
or {"ok": false, "code": auth|forbidden|not_found|rate_limited|no_exact_match|upstream|
unreachable, "error": …} — so agents branch on ok and code, never parse prose.
Scoping a lens per agent¶
Access is deny-by-default: a caller can query a lens only if the lens's lens.yaml
grants it (services/contracts/lens_config.py):
access:
allow:
- caller: support-bot
pii_policy: redact
list_lenses and route_query operate over the caller's accessible lenses only
(services/api/query.py:152, services/api/route.py) — an agent cannot route into, or
even see, a lens it was not granted. Rules match a caller by name or by group, carry a
per-caller PII policy (redact by default) and per-caller rate limits, and every call is
attributed to the caller in the audit log. One agent, one key, one scope: the agent for
support sees the support lens and nothing else.
Grants are edits to lens.yaml — change the file, dst apply, done. The same
deny-by-default rule governs humans and applications; agents are just callers.