@burmese/mcp 3.1.0

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 OpenPets
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/dist/args.d.ts ADDED
@@ -0,0 +1,10 @@
1
+ export interface McpCliOptions {
2
+ readonly petId?: string;
3
+ readonly help: boolean;
4
+ readonly version: boolean;
5
+ }
6
+ export declare function parseMcpArgs(argv: readonly string[]): McpCliOptions;
7
+ export declare function validatePetId(value: string): string;
8
+ export declare function validateRawPetArg(value: string): string;
9
+ export declare function createHelpText(): string;
10
+ //# sourceMappingURL=args.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"args.d.ts","sourceRoot":"","sources":["../src/args.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC3B;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,aAAa,CA8BnE;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAKnD;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAOvD;AAED,wBAAgB,cAAc,IAAI,MAAM,CAEvC"}
package/dist/args.js ADDED
@@ -0,0 +1,49 @@
1
+ export function parseMcpArgs(argv) {
2
+ let petId;
3
+ let help = false;
4
+ let version = false;
5
+ for (let index = 0; index < argv.length; index += 1) {
6
+ const arg = argv[index];
7
+ if (arg === "--help" || arg === "-h") {
8
+ help = true;
9
+ continue;
10
+ }
11
+ if (arg === "--version" || arg === "-v") {
12
+ version = true;
13
+ continue;
14
+ }
15
+ if (arg === "--pet") {
16
+ const next = argv[index + 1];
17
+ if (!next)
18
+ throw new Error("--pet requires a pet id.");
19
+ petId = validateRawPetArg(next);
20
+ index += 1;
21
+ continue;
22
+ }
23
+ if (arg.startsWith("--pet=")) {
24
+ petId = validateRawPetArg(arg.slice("--pet=".length));
25
+ continue;
26
+ }
27
+ throw new Error(`Unknown argument: ${arg}`);
28
+ }
29
+ return { petId, help, version };
30
+ }
31
+ export function validatePetId(value) {
32
+ if (!/^[a-z0-9][a-z0-9_-]{0,63}$/.test(value) || value === "builtin") {
33
+ throw new Error(`Invalid pet id: ${value}`);
34
+ }
35
+ return value;
36
+ }
37
+ export function validateRawPetArg(value) {
38
+ const trimmed = value.trim();
39
+ if (trimmed.length < 1)
40
+ throw new Error("--pet requires a non-empty pet id.");
41
+ if (Buffer.byteLength(trimmed, "utf8") > 128 || /[\x00-\x1F\x7F/\\]/.test(trimmed)) {
42
+ throw new Error("--pet value is outside OpenPets CLI bounds.");
43
+ }
44
+ return trimmed;
45
+ }
46
+ export function createHelpText() {
47
+ return `OpenPets MCP server\n\nUsage:\n burmese-mcp [--pet <petId>]\n\nOptions:\n --pet <petId> Request an installed OpenPets pet for this MCP process; missing pets fall back to default.\n --help Show this help.\n --version Show package version.\n`;
48
+ }
49
+ //# sourceMappingURL=args.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"args.js","sourceRoot":"","sources":["../src/args.ts"],"names":[],"mappings":"AAMA,MAAM,UAAU,YAAY,CAAC,IAAuB;IAClD,IAAI,KAAyB,CAAC;IAC9B,IAAI,IAAI,GAAG,KAAK,CAAC;IACjB,IAAI,OAAO,GAAG,KAAK,CAAC;IAEpB,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QACpD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;QACxB,IAAI,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;YACrC,IAAI,GAAG,IAAI,CAAC;YACZ,SAAS;QACX,CAAC;QACD,IAAI,GAAG,KAAK,WAAW,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;YACxC,OAAO,GAAG,IAAI,CAAC;YACf,SAAS;QACX,CAAC;QACD,IAAI,GAAG,KAAK,OAAO,EAAE,CAAC;YACpB,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;YAC7B,IAAI,CAAC,IAAI;gBAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;YACvD,KAAK,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;YAChC,KAAK,IAAI,CAAC,CAAC;YACX,SAAS;QACX,CAAC;QACD,IAAI,GAAG,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC7B,KAAK,GAAG,iBAAiB,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;YACtD,SAAS;QACX,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,qBAAqB,GAAG,EAAE,CAAC,CAAC;IAC9C,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAAa;IACzC,IAAI,CAAC,4BAA4B,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACrE,MAAM,IAAI,KAAK,CAAC,mBAAmB,KAAK,EAAE,CAAC,CAAC;IAC9C,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,KAAa;IAC7C,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC7B,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;IAC9E,IAAI,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,MAAM,CAAC,GAAG,GAAG,IAAI,oBAAoB,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QACnF,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;IACjE,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,OAAO,mQAAmQ,CAAC;AAC7Q,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=check-mcp-contract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check-mcp-contract.d.ts","sourceRoot":"","sources":["../src/check-mcp-contract.ts"],"names":[],"mappings":""}
@@ -0,0 +1,367 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
4
+ import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
5
+ import { InMemoryTransport } from "@modelcontextprotocol/sdk/inMemory.js";
6
+ import { CallToolResultSchema } from "@modelcontextprotocol/sdk/types.js";
7
+ import { parseMcpArgs } from "./args.js";
8
+ import { wireTransportLifecycle } from "./index.js";
9
+ import { createOpenPetsMcpServer } from "./server.js";
10
+ import { createMcpStatus, sanitizeUnavailableReason } from "./tools.js";
11
+ parseMcpArgs(["--pet", "snoopy"]);
12
+ parseMcpArgs(["--pet=snoopy"]);
13
+ parseMcpArgs(["--pet", "Bad Pet"]);
14
+ parseMcpArgs(["--help"]);
15
+ assertRejects(() => parseMcpArgs(["--pet", "bad/pet"]));
16
+ assertRejects(() => parseMcpArgs(["--agent", "claude"]));
17
+ const unavailableStatus = createMcpStatus({ ok: false, appRunning: false, unavailableReason: "/Users/alvin/.config/OpenPets/runtime/ipc.json ENOENT" }, "snoopy");
18
+ if (unavailableStatus.routingImplemented !== true || unavailableStatus.configuredPetId !== "snoopy") {
19
+ throw new Error("MCP status did not preserve configured pet during degraded status.");
20
+ }
21
+ if (unavailableStatus.unavailableReason?.includes("/Users/")) {
22
+ throw new Error("Unavailable reason leaked a local path.");
23
+ }
24
+ if (sanitizeUnavailableReason("/tmp/openpets-501/openpets-1.sock ENOENT")?.includes("/tmp")) {
25
+ throw new Error("Sanitizer leaked socket path.");
26
+ }
27
+ await checkMcpServerContract();
28
+ await checkStdioServerContract();
29
+ await checkT6TransportOnclose();
30
+ await checkT7EnsureLeaseHeartbeatFirst();
31
+ await checkT8ExitOnce();
32
+ const builtEntrypoint = readFileSync(join("dist", "index.js"), "utf8");
33
+ if (!builtEntrypoint.startsWith("#!/usr/bin/env node")) {
34
+ throw new Error("Built MCP entrypoint is missing a Node shebang.");
35
+ }
36
+ console.error("MCP contract validation passed.");
37
+ // T8 exercises the real stdio lifecycle wiring, which subscribes to process
38
+ // stdin; under a piped runner (pnpm -r) stdin never closes, so exit explicitly.
39
+ process.exit(0);
40
+ async function checkMcpServerContract() {
41
+ const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
42
+ const fakeClient = {
43
+ status: async () => ({
44
+ ok: true,
45
+ appRunning: true,
46
+ defaultPet: { id: "snoopy", displayName: "Snoopy" },
47
+ activeSessions: [
48
+ { line: "Claude Code: active, Snoopy (agent pet)" },
49
+ { line: "Codex: active, Mochi (agent pet)" },
50
+ ],
51
+ defaultPetRoster: [
52
+ { key: "client:test", label: "Claude", reaction: "thinking", message: "Working" },
53
+ ],
54
+ }),
55
+ listPets: async () => ({ ok: true, pets: [], defaultPetId: "builtin" }),
56
+ installPet: async () => { throw new Error("unused"); },
57
+ acquireLease: async () => ({ leaseId: "lease-1", requestedPetId: "snoopy", targetKind: "explicit", actualTargetPetId: "snoopy", actualTargetPetName: "Snoopy", usingDefaultPet: false, expiresAt: Date.now() + 15_000, leaseActive: true }),
58
+ heartbeatLease: async (leaseId) => ({ leaseId, expiresAt: Date.now() + 15_000 }),
59
+ releaseLease: async () => ({ released: true }),
60
+ react: async (reaction, options) => ({ ok: true, reaction, leaseId: options?.leaseId, clientLabel: options?.clientLabel }),
61
+ say: async (message, options) => ({ ok: true, message, leaseId: options?.leaseId, clientLabel: options?.clientLabel }),
62
+ hello: async () => ({ ok: true }),
63
+ };
64
+ const server = createOpenPetsMcpServer({ configuredPetId: "snoopy", client: fakeClient, lease: { lease: await fakeClient.acquireLease() }, leaseReady: Promise.resolve() });
65
+ const client = new Client({ name: "openpets-contract", version: "0.0.0" });
66
+ await Promise.all([server.connect(serverTransport), client.connect(clientTransport)]);
67
+ try {
68
+ const tools = await client.listTools();
69
+ const names = tools.tools.map((tool) => tool.name).sort();
70
+ if (names.join(",") !== "burmese_react,burmese_say,burmese_status") {
71
+ throw new Error(`Unexpected MCP tool list: ${names.join(",")}`);
72
+ }
73
+ const status = await client.callTool({ name: "burmese_status", arguments: {} }, CallToolResultSchema);
74
+ const structured = status.structuredContent;
75
+ if (!structured.ok || structured.configuredPetId !== "snoopy" || structured.routingImplemented !== true || structured.actualTargetPetId !== "snoopy") {
76
+ throw new Error("Status tool returned unexpected structured content.");
77
+ }
78
+ if (structured.defaultPetRoster?.[0]?.label !== "Claude") {
79
+ throw new Error("Status tool did not preserve default pet roster snapshot.");
80
+ }
81
+ const statusFirst = Array.isArray(status.content) ? status.content[0] : undefined;
82
+ const statusText = statusFirst?.type === "text" && typeof statusFirst.text === "string" ? statusFirst.text : "";
83
+ if (!statusText.includes("- Claude Code: active, Snoopy (agent pet)") || !statusText.includes("- Codex: active, Mochi (agent pet)")) {
84
+ throw new Error("Status tool did not list multiple active sessions one per line.");
85
+ }
86
+ const react = await client.callTool({ name: "burmese_react", arguments: { reaction: "waving" } }, CallToolResultSchema);
87
+ if (react.isError)
88
+ throw new Error("Valid reaction unexpectedly failed.");
89
+ const reactStructured = react.structuredContent;
90
+ if (reactStructured?.result?.leaseId !== "lease-1")
91
+ throw new Error("Reaction did not pass lease id to client.");
92
+ if (reactStructured?.result?.clientLabel !== "openpets-contract")
93
+ throw new Error("Reaction did not pass MCP client label to desktop client.");
94
+ const invalidReact = await client.callTool({ name: "burmese_react", arguments: { reaction: "bad" } }, CallToolResultSchema);
95
+ if (!invalidReact.isError)
96
+ throw new Error("Invalid reaction was not rejected.");
97
+ const invalidSay = await client.callTool({ name: "burmese_say", arguments: { message: "const secret = 1" } }, CallToolResultSchema);
98
+ if (!invalidSay.isError)
99
+ throw new Error("Unsafe say message was not rejected.");
100
+ const stale = createMcpStatus({ ok: false, appRunning: true, leaseId: "missing", leaseActive: false, staleReason: "unknown_lease" }, "snoopy", undefined, "missing", "missing");
101
+ if (stale.leaseActive !== false || stale.staleReason !== "unknown_lease" || stale.ok !== false) {
102
+ throw new Error("Stale MCP lease status was not preserved.");
103
+ }
104
+ }
105
+ finally {
106
+ await client.close();
107
+ await server.close();
108
+ }
109
+ }
110
+ async function checkStdioServerContract() {
111
+ const transport = new StdioClientTransport({
112
+ command: process.execPath,
113
+ args: [join("dist", "index.js"), "--pet", "snoopy"],
114
+ env: { ...process.env, OPENPETS_DISCOVERY_FILE: join(process.cwd(), ".missing-openpets-discovery.json") },
115
+ stderr: "pipe",
116
+ });
117
+ const client = new Client({ name: "openpets-stdio-contract", version: "0.0.0" });
118
+ await client.connect(transport);
119
+ try {
120
+ const tools = await client.listTools();
121
+ const names = tools.tools.map((tool) => tool.name).sort();
122
+ if (names.join(",") !== "burmese_react,burmese_say,burmese_status") {
123
+ throw new Error(`Unexpected stdio MCP tool list: ${names.join(",")}`);
124
+ }
125
+ const status = await client.callTool({ name: "burmese_status", arguments: {} }, CallToolResultSchema);
126
+ const content = Array.isArray(status.content) ? status.content : [];
127
+ const first = content[0];
128
+ const text = first?.type === "text" && typeof first.text === "string" ? first.text : "";
129
+ if (!text.includes("Configured --pet snoopy") || !text.includes("actual target is unavailable")) {
130
+ throw new Error("Unavailable stdio status did not explain configured pet and unavailable target.");
131
+ }
132
+ const structured = status.structuredContent;
133
+ if (structured.appRunning !== false || structured.configuredPetId !== "snoopy" || structured.routingImplemented !== true) {
134
+ throw new Error("Unavailable stdio status returned unexpected structured content.");
135
+ }
136
+ }
137
+ finally {
138
+ await client.close();
139
+ }
140
+ }
141
+ /**
142
+ * T6 — Fix 3: transport.onclose must (a) release the active lease,
143
+ * (b) invoke the injected exit seam exactly once, and
144
+ * (c) NOT call acquireLease afterward.
145
+ */
146
+ async function checkT6TransportOnclose() {
147
+ const calls = [];
148
+ const activeLeaseId = "t6-lease-99";
149
+ const fakeClient = {
150
+ status: async () => ({ ok: true, appRunning: true }),
151
+ listPets: async () => ({ ok: true, pets: [], defaultPetId: "builtin" }),
152
+ installPet: async () => { throw new Error("unused"); },
153
+ acquireLease: async () => {
154
+ calls.push("acquireLease");
155
+ return { leaseId: "new-lease", requestedPetId: undefined, targetKind: "default", actualTargetPetId: "default", actualTargetPetName: "Default", usingDefaultPet: true, expiresAt: Date.now() + 15_000, leaseActive: true };
156
+ },
157
+ heartbeatLease: async (leaseId) => { calls.push(`heartbeat:${leaseId}`); return { leaseId, expiresAt: Date.now() + 15_000 }; },
158
+ releaseLease: async (leaseId) => { calls.push(`releaseLease:${leaseId}`); return { released: true }; },
159
+ react: async () => ({ ok: true }),
160
+ say: async () => ({ ok: true }),
161
+ hello: async () => ({ ok: true }),
162
+ };
163
+ const lease = {
164
+ lease: { leaseId: activeLeaseId, requestedPetId: undefined, targetKind: "default", actualTargetPetId: "default", actualTargetPetName: "Default", usingDefaultPet: true, expiresAt: Date.now() + 15_000, leaseActive: true },
165
+ };
166
+ // Minimal stubs — we only need onclose to be wirable
167
+ const fakeTransport = {};
168
+ const fakeServer = { close: async () => { } };
169
+ let exitCalls = 0;
170
+ const fakeExit = () => { exitCalls++; };
171
+ wireTransportLifecycle({
172
+ transport: fakeTransport,
173
+ server: fakeServer,
174
+ client: fakeClient,
175
+ lease,
176
+ leaseReady: Promise.resolve(),
177
+ exit: fakeExit,
178
+ });
179
+ if (typeof fakeTransport.onclose !== "function") {
180
+ throw new Error("T6: wireTransportLifecycle did not set transport.onclose.");
181
+ }
182
+ // Trigger the onclose callback (simulates stdin EOF)
183
+ fakeTransport.onclose();
184
+ // Allow the async close() to settle
185
+ await new Promise((resolve) => setTimeout(resolve, 50));
186
+ if (!calls.includes(`releaseLease:${activeLeaseId}`)) {
187
+ throw new Error(`T6: releaseLease(${activeLeaseId}) was not called. Calls: ${calls.join(",")}`);
188
+ }
189
+ if (exitCalls !== 1) {
190
+ throw new Error(`T6: exit seam was called ${exitCalls} times (expected 1).`);
191
+ }
192
+ if (calls.includes("acquireLease")) {
193
+ throw new Error(`T6: acquireLease was called after transport.onclose — orphan re-acquire detected. Calls: ${calls.join(",")}`);
194
+ }
195
+ }
196
+ /**
197
+ * T7 — Fix 2: when staleLeaseId + staleLease are present and heartbeatLease SUCCEEDS,
198
+ * ensureLease must restore context.lease.lease from the stale lease and NOT call acquireLease.
199
+ * Converse: when heartbeatLease REJECTS, acquireLease MUST be called.
200
+ */
201
+ async function checkT7EnsureLeaseHeartbeatFirst() {
202
+ const staleLeaseId = "t7-stale-lease";
203
+ const staleLease = {
204
+ leaseId: staleLeaseId,
205
+ requestedPetId: "snoopy",
206
+ targetKind: "explicit",
207
+ actualTargetPetId: "snoopy",
208
+ actualTargetPetName: "Snoopy",
209
+ usingDefaultPet: false,
210
+ expiresAt: Date.now() - 1_000, // expired on client side
211
+ leaseActive: true,
212
+ };
213
+ // --- T7a: heartbeat succeeds → restore lease, no acquireLease ---
214
+ {
215
+ const calls = [];
216
+ const [, serverTransport] = InMemoryTransport.createLinkedPair();
217
+ const fakeClient = {
218
+ status: async () => ({ ok: true, appRunning: true }),
219
+ listPets: async () => ({ ok: true, pets: [], defaultPetId: "builtin" }),
220
+ installPet: async () => { throw new Error("unused"); },
221
+ acquireLease: async () => { calls.push("acquireLease"); return { leaseId: "new-lease", requestedPetId: "snoopy", targetKind: "explicit", actualTargetPetId: "snoopy", actualTargetPetName: "Snoopy", usingDefaultPet: false, expiresAt: Date.now() + 15_000, leaseActive: true }; },
222
+ heartbeatLease: async (leaseId) => { calls.push(`heartbeat:${leaseId}`); return { leaseId, expiresAt: Date.now() + 15_000 }; },
223
+ releaseLease: async () => { calls.push("releaseLease"); return { released: true }; },
224
+ react: async (reaction, options) => ({ ok: true, reaction, leaseId: options?.leaseId }),
225
+ say: async (message, options) => ({ ok: true, message, leaseId: options?.leaseId }),
226
+ hello: async () => ({ ok: true }),
227
+ };
228
+ const lease = { lease: undefined, staleLeaseId, staleLease };
229
+ const server = createOpenPetsMcpServer({ configuredPetId: "snoopy", client: fakeClient, lease, leaseReady: Promise.resolve() });
230
+ const mcpClient = new Client({ name: "t7a", version: "0.0.0" });
231
+ const [clientTransport] = InMemoryTransport.createLinkedPair();
232
+ // We need the leaseReady-resolved server; connect it just to allow tool calls
233
+ // Instead call handleReact directly via the server tool interface by invoking
234
+ // the MCP tool through a fresh in-memory pair.
235
+ const [ct, st] = InMemoryTransport.createLinkedPair();
236
+ const server2 = createOpenPetsMcpServer({ configuredPetId: "snoopy", client: fakeClient, lease, leaseReady: Promise.resolve() });
237
+ const mc = new Client({ name: "t7a-client", version: "0.0.0" });
238
+ await Promise.all([server2.connect(st), mc.connect(ct)]);
239
+ try {
240
+ // Calling burmese_react triggers ensureLease (lease is undefined, staleLeaseId is set)
241
+ const result = await mc.callTool({ name: "burmese_react", arguments: { reaction: "waving" } }, CallToolResultSchema);
242
+ if (result.isError)
243
+ throw new Error(`T7a: burmese_react returned error: ${JSON.stringify(result.content)}`);
244
+ if (calls.includes("acquireLease")) {
245
+ throw new Error(`T7a: acquireLease was called despite heartbeat succeeding. Calls: ${calls.join(",")}`);
246
+ }
247
+ if (!calls.some((c) => c.startsWith("heartbeat:"))) {
248
+ throw new Error(`T7a: heartbeatLease was not attempted. Calls: ${calls.join(",")}`);
249
+ }
250
+ if (!lease.lease || lease.lease.leaseId !== staleLeaseId) {
251
+ throw new Error(`T7a: lease was not restored from staleLeaseId. lease.leaseId=${lease.lease?.leaseId}`);
252
+ }
253
+ if (lease.staleLeaseId !== undefined || lease.staleLease !== undefined) {
254
+ throw new Error(`T7a: staleLeaseId / staleLease were not cleared after recovery.`);
255
+ }
256
+ }
257
+ finally {
258
+ await mc.close();
259
+ await server2.close();
260
+ }
261
+ void clientTransport;
262
+ void serverTransport;
263
+ void server;
264
+ void mcpClient; // unused stubs
265
+ }
266
+ // --- T7b: heartbeat fails → acquireLease IS called ---
267
+ {
268
+ const calls = [];
269
+ const fakeClient = {
270
+ status: async () => ({ ok: true, appRunning: true }),
271
+ listPets: async () => ({ ok: true, pets: [], defaultPetId: "builtin" }),
272
+ installPet: async () => { throw new Error("unused"); },
273
+ acquireLease: async () => { calls.push("acquireLease"); return { leaseId: "new-lease-2", requestedPetId: "snoopy", targetKind: "explicit", actualTargetPetId: "snoopy", actualTargetPetName: "Snoopy", usingDefaultPet: false, expiresAt: Date.now() + 15_000, leaseActive: true }; },
274
+ heartbeatLease: async (leaseId) => { calls.push(`heartbeat:${leaseId}`); throw new Error("lease not found"); },
275
+ releaseLease: async () => { calls.push("releaseLease"); return { released: true }; },
276
+ react: async (reaction, options) => ({ ok: true, reaction, leaseId: options?.leaseId }),
277
+ say: async (message, options) => ({ ok: true, message, leaseId: options?.leaseId }),
278
+ hello: async () => ({ ok: true }),
279
+ };
280
+ const lease = { lease: undefined, staleLeaseId, staleLease };
281
+ const [ct2, st2] = InMemoryTransport.createLinkedPair();
282
+ const server3 = createOpenPetsMcpServer({ configuredPetId: "snoopy", client: fakeClient, lease, leaseReady: Promise.resolve() });
283
+ const mc2 = new Client({ name: "t7b-client", version: "0.0.0" });
284
+ await Promise.all([server3.connect(st2), mc2.connect(ct2)]);
285
+ try {
286
+ const result = await mc2.callTool({ name: "burmese_react", arguments: { reaction: "waving" } }, CallToolResultSchema);
287
+ if (result.isError)
288
+ throw new Error(`T7b: burmese_react returned error: ${JSON.stringify(result.content)}`);
289
+ if (!calls.some((c) => c.startsWith("heartbeat:"))) {
290
+ throw new Error(`T7b: heartbeatLease was not attempted. Calls: ${calls.join(",")}`);
291
+ }
292
+ if (!calls.includes("acquireLease")) {
293
+ throw new Error(`T7b: acquireLease was NOT called after heartbeat failure. Calls: ${calls.join(",")}`);
294
+ }
295
+ }
296
+ finally {
297
+ await mc2.close();
298
+ await server3.close();
299
+ }
300
+ }
301
+ }
302
+ function assertRejects(callback) {
303
+ try {
304
+ callback();
305
+ }
306
+ catch {
307
+ return;
308
+ }
309
+ throw new Error("Expected validation to reject.");
310
+ }
311
+ /**
312
+ * T8 — Fix L2: exit seam must fire EXACTLY ONCE even when transport.onclose is triggered
313
+ * multiple times (re-entrant from server.close, or repeated calls from close()). Release
314
+ * must precede the single exit call.
315
+ */
316
+ async function checkT8ExitOnce() {
317
+ const activeLeaseId = "t8-lease-77";
318
+ const releaseOrder = [];
319
+ const fakeClient = {
320
+ status: async () => ({ ok: true, appRunning: true }),
321
+ listPets: async () => ({ ok: true, pets: [], defaultPetId: "builtin" }),
322
+ installPet: async () => { throw new Error("unused"); },
323
+ acquireLease: async () => ({ leaseId: "new", requestedPetId: undefined, targetKind: "default", actualTargetPetId: "default", actualTargetPetName: "Default", usingDefaultPet: true, expiresAt: Date.now() + 15_000, leaseActive: true }),
324
+ heartbeatLease: async (leaseId) => ({ leaseId, expiresAt: Date.now() + 15_000 }),
325
+ releaseLease: async (leaseId) => { releaseOrder.push("release:" + leaseId); return { released: true }; },
326
+ react: async () => ({ ok: true }),
327
+ say: async () => ({ ok: true }),
328
+ hello: async () => ({ ok: true }),
329
+ };
330
+ const lease = {
331
+ lease: { leaseId: activeLeaseId, requestedPetId: undefined, targetKind: "default", actualTargetPetId: "default", actualTargetPetName: "Default", usingDefaultPet: true, expiresAt: Date.now() + 15_000, leaseActive: true },
332
+ };
333
+ const fakeTransport = {};
334
+ // server.close re-fires onclose to simulate MCP SDK re-entrancy
335
+ const fakeServer = { close: async () => { fakeTransport.onclose?.(); } };
336
+ let exitCalls = 0;
337
+ const fakeExit = () => { exitCalls++; releaseOrder.push("exit"); };
338
+ wireTransportLifecycle({
339
+ transport: fakeTransport,
340
+ server: fakeServer,
341
+ client: fakeClient,
342
+ lease,
343
+ leaseReady: Promise.resolve(),
344
+ exit: fakeExit,
345
+ });
346
+ // Fire onclose three times (natural + re-entrant from server.close + extra call)
347
+ fakeTransport.onclose?.();
348
+ fakeTransport.onclose?.();
349
+ fakeTransport.onclose?.();
350
+ // Allow async teardown to settle
351
+ await new Promise((resolve) => setTimeout(resolve, 50));
352
+ if (exitCalls !== 1) {
353
+ throw new Error("T8: exit seam fired " + exitCalls + " times — expected exactly 1. Order: " + releaseOrder.join(","));
354
+ }
355
+ const releaseIdx = releaseOrder.indexOf("release:" + activeLeaseId);
356
+ const exitIdx = releaseOrder.indexOf("exit");
357
+ if (releaseIdx === -1) {
358
+ throw new Error("T8: releaseLease was never called. Order: " + releaseOrder.join(","));
359
+ }
360
+ if (exitIdx === -1) {
361
+ throw new Error("T8: exit was never recorded. Order: " + releaseOrder.join(","));
362
+ }
363
+ if (releaseIdx >= exitIdx) {
364
+ throw new Error("T8: release did not precede exit. Order: " + releaseOrder.join(","));
365
+ }
366
+ }
367
+ //# sourceMappingURL=check-mcp-contract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check-mcp-contract.js","sourceRoot":"","sources":["../src/check-mcp-contract.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ensure-executable.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ensure-executable.d.ts","sourceRoot":"","sources":["../src/ensure-executable.ts"],"names":[],"mappings":""}
@@ -0,0 +1,8 @@
1
+ import { chmodSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ const entrypoint = join(dirname(fileURLToPath(import.meta.url)), "index.js");
5
+ if (process.platform !== "win32") {
6
+ chmodSync(entrypoint, 0o755);
7
+ }
8
+ //# sourceMappingURL=ensure-executable.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ensure-executable.js","sourceRoot":"","sources":["../src/ensure-executable.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;AAE7E,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;IACjC,SAAS,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;AAC/B,CAAC"}
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env node
2
+ import type { OpenPetsClient, OpenPetsLeaseResult } from "@burmese/client";
3
+ import { type LeaseContext } from "./tools.js";
4
+ /** Minimal transport interface required by wireTransportLifecycle (subset of StdioServerTransport). */
5
+ export interface McpTransportHook {
6
+ onclose?: (() => void) | undefined;
7
+ }
8
+ /** Minimal server interface required by wireTransportLifecycle. */
9
+ export interface McpServerHook {
10
+ close(): Promise<void>;
11
+ }
12
+ export interface TransportLifecycleOptions {
13
+ readonly transport: McpTransportHook;
14
+ readonly server: McpServerHook;
15
+ readonly client: OpenPetsClient;
16
+ readonly lease: LeaseContext;
17
+ readonly leaseReady: Promise<void>;
18
+ readonly requestedPetId?: string;
19
+ /**
20
+ * Called after teardown when the transport closes. Defaults to `() => process.exit(0)`.
21
+ * Override in tests to prevent the process from actually exiting.
22
+ */
23
+ readonly exit?: () => void;
24
+ }
25
+ /**
26
+ * Wires heartbeat, retry, and graceful-close logic onto a transport.
27
+ * Exported so tests can invoke the lifecycle without spawning a real process.
28
+ *
29
+ * Returns the `close` function so callers (e.g. SIGINT handlers) can reuse it.
30
+ */
31
+ export declare function wireTransportLifecycle(opts: TransportLifecycleOptions): {
32
+ close: () => Promise<void>;
33
+ };
34
+ export type { LeaseContext, OpenPetsLeaseResult };
35
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAMA,OAAO,KAAK,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAI3E,OAAO,EAAqB,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAElE,uGAAuG;AACvG,MAAM,WAAW,gBAAgB;IAC/B,OAAO,CAAC,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAC;CACpC;AAED,mEAAmE;AACnE,MAAM,WAAW,aAAa;IAC5B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,SAAS,EAAE,gBAAgB,CAAC;IACrC,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;IAC/B,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAChC,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;IAC7B,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC;;;OAGG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,IAAI,CAAC;CAC5B;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,yBAAyB,GAAG;IAAE,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAAE,CAwFtG;AAmED,YAAY,EAAE,YAAY,EAAE,mBAAmB,EAAE,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,169 @@
1
+ #!/usr/bin/env node
2
+ import { readFileSync } from "node:fs";
3
+ import { dirname, join } from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
6
+ import { createHelpText, parseMcpArgs } from "./args.js";
7
+ import { createOpenPetsMcpServer } from "./server.js";
8
+ import { createToolContext } from "./tools.js";
9
+ /**
10
+ * Wires heartbeat, retry, and graceful-close logic onto a transport.
11
+ * Exported so tests can invoke the lifecycle without spawning a real process.
12
+ *
13
+ * Returns the `close` function so callers (e.g. SIGINT handlers) can reuse it.
14
+ */
15
+ export function wireTransportLifecycle(opts) {
16
+ const { transport, server, client, lease, leaseReady, requestedPetId } = opts;
17
+ const exit = opts.exit ?? (() => process.exit(0));
18
+ let exited = false;
19
+ const exitOnce = () => { if (exited)
20
+ return; exited = true; exit(); };
21
+ let heartbeatTimer = null;
22
+ let retryTimer = null;
23
+ let retryDelayMs = 5_000;
24
+ const MAX_RETRY_DELAY_MS = 60_000;
25
+ let closing = false;
26
+ function scheduleRetry() {
27
+ if (retryTimer || closing)
28
+ return;
29
+ retryTimer = setTimeout(() => {
30
+ retryTimer = null;
31
+ if (closing || lease.lease)
32
+ return;
33
+ // Fix 2: attempt heartbeat-first recovery when a stale lease is saved
34
+ void (async () => {
35
+ const staleLeaseId = lease.staleLeaseId;
36
+ const staleLease = lease.staleLease;
37
+ if (staleLeaseId && staleLease) {
38
+ try {
39
+ const hb = await client.heartbeatLease(staleLeaseId);
40
+ // Heartbeat succeeded — desktop still holds the original lease
41
+ lease.lease = { ...staleLease, leaseId: hb.leaseId, expiresAt: hb.expiresAt, leaseActive: true };
42
+ lease.staleLeaseId = undefined;
43
+ lease.staleLease = undefined;
44
+ lease.degradedReason = undefined;
45
+ retryDelayMs = 5_000;
46
+ return;
47
+ }
48
+ catch {
49
+ // Heartbeat failed — fall through to acquireLease
50
+ }
51
+ }
52
+ try {
53
+ const result = await client.acquireLease({ requestedPetId });
54
+ lease.lease = result;
55
+ lease.staleLeaseId = undefined;
56
+ lease.staleLease = undefined;
57
+ lease.degradedReason = undefined;
58
+ retryDelayMs = 5_000;
59
+ }
60
+ catch (error) {
61
+ lease.degradedReason = sanitizeMcpRuntimeError(error);
62
+ retryDelayMs = Math.min(retryDelayMs * 2, MAX_RETRY_DELAY_MS);
63
+ scheduleRetry();
64
+ }
65
+ })();
66
+ }, retryDelayMs);
67
+ retryTimer.unref?.();
68
+ }
69
+ leaseReady.then(() => {
70
+ if (!lease.lease)
71
+ return;
72
+ heartbeatTimer = setInterval(() => {
73
+ if (closing || !lease.lease)
74
+ return;
75
+ void client.heartbeatLease(lease.lease.leaseId).catch((error) => {
76
+ // Save full stale lease for heartbeat-first recovery in scheduleRetry / ensureLease
77
+ lease.staleLease = lease.lease;
78
+ lease.staleLeaseId = lease.lease?.leaseId;
79
+ lease.degradedReason = sanitizeMcpRuntimeError(error);
80
+ lease.lease = undefined;
81
+ retryDelayMs = 5_000;
82
+ scheduleRetry();
83
+ });
84
+ }, 5_000);
85
+ heartbeatTimer.unref?.();
86
+ }).catch(() => { });
87
+ const close = async () => {
88
+ if (closing)
89
+ return;
90
+ closing = true;
91
+ if (heartbeatTimer)
92
+ clearInterval(heartbeatTimer);
93
+ heartbeatTimer = null;
94
+ if (retryTimer)
95
+ clearTimeout(retryTimer);
96
+ retryTimer = null;
97
+ const leaseId = lease.lease?.leaseId;
98
+ lease.lease = undefined;
99
+ if (leaseId) {
100
+ try {
101
+ await client.releaseLease(leaseId);
102
+ }
103
+ catch { /* best effort */ }
104
+ }
105
+ try {
106
+ await server.close();
107
+ }
108
+ catch { /* ignore shutdown errors */ }
109
+ };
110
+ // Fix 3: exit after teardown so the process doesn't linger as an orphan
111
+ transport.onclose = () => { void close().finally(() => exitOnce()); };
112
+ return { close };
113
+ }
114
+ async function main() {
115
+ const options = parseMcpArgs(process.argv.slice(2));
116
+ if (options.help) {
117
+ process.stdout.write(createHelpText());
118
+ return;
119
+ }
120
+ if (options.version) {
121
+ process.stdout.write(`${readPackageVersion()}\n`);
122
+ return;
123
+ }
124
+ const lease = {};
125
+ const context = createToolContext(options.petId);
126
+ const leaseReady = acquireStartupLease(context.client, lease, options.petId);
127
+ const server = createOpenPetsMcpServer({ ...context, lease, leaseReady });
128
+ const transport = new StdioServerTransport();
129
+ const { close } = wireTransportLifecycle({ transport, server, client: context.client, lease, leaseReady, requestedPetId: options.petId });
130
+ process.on("SIGINT", () => { void close().finally(() => process.exit(0)); });
131
+ process.on("SIGTERM", () => { void close().finally(() => process.exit(0)); });
132
+ await server.connect(transport);
133
+ }
134
+ async function acquireStartupLease(client, lease, requestedPetId) {
135
+ try {
136
+ lease.lease = await client.acquireLease({ requestedPetId });
137
+ lease.staleLeaseId = undefined;
138
+ lease.staleLease = undefined;
139
+ lease.degradedReason = undefined;
140
+ }
141
+ catch (error) {
142
+ lease.lease = undefined;
143
+ lease.staleLeaseId = undefined;
144
+ lease.staleLease = undefined;
145
+ lease.degradedReason = sanitizeMcpRuntimeError(error);
146
+ }
147
+ }
148
+ function sanitizeMcpRuntimeError(error) {
149
+ const message = error instanceof Error ? error.message : "OpenPets lease operation failed.";
150
+ if (/\/|\\|\.sock|pipe|token|ipc\.json|ENOENT|ECONNREFUSED|EACCES/i.test(message)) {
151
+ return "OpenPets desktop app or local IPC is unavailable.";
152
+ }
153
+ return message.slice(0, 160);
154
+ }
155
+ main().catch((error) => {
156
+ process.stderr.write(`OpenPets MCP server failed: ${error instanceof Error ? error.message : String(error)}\n`);
157
+ process.exit(1);
158
+ });
159
+ function readPackageVersion() {
160
+ try {
161
+ const here = dirname(fileURLToPath(import.meta.url));
162
+ const packageJson = JSON.parse(readFileSync(join(here, "..", "package.json"), "utf8"));
163
+ return typeof packageJson.version === "string" ? packageJson.version : "0.0.0";
164
+ }
165
+ catch {
166
+ return "0.0.0";
167
+ }
168
+ }
169
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { type ToolContext } from "./tools.js";
3
+ export declare function createOpenPetsMcpServer(context: ToolContext): McpServer;
4
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAgE,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AAE5G,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,WAAW,GAAG,SAAS,CAuCvE"}
package/dist/server.js ADDED
@@ -0,0 +1,39 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { handleReact, handleSay, handleStatus, reactSchema, saySchema } from "./tools.js";
3
+ export function createOpenPetsMcpServer(context) {
4
+ const server = new McpServer({ name: "burmese", version: "0.0.0" }, {
5
+ instructions: "Interact with the user's OpenPets desktop companion. Use burmese_status first. Use burmese_say only for short status/personality messages, never code, logs, secrets, URLs, or file paths.",
6
+ });
7
+ // The connected MCP client (Claude Code, Cursor, Codex, opencode, …) declares
8
+ // its name in the `initialize` handshake. We forward it so the desktop can
9
+ // label this session in the multi-integration status roster. Available only
10
+ // after initialize completes — which always precedes any tool call.
11
+ const getClientLabel = () => {
12
+ try {
13
+ return server.server.getClientVersion()?.name;
14
+ }
15
+ catch {
16
+ return undefined;
17
+ }
18
+ };
19
+ server.registerTool("burmese_status", {
20
+ title: "OpenPets Status",
21
+ description: "Check whether OpenPets is reachable and which pet MCP events currently target.",
22
+ inputSchema: {},
23
+ annotations: { readOnlyHint: true, idempotentHint: true },
24
+ }, async () => handleStatus(context));
25
+ server.registerTool("burmese_react", {
26
+ title: "OpenPets React",
27
+ description: "Set a short coding-oriented reaction on the OpenPets desktop pet.",
28
+ inputSchema: reactSchema,
29
+ annotations: { readOnlyHint: false, idempotentHint: false },
30
+ }, async (input) => handleReact(input, context, getClientLabel()));
31
+ server.registerTool("burmese_say", {
32
+ title: "OpenPets Say",
33
+ description: "Show a short safe message on the OpenPets desktop pet. Do not send code, logs, secrets, URLs, or file paths.",
34
+ inputSchema: saySchema,
35
+ annotations: { readOnlyHint: false, idempotentHint: false },
36
+ }, async (input) => handleSay(input, context, getClientLabel()));
37
+ return server;
38
+ }
39
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,SAAS,EAAoB,MAAM,YAAY,CAAC;AAE5G,MAAM,UAAU,uBAAuB,CAAC,OAAoB;IAC1D,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE;QAClE,YAAY,EAAE,4LAA4L;KAC3M,CAAC,CAAC;IAEH,8EAA8E;IAC9E,2EAA2E;IAC3E,4EAA4E;IAC5E,oEAAoE;IACpE,MAAM,cAAc,GAAG,GAAuB,EAAE;QAC9C,IAAI,CAAC;YACH,OAAO,MAAM,CAAC,MAAM,CAAC,gBAAgB,EAAE,EAAE,IAAI,CAAC;QAChD,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,SAAS,CAAC;QACnB,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,CAAC,YAAY,CAAC,gBAAgB,EAAE;QACpC,KAAK,EAAE,iBAAiB;QACxB,WAAW,EAAE,gFAAgF;QAC7F,WAAW,EAAE,EAAE;QACf,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE;KAC1D,EAAE,KAAK,IAAI,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC;IAEtC,MAAM,CAAC,YAAY,CAAC,eAAe,EAAE;QACnC,KAAK,EAAE,gBAAgB;QACvB,WAAW,EAAE,mEAAmE;QAChF,WAAW,EAAE,WAAW;QACxB,WAAW,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE;KAC5D,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC,CAAC,CAAC;IAEnE,MAAM,CAAC,YAAY,CAAC,aAAa,EAAE;QACjC,KAAK,EAAE,cAAc;QACrB,WAAW,EAAE,8GAA8G;QAC3H,WAAW,EAAE,SAAS;QACtB,WAAW,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE;KAC5D,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC,CAAC,CAAC;IAEjE,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,98 @@
1
+ import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
2
+ import { type OpenPetsClient, type OpenPetsLeaseResult, type OpenPetsReaction, type OpenPetsStatusResult } from "@burmese/client";
3
+ import { z } from "zod";
4
+ export declare const reactionSchema: z.ZodEnum<{
5
+ idle: "idle";
6
+ thinking: "thinking";
7
+ working: "working";
8
+ editing: "editing";
9
+ running: "running";
10
+ testing: "testing";
11
+ waiting: "waiting";
12
+ waving: "waving";
13
+ success: "success";
14
+ error: "error";
15
+ celebrating: "celebrating";
16
+ }>;
17
+ export declare const saySchema: z.ZodObject<{
18
+ message: z.ZodString;
19
+ reaction: z.ZodOptional<z.ZodEnum<{
20
+ idle: "idle";
21
+ thinking: "thinking";
22
+ working: "working";
23
+ editing: "editing";
24
+ running: "running";
25
+ testing: "testing";
26
+ waiting: "waiting";
27
+ waving: "waving";
28
+ success: "success";
29
+ error: "error";
30
+ celebrating: "celebrating";
31
+ }>>;
32
+ }, z.core.$strip>;
33
+ export declare const reactSchema: z.ZodObject<{
34
+ reaction: z.ZodEnum<{
35
+ idle: "idle";
36
+ thinking: "thinking";
37
+ working: "working";
38
+ editing: "editing";
39
+ running: "running";
40
+ testing: "testing";
41
+ waiting: "waiting";
42
+ waving: "waving";
43
+ success: "success";
44
+ error: "error";
45
+ celebrating: "celebrating";
46
+ }>;
47
+ }, z.core.$strip>;
48
+ export interface OpenPetsMcpStatus {
49
+ readonly [key: string]: unknown;
50
+ ok: boolean;
51
+ appRunning: boolean;
52
+ configuredPetId?: string;
53
+ actualTargetPetId?: string;
54
+ actualTargetPetName?: string;
55
+ usingDefaultPet: boolean;
56
+ routingImplemented: boolean;
57
+ unavailableReason?: string;
58
+ fallbackReason?: string;
59
+ activeSessions?: readonly OpenPetsActiveSessionStatus[];
60
+ defaultPetRoster?: readonly OpenPetsDefaultPetRosterStatus[];
61
+ }
62
+ export interface OpenPetsActiveSessionStatus {
63
+ readonly [key: string]: unknown;
64
+ readonly line: string;
65
+ }
66
+ export interface OpenPetsDefaultPetRosterStatus {
67
+ readonly [key: string]: unknown;
68
+ readonly key: string;
69
+ readonly integrationId?: string;
70
+ readonly label?: string;
71
+ readonly sources?: readonly string[];
72
+ readonly reaction?: string;
73
+ readonly message?: string;
74
+ }
75
+ export interface LeaseContext {
76
+ lease?: OpenPetsLeaseResult;
77
+ staleLeaseId?: string;
78
+ /** Full lease object saved when the lease became stale; used for heartbeat-first recovery. */
79
+ staleLease?: OpenPetsLeaseResult;
80
+ degradedReason?: string;
81
+ }
82
+ export interface ToolContext {
83
+ readonly configuredPetId?: string;
84
+ readonly client?: OpenPetsClient;
85
+ readonly lease?: LeaseContext;
86
+ readonly leaseReady?: Promise<void>;
87
+ }
88
+ export declare function createToolContext(configuredPetId?: string): ToolContext & {
89
+ readonly client: OpenPetsClient;
90
+ };
91
+ export declare function handleStatus(context: ToolContext): Promise<CallToolResult>;
92
+ export declare function handleReact(input: unknown, context: ToolContext, clientLabel?: string): Promise<CallToolResult>;
93
+ export declare function handleSay(input: unknown, context: ToolContext, clientLabel?: string): Promise<CallToolResult>;
94
+ export declare function createMcpStatus(status: OpenPetsStatusResult, configuredPetId?: string, lease?: OpenPetsLeaseResult, degradedReason?: string, staleLeaseId?: string): OpenPetsMcpStatus;
95
+ export declare function toolError(message: string): CallToolResult;
96
+ export declare function sanitizeUnavailableReason(value: unknown): string | undefined;
97
+ export type { OpenPetsReaction };
98
+ //# sourceMappingURL=tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"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"}
package/dist/tools.js ADDED
@@ -0,0 +1,227 @@
1
+ import { allowedReactions, createOpenPetsClient, OpenPetsClientError } from "@burmese/client";
2
+ import { z } from "zod";
3
+ export const reactionSchema = z.enum(allowedReactions);
4
+ export const saySchema = z.object({
5
+ message: z.string().trim().min(1).max(140)
6
+ .refine((value) => !/[\r\n]/.test(value), "Message must be single-line.")
7
+ .refine((value) => !/```|<script|function\s+\w+|=>|\b(class|import|export|const|let|var)\b/.test(value), "Message looks like code.")
8
+ .refine((value) => !/https?:\/\/|www\.|\/[\w.-]+\/[\w./-]+|[A-Za-z]:\\/.test(value), "Message contains URL or path-like content.")
9
+ .refine((value) => !/(api[_-]?key|secret|token|password|passwd|BEGIN [A-Z ]+PRIVATE KEY)/i.test(value), "Message looks secret-like."),
10
+ reaction: reactionSchema.optional(),
11
+ });
12
+ export const reactSchema = z.object({ reaction: reactionSchema });
13
+ export function createToolContext(configuredPetId) {
14
+ return {
15
+ configuredPetId,
16
+ client: createOpenPetsClient(),
17
+ };
18
+ }
19
+ export async function handleStatus(context) {
20
+ await context.leaseReady;
21
+ const client = context.client ?? createOpenPetsClient();
22
+ const leaseId = context.lease?.lease?.leaseId ?? context.lease?.staleLeaseId;
23
+ const status = await client.status({ leaseId });
24
+ const structured = createMcpStatus(status, context.configuredPetId, context.lease?.lease, context.lease?.degradedReason, context.lease?.staleLeaseId);
25
+ const configuredText = context.configuredPetId
26
+ ? `Configured --pet ${context.configuredPetId}; actual target is ${structured.actualTargetPetId ?? "unavailable"}.`
27
+ : "No --pet configured; actual target is the desktop default pet.";
28
+ if (!structured.appRunning) {
29
+ return {
30
+ content: [{ type: "text", text: `OpenPets is unavailable. ${configuredText} ${structured.unavailableReason ?? "Open the OpenPets desktop app and try again."}` }],
31
+ structuredContent: structured,
32
+ };
33
+ }
34
+ const sessionLines = getActiveSessionLines(structured.activeSessions);
35
+ if (sessionLines.length > 1) {
36
+ return {
37
+ content: [{ type: "text", text: [`- OpenPets: running; ${configuredText}`, ...sessionLines.map((line) => `- ${line}`)].join("\n") }],
38
+ structuredContent: structured,
39
+ };
40
+ }
41
+ return {
42
+ content: [{ type: "text", text: `OpenPets is running. ${configuredText}` }],
43
+ structuredContent: structured,
44
+ };
45
+ }
46
+ async function ensureLease(context) {
47
+ if (context.lease?.lease)
48
+ return true;
49
+ try {
50
+ const client = context.client ?? createOpenPetsClient();
51
+ // Fix 2: attempt heartbeat-first recovery when a stale lease is saved
52
+ const staleLeaseId = context.lease?.staleLeaseId;
53
+ const staleLease = context.lease?.staleLease;
54
+ if (staleLeaseId && staleLease) {
55
+ try {
56
+ const hb = await client.heartbeatLease(staleLeaseId);
57
+ // Heartbeat succeeded — desktop still holds the original lease
58
+ if (context.lease) {
59
+ context.lease.lease = { ...staleLease, leaseId: hb.leaseId, expiresAt: hb.expiresAt, leaseActive: true };
60
+ context.lease.staleLeaseId = undefined;
61
+ context.lease.staleLease = undefined;
62
+ context.lease.degradedReason = undefined;
63
+ }
64
+ return true;
65
+ }
66
+ catch {
67
+ // Heartbeat failed — fall through to acquireLease
68
+ }
69
+ }
70
+ const newLease = await client.acquireLease({ requestedPetId: context.configuredPetId });
71
+ if (context.lease) {
72
+ context.lease.lease = newLease;
73
+ context.lease.staleLeaseId = undefined;
74
+ context.lease.staleLease = undefined;
75
+ context.lease.degradedReason = undefined;
76
+ }
77
+ return !!newLease;
78
+ }
79
+ catch {
80
+ return false;
81
+ }
82
+ }
83
+ export async function handleReact(input, context, clientLabel) {
84
+ await context.leaseReady;
85
+ const parsed = reactSchema.safeParse(input);
86
+ if (!parsed.success)
87
+ return toolError("Invalid reaction. Use one of: " + allowedReactions.join(", "));
88
+ if (!(await ensureLease(context)))
89
+ return toolError(`OpenPets lease is unavailable. ${sanitizeUnavailableReason(context.lease?.degradedReason) ?? "Open OpenPets and try again."}`);
90
+ try {
91
+ const client = context.client ?? createOpenPetsClient();
92
+ const result = await client.react(parsed.data.reaction, { leaseId: context.lease.lease.leaseId, clientLabel, source: "mcp" });
93
+ return {
94
+ content: [{ type: "text", text: `OpenPets reaction sent: ${parsed.data.reaction}` }],
95
+ structuredContent: { ok: true, reaction: parsed.data.reaction, result },
96
+ };
97
+ }
98
+ catch (error) {
99
+ return toolError(`OpenPets desktop app is not running or local IPC is unavailable. ${sanitizeError(error)}`);
100
+ }
101
+ }
102
+ export async function handleSay(input, context, clientLabel) {
103
+ await context.leaseReady;
104
+ const parsed = saySchema.safeParse(input);
105
+ if (!parsed.success)
106
+ return toolError("Invalid message. Keep it short, single-line, and avoid code, secrets, URLs, and file paths.");
107
+ if (!(await ensureLease(context)))
108
+ return toolError(`OpenPets lease is unavailable. ${sanitizeUnavailableReason(context.lease?.degradedReason) ?? "Open OpenPets and try again."}`);
109
+ try {
110
+ const client = context.client ?? createOpenPetsClient();
111
+ const result = await client.say(parsed.data.message, { reaction: parsed.data.reaction, leaseId: context.lease.lease.leaseId, clientLabel, source: "mcp" });
112
+ return {
113
+ content: [{ type: "text", text: "OpenPets message sent." }],
114
+ structuredContent: { ok: true, result },
115
+ };
116
+ }
117
+ catch (error) {
118
+ return toolError(`OpenPets desktop app is not running or local IPC is unavailable. ${sanitizeError(error)}`);
119
+ }
120
+ }
121
+ export function createMcpStatus(status, configuredPetId, lease, degradedReason, staleLeaseId) {
122
+ const activeSessions = parseActiveSessions(status.activeSessions);
123
+ const defaultPetRoster = parseDefaultPetRoster(status.defaultPetRoster);
124
+ if (status.leaseActive === false || staleLeaseId) {
125
+ return {
126
+ ok: false,
127
+ appRunning: status.appRunning === true,
128
+ configuredPetId,
129
+ usingDefaultPet: true,
130
+ routingImplemented: true,
131
+ unavailableReason: sanitizeUnavailableReason(degradedReason ?? status.unavailableReason ?? status.staleReason),
132
+ leaseId: typeof status.leaseId === "string" ? status.leaseId : staleLeaseId,
133
+ leaseActive: false,
134
+ staleReason: typeof status.staleReason === "string" ? status.staleReason : "unknown_lease",
135
+ activeSessions,
136
+ defaultPetRoster,
137
+ };
138
+ }
139
+ if (lease) {
140
+ const statusTargetPetId = typeof status.actualTargetPetId === "string" ? status.actualTargetPetId : undefined;
141
+ const statusTargetPetName = typeof status.actualTargetPetName === "string" ? status.actualTargetPetName : undefined;
142
+ const statusUsingDefault = typeof status.usingDefaultPet === "boolean" ? status.usingDefaultPet : undefined;
143
+ const statusFallbackReason = typeof status.fallbackReason === "string" ? status.fallbackReason : undefined;
144
+ return {
145
+ ok: status.appRunning === true && status.ok !== false,
146
+ appRunning: status.appRunning === true,
147
+ configuredPetId,
148
+ actualTargetPetId: statusTargetPetId ?? lease.actualTargetPetId,
149
+ actualTargetPetName: statusTargetPetName ?? lease.actualTargetPetName,
150
+ usingDefaultPet: statusUsingDefault ?? lease.usingDefaultPet,
151
+ routingImplemented: true,
152
+ fallbackReason: statusFallbackReason ?? lease.fallbackReason,
153
+ leaseId: lease.leaseId,
154
+ leaseActive: lease.leaseActive,
155
+ activeSessions,
156
+ defaultPetRoster,
157
+ };
158
+ }
159
+ const defaultPet = isRecord(status.defaultPet) ? status.defaultPet : undefined;
160
+ const actualTargetPetId = typeof defaultPet?.id === "string" ? defaultPet.id : undefined;
161
+ const actualTargetPetName = typeof defaultPet?.displayName === "string" ? defaultPet.displayName : undefined;
162
+ const appRunning = status.appRunning === true;
163
+ return {
164
+ ok: appRunning && status.ok !== false,
165
+ appRunning,
166
+ configuredPetId,
167
+ actualTargetPetId,
168
+ actualTargetPetName,
169
+ usingDefaultPet: true,
170
+ routingImplemented: true,
171
+ unavailableReason: appRunning ? undefined : sanitizeUnavailableReason(degradedReason ?? status.unavailableReason),
172
+ fallbackReason: undefined,
173
+ activeSessions,
174
+ defaultPetRoster,
175
+ };
176
+ }
177
+ export function toolError(message) {
178
+ return { content: [{ type: "text", text: message }], isError: true };
179
+ }
180
+ export function sanitizeUnavailableReason(value) {
181
+ if (typeof value !== "string" || value.length === 0)
182
+ return "OpenPets desktop app is unavailable.";
183
+ if (/\/|\\|\.sock|pipe|token|ipc\.json|ENOENT|ECONNREFUSED|EACCES/i.test(value)) {
184
+ return "OpenPets desktop app or local IPC is unavailable.";
185
+ }
186
+ return value.slice(0, 160);
187
+ }
188
+ function sanitizeError(error) {
189
+ if (error instanceof OpenPetsClientError)
190
+ return sanitizeUnavailableReason(error.message) ?? "OpenPets is unavailable.";
191
+ return "Open OpenPets and try again.";
192
+ }
193
+ function parseActiveSessions(value) {
194
+ if (!Array.isArray(value))
195
+ return undefined;
196
+ const sessions = value.flatMap((item) => {
197
+ if (!isRecord(item) || typeof item.line !== "string")
198
+ return [];
199
+ return [{ ...item, line: sanitizeStatusLine(item.line) }];
200
+ });
201
+ return sessions.length > 0 ? sessions : undefined;
202
+ }
203
+ function parseDefaultPetRoster(value) {
204
+ if (!Array.isArray(value))
205
+ return undefined;
206
+ const rows = value.flatMap((item) => {
207
+ if (!isRecord(item) || typeof item.key !== "string")
208
+ return [];
209
+ const integrationId = typeof item.integrationId === "string" ? sanitizeStatusLine(item.integrationId) : undefined;
210
+ const label = typeof item.label === "string" ? sanitizeStatusLine(item.label) : undefined;
211
+ const sources = Array.isArray(item.sources) ? item.sources.filter((s) => typeof s === "string").map((s) => sanitizeStatusLine(s)) : undefined;
212
+ const reaction = typeof item.reaction === "string" ? sanitizeStatusLine(item.reaction) : undefined;
213
+ const message = typeof item.message === "string" ? sanitizeStatusLine(item.message) : undefined;
214
+ return [{ key: item.key.slice(0, 160), integrationId, label, sources, reaction, message }];
215
+ });
216
+ return rows.length > 0 ? rows : undefined;
217
+ }
218
+ function getActiveSessionLines(sessions) {
219
+ return (sessions ?? []).map((session) => sanitizeStatusLine(session.line)).filter(Boolean);
220
+ }
221
+ function sanitizeStatusLine(value) {
222
+ return value.replace(/[\r\n]/g, " ").replace(/\s+/g, " ").trim().slice(0, 140);
223
+ }
224
+ function isRecord(value) {
225
+ return typeof value === "object" && value !== null;
226
+ }
227
+ //# sourceMappingURL=tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.js","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@burmese/mcp",
3
+ "version": "3.1.0",
4
+ "license": "MIT",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "git+https://github.com/wannabeepolymath/pet-assistant.git",
8
+ "directory": "packages/mcp"
9
+ },
10
+ "type": "module",
11
+ "main": "dist/index.js",
12
+ "types": "dist/index.d.ts",
13
+ "bin": {
14
+ "burmese-mcp": "./dist/index.js"
15
+ },
16
+ "files": [
17
+ "dist"
18
+ ],
19
+ "publishConfig": {
20
+ "access": "public"
21
+ },
22
+ "exports": {
23
+ ".": {
24
+ "types": "./dist/index.d.ts",
25
+ "default": "./dist/index.js"
26
+ }
27
+ },
28
+ "devDependencies": {
29
+ "@types/node": "^25.6.2",
30
+ "typescript": "^6.0.3"
31
+ },
32
+ "dependencies": {
33
+ "@modelcontextprotocol/sdk": "^1.29.0",
34
+ "zod": "^4.4.3",
35
+ "@burmese/client": "3.1.0"
36
+ },
37
+ "scripts": {
38
+ "test": "node dist/check-mcp-contract.js",
39
+ "check": "pnpm --filter @burmese/client build && pnpm typecheck && pnpm build && pnpm test",
40
+ "typecheck": "tsc --noEmit",
41
+ "build": "tsc && node dist/ensure-executable.js"
42
+ }
43
+ }