Stately MCP
Use Stately's machine tools from an MCP compatible agent.
Use Stately's machine tools from an MCP-compatible agent.
Connect
Choose your client and add Stately MCP using one of these methods.
Codex
codex mcp add stately --url https://stately.ai/mcp
codex mcp login statelyClaude Code
claude mcp add --transport http stately https://stately.ai/mcpThen open Claude Code, run /mcp, and complete Stately sign-in.
Cursor
Open Cursor Settings → MCP → Add new global MCP server, then add:
{
"mcpServers": {
"stately": {
"url": "https://stately.ai/mcp"
}
}
}Save the configuration and complete Stately sign-in when Cursor connects. To
share the server with a project, put the same configuration in
.cursor/mcp.json at the project root.
VS Code with GitHub Copilot
Create .vscode/mcp.json in your project:
{
"servers": {
"stately": {
"type": "http",
"url": "https://stately.ai/mcp"
}
}
}Open the Command Palette and run MCP: List Servers, start stately, then
complete Stately sign-in. For a personal configuration available in every
workspace, run MCP: Open User Configuration instead.
Other MCP clients
Add a remote server using the Streamable HTTP transport and this URL:
https://stately.ai/mcpComplete Stately sign-in when the client connects.
Machine input
Most tools accept a machine config object or a source document. Conversion supports XState, SCXML, XGraph, and D2. Validation also supports JSON, YAML, and Mermaid.
validate_machine
Checks whether a machine can be parsed and reports structural issues such as
unreachable states. A successful response contains ok and an issues array.
Summary: validate a machine
Use Stately to validate this machine:
createMachine({
id: 'player',
initial: 'paused',
states: {
paused: { on: { PLAY: 'playing' } },
playing: { on: { PAUSE: 'paused', STOP: 'stopped' } },
stopped: { type: 'final' }
}
});convert_machine
Converts a machine between XState, SCXML, XGraph, and D2. The response contains
the target format, converted content, and any warnings.
Summary: convert XState to SCXML
Use Stately to convert this machine to SCXML:
createMachine({
id: 'player',
initial: 'paused',
states: {
paused: { on: { PLAY: 'playing' } },
playing: { on: { STOP: 'stopped' } },
stopped: { type: 'final' }
}
});Summary: convert SCXML to XState
Use Stately to convert this SCXML machine to XState:
<scxml xmlns="http://www.w3.org/2005/07/scxml" name="player" initial="paused">
<state id="paused">
<transition event="PLAY" target="playing" />
</state>
<state id="playing">
<transition event="STOP" target="stopped" />
</state>
<final id="stopped" />
</scxml>Summary: convert XState to D2
Use Stately to convert this machine to D2:
createMachine({
id: 'player',
initial: 'paused',
states: {
paused: { on: { PLAY: 'playing' } },
playing: { on: { STOP: 'stopped' } },
stopped: { type: 'final' }
}
});Summary: convert XState to XGraph
Use Stately to convert this machine to XGraph:
createMachine({
id: 'player',
initial: 'paused',
states: {
paused: { on: { PLAY: 'playing' } },
playing: { on: { STOP: 'stopped' } },
stopped: { type: 'final' }
}
});diff_machines
Compares two machine documents structurally instead of comparing their source
text. It returns a summary and semantic diff; set includePatches to request
applicable patches.
Summary: compare two machine versions
Use Stately to compare these two versions of a machine and suggest patches:
Before:
createMachine({
id: 'player',
initial: 'paused',
states: {
paused: { on: { PLAY: 'playing' } },
playing: {}
}
});
After:
createMachine({
id: 'player',
initial: 'paused',
states: {
paused: { on: { PLAY: 'playing' } },
playing: { on: { STOP: 'stopped' } },
stopped: { type: 'final' }
}
});apply_machine_patches
Applies semantic patches to a machine and returns the updated document. Use
to to choose the returned format.
Summary: update a machine
Use Stately to rename the playing state to active and return the updated XState machine:
createMachine({
id: 'player',
initial: 'paused',
states: {
paused: { on: { PLAY: 'playing' } },
playing: {}
}
});generate_graph_paths
Generates shortest or simple paths through a machine. The response includes the event steps for each path plus state and transition coverage. Stately MCP returns at most five paths per call.
Summary: generate shortest paths
Use Stately to find up to five shortest paths through this machine:
createMachine({
id: 'player',
initial: 'paused',
states: {
paused: { on: { PLAY: 'playing' } },
playing: { on: { PAUSE: 'paused', STOP: 'stopped' } },
stopped: { type: 'final' }
}
});simulate_machine
Runs up to 100 events through a machine and returns a step-by-step trace of states, context, and executed action names. Guards are stubbed during this deterministic simulation.
Summary: simulate events
Use Stately to simulate PLAY followed by STOP on this machine:
createMachine({
id: 'player',
initial: 'paused',
states: {
paused: { on: { PLAY: 'playing' } },
playing: { on: { STOP: 'stopped' } },
stopped: { type: 'final' }
}
});visualize_machine
Renders a machine as an SVG diagram. The response contains the SVG string, its width and height, and any warnings.
Summary: visualize a machine
Use Stately to visualize this machine from left to right:
createMachine({
id: 'player',
initial: 'paused',
states: {
paused: { on: { PLAY: 'playing' } },
playing: { on: { STOP: 'stopped' } },
stopped: { type: 'final' }
}
});analyze_machine
Combines deterministic checks with AI review. Provide optional intent to assess
the machine against its expected behavior. The response contains issues and may
include suggested fixes. Use validate_machine when only deterministic checks
are needed.
Summary: analyze intended behavior
Use Stately to check that STOP reaches a final state and playback cannot restart:
createMachine({
id: 'player',
initial: 'paused',
states: {
paused: { on: { PLAY: 'playing' } },
playing: { on: { STOP: 'stopped' } },
stopped: { type: 'final' }
}
});generate_test_code
Generates a runnable Vitest file with one test per generated path. Each test sends the path's events and asserts its final state. Guards and actions are stubbed.
Summary: generate Vitest tests
Use Stately to generate Vitest tests for the shortest paths through this machine:
createMachine({
id: 'player',
initial: 'paused',
states: {
paused: { on: { PLAY: 'playing' } },
playing: { on: { STOP: 'stopped' } },
stopped: { type: 'final' }
}
});extract_machines_from_code
Parses XState source code and returns the extracted machine as an XGraph document.
Summary: extract a machine from TypeScript
Use Stately to extract the machine from this TypeScript:
import { createMachine } from 'xstate';
export const player = createMachine({
id: 'player',
initial: 'paused',
states: {
paused: { on: { PLAY: 'playing' } },
playing: { on: { STOP: 'stopped' } },
stopped: { type: 'final' }
}
});All Stately MCP tools are registered as read-only, non-destructive, idempotent, and closed-world.