nova-control-mcp-server 0.0.8 → 0.0.9
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 +1 -1
- package/dist/nova-control-mcp-server.js +146 -116
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -129,7 +129,7 @@ All movement tools accept an optional `within_ms` parameter. When provided, the
|
|
|
129
129
|
| `lift_to` | `angle: number`; `within_ms?` | lift head on secondary axis, range 20°–150° — s5 |
|
|
130
130
|
| `wait` | `ms: number` | pause for `ms` milliseconds before the next action |
|
|
131
131
|
| `get_state` | — | return current servo positions as a JSON object with keys `s1`–`s5` |
|
|
132
|
-
| `run_script` | `script: string` | execute a multi-line movement script (one command per line; blank lines and `#`-comments ignored; commands: `home`, `shift-to`, `roll-to`, `pitch-to`, `rotate-to`, `lift-to`, `move`, `wait
|
|
132
|
+
| `run_script` | `script: string` | execute a multi-line movement script (one command per line; blank lines and `#`-comments ignored; commands: `home [<within_ms>]`, `shift-to <angle> [<within_ms>]`, `roll-to`, `pitch-to`, `rotate-to`, `lift-to`, `move [...] [within-ms <ms>]`, `wait <ms>`) |
|
|
133
133
|
| `disconnect` | — | close the serial connection to free the port; the connection reopens automatically on the next movement command |
|
|
134
134
|
|
|
135
135
|
### Servo mapping
|
|
@@ -7,42 +7,43 @@ 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 { z as l } from "zod";
|
|
11
|
+
import { SerialPort as u } from "serialport";
|
|
11
12
|
//#region ../nova-control-node/dist/nova-control-node.js
|
|
12
|
-
var
|
|
13
|
+
var d = 9600, f = Object.freeze({
|
|
13
14
|
s1: 90,
|
|
14
15
|
s2: 90,
|
|
15
16
|
s3: 110,
|
|
16
17
|
s4: 90,
|
|
17
18
|
s5: 95
|
|
18
|
-
}),
|
|
19
|
+
}), p = Object.freeze({
|
|
19
20
|
s1: [45, 135],
|
|
20
21
|
s2: [10, 170],
|
|
21
22
|
s3: [40, 150],
|
|
22
23
|
s4: [30, 180],
|
|
23
24
|
s5: [20, 150]
|
|
24
|
-
}),
|
|
25
|
-
s1: (
|
|
26
|
-
s2: (
|
|
27
|
-
s3: (
|
|
28
|
-
s4: (
|
|
29
|
-
s5: (
|
|
25
|
+
}), m = Object.freeze({
|
|
26
|
+
s1: (p.s1[1] - p.s1[0]) / 1e3,
|
|
27
|
+
s2: (p.s2[1] - p.s2[0]) / 1e3,
|
|
28
|
+
s3: (p.s3[1] - p.s3[0]) / 1e3,
|
|
29
|
+
s4: (p.s4[1] - p.s4[0]) / 1e3,
|
|
30
|
+
s5: (p.s5[1] - p.s5[0]) / 1e3
|
|
30
31
|
});
|
|
31
|
-
function
|
|
32
|
-
let [n, r] =
|
|
32
|
+
function h(e, t) {
|
|
33
|
+
let [n, r] = p[t];
|
|
33
34
|
return Math.max(n, Math.min(r, Math.round(e)));
|
|
34
35
|
}
|
|
35
|
-
function
|
|
36
|
+
function g(e) {
|
|
36
37
|
return new Uint8Array([
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
38
|
+
h(e.s4, "s4"),
|
|
39
|
+
h(e.s3, "s3"),
|
|
40
|
+
h(e.s2, "s2"),
|
|
41
|
+
h(e.s1, "s1"),
|
|
42
|
+
h(e.s5, "s5")
|
|
42
43
|
]);
|
|
43
44
|
}
|
|
44
|
-
async function
|
|
45
|
-
let n = new
|
|
45
|
+
async function _(e, t) {
|
|
46
|
+
let n = new u({
|
|
46
47
|
path: e,
|
|
47
48
|
baudRate: t,
|
|
48
49
|
autoOpen: !1
|
|
@@ -68,22 +69,22 @@ async function g(e, t) {
|
|
|
68
69
|
}
|
|
69
70
|
};
|
|
70
71
|
}
|
|
71
|
-
function
|
|
72
|
+
function v(e, t) {
|
|
72
73
|
let n = Math.min(.499, Math.max(0, t)), r = 1 / (1 - n);
|
|
73
74
|
if (e <= n) return r * e * e / (2 * n);
|
|
74
75
|
if (e <= 1 - n) return r * (e - n / 2);
|
|
75
76
|
let i = 1 - e;
|
|
76
77
|
return 1 - r * i * i / (2 * n);
|
|
77
78
|
}
|
|
78
|
-
async function
|
|
79
|
-
let r = n?.StepIntervalMs ?? 20, i = n?.RampRatio ?? .25, a = await
|
|
79
|
+
async function y(e, t = d, n) {
|
|
80
|
+
let r = n?.StepIntervalMs ?? 20, i = n?.RampRatio ?? .25, a = await _(e, t), o = { ...f }, s, c = Promise.resolve();
|
|
80
81
|
function l(e) {
|
|
81
82
|
s = {
|
|
82
83
|
...s ?? o,
|
|
83
84
|
...e
|
|
84
85
|
};
|
|
85
86
|
}
|
|
86
|
-
async function
|
|
87
|
+
async function u() {
|
|
87
88
|
let e = c;
|
|
88
89
|
c = (async () => {
|
|
89
90
|
try {
|
|
@@ -98,14 +99,14 @@ async function v(e, t = u, n) {
|
|
|
98
99
|
"s4",
|
|
99
100
|
"s5"
|
|
100
101
|
]) {
|
|
101
|
-
let a = e[i] - o[i], s = r > 0 ?
|
|
102
|
+
let a = e[i] - o[i], s = r > 0 ? m[i] * r : Infinity;
|
|
102
103
|
Math.abs(a) > s ? (n[i] = o[i] + Math.sign(a) * s, t = !1) : n[i] = e[i];
|
|
103
104
|
}
|
|
104
|
-
t && (s = void 0), o = { ...n }, await a.write(
|
|
105
|
+
t && (s = void 0), o = { ...n }, await a.write(g(n)), t || await new Promise((e) => setTimeout(e, r));
|
|
105
106
|
}
|
|
106
107
|
})(), await c;
|
|
107
108
|
}
|
|
108
|
-
async function
|
|
109
|
+
async function p(e, t) {
|
|
109
110
|
let n = c;
|
|
110
111
|
c = (async () => {
|
|
111
112
|
try {
|
|
@@ -114,33 +115,33 @@ async function v(e, t = u, n) {
|
|
|
114
115
|
let c = { ...o }, l = r > 0 ? Math.max(1, Math.round(t / r)) : 1;
|
|
115
116
|
s = void 0;
|
|
116
117
|
for (let t = 1; t <= l; t++) {
|
|
117
|
-
let n =
|
|
118
|
+
let n = v(t / l, i), s = { ...o };
|
|
118
119
|
for (let t of Object.keys(e)) s[t] = Math.round(c[t] + (e[t] - c[t]) * n);
|
|
119
|
-
o = s, await a.write(
|
|
120
|
+
o = s, await a.write(g(s)), t < l && await new Promise((e) => setTimeout(e, r));
|
|
120
121
|
}
|
|
121
122
|
})(), await c;
|
|
122
123
|
}
|
|
123
124
|
return {
|
|
124
125
|
async home(e) {
|
|
125
|
-
e != null && e > 0 ? await
|
|
126
|
+
e != null && e > 0 ? await p({ ...f }, e) : (l({ ...f }), await u());
|
|
126
127
|
},
|
|
127
128
|
async shiftHeadTo(e, t) {
|
|
128
|
-
t != null && t > 0 ? await
|
|
129
|
+
t != null && t > 0 ? await p({ s1: e }, t) : (l({ s1: e }), await u());
|
|
129
130
|
},
|
|
130
131
|
async rollHeadTo(e, t) {
|
|
131
|
-
t != null && t > 0 ? await
|
|
132
|
+
t != null && t > 0 ? await p({ s2: e }, t) : (l({ s2: e }), await u());
|
|
132
133
|
},
|
|
133
134
|
async pitchHeadTo(e, t) {
|
|
134
|
-
t != null && t > 0 ? await
|
|
135
|
+
t != null && t > 0 ? await p({ s3: e }, t) : (l({ s3: e }), await u());
|
|
135
136
|
},
|
|
136
137
|
async liftHeadTo(e, t) {
|
|
137
|
-
t != null && t > 0 ? await
|
|
138
|
+
t != null && t > 0 ? await p({ s5: e }, t) : (l({ s5: e }), await u());
|
|
138
139
|
},
|
|
139
140
|
async rotateBodyTo(e, t) {
|
|
140
|
-
t != null && t > 0 ? await
|
|
141
|
+
t != null && t > 0 ? await p({ s4: e }, t) : (l({ s4: e }), await u());
|
|
141
142
|
},
|
|
142
143
|
async moveTo(e, t) {
|
|
143
|
-
t != null && t > 0 ? await
|
|
144
|
+
t != null && t > 0 ? await p(e, t) : (l(e), await u());
|
|
144
145
|
},
|
|
145
146
|
get State() {
|
|
146
147
|
return structuredClone(s ?? o);
|
|
@@ -152,14 +153,14 @@ async function v(e, t = u, n) {
|
|
|
152
153
|
};
|
|
153
154
|
},
|
|
154
155
|
async sendServoState() {
|
|
155
|
-
await
|
|
156
|
+
await u();
|
|
156
157
|
},
|
|
157
158
|
destroy() {
|
|
158
159
|
a.destroy();
|
|
159
160
|
}
|
|
160
161
|
};
|
|
161
162
|
}
|
|
162
|
-
async function
|
|
163
|
+
async function b(e, t) {
|
|
163
164
|
let n = t.split("\n");
|
|
164
165
|
for (let t = 0; t < n.length; t++) {
|
|
165
166
|
let r = n[t].trim(), i = t + 1;
|
|
@@ -257,7 +258,7 @@ async function y(e, t) {
|
|
|
257
258
|
}
|
|
258
259
|
//#endregion
|
|
259
260
|
//#region src/nova-control-mcp-server.ts
|
|
260
|
-
function
|
|
261
|
+
function x() {
|
|
261
262
|
try {
|
|
262
263
|
let { values: e } = r({
|
|
263
264
|
args: process.argv.slice(2),
|
|
@@ -294,20 +295,20 @@ function b() {
|
|
|
294
295
|
process.stderr.write(`nova-control-mcp: ${e.message ?? e}\n`), process.exit(1);
|
|
295
296
|
}
|
|
296
297
|
}
|
|
297
|
-
var
|
|
298
|
-
async function
|
|
299
|
-
return
|
|
298
|
+
var S = "", C = 9600, w;
|
|
299
|
+
async function T() {
|
|
300
|
+
return w ??= await y(S, C), w;
|
|
300
301
|
}
|
|
301
|
-
function
|
|
302
|
-
|
|
302
|
+
function E() {
|
|
303
|
+
w != null && (w.destroy(), w = void 0);
|
|
303
304
|
}
|
|
304
|
-
function
|
|
305
|
-
|
|
305
|
+
function D(e, t = 9600) {
|
|
306
|
+
S = e, C = t;
|
|
306
307
|
}
|
|
307
|
-
function
|
|
308
|
-
|
|
308
|
+
function O() {
|
|
309
|
+
E(), S = "", C = 9600;
|
|
309
310
|
}
|
|
310
|
-
var
|
|
311
|
+
var k = [
|
|
311
312
|
{
|
|
312
313
|
name: "home",
|
|
313
314
|
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",
|
|
@@ -498,7 +499,7 @@ var O = [
|
|
|
498
499
|
},
|
|
499
500
|
{
|
|
500
501
|
name: "run_script",
|
|
501
|
-
description: "execute a multi-line movement script — one command per line; blank lines and lines starting with # are ignored; commands: home | shift-to <angle> | roll-to <angle> | pitch-to <angle> | rotate-to <angle> | lift-to <angle> | move [shift-to <angle>] [roll-to <angle>] [pitch-to <angle>] [rotate-to <angle>] [lift-to <angle>] | wait <ms>",
|
|
502
|
+
description: "execute a multi-line movement script — one command per line; blank lines and lines starting with # are ignored; each command is fully awaited before the next begins; commands: home [<within_ms>] | shift-to <angle> [<within_ms>] | roll-to <angle> [<within_ms>] | pitch-to <angle> [<within_ms>] | rotate-to <angle> [<within_ms>] | lift-to <angle> [<within_ms>] | move [shift-to <angle>] [roll-to <angle>] [pitch-to <angle>] [rotate-to <angle>] [lift-to <angle>] [within-ms <ms>] | wait <ms>",
|
|
502
503
|
inputSchema: {
|
|
503
504
|
type: "object",
|
|
504
505
|
properties: { script: {
|
|
@@ -516,105 +517,134 @@ var O = [
|
|
|
516
517
|
properties: {}
|
|
517
518
|
}
|
|
518
519
|
}
|
|
519
|
-
]
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
520
|
+
], A = l.number().finite(), j = l.number().positive(), M = l.object({ within_ms: j.optional() }), N = l.object({
|
|
521
|
+
angle: A,
|
|
522
|
+
within_ms: j.optional()
|
|
523
|
+
}), P = l.object({
|
|
524
|
+
shift_to: A.optional(),
|
|
525
|
+
roll_to: A.optional(),
|
|
526
|
+
pitch_to: A.optional(),
|
|
527
|
+
rotate_to: A.optional(),
|
|
528
|
+
lift_to: A.optional(),
|
|
529
|
+
within_ms: j.optional()
|
|
530
|
+
}).superRefine((e, t) => {
|
|
531
|
+
e.shift_to == null && e.roll_to == null && e.pitch_to == null && e.rotate_to == null && e.lift_to == null && t.addIssue({
|
|
532
|
+
code: l.ZodIssueCode.custom,
|
|
533
|
+
message: "move: at least one of shift_to, roll_to, pitch_to, rotate_to, lift_to is required"
|
|
534
|
+
});
|
|
535
|
+
}), F = l.object({
|
|
536
|
+
within_ms: j,
|
|
537
|
+
s1: A.optional(),
|
|
538
|
+
s2: A.optional(),
|
|
539
|
+
s3: A.optional(),
|
|
540
|
+
s4: A.optional(),
|
|
541
|
+
s5: A.optional()
|
|
542
|
+
}).superRefine((e, t) => {
|
|
543
|
+
e.s1 == null && e.s2 == null && e.s3 == null && e.s4 == null && e.s5 == null && t.addIssue({
|
|
544
|
+
code: l.ZodIssueCode.custom,
|
|
545
|
+
message: "move_to: at least one servo target (s1–s5) must be specified"
|
|
546
|
+
});
|
|
547
|
+
}), I = l.object({ ms: l.number().finite().nonnegative() }), L = l.object({ script: l.string() });
|
|
548
|
+
function R(e) {
|
|
549
|
+
return e.issues.map((e) => `${e.path.length > 0 ? `${e.path.join(".")}: ` : ""}${e.message}`).join("; ");
|
|
523
550
|
}
|
|
524
|
-
async function
|
|
525
|
-
let t =
|
|
526
|
-
|
|
527
|
-
let n = e.within_ms == null ? void 0 : Number(e.within_ms);
|
|
528
|
-
return await (await w()).moveTo(t, n), `servos updated: ${JSON.stringify(t)}`;
|
|
551
|
+
async function z(e) {
|
|
552
|
+
let { within_ms: t } = M.parse(e);
|
|
553
|
+
return await (await T()).home(t), "all servos moved to home positions";
|
|
529
554
|
}
|
|
530
|
-
async function
|
|
531
|
-
let t =
|
|
532
|
-
return
|
|
555
|
+
async function B(e) {
|
|
556
|
+
let t = P.parse(e), n = {};
|
|
557
|
+
return t.shift_to != null && (n.s1 = t.shift_to), t.roll_to != null && (n.s2 = t.roll_to), t.pitch_to != null && (n.s3 = t.pitch_to), t.rotate_to != null && (n.s4 = t.rotate_to), t.lift_to != null && (n.s5 = t.lift_to), await (await T()).moveTo(n, t.within_ms), `servos updated: ${JSON.stringify(n)}`;
|
|
533
558
|
}
|
|
534
|
-
async function
|
|
535
|
-
let
|
|
536
|
-
return await (await
|
|
559
|
+
async function V(e) {
|
|
560
|
+
let { angle: t, within_ms: n } = N.parse(e);
|
|
561
|
+
return await (await T()).shiftHeadTo(t, n), `s1 (shift) → ${t}°`;
|
|
537
562
|
}
|
|
538
|
-
async function
|
|
539
|
-
let
|
|
540
|
-
return await (await
|
|
563
|
+
async function H(e) {
|
|
564
|
+
let { angle: t, within_ms: n } = N.parse(e);
|
|
565
|
+
return await (await T()).rollHeadTo(t, n), `s2 (roll) → ${t}°`;
|
|
541
566
|
}
|
|
542
|
-
async function
|
|
543
|
-
let
|
|
544
|
-
return await (await
|
|
567
|
+
async function U(e) {
|
|
568
|
+
let { angle: t, within_ms: n } = N.parse(e);
|
|
569
|
+
return await (await T()).pitchHeadTo(t, n), `s3 (pitch) → ${t}°`;
|
|
545
570
|
}
|
|
546
|
-
async function
|
|
547
|
-
let
|
|
548
|
-
return await (await
|
|
571
|
+
async function W(e) {
|
|
572
|
+
let { angle: t, within_ms: n } = N.parse(e);
|
|
573
|
+
return await (await T()).rotateBodyTo(t, n), `s4 (rotate) → ${t}°`;
|
|
549
574
|
}
|
|
550
|
-
async function
|
|
551
|
-
|
|
575
|
+
async function G(e) {
|
|
576
|
+
let { angle: t, within_ms: n } = N.parse(e);
|
|
577
|
+
return await (await T()).liftHeadTo(t, n), `s5 (lift) → ${t}°`;
|
|
552
578
|
}
|
|
553
|
-
async function
|
|
554
|
-
|
|
555
|
-
if (isNaN(t) || t <= 0) throw Error("move_to: within_ms must be a positive number");
|
|
556
|
-
let n = {};
|
|
557
|
-
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");
|
|
558
|
-
return await (await w()).moveTo(n, t), "move completed";
|
|
579
|
+
async function K() {
|
|
580
|
+
return w == null ? "not connected" : (E(), "disconnected");
|
|
559
581
|
}
|
|
560
|
-
async function
|
|
561
|
-
let t =
|
|
562
|
-
|
|
563
|
-
return await new Promise((e) => setTimeout(e, t)), `waited ${t} ms`;
|
|
582
|
+
async function q(e) {
|
|
583
|
+
let t = F.parse(e), n = {};
|
|
584
|
+
return t.s1 != null && (n.s1 = t.s1), t.s2 != null && (n.s2 = t.s2), t.s3 != null && (n.s3 = t.s3), t.s4 != null && (n.s4 = t.s4), t.s5 != null && (n.s5 = t.s5), await (await T()).moveTo(n, t.within_ms), "move completed";
|
|
564
585
|
}
|
|
565
|
-
async function
|
|
566
|
-
let
|
|
586
|
+
async function J(e) {
|
|
587
|
+
let t;
|
|
588
|
+
try {
|
|
589
|
+
t = I.parse(e);
|
|
590
|
+
} catch {
|
|
591
|
+
throw Error(`wait: invalid duration '${e.ms}' — expected a non-negative number`);
|
|
592
|
+
}
|
|
593
|
+
return await new Promise((e) => setTimeout(e, t.ms)), `waited ${t.ms} ms`;
|
|
594
|
+
}
|
|
595
|
+
async function Y() {
|
|
596
|
+
let e = await T();
|
|
567
597
|
return JSON.stringify(e.State);
|
|
568
598
|
}
|
|
569
|
-
async function
|
|
570
|
-
let t =
|
|
571
|
-
return await
|
|
599
|
+
async function X(e) {
|
|
600
|
+
let { script: t } = L.parse(e);
|
|
601
|
+
return await b(await T(), t), "script executed successfully";
|
|
572
602
|
}
|
|
573
|
-
function
|
|
603
|
+
function Z() {
|
|
574
604
|
let e = new i({
|
|
575
605
|
name: "nova-control-mcp-server",
|
|
576
606
|
version: "0.0.8"
|
|
577
607
|
}, { capabilities: { tools: {} } });
|
|
578
|
-
return e.setRequestHandler(c, async () => ({ tools:
|
|
608
|
+
return e.setRequestHandler(c, async () => ({ tools: k })), e.setRequestHandler(s, async (e) => {
|
|
579
609
|
let t = e.params.name, n = e.params.arguments ?? {};
|
|
580
610
|
try {
|
|
581
611
|
let e;
|
|
582
612
|
switch (t) {
|
|
583
613
|
case "home":
|
|
584
|
-
e = await
|
|
614
|
+
e = await z(n);
|
|
585
615
|
break;
|
|
586
616
|
case "move":
|
|
587
|
-
e = await
|
|
617
|
+
e = await B(n);
|
|
588
618
|
break;
|
|
589
619
|
case "shift_to":
|
|
590
|
-
e = await
|
|
620
|
+
e = await V(n);
|
|
591
621
|
break;
|
|
592
622
|
case "roll_to":
|
|
593
|
-
e = await
|
|
623
|
+
e = await H(n);
|
|
594
624
|
break;
|
|
595
625
|
case "pitch_to":
|
|
596
|
-
e = await
|
|
626
|
+
e = await U(n);
|
|
597
627
|
break;
|
|
598
628
|
case "rotate_to":
|
|
599
|
-
e = await
|
|
629
|
+
e = await W(n);
|
|
600
630
|
break;
|
|
601
631
|
case "lift_to":
|
|
602
|
-
e = await
|
|
632
|
+
e = await G(n);
|
|
603
633
|
break;
|
|
604
634
|
case "move_to":
|
|
605
|
-
e = await
|
|
635
|
+
e = await q(n);
|
|
606
636
|
break;
|
|
607
637
|
case "wait":
|
|
608
|
-
e = await
|
|
638
|
+
e = await J(n);
|
|
609
639
|
break;
|
|
610
640
|
case "get_state":
|
|
611
|
-
e = await
|
|
641
|
+
e = await Y();
|
|
612
642
|
break;
|
|
613
643
|
case "run_script":
|
|
614
|
-
e = await
|
|
644
|
+
e = await X(n);
|
|
615
645
|
break;
|
|
616
646
|
case "disconnect":
|
|
617
|
-
e = await
|
|
647
|
+
e = await K();
|
|
618
648
|
break;
|
|
619
649
|
default: return {
|
|
620
650
|
content: [{
|
|
@@ -632,21 +662,21 @@ function V() {
|
|
|
632
662
|
return {
|
|
633
663
|
content: [{
|
|
634
664
|
type: "text",
|
|
635
|
-
text: e instanceof Error ? e.message : String(e)
|
|
665
|
+
text: e instanceof l.ZodError ? R(e) : e instanceof Error ? e.message : String(e)
|
|
636
666
|
}],
|
|
637
667
|
isError: !0
|
|
638
668
|
};
|
|
639
669
|
}
|
|
640
670
|
}), e;
|
|
641
671
|
}
|
|
642
|
-
async function
|
|
672
|
+
async function Q(e) {
|
|
643
673
|
let t = new a();
|
|
644
674
|
await e.connect(t);
|
|
645
675
|
for (let e of ["SIGINT", "SIGTERM"]) process.on(e, () => {
|
|
646
|
-
|
|
676
|
+
E(), process.exit(0);
|
|
647
677
|
});
|
|
648
678
|
}
|
|
649
|
-
async function
|
|
679
|
+
async function $(e, t) {
|
|
650
680
|
let r = new o({ sessionIdGenerator: void 0 });
|
|
651
681
|
await e.connect(r);
|
|
652
682
|
let i = n(async (e, t) => {
|
|
@@ -658,17 +688,17 @@ async function U(e, t) {
|
|
|
658
688
|
}), i.once("error", n);
|
|
659
689
|
});
|
|
660
690
|
for (let e of ["SIGINT", "SIGTERM"]) process.on(e, async () => {
|
|
661
|
-
await r.close(), i.close(),
|
|
691
|
+
await r.close(), i.close(), E(), process.exit(0);
|
|
662
692
|
});
|
|
663
693
|
}
|
|
664
|
-
async function
|
|
665
|
-
let { Port: e, BaudRate: t, Transport: n, ListenPort: r } =
|
|
666
|
-
|
|
667
|
-
let i =
|
|
668
|
-
n === "http" ? await
|
|
694
|
+
async function ee() {
|
|
695
|
+
let { Port: e, BaudRate: t, Transport: n, ListenPort: r } = x();
|
|
696
|
+
S = e, C = t;
|
|
697
|
+
let i = Z();
|
|
698
|
+
n === "http" ? await $(i, r) : await Q(i);
|
|
669
699
|
}
|
|
670
|
-
t(process.argv[1]) === e(import.meta.url) &&
|
|
700
|
+
t(process.argv[1]) === e(import.meta.url) && ee().catch((e) => {
|
|
671
701
|
process.stderr.write(`nova-control-mcp: fatal: ${e.message ?? e}\n`), process.exit(1);
|
|
672
702
|
});
|
|
673
703
|
//#endregion
|
|
674
|
-
export {
|
|
704
|
+
export { O as _destroyForTests, D as _setupForTests, Z as createServer };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nova-control-mcp-server",
|
|
3
3
|
"description": "MCP server for controlling a NOVA DIY Artificial Intelligence Robot by Creoqode",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.9",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"nova",
|
|
@@ -30,7 +30,8 @@
|
|
|
30
30
|
],
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
33
|
-
"nova-control-node": "*"
|
|
33
|
+
"nova-control-node": "*",
|
|
34
|
+
"zod": "^4.3.6"
|
|
34
35
|
},
|
|
35
36
|
"devDependencies": {
|
|
36
37
|
"@types/node": "^22.0.0",
|