API & MCP Tool Reference
A structural reference to the Nexus programmatic surface — the REST API organized by area, the authentication model for users and automation, and the embedded MCP server that mirrors it under the same RBAC.
This page is for developers and AI-agent builders who will drive Nexus programmatically. It maps the two surfaces Nexus exposes — a REST API and an embedded Model Context Protocol (MCP) server — organized by functional area, and describes the authentication and authorization that both share. It is a structural reference: it tells you what areas exist, what each is responsible for, and which identity and permission each requires. For the exact, version-pinned request and response shapes of every REST route, treat your own tenant's /openapi.json as authoritative — it is generated from the running server and always matches the image you are on.
Two surfaces, one policy engine
Nexus has exactly one authorization model. Whether a call arrives over REST or over MCP, it resolves to the same identity, the same RBAC grants, the same per-resource scoping, and the same audit trail. There is no "API-only" back door and no MCP-only escalation. This is the single most important fact for a security reviewer: you audit the permission model once, and it governs both surfaces.
| Surface | Path | Transport | Typical client |
|---|---|---|---|
| REST API | /api/* |
HTTPS, JSON | Desktop app, Excel add-in, custom integrations, CI jobs |
| MCP server | /mcp |
Streamable HTTP (one POST per JSON-RPC call) | Claude Code, Claude Desktop, custom MCP agents |
| OpenAPI schema | /openapi.json |
HTTPS, JSON | Codegen, API explorers, contract tests |
Both surfaces run on your tenant's Container App, inside your Azure subscription. There is no Stingray-hosted API gateway in the path — the endpoint you call is the one deployed into your tenant. See Architecture for the deployment topology.
Authentication
Every request to /api/* and /mcp carries a Bearer token. Nexus recognizes two principal types, and the difference between them is central to how you design automation.
User tokens (OAuth2 + PKCE)
Interactive users authenticate against Microsoft Entra ID using the OAuth2 authorization-code flow with PKCE. The desktop app performs the flow in the system browser and stores the resulting tokens in the OS keyring (Keychain / Credential Manager / Secret Service) — never on disk in plaintext. A user token carries the user's tenant role (the built-in Reader or Admin, or a custom role) and all per-resource grants attached to that identity.
- Refresh is handled by the client; expired access tokens are exchanged transparently.
- The token is bound to a single tenant. Multi-tenant desktop users hold a separate token per server, each in its own keyring slot.
- A user token acting through the MCP server acts as that user — an agent can never exceed the human's own permissions.
Application tokens / API keys (automation)
Unattended automation — CI jobs, schedulers, backend services — authenticates as a registered application principal. An Admin registers the application, which yields a client credential; the application requests a scoped token via the client-credentials flow. Application principals are first-class in RBAC: they carry their own roles and their own per-resource grants, independent of any user.
Application tokens are deliberately constrained relative to users:
- They resolve service-level bridge credentials only — an app token can never read a user-scoped bridge credential belonging to a human. This is the service-bridge / user-bridge isolation boundary described in Connections & Bridges.
- To reach the MCP server, the application must have MCP access explicitly enabled by an Admin. It is off by default.
- Writes to executable or human-authored content — pipelines, Sites, and skills — reject app tokens outright. Those are human-only operations regardless of the app's role. Automation can run a pipeline (with Admin) but cannot author one.
What the token gates
Authorization is layered on top of authentication in a fixed order:
- Transport gate — the MCP endpoint rejects plain Reader accounts at the transport level before any tool dispatch.
- Role gate — the tenant role (the built-in Reader or Admin, or a custom role) sets the floor for an operation.
- Per-resource grant — scoped grants can widen or narrow access to an individual pipeline, report, bridge, file, Site, or tool for a specific principal.
- Execution role — a pipeline or report can pin a curated execution role so it runs with exactly the access it needs and no standing elevation.
The full model, including assume-role and admin edit-locks, is in Roles & RBAC and Execution Roles.
The REST surface by area
The REST API is organized into functional areas under /api/. The table below is the structural map; for the exact route paths, methods, and payload schemas, read your tenant's /openapi.json, which is generated from the same server build you are running.
Bridges & query
Read and write data through the bridges configured for your tenant. This area covers listing available bridges, discovering a bridge's schema (collections, fields, sample rows), and executing read or write queries expressed in UQL. Reads require the read permission (the Reader floor or a custom role carrying it); writes require Admin and are additionally gated per-adapter by writability rules (views, formula columns, and read-only collections are blocked). The engine's pushdown-versus-in-engine behavior is the same one documented in UQL & the Capability Model — the API returns a per-query log so you can see exactly which predicates were pushed down.
Reports
Create, read, update, and execute saved reports. Report definitions are versioned authored entities (see version control below); report execution runs a stored report and returns the engine envelope. Execution is subject to per-report access grants on top of the role floor. See Reports.
Pipelines & runs
Pipeline definitions are Python modules managed as versioned entities; the run lifecycle — start, dry-run, cancel, list runs, fetch a run record, fetch diagnostics and logs, and process approvals — is a separate set of operations. Starting a live run requires Admin; dry-running requires the read-level floor (the Reader role or a custom role carrying the permission). Cancellation requests cancellation and is best-effort, not a guaranteed kill — see Cancellation. The full state machine is in Run Lifecycle.
Sites
Manage per-tenant hosted Sites: the Site config plus its file assets. Site writes are human-only (app tokens are rejected). Text assets go through the standard save path; large or binary assets use the dedicated file-upload path. See Sites Overview.
Files
Store and retrieve tenant files and file references used by pipelines and reports. File bytes are uploaded through a dedicated multipart/upload path — you do not inline file content as base64 in a JSON body. File references let a pipeline address a stored artifact by ID. See Files.
RBAC & administration
Manage users, application registrations, roles, and per-resource grants; inspect effective permissions for a principal; register and rotate application secrets. All of these require Admin. User-management operations reject app tokens. This area is where you wire up the identity and access model that every other area enforces. See Users and Roles & RBAC.
Version control
Every authored entity — pipeline, report, Site, skill — is backed by a per-tenant git repository on Azure Files. This area exposes history, diff, and restore across all four kinds, plus repository status. Reading history requires the Reader floor (vcs:read); restoring requires Admin (vcs:restore) and is human-only. See Version Control.
Secrets & connections
Manage bridge connections and the secrets that back them. Secret values are stored in your per-tenant Key Vault and are never returned through the API — you set and rotate them, you never read them back. See Secrets and Connections & Bridges.
Operational endpoints
A small set of unauthenticated or lightly-scoped endpoints support health checks and schema discovery (/openapi.json). Health endpoints are intentionally minimal and do not leak internal pod identity. These are for your own monitoring; they are not a data surface.
The MCP mirror
The MCP server at /mcp exposes the same capabilities as tool calls, so an AI agent works through the identical policy engine. The tools below are grouped the way the REST surface is; the mapping is intentionally close so that a permission you understand on one surface behaves identically on the other. Full connection instructions and troubleshooting live in Connecting AI Agents and The MCP Server.
Unified entity surface
Nexus manages four kinds of authored entity — pipeline, report, site, and skill — behind a single verb set. There is no per-kind tooling to learn.
| Tool | Purpose |
|---|---|
uql_list(kind, search?, limit?) |
List entities of a kind, with optional search filter |
uql_get(kind, id, ref?, sub_path?) |
Read the current definition, or any past revision via ref (commit SHA) |
uql_save(kind, id, content, sub_path?, meta?) |
Create or update (upsert); validates then auto-versions |
uql_delete(kind, id, sub_path?) |
Delete an entity (records a deletion commit) |
uql_validate(kind, content, sub_path?) |
Validate content without saving |
uql_history(kind, id, limit?) |
Commit log for the entity, newest first |
uql_diff(kind, id, ref_a, ref_b?, sub_path?) |
Unified diff between two revisions |
uql_restore(kind, id, ref, sub_path?) |
Restore to a prior revision (creates a new commit) |
uql_status() |
Repository HEAD, per-kind commit counts, and projector status |
Every save goes through a single commit point — validate, then write, then commit to the per-tenant git repository exactly once. No-op saves (identical content) produce no commit.
Content format by kind
| Kind | content format |
Notes |
|---|---|---|
pipeline |
Python source text (async def run(ctx)) |
Requires Admin; write-protected from app tokens |
report |
JSON report definition (object or string) | report:read / report:update |
site |
JSON site config (no sub_path) or text asset (sub_path = file path) |
Human-only writes |
skill |
Markdown text | Human-only writes; skill:read / skill:manage |
For Site assets, supply sub_path to address the file within the Site (for example, index.html or app.js). Large or binary Site assets go through uql_put_site_file instead of uql_save.
Data tools
These tools query and write the data bridges configured for your tenant.
| Tool | Purpose | Permission |
|---|---|---|
list_bridges |
List available bridge names | Reader |
discover_schema |
Inspect collections and sample data for a bridge | Reader |
query_data |
Read rows, or write (insert / update / delete) | Read: Reader; Write: Admin |
execute_report |
Run a saved report and return results | Reader (subject to per-report access) |
Discovering and querying a bridge
Before querying a bridge for the first time, call list_bridges to confirm the bridge name, then discover_schema to understand the collections and field types available.
list_bridges()
→ ["salesdb", "monday"]
discover_schema(bridge="salesdb", collection="orders")
→ { "fields": [...], "sample": [...] }
query_data(bridge="salesdb", collection="orders", operation="read",
where={"status": {"$eq": "open"}}, limit=100)
→ { "data": [...], "total_rows": 42, ... }
Report execution response
execute_report returns the raw engine envelope. Multi-row reports:
{
"data": [ /* row objects */ ],
"result_type": "...",
"query_count": 2,
"total_rows": 137,
"queries": [ /* per-query log */ ],
"features_used": { "joins": 1, "group_by": false, "post_processing": false }
}
Single-aggregation reports return a scalar shape instead:
{ "result": 48250.00, "aggregation": "sum", "field": "amount",
"query_count": 1, "total_rows": 137 }
Consumers should check for data (rows) versus result (scalar) before reading the payload. The queries log tells you which predicates were pushed to the source and which were evaluated in-engine — see the capability model in UQL & Pushdown.
Pipeline execution tools
Pipeline CRUD uses the unified entity surface (kind="pipeline"). The tools below cover the run lifecycle only.
| Tool | Purpose |
|---|---|
uql_execute_pipeline |
Start a live pipeline run (Admin) |
uql_test_pipeline |
Dry-run a stored pipeline (any Reader) |
uql_cancel_pipeline |
Request cancellation of a run (best-effort) |
uql_list_pipeline_runs |
Summary list of runs for a pipeline |
uql_get_pipeline_run |
Full run record including step outputs |
uql_get_pipeline_run_diagnostics |
Events, stderr, and traceback for a run |
uql_get_pipeline_run_logs |
Raw log stream for a run |
uql_list_pending_approvals |
Runs waiting for human approval |
uql_approve_pipeline / uql_reject_pipeline |
Process an approval step (Admin) |
Internal workspace tools
Nexus provides an isolated internal Postgres workspace for each tenant — useful for intermediate results, lookups, and cross-pipeline data sharing. It has its own database and its own managed identity, and is structurally isolated from the Nexus operational tables (UQL against the workspace literally cannot reach them).
| Tool | Purpose |
|---|---|
uql_workspace_info |
Check workspace availability and readiness |
uql_workspace_list_tables |
List tables and columns in the workspace |
uql_workspace_create_table |
Create a new workspace table (Admin) |
uql_workspace_add_column |
Add a column to an existing table (Admin) |
uql_workspace_drop_table |
Drop a table (Admin) |
uql_workspace_query |
Read or write workspace rows |
Workspace writes (update, delete, create) require the Admin role. See Internal Workspace.
Skills
Skills are tenant-authored markdown playbooks that agents pull on demand via the same unified verb set.
uql_save(kind="skill", id="sales-playbook", content="# How to query orders\n…")
uql_get(kind="skill", id="sales-playbook")
Nexus also ships a set of first-party system skills — image-baked authoring guides that appear in uql_list(kind="skill") with is_system=true. They are version-pinned to the running image and cannot be modified. The nexus system skill is the recommended starting point for any new agent session. See Skills.
Errors and idempotency
- Errors are returned as structured JSON with a machine-readable code and a human message; HTTP status reflects the class (4xx for client/permission errors, 5xx for server faults). MCP tool calls surface the same error content in the JSON-RPC result.
- Auth failures return 401 (missing/expired token) or 403 (authenticated but not permitted). A Reader hitting
/mcpis rejected at the transport layer. - Writes are not automatically retried for you. If a call fails after a write may have landed, reconcile by reading current state rather than blindly re-issuing. Pipelines you author should be designed idempotent — see Retries & Idempotency.
- Version-controlled saves are naturally idempotent: an identical
uql_saveproduces no new commit.
What this reference does and doesn't give you
- It does give you the structural map, the identity model, and the permission each area requires — enough to design an integration and reason about its blast radius.
- It does not enumerate every route path and field schema, because those are version-pinned to your running image. The authoritative, always-current contract is your tenant's own
/openapi.json. Generate clients from that, not from a copied path list. - For agent-specific behavior (session handling, pairing, the desktop loopback proxy), read the MCP pages rather than this one.