Skip to main content
An automation is a FlowPlan — a small JSON graph of steps behind a trigger — that runs in its own session. Over MCP you write that JSON yourself: describe_capabilities gives the vocabulary, draft_automation validates it and stores a draft, edit_automation publishes it (or runs, dry-runs, pauses it). What you publish is a normal automation: it appears on /automations, approvals land in its session, and a person can edit it there afterwards. The sidecars-automations skill teaches the loop. Both scopes arrive by step-up consent the first time a tool needing them is called. Anything you cannot open — another person’s personal automation, a row in another workspace — is not found, never “forbidden”. Changing an automation needs the same right the page needs: its creator for a personal one, a workspace admin for a workspace one.

The plan

A plan is { "planVersion": 1, "name": "…", "description": "…", "nodes": [...], "edges": [...] } — name and description are required — with at most 200 nodes. Node shapes — capability, agent, transform, branch, map, subflow, approval, notify, delay — and the transform operations are returned verbatim by describe_capabilities; copy them. Inputs are bound with {"kind":"literal","value":…}, {"kind":"ref","node":"<upstream id>","path":"…"} or {"kind":"trigger","path":"…"}. Every write capability must sit downstream of an approval node unless the draft is submitted with write_approval: "automatic", in which case the plan may have no approval node at all. The trigger on the wire:

list_automations

Scope: automations:read · Kind: read-only · Annotations: readOnlyHint: true, destructiveHint: false, openWorldHint: false
List the automations you can see in this workspace — your personal ones and the workspace’s — newest first.

Parameters

number
default:"50"
Rows to return, at most 200.

Returns

array
Rows with automation_id, name, enabled, degraded_reason?, trigger, scope (personal | workspace), can_control, version?, step_count?, namespaces?, session_id?, next_fire_at?, last_fired_at?, consecutive_failures, created_at, url?.
boolean
More rows exist than limit returned.

read_automation

Scope: automations:read · Kind: read-only · Annotations: readOnlyHint: true, destructiveHint: false, openWorldHint: false
Read one automation: the ask it implements, its numbered steps, what it writes to, its trigger, scope, state and live version. include_plan adds the plan JSON; include_runs the latest runs; run_id one run’s per-node detail.

Parameters

string
required
From list_automations or a publish.
boolean
default:"false"
Add plan_json — the live FlowPlan, the best worked example for writing or revising one.
boolean
default:"false"
Add the latest 20 runs (run_id, status, dry_run, cause, error?, timestamps) and runs_truncated.
string
Add one run’s detail: nodes[] with node_id, status, attempt, error?, and the run’s output?. A run that is not this automation’s reads as null.

Returns

…
Identity and the sentence the plan implements.
string[]
The live version’s steps, numbered as the page shows them.
string[]
Capability keys the plan writes with (linear.createIssuesFromItems).
string[]
Systems it touches; personal_connectors names the creator’s own connections it depends on.
…
State, as on the row.
…
The live version. flow_version_id is what a schedule-only republish passes.
string
Where its runs and approvals land.
…
When asked for.

describe_capabilities

Scope: automations:read · Kind: read-only · Annotations: readOnlyHint: true, destructiveHint: false, openWorldHint: false
Everything needed to write a FlowPlan: the workspace’s connectors, the node, transform, binding and trigger-input forms to copy verbatim, the write-approval rule, and the capability catalogue per namespace. Call it first with include_schemas: false, then narrowed to the namespaces your plan needs.

Parameters

string[]
Only these namespaces’ capabilities. Default: every namespace the workspace may use. A namespace listed with connected: false exists but may not be used here.
boolean
default:"true"
Include each capability’s input and output JSON schema.

Returns

number
1 and 200.
array
provider, name, personal, namespace for each connected system. A workspace-scoped automation cannot use a personal one.
string
The vocabulary, rendered from the same source the validator checks against.
array
namespace, connected, capabilities[] with key, kind (read | write), describe, large?, async?, input?, output?.
…
Past ~90 KB the tail namespaces lose their schemas; call again narrowed to them.

draft_automation

Scope: automations:write · Kind: write · Annotations: readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false
Validate a FlowPlan you wrote and store it as a draft version. Nothing is scheduled until it is published.

Parameters

object
required
The FlowPlan (planVersion: 1).
string
required
The request this plan implements, in one sentence; shown on the automation.
'required' | 'automatic'
default:"required"
required: every write behind an approval node. automatic: no approval nodes; writes run unattended.
string
Draft the next version of this automation instead of a new one. Needs the right to change it.

Returns

Either a draft:
'plan'
…
What edit_automation publish takes.
…
Read these back to the person before publishing.
or a failure (isError: true), with nothing stored:
'failed'
array
rule (shape, dag/cycle, capability/not-connected, capability/input, binding/not-upstream, …), path into your plan JSON (["nodes", 2, "inputs", "issues"]), node_id?, message. Fix exactly these and resubmit.

edit_automation

Scope: automations:write · Kind: write · Annotations: readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false
One tool, three actions: publish a draft behind a trigger, run an automation now (or dry_run it), set_enabled to pause or resume. Pausing is the undo for everything; there is no delete. A paused automation refuses a real run but still accepts dry_run: true, so it can be tested without starting its schedule.

Parameters

'publish' | 'run' | 'set_enabled'
required
string
Required for run and set_enabled. On publish, makes the draft that automation’s next version; without it a new automation is created.
string
publish: the draft from draft_automation (or the live version, to change only the trigger).
object
publish: see the plan.
…
publish. name is required for a new automation.
'personal' | 'workspace'
publish. workspace needs an admin and cannot use personal connectors.
'off' | 'problems' | 'everyRun'
publish: when the creator is notified.
number
publish: minimum seconds between event-triggered runs.
boolean
publish: false leaves it paused for review (default enabled). set_enabled: required.
boolean
default:"false"
run: simulate writes.

Returns

string
Echoed.
string
…
On publish.
…
On run; run_id is set for a dry run and readable with read_automation(run_id). A normal run is queued and appears under include_runs moments later.
…
On set_enabled.
Refusals carry the page’s own sentence: “Enable the automation before running it”, “Only its creator can change this automation”, “Only workspace admins can change this automation”, “That draft is not a version of this automation”.