Use Remote MCP
How do you call remote MCP against the right account and workflow? Call it with the account’s OAuth grant, an explicit workflow ID on every scoped operation, and inline inputs. The server keeps account authorization between requests, but it keeps no selected workflow. Before you decide that the work finished, read the state the operation returned. A successful tool response can describe a failed execution or an approval nobody has answered.
Connect the account you intend to use
Section titled “Connect the account you intend to use”The endpoint is https://mcp.getcontroller.ai/mcp. It accepts JSON-RPC over stateless Streamable HTTP using POST. There is no persistent transport session and no server-initiated event stream.
Authentication uses an OAuth authorization-code flow with PKCE using S256, refresh tokens, dynamic client registration, and Client ID Metadata Documents. Let your host perform that flow.
In the app: Connect provides coding-assistant setup. During MCP authorization, choose My Controller account or Separate agent account. The existing-account path opens /connect/mcp, headed Connect your Controller account. Review the signed-in account there, then select Connect account.
With an assistant: call account_status with {}. Inspect credentialKind, grantedScopes, account.kind, and account.appUrl. Account kinds include member, agent, and claimed. The local counterpart is cai auth status --json. Its credential and machine context differ from MCP’s host-managed OAuth result.
| Scope | What it permits | What to check |
|---|---|---|
controller:read | Read-only tools. | It cannot authorize a write operation. |
controller:full | Read and write tools. | Resource permissions and operation-specific requirements still apply. |
For account claiming and revocation, use Assistant access and security.
Choose tools separately from permissions
Section titled “Choose tools separately from permissions”The CLI 0.2.24 catalog has 149 typed MCP tools derived from 166 CLI operations. Do not work out a tool name by respelling a command. An operation can be combined with another, split, replaced by a server handler, or left out. The MCP reference records the command counterparts.
To narrow the catalog to a few families, use the plural query parameter, for example https://mcp.getcontroller.ai/mcp?toolsets=workflow,flow,run,execution. The selection limits both discovery and calls. If you omit it, the selection is all.
| Preset | Included work | Boundary |
|---|---|---|
build | Every tool except the agent family. | Includes writes. |
agents | Agents, connections, integrations, account, and guides. | Includes writes. |
read | Read-only tools plus account and guide tools. | Selection alone does not prohibit writes. |
Account and guide tools stay listed whatever you select, including the writes account_claim_start, account_claim_verify, and file_share. If you need read-only access enforced, use https://mcp.getcontroller.ai/mcp/readonly. That route rejects every known write, even with a Full grant.
tools/list normally returns the whole selected catalog. If it returns nextCursor, request the next page.
Carry the Invoice workflow ID through every call
Section titled “Carry the Invoice workflow ID through every call”In the app: open Workflows → Invoice intake, select Check invoice, and use Test current flow for the development test. Select Dev before you test, then inspect the returned run through Run history.
With an assistant: the CLI examples below assume no workflow pin, so they pass --workflow <workflowId> explicitly. MCP always requires workflowId on a scoped call. Start by listing the workflows:
cai workflow list --jsonNote Invoice intake’s data.items[].id. The commands that follow use it as <workflowId>. For MCP, call workflow_list with {}.
Next, list the flows in that workflow:
cai flow list --workflow <workflowId> --jsonNote Check invoice’s data.items[].id as <flowId>. For MCP, call flow_list with workflowId.
Before you run anything, read back the input keys that flow accepts:
cai run inputs <flowId> --flow --workflow <workflowId> --jsonFor MCP, use run_inputs with workflowId, the discovered flow ID as nodeIdOrFlowId, and flow: true.
Development runs execute configured provider actions and spend usage. Inspect the flow you selected before you test it. When those inputs accept Invoice ID and Amount, run the fixture INV-104 / 120:
cai run flow <flowId> --workflow <workflowId> --target dev --inputs '{"Invoice ID":"INV-104","Amount":120}' --timeout 60000 --jsonFor MCP, use run_flow with workflowId, flowId, target: "dev", the parsed inputs object, and waitSeconds: 60. The CLI timeout is in milliseconds.
A live MCP run requires both target: "live" and confirmLive: true.
Check the fixture result against its business rule. INV-104 / 120 should return invoice_id: "INV-104" and review_needed: false, and INV-105 / 1500 should need review. These are the Invoice example’s rules, not built-in validation. If the execution finishes but those values are missing, inspect the Return response and the resolved inputs before you report success.
Keep later calls scoped to the same workflow, including the reads you make after an error. A fresh MCP call cannot use a local terminal’s workflow pin. Calls that share an OAuth grant run one at a time. An overlapping call waits up to 1.5 seconds for the lock, then receives a busy error if the lock stays occupied. Wait for the in-flight call to finish, inspect its result or the state it changed, and only then retry the rejected call.
Supply inline content
Section titled “Supply inline content”Remote calls cannot read a file on your computer. Supply parsed objects for inputs, and inline text for file-backed parameters. Agent instructions go in instructions, and a CSV import goes in content.
Data writes require an explicit env: "dev" or "live". For CSV, validation and commit are separate tools. Both require workflowId, type, env, and CSV content, and their headers use field display names. data_record_import_validate writes nothing. data_record_import_commit validates during the call, appends the valid rows, and skips the invalid ones. Validating first is recommended, not required. Running commit a second time appends the valid rows again, so read the counts and query the same store before you retry. Follow Import and move data before committing invoice records.
A JSON value bound to a CLI flag has a 32 KiB serialized limit. File-bound content, JSON included, has a 2 MiB UTF-8 limit. file_share accepts name, content, optional encoding (utf8 or base64), and optional mimeType, with a 2 MiB decoded limit. If you omit mimeType, it is inferred from the extension or defaults to application/octet-stream. Show the returned download link and its expiry to the person.
Runtime validation rejects unknown parameter names. It caps ordinary unpatterned strings at 32,768 characters, arrays at 1,000 items, and objects at 256 properties. File-bound root strings use the file ceiling. An individual schema can impose smaller limits or cross-field requirements.
Read the result before repeating work
Section titled “Read the result before repeating work”Inspect structuredContent.data, any warnings, and the returned events. isError: false means the tool returned a usable result. The workflow can still be failed, paused, or unfinished. An agent can be waiting for permission.
When the serialized result exceeds 96 KiB, the server returns dataPreview and outputArtifact with the complete result’s link. Fetch that artifact before treating the preview as complete.
When you download a large result, read outputArtifact.uri, mimeType, size, and expiresAt from the response. Private artifacts hold up to 10 MiB and expire after 24 hours by default. Use the returned expiry for the actual link. Revoking the artifact’s OAuth grant also removes access to it. Download an invoice report the person needs to keep before that link expires.
The transport separately caps a tool response at 140 KiB, and HTTP requests and responses at 16 MiB. Those outer limits do not increase any operation’s input allowance.
If outcomeUnknown, timedOut, outputLimitExceeded, or postExecutionError appears, inspect the existing state before you retry a write. The execution or the output delivery may have failed after the operation took effect.
Continue the execution you already started
Section titled “Continue the execution you already started”agent_test and agent_conversation_create both require rail. "draft" selects the current draft, and "live" selects the published version.
run_flow, run_node, agent_test, agent_conversation_send, and approval_resume accept waitSeconds, which defaults to 60 and is capped at 120. Zero minimizes the waiting. It does not cancel the operation.
| Returned identity | Next MCP call | Required context |
|---|---|---|
workflowExecutionId | execution_get | The same workflowId and workflowExecutionId. |
conversationId | agent_conversation_status and agent_conversation_history | That conversationId. |
approvalId | approval_resume | That approvalId. |
Keep each returned ID and pass it verbatim to the next MCP call. Page through execution_tree with the same workflow and execution IDs, passing its nextCursor as cursor. For one row’s detailed inputs, resolved configuration, and output, use execution_node_get.
For an agent approval, read the pending requestId from conversation history. Use agent_conversation_approve or agent_conversation_deny only for the person’s decision. Do not send the message again. agent_test creates a new conversation on every call.
When the task moves to another area, fetch the relevant skill with guide_list and guide_get. guide_get takes a name from the list, and returns instructions plus reference files from the server’s installed bundle. It does not inspect or update the skills on your computer.