@promptprojectmanager/mcp-server 4.5.7 → 4.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/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,282 @@ 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
+ ## \u26A0\uFE0F CRITICAL RULE: STRICT SUB-AGENT MODE
142
+
143
+ **You are the ORCHESTRATOR, not the executor.**
144
+
145
+ You MUST NEVER execute ticket work directly. ALL ticket execution MUST go through Task sub-agents.
146
+
147
+ Your ONLY jobs are:
148
+ 1. Poll for YOLO tickets
149
+ 2. Claim tickets (transition to "working" status)
150
+ 3. Spawn Task sub-agents to execute them
151
+ 4. Report results when sub-agents complete
152
+
153
+ **FORBIDDEN**: Doing the ticket work yourself (no web searches, no code writing, no file edits for tickets)
154
+ **REQUIRED**: Always use the Task tool to spawn a sub-agent for EVERY ticket
155
+
156
+ ---
157
+
158
+ ## Current Configuration
159
+ | Setting | Value |
160
+ |---------|-------|
161
+ | Poll Interval | ${pollIntervalSec}s |
162
+ | Max Parallel | ${config.maxParallel} |
163
+ | Ticket Timeout | ${Math.round(config.ticketTimeout / 1e3 / 60)} minutes |
164
+ | Working Directory | ${config.workingDirectory} |
165
+
166
+ ## Pending YOLO Tickets
167
+ ${pendingTickets.length > 0 ? formatPendingTickets(pendingTickets) : "_No tickets with YOLO flag currently in queue._"}
168
+
169
+ ${pendingTickets.length > 0 ? `
170
+ ## \u{1F4E5} Execute These Tickets NOW
171
+
172
+ For EACH pending ticket, you MUST:
173
+
174
+ ### Step 1: Claim the ticket
175
+ \`\`\`
176
+ tickets_work with ticketSlug: "{slug}"
177
+ \`\`\`
178
+
179
+ ### Step 2: Spawn a Task sub-agent (REQUIRED - DO NOT SKIP)
180
+ \`\`\`
181
+ Task tool with:
182
+ description: "Execute YOLO ticket {slug}"
183
+ subagent_type: "general-purpose"
184
+ prompt: [use the template below]
185
+ run_in_background: ${config.maxParallel > 1 ? "true" : "false"}
186
+ \`\`\`
187
+
188
+ ### Sub-Agent Prompt Template (copy this exactly):
189
+
190
+ \`\`\`
191
+ You are executing a YOLO ticket autonomously.
192
+
193
+ ## Ticket: {ticketSlug}
194
+
195
+ {ticketContent}
196
+
197
+ ---
198
+
199
+ ## Your Instructions
200
+
201
+ 1. Execute the task described above
202
+ 2. When complete, close the ticket: tickets_close with ticketSlug: "{ticketSlug}"
203
+ 3. If blocked, update the ticket: tickets_update with your findings
204
+ 4. Return a brief summary of what you accomplished
205
+ \`\`\`
206
+
207
+ ### Step 3: Report the result
208
+ After each sub-agent completes, report:
209
+ - \u2705 Success: what was done
210
+ - \u274C Failure: what went wrong
211
+
212
+ ---
213
+
214
+ **START NOW**: Claim and spawn sub-agents for all ${pendingTickets.length} pending ticket(s) above.
215
+ ` : `
216
+ ## \u{1F504} No Tickets Ready
217
+
218
+ No YOLO tickets are currently pending. Options:
219
+ - Say **"poll"** to check for new tickets
220
+ - Say **"stop"** to exit orchestrator mode
221
+ `}
222
+
223
+ ## Commands
224
+ | Command | Action |
225
+ |---------|--------|
226
+ | "poll" / "check" | Refresh the ticket list |
227
+ | "status" | Show orchestrator status |
228
+ | "stop" / "exit" | Stop the orchestrator |
229
+
230
+ ---
231
+
232
+ _Orchestrator started at ${(/* @__PURE__ */ new Date()).toISOString()}_`;
233
+ }
234
+ function formatPendingTickets(tickets) {
235
+ return tickets.map((t, i) => {
236
+ const num = t.ticketNumber ? `#${t.ticketNumber}` : "";
237
+ const title = t.slug;
238
+ const preview = t.content.slice(0, 150).replace(/\n/g, " ");
239
+ return `### ${i + 1}. ${num} ${title}
240
+ > ${preview}${t.content.length > 150 ? "..." : ""}`;
241
+ }).join("\n\n");
242
+ }
243
+ function formatOrchestratorStatus(status, pendingTickets) {
244
+ if (!status) {
245
+ return `# YOLO Orchestrator Status
246
+
247
+ **State**: Not started
248
+
249
+ _Use \`tickets_yolo_start\` to begin orchestration._`;
250
+ }
251
+ const lines = [
252
+ "# YOLO Orchestrator Status",
253
+ "",
254
+ `**State**: ${status.state}`,
255
+ `**Project**: ${status.projectSlug}`
256
+ ];
257
+ if (status.startedAt) {
258
+ lines.push(`**Started**: ${status.startedAt}`);
259
+ }
260
+ if (status.lastPollAt) {
261
+ lines.push(`**Last Poll**: ${status.lastPollAt}`);
262
+ }
263
+ lines.push(`**Tickets Processed**: ${status.ticketsProcessed}`);
264
+ if (status.currentlyExecuting && status.currentlyExecuting.length > 0) {
265
+ lines.push("");
266
+ lines.push("## Currently Executing (Sub-Agents)");
267
+ for (const exec of status.currentlyExecuting) {
268
+ const num = exec.ticketNumber ? `#${exec.ticketNumber}` : "";
269
+ const elapsed = getElapsedTime(exec.startedAt);
270
+ lines.push(`- **${num} ${exec.ticketSlug}** (${elapsed})`);
271
+ }
272
+ }
273
+ lines.push("");
274
+ lines.push("## Pending YOLO Tickets");
275
+ if (pendingTickets.length > 0) {
276
+ lines.push("");
277
+ lines.push("**Action Required**: Spawn Task sub-agents for these tickets:");
278
+ lines.push("");
279
+ for (const ticket of pendingTickets) {
280
+ const num = ticket.ticketNumber ? `#${ticket.ticketNumber}` : "";
281
+ lines.push(`- **${num} ${ticket.slug}**`);
282
+ }
283
+ } else {
284
+ lines.push("_No tickets pending_");
285
+ }
286
+ return lines.join("\n");
287
+ }
288
+ function getElapsedTime(startedAt) {
289
+ const start = new Date(startedAt).getTime();
290
+ const elapsed = Date.now() - start;
291
+ const minutes = Math.floor(elapsed / 1e3 / 60);
292
+ const seconds = Math.floor(elapsed / 1e3 % 60);
293
+ if (minutes > 0) {
294
+ return `${minutes}m ${seconds}s`;
295
+ }
296
+ return `${seconds}s`;
297
+ }
298
+
114
299
  // 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) {
