@vscxml/mcp 0.1.2 → 0.1.4
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 +15 -42
- package/dist/bin/scxml-mcp.js +8 -3
- package/dist/bin/scxml-mcp.js.map +1 -1
- package/dist/index.js +11 -6
- package/dist/index.js.map +1 -1
- package/dist/process-manager.d.ts +3 -24
- package/dist/process-manager.js +4 -131
- package/dist/process-manager.js.map +1 -1
- package/package.json +2 -2
- package/server.json +3 -3
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@ LLM (Claude Code / Claude Desktop / Cursor)
|
|
|
10
10
|
| MCP Protocol (stdio)
|
|
11
11
|
v
|
|
12
12
|
+-----------------------------------------------+
|
|
13
|
-
| @vscxml/mcp
|
|
13
|
+
| @vscxml/mcp |
|
|
14
14
|
| |
|
|
15
15
|
| SimulatorBridge ----WS:48621----> Simulator |
|
|
16
16
|
| GeneratorBridge ---HTTP:48620---> Generator |
|
|
@@ -25,44 +25,28 @@ The MCP server is a **thin client** that bridges three VSCXML backends:
|
|
|
25
25
|
|
|
26
26
|
## Setup
|
|
27
27
|
|
|
28
|
-
### Claude Code
|
|
28
|
+
### Claude Code (one-line)
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
```bash
|
|
31
|
+
# Project-level (current project only):
|
|
32
|
+
claude mcp add vscxml -- npx -y @vscxml/mcp
|
|
31
33
|
|
|
32
|
-
|
|
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
|
-
}
|
|
34
|
+
# User-level (all projects):
|
|
35
|
+
claude mcp add -s user vscxml -- npx -y @vscxml/mcp
|
|
41
36
|
```
|
|
42
37
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
```json
|
|
46
|
-
{
|
|
47
|
-
"mcpServers": {
|
|
48
|
-
"scxml-gen": {
|
|
49
|
-
"command": "npx",
|
|
50
|
-
"args": ["@vscxml/mcp"]
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
```
|
|
38
|
+
Restart Claude Code after adding. The 37 tools will appear in the tool list.
|
|
55
39
|
|
|
56
40
|
### Claude Desktop
|
|
57
41
|
|
|
58
|
-
|
|
42
|
+
In `Settings > Developer > MCP Servers`:
|
|
59
43
|
|
|
60
44
|
```json
|
|
61
45
|
{
|
|
62
46
|
"mcpServers": {
|
|
63
|
-
"
|
|
47
|
+
"vscxml": {
|
|
64
48
|
"command": "npx",
|
|
65
|
-
"args": ["@vscxml/mcp"]
|
|
49
|
+
"args": ["-y", "@vscxml/mcp"]
|
|
66
50
|
}
|
|
67
51
|
}
|
|
68
52
|
}
|
|
@@ -70,24 +54,13 @@ Add to Claude Desktop settings (`Settings > Developer > MCP Servers`):
|
|
|
70
54
|
|
|
71
55
|
### Custom backend URLs
|
|
72
56
|
|
|
73
|
-
```
|
|
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
|
-
}
|
|
57
|
+
```bash
|
|
58
|
+
claude mcp add vscxml -- npx -y @vscxml/mcp --generator http://localhost:48620 --simulator ws://localhost:48621 --editor ws://localhost:48623
|
|
82
59
|
```
|
|
83
60
|
|
|
84
|
-
Or via environment variables:
|
|
61
|
+
Or via environment variables: `VSCXML_GENERATOR_URL`, `VSCXML_SIMULATOR_URL`, `VSCXML_EDITOR_URL`.
|
|
85
62
|
|
|
86
|
-
|
|
87
|
-
VSCXML_GENERATOR_URL=http://localhost:48620
|
|
88
|
-
VSCXML_SIMULATOR_URL=ws://localhost:48621
|
|
89
|
-
VSCXML_EDITOR_URL=ws://localhost:48623
|
|
90
|
-
```
|
|
63
|
+
> **Full setup guide with usage examples:** [vscxml.com/docs/mcp-setup.html](https://vscxml.com/docs/mcp-setup.html)
|
|
91
64
|
|
|
92
65
|
## Prerequisites
|
|
93
66
|
|
package/dist/bin/scxml-mcp.js
CHANGED
|
@@ -31,15 +31,20 @@ Environment variables:
|
|
|
31
31
|
VSCXML_SIMULATOR_URL Override simulator URL
|
|
32
32
|
VSCXML_EDITOR_URL Override editor URL
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
Install:
|
|
35
|
+
claude mcp add vscxml -- npx -y @vscxml/mcp
|
|
36
|
+
|
|
37
|
+
Claude Desktop config (settings.json):
|
|
35
38
|
{
|
|
36
39
|
"mcpServers": {
|
|
37
|
-
"
|
|
40
|
+
"vscxml": {
|
|
38
41
|
"command": "npx",
|
|
39
|
-
"args": ["@vscxml/mcp"]
|
|
42
|
+
"args": ["-y", "@vscxml/mcp"]
|
|
40
43
|
}
|
|
41
44
|
}
|
|
42
45
|
}
|
|
46
|
+
|
|
47
|
+
Docs: https://vscxml.com/docs/mcp-setup.html
|
|
43
48
|
`);
|
|
44
49
|
process.exit(0);
|
|
45
50
|
}
|
|
@@ -1 +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
|
|
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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8BnB,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"}
|
package/dist/index.js
CHANGED
|
@@ -8,22 +8,27 @@ export { createServer } from './server.js';
|
|
|
8
8
|
*/
|
|
9
9
|
export async function startStdio(config = {}) {
|
|
10
10
|
const processManager = new ProcessManager();
|
|
11
|
-
//
|
|
12
|
-
const genUrl = await processManager.
|
|
11
|
+
// Discover backends (never auto-spawn — user must start them manually)
|
|
12
|
+
const genUrl = await processManager.discoverGenerator(config.generatorUrl);
|
|
13
13
|
if (genUrl) {
|
|
14
14
|
config.generatorUrl = genUrl;
|
|
15
15
|
console.error(`[MCP] Generator: ${genUrl}`);
|
|
16
16
|
}
|
|
17
|
-
|
|
17
|
+
else {
|
|
18
|
+
console.error(`[MCP] Generator not found. Start it manually: vscxml-generator-cli serve --port ${8080} --cors`);
|
|
19
|
+
}
|
|
20
|
+
const simUrl = await processManager.discoverSimulator(config.simulatorUrl);
|
|
18
21
|
if (simUrl) {
|
|
19
22
|
config.simulatorUrl = simUrl;
|
|
20
23
|
console.error(`[MCP] Simulator: ${simUrl}`);
|
|
21
24
|
}
|
|
25
|
+
else {
|
|
26
|
+
console.error(`[MCP] Simulator not found. Start it manually before using simulation tools.`);
|
|
27
|
+
}
|
|
22
28
|
const server = createServer(config);
|
|
23
29
|
const transport = new StdioServerTransport();
|
|
24
|
-
|
|
25
|
-
process.on('
|
|
26
|
-
process.on('SIGTERM', () => { processManager.shutdown(); process.exit(0); });
|
|
30
|
+
process.on('SIGINT', () => process.exit(0));
|
|
31
|
+
process.on('SIGTERM', () => process.exit(0));
|
|
27
32
|
await server.connect(transport);
|
|
28
33
|
}
|
|
29
34
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAGtD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3C;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,SAAoB,EAAE;IACrD,MAAM,cAAc,GAAG,IAAI,cAAc,EAAE,CAAC;IAE5C,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAGtD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3C;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,SAAoB,EAAE;IACrD,MAAM,cAAc,GAAG,IAAI,cAAc,EAAE,CAAC;IAE5C,uEAAuE;IACvE,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,iBAAiB,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;IAC3E,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,CAAC,YAAY,GAAG,MAAM,CAAC;QAC7B,OAAO,CAAC,KAAK,CAAC,oBAAoB,MAAM,EAAE,CAAC,CAAC;IAC9C,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,KAAK,CAAC,mFAAmF,IAAI,SAAS,CAAC,CAAC;IAClH,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,iBAAiB,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;IAC3E,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,CAAC,YAAY,GAAG,MAAM,CAAC;QAC7B,OAAO,CAAC,KAAK,CAAC,oBAAoB,MAAM,EAAE,CAAC,CAAC;IAC9C,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,KAAK,CAAC,6EAA6E,CAAC,CAAC;IAC/F,CAAC;IAED,MAAM,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;IACpC,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAE7C,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5C,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAE7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAClC,CAAC"}
|
|
@@ -1,42 +1,21 @@
|
|
|
1
|
-
import { ChildProcess } from 'child_process';
|
|
2
1
|
/**
|
|
3
|
-
* Discovers
|
|
2
|
+
* Discovers VSCXML backend processes running on known ports.
|
|
4
3
|
*
|
|
5
4
|
* Discovery order for each backend:
|
|
6
5
|
* 1. Environment variable (VSCXML_GENERATOR_URL, etc.)
|
|
7
6
|
* 2. MCP config args (--generator, --simulator)
|
|
8
7
|
* 3. Default ports (probe localhost)
|
|
9
|
-
*
|
|
8
|
+
*
|
|
9
|
+
* If a backend is not found, returns null — the user must start it manually.
|
|
10
10
|
*/
|
|
11
11
|
export declare class ProcessManager {
|
|
12
|
-
private children;
|
|
13
12
|
/** Discover the generator URL */
|
|
14
13
|
discoverGenerator(configUrl?: string): Promise<string | null>;
|
|
15
14
|
/** Discover the simulator URL */
|
|
16
15
|
discoverSimulator(configUrl?: string): Promise<string | null>;
|
|
17
16
|
/** Discover the editor URL */
|
|
18
17
|
discoverEditor(configUrl?: string): Promise<string | null>;
|
|
19
|
-
/** Get known install paths for the generator CLI */
|
|
20
|
-
getGeneratorPaths(): string[];
|
|
21
|
-
/** Get known install paths for the simulator */
|
|
22
|
-
getSimulatorPaths(): string[];
|
|
23
|
-
/** Spawn a generator process */
|
|
24
|
-
spawnGenerator(execPath: string, port?: number): ChildProcess;
|
|
25
|
-
/** Spawn a simulator process */
|
|
26
|
-
spawnSimulator(execPath: string, wsPort?: number, restPort?: number): ChildProcess;
|
|
27
|
-
/** Shut down all spawned child processes */
|
|
28
18
|
shutdown(): void;
|
|
29
|
-
/**
|
|
30
|
-
* Auto-discover and optionally spawn the generator backend.
|
|
31
|
-
* Returns the URL if available, null if not.
|
|
32
|
-
*/
|
|
33
|
-
ensureGenerator(configUrl?: string): Promise<string | null>;
|
|
34
|
-
/**
|
|
35
|
-
* Auto-discover and optionally spawn the simulator backend.
|
|
36
|
-
*/
|
|
37
|
-
ensureSimulator(configUrl?: string): Promise<string | null>;
|
|
38
|
-
private waitForHealth;
|
|
39
|
-
private waitForWs;
|
|
40
19
|
private probeHttp;
|
|
41
20
|
private probeWs;
|
|
42
21
|
}
|
package/dist/process-manager.js
CHANGED
|
@@ -1,28 +1,22 @@
|
|
|
1
|
-
import { spawn } from 'child_process';
|
|
2
|
-
import { existsSync } from 'fs';
|
|
3
|
-
import { join } from 'path';
|
|
4
1
|
import { DEFAULT_PORTS } from './types.js';
|
|
5
2
|
/**
|
|
6
|
-
* Discovers
|
|
3
|
+
* Discovers VSCXML backend processes running on known ports.
|
|
7
4
|
*
|
|
8
5
|
* Discovery order for each backend:
|
|
9
6
|
* 1. Environment variable (VSCXML_GENERATOR_URL, etc.)
|
|
10
7
|
* 2. MCP config args (--generator, --simulator)
|
|
11
8
|
* 3. Default ports (probe localhost)
|
|
12
|
-
*
|
|
9
|
+
*
|
|
10
|
+
* If a backend is not found, returns null — the user must start it manually.
|
|
13
11
|
*/
|
|
14
12
|
export class ProcessManager {
|
|
15
|
-
children = [];
|
|
16
13
|
/** Discover the generator URL */
|
|
17
14
|
async discoverGenerator(configUrl) {
|
|
18
|
-
// 1. Env var
|
|
19
15
|
const envUrl = process.env.VSCXML_GENERATOR_URL;
|
|
20
16
|
if (envUrl)
|
|
21
17
|
return envUrl;
|
|
22
|
-
// 2. Config
|
|
23
18
|
if (configUrl)
|
|
24
19
|
return configUrl;
|
|
25
|
-
// 3. Probe default port
|
|
26
20
|
const defaultUrl = `http://localhost:${DEFAULT_PORTS.generator}`;
|
|
27
21
|
if (await this.probeHttp(defaultUrl))
|
|
28
22
|
return defaultUrl;
|
|
@@ -30,14 +24,11 @@ export class ProcessManager {
|
|
|
30
24
|
}
|
|
31
25
|
/** Discover the simulator URL */
|
|
32
26
|
async discoverSimulator(configUrl) {
|
|
33
|
-
// 1. Env var
|
|
34
27
|
const envUrl = process.env.VSCXML_SIMULATOR_URL;
|
|
35
28
|
if (envUrl)
|
|
36
29
|
return envUrl;
|
|
37
|
-
// 2. Config
|
|
38
30
|
if (configUrl)
|
|
39
31
|
return configUrl;
|
|
40
|
-
// 3. Probe default port
|
|
41
32
|
const defaultUrl = `ws://localhost:${DEFAULT_PORTS.simulatorWs}`;
|
|
42
33
|
if (await this.probeWs(defaultUrl))
|
|
43
34
|
return defaultUrl;
|
|
@@ -55,124 +46,8 @@ export class ProcessManager {
|
|
|
55
46
|
return defaultUrl;
|
|
56
47
|
return null;
|
|
57
48
|
}
|
|
58
|
-
/** Get known install paths for the generator CLI */
|
|
59
|
-
getGeneratorPaths() {
|
|
60
|
-
const platform = process.platform;
|
|
61
|
-
const paths = [];
|
|
62
|
-
if (platform === 'win32') {
|
|
63
|
-
const localAppData = process.env.LOCALAPPDATA || '';
|
|
64
|
-
paths.push(join(localAppData, 'VSCXML-Generator-CLI', 'vscxml-generator-cli.exe'));
|
|
65
|
-
}
|
|
66
|
-
else if (platform === 'darwin') {
|
|
67
|
-
paths.push('/Applications/VSCXML-Generator-CLI.app/Contents/MacOS/VSCXML-Generator-CLI');
|
|
68
|
-
}
|
|
69
|
-
else {
|
|
70
|
-
paths.push('/opt/vscxml-generator-cli/bin/vscxml-generator-cli');
|
|
71
|
-
}
|
|
72
|
-
return paths.filter((p) => existsSync(p));
|
|
73
|
-
}
|
|
74
|
-
/** Get known install paths for the simulator */
|
|
75
|
-
getSimulatorPaths() {
|
|
76
|
-
const platform = process.platform;
|
|
77
|
-
const paths = [];
|
|
78
|
-
if (platform === 'win32') {
|
|
79
|
-
const localAppData = process.env.LOCALAPPDATA || '';
|
|
80
|
-
paths.push(join(localAppData, 'VSCXML-Simulator', 'vscxml-simulator.exe'));
|
|
81
|
-
}
|
|
82
|
-
else if (platform === 'darwin') {
|
|
83
|
-
paths.push('/Applications/VSCXML-Simulator.app/Contents/MacOS/VSCXML-Simulator');
|
|
84
|
-
}
|
|
85
|
-
else {
|
|
86
|
-
paths.push('/opt/vscxml-simulator/bin/vscxml-simulator');
|
|
87
|
-
}
|
|
88
|
-
return paths.filter((p) => existsSync(p));
|
|
89
|
-
}
|
|
90
|
-
/** Spawn a generator process */
|
|
91
|
-
spawnGenerator(execPath, port = DEFAULT_PORTS.generator) {
|
|
92
|
-
const child = spawn(execPath, ['serve', '--port', String(port), '--cors'], {
|
|
93
|
-
stdio: 'ignore',
|
|
94
|
-
detached: false,
|
|
95
|
-
});
|
|
96
|
-
this.children.push(child);
|
|
97
|
-
return child;
|
|
98
|
-
}
|
|
99
|
-
/** Spawn a simulator process */
|
|
100
|
-
spawnSimulator(execPath, wsPort = DEFAULT_PORTS.simulatorWs, restPort = DEFAULT_PORTS.simulatorRest) {
|
|
101
|
-
const child = spawn(execPath, ['serve', '--ws-port', String(wsPort), '--rest-port', String(restPort), '--cors'], { stdio: 'ignore', detached: false });
|
|
102
|
-
this.children.push(child);
|
|
103
|
-
return child;
|
|
104
|
-
}
|
|
105
|
-
/** Shut down all spawned child processes */
|
|
106
49
|
shutdown() {
|
|
107
|
-
|
|
108
|
-
try {
|
|
109
|
-
child.kill();
|
|
110
|
-
}
|
|
111
|
-
catch {
|
|
112
|
-
// ignore
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
this.children = [];
|
|
116
|
-
}
|
|
117
|
-
/**
|
|
118
|
-
* Auto-discover and optionally spawn the generator backend.
|
|
119
|
-
* Returns the URL if available, null if not.
|
|
120
|
-
*/
|
|
121
|
-
async ensureGenerator(configUrl) {
|
|
122
|
-
// Try discovery first
|
|
123
|
-
const url = await this.discoverGenerator(configUrl);
|
|
124
|
-
if (url)
|
|
125
|
-
return url;
|
|
126
|
-
// Try auto-spawn
|
|
127
|
-
const paths = this.getGeneratorPaths();
|
|
128
|
-
if (paths.length === 0)
|
|
129
|
-
return null;
|
|
130
|
-
console.error(`[ProcessManager] Generator not found on default port, spawning ${paths[0]}...`);
|
|
131
|
-
this.spawnGenerator(paths[0]);
|
|
132
|
-
// Wait for it to come up (poll health)
|
|
133
|
-
const targetUrl = `http://localhost:${DEFAULT_PORTS.generator}`;
|
|
134
|
-
if (await this.waitForHealth(targetUrl, 15000)) {
|
|
135
|
-
return targetUrl;
|
|
136
|
-
}
|
|
137
|
-
console.error('[ProcessManager] Generator failed to start');
|
|
138
|
-
return null;
|
|
139
|
-
}
|
|
140
|
-
/**
|
|
141
|
-
* Auto-discover and optionally spawn the simulator backend.
|
|
142
|
-
*/
|
|
143
|
-
async ensureSimulator(configUrl) {
|
|
144
|
-
const url = await this.discoverSimulator(configUrl);
|
|
145
|
-
if (url)
|
|
146
|
-
return url;
|
|
147
|
-
const paths = this.getSimulatorPaths();
|
|
148
|
-
if (paths.length === 0)
|
|
149
|
-
return null;
|
|
150
|
-
console.error(`[ProcessManager] Simulator not found on default port, spawning ${paths[0]}...`);
|
|
151
|
-
this.spawnSimulator(paths[0]);
|
|
152
|
-
const targetUrl = `ws://localhost:${DEFAULT_PORTS.simulatorWs}`;
|
|
153
|
-
if (await this.waitForWs(targetUrl, 15000)) {
|
|
154
|
-
return targetUrl;
|
|
155
|
-
}
|
|
156
|
-
console.error('[ProcessManager] Simulator failed to start');
|
|
157
|
-
return null;
|
|
158
|
-
}
|
|
159
|
-
async waitForHealth(url, timeoutMs) {
|
|
160
|
-
const deadline = Date.now() + timeoutMs;
|
|
161
|
-
while (Date.now() < deadline) {
|
|
162
|
-
if (await this.probeHttp(url))
|
|
163
|
-
return true;
|
|
164
|
-
await new Promise((r) => setTimeout(r, 500));
|
|
165
|
-
}
|
|
166
|
-
return false;
|
|
167
|
-
}
|
|
168
|
-
async waitForWs(url, timeoutMs) {
|
|
169
|
-
const deadline = Date.now() + timeoutMs;
|
|
170
|
-
while (Date.now() < deadline) {
|
|
171
|
-
if (await this.probeWs(url))
|
|
172
|
-
return true;
|
|
173
|
-
await new Promise((r) => setTimeout(r, 500));
|
|
174
|
-
}
|
|
175
|
-
return false;
|
|
50
|
+
// No-op: we no longer spawn child processes
|
|
176
51
|
}
|
|
177
52
|
async probeHttp(url) {
|
|
178
53
|
try {
|
|
@@ -186,8 +61,6 @@ export class ProcessManager {
|
|
|
186
61
|
}
|
|
187
62
|
}
|
|
188
63
|
async probeWs(url) {
|
|
189
|
-
// Use a simple TCP connection probe instead of full WS handshake.
|
|
190
|
-
// More reliable on Windows where WS open/close races can cause false negatives.
|
|
191
64
|
const { createConnection } = await import('net');
|
|
192
65
|
const parsed = new URL(url);
|
|
193
66
|
const port = parseInt(parsed.port) || 48621;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"process-manager.js","sourceRoot":"","sources":["../src/process-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"process-manager.js","sourceRoot":"","sources":["../src/process-manager.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vscxml/mcp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "MCP server for the VSCXML suite — 37 tools for designing, simulating, generating, and visually editing W3C SCXML state machines via LLMs (Claude Code, Claude Desktop, Cursor)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
],
|
|
57
57
|
"repository": {
|
|
58
58
|
"type": "git",
|
|
59
|
-
"url": "https://github.com/
|
|
59
|
+
"url": "https://github.com/miho/vscxml",
|
|
60
60
|
"directory": "scxml-mcp"
|
|
61
61
|
}
|
|
62
62
|
}
|
package/server.json
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://registry.modelcontextprotocol.io/schemas/server.json",
|
|
3
|
-
"name": "io.github.
|
|
3
|
+
"name": "io.github.miho/vscxml",
|
|
4
4
|
"title": "VSCXML — State Machine Design, Simulation & Code Generation",
|
|
5
5
|
"description": "37 MCP tools for VSCXML — design, simulate, generate, and visually edit W3C SCXML state machines. Create state machines from natural language, simulate behavior with traces, generate production code for 7 targets (Java, JavaScript, C#, C, Python, Go, Structured Text), export SVG/PNG/interactive HTML, and collaborate visually with the VSCXML-Editor. Works with VSCXML-Generator-CLI, VSCXML-Simulator, and VSCXML-Editor.",
|
|
6
6
|
"homepage": "https://vscxml.com/docs/mcp-setup.html",
|
|
7
7
|
"repository": {
|
|
8
|
-
"url": "https://github.com/
|
|
8
|
+
"url": "https://github.com/miho/vscxml",
|
|
9
9
|
"source": "github"
|
|
10
10
|
},
|
|
11
11
|
"packages": [
|
|
12
12
|
{
|
|
13
13
|
"registry_name": "npm",
|
|
14
14
|
"name": "@vscxml/mcp",
|
|
15
|
-
"version": "0.1.
|
|
15
|
+
"version": "0.1.3",
|
|
16
16
|
"runtime": "node",
|
|
17
17
|
"environment_variables": [
|
|
18
18
|
{
|