@episoda/mcp 0.1.7 → 0.1.9
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 +287 -1
- package/dist/cli.js.map +1 -1
- package/dist/workflow-server.js +287 -1
- package/dist/workflow-server.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -278,7 +278,7 @@ ${task.description_md || "_No description_"}`
|
|
|
278
278
|
}
|
|
279
279
|
},
|
|
280
280
|
async (args) => {
|
|
281
|
-
const result = await apiRequest("GET", `/api/
|
|
281
|
+
const result = await apiRequest("GET", `/api/tasks?module_id=${args.module_uid}`);
|
|
282
282
|
if (!result.success || !result.tasks) {
|
|
283
283
|
return { content: [{ type: "text", text: `Error: ${result.error || "Failed to fetch tasks"}` }], isError: true };
|
|
284
284
|
}
|
|
@@ -300,6 +300,27 @@ ${taskList}`
|
|
|
300
300
|
};
|
|
301
301
|
}
|
|
302
302
|
);
|
|
303
|
+
server.registerTool(
|
|
304
|
+
"delete_task",
|
|
305
|
+
{
|
|
306
|
+
description: "Delete a task by UID",
|
|
307
|
+
inputSchema: {
|
|
308
|
+
task_uid: z.string().describe("The UID of the task (e.g., EP584-1)")
|
|
309
|
+
}
|
|
310
|
+
},
|
|
311
|
+
async (args) => {
|
|
312
|
+
const result = await apiRequest("DELETE", `/api/tasks/${args.task_uid}`);
|
|
313
|
+
if (!result.success) {
|
|
314
|
+
return { content: [{ type: "text", text: `Error: ${result.error}` }], isError: true };
|
|
315
|
+
}
|
|
316
|
+
return {
|
|
317
|
+
content: [{
|
|
318
|
+
type: "text",
|
|
319
|
+
text: `Task ${args.task_uid} deleted`
|
|
320
|
+
}]
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
);
|
|
303
324
|
server.registerTool(
|
|
304
325
|
"batch_update_task_state",
|
|
305
326
|
{
|
|
@@ -629,6 +650,123 @@ ${mod.description_md || "_No description_"}`
|
|
|
629
650
|
};
|
|
630
651
|
}
|
|
631
652
|
);
|
|
653
|
+
server.registerTool(
|
|
654
|
+
"delete_module",
|
|
655
|
+
{
|
|
656
|
+
description: "Delete a module by UID",
|
|
657
|
+
inputSchema: {
|
|
658
|
+
module_uid: z.string().describe("The UID of the module (e.g., EP584)")
|
|
659
|
+
}
|
|
660
|
+
},
|
|
661
|
+
async (args) => {
|
|
662
|
+
const result = await apiRequest("DELETE", `/api/modules/${args.module_uid}`);
|
|
663
|
+
if (!result.success) {
|
|
664
|
+
return { content: [{ type: "text", text: `Error: ${result.error}` }], isError: true };
|
|
665
|
+
}
|
|
666
|
+
return {
|
|
667
|
+
content: [{
|
|
668
|
+
type: "text",
|
|
669
|
+
text: `Module ${args.module_uid} deleted`
|
|
670
|
+
}]
|
|
671
|
+
};
|
|
672
|
+
}
|
|
673
|
+
);
|
|
674
|
+
server.registerTool(
|
|
675
|
+
"list_modules",
|
|
676
|
+
{
|
|
677
|
+
description: `List modules in the project with optional filtering.
|
|
678
|
+
|
|
679
|
+
USE THIS WHEN:
|
|
680
|
+
- Discovering modules without knowing UIDs
|
|
681
|
+
- Checking what's currently in progress
|
|
682
|
+
- Finding modules by state`,
|
|
683
|
+
inputSchema: {
|
|
684
|
+
state: z.enum(["backlog", "ready", "doing", "review", "done"]).optional().describe("Filter by module state"),
|
|
685
|
+
limit: z.number().optional().describe("Maximum results (default: 25)"),
|
|
686
|
+
include_task_counts: z.boolean().optional().describe("Include task counts per module")
|
|
687
|
+
}
|
|
688
|
+
},
|
|
689
|
+
async (args) => {
|
|
690
|
+
const params = new URLSearchParams();
|
|
691
|
+
if (args.state) params.set("state", args.state);
|
|
692
|
+
if (args.limit) params.set("limit", String(args.limit));
|
|
693
|
+
if (args.include_task_counts) params.set("includeTaskCounts", "true");
|
|
694
|
+
const query = params.toString();
|
|
695
|
+
const result = await apiRequest("GET", `/api/modules${query ? `?${query}` : ""}`);
|
|
696
|
+
if (!result.success || !result.modules) {
|
|
697
|
+
return { content: [{ type: "text", text: `Error: ${result.error || "Failed to fetch modules"}` }], isError: true };
|
|
698
|
+
}
|
|
699
|
+
if (result.modules.length === 0) {
|
|
700
|
+
return { content: [{ type: "text", text: `No modules found${args.state ? ` in state "${args.state}"` : ""}.` }] };
|
|
701
|
+
}
|
|
702
|
+
const moduleList = result.modules.map((m) => {
|
|
703
|
+
const taskInfo = m.task_counts ? ` [${m.task_counts.done}/${m.task_counts.total} tasks]` : "";
|
|
704
|
+
return `- **${m.uid}**: ${m.title} (${m.state})${taskInfo}`;
|
|
705
|
+
}).join("\n");
|
|
706
|
+
return {
|
|
707
|
+
content: [{
|
|
708
|
+
type: "text",
|
|
709
|
+
text: `# Modules${args.state ? ` (${args.state})` : ""}
|
|
710
|
+
|
|
711
|
+
${moduleList}`
|
|
712
|
+
}]
|
|
713
|
+
};
|
|
714
|
+
}
|
|
715
|
+
);
|
|
716
|
+
server.registerTool(
|
|
717
|
+
"transition_module",
|
|
718
|
+
{
|
|
719
|
+
description: `Transition a module to a new state using the orchestrated transition API.
|
|
720
|
+
|
|
721
|
+
This triggers the full transition flow (e.g., doing\u2192review creates PR, review\u2192done triggers merge).
|
|
722
|
+
Use this instead of request_review or mark_done for full control.`,
|
|
723
|
+
inputSchema: {
|
|
724
|
+
module_uid: z.string().describe("The UID of the module (e.g., EP584)"),
|
|
725
|
+
target_state: z.enum(["ready", "doing", "review", "done"]).describe("Target state for the module")
|
|
726
|
+
}
|
|
727
|
+
},
|
|
728
|
+
async (args) => {
|
|
729
|
+
const result = await apiRequest(
|
|
730
|
+
"POST",
|
|
731
|
+
`/api/modules/${args.module_uid}/transition`,
|
|
732
|
+
{ target_state: args.target_state }
|
|
733
|
+
);
|
|
734
|
+
if (!result.success) {
|
|
735
|
+
return { content: [{ type: "text", text: `Error: ${result.error}` }], isError: true };
|
|
736
|
+
}
|
|
737
|
+
return {
|
|
738
|
+
content: [{
|
|
739
|
+
type: "text",
|
|
740
|
+
text: `Module ${args.module_uid} transitioned to ${args.target_state}`
|
|
741
|
+
}]
|
|
742
|
+
};
|
|
743
|
+
}
|
|
744
|
+
);
|
|
745
|
+
server.registerTool(
|
|
746
|
+
"archive_module",
|
|
747
|
+
{
|
|
748
|
+
description: "Archive a module instead of deleting it",
|
|
749
|
+
inputSchema: {
|
|
750
|
+
module_uid: z.string().describe("The UID of the module (e.g., EP584)")
|
|
751
|
+
}
|
|
752
|
+
},
|
|
753
|
+
async (args) => {
|
|
754
|
+
const result = await apiRequest(
|
|
755
|
+
"POST",
|
|
756
|
+
`/api/modules/${args.module_uid}/archive`,
|
|
757
|
+
{}
|
|
758
|
+
);
|
|
759
|
+
if (!result.success) {
|
|
760
|
+
return { content: [{ type: "text", text: `Error: ${result.error}` }], isError: true };
|
|
761
|
+
}
|
|
762
|
+
return {
|
|
763
|
+
content: [{
|
|
764
|
+
type: "text",
|
|
765
|
+
text: `Module ${args.module_uid} archived`
|
|
766
|
+
}]
|
|
767
|
+
};
|
|
768
|
+
}
|
|
769
|
+
);
|
|
632
770
|
server.registerTool(
|
|
633
771
|
"get_knowledge",
|
|
634
772
|
{
|
|
@@ -856,6 +994,62 @@ Both semantic and text search returned no results.` }] };
|
|
|
856
994
|
Query: "${args.query}"
|
|
857
995
|
Found: ${ranked.length} documents (${bothCount} matched both semantic + text)
|
|
858
996
|
|
|
997
|
+
${list}`
|
|
998
|
+
}]
|
|
999
|
+
};
|
|
1000
|
+
}
|
|
1001
|
+
);
|
|
1002
|
+
server.registerTool(
|
|
1003
|
+
"search_conversations",
|
|
1004
|
+
{
|
|
1005
|
+
description: `Search past agent conversations in this project.
|
|
1006
|
+
|
|
1007
|
+
This searches agent conversation history (agent_messages) across sessions you can access.
|
|
1008
|
+
|
|
1009
|
+
USE THIS WHEN:
|
|
1010
|
+
- The user references a prior discussion
|
|
1011
|
+
- You need to recover context after compaction
|
|
1012
|
+
- You want to find when/where something was decided`,
|
|
1013
|
+
inputSchema: {
|
|
1014
|
+
query: z.string().describe("Semantic search query"),
|
|
1015
|
+
limit: z.number().optional().describe("Max results (default: 10)"),
|
|
1016
|
+
threshold: z.number().optional().describe("Min similarity 0-1 (default: 0.5)"),
|
|
1017
|
+
days_back: z.number().optional().describe("Limit to recent N days (optional)"),
|
|
1018
|
+
session_id: z.string().optional().describe("Limit to a specific session UUID (optional)")
|
|
1019
|
+
}
|
|
1020
|
+
},
|
|
1021
|
+
async (args) => {
|
|
1022
|
+
const result = await apiRequest(
|
|
1023
|
+
"POST",
|
|
1024
|
+
"/api/search/conversations",
|
|
1025
|
+
{
|
|
1026
|
+
query: args.query,
|
|
1027
|
+
limit: args.limit || 10,
|
|
1028
|
+
threshold: args.threshold || 0.5,
|
|
1029
|
+
...args.days_back !== void 0 ? { days_back: args.days_back } : {},
|
|
1030
|
+
...args.session_id ? { session_id: args.session_id } : {}
|
|
1031
|
+
}
|
|
1032
|
+
);
|
|
1033
|
+
if (!result.success || !result.results) {
|
|
1034
|
+
return { content: [{ type: "text", text: `Error: ${result.error || "Conversation search failed"}` }], isError: true };
|
|
1035
|
+
}
|
|
1036
|
+
if (result.results.length === 0) {
|
|
1037
|
+
return { content: [{ type: "text", text: `No conversation messages found matching: "${args.query}"` }] };
|
|
1038
|
+
}
|
|
1039
|
+
const list = result.results.map((r) => {
|
|
1040
|
+
const score = Math.round((r.similarity || 0) * 100);
|
|
1041
|
+
const moduleInfo = r.module_uid ? ` | ${r.module_uid}${r.module_title ? `: ${r.module_title}` : ""}` : "";
|
|
1042
|
+
const when = r.created_at ? ` | ${r.created_at}` : "";
|
|
1043
|
+
return `- [${r.role}, ${score}%] ${r.content_snippet}${moduleInfo}${when}`;
|
|
1044
|
+
}).join("\n");
|
|
1045
|
+
return {
|
|
1046
|
+
content: [{
|
|
1047
|
+
type: "text",
|
|
1048
|
+
text: `# Conversation Search Results
|
|
1049
|
+
|
|
1050
|
+
Query: "${args.query}"
|
|
1051
|
+
Found: ${result.results.length}
|
|
1052
|
+
|
|
859
1053
|
${list}`
|
|
860
1054
|
}]
|
|
861
1055
|
};
|
|
@@ -917,6 +1111,98 @@ ${list}`
|
|
|
917
1111
|
};
|
|
918
1112
|
}
|
|
919
1113
|
);
|
|
1114
|
+
server.registerTool(
|
|
1115
|
+
"create_knowledge",
|
|
1116
|
+
{
|
|
1117
|
+
description: `Create a new knowledge document in the knowledge base.
|
|
1118
|
+
|
|
1119
|
+
USE THIS WHEN:
|
|
1120
|
+
- Documenting technical decisions or architecture
|
|
1121
|
+
- Capturing research findings or discoveries
|
|
1122
|
+
- Creating process directives or guidelines
|
|
1123
|
+
|
|
1124
|
+
All documentation MUST be created in the knowledge base, not as markdown files.`,
|
|
1125
|
+
inputSchema: {
|
|
1126
|
+
title: z.string().describe("Title of the knowledge document"),
|
|
1127
|
+
domain: z.enum(["tech", "business", "process", "people"]).describe("Knowledge domain"),
|
|
1128
|
+
doc_type: z.enum(["directive", "discovery", "documentation"]).describe("Document type"),
|
|
1129
|
+
significance: z.number().describe("Significance score from 0.0 to 1.0"),
|
|
1130
|
+
markdown: z.string().describe("The document content in markdown")
|
|
1131
|
+
}
|
|
1132
|
+
},
|
|
1133
|
+
async (args) => {
|
|
1134
|
+
const result = await apiRequest("POST", "/api/knowledge", {
|
|
1135
|
+
title: args.title,
|
|
1136
|
+
domain: args.domain,
|
|
1137
|
+
doc_type: args.doc_type,
|
|
1138
|
+
significance: args.significance,
|
|
1139
|
+
markdown: args.markdown
|
|
1140
|
+
});
|
|
1141
|
+
if (!result.success) {
|
|
1142
|
+
return { content: [{ type: "text", text: `Error: ${result.error}` }], isError: true };
|
|
1143
|
+
}
|
|
1144
|
+
const k = result.knowledge;
|
|
1145
|
+
return {
|
|
1146
|
+
content: [{
|
|
1147
|
+
type: "text",
|
|
1148
|
+
text: `Created knowledge document${k?.uid ? ` ${k.uid}` : ""}: ${k?.title} (id: ${k?.id})`
|
|
1149
|
+
}]
|
|
1150
|
+
};
|
|
1151
|
+
}
|
|
1152
|
+
);
|
|
1153
|
+
server.registerTool(
|
|
1154
|
+
"update_knowledge",
|
|
1155
|
+
{
|
|
1156
|
+
description: "Update an existing knowledge document",
|
|
1157
|
+
inputSchema: {
|
|
1158
|
+
knowledge_id: z.string().describe("The ID of the knowledge document"),
|
|
1159
|
+
title: z.string().optional().describe("New title"),
|
|
1160
|
+
markdown: z.string().optional().describe("New markdown content"),
|
|
1161
|
+
domain: z.enum(["tech", "business", "process", "people"]).optional().describe("New domain"),
|
|
1162
|
+
doc_type: z.enum(["directive", "discovery", "documentation"]).optional().describe("New document type"),
|
|
1163
|
+
significance: z.number().optional().describe("New significance score (0.0-1.0)")
|
|
1164
|
+
}
|
|
1165
|
+
},
|
|
1166
|
+
async (args) => {
|
|
1167
|
+
const updates = {};
|
|
1168
|
+
if (args.title) updates.title = args.title;
|
|
1169
|
+
if (args.markdown) updates.markdown = args.markdown;
|
|
1170
|
+
if (args.domain) updates.domain = args.domain;
|
|
1171
|
+
if (args.doc_type) updates.doc_type = args.doc_type;
|
|
1172
|
+
if (args.significance !== void 0) updates.significance = args.significance;
|
|
1173
|
+
const result = await apiRequest("PATCH", `/api/knowledge/${args.knowledge_id}`, updates);
|
|
1174
|
+
if (!result.success) {
|
|
1175
|
+
return { content: [{ type: "text", text: `Error: ${result.error}` }], isError: true };
|
|
1176
|
+
}
|
|
1177
|
+
return {
|
|
1178
|
+
content: [{
|
|
1179
|
+
type: "text",
|
|
1180
|
+
text: `Knowledge document ${args.knowledge_id} updated`
|
|
1181
|
+
}]
|
|
1182
|
+
};
|
|
1183
|
+
}
|
|
1184
|
+
);
|
|
1185
|
+
server.registerTool(
|
|
1186
|
+
"delete_knowledge",
|
|
1187
|
+
{
|
|
1188
|
+
description: "Delete a knowledge document by ID",
|
|
1189
|
+
inputSchema: {
|
|
1190
|
+
knowledge_id: z.string().describe("The ID of the knowledge document")
|
|
1191
|
+
}
|
|
1192
|
+
},
|
|
1193
|
+
async (args) => {
|
|
1194
|
+
const result = await apiRequest("DELETE", `/api/knowledge/${args.knowledge_id}`);
|
|
1195
|
+
if (!result.success) {
|
|
1196
|
+
return { content: [{ type: "text", text: `Error: ${result.error}` }], isError: true };
|
|
1197
|
+
}
|
|
1198
|
+
return {
|
|
1199
|
+
content: [{
|
|
1200
|
+
type: "text",
|
|
1201
|
+
text: `Knowledge document ${args.knowledge_id} deleted`
|
|
1202
|
+
}]
|
|
1203
|
+
};
|
|
1204
|
+
}
|
|
1205
|
+
);
|
|
920
1206
|
server.registerTool(
|
|
921
1207
|
"get_module_context",
|
|
922
1208
|
{
|