300
+ function startOrchestrator(baseConfig, args, pendingTickets) {
120
301
  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 = {
302
+ const orchestratorConfig = {
133
303
  projectSlug: baseConfig.projectSlug,
134
- projectToken: baseConfig.projectToken,
135
- convexUrl: baseConfig.convexUrl,
136
- workingDirectory,
137
304
  pollIntervalMs: args?.pollIntervalMs ?? 3e4,
138
305
  maxParallel: args?.maxParallel ?? 1,
139
306
  ticketTimeout: args?.ticketTimeout ?? 18e5,
140
- enableNotifications: args?.enableNotifications ?? true
307
+ workingDirectory
141
308
  };
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
- };
309
+ getWatcherDir(workingDirectory);
310
+ const initialStatus = {
311
+ state: "running",
312
+ projectSlug: baseConfig.projectSlug,
313
+ startedAt: (/* @__PURE__ */ new Date()).toISOString(),
314
+ ticketsProcessed: 0,
315
+ currentlyExecuting: [],
316
+ config: {
317
+ projectSlug: baseConfig.projectSlug,
318
+ convexUrl: baseConfig.convexUrl,
319
+ pollIntervalMs: orchestratorConfig.pollIntervalMs,
320
+ maxParallel: orchestratorConfig.maxParallel,
321
+ ticketTimeout: orchestratorConfig.ticketTimeout,
322
+ enableNotifications: args?.enableNotifications ?? true,
323
+ workingDirectory
182
324
  }
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
- }
325
+ };
326
+ writeStatus(workingDirectory, initialStatus);
327
+ const instructions = buildOrchestratorInstructions(orchestratorConfig, pendingTickets);
328
+ return {
329
+ success: true,
330
+ message: "Orchestrator started",
331
+ instructions,
332
+ config: initialStatus.config,
333
+ alreadyRunning: false
334
+ };
190
335
  }
