@promptprojectmanager/mcp-server 4.5.7 → 4.6.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/dist/index.js CHANGED
@@ -1,14 +1,4 @@
1
1
  #!/usr/bin/env node
2
- import {
3
- getLogFile,
4
- getWatcherDir,
5
- isProcessRunning,
6
- isWatcherRunning,
7
- readPid,
8
- readStatus,
9
- removePid,
10
- writeStatus
11
- } from "./chunk-ATAMNB7A.js";
12
2
 
13
3
  // src/index.ts
14
4
  import minimist from "minimist";
@@ -111,168 +101,258 @@ function parseWatcherStartArgs(args) {
111
101
  };
112
102
  }
113
103
 
104
+ // src/watcher/watcher_state.ts
105
+ import { existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync } from "fs";
106
+ import { join } from "path";
107
+ function getWatcherDir(workingDirectory) {
108
+ const dir = join(workingDirectory, ".ppm", "yolo");
109
+ if (!existsSync(dir)) {
110
+ mkdirSync(dir, { recursive: true });
111
+ }
112
+ return dir;
113
+ }
114
+ function getStatusFile(workingDirectory) {
115
+ return join(getWatcherDir(workingDirectory), "status.json");
116
+ }
117
+ function writeStatus(workingDirectory, status) {
118
+ const statusFile = getStatusFile(workingDirectory);
119
+ writeFileSync(statusFile, JSON.stringify(status, null, 2), "utf-8");
120
+ }
121
+ function readStatus(workingDirectory) {
122
+ const statusFile = getStatusFile(workingDirectory);
123
+ if (!existsSync(statusFile)) {
124
+ return void 0;
125
+ }
126
+ try {
127
+ const content = readFileSync(statusFile, "utf-8");
128
+ return JSON.parse(content);
129
+ } catch {
130
+ return void 0;
131
+ }
132
+ }
133
+
134
+ // src/watcher/watcher_orchestrator.ts
135
+ function buildOrchestratorInstructions(config, pendingTickets) {
136
+ const pollIntervalSec = Math.round(config.pollIntervalMs / 1e3);
137
+ return `# \u{1F916} YOLO Orchestrator Active
138
+
139
+ You are now the **YOLO Orchestrator** for project \`${config.projectSlug}\`.
140
+
141
+ ## Current Configuration
142
+ - **Poll Interval**: ${pollIntervalSec}s
143
+ - **Max Parallel**: ${config.maxParallel}
144
+ - **Ticket Timeout**: ${Math.round(config.ticketTimeout / 1e3 / 60)} minutes
145
+ - **Working Directory**: ${config.workingDirectory}
146
+
147
+ ## Pending YOLO Tickets
148
+ ${pendingTickets.length > 0 ? formatPendingTickets(pendingTickets) : "_No tickets with YOLO flag currently in queue._"}
149
+
150
+ ## Your Job
151
+
152
+ ${pendingTickets.length > 0 ? `
153
+ ### \u{1F4E5} Execute Pending Tickets
154
+
155
+ For each pending ticket above:
156
+
157
+ 1. **Claim it** using \`tickets_work\` with the ticket slug
158
+ 2. **Spawn a Task sub-agent** to execute it:
159
+ \`\`\`
160
+ Task tool with:
161
+ - subagent_type: "general-purpose"
162
+ - prompt: The ticket content (what needs to be done)
163
+ - run_in_background: true (for parallel execution)
164
+ \`\`\`
165
+ 3. **Report** the result when the sub-agent completes
166
+
167
+ ### Sub-Agent Prompt Template
168
+
169
+ When spawning a sub-agent, use this prompt structure:
170
+
171
+ \`\`\`
172
+ Execute this ticket autonomously:
173
+
174
+ ## Ticket: {ticketSlug}
175
+
176
+ {ticketContent}
177
+
178
+ ---
179
+
180
+ When complete:
181
+ 1. Use \`tickets_close\` to close the ticket with slug "{ticketSlug}"
182
+ 2. Provide a brief summary of what was accomplished
183
+
184
+ If you encounter blocking issues, use \`tickets_update\` to log your findings.
185
+ \`\`\`
186
+ ` : `
187
+ ### \u{1F504} No Tickets Ready
188
+
189
+ No YOLO tickets are currently pending. You can:
190
+ - Say **"poll"** or **"check"** to refresh the ticket list
191
+ - Say **"stop"** to exit orchestrator mode
192
+ - Wait for tickets to be flagged with YOLO in the PPM UI
193
+ `}
194
+
195
+ ## Commands
196
+
197
+ - **"poll"** or **"continue"** - Check for new YOLO tickets
198
+ - **"status"** - Show current orchestrator status
199
+ - **"stop"** or **"exit"** - Stop the orchestrator
200
+
201
+ ## Status Tracking
202
+
203
+ Use \`tickets_yolo_status\` to:
204
+ - See pending YOLO tickets
205
+ - Check currently executing tickets
206
+ - View processed ticket count
207
+
208
+ ---
209
+
210
+ _Orchestrator started at ${(/* @__PURE__ */ new Date()).toISOString()}_
211
+ _Say "poll" to check for tickets, "stop" to exit._`;
212
+ }
213
+ function formatPendingTickets(tickets) {
214
+ return tickets.map((t, i) => {
215
+ const num = t.ticketNumber ? `#${t.ticketNumber}` : "";
216
+ const title = t.slug;
217
+ const preview = t.content.slice(0, 100).replace(/\n/g, " ");
218
+ return `${i + 1}. **${num} ${title}**
219
+ _${preview}${t.content.length > 100 ? "..." : ""}_`;
220
+ }).join("\n\n");
221
+ }
222
+ function formatOrchestratorStatus(status, pendingTickets) {
223
+ if (!status) {
224
+ return `# YOLO Orchestrator Status
225
+
226
+ **State**: Not started
227
+
228
+ _Use \`tickets_yolo_start\` to begin orchestration._`;
229
+ }
230
+ const lines = [
231
+ "# YOLO Orchestrator Status",
232
+ "",
233
+ `**State**: ${status.state}`,
234
+ `**Project**: ${status.projectSlug}`
235
+ ];
236
+ if (status.startedAt) {
237
+ lines.push(`**Started**: ${status.startedAt}`);
238
+ }
239
+ if (status.lastPollAt) {
240
+ lines.push(`**Last Poll**: ${status.lastPollAt}`);
241
+ }
242
+ lines.push(`**Tickets Processed**: ${status.ticketsProcessed}`);
243
+ if (status.currentlyExecuting && status.currentlyExecuting.length > 0) {
244
+ lines.push("");
245
+ lines.push("## Currently Executing");
246
+ for (const exec of status.currentlyExecuting) {
247
+ const num = exec.ticketNumber ? `#${exec.ticketNumber}` : "";
248
+ const elapsed = getElapsedTime(exec.startedAt);
249
+ lines.push(`- **${num} ${exec.ticketSlug}** (${elapsed})`);
250
+ }
251
+ }
252
+ lines.push("");
253
+ lines.push("## Pending YOLO Tickets");
254
+ if (pendingTickets.length > 0) {
255
+ for (const ticket of pendingTickets) {
256
+ const num = ticket.ticketNumber ? `#${ticket.ticketNumber}` : "";
257
+ lines.push(`- **${num} ${ticket.slug}**`);
258
+ }
259
+ } else {
260
+ lines.push("_No tickets pending_");
261
+ }
262
+ return lines.join("\n");
263
+ }
264
+ function getElapsedTime(startedAt) {
265
+ const start = new Date(startedAt).getTime();
266
+ const elapsed = Date.now() - start;
267
+ const minutes = Math.floor(elapsed / 1e3 / 60);
268
+ const seconds = Math.floor(elapsed / 1e3 % 60);
269
+ if (minutes > 0) {
270
+ return `${minutes}m ${seconds}s`;
271
+ }
272
+ return `${seconds}s`;
273
+ }
274
+
114
275
  // src/watcher/watcher_controller.ts
