Safety model
Use MCP as a governed capability boundary for agents.
MCP should expose a governed analytics layer, not a database console.
With hypequery MCP, the agent can only use the datasets you register. It receives tools for discovery and semantic querying. It does not receive a raw SQL execution tool.
What MCP constrains
- which datasets are visible
- which dimensions and measures can be requested
- which filter operators the tool schema accepts
- query execution through the dataset client
- tenant scoping when the server is configured with a trusted
tenantId
MCP can also expose relationship metadata through schema introspection, but current dataset execution is still same-dataset.
What MCP does not replace
MCP does not replace authentication, authorization, or tenant identity. The stock stdio server receives tool calls from a local MCP client and executes them through the analytics dataset client you provide.
Do not expose a shared multi-tenant MCP server unless the process is already scoped to one tenant. Treat MCP clients as powerful local operators, not public end-user clients.
Safer patterns
Prefer one of these patterns:
- run MCP for local development or internal admin use only
- expose only non-sensitive aggregate datasets
- run a tenant-specific MCP process with
tenantId - keep sensitive tables out of the exported
datasetsregistry - enable
includeSqlonly in trusted debugging sessions
Registry boundary
The exported datasets registry is the main boundary.
import { publishDatasets } from '@hypequery/datasets';
export const datasets = publishDatasets()
.publish(Orders)
.build();If a dataset is not in this object, the MCP server cannot list it, introspect it, or query it.
Tenant boundary
If registered datasets have tenantKey, the MCP server requires a trusted tenant scope. In the programmatic API, pass tenantId.
await createMCPServer({
datasets,
analytics,
tenantId: 'tenant_123',
});The server forwards that value into dataset execution as runtime tenant context. Agents should not choose tenant ids through filters.
With the CLI, pass the tenant as npx hypequery mcp --tenant <id>. It refuses to start for tenant-scoped datasets without one.
The standalone hypequery-mcp binary does not accept a tenant, so it cannot serve tenant-keyed datasets: startup fails with MCP server tenantId is required for tenant-scoped datasets. Use hypequery mcp --tenant or the programmatic createMCPServer({ ..., tenantId }) instead.
Either way, one server process serves one tenant.
Raw SQL boundary
The MCP server exposes semantic tools:
list_datasetsget_dataset_schemaquery_datasetquery_metric
It does not expose a generic run_sql tool.
Generated SQL and SQL-backed field expressions are also redacted from MCP responses by default. Programmatic servers can opt in with includeSql: true for trusted local debugging.
For the broader application boundary between semantic runtime input and trusted raw SQL APIs, see Trust Boundaries.