@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.
Files changed (2) hide show
  1. package/README.md +301 -80
  2. 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
- Add this remote MCP server URL to your client:
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
- The client will open Stately sign-in when authentication is required.
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 either `machine` plus `format`, or a `source` object with
22
- `format` and `content`. Conversion-based tools support `xstate`, `scxml`,
23
- `xgraph`, and `d2`. Validation also supports `json`, `yaml`, and `mermaid`.
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
- Example prompt: "Check this machine for logic problems."
88
+ <details>
89
+ <summary>Summary: validate a machine</summary>
36
90
 
37
- ```json
38
- {
39
- "machine": "<machine source>",
40
- "format": "xstate"
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
- Example prompt: "Convert this machine to SCXML."
114
+ <details>
115
+ <summary>Summary: convert XState to SCXML</summary>
52
116
 
53
- ```json
54
- {
55
- "machine": "<machine source>",
56
- "format": "xstate",
57
- "to": "scxml"
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
- Example prompt: "What changed between these two machines?"
198
+ <details>
199
+ <summary>Summary: compare two machine versions</summary>
70
200
 
71
- ```json
72
- {
73
- "base": { "format": "xstate", "content": "<old machine source>" },
74
- "compare": { "format": "xstate", "content": "<new machine source>" },
75
- "includePatches": true
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
- Example prompt: "Apply these suggested changes and return XState code."
235
+ <details>
236
+ <summary>Summary: update a machine</summary>
87
237
 
88
- ```json
89
- {
90
- "machine": "<machine source>",
91
- "format": "xstate",
92
- "patches": [
93
- { "op": "updateState", "stateId": "active", "key": "complete" }
94
- ],
95
- "to": "xstate"
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
- Example prompt: "Find the shortest paths through this machine."
261
+ <details>
262
+ <summary>Summary: generate shortest paths</summary>
108
263
 
109
- ```json
110
- {
111
- "machine": "<machine source>",
112
- "format": "xstate",
113
- "kind": "shortest",
114
- "max": 5
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
- Example prompt: "Simulate PLAY followed by STOP."
288
+ <details>
289
+ <summary>Summary: simulate events</summary>
127
290
 
128
- ```json
129
- {
130
- "machine": "<machine source>",
131
- "format": "xstate",
132
- "events": [{ "type": "PLAY" }, { "type": "STOP" }]
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
- Example prompt: "Draw this machine from left to right."
314
+ <details>
315
+ <summary>Summary: visualize a machine</summary>
144
316
 
145
- ```json
146
- {
147
- "machine": "<machine source>",
148
- "format": "xstate",
149
- "direction": "right"
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
- Example prompt: "Check that STOP always ends playback permanently."
342
+ <details>
343
+ <summary>Summary: analyze intended behavior</summary>
163
344
 
164
- ```json
165
- {
166
- "machine": "<machine source>",
167
- "format": "xstate",
168
- "intent": "STOP must reach a final state, and playback must not restart"
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
- Example prompt: "Generate tests for the shortest paths through this machine."
369
+ <details>
370
+ <summary>Summary: generate Vitest tests</summary>
181
371
 
182
- ```json
183
- {
184
- "machine": "<machine source>",
185
- "format": "xstate",
186
- "kind": "shortest",
187
- "max": 5
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
- Example prompt: "Extract the XState machine from this TypeScript file."
395
+ <details>
396
+ <summary>Summary: extract a machine from TypeScript</summary>
199
397
 
200
- ```json
201
- {
202
- "code": "import { createMachine } from 'xstate';\nexport const player = createMachine({ /* complete config */ });"
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).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@statelyai/mcp",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "license": "UNLICENSED",
5
5
  "type": "module",
6
6
  "files": [