@daeda/mcp-pro 0.1.20 → 0.1.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -3320,6 +3320,8 @@ if (!LICENSE_KEY) {
3320
3320
  process.exit(1);
3321
3321
  }
3322
3322
  var WS_URL = process.env.MCP_CLIENT_WEBSOCKET_URL ?? process.env.websocket_url ?? "wss://mcp-ws.daeda.tech";
3323
+ var PING_INTERVAL_MS = 15e3;
3324
+ var PONG_TIMEOUT_MS = 1e4;
3323
3325
  var WebSocketLive = Layer5.effect(
3324
3326
  WebSocketService,
3325
3327
  Effect40.gen(function* () {
@@ -3333,6 +3335,9 @@ var WebSocketLive = Layer5.effect(
3333
3335
  const pendingPlanListRef = yield* Ref14.make(null);
3334
3336
  const handlersRef = yield* Ref14.make(null);
3335
3337
  const encryptionKeyRef = yield* Ref14.make(null);
3338
+ let pingInterval = null;
3339
+ let pongTimeout = null;
3340
+ let awaitingPong = false;
3336
3341
  const requireWs = pipe33(
3337
3342
  Ref14.get(wsRef),
3338
3343
  Effect40.flatMap(
@@ -3366,26 +3371,95 @@ var WebSocketLive = Layer5.effect(
3366
3371
  Match.when({ type: "plan:list:response" }, (m) => handlePlanListResponse(m.payload, ctx)),
3367
3372
  Match.orElse(() => Effect40.void)
3368
3373
  );
3374
+ const stopPing = () => {
3375
+ if (pingInterval) {
3376
+ clearInterval(pingInterval);
3377
+ pingInterval = null;
3378
+ }
3379
+ if (pongTimeout) {
3380
+ clearTimeout(pongTimeout);
3381
+ pongTimeout = null;
3382
+ }
3383
+ awaitingPong = false;
3384
+ };
3385
+ const startPing = (ws) => {
3386
+ stopPing();
3387
+ pingInterval = setInterval(() => {
3388
+ if (awaitingPong) {
3389
+ console.error("[ws:ping] Pong not received in time \u2014 closing stale connection");
3390
+ stopPing();
3391
+ try {
3392
+ ws.close();
3393
+ } catch {
3394
+ }
3395
+ return;
3396
+ }
3397
+ try {
3398
+ ws.send(JSON.stringify({ type: "ping", payload: { timestamp: Date.now() } }));
3399
+ awaitingPong = true;
3400
+ pongTimeout = setTimeout(() => {
3401
+ if (awaitingPong) {
3402
+ console.error("[ws:ping] Pong timeout \u2014 closing stale connection");
3403
+ stopPing();
3404
+ try {
3405
+ ws.close();
3406
+ } catch {
3407
+ }
3408
+ }
3409
+ }, PONG_TIMEOUT_MS);
3410
+ } catch {
3411
+ console.error("[ws:ping] Failed to send ping \u2014 connection may be dead");
3412
+ stopPing();
3413
+ try {
3414
+ ws.close();
3415
+ } catch {
3416
+ }
3417
+ }
3418
+ }, PING_INTERVAL_MS);
3419
+ };
3369
3420
  const wireMessageHandler = (ws) => Effect40.sync(() => {
3370
3421
  ws.onmessage = (event) => {
3422
+ let parsed;
3423
+ try {
3424
+ parsed = JSON.parse(event.data);
3425
+ } catch (err) {
3426
+ console.error("[ws:message] Failed to parse message:", err);
3427
+ return;
3428
+ }
3429
+ if (parsed.type === "pong") {
3430
+ awaitingPong = false;
3431
+ if (pongTimeout) {
3432
+ clearTimeout(pongTimeout);
3433
+ pongTimeout = null;
3434
+ }
3435
+ return;
3436
+ }
3371
3437
  console.error("Received:", event.data);
3372
3438
  pipe33(
3373
- Effect40.try({
3374
- try: () => JSON.parse(event.data),
3375
- catch: (error) => new WebSocketError({ url: WS_URL, cause: error })
3376
- }),
3439
+ Effect40.succeed(parsed),
3377
3440
  Effect40.flatMap(routeMessage),
3378
3441
  Effect40.catchAll((err) => Effect40.sync(() => console.error("[ws:message] Error handling message:", err))),
3379
3442
  Effect40.runFork
3380
3443
  );
3381
3444
  };
3382
3445
  });
3446
+ const rejectAllPending = () => {
3447
+ const closeError = new WebSocketError({ url: WS_URL, cause: new Error("WebSocket closed") });
3448
+ const pendingArtifact = Effect40.runSync(Ref14.getAndSet(pendingArtifactRef, null));
3449
+ if (pendingArtifact) pendingArtifact.reject(closeError);
3450
+ const pendingPlanCreate = Effect40.runSync(Ref14.getAndSet(pendingPlanCreateRef, null));
3451
+ if (pendingPlanCreate) pendingPlanCreate.reject(closeError);
3452
+ const pendingPlanList = Effect40.runSync(Ref14.getAndSet(pendingPlanListRef, null));
3453
+ if (pendingPlanList) pendingPlanList.reject(closeError);
3454
+ const pendingPlugins = Effect40.runSync(Ref14.getAndSet(pendingPluginRequestsRef, /* @__PURE__ */ new Map()));
3455
+ for (const [, pending] of pendingPlugins) {
3456
+ pending.reject(closeError);
3457
+ }
3458
+ };
3383
3459
  const wireCloseHandler = (ws) => Effect40.sync(() => {
3384
3460
  ws.onclose = () => {
3385
- const pending = Effect40.runSync(Ref14.getAndSet(pendingArtifactRef, null));
3386
- if (pending) {
3387
- pending.reject(new WebSocketError({ url: WS_URL, cause: new Error("WebSocket closed") }));
3388
- }
3461
+ stopPing();
3462
+ rejectAllPending();
3389
3463
  pipe33(
3390
3464
  Ref14.set(stateRef, "disconnected"),
3391
3465
  Effect40.flatMap(() => Ref14.set(wsRef, null)),
@@ -3403,6 +3477,7 @@ var WebSocketLive = Layer5.effect(
3403
3477
  (ws) => Effect40.async((resume) => {
3404
3478
  ws.onopen = () => {
3405
3479
  console.error(`[ws] Connected to ${WS_URL}, sending register`);
3480
+ startPing(ws);
3406
3481
  pipe33(
3407
3482
  Ref14.set(stateRef, "connected"),
3408
3483
  Effect40.flatMap(() => Ref14.set(isReconnectingRef, false)),
@@ -3478,7 +3553,12 @@ var WebSocketLive = Layer5.effect(
3478
3553
  reject: (error) => resume(Effect40.fail(error))
3479
3554
  };
3480
3555
  Effect40.runSync(Ref14.set(pendingArtifactRef, pending));
3481
- ws.send(JSON.stringify({ type: "sync:artifact", payload: { artifact_id: artifactId } }));
3556
+ try {
3557
+ ws.send(JSON.stringify({ type: "sync:artifact", payload: { artifact_id: artifactId } }));
3558
+ } catch (err) {
3559
+ Effect40.runSync(Ref14.set(pendingArtifactRef, null));
3560
+ resume(Effect40.fail(new WebSocketError({ url: WS_URL, cause: err })));
3561
+ }
3482
3562
  })
3483
3563
  ),
3484
3564
  Effect40.timeoutFail({
@@ -3500,14 +3580,21 @@ var WebSocketLive = Layer5.effect(
3500
3580
  const next = new Map(pendingMap);
3501
3581
  next.set(requestId, pending);
3502
3582
  Effect40.runSync(Ref14.set(pendingPluginRequestsRef, next));
3503
- ws.send(JSON.stringify({
3504
- type: "sync:plugin-data",
3505
- payload: {
3506
- target_portal: portalId,
3507
- plugin_name: pluginName,
3508
- request_id: requestId
3509
- }
3510
- }));
3583
+ try {
3584
+ ws.send(JSON.stringify({
3585
+ type: "sync:plugin-data",
3586
+ payload: {
3587
+ target_portal: portalId,
3588
+ plugin_name: pluginName,
3589
+ request_id: requestId
3590
+ }
3591
+ }));
3592
+ } catch (err) {
3593
+ const cleanup = new Map(Effect40.runSync(Ref14.get(pendingPluginRequestsRef)));
3594
+ cleanup.delete(requestId);
3595
+ Effect40.runSync(Ref14.set(pendingPluginRequestsRef, cleanup));
3596
+ resume(Effect40.fail(new WebSocketError({ url: WS_URL, cause: err })));
3597
+ }
3511
3598
  }),
3512
3599
  Effect40.timeoutFail({
3513
3600
  duration: Duration.seconds(timeoutSeconds ?? 30),
@@ -3535,7 +3622,12 @@ var WebSocketLive = Layer5.effect(
3535
3622
  reject: (error) => resume(Effect40.fail(error))
3536
3623
  };
3537
3624
  Effect40.runSync(Ref14.set(pendingPlanCreateRef, pending));
3538
- ws.send(JSON.stringify({ type: "plan:create", payload: { target_portal: portalId, ...plan.dry_run ? { dry_run: true } : {}, plan } }));
3625
+ try {
3626
+ ws.send(JSON.stringify({ type: "plan:create", payload: { target_portal: portalId, ...plan.dry_run ? { dry_run: true } : {}, plan } }));
3627
+ } catch (err) {
3628
+ Effect40.runSync(Ref14.set(pendingPlanCreateRef, null));
3629
+ resume(Effect40.fail(new WebSocketError({ url: WS_URL, cause: err })));
3630
+ }
3539
3631
  })
3540
3632
  ),
3541
3633
  Effect40.timeoutFail({
@@ -3552,7 +3644,12 @@ var WebSocketLive = Layer5.effect(
3552
3644
  reject: (error) => resume(Effect40.fail(error))
3553
3645
  };
3554
3646
  Effect40.runSync(Ref14.set(pendingPlanListRef, pending));
3555
- ws.send(JSON.stringify({ type: "plan:list", payload: { target_portal: portalId, ...status && { status } } }));
3647
+ try {
3648
+ ws.send(JSON.stringify({ type: "plan:list", payload: { target_portal: portalId, ...status && { status } } }));
3649
+ } catch (err) {
3650
+ Effect40.runSync(Ref14.set(pendingPlanListRef, null));
3651
+ resume(Effect40.fail(new WebSocketError({ url: WS_URL, cause: err })));
3652
+ }
3556
3653
  })
3557
3654
  ),
3558
3655
  Effect40.timeoutFail({
@@ -11781,7 +11878,7 @@ var BUILT_IN_ACTION_TYPES = {
11781
11878
  description: "Set, edit, copy, or clear property values for enrolled or associated records",
11782
11879
  connectionType: "SINGLE_CONNECTION",
11783
11880
  fields: [
11784
- { name: "property_name", type: "string", required: true, description: "Internal property name to set" },
11881
+ { name: "property", type: "string", required: true, description: "Internal property name to set" },
11785
11882
  { name: "value", type: "object", required: true, description: "MUST include type: 'STATIC_VALUE' when setting a value, e.g. { type: 'STATIC_VALUE', staticValue: 'value' }. Omitting type causes HTTP 500." },
11786
11883
  { name: "association", type: "object", required: false, description: "Association spec if setting on an associated record: { associationCategory: 'HUBSPOT_DEFINED', associationTypeId: <number> }" }
11787
11884
  ]
@@ -12347,7 +12444,7 @@ var collectWorkflowAssociatedPropertyActionRefs = (actions) => actions.flatMap((
12347
12444
  if (actionTypeId !== "0-5") return [];
12348
12445
  const fields48 = isRecord(action.fields) ? action.fields : void 0;
12349
12446
  const association = isRecord(fields48?.association) ? fields48.association : void 0;
12350
- const propertyName = typeof fields48?.property_name === "string" ? fields48.property_name : void 0;
12447
+ const propertyName = typeof fields48?.property === "string" ? fields48.property : typeof fields48?.property_name === "string" ? fields48.property_name : void 0;
12351
12448
  const associationTypeId = typeof association?.associationTypeId === "number" ? association.associationTypeId : void 0;
12352
12449
  if (!propertyName || associationTypeId === void 0) return [];
12353
12450
  return [{
@@ -12621,10 +12718,9 @@ var normalizeWorkflowActionValues = (actions) => actions.map((action) => {
12621
12718
  if (!fields48) return { ...action };
12622
12719
  const actionTypeId = typeof action.actionTypeId === "string" ? action.actionTypeId : "";
12623
12720
  if (actionTypeId === "0-5") {
12624
- return {
12625
- ...action,
12626
- fields: { ...fields48, value: injectStaticValueType(fields48.value) }
12627
- };
12721
+ const { property_name, ...restFields } = fields48;
12722
+ const normalizedFields = property_name && !restFields.property ? { ...restFields, property: property_name, value: injectStaticValueType(restFields.value) } : { ...restFields, value: injectStaticValueType(restFields.value) };
12723
+ return { ...action, fields: normalizedFields };
12628
12724
  }
12629
12725
  if (actionTypeId === "0-14" && Array.isArray(fields48.properties)) {
12630
12726
  return {
@@ -12656,7 +12752,7 @@ var collectWorkflowPropertyActionRefs = (actions) => actions.flatMap((action) =>
12656
12752
  const fields48 = typeof action.fields === "object" && action.fields !== null ? action.fields : void 0;
12657
12753
  const association = typeof fields48?.association === "object" && fields48.association !== null ? fields48.association : void 0;
12658
12754
  const value = typeof fields48?.value === "object" && fields48.value !== null ? fields48.value : void 0;
12659
- const propertyName = typeof fields48?.property_name === "string" ? fields48.property_name : void 0;
12755
+ const propertyName = typeof fields48?.property === "string" ? fields48.property : typeof fields48?.property_name === "string" ? fields48.property_name : void 0;
12660
12756
  if (!propertyName) return [];
12661
12757
  return [{
12662
12758
  actionId: typeof action.actionId === "string" ? action.actionId : "<missing>",
@@ -13326,10 +13422,30 @@ var buildDispatcher = (handlers) => {
13326
13422
  return h;
13327
13423
  };
13328
13424
  const validateOperation2 = (op, index) => getHandler(op.type).validate(op, index);
13329
- const validateOperationEffectful2 = (op, index) => getHandler(op.type).validateEffectful(op, index);
13330
- const preCheckOperation2 = (op, index) => getHandler(op.type).preCheck(op, index);
13331
- const executeOperation2 = (op, index) => getHandler(op.type).execute(op, index);
13332
- const postCheckOperation2 = (op, index, result) => getHandler(op.type).postCheck(op, index, result);
13425
+ const getHandlerSafe = (type, index) => {
13426
+ const h = map.get(type);
13427
+ return h ? Effect96.succeed(h) : Effect96.fail([{ severity: "error", operation_index: index, code: "UNKNOWN_OPERATION_TYPE", message: `No handler registered for operation type: ${type}` }]);
13428
+ };
13429
+ const validateOperationEffectful2 = (op, index) => pipe83(
13430
+ getHandlerSafe(op.type, index),
13431
+ Effect96.flatMap((h) => h.validateEffectful(op, index)),
13432
+ Effect96.catchAll((issues) => Effect96.succeed(issues))
13433
+ );
13434
+ const preCheckOperation2 = (op, index) => pipe83(
13435
+ getHandlerSafe(op.type, index),
13436
+ Effect96.flatMap((h) => h.preCheck(op, index)),
13437
+ Effect96.catchAll((issues) => Effect96.succeed(issues))
13438
+ );
13439
+ const executeOperation2 = (op, index) => pipe83(
13440
+ getHandlerSafe(op.type, index),
13441
+ Effect96.flatMap((h) => h.execute(op, index)),
13442
+ Effect96.catchAll(() => Effect96.succeed({ index, type: op.type, status: "failed", records_affected: 0, error: `No handler registered for operation type: ${op.type}` }))
13443
+ );
13444
+ const postCheckOperation2 = (op, index, result) => pipe83(
13445
+ getHandlerSafe(op.type, index),
13446
+ Effect96.flatMap((h) => h.postCheck(op, index, result)),
13447
+ Effect96.catchAll((issues) => Effect96.succeed(issues))
13448
+ );
13333
13449
  const validatePlan2 = (operations) => operations.flatMap((op, i) => validateOperation2(op, i));
13334
13450
  const validatePlanEffectful2 = (operations) => pipe83(
13335
13451
  Effect96.forEach(
@@ -14300,7 +14416,7 @@ No plans found${filterMsg}.` }]
14300
14416
  }
14301
14417
 
14302
14418
  // src/pure/plugin-sync-gate.ts
14303
- var PLUGIN_SYNC_DEBOUNCE_MS = 1 * 60 * 1e3;
14419
+ var PLUGIN_SYNC_DEBOUNCE_MS = 10 * 60 * 1e3;
14304
14420
  var LAST_PLUGIN_SYNC_ALL_KEY = "last_plugin_sync_all";
14305
14421
  var shouldRunPluginSync = (lastSyncAllRaw) => {
14306
14422
  if (!lastSyncAllRaw) return true;
@@ -14439,6 +14555,12 @@ var makeEnsureFresh = (deps, options2) => createEnsureFresh(
14439
14555
  );
14440
14556
 
14441
14557
  // src/index.ts
14558
+ process.on("uncaughtException", (err) => {
14559
+ console.error("[fatal:uncaughtException]", err);
14560
+ });
14561
+ process.on("unhandledRejection", (reason) => {
14562
+ console.error("[fatal:unhandledRejection]", reason);
14563
+ });
14442
14564
  var server = new McpServer({
14443
14565
  name: "mcp-pro-client",
14444
14566
  version: "1.0.0"
@@ -0,0 +1,195 @@
1
+ #!/usr/bin/env node
2
+ #!/usr/bin/env node
3
+
4
+ // src/supervisor.ts
5
+ import { spawn } from "child_process";
6
+ import { fileURLToPath } from "url";
7
+ import { dirname, resolve } from "path";
8
+ var RESTART_DELAY_MS = 500;
9
+ var MAX_RESTART_COUNT = 10;
10
+ var RESTART_WINDOW_MS = 6e4;
11
+ var isRequest = (msg) => "method" in msg && "id" in msg;
12
+ var isResponse = (msg) => "id" in msg && !("method" in msg);
13
+ var isNotification = (msg) => "method" in msg && !("id" in msg);
14
+ var serialize = (msg) => JSON.stringify(msg) + "\n";
15
+ var makeErrorResponse = (id, message) => ({
16
+ jsonrpc: "2.0",
17
+ id,
18
+ error: { code: -32603, message }
19
+ });
20
+ var LineBuffer = class {
21
+ buf = "";
22
+ push(chunk) {
23
+ this.buf += chunk;
24
+ const messages = [];
25
+ let idx;
26
+ while ((idx = this.buf.indexOf("\n")) !== -1) {
27
+ const line = this.buf.slice(0, idx).replace(/\r$/, "");
28
+ this.buf = this.buf.slice(idx + 1);
29
+ if (line.length === 0) continue;
30
+ try {
31
+ messages.push(JSON.parse(line));
32
+ } catch {
33
+ process.stderr.write(`[supervisor] Failed to parse JSON-RPC line: ${line.slice(0, 200)}
34
+ `);
35
+ }
36
+ }
37
+ return messages;
38
+ }
39
+ clear() {
40
+ this.buf = "";
41
+ }
42
+ };
43
+ var selfDir = dirname(fileURLToPath(import.meta.url));
44
+ var childScript = resolve(selfDir, "index.js");
45
+ var child = null;
46
+ var pendingRequests = /* @__PURE__ */ new Map();
47
+ var savedInitializeRequest = null;
48
+ var childReady = false;
49
+ var restarting = false;
50
+ var stdinBuffer = [];
51
+ var recentRestarts = [];
52
+ var childStdoutBuf = new LineBuffer();
53
+ var stdinBuf = new LineBuffer();
54
+ process.stdin.setEncoding("utf-8");
55
+ process.stdin.on("data", (chunk) => {
56
+ const messages = stdinBuf.push(chunk);
57
+ for (const msg of messages) {
58
+ handleUpstreamMessage(msg);
59
+ }
60
+ });
61
+ function handleUpstreamMessage(msg) {
62
+ if (isRequest(msg)) {
63
+ if (msg.method === "initialize") {
64
+ savedInitializeRequest = msg;
65
+ }
66
+ pendingRequests.set(msg.id, msg);
67
+ }
68
+ if (!childReady || !child) {
69
+ stdinBuffer.push(msg);
70
+ return;
71
+ }
72
+ forwardToChild(msg);
73
+ }
74
+ function forwardToChild(msg) {
75
+ try {
76
+ child?.stdin?.write(serialize(msg));
77
+ } catch {
78
+ process.stderr.write("[supervisor] Failed to write to child stdin\n");
79
+ }
80
+ }
81
+ function handleChildStdout(chunk) {
82
+ const messages = childStdoutBuf.push(chunk);
83
+ for (const msg of messages) {
84
+ handleDownstreamMessage(msg);
85
+ }
86
+ }
87
+ function handleDownstreamMessage(msg) {
88
+ if (isResponse(msg)) {
89
+ pendingRequests.delete(msg.id);
90
+ if (restarting && savedInitializeRequest && msg.id === savedInitializeRequest.id) {
91
+ process.stderr.write("[supervisor] Swallowed re-initialize response from child\n");
92
+ finishRestart();
93
+ return;
94
+ }
95
+ }
96
+ forwardToCodex(msg);
97
+ }
98
+ function forwardToCodex(msg) {
99
+ try {
100
+ process.stdout.write(serialize(msg));
101
+ } catch {
102
+ process.stderr.write("[supervisor] Failed to write to stdout (Codex pipe broken)\n");
103
+ process.exit(1);
104
+ }
105
+ }
106
+ function spawnChild() {
107
+ const now = Date.now();
108
+ recentRestarts.push(now);
109
+ while (recentRestarts.length > 0 && now - recentRestarts[0] > RESTART_WINDOW_MS) {
110
+ recentRestarts.shift();
111
+ }
112
+ if (recentRestarts.length > MAX_RESTART_COUNT) {
113
+ process.stderr.write(
114
+ `[supervisor] Too many restarts (${recentRestarts.length} in ${RESTART_WINDOW_MS / 1e3}s) \u2014 exiting
115
+ `
116
+ );
117
+ process.exit(1);
118
+ }
119
+ process.stderr.write(`[supervisor] Spawning MCP client: ${childScript}
120
+ `);
121
+ child = spawn(process.execPath, [childScript], {
122
+ stdio: ["pipe", "pipe", "inherit"],
123
+ env: process.env
124
+ });
125
+ child.stdout.setEncoding("utf-8");
126
+ child.stdout.on("data", handleChildStdout);
127
+ child.on("exit", (code, signal) => {
128
+ process.stderr.write(
129
+ `[supervisor] Child exited: code=${code} signal=${signal ?? "none"}
130
+ `
131
+ );
132
+ child = null;
133
+ childReady = false;
134
+ childStdoutBuf.clear();
135
+ handleChildExit();
136
+ });
137
+ child.on("error", (err) => {
138
+ process.stderr.write(`[supervisor] Child error: ${err.message}
139
+ `);
140
+ });
141
+ }
142
+ function handleChildExit() {
143
+ failPendingRequests("MCP server restarted \u2014 please retry this request");
144
+ setTimeout(() => {
145
+ process.stderr.write("[supervisor] Restarting child...\n");
146
+ spawnChild();
147
+ if (savedInitializeRequest) {
148
+ restarting = true;
149
+ forwardToChild({ ...savedInitializeRequest });
150
+ } else {
151
+ childReady = true;
152
+ restarting = false;
153
+ drainStdinBuffer();
154
+ }
155
+ }, RESTART_DELAY_MS);
156
+ }
157
+ function finishRestart() {
158
+ if (savedInitializeRequest) {
159
+ const initialized = {
160
+ jsonrpc: "2.0",
161
+ method: "notifications/initialized"
162
+ };
163
+ forwardToChild(initialized);
164
+ }
165
+ childReady = true;
166
+ restarting = false;
167
+ process.stderr.write("[supervisor] Child re-initialized \u2014 resuming proxy\n");
168
+ drainStdinBuffer();
169
+ }
170
+ function drainStdinBuffer() {
171
+ const buffered = stdinBuffer;
172
+ stdinBuffer = [];
173
+ for (const msg of buffered) {
174
+ if (isRequest(msg) && msg.method === "initialize") continue;
175
+ if (isNotification(msg) && msg.method === "notifications/initialized") continue;
176
+ forwardToChild(msg);
177
+ }
178
+ }
179
+ function failPendingRequests(message) {
180
+ for (const [id] of pendingRequests) {
181
+ forwardToCodex(makeErrorResponse(id, message));
182
+ }
183
+ pendingRequests.clear();
184
+ }
185
+ process.stderr.write("[supervisor] Starting MCP supervisor\n");
186
+ spawnChild();
187
+ childReady = true;
188
+ process.on("SIGINT", () => {
189
+ child?.kill("SIGINT");
190
+ process.exit(0);
191
+ });
192
+ process.on("SIGTERM", () => {
193
+ child?.kill("SIGTERM");
194
+ process.exit(0);
195
+ });
package/package.json CHANGED
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "name": "@daeda/mcp-pro",
3
- "version": "0.1.20",
3
+ "version": "0.1.22",
4
4
  "description": "MCP server for HubSpot CRM — sync, query, and manage your portal data",
5
5
  "type": "module",
6
6
  "bin": {
7
- "mcp-pro": "dist/index.js"
7
+ "mcp-pro": "dist/index.js",
8
+ "mcp-pro-supervised": "dist/supervisor.js"
8
9
  },
9
10
  "main": "./dist/index.js",
10
11
  "exports": {