AI assistants (MCP setup)¶
DataQ ships a built-in MCP server so AI assistants — Claude Desktop, Claude.ai, VS Code / GitHub Copilot, Cursor — can answer questions like "what failed today?" or "run the orders suite" against your live DataQ instance, with the same per-suite permissions as the signed-in user.
Endpoint & authentication¶
The server is mounted on the deployed app at:
https://<your-dataq-host>/mcp/
Keep the trailing slash
/mcp answers with a 307 redirect to /mcp/, and some HTTP clients drop the
Authorization header when following redirects — which then surfaces as a
confusing 401. Always configure clients with the /mcp/ form.
The endpoint accepts the same credentials as the REST API (ADR 0008 / 0026): an OIDC bearer token (Azure AD or Cognito), or a DataQ API key (dq_live_…). Without a working sign-in configuration the endpoint is not mounted at all — it is never unauthenticated.
Email-OTP deployments: MCP works, with an API key
A deployment running email one-time codes instead of SSO (ADR
0032) has no identity provider to issue bearer
tokens, so an API key is the only /mcp credential there — mint one as
below and use it exactly the same way. Everything else is identical, including
all 50 tools and per-suite permissions. Two rejections are deliberate in that
mode: a raw JWT is refused (there is nothing to validate it against), and your
sign-in session is never accepted — it is a browser credential and does not
authenticate /mcp, whether presented as a bearer or carried as a cookie.
Getting a token¶
Recommended — a DataQ API key (PAT): mint one via POST /api/v1/me/api-keys
(see API keys) and use it as the bearer. It lives up to a year,
is revocable per-integration, and runs with exactly your per-suite access —
built for always-on MCP configs.
Quick one-off — your web session's OIDC token: sign in to the DataQ web
app, open your browser's developer tools → Application → Session Storage →
the oidc.user:… entry → copy the access_token value.
OIDC tokens expire after ~1 hour
The pasted browser token is short-lived; when the client starts getting 401s, paste a fresh one and restart the MCP server/connection — or switch to an API key and stop re-pasting.
Never commit a config that carries a token
Keep token-bearing MCP config files out of version control (in the DataQ repo
itself, .gitignore already covers .vscode/*).
Client configuration¶
Claude Desktop / Claude.ai (claude_desktop_config.json) — and GitHub Copilot (mcp.json):
{
"mcpServers": {
"dataq": {
"url": "https://<your-dataq-host>/mcp/",
"headers": { "Authorization": "Bearer <AZURE_AD_ACCESS_TOKEN>" }
}
}
}
VS Code (workspace .vscode/mcp.json, used by Copilot agent mode) uses a servers key — not mcpServers — plus an explicit type:
{
"servers": {
"dataq": {
"type": "http",
"url": "https://<your-dataq-host>/mcp/",
"headers": { "Authorization": "Bearer <AZURE_AD_ACCESS_TOKEN>" }
}
}
}
Start it via the command palette (Cmd/Ctrl+Shift+P) → MCP: List Servers → dataq → Start (or open Copilot Chat in agent mode — configured servers start on demand).
Cursor (~/.cursor/mcp.json) uses the same mcpServers shape as Claude Desktop.
The 50 tools¶
Each tool is a thin wrapper over the same service layer as the REST API — per-suite
authorization (view for a read, edit for a mutation) and failing-sample redaction apply
identically. The complete list — every tool, who can call it, and what it does — is the
MCP tools reference, generated from the server itself and
drift-checked in CI, so it cannot go stale the way an earlier hand-typed pass of this page did.
The tools split three ways, not two:
- Read-only (27) — reads gated on
viewwhere a suite is named; workspace-wide reads such aslist_suitesandget_health_scoreneed only a signed-in user. - Changes state (18) — every one gates on
editaccess to the affected suite (schedule, binding and incident tools via the suite they target);import_suiteadditionally requires the member workspace role, since it has no existing suite to gate on. - Live probes (5) —
profile_column,list_columns,dryrun_check,suggest_column_policy,test_connectionpersist nothing but open a live datasource connection with stored credentials. They are gated like writes, not reads, because they spend a real credential against a remote system: the first four requireediton the suite whose connection they probe, andtest_connection(which has no suite) requires the member workspace role.
Troubleshooting¶
| Symptom | Cause / fix |
|---|---|
| 401 on every request | Token expired (~1 h) → paste a fresh one. Or the client followed the /mcp → /mcp/ redirect and dropped the header → use /mcp/ directly. |
| 307 responses | Missing trailing slash — configure /mcp/. |
| Server absent / connection refused locally | The MCP server is unmounted unless the deployment has a working sign-in configuration — SSO (AZURE_*) or email OTP (AUTH_EMAIL_* + an allowlist); fail-closed by design. |
| 401 with an API key on an email-OTP deployment | Check you sent the API key, not your session cookie/token: in OTP mode a dq_live_… key is the only credential /mcp accepts. |
| Tool call returns "not found" for a suite you can see in the UI as someone else | MCP calls run as the token's user — suite access is per-user, same as the web app. |