ixi MCP server
Connect Claude, Cursor, or any MCP client to your ixi workspace. The agent can then browse your canvases and files, inspect processes and pipelines, run them, read the results back, and write the code in your sandbox nodes.
The server is at:
https://api.ixi.so/mcp
Authentication is OAuth — you sign in to ixi and approve the connection in your browser. There is no API key to copy, and the connection is scoped to you: the agent sees exactly the canvases, orgs and processes your own account can see, and nothing else.
Setup
You need an ixi account with access to at least one org. That is the whole prerequisite — there is no key to create and nothing to install.
Claude.ai / Claude Desktop
- Open Settings → Connectors.
- Click Add custom connector.
- Paste
https://api.ixi.so/mcpas the URL and save. Leave the OAuth Client ID and Secret fields empty — the server registers your client automatically. - Click Connect. An ixi sign-in opens in your browser; sign in and approve.
- The connector shows as connected, and ixi's tools appear in the tool menu of any new chat.
On Team and Enterprise plans, an Owner adds the connector once under Admin settings → Connectors. Everyone else then clicks Connect and signs in with their own ixi account — each person's access is their own.
Claude Code
claude mcp add --transport http ixi https://api.ixi.so/mcp
claude mcp login ixi # opens the browser for sign-in
claude mcp list # should show: ixi — connected
Add --scope user to make the connection available in every project rather than just the
current one.
Cursor, MCP Inspector, and others
Any client that speaks streamable HTTP MCP with OAuth works. Point it at
https://api.ixi.so/mcp; discovery, registration and consent are automatic. For a bare
.mcp.json-style config the entry is:
{
"mcpServers": {
"ixi": { "type": "http", "url": "https://api.ixi.so/mcp" }
}
}
Check it worked
Ask the agent:
List my ixi orgs.
It should call list_orgs and come back with the orgs you belong to and your role in each.
If that works, everything else will — every org-scoped tool starts from an org id.
A good second thing to try, which exercises the whole read path:
Find a process in my ixi workspace and tell me what inputs it takes.
Troubleshooting
| What you see | What it means |
|---|---|
| Sign-in loops, or the connector never reaches "connected" | The URL must be the full https://api.ixi.so/mcp, including the path. A trailing slash or a bare hostname will not complete discovery. |
| Connected, but no ixi tools in the chat | Clients cache the tool list. Disconnect and reconnect the connector, or start a new chat. |
| Everything returns "not found" | You are signed in as a different ixi account from the one with access. Run list_orgs — if it comes back empty, that account is not in any org yet. |
| "…is outside your workspace" when running something | You can read that process but not run it. Running spends its org's credits, so it is limited to processes in an org you belong to. |
| A run never seems to finish | Runs have no completion event. Check attention on get_run — if it is set, the run asked a question and is waiting for a person in the ixi app. |
Claude Code times out on get_run | Lower waitSeconds, or raise the client's tool timeout (MCP_TOOL_TIMEOUT). Waiting is optional; polling always works. |
Vocabulary
The tools use ixi's own words, and getting them straight makes the rest obvious.
| Term | What it is |
|---|---|
| Canvas | A board of nodes and edges. |
| Process | A canvas made reusable, with declared inputs. It is referenced from a node on a host canvas. |
| Run | One execution of a process — itself a canvas, worked by a pixie (an agent). Takes minutes. |
| Pipeline | Processes chained together. |
| Session | One execution of a pipeline. |
| Table | Rows of data. A column can be bound to a process, so filling it runs that process once per row. |
| Sandbox | A node whose content is code — a live React/HTML frame, or a script returning JSON. |
| Org | A workspace. Most tools take an org argument — call list_orgs first. |
Runs have no "finished" event
A run is finished when its status is idle and it has published at least one result.
There is no terminal state to wait on, so:
get_runreportsstatus,publishedCountand a computedfinishedflag.- Pass
waitSecondsto haveget_runwait instead of you polling. It returns early when the run finishes, and reports progress while it waits. - If a run comes back with
attentionset, it asked a question or raised a review card. It will not move again until a person answers it in the ixi app.
Tools
Orientation
| Tool | What it does |
|---|---|
list_orgs | The orgs you belong to, with your role. The starting point for org-scoped tools. |
resolve_link | Turn a pasted ixi URL or bare id into what it actually is, with the ids other tools need. |
list_assets | Files produced by a run (runId) or sitting on a canvas (canvasId, optionally one nodeId). |
Canvases
| Tool | What it does |
|---|---|
list_canvases | List or search your canvases. |
read_canvas | Full contents of a canvas: nodes, edges, metadata. |
where_used | Which canvases reference a given entity. |
create_canvas | Create an empty canvas. |
add_nodes, edit_node, delete_node, connect_nodes | Edit a canvas. Changes appear live in any open browser tab. |
run_model | Run a single model synchronously and return its output. |
Sandboxes (code on the canvas)
A sandbox node holds source code: kind render is a React or HTML frame drawn
live in the canvas, kind script is JS that returns JSON. An agent can author and
iterate on them here.
| Tool | What it does |
|---|---|
sandbox_guide | The authoring contract — entry files, how inputs reach the code, the pinned imports, timelines, media loading. Read it before writing sandbox code; none of it is guessable. |
list_sandboxes | The sandbox nodes on a canvas, with file names and sizes. Use this instead of read_canvas, which inlines every file in full. |
read_sandbox | One node's code, inputs, assets, timeline, last run, and lastLogs — the captured tail of the frame's console output. |
create_sandbox | Add a sandbox node. Syntax-checked before it saves. |
update_sandbox | Change files, inputs, schema, timeline, presets, assets. Files merge per file; delete_files removes. |
edit_sandbox_file | Exact-string replacement inside one file — the safe way to change a few lines. |
peek_sandbox | A still of the live preview, recording nothing. The cheap edit → peek → look → fix loop. |
run_sandbox | Run it for real; the result lands in the node's tray and feeds downstream nodes. Pass inputs to call it like a function. |
Nothing broken is ever saved: code is syntax-checked on the way in, and a file that fails to parse is rejected with its line number while the node keeps its old code.
Presets are named snapshots of a sandbox's input values, cycled with arrows in the
node's settings panel — the way a person reaches the good-looking combinations without
re-tuning five controls. Pass presets: [{ name, values }] on create or update. They
merge by id rather than replacing the list, because the user saves their own
presets from that same panel: send only what you are adding or revising, keep names
stable to revise one in place, and use delete_presets to remove one.
Two limits worth knowing before you start:
peek_sandboxandrun_sandboxneed a browser tab with that canvas open. A render sandbox draws in the tab, so it is where a still or a run actually happens. With no tab open they time out and say so. Editing and reading need no tab.- Org secrets are off-limits. A script can reference vault keys as
$IXI_SECRET:NAME, so a node that declares any is readable, configurable and runnable here but its code cannot be edited through MCP, and secret names cannot be declared. Set those up in the ixi app or with a pixie. This keeps a connected agent from declaring a key and writing code that sends it elsewhere.
Processes
| Tool | What it does |
|---|---|
search_processes | Find runnable processes. Returns templateId plus the host originCanvasId / originNodeId — trigger_process needs all three. |
describe_process | A process's declared inputs, the team's notes about them, its stages, and its pixie. |
trigger_process | Start a run. Returns a runId immediately. |
get_run | Status and published results. Optional waitSeconds. |
list_runs | Page the runs of one process node, with search. |
A typical loop:
list_orgs → search_processes → describe_process → trigger_process → get_run(waitSeconds: 55)
Pipelines
| Tool | What it does |
|---|---|
describe_pipeline | Input fields, cards in dependency order (step 0 = entry), wiring, and existing sessions. |
trigger_pipeline | Create a session and start it. Returns a sessionId. |
get_pipeline_session | Per-card status. The session is settled when live is 0. |
list_pipeline_output | The session's deliverables, ordered by step. |
A pipeline refuses to start while a required input is missing — the error names which.
Tables
| Tool | What it does |
|---|---|
list_tables | The org's tables, with columns and row counts. |
describe_table | Every column, and which ones are bound to a process (derivedColumns). |
query_table | Search and page rows. q is hybrid keyword + semantic search; filters and sort work per column. |
run_table_column | Run a process across rows by filling a process-bound column. |
run_table_column is how you run a process over a batch. Pass rowIds to choose exactly
which rows, or limit to take the next N unfilled ones. It is capped at 50 rows per
call — an over-cap request is refused rather than quietly trimmed.
Limits
- Runs started over MCP are capped per account per day (100 by default), on top of your normal account run quota. A batch counts as its whole row count.
- Credits are spent by the org that owns the process you run — the same as running it from the app. A run that would exceed the org's balance is refused before it starts.
- Reading is not running. You can read any canvas shared publicly with you, but you can only run a process that lives in your own workspace, because running it spends its org's credits and publishes into its tray.
- Every run started through MCP is written to your org's audit log.
Protocol notes
For people building clients rather than using one.
- Transport: streamable HTTP, stateless.
POSTonly;GETandDELETEreturn405. No session id is issued. - Protocol revisions: the current
2026-07-28(viaserver/discover, noinitializehandshake) and the legacy2025-03-26→2025-11-25era, on the same URL. The server answers whichever the client speaks. - Auth: OAuth 2.1 resource server. Unauthenticated requests get
401with aWWW-Authenticate: Bearer resource_metadata="…"challenge pointing at/.well-known/oauth-protected-resource; dynamic client registration and PKCE are supported. - Tool results carry both
structuredContentand a serializedtextblock, so older clients lose nothing. - Errors: a problem with your request (no such canvas, over the cap, not your org)
comes back as a normal result with
isError: trueand a readable message, not a JSON-RPC error. - Progress: send a
progressTokenin a request's_metaandget_runwithwaitSecondswill streamnotifications/progresswhile it waits.
See also
- Pixie Run API — start runs from your own server with an org API key, and host the run's conversation in your frontend.
- Table API — canvas tables as a headless CMS over REST.