nova-control-mcp-server 0.0.6 → 0.0.7
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/dist/nova-control-mcp-server.js +291 -61
- package/package.json +1 -1
|
@@ -7,9 +7,239 @@ import { Server as i } from "@modelcontextprotocol/sdk/server/index.js";
|
|
|
7
7
|
import { StdioServerTransport as a } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
8
8
|
import { StreamableHTTPServerTransport as o } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
9
9
|
import { CallToolRequestSchema as s, ListToolsRequestSchema as c } from "@modelcontextprotocol/sdk/types.js";
|
|
10
|
-
import {
|
|
10
|
+
import { SerialPort as l } from "serialport";
|
|
11
|
+
//#region ../nova-control-node/dist/nova-control-node.js
|
|
12
|
+
var u = 9600, d = Object.freeze({
|
|
13
|
+
s1: 90,
|
|
14
|
+
s2: 90,
|
|
15
|
+
s3: 110,
|
|
16
|
+
s4: 90,
|
|
17
|
+
s5: 95
|
|
18
|
+
}), f = Object.freeze({
|
|
19
|
+
s1: [45, 135],
|
|
20
|
+
s2: [10, 170],
|
|
21
|
+
s3: [40, 150],
|
|
22
|
+
s4: [30, 180],
|
|
23
|
+
s5: [20, 150]
|
|
24
|
+
}), p = Object.freeze({
|
|
25
|
+
s1: (f.s1[1] - f.s1[0]) / 1e3,
|
|
26
|
+
s2: (f.s2[1] - f.s2[0]) / 1e3,
|
|
27
|
+
s3: (f.s3[1] - f.s3[0]) / 1e3,
|
|
28
|
+
s4: (f.s4[1] - f.s4[0]) / 1e3,
|
|
29
|
+
s5: (f.s5[1] - f.s5[0]) / 1e3
|
|
30
|
+
});
|
|
31
|
+
function m(e, t) {
|
|
32
|
+
let [n, r] = f[t];
|
|
33
|
+
return Math.max(n, Math.min(r, Math.round(e)));
|
|
34
|
+
}
|
|
35
|
+
function h(e) {
|
|
36
|
+
return new Uint8Array([
|
|
37
|
+
m(e.s4, "s4"),
|
|
38
|
+
m(e.s3, "s3"),
|
|
39
|
+
m(e.s2, "s2"),
|
|
40
|
+
m(e.s1, "s1"),
|
|
41
|
+
m(e.s5, "s5")
|
|
42
|
+
]);
|
|
43
|
+
}
|
|
44
|
+
async function g(e, t) {
|
|
45
|
+
let n = new l({
|
|
46
|
+
path: e,
|
|
47
|
+
baudRate: t,
|
|
48
|
+
autoOpen: !1
|
|
49
|
+
});
|
|
50
|
+
return await new Promise((e, t) => {
|
|
51
|
+
n.open((n) => {
|
|
52
|
+
n == null ? e() : t(n);
|
|
53
|
+
});
|
|
54
|
+
}), await new Promise((e) => setTimeout(e, 2e3)), {
|
|
55
|
+
async write(e) {
|
|
56
|
+
await new Promise((t, r) => {
|
|
57
|
+
n.write(Buffer.from(e), (e) => {
|
|
58
|
+
e == null ? t() : r(e);
|
|
59
|
+
});
|
|
60
|
+
}), await new Promise((e, t) => {
|
|
61
|
+
n.drain((n) => {
|
|
62
|
+
n == null ? e() : t(n);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
},
|
|
66
|
+
destroy() {
|
|
67
|
+
n.close();
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
function _(e, t) {
|
|
72
|
+
let n = Math.min(.499, Math.max(0, t)), r = 1 / (1 - n);
|
|
73
|
+
if (e <= n) return r * e * e / (2 * n);
|
|
74
|
+
if (e <= 1 - n) return r * (e - n / 2);
|
|
75
|
+
let i = 1 - e;
|
|
76
|
+
return 1 - r * i * i / (2 * n);
|
|
77
|
+
}
|
|
78
|
+
async function v(e, t = u, n) {
|
|
79
|
+
let r = n?.StepIntervalMs ?? 20, i = n?.RampRatio ?? .25, a = await g(e, t), o = { ...d }, s, c = Promise.resolve();
|
|
80
|
+
function l(e) {
|
|
81
|
+
s = {
|
|
82
|
+
...s ?? o,
|
|
83
|
+
...e
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
async function f() {
|
|
87
|
+
let e = c;
|
|
88
|
+
c = (async () => {
|
|
89
|
+
try {
|
|
90
|
+
await e;
|
|
91
|
+
} catch {}
|
|
92
|
+
for (; s != null;) {
|
|
93
|
+
let e = s, t = !0, n = { ...o };
|
|
94
|
+
for (let i of [
|
|
95
|
+
"s1",
|
|
96
|
+
"s2",
|
|
97
|
+
"s3",
|
|
98
|
+
"s4",
|
|
99
|
+
"s5"
|
|
100
|
+
]) {
|
|
101
|
+
let a = e[i] - o[i], s = r > 0 ? p[i] * r : Infinity;
|
|
102
|
+
Math.abs(a) > s ? (n[i] = o[i] + Math.sign(a) * s, t = !1) : n[i] = e[i];
|
|
103
|
+
}
|
|
104
|
+
t && (s = void 0), o = { ...n }, await a.write(h(n)), t || await new Promise((e) => setTimeout(e, r));
|
|
105
|
+
}
|
|
106
|
+
})(), await c;
|
|
107
|
+
}
|
|
108
|
+
async function m(e, t) {
|
|
109
|
+
let n = c;
|
|
110
|
+
c = (async () => {
|
|
111
|
+
try {
|
|
112
|
+
await n;
|
|
113
|
+
} catch {}
|
|
114
|
+
let c = { ...o }, l = r > 0 ? Math.max(1, Math.round(t / r)) : 1;
|
|
115
|
+
s = void 0;
|
|
116
|
+
for (let t = 1; t <= l; t++) {
|
|
117
|
+
let n = _(t / l, i), s = { ...o };
|
|
118
|
+
for (let t of Object.keys(e)) s[t] = Math.round(c[t] + (e[t] - c[t]) * n);
|
|
119
|
+
o = s, await a.write(h(s)), t < l && await new Promise((e) => setTimeout(e, r));
|
|
120
|
+
}
|
|
121
|
+
})(), await c;
|
|
122
|
+
}
|
|
123
|
+
return {
|
|
124
|
+
async home(e) {
|
|
125
|
+
e != null && e > 0 ? await m({ ...d }, e) : (l({ ...d }), await f());
|
|
126
|
+
},
|
|
127
|
+
async shiftHeadTo(e, t) {
|
|
128
|
+
t != null && t > 0 ? await m({ s1: e }, t) : (l({ s1: e }), await f());
|
|
129
|
+
},
|
|
130
|
+
async rollHeadTo(e, t) {
|
|
131
|
+
t != null && t > 0 ? await m({ s2: e }, t) : (l({ s2: e }), await f());
|
|
132
|
+
},
|
|
133
|
+
async pitchHeadTo(e, t) {
|
|
134
|
+
t != null && t > 0 ? await m({ s3: e }, t) : (l({ s3: e }), await f());
|
|
135
|
+
},
|
|
136
|
+
async liftHeadTo(e, t) {
|
|
137
|
+
t != null && t > 0 ? await m({ s5: e }, t) : (l({ s5: e }), await f());
|
|
138
|
+
},
|
|
139
|
+
async rotateBodyTo(e, t) {
|
|
140
|
+
t != null && t > 0 ? await m({ s4: e }, t) : (l({ s4: e }), await f());
|
|
141
|
+
},
|
|
142
|
+
async moveTo(e, t) {
|
|
143
|
+
t != null && t > 0 ? await m(e, t) : (l(e), await f());
|
|
144
|
+
},
|
|
145
|
+
get State() {
|
|
146
|
+
return structuredClone(s ?? o);
|
|
147
|
+
},
|
|
148
|
+
set State(e) {
|
|
149
|
+
s = {
|
|
150
|
+
...o,
|
|
151
|
+
...e
|
|
152
|
+
};
|
|
153
|
+
},
|
|
154
|
+
async sendServoState() {
|
|
155
|
+
await f();
|
|
156
|
+
},
|
|
157
|
+
destroy() {
|
|
158
|
+
a.destroy();
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
async function y(e, t) {
|
|
163
|
+
let n = t.split("\n");
|
|
164
|
+
for (let t = 0; t < n.length; t++) {
|
|
165
|
+
let r = n[t].trim(), i = t + 1;
|
|
166
|
+
if (r === "" || r.startsWith("#")) continue;
|
|
167
|
+
let a = r.split(/\s+/), o = a[0].toLowerCase();
|
|
168
|
+
switch (!0) {
|
|
169
|
+
case o === "home":
|
|
170
|
+
await e.home();
|
|
171
|
+
break;
|
|
172
|
+
case o === "shift-to": {
|
|
173
|
+
let t = Number(a[1]);
|
|
174
|
+
if (isNaN(t)) throw Error(`line ${i}: shift-to requires a numeric angle, got '${a[1]}'`);
|
|
175
|
+
await e.shiftHeadTo(t);
|
|
176
|
+
break;
|
|
177
|
+
}
|
|
178
|
+
case o === "roll-to": {
|
|
179
|
+
let t = Number(a[1]);
|
|
180
|
+
if (isNaN(t)) throw Error(`line ${i}: roll-to requires a numeric angle, got '${a[1]}'`);
|
|
181
|
+
await e.rollHeadTo(t);
|
|
182
|
+
break;
|
|
183
|
+
}
|
|
184
|
+
case o === "pitch-to": {
|
|
185
|
+
let t = Number(a[1]);
|
|
186
|
+
if (isNaN(t)) throw Error(`line ${i}: pitch-to requires a numeric angle, got '${a[1]}'`);
|
|
187
|
+
await e.pitchHeadTo(t);
|
|
188
|
+
break;
|
|
189
|
+
}
|
|
190
|
+
case o === "rotate-to": {
|
|
191
|
+
let t = Number(a[1]);
|
|
192
|
+
if (isNaN(t)) throw Error(`line ${i}: rotate-to requires a numeric angle, got '${a[1]}'`);
|
|
193
|
+
await e.rotateBodyTo(t);
|
|
194
|
+
break;
|
|
195
|
+
}
|
|
196
|
+
case o === "lift-to": {
|
|
197
|
+
let t = Number(a[1]);
|
|
198
|
+
if (isNaN(t)) throw Error(`line ${i}: lift-to requires a numeric angle, got '${a[1]}'`);
|
|
199
|
+
await e.liftHeadTo(t);
|
|
200
|
+
break;
|
|
201
|
+
}
|
|
202
|
+
case o === "move": {
|
|
203
|
+
let t = {};
|
|
204
|
+
for (let e = 1; e < a.length; e += 2) {
|
|
205
|
+
let n = a[e].toLowerCase(), r = Number(a[e + 1]);
|
|
206
|
+
if (isNaN(r)) throw Error(`line ${i}: '${n}' requires a numeric angle, got '${a[e + 1]}'`);
|
|
207
|
+
switch (n) {
|
|
208
|
+
case "shift-to":
|
|
209
|
+
t.s1 = r;
|
|
210
|
+
break;
|
|
211
|
+
case "roll-to":
|
|
212
|
+
t.s2 = r;
|
|
213
|
+
break;
|
|
214
|
+
case "pitch-to":
|
|
215
|
+
t.s3 = r;
|
|
216
|
+
break;
|
|
217
|
+
case "rotate-to":
|
|
218
|
+
t.s4 = r;
|
|
219
|
+
break;
|
|
220
|
+
case "lift-to":
|
|
221
|
+
t.s5 = r;
|
|
222
|
+
break;
|
|
223
|
+
default: throw Error(`line ${i}: unknown move argument '${n}'`);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
if (Object.keys(t).length === 0) throw Error(`line ${i}: move requires at least one servo argument`);
|
|
227
|
+
e.State = t, await e.sendServoState();
|
|
228
|
+
break;
|
|
229
|
+
}
|
|
230
|
+
case o === "wait": {
|
|
231
|
+
let e = Number(a[1]);
|
|
232
|
+
if (isNaN(e) || e < 0) throw Error(`line ${i}: wait requires a non-negative number in ms, got '${a[1]}'`);
|
|
233
|
+
await new Promise((t) => setTimeout(t, e));
|
|
234
|
+
break;
|
|
235
|
+
}
|
|
236
|
+
default: throw Error(`line ${i}: unknown command '${o}'`);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
//#endregion
|
|
11
241
|
//#region src/nova-control-mcp-server.ts
|
|
12
|
-
function
|
|
242
|
+
function b() {
|
|
13
243
|
try {
|
|
14
244
|
let { values: e } = r({
|
|
15
245
|
args: process.argv.slice(2),
|
|
@@ -46,20 +276,20 @@ function d() {
|
|
|
46
276
|
process.stderr.write(`nova-control-mcp: ${e.message ?? e}\n`), process.exit(1);
|
|
47
277
|
}
|
|
48
278
|
}
|
|
49
|
-
var
|
|
50
|
-
async function
|
|
51
|
-
return
|
|
279
|
+
var x = "", S = 9600, C;
|
|
280
|
+
async function w() {
|
|
281
|
+
return C ??= await v(x, S), C;
|
|
52
282
|
}
|
|
53
|
-
function
|
|
54
|
-
|
|
283
|
+
function T() {
|
|
284
|
+
C != null && (C.destroy(), C = void 0);
|
|
55
285
|
}
|
|
56
|
-
function
|
|
57
|
-
|
|
286
|
+
function E(e, t = 9600) {
|
|
287
|
+
x = e, S = t;
|
|
58
288
|
}
|
|
59
|
-
function
|
|
60
|
-
|
|
289
|
+
function D() {
|
|
290
|
+
T(), x = "", S = 9600;
|
|
61
291
|
}
|
|
62
|
-
var
|
|
292
|
+
var O = [
|
|
63
293
|
{
|
|
64
294
|
name: "home",
|
|
65
295
|
description: "send all servos to their home positions — pass within_ms for smooth, fluid motion with automatic velocity ramp-up and ramp-down; without within_ms the robot moves at constant maximum speed",
|
|
@@ -269,104 +499,104 @@ var y = [
|
|
|
269
499
|
}
|
|
270
500
|
}
|
|
271
501
|
];
|
|
272
|
-
async function
|
|
502
|
+
async function k(e) {
|
|
273
503
|
let t = e.within_ms == null ? void 0 : Number(e.within_ms);
|
|
274
|
-
return await (await
|
|
504
|
+
return await (await w()).home(t), "all servos moved to home positions";
|
|
275
505
|
}
|
|
276
|
-
async function
|
|
506
|
+
async function A(e) {
|
|
277
507
|
let t = {};
|
|
278
508
|
if (e.shift_to != null && (t.s1 = Number(e.shift_to)), e.roll_to != null && (t.s2 = Number(e.roll_to)), e.pitch_to != null && (t.s3 = Number(e.pitch_to)), e.rotate_to != null && (t.s4 = Number(e.rotate_to)), e.lift_to != null && (t.s5 = Number(e.lift_to)), Object.keys(t).length === 0) throw Error("move: at least one of shift_to, roll_to, pitch_to, rotate_to, lift_to is required");
|
|
279
509
|
let n = e.within_ms == null ? void 0 : Number(e.within_ms);
|
|
280
|
-
return await (await
|
|
510
|
+
return await (await w()).moveTo(t, n), `servos updated: ${JSON.stringify(t)}`;
|
|
281
511
|
}
|
|
282
|
-
async function
|
|
512
|
+
async function j(e) {
|
|
283
513
|
let t = Number(e.angle), n = e.within_ms == null ? void 0 : Number(e.within_ms);
|
|
284
|
-
return await (await
|
|
514
|
+
return await (await w()).shiftHeadTo(t, n), `s1 (shift) → ${t}°`;
|
|
285
515
|
}
|
|
286
|
-
async function
|
|
516
|
+
async function M(e) {
|
|
287
517
|
let t = Number(e.angle), n = e.within_ms == null ? void 0 : Number(e.within_ms);
|
|
288
|
-
return await (await
|
|
518
|
+
return await (await w()).rollHeadTo(t, n), `s2 (roll) → ${t}°`;
|
|
289
519
|
}
|
|
290
|
-
async function
|
|
520
|
+
async function N(e) {
|
|
291
521
|
let t = Number(e.angle), n = e.within_ms == null ? void 0 : Number(e.within_ms);
|
|
292
|
-
return await (await
|
|
522
|
+
return await (await w()).pitchHeadTo(t, n), `s3 (pitch) → ${t}°`;
|
|
293
523
|
}
|
|
294
|
-
async function
|
|
524
|
+
async function P(e) {
|
|
295
525
|
let t = Number(e.angle), n = e.within_ms == null ? void 0 : Number(e.within_ms);
|
|
296
|
-
return await (await
|
|
526
|
+
return await (await w()).rotateBodyTo(t, n), `s4 (rotate) → ${t}°`;
|
|
297
527
|
}
|
|
298
|
-
async function
|
|
528
|
+
async function F(e) {
|
|
299
529
|
let t = Number(e.angle), n = e.within_ms == null ? void 0 : Number(e.within_ms);
|
|
300
|
-
return await (await
|
|
530
|
+
return await (await w()).liftHeadTo(t, n), `s5 (lift) → ${t}°`;
|
|
301
531
|
}
|
|
302
|
-
async function
|
|
303
|
-
return
|
|
532
|
+
async function I() {
|
|
533
|
+
return C == null ? "not connected" : (T(), "disconnected");
|
|
304
534
|
}
|
|
305
|
-
async function
|
|
535
|
+
async function L(e) {
|
|
306
536
|
let t = Number(e.within_ms);
|
|
307
537
|
if (isNaN(t) || t <= 0) throw Error("move_to: within_ms must be a positive number");
|
|
308
538
|
let n = {};
|
|
309
539
|
if (e.s1 != null && (n.s1 = Number(e.s1)), e.s2 != null && (n.s2 = Number(e.s2)), e.s3 != null && (n.s3 = Number(e.s3)), e.s4 != null && (n.s4 = Number(e.s4)), e.s5 != null && (n.s5 = Number(e.s5)), Object.keys(n).length === 0) throw Error("move_to: at least one servo target (s1–s5) must be specified");
|
|
310
|
-
return await (await
|
|
540
|
+
return await (await w()).moveTo(n, t), "move completed";
|
|
311
541
|
}
|
|
312
|
-
async function
|
|
542
|
+
async function R(e) {
|
|
313
543
|
let t = Number(e.ms);
|
|
314
544
|
if (isNaN(t) || t < 0) throw Error(`wait: invalid duration '${e.ms}' — expected a non-negative number`);
|
|
315
545
|
return await new Promise((e) => setTimeout(e, t)), `waited ${t} ms`;
|
|
316
546
|
}
|
|
317
|
-
async function
|
|
318
|
-
let e = await
|
|
547
|
+
async function z() {
|
|
548
|
+
let e = await w();
|
|
319
549
|
return JSON.stringify(e.State);
|
|
320
550
|
}
|
|
321
|
-
async function
|
|
551
|
+
async function B(e) {
|
|
322
552
|
let t = String(e.script ?? "");
|
|
323
|
-
return await
|
|
553
|
+
return await y(await w(), t), "script executed successfully";
|
|
324
554
|
}
|
|
325
|
-
function
|
|
555
|
+
function V() {
|
|
326
556
|
let e = new i({
|
|
327
557
|
name: "nova-control-mcp-server",
|
|
328
|
-
version: "0.0.
|
|
558
|
+
version: "0.0.7"
|
|
329
559
|
}, { capabilities: { tools: {} } });
|
|
330
|
-
return e.setRequestHandler(c, async () => ({ tools:
|
|
560
|
+
return e.setRequestHandler(c, async () => ({ tools: O })), e.setRequestHandler(s, async (e) => {
|
|
331
561
|
let t = e.params.name, n = e.params.arguments ?? {};
|
|
332
562
|
try {
|
|
333
563
|
let e;
|
|
334
564
|
switch (t) {
|
|
335
565
|
case "home":
|
|
336
|
-
e = await
|
|
566
|
+
e = await k(n);
|
|
337
567
|
break;
|
|
338
568
|
case "move":
|
|
339
|
-
e = await
|
|
569
|
+
e = await A(n);
|
|
340
570
|
break;
|
|
341
571
|
case "shift_to":
|
|
342
|
-
e = await
|
|
572
|
+
e = await j(n);
|
|
343
573
|
break;
|
|
344
574
|
case "roll_to":
|
|
345
|
-
e = await
|
|
575
|
+
e = await M(n);
|
|
346
576
|
break;
|
|
347
577
|
case "pitch_to":
|
|
348
|
-
e = await
|
|
578
|
+
e = await N(n);
|
|
349
579
|
break;
|
|
350
580
|
case "rotate_to":
|
|
351
|
-
e = await
|
|
581
|
+
e = await P(n);
|
|
352
582
|
break;
|
|
353
583
|
case "lift_to":
|
|
354
|
-
e = await
|
|
584
|
+
e = await F(n);
|
|
355
585
|
break;
|
|
356
586
|
case "move_to":
|
|
357
|
-
e = await
|
|
587
|
+
e = await L(n);
|
|
358
588
|
break;
|
|
359
589
|
case "wait":
|
|
360
|
-
e = await
|
|
590
|
+
e = await R(n);
|
|
361
591
|
break;
|
|
362
592
|
case "get_state":
|
|
363
|
-
e = await
|
|
593
|
+
e = await z();
|
|
364
594
|
break;
|
|
365
595
|
case "run_script":
|
|
366
|
-
e = await
|
|
596
|
+
e = await B(n);
|
|
367
597
|
break;
|
|
368
598
|
case "disconnect":
|
|
369
|
-
e = await
|
|
599
|
+
e = await I();
|
|
370
600
|
break;
|
|
371
601
|
default: return {
|
|
372
602
|
content: [{
|
|
@@ -391,14 +621,14 @@ function M() {
|
|
|
391
621
|
}
|
|
392
622
|
}), e;
|
|
393
623
|
}
|
|
394
|
-
async function
|
|
624
|
+
async function H(e) {
|
|
395
625
|
let t = new a();
|
|
396
626
|
await e.connect(t);
|
|
397
627
|
for (let e of ["SIGINT", "SIGTERM"]) process.on(e, () => {
|
|
398
|
-
|
|
628
|
+
T(), process.exit(0);
|
|
399
629
|
});
|
|
400
630
|
}
|
|
401
|
-
async function
|
|
631
|
+
async function U(e, t) {
|
|
402
632
|
let r = new o({ sessionIdGenerator: void 0 });
|
|
403
633
|
await e.connect(r);
|
|
404
634
|
let i = n(async (e, t) => {
|
|
@@ -410,17 +640,17 @@ async function P(e, t) {
|
|
|
410
640
|
}), i.once("error", n);
|
|
411
641
|
});
|
|
412
642
|
for (let e of ["SIGINT", "SIGTERM"]) process.on(e, async () => {
|
|
413
|
-
await r.close(), i.close(),
|
|
643
|
+
await r.close(), i.close(), T(), process.exit(0);
|
|
414
644
|
});
|
|
415
645
|
}
|
|
416
|
-
async function
|
|
417
|
-
let { Port: e, BaudRate: t, Transport: n, ListenPort: r } =
|
|
418
|
-
|
|
419
|
-
let i =
|
|
420
|
-
n === "http" ? await
|
|
646
|
+
async function W() {
|
|
647
|
+
let { Port: e, BaudRate: t, Transport: n, ListenPort: r } = b();
|
|
648
|
+
x = e, S = t;
|
|
649
|
+
let i = V();
|
|
650
|
+
n === "http" ? await U(i, r) : await H(i);
|
|
421
651
|
}
|
|
422
|
-
t(process.argv[1]) === e(import.meta.url) &&
|
|
652
|
+
t(process.argv[1]) === e(import.meta.url) && W().catch((e) => {
|
|
423
653
|
process.stderr.write(`nova-control-mcp: fatal: ${e.message ?? e}\n`), process.exit(1);
|
|
424
654
|
});
|
|
425
655
|
//#endregion
|
|
426
|
-
export {
|
|
656
|
+
export { D as _destroyForTests, E as _setupForTests, V as createServer };
|