@statelyai/mcp 0.1.1 → 0.1.2
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 +301 -80
- 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
|
+
});
|
|
59
167
|
```
|
|
60
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
|
+
});
|
|
186
|
+
```
|
|
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,16 +285,25 @@ 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 -->
|
|
@@ -140,16 +311,25 @@ Example prompt: "Simulate PLAY followed by STOP."
|
|
|
140
311
|
Renders a machine as an SVG diagram. The response contains the SVG string,
|
|
141
312
|
its width and height, and any warnings.
|
|
142
313
|
|
|
143
|
-
|
|
314
|
+
<details>
|
|
315
|
+
<summary>Summary: visualize a machine</summary>
|
|
144
316
|
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
317
|
+
```text
|
|
318
|
+
Use Stately to visualize this machine from left to right:
|
|
319
|
+
|
|
320
|
+
createMachine({
|
|
321
|
+
id: 'player',
|
|
322
|
+
initial: 'paused',
|
|
323
|
+
states: {
|
|
324
|
+
paused: { on: { PLAY: 'playing' } },
|
|
325
|
+
playing: { on: { STOP: 'stopped' } },
|
|
326
|
+
stopped: { type: 'final' }
|
|
327
|
+
}
|
|
328
|
+
});
|
|
151
329
|
```
|
|
152
330
|
|
|
331
|
+
</details>
|
|
332
|
+
|
|
153
333
|
## `analyze_machine`
|
|
154
334
|
|
|
155
335
|
<!-- analyze_machine registration from src/server.ts and analyze response contract -->
|
|
@@ -159,16 +339,25 @@ the machine against its expected behavior. The response contains issues and may
|
|
|
159
339
|
include suggested fixes. Use `validate_machine` when only deterministic checks
|
|
160
340
|
are needed.
|
|
161
341
|
|
|
162
|
-
|
|
342
|
+
<details>
|
|
343
|
+
<summary>Summary: analyze intended behavior</summary>
|
|
163
344
|
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
345
|
+
```text
|
|
346
|
+
Use Stately to check that STOP reaches a final state and playback cannot restart:
|
|
347
|
+
|
|
348
|
+
createMachine({
|
|
349
|
+
id: 'player',
|
|
350
|
+
initial: 'paused',
|
|
351
|
+
states: {
|
|
352
|
+
paused: { on: { PLAY: 'playing' } },
|
|
353
|
+
playing: { on: { STOP: 'stopped' } },
|
|
354
|
+
stopped: { type: 'final' }
|
|
355
|
+
}
|
|
356
|
+
});
|
|
170
357
|
```
|
|
171
358
|
|
|
359
|
+
</details>
|
|
360
|
+
|
|
172
361
|
## `generate_test_code`
|
|
173
362
|
|
|
174
363
|
<!-- generate_test_code registration and generateTestCode implementation from src/server.ts -->
|
|
@@ -177,17 +366,25 @@ Generates a runnable Vitest file with one test per generated path. Each test
|
|
|
177
366
|
sends the path's events and asserts its final state. Guards and actions are
|
|
178
367
|
stubbed.
|
|
179
368
|
|
|
180
|
-
|
|
369
|
+
<details>
|
|
370
|
+
<summary>Summary: generate Vitest tests</summary>
|
|
181
371
|
|
|
182
|
-
```
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
372
|
+
```text
|
|
373
|
+
Use Stately to generate Vitest tests for the shortest paths through this machine:
|
|
374
|
+
|
|
375
|
+
createMachine({
|
|
376
|
+
id: 'player',
|
|
377
|
+
initial: 'paused',
|
|
378
|
+
states: {
|
|
379
|
+
paused: { on: { PLAY: 'playing' } },
|
|
380
|
+
playing: { on: { STOP: 'stopped' } },
|
|
381
|
+
stopped: { type: 'final' }
|
|
382
|
+
}
|
|
383
|
+
});
|
|
189
384
|
```
|
|
190
385
|
|
|
386
|
+
</details>
|
|
387
|
+
|
|
191
388
|
## `extract_machines_from_code`
|
|
192
389
|
|
|
193
390
|
<!-- extract_machines_from_code registration from src/server.ts -->
|
|
@@ -195,13 +392,37 @@ Example prompt: "Generate tests for the shortest paths through this machine."
|
|
|
195
392
|
Parses XState source code and returns the extracted machine as an XGraph
|
|
196
393
|
document.
|
|
197
394
|
|
|
198
|
-
|
|
395
|
+
<details>
|
|
396
|
+
<summary>Summary: extract a machine from TypeScript</summary>
|
|
199
397
|
|
|
200
|
-
```
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
}
|
|
398
|
+
```text
|
|
399
|
+
Use Stately to extract the machine from this TypeScript:
|
|
400
|
+
|
|
401
|
+
import { createMachine } from 'xstate';
|
|
402
|
+
|
|
403
|
+
export const player = createMachine({
|
|
404
|
+
id: 'player',
|
|
405
|
+
initial: 'paused',
|
|
406
|
+
states: {
|
|
407
|
+
paused: { on: { PLAY: 'playing' } },
|
|
408
|
+
playing: { on: { STOP: 'stopped' } },
|
|
409
|
+
stopped: { type: 'final' }
|
|
410
|
+
}
|
|
411
|
+
});
|
|
204
412
|
```
|
|
205
413
|
|
|
414
|
+
</details>
|
|
415
|
+
|
|
206
416
|
All Stately MCP tools are registered as read-only, non-destructive, idempotent,
|
|
207
417
|
and closed-world.
|
|
418
|
+
|
|
419
|
+
## Self-hosting
|
|
420
|
+
|
|
421
|
+
<!-- self-host MCP endpoint from ../editor/src/app/api/[transport]/route.ts and ../editor/src/lib/auth/oauthProtectedResource.ts -->
|
|
422
|
+
|
|
423
|
+
Self-host Stately Studio, then replace the hosted URL above with your
|
|
424
|
+
deployment's `/api/mcp` endpoint, for example
|
|
425
|
+
`https://studio.example.com/api/mcp`.
|
|
426
|
+
|
|
427
|
+
For enterprise self-hosting options, [see pricing and contact
|
|
428
|
+
us](https://stately.ai/pricing).
|