Connect your AI
Connect Claude, Codex, Cursor or any MCP client, or call Unity's agent tools and HTTP API with a key: from nothing to a shared report, with the assistant's own tools.
Unity's own assistant works through a set of tools: it inspects the report and its data model, runs queries, builds pages and visuals, previews what it built, and shares the result. The same tools are available to your AI. Connect an MCP client, or call the tools over HTTP, and your model drives Unity directly with the same contracts, permissions and receipts. Every call runs as your account and respects its report access.
Choose an approach
| You want to | Use |
|---|---|
| Let an AI client (Claude, Codex, Cursor, your own agent) operate Unity | The MCP endpoint, https://api.x4tech.org/mcp |
| Give your own model Unity's tools in your application | GET /api/reports/{report_id}/tools and POST /api/reports/{report_id}/tools/{name} |
| Write a deterministic integration | The HTTP API reference and its OpenAPI document |
| Ask Unity's assistant to do the work | An agent run, POST /api/agent/runs |
All four reach the same operations. A change made one way is visible to the others. The agent tool reference lists every tool with its exact schema.
Connect an MCP client
Unity serves the Model Context Protocol over Streamable HTTP at https://api.x4tech.org/mcp. A client connects in one of two ways.
Sign in from your AI app
Add the server URL to your AI app and connect. The app opens Unity in your browser, you approve the connection, and the app receives its own access; there is nothing to copy. Menu names vary by client version:
- Claude (claude.ai, Desktop, mobile): add a custom connector with the URL, then select Connect.
- Claude Code: run
claude mcp add --transport http unity https://api.x4tech.org/mcp, then open/mcpin Claude Code and authenticate theunityserver. - Codex: run
codex mcp add unity --url https://api.x4tech.org/mcp, thencodex mcp login unity. - Cursor: add the server to
mcp.jsonwith only itsurl, then sign in from Cursor's MCP settings. - ChatGPT: add a custom MCP server (in Plugins) with the URL and OAuth authentication, then select Continue to Unity.
Unity's connection page shows which app is asking, where it returns you, and what it will be able to do. Allow changes is on when the app asks to change reports; turn it off to connect the app read-only. The app's access lasts an hour and renews itself while you keep using it; after 30 days without use, connect again. It works only with Unity's MCP server, not the rest of the API. See and disconnect your apps under API access & sessions → Connected apps.
Use an API key
- Sign in to Unity with a regular account (demo accounts cannot create keys) and open API access & sessions in the app panel.
- Enter a Token name, choose Expires in (7, 30, 60 or 90 days), and choose Access: Read only (
workspace:read) or Read & change (workspace:write, which also reads). - Select Create token, then Copy. Unity shows the secret once; if you lose it, revoke the key and create another.
Keep the key in a server environment variable or secret store and send it in the Authorization header, never in a URL, source control or browser code. Each key belongs to your account; another person creates their own. Revoke disables a key; Sign out everywhere revokes every browser session and key and disconnects every app. Revoking a key does not undo saved changes.
In Claude Code:
claude mcp add --transport http unity https://api.x4tech.org/mcp --header "Authorization: Bearer $UNITY_API_KEY"
Clients that accept a remote server with custom headers use the same two values:
{
"mcpServers": {
"unity": {
"url": "https://api.x4tech.org/mcp",
"headers": { "Authorization": "Bearer YOUR_UNITY_API_KEY" }
}
}
}
One report or all of them
Without a report in the URL, every report tool takes a reportId argument, and the server adds ListReports and CreateReport. Add ?reportId=YOUR_REPORT_ID to bind the server to one report: its tools then act on that report only, whether you sign in or use a key. An app connected to one report can create, attach, detach and test the connections that report uses, but cannot rename or delete connections, and it shares only that report.
The server also offers resources: Unity's guides at unity://docs/{topic} (for example unity://docs/sql), the HTTP API at unity://openapi.json, and the schema of a report definition at unity://schemas/report-definition.json.
Permissions
| Credential | What it permits |
|---|---|
Read-only connection or workspace:read key | Tools and requests that only read: inspecting, querying, previewing data and stopping a running read. |
Connection that allows changes or workspace:write key | Also the tools and requests that change a report, which need Edit access to that report. |
| Browser session | Account, API key, connected app and billing management; organization administration; typing a connection's credentials; changing an existing connection's settings. |
Scopes never override report roles. A write key does not make a View-only report editable, and sharing still needs the report's Owner or an Admin. Tools your access could never call are left out; a tool you could call with more access or a write key is listed with available: false and the reason, and calling it answers that sentence.
If a report was shared with you page by page, ListReports shows it with access level Pages and the pages you can reach, and the tools you are offered are scoped to those pages: reading them, the report's data model and queries as a View-access person has them, and, on a page you may edit, changing it.
From nothing to a shared report
An agent can build and share a report from an empty account over MCP alone:
CreateReport(unbound/mcp) returns the newreportId.- Connect data.
SaveConnectionwithtype,authTypeandconfig(where to connect and how, never a secret) creates a connection attached to the report;ReadUnityDocumentation topic=connectionslists each type's settings. If the sign-in needs credentials, the result hasneedsCredentialsand acredentialsUrl: give that link to the connection's owner, who opens it in Unity, sees exactly where the credentials go, types them and selects Save. Credentials never pass through the agent.TestConnectionthen discovers the tables. A public provider that needs no key (World Bank, US Census) needs no person at all. Or import a CSV file: attach it withAttachReportFile, thenImportCsvFileturns it into a data source. - Model it.
SaveReportModelSourcewithsourceMode: tablesmodels the tables; the model tools add relationships, calculated fields and measures. - Build pages.
CreatePageandCreateVisualbuild native pages (CreateVisual,UpdateVisualandDeleteVisualtake up to 100 visuals per call, all or nothing); the HTML tools build HTML pages.QueryReportDatachecks a visual's numbers. - See it.
PreviewPagereturns a screenshot of a saved page, native or HTML, as Unity renders it; MCP clients receive it as an image. - Share it.
InspectAccessshows who can open the report and each page.SaveAccessmakes one change per call: share the report or a page with a person (an email or user ID) or a team, set a page's audience, transfer ownership (confirm: true), or publish a page at a public link (publicLink: "create"withconfirm: true, since anyone with the link can see the page) and revoke it ("revoke"). Only the report's Owner and Admins see a link's URL. Sharing sends no email. - Export it.
GetReportDefinitionreturns the whole report as one JSON document.
UpdateReport renames the report, saves its instructions for agents, or deletes it (the owner only, with confirm: true). A report you delete stays in ListReports with its deletion's status until the deletion completes, then leaves the list. A rename and instructions make a report version, and so does attaching or detaching a connection (creating one attaches it); renaming or deleting a connection, and sharing, make none; a rename is recorded with the report's next change, as a version by Unity labelled "Changed outside the report".
Work the way Unity's assistant does
The tools are designed for an inspect, change, verify loop:
- Inspect.
InspectReportlists pages (HTML and native), visuals, layout and the report's instructions.InspectDataModellists entities, fields, measures and relationships.ReadUnityDocumentationexplains report SQL, visuals and HTML pages. - Query.
QueryReportDatareads what the report shows: a saved visual, a saved HTML dataset or a trial visual query, under the report's filters and your clicks.QueryDataModelruns report SQL (DuckDB) over the whole model, without the report's filters, including joins across sources and measures.QueryConnectionruns one source's own SQL. - Change. The changing tools save immediately and return a receipt. Read a resource before changing it and send the revision you read; a stale revision is refused with the current one (
currentRevision;currentVersionfor an HTML page'sbaseVersion). A model write's revision ismodelRevision, notreportVersion. A visual is named by itsvisualUidalone. - Verify.
QueryReportDatareads a saved visual's data;PreviewPageshows the page.
When someone else is editing what a call would change, the call is refused and nothing is saved (result.code element_held, page_held or page_busy); retry later. A call never takes over someone else's editing.
Call tools over HTTP
List the tools a report offers you, with their input schemas, then call one:
curl --fail-with-body "$UNITY_API_BASE/api/reports/$UNITY_REPORT_ID/tools" \
-H "Authorization: Bearer $UNITY_API_KEY"
curl --fail-with-body "$UNITY_API_BASE/api/reports/$UNITY_REPORT_ID/tools/QueryDataModel" \
-H "Authorization: Bearer $UNITY_API_KEY" \
-H "Content-Type: application/json" \
--data '{"arguments": {"query": "SELECT region, COUNT(*) AS customers FROM customers GROUP BY region", "rowLimit": 20}}'
The hosted base URL is https://api.x4tech.org. Each listed tool has name, description, access (view or edit), readOnly, inputSchema and available; pass the entries to your model as function definitions. Through these endpoints and MCP, a property that accepts null is optional, and a *Json parameter (and operation) takes the JSON value or its text. sessionId is optional: calls with the same session ID are recorded together in your change history.
Results and errors
A call that ran answers 200 with status, result and images; a call that saved a change also returns its reportVersion. status is error when the tool ran and refused, for example an invalid definition, a stale revision or confirm_required; result is {error, code, …}: error says what to change in one sentence, and code is stable to branch on (wrong_page_kind for a tool aimed at the other kind of page). A call that did not run is an HTTP error: 404 tool_not_found, 422 invalid_tool_arguments naming the failing field, or 403 for missing access or key scope. Over MCP the same refusals arrive as tool results with isError: true, and an unknown tool name is the JSON-RPC error -32602. A changing tool called with read-only access answers 403 insufficient_scope, so an app connected by signing in can ask you for more access. Over MCP you can make up to 1,500 tool calls every 15 minutes; past that, calls answer 429 with Retry-After.
Values stay exact: decimal columns are text such as "15913.23", and each column's valueEncoding says how its values are written. Every HTTP error carries error, message (the same text) and a code.
QueryReportData returns rowLimit rows (50 by default, at most 1,000) from pageIndex, for every target; its pagination (totalRows, returnedRows, hasMore, nextPageIndex) describes the whole result, so read on with nextPageIndex until hasMore is false. The pages of a table, matrix, paged dataset or trial query come from one copy of its rows, kept until 10 minutes after the last page. QueryDataModel and QueryConnection return up to rowLimit rows (at most 200) with hasMore.
Ask Unity's assistant
POST /api/agent/runs (workspace:write) queues Unity's assistant on one of your report chats (POST /api/datachats/add creates one) and returns 202. Poll GET /api/agent/runs/{run_id}/events?view=conversation, stream GET /api/agent/runs/{run_id}/stream, or stop it with POST /api/agent/runs/{run_id}/stop. With View access the run answers and queries but changes nothing. The HTTP API reference gives every parameter.
The report definition
GetReportDefinition exports the report as one JSON document, unityReportDefinition version 1: its name and instructions, the model (entities, fields by fieldUid, relationships, calculated tables and measures), every page (a native page's layout and visuals by visualUid; an HTML page's source, datasets and bindings), the saved filters, and the connections it uses by ID, name and type, never their settings or credentials. Lists keep the report's own order where it means something (page tabs, a model's tables and columns, a visual's dataset bindings), filters and connections are ordered by ID, and keys are sorted, so the same report always exports the same bytes and two exports diff cleanly. The JSON Schema is the MCP resource unity://schemas/report-definition.json and UnityReportDefinition in the OpenAPI document.
History and restore
Every saved change makes a report version, and a tool call that made one returns it as reportVersion. ListReportVersions lists them newest first (one assistant run or one burst of edits per entry; expand lists an entry's versions one by one), DiffReportVersions compares two, GetReportDefinition reads one, and RestoreReportVersion brings back the whole report, one page or a deleted page: a dry run first, then the restore with the dry run's expectedVersion and expectedWarnings. Version n is the report after change n, so to undo one change, restore the version listed before it. There is no other undo.
Questions about your environment? Contact us.