Skip to content

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.