@promptprojectmanager/mcp-server 2.9.0 → 3.0.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 +152 -68
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -31,13 +31,6 @@ function buildPromptName(prompt) {
|
|
|
31
31
|
const promptSlug = sanitizeForMcp(prompt.slug || "unknown") || "unknown";
|
|
32
32
|
return `${workspace}:${promptSlug}`.trim();
|
|
33
33
|
}
|
|
34
|
-
function buildPromptSchema(prompt) {
|
|
35
|
-
return {
|
|
36
|
-
name: buildPromptName(prompt),
|
|
37
|
-
description: prompt.description || `Prompt: ${prompt.name}`,
|
|
38
|
-
arguments: []
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
34
|
function buildPromptHandler(prompt, config, convexClient) {
|
|
42
35
|
return async () => {
|
|
43
36
|
let flattenedPrompt = prompt.flattenedPrompt;
|
|
@@ -108,6 +101,7 @@ This is a utility tool. Call it directly as a tool to list all available prompts
|
|
|
108
101
|
|
|
109
102
|
Example: Use the \`system:prompts\` tool with optional \`search\` parameter to filter results.`
|
|
110
103
|
}
|
|
104
|
+
// Note: run_prompt is now workspace-scoped (see dynamicRunPromptTools below)
|
|
111
105
|
];
|
|
112
106
|
async function startServer(config, convexClient) {
|
|
113
107
|
console.error("[MCP] Validating API key...");
|
|
@@ -180,6 +174,15 @@ async function startServer(config, convexClient) {
|
|
|
180
174
|
});
|
|
181
175
|
}
|
|
182
176
|
console.error(`[MCP] Registering ${dynamicTicketTools.length} ticket tools for ${workspaceSlugs.size} workspace(s)...`);
|
|
177
|
+
const dynamicRunPromptTools = [];
|
|
178
|
+
for (const workspaceSlug of workspaceSlugs) {
|
|
179
|
+
dynamicRunPromptTools.push({
|
|
180
|
+
name: `${workspaceSlug}:run_prompt`,
|
|
181
|
+
description: `Execute a prompt from the "${workspaceSlug}" workspace by slug. Use system:prompts to list available prompts.`,
|
|
182
|
+
workspaceSlug
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
console.error(`[MCP] Registering ${dynamicRunPromptTools.length} run_prompt tools for ${workspaceSlugs.size} workspace(s)...`);
|
|
183
186
|
const promptNames = /* @__PURE__ */ new Set();
|
|
184
187
|
const duplicates = [];
|
|
185
188
|
validPrompts.forEach((p) => {
|
|
@@ -197,7 +200,7 @@ async function startServer(config, convexClient) {
|
|
|
197
200
|
const server = new Server(
|
|
198
201
|
{
|
|
199
202
|
name: "ppm-mcp-server",
|
|
200
|
-
version: "
|
|
203
|
+
version: "3.0.1"
|
|
201
204
|
},
|
|
202
205
|
{
|
|
203
206
|
capabilities: {
|
|
@@ -207,9 +210,6 @@ async function startServer(config, convexClient) {
|
|
|
207
210
|
}
|
|
208
211
|
);
|
|
209
212
|
server.setRequestHandler(ListPromptsRequestSchema, async () => {
|
|
210
|
-
const uniquePrompts = Array.from(
|
|
211
|
-
new Map(validPrompts.map((p) => [buildPromptName(p), p])).values()
|
|
212
|
-
);
|
|
213
213
|
const systemPromptSchemas = SYSTEM_TOOLS.filter((st) => st.isSlashCommand).map((st) => ({
|
|
214
214
|
name: st.name,
|
|
215
215
|
description: st.description
|
|
@@ -218,11 +218,15 @@ async function startServer(config, convexClient) {
|
|
|
218
218
|
name: tt.name,
|
|
219
219
|
description: tt.description
|
|
220
220
|
}));
|
|
221
|
+
const runPromptSchemas = dynamicRunPromptTools.map((rp) => ({
|
|
222
|
+
name: rp.name,
|
|
223
|
+
description: rp.description
|
|
224
|
+
}));
|
|
221
225
|
return {
|
|
222
226
|
prompts: [
|
|
223
227
|
...systemPromptSchemas,
|
|
224
228
|
...ticketPromptSchemas,
|
|
225
|
-
...
|
|
229
|
+
...runPromptSchemas
|
|
226
230
|
]
|
|
227
231
|
};
|
|
228
232
|
});
|
|
@@ -325,17 +329,49 @@ Call the \`${ticketTool.name}\` tool with the ticket number/slug and your messag
|
|
|
325
329
|
]
|
|
326
330
|
};
|
|
327
331
|
}
|
|
328
|
-
const
|
|
329
|
-
|
|
330
|
-
|
|
332
|
+
const runPromptTool = dynamicRunPromptTools.find((rp) => rp.name === promptName);
|
|
333
|
+
const runPromptMatch = promptName.match(/^(.+):run_prompt\s+(.+)$/);
|
|
334
|
+
if (runPromptTool || runPromptMatch) {
|
|
335
|
+
let promptContent;
|
|
336
|
+
let description;
|
|
337
|
+
if (runPromptMatch) {
|
|
338
|
+
const workspaceSlug = runPromptMatch[1];
|
|
339
|
+
const promptSlug = runPromptMatch[2].trim();
|
|
340
|
+
description = `Execute prompt "${promptSlug}" from "${workspaceSlug}"`;
|
|
341
|
+
promptContent = `Execute the "${promptSlug}" prompt from the "${workspaceSlug}" workspace.
|
|
342
|
+
|
|
343
|
+
Call the \`${workspaceSlug}:run_prompt\` tool with slug: "${promptSlug}".`;
|
|
344
|
+
} else {
|
|
345
|
+
description = runPromptTool.description;
|
|
346
|
+
promptContent = `Execute a prompt from the "${runPromptTool.workspaceSlug}" workspace.
|
|
347
|
+
|
|
348
|
+
## Usage
|
|
349
|
+
Call the \`${runPromptTool.name}\` tool with the prompt slug.
|
|
350
|
+
|
|
351
|
+
## Available Prompts
|
|
352
|
+
Use \`system:prompts\` to list all available prompts in this workspace.
|
|
353
|
+
|
|
354
|
+
## Example
|
|
355
|
+
/ppm:${runPromptTool.workspaceSlug}:run_prompt code-review
|
|
356
|
+
|
|
357
|
+
This will execute the "code-review" prompt.`;
|
|
358
|
+
}
|
|
359
|
+
return {
|
|
360
|
+
description,
|
|
361
|
+
messages: [
|
|
362
|
+
{
|
|
363
|
+
role: "user",
|
|
364
|
+
content: {
|
|
365
|
+
type: "text",
|
|
366
|
+
text: promptContent
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
]
|
|
370
|
+
};
|
|
331
371
|
}
|
|
332
|
-
|
|
333
|
-
return await handler();
|
|
372
|
+
throw new Error(`Unknown prompt: ${promptName}. Use workspace:run_prompt to execute prompts.`);
|
|
334
373
|
});
|
|
335
374
|
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
336
|
-
const uniquePrompts = Array.from(
|
|
337
|
-
new Map(validPrompts.map((p) => [buildPromptName(p), p])).values()
|
|
338
|
-
);
|
|
339
375
|
const tools = [
|
|
340
376
|
// System tools with full input schemas
|
|
341
377
|
...SYSTEM_TOOLS.map((st) => ({
|
|
@@ -418,14 +454,19 @@ Call the \`${ticketTool.name}\` tool with the ticket number/slug and your messag
|
|
|
418
454
|
inputSchema
|
|
419
455
|
};
|
|
420
456
|
}),
|
|
421
|
-
//
|
|
422
|
-
...
|
|
423
|
-
name:
|
|
424
|
-
description:
|
|
457
|
+
// Dynamic run_prompt tools per workspace
|
|
458
|
+
...dynamicRunPromptTools.map((rp) => ({
|
|
459
|
+
name: rp.name,
|
|
460
|
+
description: rp.description,
|
|
425
461
|
inputSchema: {
|
|
426
462
|
type: "object",
|
|
427
|
-
properties: {
|
|
428
|
-
|
|
463
|
+
properties: {
|
|
464
|
+
slug: {
|
|
465
|
+
type: "string",
|
|
466
|
+
description: "Prompt slug to execute (e.g., 'code-review', 'plan')"
|
|
467
|
+
}
|
|
468
|
+
},
|
|
469
|
+
required: ["slug"]
|
|
429
470
|
}
|
|
430
471
|
}))
|
|
431
472
|
];
|
|
@@ -433,6 +474,63 @@ Call the \`${ticketTool.name}\` tool with the ticket number/slug and your messag
|
|
|
433
474
|
});
|
|
434
475
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
435
476
|
const toolName = request.params.name;
|
|
477
|
+
const runPromptTool = dynamicRunPromptTools.find((rp) => rp.name === toolName);
|
|
478
|
+
if (runPromptTool) {
|
|
479
|
+
const promptSlug = request.params.arguments?.slug;
|
|
480
|
+
if (!promptSlug) {
|
|
481
|
+
return {
|
|
482
|
+
content: [
|
|
483
|
+
{
|
|
484
|
+
type: "text",
|
|
485
|
+
text: `Error: Missing 'slug' parameter. Provide prompt slug (e.g., 'code-review', 'plan').
|
|
486
|
+
|
|
487
|
+
Use \`system:prompts\` to list available prompts in "${runPromptTool.workspaceSlug}".`
|
|
488
|
+
}
|
|
489
|
+
],
|
|
490
|
+
isError: true
|
|
491
|
+
};
|
|
492
|
+
}
|
|
493
|
+
const fullPromptName = `${runPromptTool.workspaceSlug}:${promptSlug}`;
|
|
494
|
+
const prompt = validPrompts.find((p) => buildPromptName(p) === fullPromptName);
|
|
495
|
+
if (!prompt) {
|
|
496
|
+
return {
|
|
497
|
+
content: [
|
|
498
|
+
{
|
|
499
|
+
type: "text",
|
|
500
|
+
text: `Error: Unknown prompt "${promptSlug}" in workspace "${runPromptTool.workspaceSlug}".
|
|
501
|
+
|
|
502
|
+
Use \`system:prompts\` to list available prompts.`
|
|
503
|
+
}
|
|
504
|
+
],
|
|
505
|
+
isError: true
|
|
506
|
+
};
|
|
507
|
+
}
|
|
508
|
+
try {
|
|
509
|
+
const handler = buildPromptHandler(prompt, config, convexClient);
|
|
510
|
+
const result = await handler();
|
|
511
|
+
const promptText = result.messages.map((msg) => typeof msg.content === "string" ? msg.content : msg.content.text).join("\n\n");
|
|
512
|
+
return {
|
|
513
|
+
content: [
|
|
514
|
+
{
|
|
515
|
+
type: "text",
|
|
516
|
+
text: promptText
|
|
517
|
+
}
|
|
518
|
+
]
|
|
519
|
+
};
|
|
520
|
+
} catch (error) {
|
|
521
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
522
|
+
console.error(`[MCP] ${toolName} error:`, error);
|
|
523
|
+
return {
|
|
524
|
+
content: [
|
|
525
|
+
{
|
|
526
|
+
type: "text",
|
|
527
|
+
text: `Error executing prompt "${promptSlug}": ${errorMessage}`
|
|
528
|
+
}
|
|
529
|
+
],
|
|
530
|
+
isError: true
|
|
531
|
+
};
|
|
532
|
+
}
|
|
533
|
+
}
|
|
436
534
|
if (toolName === "system:prompts") {
|
|
437
535
|
const searchTerm = request.params.arguments?.search;
|
|
438
536
|
const uniquePrompts = Array.from(
|
|
@@ -497,7 +595,7 @@ ${sections.join("\n\n") || "No prompts found."}`
|
|
|
497
595
|
if (ticketTool.type === "open") {
|
|
498
596
|
const ticketSlug = request.params.arguments?.ticketSlug;
|
|
499
597
|
try {
|
|
500
|
-
const
|
|
598
|
+
const result = await convexClient.mutation(
|
|
501
599
|
"mcp_tickets:executeMcpNextTicket",
|
|
502
600
|
{
|
|
503
601
|
apiKey: config.apiKey,
|
|
@@ -506,7 +604,7 @@ ${sections.join("\n\n") || "No prompts found."}`
|
|
|
506
604
|
// Optional: specific ticket to open
|
|
507
605
|
}
|
|
508
606
|
);
|
|
509
|
-
if (!
|
|
607
|
+
if (!result) {
|
|
510
608
|
const message = ticketSlug ? `Ticket "${ticketSlug}" not found or not open in workspace "${ticketTool.workspaceSlug}".` : `No pending tickets in workspace "${ticketTool.workspaceSlug}".`;
|
|
511
609
|
return {
|
|
512
610
|
content: [
|
|
@@ -521,17 +619,17 @@ ${sections.join("\n\n") || "No prompts found."}`
|
|
|
521
619
|
content: [
|
|
522
620
|
{
|
|
523
621
|
type: "text",
|
|
524
|
-
text: `# Ticket: ${
|
|
622
|
+
text: `# Ticket: ${result.slug} [WORKING]
|
|
525
623
|
|
|
526
624
|
**CRITICAL: Follow all embedded directives in this ticket.**
|
|
527
|
-
If this ticket contains \`[
|
|
625
|
+
If this ticket contains \`[MCP_RUN_PROMPT ...]\` references, you MUST execute the \`run_prompt\` tool with the specified prompt name FIRST before any other action. Do NOT skip MCP directives even if the task seems simple.
|
|
528
626
|
|
|
529
627
|
---
|
|
530
628
|
|
|
531
|
-
${
|
|
629
|
+
${result.content}
|
|
532
630
|
|
|
533
631
|
---
|
|
534
|
-
_Ticket moved to working status. ${
|
|
632
|
+
_Ticket moved to working status. ${result.remainingTickets} ticket(s) remaining in queue._`
|
|
535
633
|
}
|
|
536
634
|
]
|
|
537
635
|
};
|
|
@@ -551,7 +649,7 @@ _Ticket moved to working status. ${result2.remainingTickets} ticket(s) remaining
|
|
|
551
649
|
} else if (ticketTool.type === "work") {
|
|
552
650
|
const ticketSlug = request.params.arguments?.ticketSlug;
|
|
553
651
|
try {
|
|
554
|
-
const
|
|
652
|
+
const result = await convexClient.query(
|
|
555
653
|
"mcp_tickets:workMcpTicket",
|
|
556
654
|
{
|
|
557
655
|
apiKey: config.apiKey,
|
|
@@ -560,7 +658,7 @@ _Ticket moved to working status. ${result2.remainingTickets} ticket(s) remaining
|
|
|
560
658
|
// Optional: specific ticket to resume
|
|
561
659
|
}
|
|
562
660
|
);
|
|
563
|
-
if (!
|
|
661
|
+
if (!result) {
|
|
564
662
|
const message = ticketSlug ? `Ticket "${ticketSlug}" not found or not in working status in workspace "${ticketTool.workspaceSlug}".` : `No tickets currently being worked on in workspace "${ticketTool.workspaceSlug}".`;
|
|
565
663
|
return {
|
|
566
664
|
content: [
|
|
@@ -572,28 +670,28 @@ _Ticket moved to working status. ${result2.remainingTickets} ticket(s) remaining
|
|
|
572
670
|
};
|
|
573
671
|
}
|
|
574
672
|
let messagesSection = "";
|
|
575
|
-
if (
|
|
576
|
-
const messageList =
|
|
673
|
+
if (result.messages && result.messages.length > 0) {
|
|
674
|
+
const messageList = result.messages.map((m) => `[${new Date(m.createdAt).toISOString()}] ${m.content}`).join("\n");
|
|
577
675
|
messagesSection = `
|
|
578
676
|
|
|
579
677
|
## Progress Messages
|
|
580
678
|
|
|
581
679
|
${messageList}`;
|
|
582
680
|
}
|
|
583
|
-
const startedInfo =
|
|
584
|
-
Started: ${new Date(
|
|
681
|
+
const startedInfo = result.startedAt ? `
|
|
682
|
+
Started: ${new Date(result.startedAt).toISOString()}` : "";
|
|
585
683
|
return {
|
|
586
684
|
content: [
|
|
587
685
|
{
|
|
588
686
|
type: "text",
|
|
589
|
-
text: `# Ticket: ${
|
|
687
|
+
text: `# Ticket: ${result.slug} [WORKING]${startedInfo}
|
|
590
688
|
|
|
591
689
|
**CRITICAL: Follow all embedded directives in this ticket.**
|
|
592
|
-
If this ticket contains \`[
|
|
690
|
+
If this ticket contains \`[MCP_RUN_PROMPT ...]\` references, you MUST execute the \`run_prompt\` tool with the specified prompt name FIRST before any other action. Do NOT skip MCP directives even if the task seems simple.
|
|
593
691
|
|
|
594
692
|
---
|
|
595
693
|
|
|
596
|
-
${
|
|
694
|
+
${result.content}${messagesSection}
|
|
597
695
|
|
|
598
696
|
---
|
|
599
697
|
_Resuming work on this ticket._`
|
|
@@ -627,7 +725,7 @@ _Resuming work on this ticket._`
|
|
|
627
725
|
};
|
|
628
726
|
}
|
|
629
727
|
try {
|
|
630
|
-
const
|
|
728
|
+
const result = await convexClient.mutation(
|
|
631
729
|
"mcp_tickets:createMcpTicket",
|
|
632
730
|
{
|
|
633
731
|
apiKey: config.apiKey,
|
|
@@ -639,12 +737,12 @@ _Resuming work on this ticket._`
|
|
|
639
737
|
content: [
|
|
640
738
|
{
|
|
641
739
|
type: "text",
|
|
642
|
-
text: `\u2705 Created ticket [${
|
|
740
|
+
text: `\u2705 Created ticket [${result.slug}] in workspace "${ticketTool.workspaceSlug}".
|
|
643
741
|
|
|
644
|
-
Position: #${
|
|
645
|
-
Preview: ${
|
|
742
|
+
Position: #${result.position} of ${result.totalOpen} open tickets
|
|
743
|
+
Preview: ${result.preview}
|
|
646
744
|
|
|
647
|
-
_Note: If this ticket contains \`[
|
|
745
|
+
_Note: If this ticket contains \`[MCP_RUN_PROMPT ...]\` directives, they will be mandatory when opened._`
|
|
648
746
|
}
|
|
649
747
|
]
|
|
650
748
|
};
|
|
@@ -675,7 +773,7 @@ _Note: If this ticket contains \`[MCP_*]\` directives, they will be mandatory wh
|
|
|
675
773
|
};
|
|
676
774
|
}
|
|
677
775
|
try {
|
|
678
|
-
const
|
|
776
|
+
const result = await convexClient.mutation(
|
|
679
777
|
"mcp_tickets:closeMcpTicket",
|
|
680
778
|
{
|
|
681
779
|
apiKey: config.apiKey,
|
|
@@ -687,11 +785,11 @@ _Note: If this ticket contains \`[MCP_*]\` directives, they will be mandatory wh
|
|
|
687
785
|
content: [
|
|
688
786
|
{
|
|
689
787
|
type: "text",
|
|
690
|
-
text: `\u2705 Ticket [${
|
|
788
|
+
text: `\u2705 Ticket [${result.slug}] closed in workspace "${ticketTool.workspaceSlug}".
|
|
691
789
|
|
|
692
|
-
Closed at: ${new Date(
|
|
790
|
+
Closed at: ${new Date(result.closedAt).toISOString()}
|
|
693
791
|
|
|
694
|
-
_Reminder: Ensure all embedded \`[
|
|
792
|
+
_Reminder: Ensure all embedded \`[MCP_RUN_PROMPT ...]\` directives were executed before closing._`
|
|
695
793
|
}
|
|
696
794
|
]
|
|
697
795
|
};
|
|
@@ -723,7 +821,7 @@ _Reminder: Ensure all embedded \`[MCP_*]\` directives were executed before closi
|
|
|
723
821
|
};
|
|
724
822
|
}
|
|
725
823
|
try {
|
|
726
|
-
const
|
|
824
|
+
const result = await convexClient.mutation(
|
|
727
825
|
"mcp_tickets:addMcpTicketMessage",
|
|
728
826
|
{
|
|
729
827
|
apiKey: config.apiKey,
|
|
@@ -736,9 +834,9 @@ _Reminder: Ensure all embedded \`[MCP_*]\` directives were executed before closi
|
|
|
736
834
|
content: [
|
|
737
835
|
{
|
|
738
836
|
type: "text",
|
|
739
|
-
text: `\u2705 Message added to ticket [${
|
|
837
|
+
text: `\u2705 Message added to ticket [${result.ticketSlug}].
|
|
740
838
|
|
|
741
|
-
Total messages: ${
|
|
839
|
+
Total messages: ${result.messageCount}`
|
|
742
840
|
}
|
|
743
841
|
]
|
|
744
842
|
};
|
|
@@ -757,21 +855,7 @@ Total messages: ${result2.messageCount}`
|
|
|
757
855
|
}
|
|
758
856
|
}
|
|
759
857
|
}
|
|
760
|
-
|
|
761
|
-
if (!prompt) {
|
|
762
|
-
throw new Error(`Unknown tool: ${toolName}`);
|
|
763
|
-
}
|
|
764
|
-
const handler = buildPromptHandler(prompt, config, convexClient);
|
|
765
|
-
const result = await handler();
|
|
766
|
-
const promptText = result.messages.map((msg) => typeof msg.content === "string" ? msg.content : msg.content.text).join("\n\n");
|
|
767
|
-
return {
|
|
768
|
-
content: [
|
|
769
|
-
{
|
|
770
|
-
type: "text",
|
|
771
|
-
text: promptText
|
|
772
|
-
}
|
|
773
|
-
]
|
|
774
|
-
};
|
|
858
|
+
throw new Error(`Unknown tool: ${toolName}. Use run_prompt to execute prompts by name.`);
|
|
775
859
|
});
|
|
776
860
|
const transport = new StdioServerTransport();
|
|
777
861
|
await server.connect(transport);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/convex-client.ts","../src/server.ts","../src/prompt-builder.ts"],"sourcesContent":["import minimist from \"minimist\";\nimport { createConvexClient } from \"./convex-client.js\";\nimport { startServer } from \"./server.js\";\nimport type { ServerConfig } from \"./types.js\";\n\n/**\n * Main entry point for the MCP server\n */\nasync function main() {\n try {\n // Parse CLI arguments\n const argv = minimist(process.argv.slice(2));\n const isDev = argv.dev === true;\n\n // Parse --workspaces CLI argument (Ticket 144)\n // Can be: --workspaces ws1,ws2 OR --workspaces ws1 --workspaces ws2 OR -w ws1,ws2\n const workspacesArg = argv.workspaces || argv.w;\n let selectedWorkspaces: string[] = [];\n if (workspacesArg) {\n if (Array.isArray(workspacesArg)) {\n // Multiple --workspaces flags: [\"ws1\", \"ws2\"]\n selectedWorkspaces = workspacesArg.flatMap((w: string) => String(w).split(','));\n } else {\n // Single --workspaces flag with comma-separated: \"ws1,ws2\"\n selectedWorkspaces = String(workspacesArg).split(',');\n }\n // Clean up whitespace\n selectedWorkspaces = selectedWorkspaces.map((s) => s.trim()).filter(Boolean);\n }\n\n // Check for API key (PPM_API_KEY with backward compatibility for THEPROMPTEDITOR_API_KEY)\n const apiKey = process.env.PPM_API_KEY || process.env.THEPROMPTEDITOR_API_KEY;\n if (!apiKey) {\n console.error(\n \"[MCP] ERROR: Missing PPM_API_KEY environment variable\"\n );\n console.error(\n \"[MCP] Please set your API key from Prompt Project Manager Settings page:\"\n );\n console.error(\"[MCP] export PPM_API_KEY=your_api_key_here\");\n process.exit(1);\n }\n\n // Create Convex client\n const convexClient = createConvexClient(isDev);\n const convexUrl = isDev\n ? \"https://hallowed-shrimp-344.convex.cloud\"\n : \"https://trustworthy-squirrel-735.convex.cloud\";\n\n // Build server config\n const config: ServerConfig = {\n apiKey,\n isDev,\n convexUrl,\n selectedWorkspaces, // Workspace slugs to filter (empty = all workspaces)\n };\n\n // Start server - this will keep the process alive via stdio transport\n await startServer(config, convexClient);\n\n // This line should never be reached if the promise in startServer never resolves\n console.error(\"[MCP] WARNING: startServer promise resolved unexpectedly!\");\n } catch (error) {\n console.error(\n \"[MCP] FATAL ERROR:\",\n error instanceof Error ? error.message : \"Unknown error\"\n );\n if (error instanceof Error && error.stack) {\n console.error(error.stack);\n }\n process.exit(1);\n }\n}\n\n// Handle graceful shutdown\nprocess.on(\"SIGINT\", () => {\n console.error(\"[MCP] Received SIGINT, shutting down gracefully...\");\n process.exit(0);\n});\n\nprocess.on(\"SIGTERM\", () => {\n console.error(\"[MCP] Received SIGTERM, shutting down gracefully...\");\n process.exit(0);\n});\n\nmain();\n","import { ConvexHttpClient } from \"convex/browser\";\n\nconst PROD_URL = \"https://trustworthy-squirrel-735.convex.cloud\";\nconst DEV_URL = \"https://hallowed-shrimp-344.convex.cloud\";\n\n/**\n * Create a Convex HTTP client for the appropriate deployment\n */\nexport function createConvexClient(isDev: boolean): ConvexHttpClient {\n const url = isDev ? DEV_URL : PROD_URL;\n return new ConvexHttpClient(url);\n}\n","import { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport {\n CallToolRequestSchema,\n GetPromptRequestSchema,\n ListPromptsRequestSchema,\n ListToolsRequestSchema,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport type { ConvexHttpClient } from \"convex/browser\";\nimport type { McpPrompt, ServerConfig } from \"./types.js\";\n\n/**\n * Result from executing the next ticket (Ticket 151: now moves to working status)\n */\ninterface ExecuteTicketResult {\n content: string | null;\n slug: string;\n status: string; // Ticket 151: \"working\" (no longer \"closed\")\n remainingTickets: number;\n}\n\n/**\n * Close ticket result (Ticket 151)\n */\ninterface CloseTicketResult {\n slug: string;\n status: string;\n closedAt: number;\n}\n\n/**\n * Message result (Ticket 151)\n */\ninterface AddMessageResult {\n ticketSlug: string;\n messageCount: number;\n createdAt: number;\n}\n\nimport { buildPromptHandler, buildPromptName, buildPromptSchema } from \"./prompt-builder.js\";\n\n/**\n * Built-in system tools\n */\nconst SYSTEM_TOOLS: {\n name: string;\n description: string;\n inputSchema: object;\n promptContent: string;\n isSlashCommand: boolean; // true = appears as /ppm:name, false = tool only\n}[] = [\n // Utility tool: /ppm:system:prompts\n {\n name: \"system:prompts\",\n description: \"List all available prompts from Prompt Project Manager\",\n inputSchema: {\n type: \"object\",\n properties: {\n search: {\n type: \"string\",\n description: \"Optional search term to filter prompts by name or description (case-insensitive)\",\n },\n },\n },\n isSlashCommand: true,\n promptContent: `# List Prompts\n\nThis is a utility tool. Call it directly as a tool to list all available prompts.\n\nExample: Use the \\`system:prompts\\` tool with optional \\`search\\` parameter to filter results.`,\n },\n];\n\n/**\n * Initialize and start the MCP server\n */\nexport async function startServer(\n config: ServerConfig,\n convexClient: ConvexHttpClient\n): Promise<void> {\n // Validate API key with Convex\n console.error(\"[MCP] Validating API key...\");\n const validation = await validateApiKey(convexClient, config.apiKey);\n if (!validation.valid) {\n throw new Error(`Invalid API key: ${validation.error}`);\n }\n console.error(`[MCP] API key validated for user: ${validation.userId}`);\n\n // Fetch prompts exposed to MCP (with optional workspace filter from CLI)\n console.error(\"[MCP] Fetching exposed prompts...\");\n const prompts = await fetchMcpPrompts(convexClient, config.apiKey, config.selectedWorkspaces);\n console.error(`[MCP] Found ${prompts.length} exposed prompts`);\n\n if (prompts.length === 0) {\n if (config.selectedWorkspaces.length > 0) {\n console.error(\n `[MCP] WARNING: No prompts found in workspaces: ${config.selectedWorkspaces.join(', ')}. Check that these workspace slugs exist and contain prompts.`\n );\n } else {\n console.error(\n \"[MCP] WARNING: No prompts found. Create some prompts in Prompt Project Manager to expose them via MCP.\"\n );\n }\n }\n\n // Filter out prompts with missing flattened content\n const validPrompts = prompts.filter((p) => {\n if (!p.flattenedPrompt) {\n console.error(\n `[MCP] WARNING: Skipping prompt \"${p.name}\" (${p.slug}) - missing flattened content. Re-save in ContextFS to regenerate.`\n );\n return false;\n }\n return true;\n });\n\n // Log workspace filtering info (Ticket 144)\n if (config.selectedWorkspaces.length > 0) {\n console.error(`[MCP] Workspace filter: ${config.selectedWorkspaces.join(', ')}`);\n } else {\n console.error(`[MCP] Workspace filter: ALL (no --workspaces specified)`);\n }\n console.error(`[MCP] Registering ${validPrompts.length} prompts...`);\n\n // Build dynamic ticket tools per workspace (Ticket 135, 149, 151, 153)\n // Streamlined command set: open, work, close, message, create\n const workspaceSlugs = new Set(validPrompts.map((p) => p.workspaceSlug).filter((s): s is string => !!s));\n const dynamicTicketTools: { name: string; description: string; workspaceSlug: string; type: 'open' | 'work' | 'close' | 'message' | 'create' }[] = [];\n\n for (const workspaceSlug of workspaceSlugs) {\n // Ticket 153: tickets:open (renamed from tickets:next)\n dynamicTicketTools.push({\n name: `${workspaceSlug}:tickets:open`,\n description: `Open the next ticket from the \"${workspaceSlug}\" workspace queue and move it to working status. Optionally specify a ticket number or slug.`,\n workspaceSlug,\n type: 'open',\n });\n // Ticket 153: tickets:work (context recovery for working tickets)\n dynamicTicketTools.push({\n name: `${workspaceSlug}:tickets:work`,\n description: `Resume work on a ticket in the \"${workspaceSlug}\" workspace. Returns ticket content and all progress messages for context recovery.`,\n workspaceSlug,\n type: 'work',\n });\n dynamicTicketTools.push({\n name: `${workspaceSlug}:tickets:close`,\n description: `Mark a working ticket as completed in the \"${workspaceSlug}\" workspace`,\n workspaceSlug,\n type: 'close',\n });\n dynamicTicketTools.push({\n name: `${workspaceSlug}:tickets:message`,\n description: `Add a progress message to a working or closed ticket in the \"${workspaceSlug}\" workspace`,\n workspaceSlug,\n type: 'message',\n });\n dynamicTicketTools.push({\n name: `${workspaceSlug}:tickets:create`,\n description: `Create a new ticket in the \"${workspaceSlug}\" workspace queue`,\n workspaceSlug,\n type: 'create',\n });\n }\n\n console.error(`[MCP] Registering ${dynamicTicketTools.length} ticket tools for ${workspaceSlugs.size} workspace(s)...`);\n\n // Check for duplicate prompt names\n const promptNames = new Set<string>();\n const duplicates: string[] = [];\n validPrompts.forEach((p) => {\n const name = buildPromptName(p);\n if (promptNames.has(name)) {\n duplicates.push(name);\n }\n promptNames.add(name);\n });\n\n if (duplicates.length > 0) {\n console.error(\n `[MCP] WARNING: Duplicate prompt names detected: ${duplicates.join(\", \")}. Only the first occurrence will be registered.`\n );\n }\n\n // Create MCP server\n const server = new Server(\n {\n name: \"ppm-mcp-server\",\n version: \"2.8.1\",\n },\n {\n capabilities: {\n prompts: {},\n tools: {},\n },\n }\n );\n\n // Register list_prompts handler\n server.setRequestHandler(ListPromptsRequestSchema, async () => {\n const uniquePrompts = Array.from(\n new Map(validPrompts.map((p) => [buildPromptName(p), p])).values()\n );\n\n // Build system tool schemas (only those marked as slash commands)\n const systemPromptSchemas = SYSTEM_TOOLS\n .filter((st) => st.isSlashCommand) // Only include user-facing slash commands\n .map((st) => ({\n name: st.name,\n description: st.description,\n }));\n\n // Build ticket prompt schemas (Ticket 135, 149, 153 - register as slash commands)\n // All ticket tools are available as slash commands\n const ticketPromptSchemas = dynamicTicketTools.map((tt) => ({\n name: tt.name,\n description: tt.description,\n }));\n\n return {\n prompts: [\n ...systemPromptSchemas,\n ...ticketPromptSchemas,\n ...uniquePrompts.map(buildPromptSchema),\n ],\n };\n });\n\n // Register get_prompt handler\n server.setRequestHandler(GetPromptRequestSchema, async (request) => {\n const promptName = request.params.name;\n\n // Check for system tools first (as prompts for slash command access)\n const systemTool = SYSTEM_TOOLS.find((st) => st.name === promptName);\n if (systemTool) {\n return {\n description: systemTool.description,\n messages: [\n {\n role: \"user\" as const,\n content: {\n type: \"text\" as const,\n text: systemTool.promptContent,\n },\n },\n ],\n };\n }\n\n // Check for ticket commands (Ticket 135, 149, 153 - handle as slash commands)\n // Handle exact matches and :open with optional argument (e.g., \"workspace:tickets:open 102\")\n const ticketTool = dynamicTicketTools.find((tt) => tt.name === promptName);\n const ticketOpenMatch = promptName.match(/^(.+):tickets:open\\s+(.+)$/);\n\n if (ticketTool || ticketOpenMatch) {\n let promptContent: string;\n let description: string;\n\n if (ticketOpenMatch) {\n // Handle tickets:open with specific ticket argument\n const workspaceSlug = ticketOpenMatch[1];\n const ticketArg = ticketOpenMatch[2].trim();\n description = `Open ticket \"${ticketArg}\" from \"${workspaceSlug}\"`;\n promptContent = `Open ticket \"${ticketArg}\" from the \"${workspaceSlug}\" workspace queue and move it to working status.\\n\\nCall the \\`${workspaceSlug}:tickets:open\\` tool with ticketSlug: \"${ticketArg}\".`;\n } else if (ticketTool!.type === 'open') {\n // Ticket 153: tickets:open (renamed from tickets:next)\n description = ticketTool!.description;\n promptContent = `Open the next ticket from the \"${ticketTool!.workspaceSlug}\" workspace queue and move it to working status.\\n\\nCall the \\`${ticketTool!.name}\\` tool to get the next ticket.\\n\\nYou can also specify a ticket: /ppm:${ticketTool!.workspaceSlug}:tickets:open <number-or-slug>`;\n } else if (ticketTool!.type === 'work') {\n // Ticket 153: tickets:work (context recovery)\n description = ticketTool!.description;\n promptContent = `Resume work on a ticket in the \"${ticketTool!.workspaceSlug}\" workspace.\\n\\nCall the \\`${ticketTool!.name}\\` tool to get ticket content and all progress messages for context recovery.\\n\\nIf no ticket slug is provided, returns the first working ticket (by startedAt).\\n\\nYou can also specify a ticket: /ppm:${ticketTool!.workspaceSlug}:tickets:work <number-or-slug>`;\n } else if (ticketTool!.type === 'create') {\n // Ticket 149: tickets:create slash command\n description = ticketTool!.description;\n promptContent = `Create a new ticket in the \"${ticketTool!.workspaceSlug}\" workspace queue.\n\n## How This Works\nThe user provides **instructions** (not raw content). You interpret those instructions to generate the ticket.\n\n## Instructions\n1. **Read the user's request** - they may reference a file, ask you to summarize a session, or describe what they want\n2. **Process the input** - read files, extract relevant sections, summarize as needed\n3. **Generate ticket content** with a clear, descriptive title as the first line\n4. **Call the tool** with the generated content\n\n## Content Format\n\\`\\`\\`\n[Clear descriptive title - this becomes the slug]\n\n[Body content - tasks, description, context, etc.]\n\\`\\`\\`\n\n## Examples\n- \"create a ticket from /path/to/plan.md\" → Read file, use as ticket content\n- \"summarize our brainstorm into a ticket\" → Extract key points from conversation\n- \"create a ticket for the auth bug we discussed\" → Generate from session context\n- \"just the tasks from this file\" → Extract only task items\n\nCall the \\`${ticketTool!.name}\\` tool with the final generated content.`;\n } else if (ticketTool!.type === 'close') {\n description = ticketTool!.description;\n promptContent = `Close a working ticket in the \"${ticketTool!.workspaceSlug}\" workspace.\\n\\nCall the \\`${ticketTool!.name}\\` tool with the ticket number or slug.`;\n } else if (ticketTool!.type === 'message') {\n description = ticketTool!.description;\n promptContent = `Add a progress message to a working or closed ticket in the \"${ticketTool!.workspaceSlug}\" workspace.\\n\\nCall the \\`${ticketTool!.name}\\` tool with the ticket number/slug and your message.`;\n } else {\n // Fallback for unknown type\n description = ticketTool!.description;\n promptContent = `Use the \\`${ticketTool!.name}\\` tool.`;\n }\n\n return {\n description,\n messages: [\n {\n role: \"user\" as const,\n content: {\n type: \"text\" as const,\n text: promptContent,\n },\n },\n ],\n };\n }\n\n // Check user prompts\n const prompt = validPrompts.find((p) => buildPromptName(p) === promptName);\n\n if (!prompt) {\n throw new Error(`Unknown prompt: ${promptName}`);\n }\n\n const handler = buildPromptHandler(prompt, config, convexClient);\n return await handler();\n });\n\n // Register list_tools handler\n server.setRequestHandler(ListToolsRequestSchema, async () => {\n const uniquePrompts = Array.from(\n new Map(validPrompts.map((p) => [buildPromptName(p), p])).values()\n );\n\n // Build tools array: system tools + ticket tools + each user prompt as a tool\n const tools = [\n // System tools with full input schemas\n ...SYSTEM_TOOLS.map((st) => ({\n name: st.name,\n description: st.description,\n inputSchema: st.inputSchema,\n })),\n // Dynamic ticket tools per workspace (Ticket 135, 149, 151, 153)\n ...dynamicTicketTools.map((tt) => {\n // Build inputSchema based on tool type\n let inputSchema: { type: \"object\"; properties: Record<string, object>; required: string[] };\n\n if (tt.type === 'close') {\n // close requires a ticketSlug\n inputSchema = {\n type: \"object\" as const,\n properties: {\n ticketSlug: {\n type: \"string\",\n description: \"Ticket number (e.g., '102') or full slug (e.g., '102-fix-auth')\",\n },\n },\n required: [\"ticketSlug\"],\n };\n } else if (tt.type === 'open') {\n // Ticket 153: tickets:open (renamed from tickets:next)\n inputSchema = {\n type: \"object\" as const,\n properties: {\n ticketSlug: {\n type: \"string\",\n description: \"Optional: Ticket number (e.g., '102') or full slug (e.g., '102-fix-auth'). If not provided, opens the next ticket in queue.\",\n },\n },\n required: [],\n };\n } else if (tt.type === 'work') {\n // Ticket 153: tickets:work (context recovery)\n inputSchema = {\n type: \"object\" as const,\n properties: {\n ticketSlug: {\n type: \"string\",\n description: \"Optional: Ticket number (e.g., '102') or full slug. If not provided, returns the first working ticket by startedAt.\",\n },\n },\n required: [],\n };\n } else if (tt.type === 'create') {\n inputSchema = {\n type: \"object\" as const,\n properties: {\n content: {\n type: \"string\",\n description: \"The generated ticket content. First line should be a clear descriptive title (becomes the slug). Body contains tasks, description, context as needed.\",\n },\n },\n required: [\"content\"],\n };\n } else if (tt.type === 'message') {\n // Ticket 151: message requires ticketSlug and message\n inputSchema = {\n type: \"object\" as const,\n properties: {\n ticketSlug: {\n type: \"string\",\n description: \"Ticket number (e.g., '102') or full slug (e.g., '102-fix-auth')\",\n },\n message: {\n type: \"string\",\n description: \"Progress message to add to the ticket\",\n },\n },\n required: [\"ticketSlug\", \"message\"],\n };\n } else {\n // Fallback: no params\n inputSchema = {\n type: \"object\" as const,\n properties: {},\n required: [],\n };\n }\n\n return {\n name: tt.name,\n description: tt.description,\n inputSchema,\n };\n }),\n // Each user prompt becomes a discoverable tool\n ...uniquePrompts.map((prompt) => ({\n name: buildPromptName(prompt),\n description: prompt.description || `Prompt: ${prompt.name}`,\n inputSchema: {\n type: \"object\" as const,\n properties: {},\n required: [],\n },\n })),\n ];\n\n return { tools };\n });\n\n // Register call_tool handler\n server.setRequestHandler(CallToolRequestSchema, async (request) => {\n const toolName = request.params.name;\n\n // Handle system:prompts tool\n if (toolName === \"system:prompts\") {\n const searchTerm = request.params.arguments?.search as string | undefined;\n const uniquePrompts = Array.from(\n new Map(validPrompts.map((p) => [buildPromptName(p), p])).values()\n );\n\n // Filter system tools\n let filteredSystemTools = SYSTEM_TOOLS;\n if (searchTerm) {\n const lowerSearch = searchTerm.toLowerCase();\n filteredSystemTools = SYSTEM_TOOLS.filter(\n (st) =>\n st.name.toLowerCase().includes(lowerSearch) ||\n st.description.toLowerCase().includes(lowerSearch)\n );\n }\n\n // Filter user prompts\n let filteredPrompts = uniquePrompts;\n if (searchTerm) {\n const lowerSearch = searchTerm.toLowerCase();\n filteredPrompts = uniquePrompts.filter(\n (p) =>\n buildPromptName(p).toLowerCase().includes(lowerSearch) ||\n p.name.toLowerCase().includes(lowerSearch) ||\n p.description?.toLowerCase().includes(lowerSearch)\n );\n }\n\n // Sort user prompts by workspace then by prompt slug\n filteredPrompts.sort((a, b) => {\n const aName = buildPromptName(a);\n const bName = buildPromptName(b);\n return aName.localeCompare(bName);\n });\n\n // Build system tools list\n const systemToolList = filteredSystemTools\n .map((st) => `• ${st.name}\\n Type: System\\n Description: ${st.description}`)\n .join(\"\\n\\n\");\n\n // Build user prompts list\n const userPromptList = filteredPrompts\n .map((p) => {\n const name = buildPromptName(p);\n const workspace = p.workspaceSlug || \"unknown\";\n const desc = p.description || \"No description\";\n return `• ${name}\\n Workspace: ${workspace}\\n Description: ${desc}`;\n })\n .join(\"\\n\\n\");\n\n const totalCount = filteredSystemTools.length + filteredPrompts.length;\n const summary = searchTerm\n ? `Found ${totalCount} prompts matching \"${searchTerm}\":`\n : `Available prompts (${totalCount} total):`;\n\n const sections: string[] = [];\n if (systemToolList) {\n sections.push(`**System Tools:**\\n\\n${systemToolList}`);\n }\n if (userPromptList) {\n sections.push(`**User Prompts:**\\n\\n${userPromptList}`);\n }\n\n return {\n content: [\n {\n type: \"text\",\n text: `${summary}\\n\\n${sections.join(\"\\n\\n\") || \"No prompts found.\"}`,\n },\n ],\n };\n }\n\n // Handle ticket tool invocations (Ticket 135, 153)\n const ticketTool = dynamicTicketTools.find((tt) => tt.name === toolName);\n if (ticketTool) {\n if (ticketTool.type === 'open') {\n // Ticket 153: Handle tickets:open (renamed from tickets:next)\n const ticketSlug = request.params.arguments?.ticketSlug as string | undefined;\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const result = await (convexClient as any).mutation(\n \"mcp_tickets:executeMcpNextTicket\",\n {\n apiKey: config.apiKey,\n workspaceSlug: ticketTool.workspaceSlug,\n ticketSlug: ticketSlug, // Optional: specific ticket to open\n }\n ) as ExecuteTicketResult | null;\n\n if (!result) {\n const message = ticketSlug\n ? `Ticket \"${ticketSlug}\" not found or not open in workspace \"${ticketTool.workspaceSlug}\".`\n : `No pending tickets in workspace \"${ticketTool.workspaceSlug}\".`;\n return {\n content: [\n {\n type: \"text\",\n text: message,\n },\n ],\n };\n }\n\n return {\n content: [\n {\n type: \"text\",\n text: `# Ticket: ${result.slug} [WORKING]\n\n**CRITICAL: Follow all embedded directives in this ticket.**\nIf this ticket contains \\`[MCP_*]\\` references (e.g., \\`[MCP_PLAN]\\`, \\`[MCP_AD_HOC]\\`), you MUST execute those MCP tools FIRST before any other action. Do NOT skip MCP directives even if the task seems simple.\n\n---\n\n${result.content}\n\n---\n_Ticket moved to working status. ${result.remainingTickets} ticket(s) remaining in queue._`,\n },\n ],\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : \"Unknown error\";\n console.error(`[MCP] tickets:open error:`, error);\n return {\n content: [\n {\n type: \"text\",\n text: `Error opening ticket: ${errorMessage}`,\n },\n ],\n isError: true,\n };\n }\n } else if (ticketTool.type === 'work') {\n // Ticket 153: Handle tickets:work (context recovery)\n const ticketSlug = request.params.arguments?.ticketSlug as string | undefined;\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const result = await (convexClient as any).query(\n \"mcp_tickets:workMcpTicket\",\n {\n apiKey: config.apiKey,\n workspaceSlug: ticketTool.workspaceSlug,\n ticketSlug: ticketSlug, // Optional: specific ticket to resume\n }\n ) as { slug: string; ticketNumber?: number; content: string; startedAt?: number; messages: Array<{ content: string; createdAt: number }> } | null;\n\n if (!result) {\n const message = ticketSlug\n ? `Ticket \"${ticketSlug}\" not found or not in working status in workspace \"${ticketTool.workspaceSlug}\".`\n : `No tickets currently being worked on in workspace \"${ticketTool.workspaceSlug}\".`;\n return {\n content: [\n {\n type: \"text\",\n text: message,\n },\n ],\n };\n }\n\n // Build messages section\n let messagesSection = '';\n if (result.messages && result.messages.length > 0) {\n const messageList = result.messages\n .map((m) => `[${new Date(m.createdAt).toISOString()}] ${m.content}`)\n .join('\\n');\n messagesSection = `\\n\\n## Progress Messages\\n\\n${messageList}`;\n }\n\n const startedInfo = result.startedAt\n ? `\\nStarted: ${new Date(result.startedAt).toISOString()}`\n : '';\n\n return {\n content: [\n {\n type: \"text\",\n text: `# Ticket: ${result.slug} [WORKING]${startedInfo}\n\n**CRITICAL: Follow all embedded directives in this ticket.**\nIf this ticket contains \\`[MCP_*]\\` references (e.g., \\`[MCP_PLAN]\\`, \\`[MCP_AD_HOC]\\`), you MUST execute those MCP tools FIRST before any other action. Do NOT skip MCP directives even if the task seems simple.\n\n---\n\n${result.content}${messagesSection}\n\n---\n_Resuming work on this ticket._`,\n },\n ],\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : \"Unknown error\";\n console.error(`[MCP] tickets:work error:`, error);\n return {\n content: [\n {\n type: \"text\",\n text: `Error resuming ticket: ${errorMessage}`,\n },\n ],\n isError: true,\n };\n }\n } else if (ticketTool.type === 'create') {\n // Handle tickets:create (Ticket 149)\n const content = request.params.arguments?.content as string | undefined;\n\n if (!content) {\n return {\n content: [\n {\n type: \"text\",\n text: `Error: Missing content parameter. Provide the ticket content (first line becomes the slug).`,\n },\n ],\n isError: true,\n };\n }\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const result = await (convexClient as any).mutation(\n \"mcp_tickets:createMcpTicket\",\n {\n apiKey: config.apiKey,\n workspaceSlug: ticketTool.workspaceSlug,\n content,\n }\n ) as { slug: string; preview: string; position: number; totalOpen: number };\n\n return {\n content: [\n {\n type: \"text\",\n text: `✅ Created ticket [${result.slug}] in workspace \"${ticketTool.workspaceSlug}\".\n\nPosition: #${result.position} of ${result.totalOpen} open tickets\nPreview: ${result.preview}\n\n_Note: If this ticket contains \\`[MCP_*]\\` directives, they will be mandatory when opened._`,\n },\n ],\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : \"Unknown error\";\n console.error(`[MCP] tickets:create error:`, error);\n return {\n content: [\n {\n type: \"text\",\n text: `Error creating ticket: ${errorMessage}`,\n },\n ],\n isError: true,\n };\n }\n } else if (ticketTool.type === 'close') {\n // Ticket 151: Handle tickets:close\n const ticketSlug = request.params.arguments?.ticketSlug as string | undefined;\n\n if (!ticketSlug) {\n return {\n content: [\n {\n type: \"text\",\n text: `Error: Missing ticketSlug parameter. Usage: Provide a ticket number (e.g., \"102\") or full slug (e.g., \"102-fix-auth\").`,\n },\n ],\n isError: true,\n };\n }\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const result = await (convexClient as any).mutation(\n \"mcp_tickets:closeMcpTicket\",\n {\n apiKey: config.apiKey,\n workspaceSlug: ticketTool.workspaceSlug,\n ticketSlug: ticketSlug,\n }\n ) as CloseTicketResult;\n\n return {\n content: [\n {\n type: \"text\",\n text: `✅ Ticket [${result.slug}] closed in workspace \"${ticketTool.workspaceSlug}\".\n\nClosed at: ${new Date(result.closedAt).toISOString()}\n\n_Reminder: Ensure all embedded \\`[MCP_*]\\` directives were executed before closing._`,\n },\n ],\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : \"Unknown error\";\n console.error(`[MCP] tickets:close error:`, error);\n return {\n content: [\n {\n type: \"text\",\n text: `Error closing ticket: ${errorMessage}`,\n },\n ],\n isError: true,\n };\n }\n } else if (ticketTool.type === 'message') {\n // Ticket 151: Handle tickets:message\n const ticketSlug = request.params.arguments?.ticketSlug as string | undefined;\n const message = request.params.arguments?.message as string | undefined;\n\n if (!ticketSlug || !message) {\n return {\n content: [\n {\n type: \"text\",\n text: `Error: Missing required parameters. Provide ticketSlug and message.`,\n },\n ],\n isError: true,\n };\n }\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const result = await (convexClient as any).mutation(\n \"mcp_tickets:addMcpTicketMessage\",\n {\n apiKey: config.apiKey,\n workspaceSlug: ticketTool.workspaceSlug,\n ticketSlug: ticketSlug,\n message: message,\n }\n ) as AddMessageResult;\n\n return {\n content: [\n {\n type: \"text\",\n text: `✅ Message added to ticket [${result.ticketSlug}].\\n\\nTotal messages: ${result.messageCount}`,\n },\n ],\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : \"Unknown error\";\n console.error(`[MCP] tickets:message error:`, error);\n return {\n content: [\n {\n type: \"text\",\n text: `Error adding message: ${errorMessage}`,\n },\n ],\n isError: true,\n };\n }\n }\n }\n\n // Handle user prompt tool invocations\n const prompt = validPrompts.find((p) => buildPromptName(p) === toolName);\n\n if (!prompt) {\n throw new Error(`Unknown tool: ${toolName}`);\n }\n\n // Execute the prompt and return flattened content\n const handler = buildPromptHandler(prompt, config, convexClient);\n const result = await handler();\n\n // Convert prompt result to tool result format\n // Extract text from prompt messages\n const promptText = result.messages\n .map((msg) => (typeof msg.content === 'string' ? msg.content : msg.content.text))\n .join('\\n\\n');\n\n return {\n content: [\n {\n type: \"text\",\n text: promptText,\n },\n ],\n };\n });\n\n // Start server with stdio transport\n const transport = new StdioServerTransport();\n await server.connect(transport);\n\n console.error(\"[MCP] Server started successfully\");\n console.error(`[MCP] Deployment: ${config.isDev ? \"DEVELOPMENT\" : \"PRODUCTION\"}`);\n console.error(`[MCP] Convex URL: ${config.convexUrl}`);\n console.error(`[MCP] Data mode: REAL-TIME (fetches fresh data on each invocation)`);\n\n // List all prompts\n const allPromptNames = [...Array.from(promptNames)].sort();\n console.error(`[MCP] Prompts available: ${allPromptNames.join(\", \")}`);\n console.error(`[MCP] - Total prompts: ${promptNames.size}`);\n\n // Keep the event loop alive with a heartbeat\n // This prevents Node from exiting when there are no active handles\n setInterval(() => {\n // Heartbeat every 60 seconds to keep process alive\n }, 60000);\n\n // Return a promise that never resolves to keep the server running\n return new Promise<void>(() => {\n // The transport handles stdin/stdout communication\n // The interval above keeps the event loop active\n });\n}\n\n/**\n * Validate API key with Convex\n */\nasync function validateApiKey(\n client: ConvexHttpClient,\n apiKey: string\n): Promise<{ valid: boolean; userId?: string; error?: string }> {\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const result = await client.query(\"apiKeys:validateApiKey\" as any, { key: apiKey });\n if (result) {\n return { valid: true, userId: result.userId };\n }\n return { valid: false, error: \"Invalid API key\" };\n } catch (error) {\n return {\n valid: false,\n error: error instanceof Error ? error.message : \"Unknown error\",\n };\n }\n}\n\n/**\n * Fetch prompts exposed to MCP\n * Passes workspace filter from CLI --workspaces arg (Ticket 144)\n */\nasync function fetchMcpPrompts(\n client: ConvexHttpClient,\n apiKey: string,\n workspaces: string[]\n): Promise<McpPrompt[]> {\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const prompts = await client.query(\"mcp_prompts:getMcpPrompts\" as any, {\n apiKey,\n workspaces: workspaces.length > 0 ? workspaces : undefined, // Only pass if specified\n });\n return prompts;\n } catch (error) {\n throw new Error(\n `Failed to fetch prompts: ${error instanceof Error ? error.message : \"Unknown error\"}`\n );\n }\n}\n","import type { ConvexHttpClient } from \"convex/browser\";\nimport type { McpPrompt, ServerConfig } from \"./types.js\";\n\n/**\n * Sanitizes a string for use in MCP tool names.\n * Ensures output matches MCP protocol pattern: ^[a-zA-Z0-9_-]{1,64}$\n *\n * @param str - Raw string to sanitize (workspace slug, folder path, or prompt slug)\n * @returns Sanitized string safe for MCP tool names\n */\nexport function sanitizeForMcp(str: string): string {\n return str\n .trim() // Remove leading/trailing whitespace first\n .toLowerCase() // Convert to lowercase for consistency\n .replace(/[^a-z0-9_-]/g, '-') // Replace ALL invalid chars (including spaces!) with hyphens\n .replace(/-+/g, '-') // Collapse multiple consecutive hyphens into one\n .replace(/^-+|-+$/g, '') // Remove leading and trailing hyphens\n .trim(); // Final trim to ensure no whitespace\n}\n\n/**\n * Build the MCP prompt name for a prompt with workspace scoping\n *\n * MCP tool names must match pattern: ^[a-zA-Z0-9_:-]{1,64}$\n * (letters, numbers, underscores, hyphens, and colons allowed)\n *\n * Format: workspace:prompt\n * - Folders are NOT included in slash command names\n * - Folders are only used for ZIP download organization\n *\n * Character mapping:\n * - Separator: : (colon) between workspace and prompt\n * - Hyphens: - used within multi-word slugs\n * - Example: personal:code-review, work:api-design\n */\nexport function buildPromptName(prompt: McpPrompt): string {\n const workspace = sanitizeForMcp(prompt.workspaceSlug || 'default') || 'default';\n const promptSlug = sanitizeForMcp(prompt.slug || 'unknown') || 'unknown';\n\n // Hierarchical workspace:prompt format\n return `${workspace}:${promptSlug}`.trim();\n}\n\n/**\n * Build the MCP prompt schema for a prompt\n */\nexport function buildPromptSchema(prompt: McpPrompt) {\n return {\n name: buildPromptName(prompt),\n description: prompt.description || `Prompt: ${prompt.name}`,\n arguments: [],\n };\n}\n\n/**\n * Build the prompt execution handler for a prompt\n */\nexport function buildPromptHandler(\n prompt: McpPrompt,\n config: ServerConfig,\n convexClient: ConvexHttpClient\n) {\n return async () => {\n let flattenedPrompt = prompt.flattenedPrompt;\n let promptName = prompt.name;\n\n // Always fetch fresh data from Convex (real-time mode)\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n let freshPrompts = await convexClient.query(\"mcp_prompts:getMcpPrompts\" as any, {\n apiKey: config.apiKey,\n });\n\n // Apply workspace filter to fresh data if configured\n if (config.selectedWorkspaces.length > 0) {\n freshPrompts = freshPrompts.filter((p: McpPrompt) =>\n p.workspaceSlug && config.selectedWorkspaces.includes(p.workspaceSlug)\n );\n }\n\n const freshPrompt = freshPrompts.find((p: McpPrompt) => p.slug === prompt.slug && p.workspaceSlug === prompt.workspaceSlug);\n\n if (freshPrompt) {\n flattenedPrompt = freshPrompt.flattenedPrompt;\n promptName = freshPrompt.name;\n console.error(`[MCP] Fetched fresh data for: ${buildPromptName(prompt)}`);\n } else {\n console.error(\n `[MCP] WARNING: Prompt \"${prompt.slug}\" not found in fresh fetch, using cached version`\n );\n }\n } catch (error) {\n console.error(\n `[MCP] WARNING: Failed to fetch fresh data, using cached version: ${error instanceof Error ? error.message : \"Unknown error\"}`\n );\n }\n\n if (!flattenedPrompt) {\n throw new Error(\n `Prompt \"${promptName}\" has no flattened content. Please re-save the prompt in ContextFS to regenerate it.`\n );\n }\n\n console.error(`[MCP] Executed prompt: ${buildPromptName(prompt)}`);\n\n // Return raw flattened prompt (client will parse YAML front matter)\n return {\n messages: [\n {\n role: \"user\",\n content: {\n type: \"text\" as const,\n text: flattenedPrompt,\n },\n },\n ],\n };\n };\n}\n"],"mappings":";;;AAAA,OAAO,cAAc;;;ACArB,SAAS,wBAAwB;AAEjC,IAAM,WAAW;AACjB,IAAM,UAAU;AAKT,SAAS,mBAAmB,OAAkC;AACnE,QAAM,MAAM,QAAQ,UAAU;AAC9B,SAAO,IAAI,iBAAiB,GAAG;AACjC;;;ACXA,SAAS,cAAc;AACvB,SAAS,4BAA4B;AACrC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;;;ACGA,SAAS,eAAe,KAAqB;AAClD,SAAO,IACJ,KAAK,EACL,YAAY,EACZ,QAAQ,gBAAgB,GAAG,EAC3B,QAAQ,OAAO,GAAG,EAClB,QAAQ,YAAY,EAAE,EACtB,KAAK;AACV;AAiBO,SAAS,gBAAgB,QAA2B;AACzD,QAAM,YAAY,eAAe,OAAO,iBAAiB,SAAS,KAAK;AACvE,QAAM,aAAa,eAAe,OAAO,QAAQ,SAAS,KAAK;AAG/D,SAAO,GAAG,SAAS,IAAI,UAAU,GAAG,KAAK;AAC3C;AAKO,SAAS,kBAAkB,QAAmB;AACnD,SAAO;AAAA,IACL,MAAM,gBAAgB,MAAM;AAAA,IAC5B,aAAa,OAAO,eAAe,WAAW,OAAO,IAAI;AAAA,IACzD,WAAW,CAAC;AAAA,EACd;AACF;AAKO,SAAS,mBACd,QACA,QACA,cACA;AACA,SAAO,YAAY;AACjB,QAAI,kBAAkB,OAAO;AAC7B,QAAI,aAAa,OAAO;AAGxB,QAAI;AAEF,UAAI,eAAe,MAAM,aAAa,MAAM,6BAAoC;AAAA,QAC9E,QAAQ,OAAO;AAAA,MACjB,CAAC;AAGD,UAAI,OAAO,mBAAmB,SAAS,GAAG;AACxC,uBAAe,aAAa;AAAA,UAAO,CAAC,MAClC,EAAE,iBAAiB,OAAO,mBAAmB,SAAS,EAAE,aAAa;AAAA,QACvE;AAAA,MACF;AAEA,YAAM,cAAc,aAAa,KAAK,CAAC,MAAiB,EAAE,SAAS,OAAO,QAAQ,EAAE,kBAAkB,OAAO,aAAa;AAE1H,UAAI,aAAa;AACf,0BAAkB,YAAY;AAC9B,qBAAa,YAAY;AACzB,gBAAQ,MAAM,iCAAiC,gBAAgB,MAAM,CAAC,EAAE;AAAA,MAC1E,OAAO;AACL,gBAAQ;AAAA,UACN,0BAA0B,OAAO,IAAI;AAAA,QACvC;AAAA,MACF;AAAA,IACF,SAAS,OAAO;AACd,cAAQ;AAAA,QACN,oEAAoE,iBAAiB,QAAQ,MAAM,UAAU,eAAe;AAAA,MAC9H;AAAA,IACF;AAEA,QAAI,CAAC,iBAAiB;AACpB,YAAM,IAAI;AAAA,QACR,WAAW,UAAU;AAAA,MACvB;AAAA,IACF;AAEA,YAAQ,MAAM,0BAA0B,gBAAgB,MAAM,CAAC,EAAE;AAGjE,WAAO;AAAA,MACL,UAAU;AAAA,QACR;AAAA,UACE,MAAM;AAAA,UACN,SAAS;AAAA,YACP,MAAM;AAAA,YACN,MAAM;AAAA,UACR;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;AD1EA,IAAM,eAMA;AAAA;AAAA,EAEJ;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,QAAQ;AAAA,UACN,MAAM;AAAA,UACN,aAAa;AAAA,QACf;AAAA,MACF;AAAA,IACF;AAAA,IACA,gBAAgB;AAAA,IAChB,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA,EAKjB;AACF;AAKA,eAAsB,YACpB,QACA,cACe;AAEf,UAAQ,MAAM,6BAA6B;AAC3C,QAAM,aAAa,MAAM,eAAe,cAAc,OAAO,MAAM;AACnE,MAAI,CAAC,WAAW,OAAO;AACrB,UAAM,IAAI,MAAM,oBAAoB,WAAW,KAAK,EAAE;AAAA,EACxD;AACA,UAAQ,MAAM,qCAAqC,WAAW,MAAM,EAAE;AAGtE,UAAQ,MAAM,mCAAmC;AACjD,QAAM,UAAU,MAAM,gBAAgB,cAAc,OAAO,QAAQ,OAAO,kBAAkB;AAC5F,UAAQ,MAAM,eAAe,QAAQ,MAAM,kBAAkB;AAE7D,MAAI,QAAQ,WAAW,GAAG;AACxB,QAAI,OAAO,mBAAmB,SAAS,GAAG;AACxC,cAAQ;AAAA,QACN,kDAAkD,OAAO,mBAAmB,KAAK,IAAI,CAAC;AAAA,MACxF;AAAA,IACF,OAAO;AACL,cAAQ;AAAA,QACN;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,QAAM,eAAe,QAAQ,OAAO,CAAC,MAAM;AACzC,QAAI,CAAC,EAAE,iBAAiB;AACtB,cAAQ;AAAA,QACN,mCAAmC,EAAE,IAAI,MAAM,EAAE,IAAI;AAAA,MACvD;AACA,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT,CAAC;AAGD,MAAI,OAAO,mBAAmB,SAAS,GAAG;AACxC,YAAQ,MAAM,2BAA2B,OAAO,mBAAmB,KAAK,IAAI,CAAC,EAAE;AAAA,EACjF,OAAO;AACL,YAAQ,MAAM,yDAAyD;AAAA,EACzE;AACA,UAAQ,MAAM,qBAAqB,aAAa,MAAM,aAAa;AAInE,QAAM,iBAAiB,IAAI,IAAI,aAAa,IAAI,CAAC,MAAM,EAAE,aAAa,EAAE,OAAO,CAAC,MAAmB,CAAC,CAAC,CAAC,CAAC;AACvG,QAAM,qBAA6I,CAAC;AAEpJ,aAAW,iBAAiB,gBAAgB;AAE1C,uBAAmB,KAAK;AAAA,MACtB,MAAM,GAAG,aAAa;AAAA,MACtB,aAAa,kCAAkC,aAAa;AAAA,MAC5D;AAAA,MACA,MAAM;AAAA,IACR,CAAC;AAED,uBAAmB,KAAK;AAAA,MACtB,MAAM,GAAG,aAAa;AAAA,MACtB,aAAa,mCAAmC,aAAa;AAAA,MAC7D;AAAA,MACA,MAAM;AAAA,IACR,CAAC;AACD,uBAAmB,KAAK;AAAA,MACtB,MAAM,GAAG,aAAa;AAAA,MACtB,aAAa,8CAA8C,aAAa;AAAA,MACxE;AAAA,MACA,MAAM;AAAA,IACR,CAAC;AACD,uBAAmB,KAAK;AAAA,MACtB,MAAM,GAAG,aAAa;AAAA,MACtB,aAAa,gEAAgE,aAAa;AAAA,MAC1F;AAAA,MACA,MAAM;AAAA,IACR,CAAC;AACD,uBAAmB,KAAK;AAAA,MACtB,MAAM,GAAG,aAAa;AAAA,MACtB,aAAa,+BAA+B,aAAa;AAAA,MACzD;AAAA,MACA,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AAEA,UAAQ,MAAM,qBAAqB,mBAAmB,MAAM,qBAAqB,eAAe,IAAI,kBAAkB;AAGtH,QAAM,cAAc,oBAAI,IAAY;AACpC,QAAM,aAAuB,CAAC;AAC9B,eAAa,QAAQ,CAAC,MAAM;AAC1B,UAAM,OAAO,gBAAgB,CAAC;AAC9B,QAAI,YAAY,IAAI,IAAI,GAAG;AACzB,iBAAW,KAAK,IAAI;AAAA,IACtB;AACA,gBAAY,IAAI,IAAI;AAAA,EACtB,CAAC;AAED,MAAI,WAAW,SAAS,GAAG;AACzB,YAAQ;AAAA,MACN,mDAAmD,WAAW,KAAK,IAAI,CAAC;AAAA,IAC1E;AAAA,EACF;AAGA,QAAM,SAAS,IAAI;AAAA,IACjB;AAAA,MACE,MAAM;AAAA,MACN,SAAS;AAAA,IACX;AAAA,IACA;AAAA,MACE,cAAc;AAAA,QACZ,SAAS,CAAC;AAAA,QACV,OAAO,CAAC;AAAA,MACV;AAAA,IACF;AAAA,EACF;AAGA,SAAO,kBAAkB,0BAA0B,YAAY;AAC7D,UAAM,gBAAgB,MAAM;AAAA,MAC1B,IAAI,IAAI,aAAa,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,OAAO;AAAA,IACnE;AAGA,UAAM,sBAAsB,aACzB,OAAO,CAAC,OAAO,GAAG,cAAc,EAChC,IAAI,CAAC,QAAQ;AAAA,MACZ,MAAM,GAAG;AAAA,MACT,aAAa,GAAG;AAAA,IAClB,EAAE;AAIJ,UAAM,sBAAsB,mBAAmB,IAAI,CAAC,QAAQ;AAAA,MAC1D,MAAM,GAAG;AAAA,MACT,aAAa,GAAG;AAAA,IAClB,EAAE;AAEF,WAAO;AAAA,MACL,SAAS;AAAA,QACP,GAAG;AAAA,QACH,GAAG;AAAA,QACH,GAAG,cAAc,IAAI,iBAAiB;AAAA,MACxC;AAAA,IACF;AAAA,EACF,CAAC;AAGD,SAAO,kBAAkB,wBAAwB,OAAO,YAAY;AAClE,UAAM,aAAa,QAAQ,OAAO;AAGlC,UAAM,aAAa,aAAa,KAAK,CAAC,OAAO,GAAG,SAAS,UAAU;AACnE,QAAI,YAAY;AACd,aAAO;AAAA,QACL,aAAa,WAAW;AAAA,QACxB,UAAU;AAAA,UACR;AAAA,YACE,MAAM;AAAA,YACN,SAAS;AAAA,cACP,MAAM;AAAA,cACN,MAAM,WAAW;AAAA,YACnB;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAIA,UAAM,aAAa,mBAAmB,KAAK,CAAC,OAAO,GAAG,SAAS,UAAU;AACzE,UAAM,kBAAkB,WAAW,MAAM,4BAA4B;AAErE,QAAI,cAAc,iBAAiB;AACjC,UAAI;AACJ,UAAI;AAEJ,UAAI,iBAAiB;AAEnB,cAAM,gBAAgB,gBAAgB,CAAC;AACvC,cAAM,YAAY,gBAAgB,CAAC,EAAE,KAAK;AAC1C,sBAAc,gBAAgB,SAAS,WAAW,aAAa;AAC/D,wBAAgB,gBAAgB,SAAS,eAAe,aAAa;AAAA;AAAA,aAAkE,aAAa,0CAA0C,SAAS;AAAA,MACzM,WAAW,WAAY,SAAS,QAAQ;AAEtC,sBAAc,WAAY;AAC1B,wBAAgB,kCAAkC,WAAY,aAAa;AAAA;AAAA,aAAkE,WAAY,IAAI;AAAA;AAAA,sCAA0E,WAAY,aAAa;AAAA,MAClQ,WAAW,WAAY,SAAS,QAAQ;AAEtC,sBAAc,WAAY;AAC1B,wBAAgB,mCAAmC,WAAY,aAAa;AAAA;AAAA,aAA8B,WAAY,IAAI;AAAA;AAAA;AAAA;AAAA,sCAA2M,WAAY,aAAa;AAAA,MAChW,WAAW,WAAY,SAAS,UAAU;AAExC,sBAAc,WAAY;AAC1B,wBAAgB,+BAA+B,WAAY,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,aAwBnE,WAAY,IAAI;AAAA,MACvB,WAAW,WAAY,SAAS,SAAS;AACvC,sBAAc,WAAY;AAC1B,wBAAgB,kCAAkC,WAAY,aAAa;AAAA;AAAA,aAA8B,WAAY,IAAI;AAAA,MAC3H,WAAW,WAAY,SAAS,WAAW;AACzC,sBAAc,WAAY;AAC1B,wBAAgB,gEAAgE,WAAY,aAAa;AAAA;AAAA,aAA8B,WAAY,IAAI;AAAA,MACzJ,OAAO;AAEL,sBAAc,WAAY;AAC1B,wBAAgB,aAAa,WAAY,IAAI;AAAA,MAC/C;AAEA,aAAO;AAAA,QACL;AAAA,QACA,UAAU;AAAA,UACR;AAAA,YACE,MAAM;AAAA,YACN,SAAS;AAAA,cACP,MAAM;AAAA,cACN,MAAM;AAAA,YACR;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAGA,UAAM,SAAS,aAAa,KAAK,CAAC,MAAM,gBAAgB,CAAC,MAAM,UAAU;AAEzE,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI,MAAM,mBAAmB,UAAU,EAAE;AAAA,IACjD;AAEA,UAAM,UAAU,mBAAmB,QAAQ,QAAQ,YAAY;AAC/D,WAAO,MAAM,QAAQ;AAAA,EACvB,CAAC;AAGD,SAAO,kBAAkB,wBAAwB,YAAY;AAC3D,UAAM,gBAAgB,MAAM;AAAA,MAC1B,IAAI,IAAI,aAAa,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,OAAO;AAAA,IACnE;AAGA,UAAM,QAAQ;AAAA;AAAA,MAEZ,GAAG,aAAa,IAAI,CAAC,QAAQ;AAAA,QAC3B,MAAM,GAAG;AAAA,QACT,aAAa,GAAG;AAAA,QAChB,aAAa,GAAG;AAAA,MAClB,EAAE;AAAA;AAAA,MAEF,GAAG,mBAAmB,IAAI,CAAC,OAAO;AAEhC,YAAI;AAEJ,YAAI,GAAG,SAAS,SAAS;AAEvB,wBAAc;AAAA,YACZ,MAAM;AAAA,YACN,YAAY;AAAA,cACV,YAAY;AAAA,gBACV,MAAM;AAAA,gBACN,aAAa;AAAA,cACf;AAAA,YACF;AAAA,YACA,UAAU,CAAC,YAAY;AAAA,UACzB;AAAA,QACF,WAAW,GAAG,SAAS,QAAQ;AAE7B,wBAAc;AAAA,YACZ,MAAM;AAAA,YACN,YAAY;AAAA,cACV,YAAY;AAAA,gBACV,MAAM;AAAA,gBACN,aAAa;AAAA,cACf;AAAA,YACF;AAAA,YACA,UAAU,CAAC;AAAA,UACb;AAAA,QACF,WAAW,GAAG,SAAS,QAAQ;AAE7B,wBAAc;AAAA,YACZ,MAAM;AAAA,YACN,YAAY;AAAA,cACV,YAAY;AAAA,gBACV,MAAM;AAAA,gBACN,aAAa;AAAA,cACf;AAAA,YACF;AAAA,YACA,UAAU,CAAC;AAAA,UACb;AAAA,QACF,WAAW,GAAG,SAAS,UAAU;AAC/B,wBAAc;AAAA,YACZ,MAAM;AAAA,YACN,YAAY;AAAA,cACV,SAAS;AAAA,gBACP,MAAM;AAAA,gBACN,aAAa;AAAA,cACf;AAAA,YACF;AAAA,YACA,UAAU,CAAC,SAAS;AAAA,UACtB;AAAA,QACF,WAAW,GAAG,SAAS,WAAW;AAEhC,wBAAc;AAAA,YACZ,MAAM;AAAA,YACN,YAAY;AAAA,cACV,YAAY;AAAA,gBACV,MAAM;AAAA,gBACN,aAAa;AAAA,cACf;AAAA,cACA,SAAS;AAAA,gBACP,MAAM;AAAA,gBACN,aAAa;AAAA,cACf;AAAA,YACF;AAAA,YACA,UAAU,CAAC,cAAc,SAAS;AAAA,UACpC;AAAA,QACF,OAAO;AAEL,wBAAc;AAAA,YACZ,MAAM;AAAA,YACN,YAAY,CAAC;AAAA,YACb,UAAU,CAAC;AAAA,UACb;AAAA,QACF;AAEA,eAAO;AAAA,UACL,MAAM,GAAG;AAAA,UACT,aAAa,GAAG;AAAA,UAChB;AAAA,QACF;AAAA,MACF,CAAC;AAAA;AAAA,MAED,GAAG,cAAc,IAAI,CAAC,YAAY;AAAA,QAChC,MAAM,gBAAgB,MAAM;AAAA,QAC5B,aAAa,OAAO,eAAe,WAAW,OAAO,IAAI;AAAA,QACzD,aAAa;AAAA,UACX,MAAM;AAAA,UACN,YAAY,CAAC;AAAA,UACb,UAAU,CAAC;AAAA,QACb;AAAA,MACF,EAAE;AAAA,IACJ;AAEA,WAAO,EAAE,MAAM;AAAA,EACjB,CAAC;AAGD,SAAO,kBAAkB,uBAAuB,OAAO,YAAY;AACjE,UAAM,WAAW,QAAQ,OAAO;AAGhC,QAAI,aAAa,kBAAkB;AACjC,YAAM,aAAa,QAAQ,OAAO,WAAW;AAC7C,YAAM,gBAAgB,MAAM;AAAA,QAC1B,IAAI,IAAI,aAAa,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,OAAO;AAAA,MACnE;AAGA,UAAI,sBAAsB;AAC1B,UAAI,YAAY;AACd,cAAM,cAAc,WAAW,YAAY;AAC3C,8BAAsB,aAAa;AAAA,UACjC,CAAC,OACC,GAAG,KAAK,YAAY,EAAE,SAAS,WAAW,KAC1C,GAAG,YAAY,YAAY,EAAE,SAAS,WAAW;AAAA,QACrD;AAAA,MACF;AAGA,UAAI,kBAAkB;AACtB,UAAI,YAAY;AACd,cAAM,cAAc,WAAW,YAAY;AAC3C,0BAAkB,cAAc;AAAA,UAC9B,CAAC,MACC,gBAAgB,CAAC,EAAE,YAAY,EAAE,SAAS,WAAW,KACrD,EAAE,KAAK,YAAY,EAAE,SAAS,WAAW,KACzC,EAAE,aAAa,YAAY,EAAE,SAAS,WAAW;AAAA,QACrD;AAAA,MACF;AAGA,sBAAgB,KAAK,CAAC,GAAG,MAAM;AAC7B,cAAM,QAAQ,gBAAgB,CAAC;AAC/B,cAAM,QAAQ,gBAAgB,CAAC;AAC/B,eAAO,MAAM,cAAc,KAAK;AAAA,MAClC,CAAC;AAGD,YAAM,iBAAiB,oBACpB,IAAI,CAAC,OAAO,UAAK,GAAG,IAAI;AAAA;AAAA,iBAAoC,GAAG,WAAW,EAAE,EAC5E,KAAK,MAAM;AAGd,YAAM,iBAAiB,gBACpB,IAAI,CAAC,MAAM;AACV,cAAM,OAAO,gBAAgB,CAAC;AAC9B,cAAM,YAAY,EAAE,iBAAiB;AACrC,cAAM,OAAO,EAAE,eAAe;AAC9B,eAAO,UAAK,IAAI;AAAA,eAAkB,SAAS;AAAA,iBAAoB,IAAI;AAAA,MACrE,CAAC,EACA,KAAK,MAAM;AAEd,YAAM,aAAa,oBAAoB,SAAS,gBAAgB;AAChE,YAAM,UAAU,aACZ,SAAS,UAAU,sBAAsB,UAAU,OACnD,sBAAsB,UAAU;AAEpC,YAAM,WAAqB,CAAC;AAC5B,UAAI,gBAAgB;AAClB,iBAAS,KAAK;AAAA;AAAA,EAAwB,cAAc,EAAE;AAAA,MACxD;AACA,UAAI,gBAAgB;AAClB,iBAAS,KAAK;AAAA;AAAA,EAAwB,cAAc,EAAE;AAAA,MACxD;AAEA,aAAO;AAAA,QACL,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,MAAM,GAAG,OAAO;AAAA;AAAA,EAAO,SAAS,KAAK,MAAM,KAAK,mBAAmB;AAAA,UACrE;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAGA,UAAM,aAAa,mBAAmB,KAAK,CAAC,OAAO,GAAG,SAAS,QAAQ;AACvE,QAAI,YAAY;AACd,UAAI,WAAW,SAAS,QAAQ;AAE9B,cAAM,aAAa,QAAQ,OAAO,WAAW;AAE7C,YAAI;AAEF,gBAAMA,UAAS,MAAO,aAAqB;AAAA,YACzC;AAAA,YACA;AAAA,cACE,QAAQ,OAAO;AAAA,cACf,eAAe,WAAW;AAAA,cAC1B;AAAA;AAAA,YACF;AAAA,UACF;AAEA,cAAI,CAACA,SAAQ;AACX,kBAAM,UAAU,aACZ,WAAW,UAAU,yCAAyC,WAAW,aAAa,OACtF,oCAAoC,WAAW,aAAa;AAChE,mBAAO;AAAA,cACL,SAAS;AAAA,gBACP;AAAA,kBACE,MAAM;AAAA,kBACN,MAAM;AAAA,gBACR;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAEA,iBAAO;AAAA,YACL,SAAS;AAAA,cACP;AAAA,gBACE,MAAM;AAAA,gBACN,MAAM,aAAaA,QAAO,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO5CA,QAAO,OAAO;AAAA;AAAA;AAAA,mCAGmBA,QAAO,gBAAgB;AAAA,cAC5C;AAAA,YACF;AAAA,UACF;AAAA,QACF,SAAS,OAAO;AACd,gBAAM,eAAe,iBAAiB,QAAQ,MAAM,UAAU;AAC9D,kBAAQ,MAAM,6BAA6B,KAAK;AAChD,iBAAO;AAAA,YACL,SAAS;AAAA,cACP;AAAA,gBACE,MAAM;AAAA,gBACN,MAAM,yBAAyB,YAAY;AAAA,cAC7C;AAAA,YACF;AAAA,YACA,SAAS;AAAA,UACX;AAAA,QACF;AAAA,MACF,WAAW,WAAW,SAAS,QAAQ;AAErC,cAAM,aAAa,QAAQ,OAAO,WAAW;AAE7C,YAAI;AAEF,gBAAMA,UAAS,MAAO,aAAqB;AAAA,YACzC;AAAA,YACA;AAAA,cACE,QAAQ,OAAO;AAAA,cACf,eAAe,WAAW;AAAA,cAC1B;AAAA;AAAA,YACF;AAAA,UACF;AAEA,cAAI,CAACA,SAAQ;AACX,kBAAM,UAAU,aACZ,WAAW,UAAU,sDAAsD,WAAW,aAAa,OACnG,sDAAsD,WAAW,aAAa;AAClF,mBAAO;AAAA,cACL,SAAS;AAAA,gBACP;AAAA,kBACE,MAAM;AAAA,kBACN,MAAM;AAAA,gBACR;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAGA,cAAI,kBAAkB;AACtB,cAAIA,QAAO,YAAYA,QAAO,SAAS,SAAS,GAAG;AACjD,kBAAM,cAAcA,QAAO,SACxB,IAAI,CAAC,MAAM,IAAI,IAAI,KAAK,EAAE,SAAS,EAAE,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,EAClE,KAAK,IAAI;AACZ,8BAAkB;AAAA;AAAA;AAAA;AAAA,EAA+B,WAAW;AAAA,UAC9D;AAEA,gBAAM,cAAcA,QAAO,YACvB;AAAA,WAAc,IAAI,KAAKA,QAAO,SAAS,EAAE,YAAY,CAAC,KACtD;AAEJ,iBAAO;AAAA,YACL,SAAS;AAAA,cACP;AAAA,gBACE,MAAM;AAAA,gBACN,MAAM,aAAaA,QAAO,IAAI,aAAa,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOpEA,QAAO,OAAO,GAAG,eAAe;AAAA;AAAA;AAAA;AAAA,cAIpB;AAAA,YACF;AAAA,UACF;AAAA,QACF,SAAS,OAAO;AACd,gBAAM,eAAe,iBAAiB,QAAQ,MAAM,UAAU;AAC9D,kBAAQ,MAAM,6BAA6B,KAAK;AAChD,iBAAO;AAAA,YACL,SAAS;AAAA,cACP;AAAA,gBACE,MAAM;AAAA,gBACN,MAAM,0BAA0B,YAAY;AAAA,cAC9C;AAAA,YACF;AAAA,YACA,SAAS;AAAA,UACX;AAAA,QACF;AAAA,MACF,WAAW,WAAW,SAAS,UAAU;AAEvC,cAAM,UAAU,QAAQ,OAAO,WAAW;AAE1C,YAAI,CAAC,SAAS;AACZ,iBAAO;AAAA,YACL,SAAS;AAAA,cACP;AAAA,gBACE,MAAM;AAAA,gBACN,MAAM;AAAA,cACR;AAAA,YACF;AAAA,YACA,SAAS;AAAA,UACX;AAAA,QACF;AAEA,YAAI;AAEF,gBAAMA,UAAS,MAAO,aAAqB;AAAA,YACzC;AAAA,YACA;AAAA,cACE,QAAQ,OAAO;AAAA,cACf,eAAe,WAAW;AAAA,cAC1B;AAAA,YACF;AAAA,UACF;AAEA,iBAAO;AAAA,YACL,SAAS;AAAA,cACP;AAAA,gBACE,MAAM;AAAA,gBACN,MAAM,0BAAqBA,QAAO,IAAI,mBAAmB,WAAW,aAAa;AAAA;AAAA,aAEpFA,QAAO,QAAQ,OAAOA,QAAO,SAAS;AAAA,WACxCA,QAAO,OAAO;AAAA;AAAA;AAAA,cAGX;AAAA,YACF;AAAA,UACF;AAAA,QACF,SAAS,OAAO;AACd,gBAAM,eAAe,iBAAiB,QAAQ,MAAM,UAAU;AAC9D,kBAAQ,MAAM,+BAA+B,KAAK;AAClD,iBAAO;AAAA,YACL,SAAS;AAAA,cACP;AAAA,gBACE,MAAM;AAAA,gBACN,MAAM,0BAA0B,YAAY;AAAA,cAC9C;AAAA,YACF;AAAA,YACA,SAAS;AAAA,UACX;AAAA,QACF;AAAA,MACF,WAAW,WAAW,SAAS,SAAS;AAEtC,cAAM,aAAa,QAAQ,OAAO,WAAW;AAE7C,YAAI,CAAC,YAAY;AACf,iBAAO;AAAA,YACL,SAAS;AAAA,cACP;AAAA,gBACE,MAAM;AAAA,gBACN,MAAM;AAAA,cACR;AAAA,YACF;AAAA,YACA,SAAS;AAAA,UACX;AAAA,QACF;AAEA,YAAI;AAEF,gBAAMA,UAAS,MAAO,aAAqB;AAAA,YACzC;AAAA,YACA;AAAA,cACE,QAAQ,OAAO;AAAA,cACf,eAAe,WAAW;AAAA,cAC1B;AAAA,YACF;AAAA,UACF;AAEA,iBAAO;AAAA,YACL,SAAS;AAAA,cACP;AAAA,gBACE,MAAM;AAAA,gBACN,MAAM,kBAAaA,QAAO,IAAI,0BAA0B,WAAW,aAAa;AAAA;AAAA,aAEnF,IAAI,KAAKA,QAAO,QAAQ,EAAE,YAAY,CAAC;AAAA;AAAA;AAAA,cAGtC;AAAA,YACF;AAAA,UACF;AAAA,QACF,SAAS,OAAO;AACd,gBAAM,eAAe,iBAAiB,QAAQ,MAAM,UAAU;AAC9D,kBAAQ,MAAM,8BAA8B,KAAK;AACjD,iBAAO;AAAA,YACL,SAAS;AAAA,cACP;AAAA,gBACE,MAAM;AAAA,gBACN,MAAM,yBAAyB,YAAY;AAAA,cAC7C;AAAA,YACF;AAAA,YACA,SAAS;AAAA,UACX;AAAA,QACF;AAAA,MACF,WAAW,WAAW,SAAS,WAAW;AAExC,cAAM,aAAa,QAAQ,OAAO,WAAW;AAC7C,cAAM,UAAU,QAAQ,OAAO,WAAW;AAE1C,YAAI,CAAC,cAAc,CAAC,SAAS;AAC3B,iBAAO;AAAA,YACL,SAAS;AAAA,cACP;AAAA,gBACE,MAAM;AAAA,gBACN,MAAM;AAAA,cACR;AAAA,YACF;AAAA,YACA,SAAS;AAAA,UACX;AAAA,QACF;AAEA,YAAI;AAEF,gBAAMA,UAAS,MAAO,aAAqB;AAAA,YACzC;AAAA,YACA;AAAA,cACE,QAAQ,OAAO;AAAA,cACf,eAAe,WAAW;AAAA,cAC1B;AAAA,cACA;AAAA,YACF;AAAA,UACF;AAEA,iBAAO;AAAA,YACL,SAAS;AAAA,cACP;AAAA,gBACE,MAAM;AAAA,gBACN,MAAM,mCAA8BA,QAAO,UAAU;AAAA;AAAA,kBAAyBA,QAAO,YAAY;AAAA,cACnG;AAAA,YACF;AAAA,UACF;AAAA,QACF,SAAS,OAAO;AACd,gBAAM,eAAe,iBAAiB,QAAQ,MAAM,UAAU;AAC9D,kBAAQ,MAAM,gCAAgC,KAAK;AACnD,iBAAO;AAAA,YACL,SAAS;AAAA,cACP;AAAA,gBACE,MAAM;AAAA,gBACN,MAAM,yBAAyB,YAAY;AAAA,cAC7C;AAAA,YACF;AAAA,YACA,SAAS;AAAA,UACX;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAGA,UAAM,SAAS,aAAa,KAAK,CAAC,MAAM,gBAAgB,CAAC,MAAM,QAAQ;AAEvE,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI,MAAM,iBAAiB,QAAQ,EAAE;AAAA,IAC7C;AAGA,UAAM,UAAU,mBAAmB,QAAQ,QAAQ,YAAY;AAC/D,UAAM,SAAS,MAAM,QAAQ;AAI7B,UAAM,aAAa,OAAO,SACvB,IAAI,CAAC,QAAS,OAAO,IAAI,YAAY,WAAW,IAAI,UAAU,IAAI,QAAQ,IAAK,EAC/E,KAAK,MAAM;AAEd,WAAO;AAAA,MACL,SAAS;AAAA,QACP;AAAA,UACE,MAAM;AAAA,UACN,MAAM;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAAA,EACF,CAAC;AAGD,QAAM,YAAY,IAAI,qBAAqB;AAC3C,QAAM,OAAO,QAAQ,SAAS;AAE9B,UAAQ,MAAM,mCAAmC;AACjD,UAAQ,MAAM,qBAAqB,OAAO,QAAQ,gBAAgB,YAAY,EAAE;AAChF,UAAQ,MAAM,qBAAqB,OAAO,SAAS,EAAE;AACrD,UAAQ,MAAM,oEAAoE;AAGlF,QAAM,iBAAiB,CAAC,GAAG,MAAM,KAAK,WAAW,CAAC,EAAE,KAAK;AACzD,UAAQ,MAAM,4BAA4B,eAAe,KAAK,IAAI,CAAC,EAAE;AACrE,UAAQ,MAAM,4BAA4B,YAAY,IAAI,EAAE;AAI5D,cAAY,MAAM;AAAA,EAElB,GAAG,GAAK;AAGR,SAAO,IAAI,QAAc,MAAM;AAAA,EAG/B,CAAC;AACH;AAKA,eAAe,eACb,QACA,QAC8D;AAC9D,MAAI;AAEF,UAAM,SAAS,MAAM,OAAO,MAAM,0BAAiC,EAAE,KAAK,OAAO,CAAC;AAClF,QAAI,QAAQ;AACV,aAAO,EAAE,OAAO,MAAM,QAAQ,OAAO,OAAO;AAAA,IAC9C;AACA,WAAO,EAAE,OAAO,OAAO,OAAO,kBAAkB;AAAA,EAClD,SAAS,OAAO;AACd,WAAO;AAAA,MACL,OAAO;AAAA,MACP,OAAO,iBAAiB,QAAQ,MAAM,UAAU;AAAA,IAClD;AAAA,EACF;AACF;AAMA,eAAe,gBACb,QACA,QACA,YACsB;AACtB,MAAI;AAEF,UAAM,UAAU,MAAM,OAAO,MAAM,6BAAoC;AAAA,MACrE;AAAA,MACA,YAAY,WAAW,SAAS,IAAI,aAAa;AAAA;AAAA,IACnD,CAAC;AACD,WAAO;AAAA,EACT,SAAS,OAAO;AACd,UAAM,IAAI;AAAA,MACR,4BAA4B,iBAAiB,QAAQ,MAAM,UAAU,eAAe;AAAA,IACtF;AAAA,EACF;AACF;;;AF94BA,eAAe,OAAO;AACpB,MAAI;AAEF,UAAM,OAAO,SAAS,QAAQ,KAAK,MAAM,CAAC,CAAC;AAC3C,UAAM,QAAQ,KAAK,QAAQ;AAI3B,UAAM,gBAAgB,KAAK,cAAc,KAAK;AAC9C,QAAI,qBAA+B,CAAC;AACpC,QAAI,eAAe;AACjB,UAAI,MAAM,QAAQ,aAAa,GAAG;AAEhC,6BAAqB,cAAc,QAAQ,CAAC,MAAc,OAAO,CAAC,EAAE,MAAM,GAAG,CAAC;AAAA,MAChF,OAAO;AAEL,6BAAqB,OAAO,aAAa,EAAE,MAAM,GAAG;AAAA,MACtD;AAEA,2BAAqB,mBAAmB,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,OAAO;AAAA,IAC7E;AAGA,UAAM,SAAS,QAAQ,IAAI,eAAe,QAAQ,IAAI;AACtD,QAAI,CAAC,QAAQ;AACX,cAAQ;AAAA,QACN;AAAA,MACF;AACA,cAAQ;AAAA,QACN;AAAA,MACF;AACA,cAAQ,MAAM,8CAA8C;AAC5D,cAAQ,KAAK,CAAC;AAAA,IAChB;AAGA,UAAM,eAAe,mBAAmB,KAAK;AAC7C,UAAM,YAAY,QACd,6CACA;AAGJ,UAAM,SAAuB;AAAA,MAC3B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,IACF;AAGA,UAAM,YAAY,QAAQ,YAAY;AAGtC,YAAQ,MAAM,2DAA2D;AAAA,EAC3E,SAAS,OAAO;AACd,YAAQ;AAAA,MACN;AAAA,MACA,iBAAiB,QAAQ,MAAM,UAAU;AAAA,IAC3C;AACA,QAAI,iBAAiB,SAAS,MAAM,OAAO;AACzC,cAAQ,MAAM,MAAM,KAAK;AAAA,IAC3B;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;AAGA,QAAQ,GAAG,UAAU,MAAM;AACzB,UAAQ,MAAM,oDAAoD;AAClE,UAAQ,KAAK,CAAC;AAChB,CAAC;AAED,QAAQ,GAAG,WAAW,MAAM;AAC1B,UAAQ,MAAM,qDAAqD;AACnE,UAAQ,KAAK,CAAC;AAChB,CAAC;AAED,KAAK;","names":["result"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/convex-client.ts","../src/server.ts","../src/prompt-builder.ts"],"sourcesContent":["import minimist from \"minimist\";\nimport { createConvexClient } from \"./convex-client.js\";\nimport { startServer } from \"./server.js\";\nimport type { ServerConfig } from \"./types.js\";\n\n/**\n * Main entry point for the MCP server\n */\nasync function main() {\n try {\n // Parse CLI arguments\n const argv = minimist(process.argv.slice(2));\n const isDev = argv.dev === true;\n\n // Parse --workspaces CLI argument (Ticket 144)\n // Can be: --workspaces ws1,ws2 OR --workspaces ws1 --workspaces ws2 OR -w ws1,ws2\n const workspacesArg = argv.workspaces || argv.w;\n let selectedWorkspaces: string[] = [];\n if (workspacesArg) {\n if (Array.isArray(workspacesArg)) {\n // Multiple --workspaces flags: [\"ws1\", \"ws2\"]\n selectedWorkspaces = workspacesArg.flatMap((w: string) => String(w).split(','));\n } else {\n // Single --workspaces flag with comma-separated: \"ws1,ws2\"\n selectedWorkspaces = String(workspacesArg).split(',');\n }\n // Clean up whitespace\n selectedWorkspaces = selectedWorkspaces.map((s) => s.trim()).filter(Boolean);\n }\n\n // Check for API key (PPM_API_KEY with backward compatibility for THEPROMPTEDITOR_API_KEY)\n const apiKey = process.env.PPM_API_KEY || process.env.THEPROMPTEDITOR_API_KEY;\n if (!apiKey) {\n console.error(\n \"[MCP] ERROR: Missing PPM_API_KEY environment variable\"\n );\n console.error(\n \"[MCP] Please set your API key from Prompt Project Manager Settings page:\"\n );\n console.error(\"[MCP] export PPM_API_KEY=your_api_key_here\");\n process.exit(1);\n }\n\n // Create Convex client\n const convexClient = createConvexClient(isDev);\n const convexUrl = isDev\n ? \"https://hallowed-shrimp-344.convex.cloud\"\n : \"https://trustworthy-squirrel-735.convex.cloud\";\n\n // Build server config\n const config: ServerConfig = {\n apiKey,\n isDev,\n convexUrl,\n selectedWorkspaces, // Workspace slugs to filter (empty = all workspaces)\n };\n\n // Start server - this will keep the process alive via stdio transport\n await startServer(config, convexClient);\n\n // This line should never be reached if the promise in startServer never resolves\n console.error(\"[MCP] WARNING: startServer promise resolved unexpectedly!\");\n } catch (error) {\n console.error(\n \"[MCP] FATAL ERROR:\",\n error instanceof Error ? error.message : \"Unknown error\"\n );\n if (error instanceof Error && error.stack) {\n console.error(error.stack);\n }\n process.exit(1);\n }\n}\n\n// Handle graceful shutdown\nprocess.on(\"SIGINT\", () => {\n console.error(\"[MCP] Received SIGINT, shutting down gracefully...\");\n process.exit(0);\n});\n\nprocess.on(\"SIGTERM\", () => {\n console.error(\"[MCP] Received SIGTERM, shutting down gracefully...\");\n process.exit(0);\n});\n\nmain();\n","import { ConvexHttpClient } from \"convex/browser\";\n\nconst PROD_URL = \"https://trustworthy-squirrel-735.convex.cloud\";\nconst DEV_URL = \"https://hallowed-shrimp-344.convex.cloud\";\n\n/**\n * Create a Convex HTTP client for the appropriate deployment\n */\nexport function createConvexClient(isDev: boolean): ConvexHttpClient {\n const url = isDev ? DEV_URL : PROD_URL;\n return new ConvexHttpClient(url);\n}\n","import { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport {\n CallToolRequestSchema,\n GetPromptRequestSchema,\n ListPromptsRequestSchema,\n ListToolsRequestSchema,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport type { ConvexHttpClient } from \"convex/browser\";\nimport type { McpPrompt, ServerConfig } from \"./types.js\";\n\n/**\n * Result from executing the next ticket (Ticket 151: now moves to working status)\n */\ninterface ExecuteTicketResult {\n content: string | null;\n slug: string;\n status: string; // Ticket 151: \"working\" (no longer \"closed\")\n remainingTickets: number;\n}\n\n/**\n * Close ticket result (Ticket 151)\n */\ninterface CloseTicketResult {\n slug: string;\n status: string;\n closedAt: number;\n}\n\n/**\n * Message result (Ticket 151)\n */\ninterface AddMessageResult {\n ticketSlug: string;\n messageCount: number;\n createdAt: number;\n}\n\nimport { buildPromptHandler, buildPromptName, buildPromptSchema } from \"./prompt-builder.js\";\n\n/**\n * Built-in system tools\n */\nconst SYSTEM_TOOLS: {\n name: string;\n description: string;\n inputSchema: object;\n promptContent: string;\n isSlashCommand: boolean; // true = appears as /ppm:name, false = tool only\n}[] = [\n // Utility tool: /ppm:system:prompts\n {\n name: \"system:prompts\",\n description: \"List all available prompts from Prompt Project Manager\",\n inputSchema: {\n type: \"object\",\n properties: {\n search: {\n type: \"string\",\n description: \"Optional search term to filter prompts by name or description (case-insensitive)\",\n },\n },\n },\n isSlashCommand: true,\n promptContent: `# List Prompts\n\nThis is a utility tool. Call it directly as a tool to list all available prompts.\n\nExample: Use the \\`system:prompts\\` tool with optional \\`search\\` parameter to filter results.`,\n },\n // Note: run_prompt is now workspace-scoped (see dynamicRunPromptTools below)\n];\n\n/**\n * Initialize and start the MCP server\n */\nexport async function startServer(\n config: ServerConfig,\n convexClient: ConvexHttpClient\n): Promise<void> {\n // Validate API key with Convex\n console.error(\"[MCP] Validating API key...\");\n const validation = await validateApiKey(convexClient, config.apiKey);\n if (!validation.valid) {\n throw new Error(`Invalid API key: ${validation.error}`);\n }\n console.error(`[MCP] API key validated for user: ${validation.userId}`);\n\n // Fetch prompts exposed to MCP (with optional workspace filter from CLI)\n console.error(\"[MCP] Fetching exposed prompts...\");\n const prompts = await fetchMcpPrompts(convexClient, config.apiKey, config.selectedWorkspaces);\n console.error(`[MCP] Found ${prompts.length} exposed prompts`);\n\n if (prompts.length === 0) {\n if (config.selectedWorkspaces.length > 0) {\n console.error(\n `[MCP] WARNING: No prompts found in workspaces: ${config.selectedWorkspaces.join(', ')}. Check that these workspace slugs exist and contain prompts.`\n );\n } else {\n console.error(\n \"[MCP] WARNING: No prompts found. Create some prompts in Prompt Project Manager to expose them via MCP.\"\n );\n }\n }\n\n // Filter out prompts with missing flattened content\n const validPrompts = prompts.filter((p) => {\n if (!p.flattenedPrompt) {\n console.error(\n `[MCP] WARNING: Skipping prompt \"${p.name}\" (${p.slug}) - missing flattened content. Re-save in ContextFS to regenerate.`\n );\n return false;\n }\n return true;\n });\n\n // Log workspace filtering info (Ticket 144)\n if (config.selectedWorkspaces.length > 0) {\n console.error(`[MCP] Workspace filter: ${config.selectedWorkspaces.join(', ')}`);\n } else {\n console.error(`[MCP] Workspace filter: ALL (no --workspaces specified)`);\n }\n console.error(`[MCP] Registering ${validPrompts.length} prompts...`);\n\n // Build dynamic ticket tools per workspace (Ticket 135, 149, 151, 153)\n // Streamlined command set: open, work, close, message, create\n const workspaceSlugs = new Set(validPrompts.map((p) => p.workspaceSlug).filter((s): s is string => !!s));\n const dynamicTicketTools: { name: string; description: string; workspaceSlug: string; type: 'open' | 'work' | 'close' | 'message' | 'create' }[] = [];\n\n for (const workspaceSlug of workspaceSlugs) {\n // Ticket 153: tickets:open (renamed from tickets:next)\n dynamicTicketTools.push({\n name: `${workspaceSlug}:tickets:open`,\n description: `Open the next ticket from the \"${workspaceSlug}\" workspace queue and move it to working status. Optionally specify a ticket number or slug.`,\n workspaceSlug,\n type: 'open',\n });\n // Ticket 153: tickets:work (context recovery for working tickets)\n dynamicTicketTools.push({\n name: `${workspaceSlug}:tickets:work`,\n description: `Resume work on a ticket in the \"${workspaceSlug}\" workspace. Returns ticket content and all progress messages for context recovery.`,\n workspaceSlug,\n type: 'work',\n });\n dynamicTicketTools.push({\n name: `${workspaceSlug}:tickets:close`,\n description: `Mark a working ticket as completed in the \"${workspaceSlug}\" workspace`,\n workspaceSlug,\n type: 'close',\n });\n dynamicTicketTools.push({\n name: `${workspaceSlug}:tickets:message`,\n description: `Add a progress message to a working or closed ticket in the \"${workspaceSlug}\" workspace`,\n workspaceSlug,\n type: 'message',\n });\n dynamicTicketTools.push({\n name: `${workspaceSlug}:tickets:create`,\n description: `Create a new ticket in the \"${workspaceSlug}\" workspace queue`,\n workspaceSlug,\n type: 'create',\n });\n }\n\n console.error(`[MCP] Registering ${dynamicTicketTools.length} ticket tools for ${workspaceSlugs.size} workspace(s)...`);\n\n // Build dynamic run_prompt tools per workspace (scoped like tickets)\n const dynamicRunPromptTools: { name: string; description: string; workspaceSlug: string }[] = [];\n\n for (const workspaceSlug of workspaceSlugs) {\n dynamicRunPromptTools.push({\n name: `${workspaceSlug}:run_prompt`,\n description: `Execute a prompt from the \"${workspaceSlug}\" workspace by slug. Use system:prompts to list available prompts.`,\n workspaceSlug,\n });\n }\n\n console.error(`[MCP] Registering ${dynamicRunPromptTools.length} run_prompt tools for ${workspaceSlugs.size} workspace(s)...`);\n\n // Check for duplicate prompt names\n const promptNames = new Set<string>();\n const duplicates: string[] = [];\n validPrompts.forEach((p) => {\n const name = buildPromptName(p);\n if (promptNames.has(name)) {\n duplicates.push(name);\n }\n promptNames.add(name);\n });\n\n if (duplicates.length > 0) {\n console.error(\n `[MCP] WARNING: Duplicate prompt names detected: ${duplicates.join(\", \")}. Only the first occurrence will be registered.`\n );\n }\n\n // Create MCP server\n const server = new Server(\n {\n name: \"ppm-mcp-server\",\n version: \"3.0.1\",\n },\n {\n capabilities: {\n prompts: {},\n tools: {},\n },\n }\n );\n\n // Register list_prompts handler\n // Note: Individual prompts no longer listed - use workspace:run_prompt instead\n server.setRequestHandler(ListPromptsRequestSchema, async () => {\n // Build system tool schemas (only those marked as slash commands)\n const systemPromptSchemas = SYSTEM_TOOLS\n .filter((st) => st.isSlashCommand) // Only include user-facing slash commands\n .map((st) => ({\n name: st.name,\n description: st.description,\n }));\n\n // Build ticket prompt schemas (Ticket 135, 149, 153 - register as slash commands)\n // All ticket tools are available as slash commands\n const ticketPromptSchemas = dynamicTicketTools.map((tt) => ({\n name: tt.name,\n description: tt.description,\n }));\n\n // Build run_prompt schemas per workspace (replaces individual prompt listings)\n const runPromptSchemas = dynamicRunPromptTools.map((rp) => ({\n name: rp.name,\n description: rp.description,\n }));\n\n return {\n prompts: [\n ...systemPromptSchemas,\n ...ticketPromptSchemas,\n ...runPromptSchemas,\n ],\n };\n });\n\n // Register get_prompt handler\n server.setRequestHandler(GetPromptRequestSchema, async (request) => {\n const promptName = request.params.name;\n\n // Check for system tools first (as prompts for slash command access)\n const systemTool = SYSTEM_TOOLS.find((st) => st.name === promptName);\n if (systemTool) {\n return {\n description: systemTool.description,\n messages: [\n {\n role: \"user\" as const,\n content: {\n type: \"text\" as const,\n text: systemTool.promptContent,\n },\n },\n ],\n };\n }\n\n // Check for ticket commands (Ticket 135, 149, 153 - handle as slash commands)\n // Handle exact matches and :open with optional argument (e.g., \"workspace:tickets:open 102\")\n const ticketTool = dynamicTicketTools.find((tt) => tt.name === promptName);\n const ticketOpenMatch = promptName.match(/^(.+):tickets:open\\s+(.+)$/);\n\n if (ticketTool || ticketOpenMatch) {\n let promptContent: string;\n let description: string;\n\n if (ticketOpenMatch) {\n // Handle tickets:open with specific ticket argument\n const workspaceSlug = ticketOpenMatch[1];\n const ticketArg = ticketOpenMatch[2].trim();\n description = `Open ticket \"${ticketArg}\" from \"${workspaceSlug}\"`;\n promptContent = `Open ticket \"${ticketArg}\" from the \"${workspaceSlug}\" workspace queue and move it to working status.\\n\\nCall the \\`${workspaceSlug}:tickets:open\\` tool with ticketSlug: \"${ticketArg}\".`;\n } else if (ticketTool!.type === 'open') {\n // Ticket 153: tickets:open (renamed from tickets:next)\n description = ticketTool!.description;\n promptContent = `Open the next ticket from the \"${ticketTool!.workspaceSlug}\" workspace queue and move it to working status.\\n\\nCall the \\`${ticketTool!.name}\\` tool to get the next ticket.\\n\\nYou can also specify a ticket: /ppm:${ticketTool!.workspaceSlug}:tickets:open <number-or-slug>`;\n } else if (ticketTool!.type === 'work') {\n // Ticket 153: tickets:work (context recovery)\n description = ticketTool!.description;\n promptContent = `Resume work on a ticket in the \"${ticketTool!.workspaceSlug}\" workspace.\\n\\nCall the \\`${ticketTool!.name}\\` tool to get ticket content and all progress messages for context recovery.\\n\\nIf no ticket slug is provided, returns the first working ticket (by startedAt).\\n\\nYou can also specify a ticket: /ppm:${ticketTool!.workspaceSlug}:tickets:work <number-or-slug>`;\n } else if (ticketTool!.type === 'create') {\n // Ticket 149: tickets:create slash command\n description = ticketTool!.description;\n promptContent = `Create a new ticket in the \"${ticketTool!.workspaceSlug}\" workspace queue.\n\n## How This Works\nThe user provides **instructions** (not raw content). You interpret those instructions to generate the ticket.\n\n## Instructions\n1. **Read the user's request** - they may reference a file, ask you to summarize a session, or describe what they want\n2. **Process the input** - read files, extract relevant sections, summarize as needed\n3. **Generate ticket content** with a clear, descriptive title as the first line\n4. **Call the tool** with the generated content\n\n## Content Format\n\\`\\`\\`\n[Clear descriptive title - this becomes the slug]\n\n[Body content - tasks, description, context, etc.]\n\\`\\`\\`\n\n## Examples\n- \"create a ticket from /path/to/plan.md\" → Read file, use as ticket content\n- \"summarize our brainstorm into a ticket\" → Extract key points from conversation\n- \"create a ticket for the auth bug we discussed\" → Generate from session context\n- \"just the tasks from this file\" → Extract only task items\n\nCall the \\`${ticketTool!.name}\\` tool with the final generated content.`;\n } else if (ticketTool!.type === 'close') {\n description = ticketTool!.description;\n promptContent = `Close a working ticket in the \"${ticketTool!.workspaceSlug}\" workspace.\\n\\nCall the \\`${ticketTool!.name}\\` tool with the ticket number or slug.`;\n } else if (ticketTool!.type === 'message') {\n description = ticketTool!.description;\n promptContent = `Add a progress message to a working or closed ticket in the \"${ticketTool!.workspaceSlug}\" workspace.\\n\\nCall the \\`${ticketTool!.name}\\` tool with the ticket number/slug and your message.`;\n } else {\n // Fallback for unknown type\n description = ticketTool!.description;\n promptContent = `Use the \\`${ticketTool!.name}\\` tool.`;\n }\n\n return {\n description,\n messages: [\n {\n role: \"user\" as const,\n content: {\n type: \"text\" as const,\n text: promptContent,\n },\n },\n ],\n };\n }\n\n // Check for workspace:run_prompt commands (with optional prompt slug argument)\n const runPromptTool = dynamicRunPromptTools.find((rp) => rp.name === promptName);\n const runPromptMatch = promptName.match(/^(.+):run_prompt\\s+(.+)$/);\n\n if (runPromptTool || runPromptMatch) {\n let promptContent: string;\n let description: string;\n\n if (runPromptMatch) {\n // Handle run_prompt with specific prompt slug argument\n const workspaceSlug = runPromptMatch[1];\n const promptSlug = runPromptMatch[2].trim();\n description = `Execute prompt \"${promptSlug}\" from \"${workspaceSlug}\"`;\n promptContent = `Execute the \"${promptSlug}\" prompt from the \"${workspaceSlug}\" workspace.\\n\\nCall the \\`${workspaceSlug}:run_prompt\\` tool with slug: \"${promptSlug}\".`;\n } else {\n // Base run_prompt without argument - show help\n description = runPromptTool!.description;\n promptContent = `Execute a prompt from the \"${runPromptTool!.workspaceSlug}\" workspace.\n\n## Usage\nCall the \\`${runPromptTool!.name}\\` tool with the prompt slug.\n\n## Available Prompts\nUse \\`system:prompts\\` to list all available prompts in this workspace.\n\n## Example\n/ppm:${runPromptTool!.workspaceSlug}:run_prompt code-review\n\nThis will execute the \"code-review\" prompt.`;\n }\n\n return {\n description,\n messages: [\n {\n role: \"user\" as const,\n content: {\n type: \"text\" as const,\n text: promptContent,\n },\n },\n ],\n };\n }\n\n // Unknown prompt\n throw new Error(`Unknown prompt: ${promptName}. Use workspace:run_prompt to execute prompts.`);\n });\n\n // Register list_tools handler\n // Note: Per-prompt tool registration removed in favor of workspace-scoped run_prompt tools\n // This reduces token overhead and allows dynamic prompt discovery without server restart\n server.setRequestHandler(ListToolsRequestSchema, async () => {\n // Build tools array: system tools + ticket tools + workspace:run_prompt tools\n // Individual prompts no longer registered as separate tools\n const tools = [\n // System tools with full input schemas\n ...SYSTEM_TOOLS.map((st) => ({\n name: st.name,\n description: st.description,\n inputSchema: st.inputSchema,\n })),\n // Dynamic ticket tools per workspace (Ticket 135, 149, 151, 153)\n ...dynamicTicketTools.map((tt) => {\n // Build inputSchema based on tool type\n let inputSchema: { type: \"object\"; properties: Record<string, object>; required: string[] };\n\n if (tt.type === 'close') {\n // close requires a ticketSlug\n inputSchema = {\n type: \"object\" as const,\n properties: {\n ticketSlug: {\n type: \"string\",\n description: \"Ticket number (e.g., '102') or full slug (e.g., '102-fix-auth')\",\n },\n },\n required: [\"ticketSlug\"],\n };\n } else if (tt.type === 'open') {\n // Ticket 153: tickets:open (renamed from tickets:next)\n inputSchema = {\n type: \"object\" as const,\n properties: {\n ticketSlug: {\n type: \"string\",\n description: \"Optional: Ticket number (e.g., '102') or full slug (e.g., '102-fix-auth'). If not provided, opens the next ticket in queue.\",\n },\n },\n required: [],\n };\n } else if (tt.type === 'work') {\n // Ticket 153: tickets:work (context recovery)\n inputSchema = {\n type: \"object\" as const,\n properties: {\n ticketSlug: {\n type: \"string\",\n description: \"Optional: Ticket number (e.g., '102') or full slug. If not provided, returns the first working ticket by startedAt.\",\n },\n },\n required: [],\n };\n } else if (tt.type === 'create') {\n inputSchema = {\n type: \"object\" as const,\n properties: {\n content: {\n type: \"string\",\n description: \"The generated ticket content. First line should be a clear descriptive title (becomes the slug). Body contains tasks, description, context as needed.\",\n },\n },\n required: [\"content\"],\n };\n } else if (tt.type === 'message') {\n // Ticket 151: message requires ticketSlug and message\n inputSchema = {\n type: \"object\" as const,\n properties: {\n ticketSlug: {\n type: \"string\",\n description: \"Ticket number (e.g., '102') or full slug (e.g., '102-fix-auth')\",\n },\n message: {\n type: \"string\",\n description: \"Progress message to add to the ticket\",\n },\n },\n required: [\"ticketSlug\", \"message\"],\n };\n } else {\n // Fallback: no params\n inputSchema = {\n type: \"object\" as const,\n properties: {},\n required: [],\n };\n }\n\n return {\n name: tt.name,\n description: tt.description,\n inputSchema,\n };\n }),\n // Dynamic run_prompt tools per workspace\n ...dynamicRunPromptTools.map((rp) => ({\n name: rp.name,\n description: rp.description,\n inputSchema: {\n type: \"object\" as const,\n properties: {\n slug: {\n type: \"string\",\n description: \"Prompt slug to execute (e.g., 'code-review', 'plan')\",\n },\n },\n required: [\"slug\"],\n },\n })),\n ];\n\n return { tools };\n });\n\n // Register call_tool handler\n server.setRequestHandler(CallToolRequestSchema, async (request) => {\n const toolName = request.params.name;\n\n // Handle workspace:run_prompt tools - dynamic prompt execution per workspace\n const runPromptTool = dynamicRunPromptTools.find((rp) => rp.name === toolName);\n if (runPromptTool) {\n const promptSlug = request.params.arguments?.slug as string | undefined;\n\n if (!promptSlug) {\n return {\n content: [\n {\n type: \"text\",\n text: `Error: Missing 'slug' parameter. Provide prompt slug (e.g., 'code-review', 'plan').\n\nUse \\`system:prompts\\` to list available prompts in \"${runPromptTool.workspaceSlug}\".`,\n },\n ],\n isError: true,\n };\n }\n\n // Build the full prompt name: workspace:slug\n const fullPromptName = `${runPromptTool.workspaceSlug}:${promptSlug}`;\n\n // Look up the prompt dynamically\n const prompt = validPrompts.find((p) => buildPromptName(p) === fullPromptName);\n\n if (!prompt) {\n return {\n content: [\n {\n type: \"text\",\n text: `Error: Unknown prompt \"${promptSlug}\" in workspace \"${runPromptTool.workspaceSlug}\".\n\nUse \\`system:prompts\\` to list available prompts.`,\n },\n ],\n isError: true,\n };\n }\n\n // Execute the prompt and return flattened content\n try {\n const handler = buildPromptHandler(prompt, config, convexClient);\n const result = await handler();\n\n // Convert prompt result to tool result format\n const promptText = result.messages\n .map((msg) => (typeof msg.content === 'string' ? msg.content : msg.content.text))\n .join('\\n\\n');\n\n return {\n content: [\n {\n type: \"text\",\n text: promptText,\n },\n ],\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : \"Unknown error\";\n console.error(`[MCP] ${toolName} error:`, error);\n return {\n content: [\n {\n type: \"text\",\n text: `Error executing prompt \"${promptSlug}\": ${errorMessage}`,\n },\n ],\n isError: true,\n };\n }\n }\n\n // Handle system:prompts tool\n if (toolName === \"system:prompts\") {\n const searchTerm = request.params.arguments?.search as string | undefined;\n const uniquePrompts = Array.from(\n new Map(validPrompts.map((p) => [buildPromptName(p), p])).values()\n );\n\n // Filter system tools\n let filteredSystemTools = SYSTEM_TOOLS;\n if (searchTerm) {\n const lowerSearch = searchTerm.toLowerCase();\n filteredSystemTools = SYSTEM_TOOLS.filter(\n (st) =>\n st.name.toLowerCase().includes(lowerSearch) ||\n st.description.toLowerCase().includes(lowerSearch)\n );\n }\n\n // Filter user prompts\n let filteredPrompts = uniquePrompts;\n if (searchTerm) {\n const lowerSearch = searchTerm.toLowerCase();\n filteredPrompts = uniquePrompts.filter(\n (p) =>\n buildPromptName(p).toLowerCase().includes(lowerSearch) ||\n p.name.toLowerCase().includes(lowerSearch) ||\n p.description?.toLowerCase().includes(lowerSearch)\n );\n }\n\n // Sort user prompts by workspace then by prompt slug\n filteredPrompts.sort((a, b) => {\n const aName = buildPromptName(a);\n const bName = buildPromptName(b);\n return aName.localeCompare(bName);\n });\n\n // Build system tools list\n const systemToolList = filteredSystemTools\n .map((st) => `• ${st.name}\\n Type: System\\n Description: ${st.description}`)\n .join(\"\\n\\n\");\n\n // Build user prompts list\n const userPromptList = filteredPrompts\n .map((p) => {\n const name = buildPromptName(p);\n const workspace = p.workspaceSlug || \"unknown\";\n const desc = p.description || \"No description\";\n return `• ${name}\\n Workspace: ${workspace}\\n Description: ${desc}`;\n })\n .join(\"\\n\\n\");\n\n const totalCount = filteredSystemTools.length + filteredPrompts.length;\n const summary = searchTerm\n ? `Found ${totalCount} prompts matching \"${searchTerm}\":`\n : `Available prompts (${totalCount} total):`;\n\n const sections: string[] = [];\n if (systemToolList) {\n sections.push(`**System Tools:**\\n\\n${systemToolList}`);\n }\n if (userPromptList) {\n sections.push(`**User Prompts:**\\n\\n${userPromptList}`);\n }\n\n return {\n content: [\n {\n type: \"text\",\n text: `${summary}\\n\\n${sections.join(\"\\n\\n\") || \"No prompts found.\"}`,\n },\n ],\n };\n }\n\n // Handle ticket tool invocations (Ticket 135, 153)\n const ticketTool = dynamicTicketTools.find((tt) => tt.name === toolName);\n if (ticketTool) {\n if (ticketTool.type === 'open') {\n // Ticket 153: Handle tickets:open (renamed from tickets:next)\n const ticketSlug = request.params.arguments?.ticketSlug as string | undefined;\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const result = await (convexClient as any).mutation(\n \"mcp_tickets:executeMcpNextTicket\",\n {\n apiKey: config.apiKey,\n workspaceSlug: ticketTool.workspaceSlug,\n ticketSlug: ticketSlug, // Optional: specific ticket to open\n }\n ) as ExecuteTicketResult | null;\n\n if (!result) {\n const message = ticketSlug\n ? `Ticket \"${ticketSlug}\" not found or not open in workspace \"${ticketTool.workspaceSlug}\".`\n : `No pending tickets in workspace \"${ticketTool.workspaceSlug}\".`;\n return {\n content: [\n {\n type: \"text\",\n text: message,\n },\n ],\n };\n }\n\n return {\n content: [\n {\n type: \"text\",\n text: `# Ticket: ${result.slug} [WORKING]\n\n**CRITICAL: Follow all embedded directives in this ticket.**\nIf this ticket contains \\`[MCP_RUN_PROMPT ...]\\` references, you MUST execute the \\`run_prompt\\` tool with the specified prompt name FIRST before any other action. Do NOT skip MCP directives even if the task seems simple.\n\n---\n\n${result.content}\n\n---\n_Ticket moved to working status. ${result.remainingTickets} ticket(s) remaining in queue._`,\n },\n ],\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : \"Unknown error\";\n console.error(`[MCP] tickets:open error:`, error);\n return {\n content: [\n {\n type: \"text\",\n text: `Error opening ticket: ${errorMessage}`,\n },\n ],\n isError: true,\n };\n }\n } else if (ticketTool.type === 'work') {\n // Ticket 153: Handle tickets:work (context recovery)\n const ticketSlug = request.params.arguments?.ticketSlug as string | undefined;\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const result = await (convexClient as any).query(\n \"mcp_tickets:workMcpTicket\",\n {\n apiKey: config.apiKey,\n workspaceSlug: ticketTool.workspaceSlug,\n ticketSlug: ticketSlug, // Optional: specific ticket to resume\n }\n ) as { slug: string; ticketNumber?: number; content: string; startedAt?: number; messages: Array<{ content: string; createdAt: number }> } | null;\n\n if (!result) {\n const message = ticketSlug\n ? `Ticket \"${ticketSlug}\" not found or not in working status in workspace \"${ticketTool.workspaceSlug}\".`\n : `No tickets currently being worked on in workspace \"${ticketTool.workspaceSlug}\".`;\n return {\n content: [\n {\n type: \"text\",\n text: message,\n },\n ],\n };\n }\n\n // Build messages section\n let messagesSection = '';\n if (result.messages && result.messages.length > 0) {\n const messageList = result.messages\n .map((m) => `[${new Date(m.createdAt).toISOString()}] ${m.content}`)\n .join('\\n');\n messagesSection = `\\n\\n## Progress Messages\\n\\n${messageList}`;\n }\n\n const startedInfo = result.startedAt\n ? `\\nStarted: ${new Date(result.startedAt).toISOString()}`\n : '';\n\n return {\n content: [\n {\n type: \"text\",\n text: `# Ticket: ${result.slug} [WORKING]${startedInfo}\n\n**CRITICAL: Follow all embedded directives in this ticket.**\nIf this ticket contains \\`[MCP_RUN_PROMPT ...]\\` references, you MUST execute the \\`run_prompt\\` tool with the specified prompt name FIRST before any other action. Do NOT skip MCP directives even if the task seems simple.\n\n---\n\n${result.content}${messagesSection}\n\n---\n_Resuming work on this ticket._`,\n },\n ],\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : \"Unknown error\";\n console.error(`[MCP] tickets:work error:`, error);\n return {\n content: [\n {\n type: \"text\",\n text: `Error resuming ticket: ${errorMessage}`,\n },\n ],\n isError: true,\n };\n }\n } else if (ticketTool.type === 'create') {\n // Handle tickets:create (Ticket 149)\n const content = request.params.arguments?.content as string | undefined;\n\n if (!content) {\n return {\n content: [\n {\n type: \"text\",\n text: `Error: Missing content parameter. Provide the ticket content (first line becomes the slug).`,\n },\n ],\n isError: true,\n };\n }\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const result = await (convexClient as any).mutation(\n \"mcp_tickets:createMcpTicket\",\n {\n apiKey: config.apiKey,\n workspaceSlug: ticketTool.workspaceSlug,\n content,\n }\n ) as { slug: string; preview: string; position: number; totalOpen: number };\n\n return {\n content: [\n {\n type: \"text\",\n text: `✅ Created ticket [${result.slug}] in workspace \"${ticketTool.workspaceSlug}\".\n\nPosition: #${result.position} of ${result.totalOpen} open tickets\nPreview: ${result.preview}\n\n_Note: If this ticket contains \\`[MCP_RUN_PROMPT ...]\\` directives, they will be mandatory when opened._`,\n },\n ],\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : \"Unknown error\";\n console.error(`[MCP] tickets:create error:`, error);\n return {\n content: [\n {\n type: \"text\",\n text: `Error creating ticket: ${errorMessage}`,\n },\n ],\n isError: true,\n };\n }\n } else if (ticketTool.type === 'close') {\n // Ticket 151: Handle tickets:close\n const ticketSlug = request.params.arguments?.ticketSlug as string | undefined;\n\n if (!ticketSlug) {\n return {\n content: [\n {\n type: \"text\",\n text: `Error: Missing ticketSlug parameter. Usage: Provide a ticket number (e.g., \"102\") or full slug (e.g., \"102-fix-auth\").`,\n },\n ],\n isError: true,\n };\n }\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const result = await (convexClient as any).mutation(\n \"mcp_tickets:closeMcpTicket\",\n {\n apiKey: config.apiKey,\n workspaceSlug: ticketTool.workspaceSlug,\n ticketSlug: ticketSlug,\n }\n ) as CloseTicketResult;\n\n return {\n content: [\n {\n type: \"text\",\n text: `✅ Ticket [${result.slug}] closed in workspace \"${ticketTool.workspaceSlug}\".\n\nClosed at: ${new Date(result.closedAt).toISOString()}\n\n_Reminder: Ensure all embedded \\`[MCP_RUN_PROMPT ...]\\` directives were executed before closing._`,\n },\n ],\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : \"Unknown error\";\n console.error(`[MCP] tickets:close error:`, error);\n return {\n content: [\n {\n type: \"text\",\n text: `Error closing ticket: ${errorMessage}`,\n },\n ],\n isError: true,\n };\n }\n } else if (ticketTool.type === 'message') {\n // Ticket 151: Handle tickets:message\n const ticketSlug = request.params.arguments?.ticketSlug as string | undefined;\n const message = request.params.arguments?.message as string | undefined;\n\n if (!ticketSlug || !message) {\n return {\n content: [\n {\n type: \"text\",\n text: `Error: Missing required parameters. Provide ticketSlug and message.`,\n },\n ],\n isError: true,\n };\n }\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const result = await (convexClient as any).mutation(\n \"mcp_tickets:addMcpTicketMessage\",\n {\n apiKey: config.apiKey,\n workspaceSlug: ticketTool.workspaceSlug,\n ticketSlug: ticketSlug,\n message: message,\n }\n ) as AddMessageResult;\n\n return {\n content: [\n {\n type: \"text\",\n text: `✅ Message added to ticket [${result.ticketSlug}].\\n\\nTotal messages: ${result.messageCount}`,\n },\n ],\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : \"Unknown error\";\n console.error(`[MCP] tickets:message error:`, error);\n return {\n content: [\n {\n type: \"text\",\n text: `Error adding message: ${errorMessage}`,\n },\n ],\n isError: true,\n };\n }\n }\n }\n\n // Unknown tool - individual prompt tools are no longer registered\n // Prompts should be invoked via run_prompt tool\n throw new Error(`Unknown tool: ${toolName}. Use run_prompt to execute prompts by name.`);\n });\n\n // Start server with stdio transport\n const transport = new StdioServerTransport();\n await server.connect(transport);\n\n console.error(\"[MCP] Server started successfully\");\n console.error(`[MCP] Deployment: ${config.isDev ? \"DEVELOPMENT\" : \"PRODUCTION\"}`);\n console.error(`[MCP] Convex URL: ${config.convexUrl}`);\n console.error(`[MCP] Data mode: REAL-TIME (fetches fresh data on each invocation)`);\n\n // List all prompts\n const allPromptNames = [...Array.from(promptNames)].sort();\n console.error(`[MCP] Prompts available: ${allPromptNames.join(\", \")}`);\n console.error(`[MCP] - Total prompts: ${promptNames.size}`);\n\n // Keep the event loop alive with a heartbeat\n // This prevents Node from exiting when there are no active handles\n setInterval(() => {\n // Heartbeat every 60 seconds to keep process alive\n }, 60000);\n\n // Return a promise that never resolves to keep the server running\n return new Promise<void>(() => {\n // The transport handles stdin/stdout communication\n // The interval above keeps the event loop active\n });\n}\n\n/**\n * Validate API key with Convex\n */\nasync function validateApiKey(\n client: ConvexHttpClient,\n apiKey: string\n): Promise<{ valid: boolean; userId?: string; error?: string }> {\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const result = await client.query(\"apiKeys:validateApiKey\" as any, { key: apiKey });\n if (result) {\n return { valid: true, userId: result.userId };\n }\n return { valid: false, error: \"Invalid API key\" };\n } catch (error) {\n return {\n valid: false,\n error: error instanceof Error ? error.message : \"Unknown error\",\n };\n }\n}\n\n/**\n * Fetch prompts exposed to MCP\n * Passes workspace filter from CLI --workspaces arg (Ticket 144)\n */\nasync function fetchMcpPrompts(\n client: ConvexHttpClient,\n apiKey: string,\n workspaces: string[]\n): Promise<McpPrompt[]> {\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const prompts = await client.query(\"mcp_prompts:getMcpPrompts\" as any, {\n apiKey,\n workspaces: workspaces.length > 0 ? workspaces : undefined, // Only pass if specified\n });\n return prompts;\n } catch (error) {\n throw new Error(\n `Failed to fetch prompts: ${error instanceof Error ? error.message : \"Unknown error\"}`\n );\n }\n}\n","import type { ConvexHttpClient } from \"convex/browser\";\nimport type { McpPrompt, ServerConfig } from \"./types.js\";\n\n/**\n * Sanitizes a string for use in MCP tool names.\n * Ensures output matches MCP protocol pattern: ^[a-zA-Z0-9_-]{1,64}$\n *\n * @param str - Raw string to sanitize (workspace slug, folder path, or prompt slug)\n * @returns Sanitized string safe for MCP tool names\n */\nexport function sanitizeForMcp(str: string): string {\n return str\n .trim() // Remove leading/trailing whitespace first\n .toLowerCase() // Convert to lowercase for consistency\n .replace(/[^a-z0-9_-]/g, '-') // Replace ALL invalid chars (including spaces!) with hyphens\n .replace(/-+/g, '-') // Collapse multiple consecutive hyphens into one\n .replace(/^-+|-+$/g, '') // Remove leading and trailing hyphens\n .trim(); // Final trim to ensure no whitespace\n}\n\n/**\n * Build the MCP prompt name for a prompt with workspace scoping\n *\n * MCP tool names must match pattern: ^[a-zA-Z0-9_:-]{1,64}$\n * (letters, numbers, underscores, hyphens, and colons allowed)\n *\n * Format: workspace:prompt\n * - Folders are NOT included in slash command names\n * - Folders are only used for ZIP download organization\n *\n * Character mapping:\n * - Separator: : (colon) between workspace and prompt\n * - Hyphens: - used within multi-word slugs\n * - Example: personal:code-review, work:api-design\n */\nexport function buildPromptName(prompt: McpPrompt): string {\n const workspace = sanitizeForMcp(prompt.workspaceSlug || 'default') || 'default';\n const promptSlug = sanitizeForMcp(prompt.slug || 'unknown') || 'unknown';\n\n // Hierarchical workspace:prompt format\n return `${workspace}:${promptSlug}`.trim();\n}\n\n/**\n * Build the MCP prompt schema for a prompt\n */\nexport function buildPromptSchema(prompt: McpPrompt) {\n return {\n name: buildPromptName(prompt),\n description: prompt.description || `Prompt: ${prompt.name}`,\n arguments: [],\n };\n}\n\n/**\n * Build the prompt execution handler for a prompt\n */\nexport function buildPromptHandler(\n prompt: McpPrompt,\n config: ServerConfig,\n convexClient: ConvexHttpClient\n) {\n return async () => {\n let flattenedPrompt = prompt.flattenedPrompt;\n let promptName = prompt.name;\n\n // Always fetch fresh data from Convex (real-time mode)\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n let freshPrompts = await convexClient.query(\"mcp_prompts:getMcpPrompts\" as any, {\n apiKey: config.apiKey,\n });\n\n // Apply workspace filter to fresh data if configured\n if (config.selectedWorkspaces.length > 0) {\n freshPrompts = freshPrompts.filter((p: McpPrompt) =>\n p.workspaceSlug && config.selectedWorkspaces.includes(p.workspaceSlug)\n );\n }\n\n const freshPrompt = freshPrompts.find((p: McpPrompt) => p.slug === prompt.slug && p.workspaceSlug === prompt.workspaceSlug);\n\n if (freshPrompt) {\n flattenedPrompt = freshPrompt.flattenedPrompt;\n promptName = freshPrompt.name;\n console.error(`[MCP] Fetched fresh data for: ${buildPromptName(prompt)}`);\n } else {\n console.error(\n `[MCP] WARNING: Prompt \"${prompt.slug}\" not found in fresh fetch, using cached version`\n );\n }\n } catch (error) {\n console.error(\n `[MCP] WARNING: Failed to fetch fresh data, using cached version: ${error instanceof Error ? error.message : \"Unknown error\"}`\n );\n }\n\n if (!flattenedPrompt) {\n throw new Error(\n `Prompt \"${promptName}\" has no flattened content. Please re-save the prompt in ContextFS to regenerate it.`\n );\n }\n\n console.error(`[MCP] Executed prompt: ${buildPromptName(prompt)}`);\n\n // Return raw flattened prompt (client will parse YAML front matter)\n return {\n messages: [\n {\n role: \"user\",\n content: {\n type: \"text\" as const,\n text: flattenedPrompt,\n },\n },\n ],\n };\n };\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED