@statelyai/mcp 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +312 -82
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -6,24 +6,77 @@ Use Stately's machine tools from an MCP-compatible agent.
|
|
|
6
6
|
|
|
7
7
|
<!-- public Stately MCP URL -->
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
Choose your client and add Stately MCP using one of these methods.
|
|
10
|
+
|
|
11
|
+
### Codex
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
codex mcp add stately --url https://stately.ai/mcp
|
|
15
|
+
codex mcp login stately
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
### Claude Code
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
claude mcp add --transport http stately https://stately.ai/mcp
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Then open Claude Code, run `/mcp`, and complete Stately sign-in.
|
|
25
|
+
|
|
26
|
+
### Cursor
|
|
27
|
+
|
|
28
|
+
Open **Cursor Settings → MCP → Add new global MCP server**, then add:
|
|
29
|
+
|
|
30
|
+
```json
|
|
31
|
+
{
|
|
32
|
+
"mcpServers": {
|
|
33
|
+
"stately": {
|
|
34
|
+
"url": "https://stately.ai/mcp"
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Save the configuration and complete Stately sign-in when Cursor connects. To
|
|
41
|
+
share the server with a project, put the same configuration in
|
|
42
|
+
`.cursor/mcp.json` at the project root.
|
|
43
|
+
|
|
44
|
+
### VS Code with GitHub Copilot
|
|
45
|
+
|
|
46
|
+
Create `.vscode/mcp.json` in your project:
|
|
47
|
+
|
|
48
|
+
```json
|
|
49
|
+
{
|
|
50
|
+
"servers": {
|
|
51
|
+
"stately": {
|
|
52
|
+
"type": "http",
|
|
53
|
+
"url": "https://stately.ai/mcp"
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Open the Command Palette and run **MCP: List Servers**, start `stately`, then
|
|
60
|
+
complete Stately sign-in. For a personal configuration available in every
|
|
61
|
+
workspace, run **MCP: Open User Configuration** instead.
|
|
62
|
+
|
|
63
|
+
### Other MCP clients
|
|
64
|
+
|
|
65
|
+
Add a remote server using the Streamable HTTP transport and this URL:
|
|
10
66
|
|
|
11
67
|
```text
|
|
12
68
|
https://stately.ai/mcp
|
|
13
69
|
```
|
|
14
70
|
|
|
15
|
-
|
|
71
|
+
Complete Stately sign-in when the client connects.
|
|
16
72
|
|
|
17
73
|
## Machine input
|
|
18
74
|
|
|
19
75
|
<!-- shared machine input schemas from src/server.ts -->
|
|
20
76
|
|
|
21
|
-
Most tools accept
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
The examples below use `<machine source>` as a placeholder for the complete
|
|
26
|
-
machine document supplied by the agent.
|
|
77
|
+
Most tools accept a machine config object or a source document. Conversion
|
|
78
|
+
supports XState, SCXML, XGraph, and D2. Validation also supports JSON, YAML, and
|
|
79
|
+
Mermaid.
|
|
27
80
|
|
|
28
81
|
## `validate_machine`
|
|
29
82
|
|
|
@@ -32,15 +85,25 @@ machine document supplied by the agent.
|
|
|
32
85
|
Checks whether a machine can be parsed and reports structural issues such as
|
|
33
86
|
unreachable states. A successful response contains `ok` and an `issues` array.
|
|
34
87
|
|
|
35
|
-
|
|
88
|
+
<details>
|
|
89
|
+
<summary>Summary: validate a machine</summary>
|
|
36
90
|
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
91
|
+
```text
|
|
92
|
+
Use Stately to validate this machine:
|
|
93
|
+
|
|
94
|
+
createMachine({
|
|
95
|
+
id: 'player',
|
|
96
|
+
initial: 'paused',
|
|
97
|
+
states: {
|
|
98
|
+
paused: { on: { PLAY: 'playing' } },
|
|
99
|
+
playing: { on: { PAUSE: 'paused', STOP: 'stopped' } },
|
|
100
|
+
stopped: { type: 'final' }
|
|
101
|
+
}
|
|
102
|
+
});
|
|
42
103
|
```
|
|
43
104
|
|
|
105
|
+
</details>
|
|
106
|
+
|
|
44
107
|
## `convert_machine`
|
|
45
108
|
|
|
46
109
|
<!-- convert_machine registration from src/server.ts and convert response contract -->
|
|
@@ -48,16 +111,82 @@ Example prompt: "Check this machine for logic problems."
|
|
|
48
111
|
Converts a machine between XState, SCXML, XGraph, and D2. The response contains
|
|
49
112
|
the target `format`, converted `content`, and any `warnings`.
|
|
50
113
|
|
|
51
|
-
|
|
114
|
+
<details>
|
|
115
|
+
<summary>Summary: convert XState to SCXML</summary>
|
|
52
116
|
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
117
|
+
```text
|
|
118
|
+
Use Stately to convert this machine to SCXML:
|
|
119
|
+
|
|
120
|
+
createMachine({
|
|
121
|
+
id: 'player',
|
|
122
|
+
initial: 'paused',
|
|
123
|
+
states: {
|
|
124
|
+
paused: { on: { PLAY: 'playing' } },
|
|
125
|
+
playing: { on: { STOP: 'stopped' } },
|
|
126
|
+
stopped: { type: 'final' }
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
</details>
|
|
132
|
+
|
|
133
|
+
<details>
|
|
134
|
+
<summary>Summary: convert SCXML to XState</summary>
|
|
135
|
+
|
|
136
|
+
```text
|
|
137
|
+
Use Stately to convert this SCXML machine to XState:
|
|
138
|
+
|
|
139
|
+
<scxml xmlns="http://www.w3.org/2005/07/scxml" name="player" initial="paused">
|
|
140
|
+
<state id="paused">
|
|
141
|
+
<transition event="PLAY" target="playing" />
|
|
142
|
+
</state>
|
|
143
|
+
<state id="playing">
|
|
144
|
+
<transition event="STOP" target="stopped" />
|
|
145
|
+
</state>
|
|
146
|
+
<final id="stopped" />
|
|
147
|
+
</scxml>
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
</details>
|
|
151
|
+
|
|
152
|
+
<details>
|
|
153
|
+
<summary>Summary: convert XState to D2</summary>
|
|
154
|
+
|
|
155
|
+
```text
|
|
156
|
+
Use Stately to convert this machine to D2:
|
|
157
|
+
|
|
158
|
+
createMachine({
|
|
159
|
+
id: 'player',
|
|
160
|
+
initial: 'paused',
|
|
161
|
+
states: {
|
|
162
|
+
paused: { on: { PLAY: 'playing' } },
|
|
163
|
+
playing: { on: { STOP: 'stopped' } },
|
|
164
|
+
stopped: { type: 'final' }
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
</details>
|
|
170
|
+
|
|
171
|
+
<details>
|
|
172
|
+
<summary>Summary: convert XState to XGraph</summary>
|
|
173
|
+
|
|
174
|
+
```text
|
|
175
|
+
Use Stately to convert this machine to XGraph:
|
|
176
|
+
|
|
177
|
+
createMachine({
|
|
178
|
+
id: 'player',
|
|
179
|
+
initial: 'paused',
|
|
180
|
+
states: {
|
|
181
|
+
paused: { on: { PLAY: 'playing' } },
|
|
182
|
+
playing: { on: { STOP: 'stopped' } },
|
|
183
|
+
stopped: { type: 'final' }
|
|
184
|
+
}
|
|
185
|
+
});
|
|
59
186
|
```
|
|
60
187
|
|
|
188
|
+
</details>
|
|
189
|
+
|
|
61
190
|
## `diff_machines`
|
|
62
191
|
|
|
63
192
|
<!-- diff_machines registration from src/server.ts and diff response contract -->
|
|
@@ -66,16 +195,36 @@ Compares two machine documents structurally instead of comparing their source
|
|
|
66
195
|
text. It returns a summary and semantic diff; set `includePatches` to request
|
|
67
196
|
applicable patches.
|
|
68
197
|
|
|
69
|
-
|
|
198
|
+
<details>
|
|
199
|
+
<summary>Summary: compare two machine versions</summary>
|
|
70
200
|
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
201
|
+
```text
|
|
202
|
+
Use Stately to compare these two versions of a machine and suggest patches:
|
|
203
|
+
|
|
204
|
+
Before:
|
|
205
|
+
createMachine({
|
|
206
|
+
id: 'player',
|
|
207
|
+
initial: 'paused',
|
|
208
|
+
states: {
|
|
209
|
+
paused: { on: { PLAY: 'playing' } },
|
|
210
|
+
playing: {}
|
|
211
|
+
}
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
After:
|
|
215
|
+
createMachine({
|
|
216
|
+
id: 'player',
|
|
217
|
+
initial: 'paused',
|
|
218
|
+
states: {
|
|
219
|
+
paused: { on: { PLAY: 'playing' } },
|
|
220
|
+
playing: { on: { STOP: 'stopped' } },
|
|
221
|
+
stopped: { type: 'final' }
|
|
222
|
+
}
|
|
223
|
+
});
|
|
77
224
|
```
|
|
78
225
|
|
|
226
|
+
</details>
|
|
227
|
+
|
|
79
228
|
## `apply_machine_patches`
|
|
80
229
|
|
|
81
230
|
<!-- apply_machine_patches registration from src/server.ts and apply-patches response contract -->
|
|
@@ -83,19 +232,24 @@ Example prompt: "What changed between these two machines?"
|
|
|
83
232
|
Applies semantic patches to a machine and returns the updated document. Use
|
|
84
233
|
`to` to choose the returned format.
|
|
85
234
|
|
|
86
|
-
|
|
235
|
+
<details>
|
|
236
|
+
<summary>Summary: update a machine</summary>
|
|
87
237
|
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
}
|
|
238
|
+
```text
|
|
239
|
+
Use Stately to rename the playing state to active and return the updated XState machine:
|
|
240
|
+
|
|
241
|
+
createMachine({
|
|
242
|
+
id: 'player',
|
|
243
|
+
initial: 'paused',
|
|
244
|
+
states: {
|
|
245
|
+
paused: { on: { PLAY: 'playing' } },
|
|
246
|
+
playing: {}
|
|
247
|
+
}
|
|
248
|
+
});
|
|
97
249
|
```
|
|
98
250
|
|
|
251
|
+
</details>
|
|
252
|
+
|
|
99
253
|
## `generate_graph_paths`
|
|
100
254
|
|
|
101
255
|
<!-- generate_graph_paths registration from src/server.ts and graph-paths response contract -->
|
|
@@ -104,17 +258,25 @@ Generates shortest or simple paths through a machine. The response includes
|
|
|
104
258
|
the event steps for each path plus state and transition coverage. Stately MCP
|
|
105
259
|
returns at most five paths per call.
|
|
106
260
|
|
|
107
|
-
|
|
261
|
+
<details>
|
|
262
|
+
<summary>Summary: generate shortest paths</summary>
|
|
108
263
|
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
264
|
+
```text
|
|
265
|
+
Use Stately to find up to five shortest paths through this machine:
|
|
266
|
+
|
|
267
|
+
createMachine({
|
|
268
|
+
id: 'player',
|
|
269
|
+
initial: 'paused',
|
|
270
|
+
states: {
|
|
271
|
+
paused: { on: { PLAY: 'playing' } },
|
|
272
|
+
playing: { on: { PAUSE: 'paused', STOP: 'stopped' } },
|
|
273
|
+
stopped: { type: 'final' }
|
|
274
|
+
}
|
|
275
|
+
});
|
|
116
276
|
```
|
|
117
277
|
|
|
278
|
+
</details>
|
|
279
|
+
|
|
118
280
|
## `simulate_machine`
|
|
119
281
|
|
|
120
282
|
<!-- simulate_machine registration from src/server.ts and simulate response contract -->
|
|
@@ -123,33 +285,60 @@ Runs up to 100 events through a machine and returns a step-by-step trace of
|
|
|
123
285
|
states, context, and executed action names. Guards are stubbed during this
|
|
124
286
|
deterministic simulation.
|
|
125
287
|
|
|
126
|
-
|
|
288
|
+
<details>
|
|
289
|
+
<summary>Summary: simulate events</summary>
|
|
127
290
|
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
291
|
+
```text
|
|
292
|
+
Use Stately to simulate PLAY followed by STOP on this machine:
|
|
293
|
+
|
|
294
|
+
createMachine({
|
|
295
|
+
id: 'player',
|
|
296
|
+
initial: 'paused',
|
|
297
|
+
states: {
|
|
298
|
+
paused: { on: { PLAY: 'playing' } },
|
|
299
|
+
playing: { on: { STOP: 'stopped' } },
|
|
300
|
+
stopped: { type: 'final' }
|
|
301
|
+
}
|
|
302
|
+
});
|
|
134
303
|
```
|
|
135
304
|
|
|
305
|
+
</details>
|
|
306
|
+
|
|
136
307
|
## `visualize_machine`
|
|
137
308
|
|
|
138
309
|
<!-- visualize_machine registration from src/server.ts and visualize response contract -->
|
|
139
310
|
|
|
140
|
-
Renders
|
|
141
|
-
|
|
311
|
+
Renders each machine hierarchy level as a directly viewable PNG. Codex,
|
|
312
|
+
Claude, and other image-capable MCP clients receive one native image block per
|
|
313
|
+
parent node. Structured content contains parent IDs, labels, hierarchy levels,
|
|
314
|
+
dimensions, and warnings without duplicating image data. Use `parentNodeIds` to
|
|
315
|
+
select levels; omit it to render every parent with direct child states.
|
|
142
316
|
|
|
143
|
-
|
|
317
|
+
Each returned image uses the MCP `ImageContent` shape:
|
|
144
318
|
|
|
145
|
-
```
|
|
146
|
-
{
|
|
147
|
-
"machine": "<machine source>",
|
|
148
|
-
"format": "xstate",
|
|
149
|
-
"direction": "right"
|
|
150
|
-
}
|
|
319
|
+
```ts
|
|
320
|
+
{ type: 'image', data: pngBase64, mimeType: 'image/png' }
|
|
151
321
|
```
|
|
152
322
|
|
|
323
|
+
<details>
|
|
324
|
+
<summary>Summary: visualize a machine</summary>
|
|
325
|
+
|
|
326
|
+
```text
|
|
327
|
+
Use Stately to visualize this machine from left to right:
|
|
328
|
+
|
|
329
|
+
createMachine({
|
|
330
|
+
id: 'player',
|
|
331
|
+
initial: 'paused',
|
|
332
|
+
states: {
|
|
333
|
+
paused: { on: { PLAY: 'playing' } },
|
|
334
|
+
playing: { on: { STOP: 'stopped' } },
|
|
335
|
+
stopped: { type: 'final' }
|
|
336
|
+
}
|
|
337
|
+
});
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
</details>
|
|
341
|
+
|
|
153
342
|
## `analyze_machine`
|
|
154
343
|
|
|
155
344
|
<!-- analyze_machine registration from src/server.ts and analyze response contract -->
|
|
@@ -159,16 +348,25 @@ the machine against its expected behavior. The response contains issues and may
|
|
|
159
348
|
include suggested fixes. Use `validate_machine` when only deterministic checks
|
|
160
349
|
are needed.
|
|
161
350
|
|
|
162
|
-
|
|
351
|
+
<details>
|
|
352
|
+
<summary>Summary: analyze intended behavior</summary>
|
|
163
353
|
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
354
|
+
```text
|
|
355
|
+
Use Stately to check that STOP reaches a final state and playback cannot restart:
|
|
356
|
+
|
|
357
|
+
createMachine({
|
|
358
|
+
id: 'player',
|
|
359
|
+
initial: 'paused',
|
|
360
|
+
states: {
|
|
361
|
+
paused: { on: { PLAY: 'playing' } },
|
|
362
|
+
playing: { on: { STOP: 'stopped' } },
|
|
363
|
+
stopped: { type: 'final' }
|
|
364
|
+
}
|
|
365
|
+
});
|
|
170
366
|
```
|
|
171
367
|
|
|
368
|
+
</details>
|
|
369
|
+
|
|
172
370
|
## `generate_test_code`
|
|
173
371
|
|
|
174
372
|
<!-- generate_test_code registration and generateTestCode implementation from src/server.ts -->
|
|
@@ -177,17 +375,25 @@ Generates a runnable Vitest file with one test per generated path. Each test
|
|
|
177
375
|
sends the path's events and asserts its final state. Guards and actions are
|
|
178
376
|
stubbed.
|
|
179
377
|
|
|
180
|
-
|
|
378
|
+
<details>
|
|
379
|
+
<summary>Summary: generate Vitest tests</summary>
|
|
181
380
|
|
|
182
|
-
```
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
381
|
+
```text
|
|
382
|
+
Use Stately to generate Vitest tests for the shortest paths through this machine:
|
|
383
|
+
|
|
384
|
+
createMachine({
|
|
385
|
+
id: 'player',
|
|
386
|
+
initial: 'paused',
|
|
387
|
+
states: {
|
|
388
|
+
paused: { on: { PLAY: 'playing' } },
|
|
389
|
+
playing: { on: { STOP: 'stopped' } },
|
|
390
|
+
stopped: { type: 'final' }
|
|
391
|
+
}
|
|
392
|
+
});
|
|
189
393
|
```
|
|
190
394
|
|
|
395
|
+
</details>
|
|
396
|
+
|
|
191
397
|
## `extract_machines_from_code`
|
|
192
398
|
|
|
193
399
|
<!-- extract_machines_from_code registration from src/server.ts -->
|
|
@@ -195,13 +401,37 @@ Example prompt: "Generate tests for the shortest paths through this machine."
|
|
|
195
401
|
Parses XState source code and returns the extracted machine as an XGraph
|
|
196
402
|
document.
|
|
197
403
|
|
|
198
|
-
|
|
404
|
+
<details>
|
|
405
|
+
<summary>Summary: extract a machine from TypeScript</summary>
|
|
199
406
|
|
|
200
|
-
```
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
}
|
|
407
|
+
```text
|
|
408
|
+
Use Stately to extract the machine from this TypeScript:
|
|
409
|
+
|
|
410
|
+
import { createMachine } from 'xstate';
|
|
411
|
+
|
|
412
|
+
export const player = createMachine({
|
|
413
|
+
id: 'player',
|
|
414
|
+
initial: 'paused',
|
|
415
|
+
states: {
|
|
416
|
+
paused: { on: { PLAY: 'playing' } },
|
|
417
|
+
playing: { on: { STOP: 'stopped' } },
|
|
418
|
+
stopped: { type: 'final' }
|
|
419
|
+
}
|
|
420
|
+
});
|
|
204
421
|
```
|
|
205
422
|
|
|
423
|
+
</details>
|
|
424
|
+
|
|
206
425
|
All Stately MCP tools are registered as read-only, non-destructive, idempotent,
|
|
207
426
|
and closed-world.
|
|
427
|
+
|
|
428
|
+
## Self-hosting
|
|
429
|
+
|
|
430
|
+
<!-- self-host MCP endpoint from ../editor/src/app/api/[transport]/route.ts and ../editor/src/lib/auth/oauthProtectedResource.ts -->
|
|
431
|
+
|
|
432
|
+
Self-host Stately Studio, then replace the hosted URL above with your
|
|
433
|
+
deployment's `/api/mcp` endpoint, for example
|
|
434
|
+
`https://studio.example.com/api/mcp`.
|
|
435
|
+
|
|
436
|
+
For enterprise self-hosting options, [see pricing and contact
|
|
437
|
+
us](https://stately.ai/pricing).
|