115
- import { spawn } from "child_process";
116
- import { openSync, appendFileSync } from "fs";
117
- import { dirname, join } from "path";
118
- import { fileURLToPath } from "url";
119
- async function startWatcher(baseConfig, args) {
276
+ function startOrchestrator(baseConfig, args, pendingTickets) {
120
277
  const workingDirectory = args?.workingDirectory ?? baseConfig.workingDirectory;
121
- if (isWatcherRunning(workingDirectory)) {
122
- const existingPid = readPid(workingDirectory);
123
- const existingStatus = readStatus(workingDirectory);
124
- return {
125
- success: true,
126
- message: "Watcher is already running",
127
- pid: existingPid,
128
- alreadyRunning: true,
129
- config: existingStatus?.config
130
- };
131
- }
132
- const config = {
278
+ const orchestratorConfig = {
133
279
  projectSlug: baseConfig.projectSlug,
134
- projectToken: baseConfig.projectToken,
135
- convexUrl: baseConfig.convexUrl,
136
- workingDirectory,
137
280
  pollIntervalMs: args?.pollIntervalMs ?? 3e4,
138
281
  maxParallel: args?.maxParallel ?? 1,
139
282
  ticketTimeout: args?.ticketTimeout ?? 18e5,
140
- enableNotifications: args?.enableNotifications ?? true
283
+ workingDirectory
141
284
  };
142
- const configJson = JSON.stringify(config);
143
- const configBase64 = Buffer.from(configJson).toString("base64");
144
- const daemonPath = getDaemonPath();
145
- try {
146
- getWatcherDir(workingDirectory);
147
- const logFile = getLogFile(workingDirectory);
148
- appendFileSync(logFile, `
149
- --- Daemon starting at ${(/* @__PURE__ */ new Date()).toISOString()} ---
150
- `);
151
- const logFd = openSync(logFile, "a");
152
- const child = spawn(process.execPath, [daemonPath, "--config", configBase64], {
153
- detached: true,
154
- stdio: ["ignore", logFd, logFd],
155
- // stdout & stderr → log file descriptor
156
- cwd: workingDirectory
157
- });
158
- child.unref();
159
- await new Promise((resolve) => setTimeout(resolve, 500));
160
- const pid = readPid(workingDirectory);
161
- if (pid && isProcessRunning(pid)) {
162
- return {
163
- success: true,
164
- message: "Watcher started successfully",
165
- pid,
166
- alreadyRunning: false,
167
- config: {
168
- projectSlug: config.projectSlug,
169
- convexUrl: config.convexUrl,
170
- pollIntervalMs: config.pollIntervalMs,
171
- maxParallel: config.maxParallel,
172
- ticketTimeout: config.ticketTimeout,
173
- enableNotifications: config.enableNotifications,
174
- workingDirectory: config.workingDirectory
175
- }
176
- };
177
- } else {
178
- return {
179
- success: false,
180
- message: "Daemon process started but failed to initialize. Check logs in .ppm/yolo/"
181
- };
285
+ getWatcherDir(workingDirectory);
286
+ const initialStatus = {
287
+ state: "running",
288
+ projectSlug: baseConfig.projectSlug,
289
+ startedAt: (/* @__PURE__ */ new Date()).toISOString(),
290
+ ticketsProcessed: 0,
291
+ currentlyExecuting: [],
292
+ config: {
293
+ projectSlug: baseConfig.projectSlug,
294
+ convexUrl: baseConfig.convexUrl,
295
+ pollIntervalMs: orchestratorConfig.pollIntervalMs,
296
+ maxParallel: orchestratorConfig.maxParallel,
297
+ ticketTimeout: orchestratorConfig.ticketTimeout,
298
+ enableNotifications: args?.enableNotifications ?? true,
299
+ workingDirectory
182
300
  }
183
- } catch (error) {
184
- const errorMessage = error instanceof Error ? error.message : "Unknown error";
185
- return {
186
- success: false,
187
- message: `Failed to start watcher: ${errorMessage}`
188
- };
189
- }
301
+ };
302
+ writeStatus(workingDirectory, initialStatus);
303
+ const instructions = buildOrchestratorInstructions(orchestratorConfig, pendingTickets);
304
+ return {
305
+ success: true,
306
+ message: "Orchestrator started",
307
+ instructions,
308
+ config: initialStatus.config,
309
+ alreadyRunning: false
310
+ };
190
311
  }
191
- async function stopWatcher(workingDirectory) {
192
- const pid = readPid(workingDirectory);
193
- if (!pid) {
312
+ function stopOrchestrator(workingDirectory) {
313
+ const status = readStatus(workingDirectory);
314
+ if (!status) {
194
315
  return {
195
316
  success: true,
196
- message: "No watcher is running",
317
+ message: "No orchestrator session found",
197
318
  wasRunning: false
198
319
  };
199
320
  }
200
- if (!isProcessRunning(pid)) {
201
- removePid(workingDirectory);
202
- const status = readStatus(workingDirectory);
203
- if (status) {
204
- writeStatus(workingDirectory, { ...status, state: "stopped" });
205
- }
321
+ if (status.state !== "running") {
206
322
  return {
207
323
  success: true,
208
- message: "Watcher was not running (cleaned up stale PID file)",
324
+ message: `Orchestrator was already ${status.state}`,
209
325
  wasRunning: false
210
326
  };
211
327
  }
212
- try {
213
- process.kill(pid, "SIGTERM");
214
- const maxWait = 5e3;
215
- const checkInterval = 100;
216
- let waited = 0;
217
- while (waited < maxWait && isProcessRunning(pid)) {
218
- await new Promise((resolve) => setTimeout(resolve, checkInterval));
219
- waited += checkInterval;
220
- }
221
- if (isProcessRunning(pid)) {
222
- try {
223
- process.kill(pid, "SIGKILL");
224
- } catch {
225
- }
226
- }
227
- removePid(workingDirectory);
228
- const status = readStatus(workingDirectory);
229
- if (status) {
230
- writeStatus(workingDirectory, { ...status, state: "stopped" });
231
- }
232
- return {
233
- success: true,
234
- message: "Watcher stopped successfully",
235
- wasRunning: true
236
- };
237
- } catch (error) {
238
- const errorMessage = error instanceof Error ? error.message : "Unknown error";
239
- return {
240
- success: false,
241
- message: `Failed to stop watcher: ${errorMessage}`,
242
- wasRunning: true
243
- };
244
- }
328
+ writeStatus(workingDirectory, {
329
+ ...status,
330
+ state: "stopped"
331
+ });
332
+ return {
333
+ success: true,
334
+ message: "Orchestrator stopped",
335
+ wasRunning: true
336
+ };
245
337
  }
246
- function getWatcherStatus(workingDirectory) {
338
+ function getOrchestratorStatus(workingDirectory, pendingTickets) {
247
339
  const status = readStatus(workingDirectory);
340
+ const formattedStatus = formatOrchestratorStatus(status ?? null, pendingTickets);
248
341
  if (!status) {
249
342
  return {
250
343
  success: true,
251
- message: "No watcher has been started for this project"
344
+ message: "No orchestrator session has been started for this project",
345
+ pendingTickets,
346
+ formattedStatus
252
347
  };
253
348
  }
254
- if (status.state === "running" && status.pid) {
255
- if (!isProcessRunning(status.pid)) {
256
- const updatedStatus = { ...status, state: "stopped" };
257
- writeStatus(workingDirectory, updatedStatus);
258
- removePid(workingDirectory);
259
- return {
260
- success: true,
261
- status: updatedStatus,
262
- message: "Watcher process has stopped unexpectedly"
263
- };
264
- }
265
- }
266
349
  return {
267
350
  success: true,
268
- status
351
+ status,
352
+ pendingTickets,
353
+ formattedStatus
269
354
  };
270
355
  }
271
- function getDaemonPath() {
272
- const currentFilePath = fileURLToPath(import.meta.url);
273
- const currentDir = dirname(currentFilePath);
274
- return join(currentDir, "watcher", "watcher_daemon.js");
275
- }
276
356
 
277
357
  // src/prompt-builder.ts
278
358
  var AmbiguousPromptError = class extends Error {
@@ -415,25 +495,25 @@ async function startServer(config, convexClientRaw) {
415
495
  projectSlug,
416
496
  type: "update"
417
497
  },
418
- // YOLO watcher tools - autonomous ticket execution
498
+ // YOLO orchestrator tools - sub-agent based autonomous ticket execution
419
499
  {
420
500
  name: `tickets_yolo_start`,
421
501
  description: `Start the YOLO ticket watcher for "${projectSlug}". Polls for open tickets with yolo flag and spawns Terminal windows with Claude Code to execute them autonomously.`,
422
- slashDescription: `Start YOLO watcher for autonomous ticket execution`,
502
+ slashDescription: `Start YOLO orchestrator for autonomous ticket execution`,
423
503
  projectSlug,
424
504
  type: "yolo_start"
425
505
  },
426
506
  {
427
507
  name: `tickets_yolo_stop`,
428
508
  description: `Stop the YOLO ticket watcher for "${projectSlug}"`,
429
- slashDescription: `Stop the YOLO watcher daemon`,
509
+ slashDescription: `Stop the YOLO orchestrator`,
430
510
  projectSlug,
431
511
  type: "yolo_stop"
432
512
  },
433
513
  {
434
514
  name: `tickets_yolo_status`,
435
515
  description: `Get YOLO watcher status for "${projectSlug}"`,
436
- slashDescription: `Check YOLO watcher status and metrics`,
516
+ slashDescription: `Check YOLO orchestrator status and pending tickets`,
437
517
  projectSlug,
438
518
  type: "yolo_status"
439
519
  }
@@ -1520,33 +1600,31 @@ _Ticket content has been appended with your update._`
1520
1600
  const args = parseWatcherStartArgs(request.params.arguments);
1521
1601
  const workingDirectory = args.workingDirectory ?? process.cwd();
1522
1602
  try {
1523
- const result = await startWatcher(
1603
+ let pendingTickets = [];
1604
+ try {
1605
+ pendingTickets = await convexClient.query(
1606
+ "mcp_tickets:listYoloTickets",
1607
+ {
1608
+ projectToken: config.projectToken,
1609
+ projectSlug: ticketTool.projectSlug
1610
+ }
1611
+ );
1612
+ } catch (queryError) {
1613
+ console.error(`[MCP] Failed to query YOLO tickets:`, queryError);
1614
+ }
1615
+ const result = startOrchestrator(
1524
1616
  {
1525
1617
  projectSlug: ticketTool.projectSlug,
1526
1618
  projectToken: config.projectToken,
1527
1619
  convexUrl: config.convexUrl,
1528
1620
  workingDirectory
1529
1621
  },
1530
- args
1622
+ args,
1623
+ pendingTickets
1531
1624
  );
1532
- if (result.success) {
1533
- const statusLines = [
1534
- result.alreadyRunning ? `\u2139\uFE0F Watcher is already running (PID: ${result.pid})` : `\u2705 Watcher started (PID: ${result.pid})`
1535
- ];
1536
- if (result.config) {
1537
- statusLines.push("");
1538
- statusLines.push("**Configuration:**");
1539
- statusLines.push(` Poll Interval: ${result.config.pollIntervalMs / 1e3}s`);
1540
- statusLines.push(` Max Parallel: ${result.config.maxParallel}`);
1541
- statusLines.push(` Ticket Timeout: ${result.config.ticketTimeout / 1e3 / 60} min`);
1542
- statusLines.push(` Notifications: ${result.config.enableNotifications ? "enabled" : "disabled"}`);
1543
- statusLines.push(` Working Directory: ${result.config.workingDirectory}`);
1544
- }
1545
- statusLines.push("");
1546
- statusLines.push("_The watcher will poll for open tickets with the YOLO flag and spawn Claude Code terminals to execute them._");
1547
- statusLines.push("_Use `tickets_yolo_status` to check progress, `tickets_yolo_stop` to stop._");
1625
+ if (result.success && result.instructions) {
1548
1626
  return {
1549
- content: [{ type: "text", text: statusLines.join("\n") }]
1627
+ content: [{ type: "text", text: result.instructions }]
1550
1628
  };
1551
1629
  } else {
1552
1630
  return {
@@ -1558,19 +1636,19 @@ _Ticket content has been appended with your update._`
1558
1636
  const errorMessage = error instanceof Error ? error.message : "Unknown error";
1559
1637
  console.error(`[MCP] tickets_yolo_start error:`, error);
1560
1638
  return {
1561
- content: [{ type: "text", text: `Error starting watcher: ${errorMessage}` }],
1639
+ content: [{ type: "text", text: `Error starting orchestrator: ${errorMessage}` }],
1562
1640
  isError: true
1563
1641
  };
1564
1642
  }
1565
1643
  } else if (ticketTool.type === "yolo_stop") {
1566
1644
  const workingDirectory = process.cwd();
1567
1645
  try {
1568
- const result = await stopWatcher(workingDirectory);
1646
+ const result = stopOrchestrator(workingDirectory);
1569
1647
  if (result.success) {
1570
1648
  return {
1571
1649
  content: [{
1572
1650
  type: "text",
1573
- text: result.wasRunning ? `\u2705 Watcher stopped successfully` : `\u2139\uFE0F ${result.message}`
1651
+ text: result.wasRunning ? `\u2705 Orchestrator stopped. You can stop processing tickets now.` : `\u2139\uFE0F ${result.message}`
1574
1652
  }]
1575
1653
  };
1576
1654
  } else {
@@ -1583,62 +1661,39 @@ _Ticket content has been appended with your update._`
1583
1661
  const errorMessage = error instanceof Error ? error.message : "Unknown error";
1584
1662
  console.error(`[MCP] tickets_yolo_stop error:`, error);
1585
1663
  return {
1586
- content: [{ type: "text", text: `Error stopping watcher: ${errorMessage}` }],
1664
+ content: [{ type: "text", text: `Error stopping orchestrator: ${errorMessage}` }],
1587
1665
  isError: true
1588
1666
  };
1589
1667
  }
1590
1668
  } else if (ticketTool.type === "yolo_status") {
1591
1669
  const workingDirectory = process.cwd();
1592
1670
  try {
1593
- const result = getWatcherStatus(workingDirectory);
1594
- if (!result.status) {
1671
+ let pendingTickets = [];
1672
+ try {
1673
+ pendingTickets = await convexClient.query(
1674
+ "mcp_tickets:listYoloTickets",
1675
+ {
1676
+ projectToken: config.projectToken,
1677
+ projectSlug: ticketTool.projectSlug
1678
+ }
1679
+ );
1680
+ } catch (queryError) {
1681
+ console.error(`[MCP] Failed to query YOLO tickets:`, queryError);
1682
+ }
1683
+ const result = getOrchestratorStatus(workingDirectory, pendingTickets);
1684
+ if (result.formattedStatus) {
1595
1685
  return {
1596
- content: [{ type: "text", text: `\u2139\uFE0F ${result.message ?? "No watcher status available"}` }]
1686
+ content: [{ type: "text", text: result.formattedStatus }]
1597
1687
  };
1598
1688
  }
1599
- const status = result.status;
1600
- const lines = [
1601
- `# YOLO Watcher Status: ${status.projectSlug}`,
1602
- "",
1603
- `**State:** ${status.state.toUpperCase()}`
1604
- ];
1605
- if (status.pid) {
1606
- lines.push(`**PID:** ${status.pid}`);
1607
- }
1608
- if (status.startedAt) {
1609
- lines.push(`**Started:** ${status.startedAt}`);
1610
- }
1611
- if (status.lastPollAt) {
1612
- lines.push(`**Last Poll:** ${status.lastPollAt}`);
1613
- }
1614
- lines.push(`**Tickets Processed:** ${status.ticketsProcessed}`);
1615
- if (status.currentlyExecuting && status.currentlyExecuting.length > 0) {
1616
- lines.push("");
1617
- lines.push("**Currently Executing:**");
1618
- for (const exec of status.currentlyExecuting) {
1619
- const displayName = exec.ticketNumber ? `#${exec.ticketNumber} ${exec.ticketSlug}` : exec.ticketSlug;
1620
- lines.push(` \u2022 ${displayName} (started: ${exec.startedAt})`);
1621
- }
1622
- }
1623
- if (status.lastError) {
1624
- lines.push("");
1625
- lines.push(`**Last Error:** ${status.lastError}`);
1626
- }
1627
- if (status.config) {
1628
- lines.push("");
1629
- lines.push("**Configuration:**");
1630
- lines.push(` Poll Interval: ${status.config.pollIntervalMs / 1e3}s`);
1631
- lines.push(` Max Parallel: ${status.config.maxParallel}`);
1632
- lines.push(` Working Directory: ${status.config.workingDirectory}`);
1633
- }
1634
1689
  return {
1635
- content: [{ type: "text", text: lines.join("\n") }]
1690
+ content: [{ type: "text", text: `\u2139\uFE0F ${result.message ?? "No orchestrator status available"}` }]
1636
1691
  };
1637
1692
  } catch (error) {
1638
1693
  const errorMessage = error instanceof Error ? error.message : "Unknown error";
1639
1694
  console.error(`[MCP] tickets_yolo_status error:`, error);
1640
1695
  return {
1641
- content: [{ type: "text", text: `Error getting watcher status: ${errorMessage}` }],
1696
+ content: [{ type: "text", text: `Error getting orchestrator status: ${errorMessage}` }],
1642
1697
  isError: true
1643
1698
  };
1644
1699
  }