wocingflow-mcp-server 0.0.1

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,84 @@
1
+ # wocingflow-mcp-server
2
+
3
+ WocingFlow MCP launcher package compatible with `install-mcp`.
4
+
5
+ ## What this package does
6
+
7
+ - Starts WocingFlow backend `mcp_server` on HTTP (`127.0.0.1:8787` by default)
8
+ - Bridges HTTP MCP to stdio using `mcp-remote@latest`
9
+ - Exposes a bin command: `wocingflow-mcp-server`
10
+
11
+ ## Install to Cursor via install-mcp
12
+
13
+ After publishing this package to npm:
14
+
15
+ ## Configure Your AI Assistant
16
+
17
+ Use `install-mcp` to add the server to your AI assistant:
18
+
19
+ ```bash
20
+ npx -y install-mcp wocingflow-mcp-server --client claude-code
21
+ ```
22
+
23
+ Supported clients: `claude-code`, `cursor`, `windsurf`, `vscode`, `cline`, `roo-cline`, `claude`, `zed`, `goose`, `warp`, `codex`
24
+
25
+ ### Claude Code
26
+
27
+ ```bash
28
+ npx -y install-mcp wocingflow-mcp-server --client claude-code
29
+ ```
30
+
31
+ ### Cursor
32
+
33
+ ```bash
34
+ npx -y install-mcp wocingflow-mcp-server --client cursor
35
+ ```
36
+
37
+ ### VS Code / Copilot
38
+
39
+ ```bash
40
+ npx -y install-mcp wocingflow-mcp-server --client vscode
41
+ ```
42
+
43
+ ### Windsurf
44
+
45
+ ```bash
46
+ npx -y install-mcp wocingflow-mcp-server --client windsurf
47
+ ```
48
+
49
+ ### Cline
50
+
51
+ ```bash
52
+ npx -y install-mcp wocingflow-mcp-server --client cline
53
+ ```
54
+
55
+ Restart your AI assistant after adding the configuration.
56
+
57
+ ## Local .tgz install (Windows example)
58
+
59
+ Use `--package <path-to-tgz> <bin-name>` form instead of calling the `.tgz` directly:
60
+
61
+ ```bash
62
+ npx -y install-mcp "npx --yes --package d:/Project/wocingflow/mcp/wocingflow-mcp-server/wocingflow-mcp-server-0.0.1.tgz wocingflow-mcp-server" --client cursor --name wocingflow-mcp-server --yes
63
+ ```
64
+
65
+ ## Local development usage
66
+
67
+ From this folder:
68
+
69
+ ```bash
70
+ npm pack
71
+ ```
72
+
73
+ Then install the generated tarball target with `install-mcp`:
74
+
75
+ ```bash
76
+ npx -y install-mcp "npx --yes --package d:/Project/wocingflow/mcp/wocingflow-mcp-server/wocingflow-mcp-server-0.0.1.tgz wocingflow-mcp-server" --client cursor --name wocingflow-mcp-server --yes
77
+ ```
78
+
79
+ ## Environment variables
80
+
81
+ - `WF_MCP_SERVER_BIN`: absolute path to `mcp_server` binary (optional)
82
+ - `WF_SERVICE_DATA_DIR`: absolute path to `service/data` (optional)
83
+ - `WF_MCP_HTTP_HOST`: default `127.0.0.1`
84
+ - `WF_MCP_HTTP_PORT`: default `8787`
@@ -0,0 +1,200 @@
1
+ #!/usr/bin/env node
2
+ const fs = require("node:fs");
3
+ const path = require("node:path");
4
+ const net = require("node:net");
5
+ const { spawn } = require("node:child_process");
6
+
7
+ function sleep(ms) {
8
+ return new Promise((resolve) => setTimeout(resolve, ms));
9
+ }
10
+
11
+ function isWindows() {
12
+ return process.platform === "win32";
13
+ }
14
+
15
+ function fileExists(filePath) {
16
+ try {
17
+ return fs.existsSync(filePath);
18
+ } catch {
19
+ return false;
20
+ }
21
+ }
22
+
23
+ function candidateRoots() {
24
+ const cwd = process.cwd();
25
+ return [cwd, path.resolve(cwd, ".."), path.resolve(cwd, "..", "..")];
26
+ }
27
+
28
+ function resolveServiceDataDir() {
29
+ if (process.env.WF_SERVICE_DATA_DIR && fileExists(process.env.WF_SERVICE_DATA_DIR)) {
30
+ return process.env.WF_SERVICE_DATA_DIR;
31
+ }
32
+ for (const root of candidateRoots()) {
33
+ const candidate = path.join(root, "service", "data");
34
+ if (fileExists(candidate)) {
35
+ return candidate;
36
+ }
37
+ }
38
+ return "";
39
+ }
40
+
41
+ function resolveServerLaunch() {
42
+ if (process.env.WF_MCP_SERVER_BIN && fileExists(process.env.WF_MCP_SERVER_BIN)) {
43
+ return { command: process.env.WF_MCP_SERVER_BIN, args: [] };
44
+ }
45
+
46
+ const exeName = isWindows() ? "mcp_server.exe" : "mcp_server";
47
+ const bundledPath = path.join(__dirname, "..", "vendor", exeName);
48
+ if (fileExists(bundledPath)) {
49
+ return { command: bundledPath, args: [] };
50
+ }
51
+
52
+ for (const root of candidateRoots()) {
53
+ const debugPath = path.join(root, "service", "target", "debug", exeName);
54
+ const releasePath = path.join(root, "service", "target", "release", exeName);
55
+ if (fileExists(debugPath)) return { command: debugPath, args: [] };
56
+ if (fileExists(releasePath)) return { command: releasePath, args: [] };
57
+ }
58
+
59
+ for (const root of candidateRoots()) {
60
+ const manifestPath = path.join(root, "service", "Cargo.toml");
61
+ if (fileExists(manifestPath)) {
62
+ return {
63
+ command: "cargo",
64
+ args: ["run", "--manifest-path", manifestPath, "--bin", "mcp_server", "--"],
65
+ };
66
+ }
67
+ }
68
+
69
+ throw new Error(
70
+ "Cannot locate wocingflow mcp_server. Build service/bin/mcp_server or set WF_MCP_SERVER_BIN."
71
+ );
72
+ }
73
+
74
+ async function resolvePort() {
75
+ if (process.env.WF_MCP_HTTP_PORT) {
76
+ return String(process.env.WF_MCP_HTTP_PORT);
77
+ }
78
+ return String(
79
+ await new Promise((resolve, reject) => {
80
+ const server = net.createServer();
81
+ server.listen(0, "127.0.0.1", () => {
82
+ const address = server.address();
83
+ if (!address || typeof address === "string") {
84
+ server.close();
85
+ reject(new Error("Failed to allocate free TCP port."));
86
+ return;
87
+ }
88
+ const freePort = address.port;
89
+ server.close(() => resolve(freePort));
90
+ });
91
+ server.on("error", reject);
92
+ })
93
+ );
94
+ }
95
+
96
+ async function waitHealth(endpoint, timeoutMs) {
97
+ const started = Date.now();
98
+ while (Date.now() - started < timeoutMs) {
99
+ try {
100
+ const response = await fetch(`${endpoint}/health`);
101
+ if (response.ok) return;
102
+ } catch {
103
+ // keep waiting
104
+ }
105
+ await sleep(300);
106
+ }
107
+ throw new Error(`mcp_server health check timeout: ${endpoint}/health`);
108
+ }
109
+
110
+ function spawnBackend(command, args, env) {
111
+ const child = spawn(command, args, {
112
+ stdio: ["ignore", "pipe", "pipe"],
113
+ env,
114
+ shell: false,
115
+ windowsHide: true,
116
+ });
117
+ child.stdout.on("data", (chunk) => {
118
+ process.stderr.write(String(chunk));
119
+ });
120
+ child.stderr.on("data", (chunk) => {
121
+ process.stderr.write(String(chunk));
122
+ });
123
+ return child;
124
+ }
125
+
126
+ function spawnBridge(env, endpoint) {
127
+ let command;
128
+ let args;
129
+ if (isWindows()) {
130
+ command = "cmd.exe";
131
+ args = ["/d", "/s", "/c", `npx -y mcp-remote@latest ${endpoint}`];
132
+ } else {
133
+ command = "npx";
134
+ args = ["-y", "mcp-remote@latest", endpoint];
135
+ }
136
+
137
+ const child = spawn(command, args, {
138
+ stdio: ["pipe", "pipe", "pipe"],
139
+ env,
140
+ shell: false,
141
+ windowsHide: true,
142
+ });
143
+
144
+ process.stdin.pipe(child.stdin);
145
+ child.stdout.pipe(process.stdout);
146
+ child.stderr.pipe(process.stderr);
147
+ return child;
148
+ }
149
+
150
+ async function main() {
151
+ const host = process.env.WF_MCP_HTTP_HOST || "127.0.0.1";
152
+ const port = await resolvePort();
153
+ const endpoint = `http://${host}:${port}`;
154
+ const serviceDataDir = resolveServiceDataDir();
155
+ const launch = resolveServerLaunch();
156
+
157
+ const backendEnv = { ...process.env };
158
+ if (serviceDataDir) {
159
+ backendEnv.WF_SERVICE_DATA_DIR = serviceDataDir;
160
+ }
161
+
162
+ const backend = spawnBackend(
163
+ launch.command,
164
+ [...launch.args, "--host", host, "--port", String(port)],
165
+ backendEnv
166
+ );
167
+
168
+ let shuttingDown = false;
169
+ const shutdown = () => {
170
+ if (shuttingDown) return;
171
+ shuttingDown = true;
172
+ if (!backend.killed) {
173
+ backend.kill();
174
+ }
175
+ };
176
+
177
+ process.on("SIGINT", shutdown);
178
+ process.on("SIGTERM", shutdown);
179
+ process.on("exit", shutdown);
180
+
181
+ backend.on("exit", (code) => {
182
+ if (!shuttingDown && code !== 0) {
183
+ console.error(`[wocingflow-mcp] backend exited early with code ${code}`);
184
+ process.exit(code || 1);
185
+ }
186
+ });
187
+
188
+ await waitHealth(endpoint, 20000);
189
+
190
+ const bridge = spawnBridge(process.env, endpoint);
191
+ bridge.on("exit", (code) => {
192
+ shutdown();
193
+ process.exit(code || 0);
194
+ });
195
+ }
196
+
197
+ main().catch((error) => {
198
+ console.error(`[wocingflow-mcp] ${error.message}`);
199
+ process.exit(1);
200
+ });
package/package.json ADDED
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "wocingflow-mcp-server",
3
+ "version": "0.0.1",
4
+ "description": "MCP stdio launcher for WocingFlow service mcp_server",
5
+ "type": "commonjs",
6
+ "bin": {
7
+ "wocingflow-mcp-server": "bin/wocingflow-mcp-server.js"
8
+ },
9
+ "engines": {
10
+ "node": ">=18"
11
+ },
12
+ "scripts": {
13
+ "prepack": "node scripts/prepack.js"
14
+ },
15
+ "files": [
16
+ "bin",
17
+ "vendor"
18
+ ]
19
+ }
Binary file