191
- async function stopWatcher(workingDirectory) {
192
- const pid = readPid(workingDirectory);
193
- if (!pid) {
336
+ function stopOrchestrator(workingDirectory) {
337
+ const status = readStatus(workingDirectory);
338
+ if (!status) {
194
339
  return {
195
340
  success: true,
196
- message: "No watcher is running",
341
+ message: "No orchestrator session found",
197
342
  wasRunning: false
198
343
  };
199
344
  }
200
- if (!isProcessRunning(pid)) {
201
- removePid(workingDirectory);
202
- const status = readStatus(workingDirectory);
203
- if (status) {
204
- writeStatus(workingDirectory, { ...status, state: "stopped" });
205
- }
345
+ if (status.state !== "running") {
206
346
  return {
207
347
  success: true,
208
- message: "Watcher was not running (cleaned up stale PID file)",
348
+ message: `Orchestrator was already ${status.state}`,
209
349
  wasRunning: false
210
350
  };
211
351
  }
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
- }
352
+ writeStatus(workingDirectory, {
353
+ ...status,
354
+ state: "stopped"
355
+ });
356
+ return {
357
+ success: true,
358
+ message: "Orchestrator stopped",
359
+ wasRunning: true
360
+ };
245
361
  }
246
- function getWatcherStatus(workingDirectory) {
362
+ function getOrchestratorStatus(workingDirectory, pendingTickets) {
247
363
  const status = readStatus(workingDirectory);
364
+ const formattedStatus = formatOrchestratorStatus(status ?? null, pendingTickets);
248
365
  if (!status) {
249
366
  return {
250
367
  success: true,
251
- message: "No watcher has been started for this project"
368
+ message: "No orchestrator session has been started for this project",
369
+ pendingTickets,
370
+ formattedStatus
252
371
  };
253
372
  }
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
373
  return {
267
374
  success: true,
268
- status
375
+ status,
376
+ pendingTickets,
377
+ formattedStatus
269
378
  };
270
379
  }
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
380
 
277
381
  // src/prompt-builder.ts
278
382
  var AmbiguousPromptError = class extends Error {
@@ -415,25 +519,25 @@ async function startServer(config, convexClientRaw) {
415
519
  projectSlug,
416
520
  type: "update"
417
521
  },
418
- // YOLO watcher tools - autonomous ticket execution
522
+ // YOLO orchestrator tools - sub-agent based autonomous ticket execution
419
523
  {
420
524
  name: `tickets_yolo_start`,
421
525
  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`,
526
+ slashDescription: `Start YOLO orchestrator for autonomous ticket execution`,
423
527
  projectSlug,
424
528
  type: "yolo_start"
425
529
  },
426
530
  {
427
531
  name: `tickets_yolo_stop`,
428
532
  description: `Stop the YOLO ticket watcher for "${projectSlug}"`,
429
- slashDescription: `Stop the YOLO watcher daemon`,
533
+ slashDescription: `Stop the YOLO orchestrator`,
430
534
  projectSlug,
431
535
  type: "yolo_stop"
432
536
  },
433
537
  {
434
538
  name: `tickets_yolo_status`,
435
539
  description: `Get YOLO watcher status for "${projectSlug}"`,
436
- slashDescription: `Check YOLO watcher status and metrics`,
540
+ slashDescription: `Check YOLO orchestrator status and pending tickets`,
437
541
  projectSlug,
438
542
  type: "yolo_status"
439
543
  }
@@ -1520,33 +1624,31 @@ _Ticket content has been appended with your update._`
1520
1624
  const args = parseWatcherStartArgs(request.params.arguments);
1521
1625
  const workingDirectory = args.workingDirectory ?? process.cwd();
1522
1626
  try {
1523
- const result = await startWatcher(
1627
+ let pendingTickets = [];
1628
+ try {
1629
+ pendingTickets = await convexClient.query(
1630
+ "mcp_tickets:listYoloTickets",
1631
+ {
1632
+ projectToken: config.projectToken,
1633
+ projectSlug: ticketTool.projectSlug
1634
+ }
1635
+ );
1636
+ } catch (queryError) {
1637
+ console.error(`[MCP] Failed to query YOLO tickets:`, queryError);
1638
+ }
1639
+ const result = startOrchestrator(
1524
1640
  {
1525
1641
  projectSlug: ticketTool.projectSlug,
1526
1642
  projectToken: config.projectToken,
1527
1643
  convexUrl: config.convexUrl,
1528
1644
  workingDirectory
1529
1645
  },
1530
- args
1646
+ args,
1647
+ pendingTickets
1531
1648
  );
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._");
1649
+ if (result.success && result.instructions) {
1548
1650
  return {
1549
- content: [{ type: "text", text: statusLines.join("\n") }]
1651
+ content: [{ type: "text", text: result.instructions }]
1550
1652
  };
1551
1653
  } else {
1552
1654
  return {
@@ -1558,19 +1660,19 @@ _Ticket content has been appended with your update._`
1558
1660
  const errorMessage = error instanceof Error ? error.message : "Unknown error";
1559
1661
  console.error(`[MCP] tickets_yolo_start error:`, error);
1560
1662
  return {
1561
- content: [{ type: "text", text: `Error starting watcher: ${errorMessage}` }],
1663
+ content: [{ type: "text", text: `Error starting orchestrator: ${errorMessage}` }],
1562
1664
  isError: true
1563
1665
  };
1564
1666
  }
1565
1667
  } else if (ticketTool.type === "yolo_stop") {
1566
1668
  const workingDirectory = process.cwd();
1567
1669
  try {
1568
- const result = await stopWatcher(workingDirectory);
1670
+ const result = stopOrchestrator(workingDirectory);
1569
1671
  if (result.success) {
1570
1672
  return {
1571
1673
  content: [{
1572
1674
  type: "text",
1573
- text: result.wasRunning ? `\u2705 Watcher stopped successfully` : `\u2139\uFE0F ${result.message}`
1675
+ text: result.wasRunning ? `\u2705 Orchestrator stopped. You can stop processing tickets now.` : `\u2139\uFE0F ${result.message}`
1574
1676
  }]
1575
1677
  };
1576
1678
  } else {
@@ -1583,62 +1685,39 @@ _Ticket content has been appended with your update._`
1583
1685
  const errorMessage = error instanceof Error ? error.message : "Unknown error";
1584
1686
  console.error(`[MCP] tickets_yolo_stop error:`, error);
1585
1687
  return {
1586
- content: [{ type: "text", text: `Error stopping watcher: ${errorMessage}` }],
1688
+ content: [{ type: "text", text: `Error stopping orchestrator: ${errorMessage}` }],
1587
1689
  isError: true
1588
1690
  };
1589
1691
  }
1590
1692
  } else if (ticketTool.type === "yolo_status") {
1591
1693
  const workingDirectory = process.cwd();
1592
1694
  try {
1593
- const result = getWatcherStatus(workingDirectory);
1594
- if (!result.status) {
1695
+ let pendingTickets = [];
1696
+ try {
1697
+ pendingTickets = await convexClient.query(
1698
+ "mcp_tickets:listYoloTickets",
1699
+ {
1700
+ projectToken: config.projectToken,
1701
+ projectSlug: ticketTool.projectSlug
1702
+ }
1703
+ );
1704
+ } catch (queryError) {
1705
+ console.error(`[MCP] Failed to query YOLO tickets:`, queryError);
1706
+ }
1707
+ const result = getOrchestratorStatus(workingDirectory, pendingTickets);
1708
+ if (result.formattedStatus) {
1595
1709
  return {
1596
- content: [{ type: "text", text: `\u2139\uFE0F ${result.message ?? "No watcher status available"}` }]
1710
+ content: [{ type: "text", text: result.formattedStatus }]
1597
1711
  };
1598
1712
  }
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
1713
  return {
1635
- content: [{ type: "text", text: lines.join("\n") }]
1714
+ content: [{ type: "text", text: `\u2139\uFE0F ${result.message ?? "No orchestrator status available"}` }]
1636
1715
  };
1637
1716
  } catch (error) {
1638
1717
  const errorMessage = error instanceof Error ? error.message : "Unknown error";
1639
1718
  console.error(`[MCP] tickets_yolo_status error:`, error);
1640
1719
  return {
1641
- content: [{ type: "text", text: `Error getting watcher status: ${errorMessage}` }],
1720
+ content: [{ type: "text", text: `Error getting orchestrator status: ${errorMessage}` }],
1642
1721
  isError: true
1643
1722
  };
1644
1723
  }