obsbot-mcp 0.3.1 → 0.4.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 +195 -38
- package/dist/codec/commands.d.ts +42 -4
- package/dist/codec/commands.js +72 -10
- package/dist/codec/commands.js.map +1 -1
- package/dist/codec/frame.d.ts +1 -0
- package/dist/codec/frame.js +1 -1
- package/dist/codec/frame.js.map +1 -1
- package/dist/codec/preset.d.ts +40 -0
- package/dist/codec/preset.js +198 -0
- package/dist/codec/preset.js.map +1 -0
- package/dist/codec/types.d.ts +4 -0
- package/dist/device/helper-factory.d.ts +25 -0
- package/dist/device/helper-factory.js +40 -0
- package/dist/device/helper-factory.js.map +1 -0
- package/dist/device/manager.d.ts +326 -2
- package/dist/device/manager.js +720 -24
- package/dist/device/manager.js.map +1 -1
- package/dist/ipc/client.d.ts +19 -0
- package/dist/ipc/client.js +81 -0
- package/dist/ipc/client.js.map +1 -0
- package/dist/ipc/coordinator.d.ts +29 -0
- package/dist/ipc/coordinator.js +94 -0
- package/dist/ipc/coordinator.js.map +1 -0
- package/dist/ipc/owner.d.ts +21 -0
- package/dist/ipc/owner.js +59 -0
- package/dist/ipc/owner.js.map +1 -0
- package/dist/ipc/protocol.d.ts +21 -0
- package/dist/ipc/protocol.js +56 -0
- package/dist/ipc/protocol.js.map +1 -0
- package/dist/ipc/rendezvous.d.ts +26 -0
- package/dist/ipc/rendezvous.js +93 -0
- package/dist/ipc/rendezvous.js.map +1 -0
- package/dist/mcp/log-sink.d.ts +12 -0
- package/dist/mcp/log-sink.js +27 -0
- package/dist/mcp/log-sink.js.map +1 -0
- package/dist/mcp/ready.d.ts +16 -4
- package/dist/mcp/ready.js +11 -8
- package/dist/mcp/ready.js.map +1 -1
- package/dist/mcp/render.js +1 -1
- package/dist/mcp/render.js.map +1 -1
- package/dist/mcp/server.js +68 -18
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/tools.d.ts +5 -3
- package/dist/mcp/tools.js +787 -186
- package/dist/mcp/tools.js.map +1 -1
- package/dist/transport/helper-process.d.ts +36 -0
- package/dist/transport/helper-process.js +190 -10
- package/dist/transport/helper-process.js.map +1 -1
- package/dist/transport/linux.d.ts +40 -0
- package/dist/transport/linux.js +92 -2
- package/dist/transport/linux.js.map +1 -1
- package/dist/transport/macos.d.ts +13 -0
- package/dist/transport/macos.js +59 -3
- package/dist/transport/macos.js.map +1 -1
- package/dist/transport/read-serial.d.ts +26 -0
- package/dist/transport/read-serial.js +87 -0
- package/dist/transport/read-serial.js.map +1 -0
- package/dist/transport/transport.d.ts +24 -0
- package/dist/transport/windows.d.ts +4 -0
- package/dist/transport/windows.js +31 -4
- package/dist/transport/windows.js.map +1 -1
- package/native/prebuilt/darwin-arm64/obsbot-helper +0 -0
- package/native/prebuilt/darwin-x64/obsbot-helper +0 -0
- package/native/prebuilt/linux-x64/obsbot-helper +0 -0
- package/native/prebuilt/win32-x64/obsbot-helper.exe +0 -0
- package/package.json +3 -2
- package/dist/device/session.d.ts +0 -22
- package/dist/device/session.js +0 -37
- package/dist/device/session.js.map +0 -1
package/dist/mcp/ready.d.ts
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
import { ObsbotTransport } from "../transport/transport.js";
|
|
2
|
-
|
|
2
|
+
/**
|
|
3
|
+
* The minimal slice of connection-lifecycle control the readiness gate needs to
|
|
4
|
+
* self-heal a mid-session disconnect: drop the dead transport so a re-resolve
|
|
5
|
+
* rebinds, and report (once, clearing on read) whether that re-resolve was a
|
|
6
|
+
* reconnect. Satisfied by DeviceManager (via a thin adapter in server.ts); the
|
|
7
|
+
* two methods are exactly what the retired DeviceSession exposed, so ensureReady
|
|
8
|
+
* changes only the type it depends on, not its body.
|
|
9
|
+
*/
|
|
10
|
+
export interface ReconnectCtl {
|
|
11
|
+
invalidate(): Promise<void>;
|
|
12
|
+
takeReconnected(): boolean;
|
|
13
|
+
}
|
|
3
14
|
export type ReadyResult = {
|
|
4
15
|
ok: true;
|
|
5
16
|
transport: ObsbotTransport;
|
|
@@ -14,6 +25,7 @@ export interface ReadyOpts {
|
|
|
14
25
|
wakeTimeoutMs?: number;
|
|
15
26
|
settleMs?: number;
|
|
16
27
|
}
|
|
28
|
+
export declare const msg: (e: unknown) => string;
|
|
17
29
|
/**
|
|
18
30
|
* Gate a gimbal/AI command on device readiness. A single status read is a 3-way
|
|
19
31
|
* probe: it throws when the device is unreachable, and otherwise reports awake.
|
|
@@ -25,7 +37,7 @@ export interface ReadyOpts {
|
|
|
25
37
|
* - awake → { ok:true, transport, reconnected }.
|
|
26
38
|
*
|
|
27
39
|
* The command is only sent by the caller after ok:true — a gate failure never
|
|
28
|
-
* touches the gimbal. Without a
|
|
29
|
-
* still applies.
|
|
40
|
+
* touches the gimbal. Without a reconnect controller, self-heal is skipped but
|
|
41
|
+
* awake-gating still applies.
|
|
30
42
|
*/
|
|
31
|
-
export declare function ensureReady(getTransport: () => Promise<ObsbotTransport>,
|
|
43
|
+
export declare function ensureReady(getTransport: () => Promise<ObsbotTransport>, reconnect?: ReconnectCtl, opts?: ReadyOpts): Promise<ReadyResult>;
|
package/dist/mcp/ready.js
CHANGED
|
@@ -2,7 +2,10 @@ import { decodeStatus } from "../codec/commands.js";
|
|
|
2
2
|
import { encodeSetRunStatus } from "../codec/commands.js";
|
|
3
3
|
const DEFAULTS = { pollMs: 200, wakeTimeoutMs: 2500, settleMs: 300 };
|
|
4
4
|
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
5
|
-
|
|
5
|
+
// Exported for reuse by any caller catch block that needs a safe error string —
|
|
6
|
+
// `(e as Error).message` yields "undefined" on a non-Error throw (e.g. a string
|
|
7
|
+
// or plain object thrown by a mock/dependency).
|
|
8
|
+
export const msg = (e) => (e instanceof Error ? e.message : String(e));
|
|
6
9
|
const readAwake = async (t) => decodeStatus(await t.recvStatus()).awake;
|
|
7
10
|
/**
|
|
8
11
|
* Gate a gimbal/AI command on device readiness. A single status read is a 3-way
|
|
@@ -15,10 +18,10 @@ const readAwake = async (t) => decodeStatus(await t.recvStatus()).awake;
|
|
|
15
18
|
* - awake → { ok:true, transport, reconnected }.
|
|
16
19
|
*
|
|
17
20
|
* The command is only sent by the caller after ok:true — a gate failure never
|
|
18
|
-
* touches the gimbal. Without a
|
|
19
|
-
* still applies.
|
|
21
|
+
* touches the gimbal. Without a reconnect controller, self-heal is skipped but
|
|
22
|
+
* awake-gating still applies.
|
|
20
23
|
*/
|
|
21
|
-
export async function ensureReady(getTransport,
|
|
24
|
+
export async function ensureReady(getTransport, reconnect, opts = {}) {
|
|
22
25
|
const { pollMs, wakeTimeoutMs, settleMs } = { ...DEFAULTS, ...opts };
|
|
23
26
|
let t;
|
|
24
27
|
try {
|
|
@@ -32,11 +35,11 @@ export async function ensureReady(getTransport, session, opts = {}) {
|
|
|
32
35
|
awake = await readAwake(t);
|
|
33
36
|
}
|
|
34
37
|
catch (e) {
|
|
35
|
-
// Probe failed — device likely unplugged. Self-heal once if we
|
|
36
|
-
if (!
|
|
38
|
+
// Probe failed — device likely unplugged. Self-heal once if we can.
|
|
39
|
+
if (!reconnect) {
|
|
37
40
|
return { ok: false, reason: "unreachable", error: `camera not reachable: ${msg(e)}` };
|
|
38
41
|
}
|
|
39
|
-
|
|
42
|
+
await reconnect.invalidate();
|
|
40
43
|
try {
|
|
41
44
|
t = await getTransport();
|
|
42
45
|
awake = await readAwake(t);
|
|
@@ -66,6 +69,6 @@ export async function ensureReady(getTransport, session, opts = {}) {
|
|
|
66
69
|
}
|
|
67
70
|
await sleep(settleMs); // let the gimbal finish rising before we drive it
|
|
68
71
|
}
|
|
69
|
-
return { ok: true, transport: t, reconnected:
|
|
72
|
+
return { ok: true, transport: t, reconnected: reconnect?.takeReconnected() ?? false };
|
|
70
73
|
}
|
|
71
74
|
//# sourceMappingURL=ready.js.map
|
package/dist/mcp/ready.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ready.js","sourceRoot":"","sources":["../../src/mcp/ready.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"ready.js","sourceRoot":"","sources":["../../src/mcp/ready.ts"],"names":[],"mappings":"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"}
|
package/dist/mcp/render.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Render a tool handler's return value into an MCP CallTool result. A handler
|
|
2
2
|
// may either return a plain object (serialized to a single text block, the
|
|
3
3
|
// default for every control tool) or an object that already carries an MCP
|
|
4
|
-
// `content` array (e.g.
|
|
4
|
+
// `content` array (e.g. obsbot_capture_snapshot returning an image block), which is
|
|
5
5
|
// passed through untouched.
|
|
6
6
|
export function renderToolResult(result) {
|
|
7
7
|
if (result !== null &&
|
package/dist/mcp/render.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/mcp/render.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,2EAA2E;AAC3E,2EAA2E;AAC3E,
|
|
1
|
+
{"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/mcp/render.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,2EAA2E;AAC3E,2EAA2E;AAC3E,oFAAoF;AACpF,4BAA4B;AAC5B,MAAM,UAAU,gBAAgB,CAAC,MAAe;IAC9C,IACE,MAAM,KAAK,IAAI;QACf,OAAO,MAAM,KAAK,QAAQ;QAC1B,KAAK,CAAC,OAAO,CAAE,MAAgC,CAAC,OAAO,CAAC,EACxD,CAAC;QACD,OAAO,MAAgC,CAAC;IAC1C,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC;AACvE,CAAC"}
|
package/dist/mcp/server.js
CHANGED
|
@@ -3,28 +3,75 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
|
|
|
3
3
|
import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
4
4
|
import { zodToJsonSchema } from "zod-to-json-schema";
|
|
5
5
|
import { DeviceManager } from "../device/manager.js";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
6
|
+
import { helperFactory } from "../device/helper-factory.js";
|
|
7
|
+
import { makeLogSink } from "./log-sink.js";
|
|
8
8
|
import { createTools } from "./tools.js";
|
|
9
9
|
import { renderToolResult } from "./render.js";
|
|
10
10
|
import { CaptureManager } from "../capture/manager.js";
|
|
11
|
+
import { Coordinator, serialize } from "../ipc/coordinator.js";
|
|
11
12
|
export async function startServer(opts = {}) {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
//
|
|
16
|
-
//
|
|
17
|
-
|
|
18
|
-
|
|
13
|
+
// helperFactory subscribes every helper it spawns to the OS bus events, so
|
|
14
|
+
// the manager hears about a camera arriving or leaving instead of finding
|
|
15
|
+
// out by failing a call. See src/device/helper-factory.ts.
|
|
16
|
+
//
|
|
17
|
+
// OBSBOT_LOG_FILE additionally mirrors the manager's diagnostics to a file:
|
|
18
|
+
// our stderr goes to a pipe the launcher owns, so a rare event like a
|
|
19
|
+
// retried arrival re-bind would otherwise be unobservable after the fact.
|
|
20
|
+
const log = makeLogSink(process.env.OBSBOT_LOG_FILE, (m) => console.error(m));
|
|
21
|
+
const mgr = new DeviceManager(helperFactory(() => mgr), { log });
|
|
22
|
+
// DeviceManager now owns the connection lifecycle: lazy bind, invalidate +
|
|
23
|
+
// re-bind on a mid-session disconnect (self-heal), and per-camera reconnect
|
|
24
|
+
// tracking. createTools derives per-camera resolution (getTransport / reconnect
|
|
25
|
+
// / readiness gate) from the manager itself, keyed by each tool's optional
|
|
26
|
+
// `camera` selector — so nothing per-camera is wired up out here anymore.
|
|
19
27
|
const capture = new CaptureManager();
|
|
20
|
-
// --debug exposes the RE/diagnostics surface (
|
|
21
|
-
const tools = createTools(
|
|
22
|
-
//
|
|
23
|
-
|
|
28
|
+
// --debug exposes the RE/diagnostics surface (obsbot_debug_probe tool + status raw block).
|
|
29
|
+
const tools = createTools(mgr, capture, opts.debug ?? false);
|
|
30
|
+
// Single-owner camera coordination across concurrent MCP clients (see
|
|
31
|
+
// IPC-DESIGN.md). Every instance elects: the owner runs tool calls locally
|
|
32
|
+
// against the one DeviceManager; clients forward theirs to the owner and
|
|
33
|
+
// re-elect if it dies. runLocal is the tool dispatch, serialize()-wrapped so
|
|
34
|
+
// it is the single-camera lock — covering both this instance's own calls and
|
|
35
|
+
// any forwarded from clients (the local path bypasses OwnerServer's queue). A
|
|
36
|
+
// lone instance is simply the owner with no peers: it behaves exactly as
|
|
37
|
+
// before, plus an idle listener.
|
|
38
|
+
const runLocal = serialize(async (name, args) => {
|
|
39
|
+
const tool = tools.find((t) => t.name === name);
|
|
40
|
+
if (!tool)
|
|
41
|
+
throw new Error(`unknown tool: ${name}`);
|
|
42
|
+
return tool.handler(args);
|
|
43
|
+
});
|
|
44
|
+
const coordinator = new Coordinator(runLocal);
|
|
45
|
+
await coordinator.start();
|
|
46
|
+
// Report the coordination role on STDERR (never stdout — that's the JSON-RPC
|
|
47
|
+
// channel). Useful for ops ("am I the owner or a client?") and observed by the
|
|
48
|
+
// ipc-hw-smoke harness to confirm a client really forwards to the owner.
|
|
49
|
+
console.error(`obsbot-mcp: ipc role=${coordinator.roleName}`);
|
|
50
|
+
// Kill any recording/preview child processes when the server exits, so nothing
|
|
51
|
+
// orphans, and drop the IPC endpoint / owner connection.
|
|
52
|
+
const shutdown = () => {
|
|
53
|
+
capture.stopAll();
|
|
54
|
+
void coordinator.close();
|
|
55
|
+
// The manager holds a watcher process that is deliberately never closed by
|
|
56
|
+
// any operation, so nothing else would ever stop it.
|
|
57
|
+
//
|
|
58
|
+
// Belt-and-braces, and measured to be so: with this line commented out, a
|
|
59
|
+
// real server bound to hardware and sent SIGTERM still left zero orphaned
|
|
60
|
+
// helpers, because they exit on stdin EOF when we die (helper.m:1180). The
|
|
61
|
+
// SIGINT/SIGTERM handlers also process.exit(0) immediately after this, and
|
|
62
|
+
// it is fire-and-forget, so the close() very likely does not finish.
|
|
63
|
+
//
|
|
64
|
+
// Kept anyway: it costs nothing, it is the correct thing to call, and it
|
|
65
|
+
// covers an orderly stop that does NOT tear down our stdio. Do not mistake
|
|
66
|
+
// it for what reaps the helpers — that is the pipe.
|
|
67
|
+
void mgr.shutdown();
|
|
68
|
+
};
|
|
24
69
|
process.on("exit", shutdown);
|
|
25
70
|
process.on("SIGINT", () => { shutdown(); process.exit(0); });
|
|
26
71
|
process.on("SIGTERM", () => { shutdown(); process.exit(0); });
|
|
27
|
-
const server = new Server(
|
|
72
|
+
const server = new Server(
|
|
73
|
+
// Must match package.json's version; test/version-sync.test.ts enforces it.
|
|
74
|
+
{ name: "obsbot-mcp", version: "0.4.1" }, { capabilities: { tools: {} } });
|
|
28
75
|
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
29
76
|
tools: tools.map((tool) => ({
|
|
30
77
|
name: tool.name,
|
|
@@ -36,11 +83,14 @@ export async function startServer(opts = {}) {
|
|
|
36
83
|
})),
|
|
37
84
|
}));
|
|
38
85
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
39
|
-
const
|
|
40
|
-
if (!
|
|
41
|
-
throw new Error(`unknown tool: ${
|
|
86
|
+
const name = request.params.name;
|
|
87
|
+
if (!tools.find((t) => t.name === name)) {
|
|
88
|
+
throw new Error(`unknown tool: ${name}`);
|
|
42
89
|
}
|
|
43
|
-
|
|
90
|
+
// Route through the coordinator: run locally if we own the camera, else
|
|
91
|
+
// forward to whoever does. renderToolResult runs here at the MCP boundary,
|
|
92
|
+
// on the raw tool result either way.
|
|
93
|
+
const result = await coordinator.dispatch(name, request.params.arguments ?? {});
|
|
44
94
|
return renderToolResult(result);
|
|
45
95
|
});
|
|
46
96
|
const stdioTransport = new StdioServerTransport();
|
package/dist/mcp/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EACL,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"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"}
|
package/dist/mcp/tools.d.ts
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { ObsbotTransport } from "../transport/transport.js";
|
|
3
2
|
import { DeviceManager } from "../device/manager.js";
|
|
4
|
-
import { DeviceSession } from "../device/session.js";
|
|
5
3
|
import type { CaptureManager } from "../capture/manager.js";
|
|
6
4
|
export interface ToolDef {
|
|
7
5
|
name: string;
|
|
@@ -9,4 +7,8 @@ export interface ToolDef {
|
|
|
9
7
|
schema: z.ZodTypeAny;
|
|
10
8
|
handler: (args: unknown) => Promise<object>;
|
|
11
9
|
}
|
|
12
|
-
export
|
|
10
|
+
export interface PresetReadOpts {
|
|
11
|
+
attempts?: number;
|
|
12
|
+
backoffMs?: number[];
|
|
13
|
+
}
|
|
14
|
+
export declare function createTools(mgr: DeviceManager, capture?: CaptureManager, debug?: boolean, presetRead?: PresetReadOpts): ToolDef[];
|