@episoda/mcp 0.1.8 → 0.1.10
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/cli.js +231 -1
- package/dist/cli.js.map +1 -1
- package/dist/workflow-server.js +231 -1
- package/dist/workflow-server.js.map +1 -1
- package/package.json +1 -1
package/dist/workflow-server.js
CHANGED
|
@@ -252,7 +252,7 @@ server.registerTool(
|
|
|
252
252
|
}
|
|
253
253
|
},
|
|
254
254
|
async (args) => {
|
|
255
|
-
const result = await apiRequest("GET", `/api/
|
|
255
|
+
const result = await apiRequest("GET", `/api/tasks?module_id=${args.module_uid}`);
|
|
256
256
|
if (!result.success || !result.tasks) {
|
|
257
257
|
return { content: [{ type: "text", text: `Error: ${result.error || "Failed to fetch tasks"}` }], isError: true };
|
|
258
258
|
}
|
|
@@ -274,6 +274,27 @@ ${taskList}`
|
|
|
274
274
|
};
|
|
275
275
|
}
|
|
276
276
|
);
|
|
277
|
+
server.registerTool(
|
|
278
|
+
"delete_task",
|
|
279
|
+
{
|
|
280
|
+
description: "Delete a task by UID",
|
|
281
|
+
inputSchema: {
|
|
282
|
+
task_uid: z.string().describe("The UID of the task (e.g., EP584-1)")
|
|
283
|
+
}
|
|
284
|
+
},
|
|
285
|
+
async (args) => {
|
|
286
|
+
const result = await apiRequest("DELETE", `/api/tasks/${args.task_uid}`);
|
|
287
|
+
if (!result.success) {
|
|
288
|
+
return { content: [{ type: "text", text: `Error: ${result.error}` }], isError: true };
|
|
289
|
+
}
|
|
290
|
+
return {
|
|
291
|
+
content: [{
|
|
292
|
+
type: "text",
|
|
293
|
+
text: `Task ${args.task_uid} deleted`
|
|
294
|
+
}]
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
);
|
|
277
298
|
server.registerTool(
|
|
278
299
|
"batch_update_task_state",
|
|
279
300
|
{
|
|
@@ -603,6 +624,123 @@ ${mod.description_md || "_No description_"}`
|
|
|
603
624
|
};
|
|
604
625
|
}
|
|
605
626
|
);
|
|
627
|
+
server.registerTool(
|
|
628
|
+
"delete_module",
|
|
629
|
+
{
|
|
630
|
+
description: "Delete a module by UID",
|
|
631
|
+
inputSchema: {
|
|
632
|
+
module_uid: z.string().describe("The UID of the module (e.g., EP584)")
|
|
633
|
+
}
|
|
634
|
+
},
|
|
635
|
+
async (args) => {
|
|
636
|
+
const result = await apiRequest("DELETE", `/api/modules/${args.module_uid}`);
|
|
637
|
+
if (!result.success) {
|
|
638
|
+
return { content: [{ type: "text", text: `Error: ${result.error}` }], isError: true };
|
|
639
|
+
}
|
|
640
|
+
return {
|
|
641
|
+
content: [{
|
|
642
|
+
type: "text",
|
|
643
|
+
text: `Module ${args.module_uid} deleted`
|
|
644
|
+
}]
|
|
645
|
+
};
|
|
646
|
+
}
|
|
647
|
+
);
|
|
648
|
+
server.registerTool(
|
|
649
|
+
"list_modules",
|
|
650
|
+
{
|
|
651
|
+
description: `List modules in the project with optional filtering.
|
|
652
|
+
|
|
653
|
+
USE THIS WHEN:
|
|
654
|
+
- Discovering modules without knowing UIDs
|
|
655
|
+
- Checking what's currently in progress
|
|
656
|
+
- Finding modules by state`,
|
|
657
|
+
inputSchema: {
|
|
658
|
+
state: z.enum(["backlog", "ready", "doing", "review", "done"]).optional().describe("Filter by module state"),
|
|
659
|
+
limit: z.number().optional().describe("Maximum results (default: 25)"),
|
|
660
|
+
include_task_counts: z.boolean().optional().describe("Include task counts per module")
|
|
661
|
+
}
|
|
662
|
+
},
|
|
663
|
+
async (args) => {
|
|
664
|
+
const params = new URLSearchParams();
|
|
665
|
+
if (args.state) params.set("state", args.state);
|
|
666
|
+
if (args.limit) params.set("limit", String(args.limit));
|
|
667
|
+
if (args.include_task_counts) params.set("includeTaskCounts", "true");
|
|
668
|
+
const query = params.toString();
|
|
669
|
+
const result = await apiRequest("GET", `/api/modules${query ? `?${query}` : ""}`);
|
|
670
|
+
if (!result.success || !result.modules) {
|
|
671
|
+
return { content: [{ type: "text", text: `Error: ${result.error || "Failed to fetch modules"}` }], isError: true };
|
|
672
|
+
}
|
|
673
|
+
if (result.modules.length === 0) {
|
|
674
|
+
return { content: [{ type: "text", text: `No modules found${args.state ? ` in state "${args.state}"` : ""}.` }] };
|
|
675
|
+
}
|
|
676
|
+
const moduleList = result.modules.map((m) => {
|
|
677
|
+
const taskInfo = m.task_counts ? ` [${m.task_counts.done}/${m.task_counts.total} tasks]` : "";
|
|
678
|
+
return `- **${m.uid}**: ${m.title} (${m.state})${taskInfo}`;
|
|
679
|
+
}).join("\n");
|
|
680
|
+
return {
|
|
681
|
+
content: [{
|
|
682
|
+
type: "text",
|
|
683
|
+
text: `# Modules${args.state ? ` (${args.state})` : ""}
|
|
684
|
+
|
|
685
|
+
${moduleList}`
|
|
686
|
+
}]
|
|
687
|
+
};
|
|
688
|
+
}
|
|
689
|
+
);
|
|
690
|
+
server.registerTool(
|
|
691
|
+
"transition_module",
|
|
692
|
+
{
|
|
693
|
+
description: `Transition a module to a new state using the orchestrated transition API.
|
|
694
|
+
|
|
695
|
+
This triggers the full transition flow (e.g., doing\u2192review creates PR, review\u2192done triggers merge).
|
|
696
|
+
Use this instead of request_review or mark_done for full control.`,
|
|
697
|
+
inputSchema: {
|
|
698
|
+
module_uid: z.string().describe("The UID of the module (e.g., EP584)"),
|
|
699
|
+
target_state: z.enum(["ready", "doing", "review", "done"]).describe("Target state for the module")
|
|
700
|
+
}
|
|
701
|
+
},
|
|
702
|
+
async (args) => {
|
|
703
|
+
const result = await apiRequest(
|
|
704
|
+
"POST",
|
|
705
|
+
`/api/modules/${args.module_uid}/transition`,
|
|
706
|
+
{ targetState: args.target_state }
|
|
707
|
+
);
|
|
708
|
+
if (!result.success) {
|
|
709
|
+
return { content: [{ type: "text", text: `Error: ${result.error}` }], isError: true };
|
|
710
|
+
}
|
|
711
|
+
return {
|
|
712
|
+
content: [{
|
|
713
|
+
type: "text",
|
|
714
|
+
text: `Module ${args.module_uid} transitioned to ${args.target_state}`
|
|
715
|
+
}]
|
|
716
|
+
};
|
|
717
|
+
}
|
|
718
|
+
);
|
|
719
|
+
server.registerTool(
|
|
720
|
+
"archive_module",
|
|
721
|
+
{
|
|
722
|
+
description: "Archive a module instead of deleting it",
|
|
723
|
+
inputSchema: {
|
|
724
|
+
module_uid: z.string().describe("The UID of the module (e.g., EP584)")
|
|
725
|
+
}
|
|
726
|
+
},
|
|
727
|
+
async (args) => {
|
|
728
|
+
const result = await apiRequest(
|
|
729
|
+
"POST",
|
|
730
|
+
`/api/modules/${args.module_uid}/archive`,
|
|
731
|
+
{}
|
|
732
|
+
);
|
|
733
|
+
if (!result.success) {
|
|
734
|
+
return { content: [{ type: "text", text: `Error: ${result.error}` }], isError: true };
|
|
735
|
+
}
|
|
736
|
+
return {
|
|
737
|
+
content: [{
|
|
738
|
+
type: "text",
|
|
739
|
+
text: `Module ${args.module_uid} archived`
|
|
740
|
+
}]
|
|
741
|
+
};
|
|
742
|
+
}
|
|
743
|
+
);
|
|
606
744
|
server.registerTool(
|
|
607
745
|
"get_knowledge",
|
|
608
746
|
{
|
|
@@ -947,6 +1085,98 @@ server.registerTool(
|
|
|
947
1085
|
};
|
|
948
1086
|
}
|
|
949
1087
|
);
|
|
1088
|
+
server.registerTool(
|
|
1089
|
+
"create_knowledge",
|
|
1090
|
+
{
|
|
1091
|
+
description: `Create a new knowledge document in the knowledge base.
|
|
1092
|
+
|
|
1093
|
+
USE THIS WHEN:
|
|
1094
|
+
- Documenting technical decisions or architecture
|
|
1095
|
+
- Capturing research findings or discoveries
|
|
1096
|
+
- Creating process directives or guidelines
|
|
1097
|
+
|
|
1098
|
+
All documentation MUST be created in the knowledge base, not as markdown files.`,
|
|
1099
|
+
inputSchema: {
|
|
1100
|
+
title: z.string().describe("Title of the knowledge document"),
|
|
1101
|
+
domain: z.enum(["tech", "business", "process", "people"]).describe("Knowledge domain"),
|
|
1102
|
+
doc_type: z.enum(["directive", "discovery", "documentation"]).describe("Document type"),
|
|
1103
|
+
significance: z.number().describe("Significance score from 0.0 to 1.0"),
|
|
1104
|
+
markdown: z.string().describe("The document content in markdown")
|
|
1105
|
+
}
|
|
1106
|
+
},
|
|
1107
|
+
async (args) => {
|
|
1108
|
+
const result = await apiRequest("POST", "/api/knowledge", {
|
|
1109
|
+
title: args.title,
|
|
1110
|
+
domain: args.domain,
|
|
1111
|
+
doc_type: args.doc_type,
|
|
1112
|
+
significance: args.significance,
|
|
1113
|
+
markdown: args.markdown
|
|
1114
|
+
});
|
|
1115
|
+
if (!result.success) {
|
|
1116
|
+
return { content: [{ type: "text", text: `Error: ${result.error}` }], isError: true };
|
|
1117
|
+
}
|
|
1118
|
+
const k = result.knowledge;
|
|
1119
|
+
return {
|
|
1120
|
+
content: [{
|
|
1121
|
+
type: "text",
|
|
1122
|
+
text: `Created knowledge document${k?.uid ? ` ${k.uid}` : ""}: ${k?.title} (id: ${k?.id})`
|
|
1123
|
+
}]
|
|
1124
|
+
};
|
|
1125
|
+
}
|
|
1126
|
+
);
|
|
1127
|
+
server.registerTool(
|
|
1128
|
+
"update_knowledge",
|
|
1129
|
+
{
|
|
1130
|
+
description: "Update an existing knowledge document",
|
|
1131
|
+
inputSchema: {
|
|
1132
|
+
knowledge_id: z.string().describe("The ID of the knowledge document"),
|
|
1133
|
+
title: z.string().optional().describe("New title"),
|
|
1134
|
+
markdown: z.string().optional().describe("New markdown content"),
|
|
1135
|
+
domain: z.enum(["tech", "business", "process", "people"]).optional().describe("New domain"),
|
|
1136
|
+
doc_type: z.enum(["directive", "discovery", "documentation"]).optional().describe("New document type"),
|
|
1137
|
+
significance: z.number().optional().describe("New significance score (0.0-1.0)")
|
|
1138
|
+
}
|
|
1139
|
+
},
|
|
1140
|
+
async (args) => {
|
|
1141
|
+
const updates = {};
|
|
1142
|
+
if (args.title) updates.title = args.title;
|
|
1143
|
+
if (args.markdown) updates.markdown = args.markdown;
|
|
1144
|
+
if (args.domain) updates.domain = args.domain;
|
|
1145
|
+
if (args.doc_type) updates.doc_type = args.doc_type;
|
|
1146
|
+
if (args.significance !== void 0) updates.significance = args.significance;
|
|
1147
|
+
const result = await apiRequest("PATCH", `/api/knowledge/${args.knowledge_id}`, updates);
|
|
1148
|
+
if (!result.success) {
|
|
1149
|
+
return { content: [{ type: "text", text: `Error: ${result.error}` }], isError: true };
|
|
1150
|
+
}
|
|
1151
|
+
return {
|
|
1152
|
+
content: [{
|
|
1153
|
+
type: "text",
|
|
1154
|
+
text: `Knowledge document ${args.knowledge_id} updated`
|
|
1155
|
+
}]
|
|
1156
|
+
};
|
|
1157
|
+
}
|
|
1158
|
+
);
|
|
1159
|
+
server.registerTool(
|
|
1160
|
+
"delete_knowledge",
|
|
1161
|
+
{
|
|
1162
|
+
description: "Delete a knowledge document by ID",
|
|
1163
|
+
inputSchema: {
|
|
1164
|
+
knowledge_id: z.string().describe("The ID of the knowledge document")
|
|
1165
|
+
}
|
|
1166
|
+
},
|
|
1167
|
+
async (args) => {
|
|
1168
|
+
const result = await apiRequest("DELETE", `/api/knowledge/${args.knowledge_id}`);
|
|
1169
|
+
if (!result.success) {
|
|
1170
|
+
return { content: [{ type: "text", text: `Error: ${result.error}` }], isError: true };
|
|
1171
|
+
}
|
|
1172
|
+
return {
|
|
1173
|
+
content: [{
|
|
1174
|
+
type: "text",
|
|
1175
|
+
text: `Knowledge document ${args.knowledge_id} deleted`
|
|
1176
|
+
}]
|
|
1177
|
+
};
|
|
1178
|
+
}
|
|
1179
|
+
);
|
|
950
1180
|
server.registerTool(
|
|
951
1181
|
"get_module_context",
|
|
952
1182
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/workflow-server.ts","../src/runtime-config.ts"],"sourcesContent":["/**\n * EP895-10: Episoda Workflow MCP Server\n *\n * MCP server for Claude Code agents to interact with the Episoda workflow system.\n * Provides tools for:\n * - Task management (create, update, state transitions)\n * - Module management (create, update, state transitions)\n * - Knowledge access (search, get, link)\n *\n * Usage:\n * npx -y @episoda/mcp workflow\n *\n * Required environment variables:\n * EPISODA_API_URL - Base URL for Episoda API (e.g., https://episoda.dev)\n * EPISODA_SESSION_TOKEN - Bearer token for API authentication\n * MODULE_UID - Current module UID (for context)\n */\n\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'\nimport { z } from 'zod'\nimport { hydrateRuntimeConfig } from './runtime-config.js'\n\n// Environment configuration\nlet EPISODA_API_URL = process.env.EPISODA_API_URL || 'https://episoda.dev'\nlet EPISODA_SESSION_TOKEN = process.env.EPISODA_SESSION_TOKEN || ''\nlet EPISODA_PROJECT_ID = process.env.EPISODA_PROJECT_ID || ''\nlet EPISODA_WORKSPACE_ID = process.env.EPISODA_WORKSPACE_ID || ''\n\n/**\n * Make an authenticated API request\n */\nasync function apiRequest<T>(\n method: 'GET' | 'POST' | 'PATCH' | 'DELETE',\n path: string,\n body?: Record<string, unknown>\n): Promise<T> {\n const url = `${EPISODA_API_URL}${path}`\n const options: RequestInit = {\n method,\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${EPISODA_SESSION_TOKEN}`\n }\n }\n\n if (body && method !== 'GET') {\n options.body = JSON.stringify(body)\n }\n\n if (EPISODA_PROJECT_ID) {\n (options.headers as Record<string, string>)['x-project-id'] = EPISODA_PROJECT_ID\n }\n if (EPISODA_WORKSPACE_ID) {\n (options.headers as Record<string, string>)['x-workspace-id'] = EPISODA_WORKSPACE_ID\n }\n\n const response = await fetch(url, options)\n\n if (!response.ok) {\n const text = await response.text()\n throw new Error(`API error ${response.status}: ${text}`)\n }\n\n return response.json() as Promise<T>\n}\n\n// Create MCP server\nconst server = new McpServer({\n name: 'episoda-workflow',\n version: '1.0.0'\n}, {\n capabilities: {\n tools: {}\n },\n instructions: `\n Episoda Workflow MCP Server\n\n This server provides tools to manage the Episoda development workflow:\n - Tasks: Create, update, and transition task states\n - Modules: Create, update, and transition module states\n - Knowledge: Search, retrieve, and link knowledge documents\n\n Task and module states flow: backlog → doing → review → done\n `\n})\n\n// ============================================\n// Task Management Tools\n// ============================================\n\nserver.registerTool(\n 'create_task',\n {\n description: 'Create a new task within a module',\n inputSchema: {\n module_uid: z.string().describe('The UID of the parent module (e.g., EP584)'),\n title: z.string().describe('Title of the task'),\n description: z.string().optional().describe('Markdown description of the task'),\n type: z.enum(['task', 'bug', 'spike']).optional().describe('Type of task')\n }\n },\n async (args) => {\n interface CreateTaskResponse {\n success: boolean\n task?: { id: string; uid: string; title: string }\n error?: string\n }\n\n const result = await apiRequest<CreateTaskResponse>('POST', '/api/tasks', {\n module_id: args.module_uid, // API expects module_id (accepts both UUID and UID)\n title: args.title,\n description_md: args.description,\n type: args.type || 'task'\n })\n\n if (!result.success) {\n return { content: [{ type: 'text', text: `Error: ${result.error}` }], isError: true }\n }\n\n return {\n content: [{\n type: 'text',\n text: `Created task ${result.task?.uid}: ${result.task?.title}`\n }]\n }\n }\n)\n\nserver.registerTool(\n 'update_task_state',\n {\n description: 'Move a task to a new state (backlog, doing, review, done)',\n inputSchema: {\n task_uid: z.string().describe('The UID of the task (e.g., EP584-1)'),\n state: z.enum(['backlog', 'doing', 'review', 'done']).describe('New state for the task')\n }\n },\n async (args) => {\n interface UpdateTaskResponse {\n success: boolean\n task?: { uid: string; state: string }\n error?: string\n }\n\n const result = await apiRequest<UpdateTaskResponse>('PATCH', `/api/tasks/${args.task_uid}`, {\n state: args.state\n })\n\n if (!result.success) {\n return { content: [{ type: 'text', text: `Error: ${result.error}` }], isError: true }\n }\n\n return {\n content: [{\n type: 'text',\n text: `Task ${args.task_uid} moved to ${args.state}`\n }]\n }\n }\n)\n\nserver.registerTool(\n 'update_task',\n {\n description: 'Update task details (title, description)',\n inputSchema: {\n task_uid: z.string().describe('The UID of the task (e.g., EP584-1)'),\n title: z.string().optional().describe('New title for the task'),\n description: z.string().optional().describe('New markdown description')\n }\n },\n async (args) => {\n interface UpdateTaskResponse {\n success: boolean\n task?: { uid: string; title: string }\n error?: string\n }\n\n const updates: Record<string, string> = {}\n if (args.title) updates.title = args.title\n if (args.description) updates.description_md = args.description\n\n const result = await apiRequest<UpdateTaskResponse>('PATCH', `/api/tasks/${args.task_uid}`, updates)\n\n if (!result.success) {\n return { content: [{ type: 'text', text: `Error: ${result.error}` }], isError: true }\n }\n\n return {\n content: [{\n type: 'text',\n text: `Task ${args.task_uid} updated`\n }]\n }\n }\n)\n\nserver.registerTool(\n 'get_task_details',\n {\n description: 'Get detailed information about a task',\n inputSchema: {\n task_uid: z.string().describe('The UID of the task (e.g., EP584-1)')\n }\n },\n async (args) => {\n interface TaskResponse {\n success: boolean\n task?: {\n uid: string\n title: string\n state: string\n type: string\n description_md: string | null\n module_uid: string\n }\n error?: string\n }\n\n const result = await apiRequest<TaskResponse>('GET', `/api/tasks/${args.task_uid}`)\n\n if (!result.success || !result.task) {\n return { content: [{ type: 'text', text: `Error: ${result.error || 'Task not found'}` }], isError: true }\n }\n\n const task = result.task\n return {\n content: [{\n type: 'text',\n text: `# ${task.uid}: ${task.title}\n\n**State:** ${task.state}\n**Type:** ${task.type}\n**Module:** ${task.module_uid}\n\n${task.description_md || '_No description_'}`\n }]\n }\n }\n)\n\nserver.registerTool(\n 'list_module_tasks',\n {\n description: 'List all tasks for a module',\n inputSchema: {\n module_uid: z.string().describe('The UID of the module (e.g., EP584)')\n }\n },\n async (args) => {\n interface TasksResponse {\n success: boolean\n tasks?: Array<{\n uid: string\n title: string\n state: string\n type: string\n }>\n error?: string\n }\n\n const result = await apiRequest<TasksResponse>('GET', `/api/modules/${args.module_uid}/tasks`)\n\n if (!result.success || !result.tasks) {\n return { content: [{ type: 'text', text: `Error: ${result.error || 'Failed to fetch tasks'}` }], isError: true }\n }\n\n if (result.tasks.length === 0) {\n return { content: [{ type: 'text', text: 'No tasks found for this module.' }] }\n }\n\n const taskList = result.tasks.map(t => {\n const checkbox = t.state === 'done' ? '[x]' : '[ ]'\n const stateLabel = t.state !== 'backlog' ? ` (${t.state})` : ''\n return `- ${checkbox} **${t.uid}**: ${t.title}${stateLabel}`\n }).join('\\n')\n\n return {\n content: [{\n type: 'text',\n text: `# Tasks for ${args.module_uid}\\n\\n${taskList}`\n }]\n }\n }\n)\n\n// ============================================\n// EP1252: Batch Task Tools\n// ============================================\n\nserver.registerTool(\n 'batch_update_task_state',\n {\n description: `Update the state of multiple tasks at once.\n\nUSE THIS WHEN:\n- Marking multiple tasks as done after completing work\n- Moving several tasks to \"doing\" state\n- Bulk state transitions\n\nEFFICIENCY: Single call instead of multiple update_task_state calls.\nReduces latency from ~1.5s (6 calls) to ~300ms (1 call).`,\n inputSchema: {\n task_uids: z.array(z.string()).describe('Array of task UIDs (e.g., [\"EP1252-1\", \"EP1252-2\"])'),\n state: z.enum(['backlog', 'doing', 'done']).describe('New state for all tasks')\n }\n },\n async (args) => {\n interface TaskLookupResponse {\n success: boolean\n tasks?: Array<{ id: string; uid: string }>\n error?: string\n }\n\n interface BatchUpdateResponse {\n success: boolean\n tasks?: Array<{ id: string; uid: string; state: string }>\n summary?: { updated: number; requested: number }\n error?: { message?: string; details?: string }\n }\n\n try {\n // Step 1: Look up task UUIDs from UIDs\n // We need to query each task to get its UUID since the batch endpoint requires UUIDs\n const lookupPromises = args.task_uids.map(uid =>\n apiRequest<{ success: boolean; task?: { id: string; uid: string } }>('GET', `/api/tasks/${uid}`)\n .then(r => r.success && r.task ? { uid, id: r.task.id } : null)\n .catch(() => null)\n )\n\n const lookupResults = await Promise.all(lookupPromises)\n const validTasks = lookupResults.filter((t): t is { uid: string; id: string } => t !== null)\n const notFoundUids = args.task_uids.filter(uid => !validTasks.find(t => t.uid === uid))\n\n if (validTasks.length === 0) {\n return {\n content: [{\n type: 'text',\n text: `Error: None of the specified tasks were found.\\nNot found: ${args.task_uids.join(', ')}`\n }],\n isError: true\n }\n }\n\n // Step 2: Call batch update endpoint with UUIDs\n const updates = validTasks.map(t => ({\n id: t.id,\n state: args.state\n }))\n\n const result = await apiRequest<BatchUpdateResponse>('PATCH', '/api/tasks/batch', {\n updates\n })\n\n if (!result.success) {\n const errorMsg = result.error?.message || result.error?.details || 'Batch update failed'\n return {\n content: [{\n type: 'text',\n text: `Error: ${errorMsg}`\n }],\n isError: true\n }\n }\n\n // Build response\n const updatedUids = validTasks.map(t => t.uid)\n const failedItems = notFoundUids.map(uid => ({ uid, error: 'Task not found' }))\n\n return {\n content: [{\n type: 'text',\n text: `# Batch Update Results\n\n**Updated:** ${updatedUids.length} tasks → ${args.state}\n${updatedUids.map(uid => `- ✓ ${uid}`).join('\\n')}\n\n${failedItems.length > 0 ? `**Failed:** ${failedItems.length} tasks\\n${failedItems.map(f => `- ✗ ${f.uid}: ${f.error}`).join('\\n')}` : ''}`\n }]\n }\n } catch (error) {\n return {\n content: [{\n type: 'text',\n text: `Error: ${error instanceof Error ? error.message : 'Unknown error'}`\n }],\n isError: true\n }\n }\n }\n)\n\nserver.registerTool(\n 'batch_create_tasks',\n {\n description: `Create multiple tasks for a module at once.\n\nUSE THIS WHEN:\n- Setting up tasks for a new module\n- Creating multiple related tasks together\n- Bulk task creation from a plan\n\nEFFICIENCY: Single call instead of multiple create_task calls.`,\n inputSchema: {\n module_uid: z.string().describe('The UID of the parent module (e.g., EP1252)'),\n tasks: z.array(z.object({\n title: z.string().describe('Title of the task'),\n description: z.string().optional().describe('Markdown description'),\n state: z.enum(['backlog', 'doing', 'done']).optional().describe('Initial state (default: backlog)')\n })).describe('Array of tasks to create')\n }\n },\n async (args) => {\n interface BulkCreateResponse {\n success: boolean\n created?: number\n tasks?: Array<{ uid: string; title: string }>\n error?: string\n }\n\n try {\n // Call the bulk create endpoint (accepts module UID directly)\n const result = await apiRequest<BulkCreateResponse>('POST', '/api/tasks/bulk', {\n module_id: args.module_uid,\n tasks: args.tasks.map(t => ({\n title: t.title,\n description_md: t.description,\n state: t.state || 'backlog'\n }))\n })\n\n if (!result.success) {\n return {\n content: [{\n type: 'text',\n text: `Error: ${result.error || 'Bulk create failed'}`\n }],\n isError: true\n }\n }\n\n const createdTasks = result.tasks || []\n\n return {\n content: [{\n type: 'text',\n text: `# Batch Create Results\n\n**Created:** ${result.created || createdTasks.length} tasks for ${args.module_uid}\n\n${createdTasks.map(t => `- ✓ **${t.uid}**: ${t.title}`).join('\\n')}`\n }]\n }\n } catch (error) {\n return {\n content: [{\n type: 'text',\n text: `Error: ${error instanceof Error ? error.message : 'Unknown error'}`\n }],\n isError: true\n }\n }\n }\n)\n\nserver.registerTool(\n 'batch_get_tasks',\n {\n description: `Fetch multiple tasks by UID in a single call.\n\nUSE THIS WHEN:\n- Need details for several specific tasks\n- Checking status of multiple tasks at once\n- Gathering context for a set of tasks\n\nEFFICIENCY: Single MCP call instead of multiple get_task_details calls.`,\n inputSchema: {\n task_uids: z.array(z.string()).describe('Array of task UIDs (e.g., [\"EP1252-1\", \"EP1252-2\"])')\n }\n },\n async (args) => {\n interface TaskResponse {\n success: boolean\n task?: {\n uid: string\n title: string\n state: string\n type: string\n description_md: string | null\n }\n }\n\n try {\n type TaskInfo = NonNullable<TaskResponse['task']>\n\n // Fetch all tasks in parallel\n const fetchPromises = args.task_uids.map(uid =>\n apiRequest<TaskResponse>('GET', `/api/tasks/${uid}`)\n .then(r => r.success && r.task ? { found: true as const, task: r.task } : { found: false as const, uid })\n .catch(() => ({ found: false as const, uid }))\n )\n\n const results = await Promise.all(fetchPromises)\n const foundTasks: TaskInfo[] = []\n const notFoundUids: string[] = []\n\n for (const result of results) {\n if (result.found && result.task) {\n foundTasks.push(result.task as TaskInfo)\n } else if (!result.found) {\n notFoundUids.push(result.uid)\n }\n }\n\n if (foundTasks.length === 0) {\n return {\n content: [{\n type: 'text',\n text: `Error: None of the specified tasks were found.\\nNot found: ${args.task_uids.join(', ')}`\n }],\n isError: true\n }\n }\n\n const taskList = foundTasks.map((task) => {\n const checkbox = task.state === 'done' ? '[x]' : '[ ]'\n const stateLabel = task.state !== 'backlog' ? ` (${task.state})` : ''\n return `- ${checkbox} **${task.uid}**: ${task.title}${stateLabel}`\n }).join('\\n')\n\n return {\n content: [{\n type: 'text',\n text: `# Batch Get Results\n\n**Found:** ${foundTasks.length} tasks\n${taskList}\n\n${notFoundUids.length > 0 ? `**Not found:** ${notFoundUids.join(', ')}` : ''}`\n }]\n }\n } catch (error) {\n return {\n content: [{\n type: 'text',\n text: `Error: ${error instanceof Error ? error.message : 'Unknown error'}`\n }],\n isError: true\n }\n }\n }\n)\n\n// ============================================\n// Module Management Tools\n// ============================================\n\nserver.registerTool(\n 'create_module',\n {\n description: 'Create a new module in the project',\n inputSchema: {\n title: z.string().describe('Title of the module'),\n description: z.string().optional().describe('Markdown description of the module')\n }\n },\n async (args) => {\n interface CreateModuleResponse {\n success: boolean\n module?: { id: string; uid: string; title: string }\n error?: string\n }\n\n const result = await apiRequest<CreateModuleResponse>('POST', '/api/modules', {\n title: args.title,\n description_md: args.description\n })\n\n if (!result.success) {\n return { content: [{ type: 'text', text: `Error: ${result.error}` }], isError: true }\n }\n\n return {\n content: [{\n type: 'text',\n text: `Created module ${result.module?.uid}: ${result.module?.title}`\n }]\n }\n }\n)\n\nserver.registerTool(\n 'update_module',\n {\n description: 'Update module details (title, description)',\n inputSchema: {\n module_uid: z.string().describe('The UID of the module (e.g., EP584)'),\n title: z.string().optional().describe('New title for the module'),\n description: z.string().optional().describe('New markdown description')\n }\n },\n async (args) => {\n interface UpdateModuleResponse {\n success: boolean\n module?: { uid: string; title: string }\n error?: string\n }\n\n const updates: Record<string, string> = {}\n if (args.title) updates.title = args.title\n if (args.description) updates.description_md = args.description\n\n const result = await apiRequest<UpdateModuleResponse>('PATCH', `/api/modules/${args.module_uid}`, updates)\n\n if (!result.success) {\n return { content: [{ type: 'text', text: `Error: ${result.error}` }], isError: true }\n }\n\n return {\n content: [{\n type: 'text',\n text: `Module ${args.module_uid} updated`\n }]\n }\n }\n)\n\nserver.registerTool(\n 'request_review',\n {\n description: 'Move a module to review state',\n inputSchema: {\n module_uid: z.string().describe('The UID of the module (e.g., EP584)')\n }\n },\n async (args) => {\n interface UpdateModuleResponse {\n success: boolean\n module?: { uid: string; state: string }\n error?: string\n }\n\n const result = await apiRequest<UpdateModuleResponse>('PATCH', `/api/modules/${args.module_uid}`, {\n state: 'review'\n })\n\n if (!result.success) {\n return { content: [{ type: 'text', text: `Error: ${result.error}` }], isError: true }\n }\n\n return {\n content: [{\n type: 'text',\n text: `Module ${args.module_uid} moved to review`\n }]\n }\n }\n)\n\nserver.registerTool(\n 'mark_done',\n {\n description: 'Move a module to done state',\n inputSchema: {\n module_uid: z.string().describe('The UID of the module (e.g., EP584)')\n }\n },\n async (args) => {\n interface UpdateModuleResponse {\n success: boolean\n module?: { uid: string; state: string }\n error?: string\n }\n\n const result = await apiRequest<UpdateModuleResponse>('PATCH', `/api/modules/${args.module_uid}`, {\n state: 'done'\n })\n\n if (!result.success) {\n return { content: [{ type: 'text', text: `Error: ${result.error}` }], isError: true }\n }\n\n return {\n content: [{\n type: 'text',\n text: `Module ${args.module_uid} marked as done`\n }]\n }\n }\n)\n\nserver.registerTool(\n 'get_module_details',\n {\n description: 'Get detailed information about a module',\n inputSchema: {\n module_uid: z.string().describe('The UID of the module (e.g., EP584)')\n }\n },\n async (args) => {\n interface ModuleResponse {\n success: boolean\n module?: {\n uid: string\n title: string\n state: string\n description_md: string | null\n branch_name: string | null\n }\n error?: string\n }\n\n const result = await apiRequest<ModuleResponse>('GET', `/api/modules/${args.module_uid}`)\n\n if (!result.success || !result.module) {\n return { content: [{ type: 'text', text: `Error: ${result.error || 'Module not found'}` }], isError: true }\n }\n\n const mod = result.module\n return {\n content: [{\n type: 'text',\n text: `# ${mod.uid}: ${mod.title}\n\n**State:** ${mod.state}\n**Branch:** ${mod.branch_name || '_Not set_'}\n\n${mod.description_md || '_No description_'}`\n }]\n }\n }\n)\n\n// ============================================\n// Knowledge Tools\n// ============================================\n\nserver.registerTool(\n 'get_knowledge',\n {\n description: 'Fetch a knowledge document by ID',\n inputSchema: {\n knowledge_id: z.string().describe('The ID of the knowledge document')\n }\n },\n async (args) => {\n interface KnowledgeResponse {\n success: boolean\n knowledge?: {\n id: string\n title: string\n doc_type: string\n domain: string\n sections: Array<{ heading?: string; content?: string }>\n }\n error?: string\n }\n\n const result = await apiRequest<KnowledgeResponse>('GET', `/api/knowledge/${args.knowledge_id}`)\n\n if (!result.success || !result.knowledge) {\n return { content: [{ type: 'text', text: `Error: ${result.error || 'Knowledge not found'}` }], isError: true }\n }\n\n const doc = result.knowledge\n const sections = doc.sections.map(s => {\n const heading = s.heading ? `## ${s.heading}\\n\\n` : ''\n return `${heading}${s.content || ''}`\n }).join('\\n\\n')\n\n return {\n content: [{\n type: 'text',\n text: `# ${doc.title}\n\n**Type:** ${doc.doc_type} | **Domain:** ${doc.domain}\n\n${sections}`\n }]\n }\n }\n)\n\n// EP1242: Three search tools with clear use cases for AI agents\n\nserver.registerTool(\n 'search_knowledge_semantic',\n {\n description: `Search knowledge using vector similarity (semantic/conceptual matching).\n\nUSE THIS WHEN:\n- Looking for documents about a concept: \"authentication patterns\", \"error handling\"\n- Finding related content even if exact words don't match\n- Discovering documentation about a topic\n\nDO NOT USE WHEN:\n- Looking for a specific document by ID/UID (use get_knowledge)\n- Searching for exact title match (use search_knowledge_text)`,\n inputSchema: {\n query: z.string().describe('Natural language query describing what you\\'re looking for'),\n limit: z.number().optional().describe('Maximum results (default: 10)'),\n threshold: z.number().optional().describe('Minimum similarity 0-1 (default: 0.5, lower = more results)')\n }\n },\n async (args) => {\n interface SemanticSearchResponse {\n success: boolean\n results?: Array<{\n id: string\n uid?: string\n title: string\n doc_type: string\n similarity: number\n markdown?: string\n }>\n query_info?: { took_ms: number }\n error?: string\n }\n\n const result = await apiRequest<SemanticSearchResponse>(\n 'POST',\n '/api/search/semantic',\n {\n query: args.query,\n types: ['knowledge'],\n limit: args.limit || 10,\n threshold: args.threshold || 0.5\n }\n )\n\n if (!result.success || !result.results) {\n return { content: [{ type: 'text', text: `Error: ${result.error || 'Semantic search failed'}` }], isError: true }\n }\n\n if (result.results.length === 0) {\n return { content: [{ type: 'text', text: `No knowledge documents found semantically matching: \"${args.query}\"\\n\\nTry:\\n- Broader search terms\\n- Lower threshold (e.g., 0.3)\\n- Text search for exact matches` }] }\n }\n\n const list = result.results.map(r => {\n const score = Math.round(r.similarity * 100)\n const uid = r.uid ? ` (${r.uid})` : ''\n const snippet = r.markdown ? `\\n ${r.markdown.substring(0, 150)}...` : ''\n return `- **${r.title}**${uid} [${r.doc_type}, ${score}% match]${snippet}`\n }).join('\\n\\n')\n\n const timing = result.query_info ? ` (${result.query_info.took_ms}ms)` : ''\n\n return {\n content: [{\n type: 'text',\n text: `# Semantic Search Results${timing}\\n\\nQuery: \"${args.query}\"\\nFound: ${result.results.length} documents\\n\\n${list}`\n }]\n }\n }\n)\n\nserver.registerTool(\n 'search_knowledge_text',\n {\n description: `Search knowledge using text/keyword matching (fast, exact).\n\nUSE THIS WHEN:\n- Looking for documents by UID: \"K123\", \"K45\"\n- Searching for exact title: \"API Authentication Guide\"\n- Finding documents containing specific terms\n\nDO NOT USE WHEN:\n- Looking for conceptually related content (use search_knowledge_semantic)\n- Want to find documents about a topic without knowing exact words`,\n inputSchema: {\n query: z.string().describe('Text to search for (searches title, UID, domain, content)'),\n limit: z.number().optional().describe('Maximum results (default: 20)')\n }\n },\n async (args) => {\n interface TextSearchResponse {\n success: boolean\n results?: Array<{\n id: string\n uid?: string\n title: string\n doc_type?: string\n type: string\n markdown?: string\n }>\n total?: number\n error?: string\n }\n\n const result = await apiRequest<TextSearchResponse>(\n 'POST',\n '/api/search/text',\n {\n query: args.query,\n types: ['knowledge'],\n limit: args.limit || 20\n }\n )\n\n if (!result.success || !result.results) {\n return { content: [{ type: 'text', text: `Error: ${result.error || 'Text search failed'}` }], isError: true }\n }\n\n if (result.results.length === 0) {\n return { content: [{ type: 'text', text: `No knowledge documents found matching: \"${args.query}\"\\n\\nTry:\\n- Different keywords\\n- Semantic search for conceptual matches` }] }\n }\n\n const list = result.results.map(r => {\n const uid = r.uid ? ` (${r.uid})` : ''\n const docType = r.doc_type ? ` [${r.doc_type}]` : ''\n const snippet = r.markdown ? `\\n ${r.markdown.substring(0, 150)}...` : ''\n return `- **${r.title}**${uid}${docType}${snippet}`\n }).join('\\n\\n')\n\n return {\n content: [{\n type: 'text',\n text: `# Text Search Results\\n\\nQuery: \"${args.query}\"\\nFound: ${result.results.length} of ${result.total || result.results.length} documents\\n\\n${list}`\n }]\n }\n }\n)\n\nserver.registerTool(\n 'search_knowledge_hybrid',\n {\n description: `Search knowledge using both semantic AND text matching (best for general queries).\n\nCombines results using Reciprocal Rank Fusion (RRF) algorithm.\nDocuments that match BOTH semantically and textually rank highest.\n\nUSE THIS WHEN:\n- General search where you want comprehensive results\n- Not sure if semantic or text search is better\n- Want the best of both approaches\n\nThis is the recommended default search for most queries.`,\n inputSchema: {\n query: z.string().describe('Search query (will be used for both semantic and text matching)'),\n limit: z.number().optional().describe('Maximum results (default: 10)')\n }\n },\n async (args) => {\n interface SearchResult {\n id: string\n uid?: string\n title: string\n doc_type?: string\n similarity?: number\n markdown?: string\n }\n\n interface SemanticResponse {\n success: boolean\n results?: SearchResult[]\n error?: string\n }\n\n interface TextResponse {\n success: boolean\n results?: SearchResult[]\n error?: string\n }\n\n // Run both searches in parallel\n const [semanticResult, textResult] = await Promise.all([\n apiRequest<SemanticResponse>('POST', '/api/search/semantic', {\n query: args.query,\n types: ['knowledge'],\n limit: 50,\n threshold: 0.4\n }),\n apiRequest<TextResponse>('POST', '/api/search/text', {\n query: args.query,\n types: ['knowledge'],\n limit: 50\n })\n ])\n\n const semanticResults = semanticResult.success ? (semanticResult.results || []) : []\n const textResults = textResult.success ? (textResult.results || []) : []\n\n // Apply Reciprocal Rank Fusion (RRF) with k=60\n const K = 60\n const scores = new Map<string, { score: number; doc: SearchResult; sources: string[] }>()\n\n // Score semantic results\n semanticResults.forEach((doc, index) => {\n const rrfScore = 1 / (K + index + 1)\n scores.set(doc.id, { score: rrfScore, doc, sources: ['semantic'] })\n })\n\n // Score text results and merge\n textResults.forEach((doc, index) => {\n const rrfScore = 1 / (K + index + 1)\n const existing = scores.get(doc.id)\n if (existing) {\n existing.score += rrfScore\n existing.sources.push('text')\n } else {\n scores.set(doc.id, { score: rrfScore, doc, sources: ['text'] })\n }\n })\n\n // Sort by RRF score and limit\n const limit = args.limit || 10\n const ranked = Array.from(scores.values())\n .sort((a, b) => b.score - a.score)\n .slice(0, limit)\n\n if (ranked.length === 0) {\n return { content: [{ type: 'text', text: `No knowledge documents found for: \"${args.query}\"\\n\\nBoth semantic and text search returned no results.` }] }\n }\n\n const list = ranked.map(({ doc, score, sources }) => {\n const uid = doc.uid ? ` (${doc.uid})` : ''\n const docType = doc.doc_type ? ` [${doc.doc_type}]` : ''\n const matchType = sources.length === 2 ? '⭐ both' : sources[0]\n const snippet = doc.markdown ? `\\n ${doc.markdown.substring(0, 150)}...` : ''\n return `- **${doc.title}**${uid}${docType} (${matchType})${snippet}`\n }).join('\\n\\n')\n\n const bothCount = ranked.filter(r => r.sources.length === 2).length\n\n return {\n content: [{\n type: 'text',\n text: `# Hybrid Search Results (RRF)\\n\\nQuery: \"${args.query}\"\\nFound: ${ranked.length} documents (${bothCount} matched both semantic + text)\\n\\n${list}`\n }]\n }\n }\n)\n\nserver.registerTool(\n 'search_conversations',\n {\n description: `Search past agent conversations in this project.\n\nThis searches agent conversation history (agent_messages) across sessions you can access.\n\nUSE THIS WHEN:\n- The user references a prior discussion\n- You need to recover context after compaction\n- You want to find when/where something was decided`,\n inputSchema: {\n query: z.string().describe('Semantic search query'),\n limit: z.number().optional().describe('Max results (default: 10)'),\n threshold: z.number().optional().describe('Min similarity 0-1 (default: 0.5)'),\n days_back: z.number().optional().describe('Limit to recent N days (optional)'),\n session_id: z.string().optional().describe('Limit to a specific session UUID (optional)')\n }\n },\n async (args) => {\n interface ConversationSearchResponse {\n success: boolean\n results?: Array<{\n message_id: string\n session_id: string\n role: string\n content_snippet: string\n similarity: number\n created_at: string\n module_uid?: string | null\n module_title?: string | null\n agent_provider?: string\n }>\n total?: number\n error?: string\n }\n\n const result = await apiRequest<ConversationSearchResponse>(\n 'POST',\n '/api/search/conversations',\n {\n query: args.query,\n limit: args.limit || 10,\n threshold: args.threshold || 0.5,\n ...(args.days_back !== undefined ? { days_back: args.days_back } : {}),\n ...(args.session_id ? { session_id: args.session_id } : {})\n }\n )\n\n if (!result.success || !result.results) {\n return { content: [{ type: 'text', text: `Error: ${result.error || 'Conversation search failed'}` }], isError: true }\n }\n\n if (result.results.length === 0) {\n return { content: [{ type: 'text', text: `No conversation messages found matching: \"${args.query}\"` }] }\n }\n\n const list = result.results.map(r => {\n const score = Math.round((r.similarity || 0) * 100)\n const moduleInfo = r.module_uid ? ` | ${r.module_uid}${r.module_title ? `: ${r.module_title}` : ''}` : ''\n const when = r.created_at ? ` | ${r.created_at}` : ''\n return `- [${r.role}, ${score}%] ${r.content_snippet}${moduleInfo}${when}`\n }).join('\\n')\n\n return {\n content: [{\n type: 'text',\n text: `# Conversation Search Results\\n\\nQuery: \"${args.query}\"\\nFound: ${result.results.length}\\n\\n${list}`\n }]\n }\n }\n)\n\nserver.registerTool(\n 'list_linked_knowledge',\n {\n description: 'List knowledge documents linked to a module',\n inputSchema: {\n module_uid: z.string().describe('The UID of the module (e.g., EP584)')\n }\n },\n async (args) => {\n interface LinkedKnowledgeResponse {\n success: boolean\n knowledge?: Array<{\n id: string\n title: string\n doc_type: string\n }>\n error?: string\n }\n\n const result = await apiRequest<LinkedKnowledgeResponse>(\n 'GET',\n `/api/modules/${args.module_uid}/knowledge`\n )\n\n if (!result.success || !result.knowledge) {\n return { content: [{ type: 'text', text: `Error: ${result.error || 'Failed to fetch knowledge'}` }], isError: true }\n }\n\n if (result.knowledge.length === 0) {\n return { content: [{ type: 'text', text: 'No knowledge documents linked to this module.' }] }\n }\n\n const list = result.knowledge.map(k => `- **${k.title}** (${k.doc_type})`).join('\\n')\n\n return {\n content: [{\n type: 'text',\n text: `# Linked Knowledge for ${args.module_uid}\\n\\n${list}`\n }]\n }\n }\n)\n\nserver.registerTool(\n 'link_knowledge',\n {\n description: 'Link a knowledge document to a module',\n inputSchema: {\n module_uid: z.string().describe('The UID of the module (e.g., EP584)'),\n knowledge_id: z.string().describe('The ID of the knowledge document to link')\n }\n },\n async (args) => {\n interface LinkResponse {\n success: boolean\n error?: string\n }\n\n const result = await apiRequest<LinkResponse>(\n 'POST',\n `/api/modules/${args.module_uid}/knowledge/link`,\n { knowledge_id: args.knowledge_id }\n )\n\n if (!result.success) {\n return { content: [{ type: 'text', text: `Error: ${result.error}` }], isError: true }\n }\n\n return {\n content: [{\n type: 'text',\n text: `Knowledge document linked to module ${args.module_uid}`\n }]\n }\n }\n)\n\n// ============================================\n// Context Tools\n// ============================================\n\nserver.registerTool(\n 'get_module_context',\n {\n description: 'Get the full context for a module (title, tasks, linked knowledge)',\n inputSchema: {\n module_uid: z.string().describe('The UID of the module (e.g., EP584)')\n }\n },\n async (args) => {\n interface ContextResponse {\n success: boolean\n context?: string\n error?: string\n }\n\n // Use the agent-accessible module context API\n const result = await apiRequest<ContextResponse>(\n 'GET',\n `/api/agent/context/module/${args.module_uid}`\n )\n\n if (!result.success || !result.context) {\n return { content: [{ type: 'text', text: `Error: ${result.error || 'Failed to fetch context'}` }], isError: true }\n }\n\n return {\n content: [{\n type: 'text',\n text: result.context\n }]\n }\n }\n)\n\nserver.registerTool(\n 'get_project_context',\n {\n description: 'Get the project-wide context (C2 bundle with active work, priorities)',\n inputSchema: {}\n },\n async () => {\n interface ContextResponse {\n success: boolean\n prompt?: string\n error?: string\n }\n\n // Use the agent-accessible system prompt API\n const result = await apiRequest<ContextResponse>(\n 'GET',\n '/api/agent/context/system'\n )\n\n if (!result.success || !result.prompt) {\n return { content: [{ type: 'text', text: `Error: ${result.error || 'Failed to fetch context'}` }], isError: true }\n }\n\n return {\n content: [{\n type: 'text',\n text: result.prompt\n }]\n }\n }\n)\n\n// ============================================\n// Start Server\n// ============================================\n\nasync function main() {\n const runtimeConfig = await hydrateRuntimeConfig()\n EPISODA_API_URL = runtimeConfig.apiUrl\n EPISODA_SESSION_TOKEN = runtimeConfig.sessionToken\n EPISODA_PROJECT_ID = runtimeConfig.projectId\n EPISODA_WORKSPACE_ID = runtimeConfig.workspaceId\n\n const transport = new StdioServerTransport()\n await server.connect(transport)\n\n // Log to stderr so it doesn't interfere with MCP protocol\n console.error('[episoda-workflow] MCP server started')\n console.error(`[episoda-workflow] API URL: ${EPISODA_API_URL}`)\n console.error(`[episoda-workflow] Token: ${EPISODA_SESSION_TOKEN ? '****' : 'NOT SET'}`)\n}\n\nmain().catch((error) => {\n console.error('[episoda-workflow] Fatal error:', error)\n process.exit(1)\n})\n","import * as fs from 'node:fs'\nimport * as os from 'node:os'\nimport * as path from 'node:path'\n\nconst DEFAULT_API_URL = 'https://episoda.dev'\nconst DEFAULT_CONFIG_FILE = 'config.json'\n\ninterface EpisodaLocalConfig {\n access_token?: string\n project_id?: string\n workspace_id?: string\n api_url?: string\n}\n\nexport interface RuntimeConfig {\n apiUrl: string\n sessionToken: string\n projectId: string\n workspaceId: string\n}\n\nconst normalizeEnv = (value?: string): string | undefined => {\n if (!value) return undefined\n const trimmed = value.trim()\n return trimmed.length > 0 ? trimmed : undefined\n}\n\nconst readEnvConfig = () => ({\n apiUrl: normalizeEnv(process.env.EPISODA_API_URL),\n sessionToken: normalizeEnv(process.env.EPISODA_SESSION_TOKEN),\n projectId: normalizeEnv(process.env.EPISODA_PROJECT_ID),\n workspaceId: normalizeEnv(process.env.EPISODA_WORKSPACE_ID)\n})\n\nconst buildMissingMessage = (missing: string[], apiUrl: string): string => {\n return [\n `[episoda-mcp] Missing auth context: ${missing.join(', ')}`,\n '[episoda-mcp] Set EPISODA_* env vars or run:',\n `[episoda-mcp] episoda auth --api-url ${apiUrl}`\n ].join('\\n')\n}\n\nconst getConfigPath = (): string => {\n // MCP supports a full-path override in addition to the core-style config dir.\n if (process.env.EPISODA_CONFIG_PATH) {\n return process.env.EPISODA_CONFIG_PATH\n }\n const configDir = process.env.EPISODA_CONFIG_DIR || path.join(os.homedir(), '.episoda')\n return path.join(configDir, DEFAULT_CONFIG_FILE)\n}\n\nconst loadLocalConfig = (): EpisodaLocalConfig | null => {\n const configPath = getConfigPath()\n if (!fs.existsSync(configPath)) {\n return null\n }\n try {\n const content = fs.readFileSync(configPath, 'utf8')\n return JSON.parse(content) as EpisodaLocalConfig\n } catch (error) {\n console.error('[episoda-mcp] Failed to load config:', error)\n return null\n }\n}\n\nexport async function resolveRuntimeConfig(): Promise<RuntimeConfig> {\n const envConfig = readEnvConfig()\n\n let fileConfig: EpisodaLocalConfig | null = null\n if (!envConfig.sessionToken || !envConfig.projectId || !envConfig.workspaceId || !envConfig.apiUrl) {\n fileConfig = loadLocalConfig()\n }\n\n const resolved: RuntimeConfig = {\n apiUrl: envConfig.apiUrl || fileConfig?.api_url || DEFAULT_API_URL,\n sessionToken: envConfig.sessionToken || fileConfig?.access_token || '',\n projectId: envConfig.projectId || fileConfig?.project_id || '',\n workspaceId: envConfig.workspaceId || fileConfig?.workspace_id || ''\n }\n\n const missing: string[] = []\n if (!resolved.sessionToken) missing.push('EPISODA_SESSION_TOKEN')\n if (!resolved.projectId) missing.push('EPISODA_PROJECT_ID')\n if (!resolved.workspaceId) missing.push('EPISODA_WORKSPACE_ID')\n\n if (missing.length > 0) {\n throw new Error(buildMissingMessage(missing, resolved.apiUrl))\n }\n\n return resolved\n}\n\nexport async function hydrateRuntimeConfig(): Promise<RuntimeConfig> {\n const resolved = await resolveRuntimeConfig()\n\n if (!normalizeEnv(process.env.EPISODA_API_URL)) {\n process.env.EPISODA_API_URL = resolved.apiUrl\n }\n if (!normalizeEnv(process.env.EPISODA_SESSION_TOKEN)) {\n process.env.EPISODA_SESSION_TOKEN = resolved.sessionToken\n }\n if (!normalizeEnv(process.env.EPISODA_PROJECT_ID)) {\n process.env.EPISODA_PROJECT_ID = resolved.projectId\n }\n if (!normalizeEnv(process.env.EPISODA_WORKSPACE_ID)) {\n process.env.EPISODA_WORKSPACE_ID = resolved.workspaceId\n }\n\n return resolved\n}\n"],"mappings":"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","names":["path"]}
|
|
1
|
+
{"version":3,"sources":["../src/workflow-server.ts","../src/runtime-config.ts"],"sourcesContent":["/**\n * EP895-10: Episoda Workflow MCP Server\n *\n * MCP server for Claude Code agents to interact with the Episoda workflow system.\n * Provides tools for:\n * - Task management (create, update, state transitions)\n * - Module management (create, update, state transitions)\n * - Knowledge access (search, get, link)\n *\n * Usage:\n * npx -y @episoda/mcp workflow\n *\n * Required environment variables:\n * EPISODA_API_URL - Base URL for Episoda API (e.g., https://episoda.dev)\n * EPISODA_SESSION_TOKEN - Bearer token for API authentication\n * MODULE_UID - Current module UID (for context)\n */\n\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'\nimport { z } from 'zod'\nimport { hydrateRuntimeConfig } from './runtime-config.js'\n\n// Environment configuration\nlet EPISODA_API_URL = process.env.EPISODA_API_URL || 'https://episoda.dev'\nlet EPISODA_SESSION_TOKEN = process.env.EPISODA_SESSION_TOKEN || ''\nlet EPISODA_PROJECT_ID = process.env.EPISODA_PROJECT_ID || ''\nlet EPISODA_WORKSPACE_ID = process.env.EPISODA_WORKSPACE_ID || ''\n\n/**\n * Make an authenticated API request\n */\nasync function apiRequest<T>(\n method: 'GET' | 'POST' | 'PATCH' | 'DELETE',\n path: string,\n body?: Record<string, unknown>\n): Promise<T> {\n const url = `${EPISODA_API_URL}${path}`\n const options: RequestInit = {\n method,\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${EPISODA_SESSION_TOKEN}`\n }\n }\n\n if (body && method !== 'GET') {\n options.body = JSON.stringify(body)\n }\n\n if (EPISODA_PROJECT_ID) {\n (options.headers as Record<string, string>)['x-project-id'] = EPISODA_PROJECT_ID\n }\n if (EPISODA_WORKSPACE_ID) {\n (options.headers as Record<string, string>)['x-workspace-id'] = EPISODA_WORKSPACE_ID\n }\n\n const response = await fetch(url, options)\n\n if (!response.ok) {\n const text = await response.text()\n throw new Error(`API error ${response.status}: ${text}`)\n }\n\n return response.json() as Promise<T>\n}\n\n// Create MCP server\nconst server = new McpServer({\n name: 'episoda-workflow',\n version: '1.0.0'\n}, {\n capabilities: {\n tools: {}\n },\n instructions: `\n Episoda Workflow MCP Server\n\n This server provides tools to manage the Episoda development workflow:\n - Tasks: Create, update, and transition task states\n - Modules: Create, update, and transition module states\n - Knowledge: Search, retrieve, and link knowledge documents\n\n Task and module states flow: backlog → doing → review → done\n `\n})\n\n// ============================================\n// Task Management Tools\n// ============================================\n\nserver.registerTool(\n 'create_task',\n {\n description: 'Create a new task within a module',\n inputSchema: {\n module_uid: z.string().describe('The UID of the parent module (e.g., EP584)'),\n title: z.string().describe('Title of the task'),\n description: z.string().optional().describe('Markdown description of the task'),\n type: z.enum(['task', 'bug', 'spike']).optional().describe('Type of task')\n }\n },\n async (args) => {\n interface CreateTaskResponse {\n success: boolean\n task?: { id: string; uid: string; title: string }\n error?: string\n }\n\n const result = await apiRequest<CreateTaskResponse>('POST', '/api/tasks', {\n module_id: args.module_uid, // API expects module_id (accepts both UUID and UID)\n title: args.title,\n description_md: args.description,\n type: args.type || 'task'\n })\n\n if (!result.success) {\n return { content: [{ type: 'text', text: `Error: ${result.error}` }], isError: true }\n }\n\n return {\n content: [{\n type: 'text',\n text: `Created task ${result.task?.uid}: ${result.task?.title}`\n }]\n }\n }\n)\n\nserver.registerTool(\n 'update_task_state',\n {\n description: 'Move a task to a new state (backlog, doing, review, done)',\n inputSchema: {\n task_uid: z.string().describe('The UID of the task (e.g., EP584-1)'),\n state: z.enum(['backlog', 'doing', 'review', 'done']).describe('New state for the task')\n }\n },\n async (args) => {\n interface UpdateTaskResponse {\n success: boolean\n task?: { uid: string; state: string }\n error?: string\n }\n\n const result = await apiRequest<UpdateTaskResponse>('PATCH', `/api/tasks/${args.task_uid}`, {\n state: args.state\n })\n\n if (!result.success) {\n return { content: [{ type: 'text', text: `Error: ${result.error}` }], isError: true }\n }\n\n return {\n content: [{\n type: 'text',\n text: `Task ${args.task_uid} moved to ${args.state}`\n }]\n }\n }\n)\n\nserver.registerTool(\n 'update_task',\n {\n description: 'Update task details (title, description)',\n inputSchema: {\n task_uid: z.string().describe('The UID of the task (e.g., EP584-1)'),\n title: z.string().optional().describe('New title for the task'),\n description: z.string().optional().describe('New markdown description')\n }\n },\n async (args) => {\n interface UpdateTaskResponse {\n success: boolean\n task?: { uid: string; title: string }\n error?: string\n }\n\n const updates: Record<string, string> = {}\n if (args.title) updates.title = args.title\n if (args.description) updates.description_md = args.description\n\n const result = await apiRequest<UpdateTaskResponse>('PATCH', `/api/tasks/${args.task_uid}`, updates)\n\n if (!result.success) {\n return { content: [{ type: 'text', text: `Error: ${result.error}` }], isError: true }\n }\n\n return {\n content: [{\n type: 'text',\n text: `Task ${args.task_uid} updated`\n }]\n }\n }\n)\n\nserver.registerTool(\n 'get_task_details',\n {\n description: 'Get detailed information about a task',\n inputSchema: {\n task_uid: z.string().describe('The UID of the task (e.g., EP584-1)')\n }\n },\n async (args) => {\n interface TaskResponse {\n success: boolean\n task?: {\n uid: string\n title: string\n state: string\n type: string\n description_md: string | null\n module_uid: string\n }\n error?: string\n }\n\n const result = await apiRequest<TaskResponse>('GET', `/api/tasks/${args.task_uid}`)\n\n if (!result.success || !result.task) {\n return { content: [{ type: 'text', text: `Error: ${result.error || 'Task not found'}` }], isError: true }\n }\n\n const task = result.task\n return {\n content: [{\n type: 'text',\n text: `# ${task.uid}: ${task.title}\n\n**State:** ${task.state}\n**Type:** ${task.type}\n**Module:** ${task.module_uid}\n\n${task.description_md || '_No description_'}`\n }]\n }\n }\n)\n\nserver.registerTool(\n 'list_module_tasks',\n {\n description: 'List all tasks for a module',\n inputSchema: {\n module_uid: z.string().describe('The UID of the module (e.g., EP584)')\n }\n },\n async (args) => {\n interface TasksResponse {\n success: boolean\n tasks?: Array<{\n uid: string\n title: string\n state: string\n type: string\n }>\n error?: string\n }\n\n const result = await apiRequest<TasksResponse>('GET', `/api/tasks?module_id=${args.module_uid}`)\n\n if (!result.success || !result.tasks) {\n return { content: [{ type: 'text', text: `Error: ${result.error || 'Failed to fetch tasks'}` }], isError: true }\n }\n\n if (result.tasks.length === 0) {\n return { content: [{ type: 'text', text: 'No tasks found for this module.' }] }\n }\n\n const taskList = result.tasks.map(t => {\n const checkbox = t.state === 'done' ? '[x]' : '[ ]'\n const stateLabel = t.state !== 'backlog' ? ` (${t.state})` : ''\n return `- ${checkbox} **${t.uid}**: ${t.title}${stateLabel}`\n }).join('\\n')\n\n return {\n content: [{\n type: 'text',\n text: `# Tasks for ${args.module_uid}\\n\\n${taskList}`\n }]\n }\n }\n)\n\nserver.registerTool(\n 'delete_task',\n {\n description: 'Delete a task by UID',\n inputSchema: {\n task_uid: z.string().describe('The UID of the task (e.g., EP584-1)')\n }\n },\n async (args) => {\n interface DeleteTaskResponse {\n success: boolean\n message?: string\n error?: string\n }\n\n const result = await apiRequest<DeleteTaskResponse>('DELETE', `/api/tasks/${args.task_uid}`)\n\n if (!result.success) {\n return { content: [{ type: 'text', text: `Error: ${result.error}` }], isError: true }\n }\n\n return {\n content: [{\n type: 'text',\n text: `Task ${args.task_uid} deleted`\n }]\n }\n }\n)\n\n// ============================================\n// EP1252: Batch Task Tools\n// ============================================\n\nserver.registerTool(\n 'batch_update_task_state',\n {\n description: `Update the state of multiple tasks at once.\n\nUSE THIS WHEN:\n- Marking multiple tasks as done after completing work\n- Moving several tasks to \"doing\" state\n- Bulk state transitions\n\nEFFICIENCY: Single call instead of multiple update_task_state calls.\nReduces latency from ~1.5s (6 calls) to ~300ms (1 call).`,\n inputSchema: {\n task_uids: z.array(z.string()).describe('Array of task UIDs (e.g., [\"EP1252-1\", \"EP1252-2\"])'),\n state: z.enum(['backlog', 'doing', 'done']).describe('New state for all tasks')\n }\n },\n async (args) => {\n interface TaskLookupResponse {\n success: boolean\n tasks?: Array<{ id: string; uid: string }>\n error?: string\n }\n\n interface BatchUpdateResponse {\n success: boolean\n tasks?: Array<{ id: string; uid: string; state: string }>\n summary?: { updated: number; requested: number }\n error?: { message?: string; details?: string }\n }\n\n try {\n // Step 1: Look up task UUIDs from UIDs\n // We need to query each task to get its UUID since the batch endpoint requires UUIDs\n const lookupPromises = args.task_uids.map(uid =>\n apiRequest<{ success: boolean; task?: { id: string; uid: string } }>('GET', `/api/tasks/${uid}`)\n .then(r => r.success && r.task ? { uid, id: r.task.id } : null)\n .catch(() => null)\n )\n\n const lookupResults = await Promise.all(lookupPromises)\n const validTasks = lookupResults.filter((t): t is { uid: string; id: string } => t !== null)\n const notFoundUids = args.task_uids.filter(uid => !validTasks.find(t => t.uid === uid))\n\n if (validTasks.length === 0) {\n return {\n content: [{\n type: 'text',\n text: `Error: None of the specified tasks were found.\\nNot found: ${args.task_uids.join(', ')}`\n }],\n isError: true\n }\n }\n\n // Step 2: Call batch update endpoint with UUIDs\n const updates = validTasks.map(t => ({\n id: t.id,\n state: args.state\n }))\n\n const result = await apiRequest<BatchUpdateResponse>('PATCH', '/api/tasks/batch', {\n updates\n })\n\n if (!result.success) {\n const errorMsg = result.error?.message || result.error?.details || 'Batch update failed'\n return {\n content: [{\n type: 'text',\n text: `Error: ${errorMsg}`\n }],\n isError: true\n }\n }\n\n // Build response\n const updatedUids = validTasks.map(t => t.uid)\n const failedItems = notFoundUids.map(uid => ({ uid, error: 'Task not found' }))\n\n return {\n content: [{\n type: 'text',\n text: `# Batch Update Results\n\n**Updated:** ${updatedUids.length} tasks → ${args.state}\n${updatedUids.map(uid => `- ✓ ${uid}`).join('\\n')}\n\n${failedItems.length > 0 ? `**Failed:** ${failedItems.length} tasks\\n${failedItems.map(f => `- ✗ ${f.uid}: ${f.error}`).join('\\n')}` : ''}`\n }]\n }\n } catch (error) {\n return {\n content: [{\n type: 'text',\n text: `Error: ${error instanceof Error ? error.message : 'Unknown error'}`\n }],\n isError: true\n }\n }\n }\n)\n\nserver.registerTool(\n 'batch_create_tasks',\n {\n description: `Create multiple tasks for a module at once.\n\nUSE THIS WHEN:\n- Setting up tasks for a new module\n- Creating multiple related tasks together\n- Bulk task creation from a plan\n\nEFFICIENCY: Single call instead of multiple create_task calls.`,\n inputSchema: {\n module_uid: z.string().describe('The UID of the parent module (e.g., EP1252)'),\n tasks: z.array(z.object({\n title: z.string().describe('Title of the task'),\n description: z.string().optional().describe('Markdown description'),\n state: z.enum(['backlog', 'doing', 'done']).optional().describe('Initial state (default: backlog)')\n })).describe('Array of tasks to create')\n }\n },\n async (args) => {\n interface BulkCreateResponse {\n success: boolean\n created?: number\n tasks?: Array<{ uid: string; title: string }>\n error?: string\n }\n\n try {\n // Call the bulk create endpoint (accepts module UID directly)\n const result = await apiRequest<BulkCreateResponse>('POST', '/api/tasks/bulk', {\n module_id: args.module_uid,\n tasks: args.tasks.map(t => ({\n title: t.title,\n description_md: t.description,\n state: t.state || 'backlog'\n }))\n })\n\n if (!result.success) {\n return {\n content: [{\n type: 'text',\n text: `Error: ${result.error || 'Bulk create failed'}`\n }],\n isError: true\n }\n }\n\n const createdTasks = result.tasks || []\n\n return {\n content: [{\n type: 'text',\n text: `# Batch Create Results\n\n**Created:** ${result.created || createdTasks.length} tasks for ${args.module_uid}\n\n${createdTasks.map(t => `- ✓ **${t.uid}**: ${t.title}`).join('\\n')}`\n }]\n }\n } catch (error) {\n return {\n content: [{\n type: 'text',\n text: `Error: ${error instanceof Error ? error.message : 'Unknown error'}`\n }],\n isError: true\n }\n }\n }\n)\n\nserver.registerTool(\n 'batch_get_tasks',\n {\n description: `Fetch multiple tasks by UID in a single call.\n\nUSE THIS WHEN:\n- Need details for several specific tasks\n- Checking status of multiple tasks at once\n- Gathering context for a set of tasks\n\nEFFICIENCY: Single MCP call instead of multiple get_task_details calls.`,\n inputSchema: {\n task_uids: z.array(z.string()).describe('Array of task UIDs (e.g., [\"EP1252-1\", \"EP1252-2\"])')\n }\n },\n async (args) => {\n interface TaskResponse {\n success: boolean\n task?: {\n uid: string\n title: string\n state: string\n type: string\n description_md: string | null\n }\n }\n\n try {\n type TaskInfo = NonNullable<TaskResponse['task']>\n\n // Fetch all tasks in parallel\n const fetchPromises = args.task_uids.map(uid =>\n apiRequest<TaskResponse>('GET', `/api/tasks/${uid}`)\n .then(r => r.success && r.task ? { found: true as const, task: r.task } : { found: false as const, uid })\n .catch(() => ({ found: false as const, uid }))\n )\n\n const results = await Promise.all(fetchPromises)\n const foundTasks: TaskInfo[] = []\n const notFoundUids: string[] = []\n\n for (const result of results) {\n if (result.found && result.task) {\n foundTasks.push(result.task as TaskInfo)\n } else if (!result.found) {\n notFoundUids.push(result.uid)\n }\n }\n\n if (foundTasks.length === 0) {\n return {\n content: [{\n type: 'text',\n text: `Error: None of the specified tasks were found.\\nNot found: ${args.task_uids.join(', ')}`\n }],\n isError: true\n }\n }\n\n const taskList = foundTasks.map((task) => {\n const checkbox = task.state === 'done' ? '[x]' : '[ ]'\n const stateLabel = task.state !== 'backlog' ? ` (${task.state})` : ''\n return `- ${checkbox} **${task.uid}**: ${task.title}${stateLabel}`\n }).join('\\n')\n\n return {\n content: [{\n type: 'text',\n text: `# Batch Get Results\n\n**Found:** ${foundTasks.length} tasks\n${taskList}\n\n${notFoundUids.length > 0 ? `**Not found:** ${notFoundUids.join(', ')}` : ''}`\n }]\n }\n } catch (error) {\n return {\n content: [{\n type: 'text',\n text: `Error: ${error instanceof Error ? error.message : 'Unknown error'}`\n }],\n isError: true\n }\n }\n }\n)\n\n// ============================================\n// Module Management Tools\n// ============================================\n\nserver.registerTool(\n 'create_module',\n {\n description: 'Create a new module in the project',\n inputSchema: {\n title: z.string().describe('Title of the module'),\n description: z.string().optional().describe('Markdown description of the module')\n }\n },\n async (args) => {\n interface CreateModuleResponse {\n success: boolean\n module?: { id: string; uid: string; title: string }\n error?: string\n }\n\n const result = await apiRequest<CreateModuleResponse>('POST', '/api/modules', {\n title: args.title,\n description_md: args.description\n })\n\n if (!result.success) {\n return { content: [{ type: 'text', text: `Error: ${result.error}` }], isError: true }\n }\n\n return {\n content: [{\n type: 'text',\n text: `Created module ${result.module?.uid}: ${result.module?.title}`\n }]\n }\n }\n)\n\nserver.registerTool(\n 'update_module',\n {\n description: 'Update module details (title, description)',\n inputSchema: {\n module_uid: z.string().describe('The UID of the module (e.g., EP584)'),\n title: z.string().optional().describe('New title for the module'),\n description: z.string().optional().describe('New markdown description')\n }\n },\n async (args) => {\n interface UpdateModuleResponse {\n success: boolean\n module?: { uid: string; title: string }\n error?: string\n }\n\n const updates: Record<string, string> = {}\n if (args.title) updates.title = args.title\n if (args.description) updates.description_md = args.description\n\n const result = await apiRequest<UpdateModuleResponse>('PATCH', `/api/modules/${args.module_uid}`, updates)\n\n if (!result.success) {\n return { content: [{ type: 'text', text: `Error: ${result.error}` }], isError: true }\n }\n\n return {\n content: [{\n type: 'text',\n text: `Module ${args.module_uid} updated`\n }]\n }\n }\n)\n\nserver.registerTool(\n 'request_review',\n {\n description: 'Move a module to review state',\n inputSchema: {\n module_uid: z.string().describe('The UID of the module (e.g., EP584)')\n }\n },\n async (args) => {\n interface UpdateModuleResponse {\n success: boolean\n module?: { uid: string; state: string }\n error?: string\n }\n\n const result = await apiRequest<UpdateModuleResponse>('PATCH', `/api/modules/${args.module_uid}`, {\n state: 'review'\n })\n\n if (!result.success) {\n return { content: [{ type: 'text', text: `Error: ${result.error}` }], isError: true }\n }\n\n return {\n content: [{\n type: 'text',\n text: `Module ${args.module_uid} moved to review`\n }]\n }\n }\n)\n\nserver.registerTool(\n 'mark_done',\n {\n description: 'Move a module to done state',\n inputSchema: {\n module_uid: z.string().describe('The UID of the module (e.g., EP584)')\n }\n },\n async (args) => {\n interface UpdateModuleResponse {\n success: boolean\n module?: { uid: string; state: string }\n error?: string\n }\n\n const result = await apiRequest<UpdateModuleResponse>('PATCH', `/api/modules/${args.module_uid}`, {\n state: 'done'\n })\n\n if (!result.success) {\n return { content: [{ type: 'text', text: `Error: ${result.error}` }], isError: true }\n }\n\n return {\n content: [{\n type: 'text',\n text: `Module ${args.module_uid} marked as done`\n }]\n }\n }\n)\n\nserver.registerTool(\n 'get_module_details',\n {\n description: 'Get detailed information about a module',\n inputSchema: {\n module_uid: z.string().describe('The UID of the module (e.g., EP584)')\n }\n },\n async (args) => {\n interface ModuleResponse {\n success: boolean\n module?: {\n uid: string\n title: string\n state: string\n description_md: string | null\n branch_name: string | null\n }\n error?: string\n }\n\n const result = await apiRequest<ModuleResponse>('GET', `/api/modules/${args.module_uid}`)\n\n if (!result.success || !result.module) {\n return { content: [{ type: 'text', text: `Error: ${result.error || 'Module not found'}` }], isError: true }\n }\n\n const mod = result.module\n return {\n content: [{\n type: 'text',\n text: `# ${mod.uid}: ${mod.title}\n\n**State:** ${mod.state}\n**Branch:** ${mod.branch_name || '_Not set_'}\n\n${mod.description_md || '_No description_'}`\n }]\n }\n }\n)\n\nserver.registerTool(\n 'delete_module',\n {\n description: 'Delete a module by UID',\n inputSchema: {\n module_uid: z.string().describe('The UID of the module (e.g., EP584)')\n }\n },\n async (args) => {\n interface DeleteModuleResponse {\n success: boolean\n error?: string\n }\n\n const result = await apiRequest<DeleteModuleResponse>('DELETE', `/api/modules/${args.module_uid}`)\n\n if (!result.success) {\n return { content: [{ type: 'text', text: `Error: ${result.error}` }], isError: true }\n }\n\n return {\n content: [{\n type: 'text',\n text: `Module ${args.module_uid} deleted`\n }]\n }\n }\n)\n\nserver.registerTool(\n 'list_modules',\n {\n description: `List modules in the project with optional filtering.\n\nUSE THIS WHEN:\n- Discovering modules without knowing UIDs\n- Checking what's currently in progress\n- Finding modules by state`,\n inputSchema: {\n state: z.enum(['backlog', 'ready', 'doing', 'review', 'done']).optional().describe('Filter by module state'),\n limit: z.number().optional().describe('Maximum results (default: 25)'),\n include_task_counts: z.boolean().optional().describe('Include task counts per module')\n }\n },\n async (args) => {\n interface ListModulesResponse {\n success: boolean\n modules?: Array<{\n uid: string\n title: string\n state: string\n priority?: number\n task_counts?: { total: number; done: number }\n }>\n error?: string\n }\n\n const params = new URLSearchParams()\n if (args.state) params.set('state', args.state)\n if (args.limit) params.set('limit', String(args.limit))\n if (args.include_task_counts) params.set('includeTaskCounts', 'true')\n\n const query = params.toString()\n const result = await apiRequest<ListModulesResponse>('GET', `/api/modules${query ? `?${query}` : ''}`)\n\n if (!result.success || !result.modules) {\n return { content: [{ type: 'text', text: `Error: ${result.error || 'Failed to fetch modules'}` }], isError: true }\n }\n\n if (result.modules.length === 0) {\n return { content: [{ type: 'text', text: `No modules found${args.state ? ` in state \"${args.state}\"` : ''}.` }] }\n }\n\n const moduleList = result.modules.map(m => {\n const taskInfo = m.task_counts ? ` [${m.task_counts.done}/${m.task_counts.total} tasks]` : ''\n return `- **${m.uid}**: ${m.title} (${m.state})${taskInfo}`\n }).join('\\n')\n\n return {\n content: [{\n type: 'text',\n text: `# Modules${args.state ? ` (${args.state})` : ''}\\n\\n${moduleList}`\n }]\n }\n }\n)\n\nserver.registerTool(\n 'transition_module',\n {\n description: `Transition a module to a new state using the orchestrated transition API.\n\nThis triggers the full transition flow (e.g., doing→review creates PR, review→done triggers merge).\nUse this instead of request_review or mark_done for full control.`,\n inputSchema: {\n module_uid: z.string().describe('The UID of the module (e.g., EP584)'),\n target_state: z.enum(['ready', 'doing', 'review', 'done']).describe('Target state for the module')\n }\n },\n async (args) => {\n interface TransitionResponse {\n success: boolean\n module?: { uid: string; state: string }\n error?: string\n }\n\n const result = await apiRequest<TransitionResponse>(\n 'POST',\n `/api/modules/${args.module_uid}/transition`,\n { targetState: args.target_state }\n )\n\n if (!result.success) {\n return { content: [{ type: 'text', text: `Error: ${result.error}` }], isError: true }\n }\n\n return {\n content: [{\n type: 'text',\n text: `Module ${args.module_uid} transitioned to ${args.target_state}`\n }]\n }\n }\n)\n\nserver.registerTool(\n 'archive_module',\n {\n description: 'Archive a module instead of deleting it',\n inputSchema: {\n module_uid: z.string().describe('The UID of the module (e.g., EP584)')\n }\n },\n async (args) => {\n interface ArchiveResponse {\n success: boolean\n error?: string\n }\n\n const result = await apiRequest<ArchiveResponse>(\n 'POST',\n `/api/modules/${args.module_uid}/archive`,\n {}\n )\n\n if (!result.success) {\n return { content: [{ type: 'text', text: `Error: ${result.error}` }], isError: true }\n }\n\n return {\n content: [{\n type: 'text',\n text: `Module ${args.module_uid} archived`\n }]\n }\n }\n)\n\n// ============================================\n// Knowledge Tools\n// ============================================\n\nserver.registerTool(\n 'get_knowledge',\n {\n description: 'Fetch a knowledge document by ID',\n inputSchema: {\n knowledge_id: z.string().describe('The ID of the knowledge document')\n }\n },\n async (args) => {\n interface KnowledgeResponse {\n success: boolean\n knowledge?: {\n id: string\n title: string\n doc_type: string\n domain: string\n sections: Array<{ heading?: string; content?: string }>\n }\n error?: string\n }\n\n const result = await apiRequest<KnowledgeResponse>('GET', `/api/knowledge/${args.knowledge_id}`)\n\n if (!result.success || !result.knowledge) {\n return { content: [{ type: 'text', text: `Error: ${result.error || 'Knowledge not found'}` }], isError: true }\n }\n\n const doc = result.knowledge\n const sections = doc.sections.map(s => {\n const heading = s.heading ? `## ${s.heading}\\n\\n` : ''\n return `${heading}${s.content || ''}`\n }).join('\\n\\n')\n\n return {\n content: [{\n type: 'text',\n text: `# ${doc.title}\n\n**Type:** ${doc.doc_type} | **Domain:** ${doc.domain}\n\n${sections}`\n }]\n }\n }\n)\n\n// EP1242: Three search tools with clear use cases for AI agents\n\nserver.registerTool(\n 'search_knowledge_semantic',\n {\n description: `Search knowledge using vector similarity (semantic/conceptual matching).\n\nUSE THIS WHEN:\n- Looking for documents about a concept: \"authentication patterns\", \"error handling\"\n- Finding related content even if exact words don't match\n- Discovering documentation about a topic\n\nDO NOT USE WHEN:\n- Looking for a specific document by ID/UID (use get_knowledge)\n- Searching for exact title match (use search_knowledge_text)`,\n inputSchema: {\n query: z.string().describe('Natural language query describing what you\\'re looking for'),\n limit: z.number().optional().describe('Maximum results (default: 10)'),\n threshold: z.number().optional().describe('Minimum similarity 0-1 (default: 0.5, lower = more results)')\n }\n },\n async (args) => {\n interface SemanticSearchResponse {\n success: boolean\n results?: Array<{\n id: string\n uid?: string\n title: string\n doc_type: string\n similarity: number\n markdown?: string\n }>\n query_info?: { took_ms: number }\n error?: string\n }\n\n const result = await apiRequest<SemanticSearchResponse>(\n 'POST',\n '/api/search/semantic',\n {\n query: args.query,\n types: ['knowledge'],\n limit: args.limit || 10,\n threshold: args.threshold || 0.5\n }\n )\n\n if (!result.success || !result.results) {\n return { content: [{ type: 'text', text: `Error: ${result.error || 'Semantic search failed'}` }], isError: true }\n }\n\n if (result.results.length === 0) {\n return { content: [{ type: 'text', text: `No knowledge documents found semantically matching: \"${args.query}\"\\n\\nTry:\\n- Broader search terms\\n- Lower threshold (e.g., 0.3)\\n- Text search for exact matches` }] }\n }\n\n const list = result.results.map(r => {\n const score = Math.round(r.similarity * 100)\n const uid = r.uid ? ` (${r.uid})` : ''\n const snippet = r.markdown ? `\\n ${r.markdown.substring(0, 150)}...` : ''\n return `- **${r.title}**${uid} [${r.doc_type}, ${score}% match]${snippet}`\n }).join('\\n\\n')\n\n const timing = result.query_info ? ` (${result.query_info.took_ms}ms)` : ''\n\n return {\n content: [{\n type: 'text',\n text: `# Semantic Search Results${timing}\\n\\nQuery: \"${args.query}\"\\nFound: ${result.results.length} documents\\n\\n${list}`\n }]\n }\n }\n)\n\nserver.registerTool(\n 'search_knowledge_text',\n {\n description: `Search knowledge using text/keyword matching (fast, exact).\n\nUSE THIS WHEN:\n- Looking for documents by UID: \"K123\", \"K45\"\n- Searching for exact title: \"API Authentication Guide\"\n- Finding documents containing specific terms\n\nDO NOT USE WHEN:\n- Looking for conceptually related content (use search_knowledge_semantic)\n- Want to find documents about a topic without knowing exact words`,\n inputSchema: {\n query: z.string().describe('Text to search for (searches title, UID, domain, content)'),\n limit: z.number().optional().describe('Maximum results (default: 20)')\n }\n },\n async (args) => {\n interface TextSearchResponse {\n success: boolean\n results?: Array<{\n id: string\n uid?: string\n title: string\n doc_type?: string\n type: string\n markdown?: string\n }>\n total?: number\n error?: string\n }\n\n const result = await apiRequest<TextSearchResponse>(\n 'POST',\n '/api/search/text',\n {\n query: args.query,\n types: ['knowledge'],\n limit: args.limit || 20\n }\n )\n\n if (!result.success || !result.results) {\n return { content: [{ type: 'text', text: `Error: ${result.error || 'Text search failed'}` }], isError: true }\n }\n\n if (result.results.length === 0) {\n return { content: [{ type: 'text', text: `No knowledge documents found matching: \"${args.query}\"\\n\\nTry:\\n- Different keywords\\n- Semantic search for conceptual matches` }] }\n }\n\n const list = result.results.map(r => {\n const uid = r.uid ? ` (${r.uid})` : ''\n const docType = r.doc_type ? ` [${r.doc_type}]` : ''\n const snippet = r.markdown ? `\\n ${r.markdown.substring(0, 150)}...` : ''\n return `- **${r.title}**${uid}${docType}${snippet}`\n }).join('\\n\\n')\n\n return {\n content: [{\n type: 'text',\n text: `# Text Search Results\\n\\nQuery: \"${args.query}\"\\nFound: ${result.results.length} of ${result.total || result.results.length} documents\\n\\n${list}`\n }]\n }\n }\n)\n\nserver.registerTool(\n 'search_knowledge_hybrid',\n {\n description: `Search knowledge using both semantic AND text matching (best for general queries).\n\nCombines results using Reciprocal Rank Fusion (RRF) algorithm.\nDocuments that match BOTH semantically and textually rank highest.\n\nUSE THIS WHEN:\n- General search where you want comprehensive results\n- Not sure if semantic or text search is better\n- Want the best of both approaches\n\nThis is the recommended default search for most queries.`,\n inputSchema: {\n query: z.string().describe('Search query (will be used for both semantic and text matching)'),\n limit: z.number().optional().describe('Maximum results (default: 10)')\n }\n },\n async (args) => {\n interface SearchResult {\n id: string\n uid?: string\n title: string\n doc_type?: string\n similarity?: number\n markdown?: string\n }\n\n interface SemanticResponse {\n success: boolean\n results?: SearchResult[]\n error?: string\n }\n\n interface TextResponse {\n success: boolean\n results?: SearchResult[]\n error?: string\n }\n\n // Run both searches in parallel\n const [semanticResult, textResult] = await Promise.all([\n apiRequest<SemanticResponse>('POST', '/api/search/semantic', {\n query: args.query,\n types: ['knowledge'],\n limit: 50,\n threshold: 0.4\n }),\n apiRequest<TextResponse>('POST', '/api/search/text', {\n query: args.query,\n types: ['knowledge'],\n limit: 50\n })\n ])\n\n const semanticResults = semanticResult.success ? (semanticResult.results || []) : []\n const textResults = textResult.success ? (textResult.results || []) : []\n\n // Apply Reciprocal Rank Fusion (RRF) with k=60\n const K = 60\n const scores = new Map<string, { score: number; doc: SearchResult; sources: string[] }>()\n\n // Score semantic results\n semanticResults.forEach((doc, index) => {\n const rrfScore = 1 / (K + index + 1)\n scores.set(doc.id, { score: rrfScore, doc, sources: ['semantic'] })\n })\n\n // Score text results and merge\n textResults.forEach((doc, index) => {\n const rrfScore = 1 / (K + index + 1)\n const existing = scores.get(doc.id)\n if (existing) {\n existing.score += rrfScore\n existing.sources.push('text')\n } else {\n scores.set(doc.id, { score: rrfScore, doc, sources: ['text'] })\n }\n })\n\n // Sort by RRF score and limit\n const limit = args.limit || 10\n const ranked = Array.from(scores.values())\n .sort((a, b) => b.score - a.score)\n .slice(0, limit)\n\n if (ranked.length === 0) {\n return { content: [{ type: 'text', text: `No knowledge documents found for: \"${args.query}\"\\n\\nBoth semantic and text search returned no results.` }] }\n }\n\n const list = ranked.map(({ doc, score, sources }) => {\n const uid = doc.uid ? ` (${doc.uid})` : ''\n const docType = doc.doc_type ? ` [${doc.doc_type}]` : ''\n const matchType = sources.length === 2 ? '⭐ both' : sources[0]\n const snippet = doc.markdown ? `\\n ${doc.markdown.substring(0, 150)}...` : ''\n return `- **${doc.title}**${uid}${docType} (${matchType})${snippet}`\n }).join('\\n\\n')\n\n const bothCount = ranked.filter(r => r.sources.length === 2).length\n\n return {\n content: [{\n type: 'text',\n text: `# Hybrid Search Results (RRF)\\n\\nQuery: \"${args.query}\"\\nFound: ${ranked.length} documents (${bothCount} matched both semantic + text)\\n\\n${list}`\n }]\n }\n }\n)\n\nserver.registerTool(\n 'search_conversations',\n {\n description: `Search past agent conversations in this project.\n\nThis searches agent conversation history (agent_messages) across sessions you can access.\n\nUSE THIS WHEN:\n- The user references a prior discussion\n- You need to recover context after compaction\n- You want to find when/where something was decided`,\n inputSchema: {\n query: z.string().describe('Semantic search query'),\n limit: z.number().optional().describe('Max results (default: 10)'),\n threshold: z.number().optional().describe('Min similarity 0-1 (default: 0.5)'),\n days_back: z.number().optional().describe('Limit to recent N days (optional)'),\n session_id: z.string().optional().describe('Limit to a specific session UUID (optional)')\n }\n },\n async (args) => {\n interface ConversationSearchResponse {\n success: boolean\n results?: Array<{\n message_id: string\n session_id: string\n role: string\n content_snippet: string\n similarity: number\n created_at: string\n module_uid?: string | null\n module_title?: string | null\n agent_provider?: string\n }>\n total?: number\n error?: string\n }\n\n const result = await apiRequest<ConversationSearchResponse>(\n 'POST',\n '/api/search/conversations',\n {\n query: args.query,\n limit: args.limit || 10,\n threshold: args.threshold || 0.5,\n ...(args.days_back !== undefined ? { days_back: args.days_back } : {}),\n ...(args.session_id ? { session_id: args.session_id } : {})\n }\n )\n\n if (!result.success || !result.results) {\n return { content: [{ type: 'text', text: `Error: ${result.error || 'Conversation search failed'}` }], isError: true }\n }\n\n if (result.results.length === 0) {\n return { content: [{ type: 'text', text: `No conversation messages found matching: \"${args.query}\"` }] }\n }\n\n const list = result.results.map(r => {\n const score = Math.round((r.similarity || 0) * 100)\n const moduleInfo = r.module_uid ? ` | ${r.module_uid}${r.module_title ? `: ${r.module_title}` : ''}` : ''\n const when = r.created_at ? ` | ${r.created_at}` : ''\n return `- [${r.role}, ${score}%] ${r.content_snippet}${moduleInfo}${when}`\n }).join('\\n')\n\n return {\n content: [{\n type: 'text',\n text: `# Conversation Search Results\\n\\nQuery: \"${args.query}\"\\nFound: ${result.results.length}\\n\\n${list}`\n }]\n }\n }\n)\n\nserver.registerTool(\n 'list_linked_knowledge',\n {\n description: 'List knowledge documents linked to a module',\n inputSchema: {\n module_uid: z.string().describe('The UID of the module (e.g., EP584)')\n }\n },\n async (args) => {\n interface LinkedKnowledgeResponse {\n success: boolean\n knowledge?: Array<{\n id: string\n title: string\n doc_type: string\n }>\n error?: string\n }\n\n const result = await apiRequest<LinkedKnowledgeResponse>(\n 'GET',\n `/api/modules/${args.module_uid}/knowledge`\n )\n\n if (!result.success || !result.knowledge) {\n return { content: [{ type: 'text', text: `Error: ${result.error || 'Failed to fetch knowledge'}` }], isError: true }\n }\n\n if (result.knowledge.length === 0) {\n return { content: [{ type: 'text', text: 'No knowledge documents linked to this module.' }] }\n }\n\n const list = result.knowledge.map(k => `- **${k.title}** (${k.doc_type})`).join('\\n')\n\n return {\n content: [{\n type: 'text',\n text: `# Linked Knowledge for ${args.module_uid}\\n\\n${list}`\n }]\n }\n }\n)\n\nserver.registerTool(\n 'link_knowledge',\n {\n description: 'Link a knowledge document to a module',\n inputSchema: {\n module_uid: z.string().describe('The UID of the module (e.g., EP584)'),\n knowledge_id: z.string().describe('The ID of the knowledge document to link')\n }\n },\n async (args) => {\n interface LinkResponse {\n success: boolean\n error?: string\n }\n\n const result = await apiRequest<LinkResponse>(\n 'POST',\n `/api/modules/${args.module_uid}/knowledge/link`,\n { knowledge_id: args.knowledge_id }\n )\n\n if (!result.success) {\n return { content: [{ type: 'text', text: `Error: ${result.error}` }], isError: true }\n }\n\n return {\n content: [{\n type: 'text',\n text: `Knowledge document linked to module ${args.module_uid}`\n }]\n }\n }\n)\n\nserver.registerTool(\n 'create_knowledge',\n {\n description: `Create a new knowledge document in the knowledge base.\n\nUSE THIS WHEN:\n- Documenting technical decisions or architecture\n- Capturing research findings or discoveries\n- Creating process directives or guidelines\n\nAll documentation MUST be created in the knowledge base, not as markdown files.`,\n inputSchema: {\n title: z.string().describe('Title of the knowledge document'),\n domain: z.enum(['tech', 'business', 'process', 'people']).describe('Knowledge domain'),\n doc_type: z.enum(['directive', 'discovery', 'documentation']).describe('Document type'),\n significance: z.number().describe('Significance score from 0.0 to 1.0'),\n markdown: z.string().describe('The document content in markdown')\n }\n },\n async (args) => {\n interface CreateKnowledgeResponse {\n success: boolean\n knowledge?: { id: string; uid?: string; title: string }\n error?: string\n }\n\n const result = await apiRequest<CreateKnowledgeResponse>('POST', '/api/knowledge', {\n title: args.title,\n domain: args.domain,\n doc_type: args.doc_type,\n significance: args.significance,\n markdown: args.markdown\n })\n\n if (!result.success) {\n return { content: [{ type: 'text', text: `Error: ${result.error}` }], isError: true }\n }\n\n const k = result.knowledge\n return {\n content: [{\n type: 'text',\n text: `Created knowledge document${k?.uid ? ` ${k.uid}` : ''}: ${k?.title} (id: ${k?.id})`\n }]\n }\n }\n)\n\nserver.registerTool(\n 'update_knowledge',\n {\n description: 'Update an existing knowledge document',\n inputSchema: {\n knowledge_id: z.string().describe('The ID of the knowledge document'),\n title: z.string().optional().describe('New title'),\n markdown: z.string().optional().describe('New markdown content'),\n domain: z.enum(['tech', 'business', 'process', 'people']).optional().describe('New domain'),\n doc_type: z.enum(['directive', 'discovery', 'documentation']).optional().describe('New document type'),\n significance: z.number().optional().describe('New significance score (0.0-1.0)')\n }\n },\n async (args) => {\n interface UpdateKnowledgeResponse {\n success: boolean\n knowledge?: { id: string; uid?: string; title: string }\n error?: string\n }\n\n const updates: Record<string, unknown> = {}\n if (args.title) updates.title = args.title\n if (args.markdown) updates.markdown = args.markdown\n if (args.domain) updates.domain = args.domain\n if (args.doc_type) updates.doc_type = args.doc_type\n if (args.significance !== undefined) updates.significance = args.significance\n\n const result = await apiRequest<UpdateKnowledgeResponse>('PATCH', `/api/knowledge/${args.knowledge_id}`, updates)\n\n if (!result.success) {\n return { content: [{ type: 'text', text: `Error: ${result.error}` }], isError: true }\n }\n\n return {\n content: [{\n type: 'text',\n text: `Knowledge document ${args.knowledge_id} updated`\n }]\n }\n }\n)\n\nserver.registerTool(\n 'delete_knowledge',\n {\n description: 'Delete a knowledge document by ID',\n inputSchema: {\n knowledge_id: z.string().describe('The ID of the knowledge document')\n }\n },\n async (args) => {\n interface DeleteKnowledgeResponse {\n success: boolean\n error?: string\n }\n\n const result = await apiRequest<DeleteKnowledgeResponse>('DELETE', `/api/knowledge/${args.knowledge_id}`)\n\n if (!result.success) {\n return { content: [{ type: 'text', text: `Error: ${result.error}` }], isError: true }\n }\n\n return {\n content: [{\n type: 'text',\n text: `Knowledge document ${args.knowledge_id} deleted`\n }]\n }\n }\n)\n\n// ============================================\n// Context Tools\n// ============================================\n\nserver.registerTool(\n 'get_module_context',\n {\n description: 'Get the full context for a module (title, tasks, linked knowledge)',\n inputSchema: {\n module_uid: z.string().describe('The UID of the module (e.g., EP584)')\n }\n },\n async (args) => {\n interface ContextResponse {\n success: boolean\n context?: string\n error?: string\n }\n\n // Use the agent-accessible module context API\n const result = await apiRequest<ContextResponse>(\n 'GET',\n `/api/agent/context/module/${args.module_uid}`\n )\n\n if (!result.success || !result.context) {\n return { content: [{ type: 'text', text: `Error: ${result.error || 'Failed to fetch context'}` }], isError: true }\n }\n\n return {\n content: [{\n type: 'text',\n text: result.context\n }]\n }\n }\n)\n\nserver.registerTool(\n 'get_project_context',\n {\n description: 'Get the project-wide context (C2 bundle with active work, priorities)',\n inputSchema: {}\n },\n async () => {\n interface ContextResponse {\n success: boolean\n prompt?: string\n error?: string\n }\n\n // Use the agent-accessible system prompt API\n const result = await apiRequest<ContextResponse>(\n 'GET',\n '/api/agent/context/system'\n )\n\n if (!result.success || !result.prompt) {\n return { content: [{ type: 'text', text: `Error: ${result.error || 'Failed to fetch context'}` }], isError: true }\n }\n\n return {\n content: [{\n type: 'text',\n text: result.prompt\n }]\n }\n }\n)\n\n// ============================================\n// Start Server\n// ============================================\n\nasync function main() {\n const runtimeConfig = await hydrateRuntimeConfig()\n EPISODA_API_URL = runtimeConfig.apiUrl\n EPISODA_SESSION_TOKEN = runtimeConfig.sessionToken\n EPISODA_PROJECT_ID = runtimeConfig.projectId\n EPISODA_WORKSPACE_ID = runtimeConfig.workspaceId\n\n const transport = new StdioServerTransport()\n await server.connect(transport)\n\n // Log to stderr so it doesn't interfere with MCP protocol\n console.error('[episoda-workflow] MCP server started')\n console.error(`[episoda-workflow] API URL: ${EPISODA_API_URL}`)\n console.error(`[episoda-workflow] Token: ${EPISODA_SESSION_TOKEN ? '****' : 'NOT SET'}`)\n}\n\nmain().catch((error) => {\n console.error('[episoda-workflow] Fatal error:', error)\n process.exit(1)\n})\n","import * as fs from 'node:fs'\nimport * as os from 'node:os'\nimport * as path from 'node:path'\n\nconst DEFAULT_API_URL = 'https://episoda.dev'\nconst DEFAULT_CONFIG_FILE = 'config.json'\n\ninterface EpisodaLocalConfig {\n access_token?: string\n project_id?: string\n workspace_id?: string\n api_url?: string\n}\n\nexport interface RuntimeConfig {\n apiUrl: string\n sessionToken: string\n projectId: string\n workspaceId: string\n}\n\nconst normalizeEnv = (value?: string): string | undefined => {\n if (!value) return undefined\n const trimmed = value.trim()\n return trimmed.length > 0 ? trimmed : undefined\n}\n\nconst readEnvConfig = () => ({\n apiUrl: normalizeEnv(process.env.EPISODA_API_URL),\n sessionToken: normalizeEnv(process.env.EPISODA_SESSION_TOKEN),\n projectId: normalizeEnv(process.env.EPISODA_PROJECT_ID),\n workspaceId: normalizeEnv(process.env.EPISODA_WORKSPACE_ID)\n})\n\nconst buildMissingMessage = (missing: string[], apiUrl: string): string => {\n return [\n `[episoda-mcp] Missing auth context: ${missing.join(', ')}`,\n '[episoda-mcp] Set EPISODA_* env vars or run:',\n `[episoda-mcp] episoda auth --api-url ${apiUrl}`\n ].join('\\n')\n}\n\nconst getConfigPath = (): string => {\n // MCP supports a full-path override in addition to the core-style config dir.\n if (process.env.EPISODA_CONFIG_PATH) {\n return process.env.EPISODA_CONFIG_PATH\n }\n const configDir = process.env.EPISODA_CONFIG_DIR || path.join(os.homedir(), '.episoda')\n return path.join(configDir, DEFAULT_CONFIG_FILE)\n}\n\nconst loadLocalConfig = (): EpisodaLocalConfig | null => {\n const configPath = getConfigPath()\n if (!fs.existsSync(configPath)) {\n return null\n }\n try {\n const content = fs.readFileSync(configPath, 'utf8')\n return JSON.parse(content) as EpisodaLocalConfig\n } catch (error) {\n console.error('[episoda-mcp] Failed to load config:', error)\n return null\n }\n}\n\nexport async function resolveRuntimeConfig(): Promise<RuntimeConfig> {\n const envConfig = readEnvConfig()\n\n let fileConfig: EpisodaLocalConfig | null = null\n if (!envConfig.sessionToken || !envConfig.projectId || !envConfig.workspaceId || !envConfig.apiUrl) {\n fileConfig = loadLocalConfig()\n }\n\n const resolved: RuntimeConfig = {\n apiUrl: envConfig.apiUrl || fileConfig?.api_url || DEFAULT_API_URL,\n sessionToken: envConfig.sessionToken || fileConfig?.access_token || '',\n projectId: envConfig.projectId || fileConfig?.project_id || '',\n workspaceId: envConfig.workspaceId || fileConfig?.workspace_id || ''\n }\n\n const missing: string[] = []\n if (!resolved.sessionToken) missing.push('EPISODA_SESSION_TOKEN')\n if (!resolved.projectId) missing.push('EPISODA_PROJECT_ID')\n if (!resolved.workspaceId) missing.push('EPISODA_WORKSPACE_ID')\n\n if (missing.length > 0) {\n throw new Error(buildMissingMessage(missing, resolved.apiUrl))\n }\n\n return resolved\n}\n\nexport async function hydrateRuntimeConfig(): Promise<RuntimeConfig> {\n const resolved = await resolveRuntimeConfig()\n\n if (!normalizeEnv(process.env.EPISODA_API_URL)) {\n process.env.EPISODA_API_URL = resolved.apiUrl\n }\n if (!normalizeEnv(process.env.EPISODA_SESSION_TOKEN)) {\n process.env.EPISODA_SESSION_TOKEN = resolved.sessionToken\n }\n if (!normalizeEnv(process.env.EPISODA_PROJECT_ID)) {\n process.env.EPISODA_PROJECT_ID = resolved.projectId\n }\n if (!normalizeEnv(process.env.EPISODA_WORKSPACE_ID)) {\n process.env.EPISODA_WORKSPACE_ID = resolved.workspaceId\n }\n\n return resolved\n}\n"],"mappings":"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","names":["path"]}
|