@vscxml/mcp 0.1.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 ADDED
@@ -0,0 +1,252 @@
1
+ # @vscxml/mcp
2
+
3
+ MCP server for the VSCXML suite. Enables LLMs (Claude Code, Claude Desktop, Cursor, etc.) to design, simulate, generate, and visually edit SCXML state machines.
4
+
5
+ ## Architecture
6
+
7
+ ```
8
+ LLM (Claude Code / Claude Desktop / Cursor)
9
+ |
10
+ | MCP Protocol (stdio)
11
+ v
12
+ +-----------------------------------------------+
13
+ | @vscxml/mcp |
14
+ | |
15
+ | SimulatorBridge ----WS:48621----> Simulator |
16
+ | GeneratorBridge ---HTTP:48620---> Generator |
17
+ | EditorBridge ------WS:48623----> Editor |
18
+ +-----------------------------------------------+
19
+ ```
20
+
21
+ The MCP server is a **thin client** that bridges three VSCXML backends:
22
+ - **VSCXML-Generator-CLI** (REST API) -- code generation, validation, inspection
23
+ - **VSCXML-Simulator** (WebSocket) -- real-time simulation with trace visibility
24
+ - **VSCXML-Editor** (WebSocket) -- visual editor interaction
25
+
26
+ ## Setup
27
+
28
+ ### Claude Code
29
+
30
+ Add to your project's `.claude/settings.json` (or global `~/.claude/settings.json`):
31
+
32
+ ```json
33
+ {
34
+ "mcpServers": {
35
+ "scxml-gen": {
36
+ "command": "node",
37
+ "args": ["C:/dev/repos/scxml-gen/scxml-mcp/dist/bin/scxml-mcp.js"]
38
+ }
39
+ }
40
+ }
41
+ ```
42
+
43
+ Or after npm publish:
44
+
45
+ ```json
46
+ {
47
+ "mcpServers": {
48
+ "scxml-gen": {
49
+ "command": "npx",
50
+ "args": ["@vscxml/mcp"]
51
+ }
52
+ }
53
+ }
54
+ ```
55
+
56
+ ### Claude Desktop
57
+
58
+ Add to Claude Desktop settings (`Settings > Developer > MCP Servers`):
59
+
60
+ ```json
61
+ {
62
+ "mcpServers": {
63
+ "scxml-gen": {
64
+ "command": "npx",
65
+ "args": ["@vscxml/mcp"]
66
+ }
67
+ }
68
+ }
69
+ ```
70
+
71
+ ### Custom backend URLs
72
+
73
+ ```json
74
+ {
75
+ "mcpServers": {
76
+ "scxml-gen": {
77
+ "command": "npx",
78
+ "args": ["@vscxml/mcp", "--generator", "http://localhost:48620", "--simulator", "ws://localhost:48621", "--editor", "ws://localhost:48623"]
79
+ }
80
+ }
81
+ }
82
+ ```
83
+
84
+ Or via environment variables:
85
+
86
+ ```
87
+ VSCXML_GENERATOR_URL=http://localhost:48620
88
+ VSCXML_SIMULATOR_URL=ws://localhost:48621
89
+ VSCXML_EDITOR_URL=ws://localhost:48623
90
+ ```
91
+
92
+ ## Prerequisites
93
+
94
+ The MCP server requires installed VSCXML backends to function:
95
+
96
+ | Backend | Purpose | Default Port |
97
+ |---------|---------|-------------|
98
+ | VSCXML-Generator-CLI | Code generation, validation, inspection, SCXML creation | 48620 (HTTP) |
99
+ | VSCXML-Simulator | Real-time simulation, trace capture | 48621 (WS), 48622 (REST) |
100
+ | VSCXML-Editor | Visual state machine editing | 48623 (WS) |
101
+
102
+ The MCP server auto-discovers backends on default ports. If not found, it attempts to spawn them from known install paths.
103
+
104
+ ## Tools (37)
105
+
106
+ ### Design (3)
107
+
108
+ | Tool | Description |
109
+ |------|-------------|
110
+ | `scxml_create` | Create SCXML from a structured specification (states, transitions, data). No raw XML needed. |
111
+ | `scxml_validate` | Validate SCXML against the W3C spec. Returns errors, state/transition counts, datamodel. |
112
+ | `scxml_inspect` | Get the full structured model: states, hierarchy, transitions, events, variables, actions. |
113
+
114
+ ### Simulation (6)
115
+
116
+ | Tool | Description |
117
+ |------|-------------|
118
+ | `scxml_sim_start` | Load SCXML into the simulator and start. Returns initial state + enabled events. |
119
+ | `scxml_sim_send` | Send an event. Returns the trace (state exits/entries, transitions, variable changes) + new state. |
120
+ | `scxml_sim_scenario` | Run a batch of events. The most useful tool for testing behavior. |
121
+ | `scxml_sim_get_state` | Get current state without sending an event. |
122
+ | `scxml_sim_set_variable` | Set a variable value during simulation. |
123
+ | `scxml_sim_reset` | Reset the simulation to its initial state. |
124
+
125
+ ### Trace Management (6)
126
+
127
+ | Tool | Description |
128
+ |------|-------------|
129
+ | `scxml_trace_embed` | Embed a trace into the SCXML document (from session history or raw JSONL content). |
130
+ | `scxml_trace_list` | List all embedded traces in the current SCXML document. |
131
+ | `scxml_trace_get` | Get a trace by name. Returns parsed entries for inspection or comparison. |
132
+ | `scxml_trace_play` | Start real-time playback of an embedded trace. |
133
+ | `scxml_trace_step` | Step forward/backward through a loaded trace. |
134
+ | `scxml_trace_delete` | Delete an embedded trace by name. |
135
+
136
+ ### Code Generation (3)
137
+
138
+ | Tool | Description |
139
+ |------|-------------|
140
+ | `scxml_generate` | Generate code for any of 7 targets (Java, JS, C#, C, Python, Go, ST). Returns source files as text. |
141
+ | `scxml_generate_project` | Generate a complete runnable project with build files, runtime, and scaffolding. |
142
+ | `scxml_list_targets` | List available targets and their options. |
143
+
144
+ ### Verification (1)
145
+
146
+ | Tool | Description |
147
+ |------|-------------|
148
+ | `scxml_compare_traces` | Compare two execution traces and report differences. |
149
+
150
+ ### Editor Interaction (8)
151
+
152
+ | Tool | Description |
153
+ |------|-------------|
154
+ | `editor_push_scxml` | Push SCXML to the visual editor for the user to see. |
155
+ | `editor_get_scxml` | Get the current SCXML from the editor (what the user is editing). |
156
+ | `editor_highlight` | Highlight states with color: hex (`#ef4444`) or preset (`error`, `success`, `warning`, `info`, `active`, `danger`). |
157
+ | `editor_add_note` | Add annotations with `attachedTo` (state), `visibleWhen` (conditional visibility), and `color`. |
158
+ | `editor_remove_notes` | Remove MCP-added notes (by ID or all). |
159
+ | `editor_navigate` | Navigate the canvas: center on a state, fit states, fit all, zoom. |
160
+ | `editor_show_notification` | Show a toast notification in the editor UI. |
161
+ | `editor_status` | Check if the editor is running and connected. |
162
+
163
+ ### File I/O (3)
164
+
165
+ | Tool | Description |
166
+ |------|-------------|
167
+ | `editor_save_file` | Save SCXML to a file path. Auto-fetches content from editor if not provided. |
168
+ | `editor_load_file` | Load an SCXML file from disk into the editor. |
169
+ | `editor_screenshot` | Capture the editor window as a PNG image. |
170
+
171
+ ### Export (3)
172
+
173
+ | Tool | Description |
174
+ |------|-------------|
175
+ | `editor_export_svg` | Export the full diagram as parseable SVG text (contains state IDs, positions, labels). |
176
+ | `editor_export_png` | Export the full diagram as a 2x resolution PNG (entire diagram, not viewport). |
177
+ | `editor_export_player_html` | Export a self-contained interactive HTML player with embedded SCXML runtime and trace playback. |
178
+
179
+ ### Selection & Awareness (3)
180
+
181
+ | Tool | Description |
182
+ |------|-------------|
183
+ | `editor_get_selection` | Get selected states, transitions, and MCP highlights with colors. Includes buffered selection events. |
184
+ | `editor_get_viewport` | Get visible area, zoom level, pan offset, and buffered selection/document change events. |
185
+ | `editor_connect_simulator` | Connect editor to the simulator for live state highlights during simulation. |
186
+
187
+ ### Status (1)
188
+
189
+ | Tool | Description |
190
+ |------|-------------|
191
+ | `scxml_status` | Check connectivity of all three backends. |
192
+
193
+ ## Example Workflow
194
+
195
+ ```
196
+ User: "Design a vending machine that accepts quarters and dimes, costs $1.25"
197
+
198
+ Claude (using MCP):
199
+ 1. scxml_create(...) -- build the state machine
200
+ 2. scxml_validate(...) -- check it's valid
201
+ 3. editor_push_scxml(...) -- show it in the visual editor
202
+ 4. editor_highlight(..., "info") -- highlight key states in blue
203
+ 5. scxml_sim_scenario(...) -- test with: dime, quarter, quarter, quarter, quarter
204
+ 6. scxml_trace_embed(...) -- save the execution trace
205
+ 7. editor_export_svg(...) -- export diagram for documentation
206
+ 8. scxml_generate(...) -- generate Python code
207
+ 9. editor_save_file(...) -- save SCXML to disk
208
+ 10. editor_export_player_html(...) -- create interactive demo for team
209
+ ```
210
+
211
+ ## Development
212
+
213
+ ```bash
214
+ cd scxml-mcp
215
+ npm install
216
+ npm run build # Compile TypeScript
217
+ npm run dev # Watch mode
218
+ npm start # Run MCP server (stdio)
219
+ ```
220
+
221
+ ### Testing
222
+
223
+ ```bash
224
+ # Start backends first:
225
+ java -jar ../scxml-core/build/libs/scxml-core-*-all.jar serve --port 48620 --cors &
226
+ java -jar ../scxml-simulator/build/libs/scxml-simulator-*-all.jar serve --ws-port 48621 --rest-port 48622 --cors &
227
+
228
+ # Run tests:
229
+ python test-e2e.py # Basic MCP protocol tests (13 tests)
230
+ python test-phase2.py # Editor tools with mock WS (14 tests)
231
+ python test-phase4.py # Collaborative tools with mock WS (11 tests)
232
+ python test-integration-all.py # All 37 tools, real backends + mock editor (77 tests)
233
+
234
+ # Real integration test (requires real editor running):
235
+ # Start editor: cd ../scxml-editor && npm run dev:electron
236
+ python test-integration-real.py # 77 tests, ZERO mocks
237
+ python test-integration-real.py --start-editor # Auto-launches editor + REPL
238
+ python test-integration-real.py --quick # Skip slow generation targets
239
+ ```
240
+
241
+ ## Default Ports
242
+
243
+ | Port | Service | Protocol |
244
+ |------|---------|----------|
245
+ | 48620 | Generator REST API | HTTP |
246
+ | 48621 | Simulator WebSocket | WS |
247
+ | 48622 | Simulator REST API | HTTP |
248
+ | 48623 | Editor API | WS |
249
+
250
+ ## License
251
+
252
+ MIT
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,51 @@
1
+ #!/usr/bin/env node
2
+ import { startStdio } from '../index.js';
3
+ // Parse CLI arguments
4
+ const args = process.argv.slice(2);
5
+ const config = {};
6
+ for (let i = 0; i < args.length; i++) {
7
+ switch (args[i]) {
8
+ case '--generator':
9
+ config.generatorUrl = args[++i];
10
+ break;
11
+ case '--simulator':
12
+ config.simulatorUrl = args[++i];
13
+ break;
14
+ case '--editor':
15
+ config.editorUrl = args[++i];
16
+ break;
17
+ case '--help':
18
+ console.error(`
19
+ @vscxml/mcp - MCP server for VSCXML state machine suite
20
+
21
+ Usage: scxml-mcp [options]
22
+
23
+ Options:
24
+ --generator <url> Generator REST API URL (default: http://localhost:48620)
25
+ --simulator <url> Simulator WebSocket URL (default: ws://localhost:48621)
26
+ --editor <url> Editor WebSocket URL (default: ws://localhost:48623)
27
+ --help Show this help
28
+
29
+ Environment variables:
30
+ VSCXML_GENERATOR_URL Override generator URL
31
+ VSCXML_SIMULATOR_URL Override simulator URL
32
+ VSCXML_EDITOR_URL Override editor URL
33
+
34
+ Example Claude Desktop config (settings.json):
35
+ {
36
+ "mcpServers": {
37
+ "scxml-gen": {
38
+ "command": "npx",
39
+ "args": ["@vscxml/mcp"]
40
+ }
41
+ }
42
+ }
43
+ `);
44
+ process.exit(0);
45
+ }
46
+ }
47
+ startStdio(config).catch((err) => {
48
+ console.error('Failed to start MCP server:', err);
49
+ process.exit(1);
50
+ });
51
+ //# sourceMappingURL=scxml-mcp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scxml-mcp.js","sourceRoot":"","sources":["../../src/bin/scxml-mcp.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGzC,sBAAsB;AACtB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACnC,MAAM,MAAM,GAAc,EAAE,CAAC;AAE7B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;IACrC,QAAQ,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QAChB,KAAK,aAAa;YAChB,MAAM,CAAC,YAAY,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;YAChC,MAAM;QACR,KAAK,aAAa;YAChB,MAAM,CAAC,YAAY,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;YAChC,MAAM;QACR,KAAK,UAAU;YACb,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;YAC7B,MAAM;QACR,KAAK,QAAQ;YACX,OAAO,CAAC,KAAK,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;CAyBnB,CAAC,CAAC;YACG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;AACH,CAAC;AAED,UAAU,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IAC/B,OAAO,CAAC,KAAK,CAAC,6BAA6B,EAAE,GAAG,CAAC,CAAC;IAClD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,135 @@
1
+ /**
2
+ * WebSocket bridge to the VSCXML-Editor API.
3
+ * The editor's Electron main process runs a lightweight WS server on port 48623
4
+ * that relays commands to/from the React renderer via IPC.
5
+ */
6
+ export declare class EditorBridge {
7
+ private ws;
8
+ private url;
9
+ private connected;
10
+ private requestId;
11
+ private pendingRequests;
12
+ private lastSelection;
13
+ private lastDocumentChange;
14
+ constructor(url?: string);
15
+ setUrl(url: string): void;
16
+ isConnected(): boolean;
17
+ /** Connect to the editor WebSocket API */
18
+ connect(): Promise<void>;
19
+ /** Disconnect */
20
+ disconnect(): void;
21
+ /** Check if editor is reachable */
22
+ isAvailable(): Promise<boolean>;
23
+ /** Push SCXML content to the editor */
24
+ pushScxml(scxml: string): Promise<{
25
+ success: boolean;
26
+ }>;
27
+ /** Get current SCXML from the editor */
28
+ getScxml(): Promise<{
29
+ scxml: string;
30
+ modified: boolean;
31
+ }>;
32
+ /** Show a toast notification in the editor */
33
+ showNotification(message: string, severity?: 'info' | 'warning' | 'error' | 'success', duration?: number): Promise<void>;
34
+ /** Highlight specific states in the editor */
35
+ highlight(states: string[], options?: {
36
+ color?: string;
37
+ duration?: number;
38
+ clear?: boolean;
39
+ }): Promise<void>;
40
+ /** Add a note to the editor canvas */
41
+ addNote(content: string, options?: {
42
+ attachedTo?: string;
43
+ color?: string;
44
+ visibleWhen?: string[];
45
+ }): Promise<{
46
+ noteId: string;
47
+ }>;
48
+ /** Remove notes from the editor */
49
+ removeNotes(noteIds?: string[]): Promise<void>;
50
+ /** Navigate the editor canvas */
51
+ navigate(options: {
52
+ target?: string;
53
+ fitStates?: string[];
54
+ fitAll?: boolean;
55
+ zoom?: number;
56
+ }): Promise<void>;
57
+ /** Save content to a file path */
58
+ saveFile(filePath: string, content: string): Promise<{
59
+ success: boolean;
60
+ filePath: string;
61
+ }>;
62
+ /** Load a file from disk into the editor */
63
+ loadFile(filePath: string): Promise<{
64
+ content: string;
65
+ filePath: string;
66
+ }>;
67
+ /** Get the current file path from the editor */
68
+ getFilePath(): Promise<{
69
+ filePath: string | null;
70
+ }>;
71
+ /** Capture a screenshot of the editor window */
72
+ screenshot(): Promise<{
73
+ data: string;
74
+ format: string;
75
+ width: number;
76
+ height: number;
77
+ }>;
78
+ /** Connect the editor's simulator panel to the simulator backend */
79
+ connectSimulator(port?: number): Promise<{
80
+ success: boolean;
81
+ }>;
82
+ /** Get the current selection in the editor */
83
+ getSelection(): Promise<{
84
+ highlightedStates: string[];
85
+ cursorPosition: {
86
+ line: number;
87
+ column: number;
88
+ } | null;
89
+ }>;
90
+ /** Get the editor viewport state */
91
+ getViewport(): Promise<{
92
+ transform: {
93
+ x: number;
94
+ y: number;
95
+ scale: number;
96
+ };
97
+ viewportWidth: number;
98
+ viewportHeight: number;
99
+ visibleArea: {
100
+ left: number;
101
+ top: number;
102
+ right: number;
103
+ bottom: number;
104
+ };
105
+ }>;
106
+ /** Export the full diagram as SVG text */
107
+ exportSvg(): Promise<{
108
+ svg: string;
109
+ }>;
110
+ /** Export the full diagram as PNG (base64) */
111
+ exportPng(): Promise<{
112
+ data: string;
113
+ width: number;
114
+ height: number;
115
+ }>;
116
+ /** Export interactive Player HTML */
117
+ exportPlayerHtml(options?: {
118
+ exportMode?: string;
119
+ selectedTraceIds?: string[];
120
+ }): Promise<{
121
+ html: string;
122
+ }>;
123
+ /** Get editor status */
124
+ getStatus(): Promise<{
125
+ connected: boolean;
126
+ hasDocument: boolean;
127
+ documentName: string | null;
128
+ }>;
129
+ private handleMessage;
130
+ /** Get the latest buffered selection event */
131
+ getLastSelection(): typeof this.lastSelection;
132
+ /** Get the latest buffered document change event */
133
+ getLastDocumentChange(): typeof this.lastDocumentChange;
134
+ private sendRequest;
135
+ }