@grec0/memory-bank-mcp 0.2.2 → 0.2.4
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/common/projectKnowledgeService.js +12 -7
- package/dist/common/version.js +1 -1
- package/dist/index.js +1 -1
- package/dist/tools/routeTask.js +171 -79
- package/package.json +1 -1
|
@@ -1034,18 +1034,23 @@ ${techContext ? `TECHNICAL CONTEXT:\n${techContext.content}` : ''}
|
|
|
1034
1034
|
Extract the following information in JSON format:
|
|
1035
1035
|
{
|
|
1036
1036
|
"description": "A concise 1-2 sentence description of what this project does",
|
|
1037
|
-
"responsibilities": ["
|
|
1038
|
-
"owns": ["
|
|
1037
|
+
"responsibilities": ["List ALL functional responsibilities - what this project DOES as capabilities/features"],
|
|
1038
|
+
"owns": ["File patterns or directories this project owns, e.g., 'src/services/', '*DTO.ts', 'controllers/'"],
|
|
1039
1039
|
"projectType": "One of: api, library, frontend, backend, cli, service, monorepo, fullstack",
|
|
1040
1040
|
"exports": "Package name if it's a library (e.g., '@company/lib-dtos'), or null if not applicable",
|
|
1041
1041
|
"keywords": ["Relevant keywords describing this project"]
|
|
1042
1042
|
}
|
|
1043
1043
|
|
|
1044
|
-
|
|
1045
|
-
- responsibilities
|
|
1046
|
-
-
|
|
1047
|
-
-
|
|
1048
|
-
-
|
|
1044
|
+
CRITICAL GUIDELINES:
|
|
1045
|
+
- responsibilities: List ALL functional capabilities - what this project DOES, NOT how it does it
|
|
1046
|
+
- ✅ GOOD: "Index codebases into vector embeddings", "Provide semantic search over code"
|
|
1047
|
+
- ❌ BAD: "Uses tree-sitter for parsing", "Runs Jest tests", "Documents caveats in README"
|
|
1048
|
+
- Focus on FEATURES and CAPABILITIES, not implementation details, configuration, testing, or documentation
|
|
1049
|
+
- owns: List directories/patterns this project creates or modifies (not every file it contains)
|
|
1050
|
+
- ✅ GOOD: "src/tools/", ".memorybank/", "src/services/"
|
|
1051
|
+
- ❌ BAD: "README.md", "package.json", "tsconfig.json" (these are generic project files)
|
|
1052
|
+
- Be thorough on functional responsibilities - missing ones cause incorrect task routing
|
|
1053
|
+
- Ignore implementation details, CI/CD, testing setup, documentation practices
|
|
1049
1054
|
|
|
1050
1055
|
Respond ONLY with the JSON object, no markdown or explanation.`;
|
|
1051
1056
|
try {
|
package/dist/common/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// Version of the MCP Kanban server
|
|
2
|
-
export const VERSION = "0.2.
|
|
2
|
+
export const VERSION = "0.2.3";
|
package/dist/index.js
CHANGED
|
@@ -873,7 +873,7 @@ server.tool(routeTaskToolDefinition.name, routeTaskToolDefinition.description, {
|
|
|
873
873
|
const result = await routeTaskTool({
|
|
874
874
|
projectId: args.projectId,
|
|
875
875
|
taskDescription: args.taskDescription
|
|
876
|
-
});
|
|
876
|
+
}, indexManager);
|
|
877
877
|
return {
|
|
878
878
|
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
879
879
|
};
|
package/dist/tools/routeTask.js
CHANGED
|
@@ -2,9 +2,13 @@
|
|
|
2
2
|
* @fileoverview Task Routing Orchestrator
|
|
3
3
|
* Uses AI reasoning to analyze tasks and distribute work across projects
|
|
4
4
|
* based on their responsibilities. MANDATORY before any implementation.
|
|
5
|
+
*
|
|
6
|
+
* The orchestrator has access to semantic search tools to verify where
|
|
7
|
+
* code actually exists, not just rely on declared responsibilities.
|
|
5
8
|
*/
|
|
6
9
|
import OpenAI from "openai";
|
|
7
10
|
import { RegistryManager } from "../common/registryManager.js";
|
|
11
|
+
import { searchMemory } from "./searchMemory.js";
|
|
8
12
|
/**
|
|
9
13
|
* Builds a context string describing all projects and their responsibilities
|
|
10
14
|
*/
|
|
@@ -35,33 +39,113 @@ function buildProjectsContext(projects, currentProjectId) {
|
|
|
35
39
|
}
|
|
36
40
|
return context;
|
|
37
41
|
}
|
|
42
|
+
/**
|
|
43
|
+
* Tools available to the orchestrator for verification
|
|
44
|
+
*/
|
|
45
|
+
const ORCHESTRATOR_TOOLS = [
|
|
46
|
+
{
|
|
47
|
+
type: "function",
|
|
48
|
+
function: {
|
|
49
|
+
name: "semantic_search",
|
|
50
|
+
description: "Search for code semantically in a specific project. Use this to verify if code already exists, where implementations are located, or to understand project structure before routing decisions.",
|
|
51
|
+
parameters: {
|
|
52
|
+
type: "object",
|
|
53
|
+
properties: {
|
|
54
|
+
projectId: {
|
|
55
|
+
type: "string",
|
|
56
|
+
description: "The project ID to search in",
|
|
57
|
+
},
|
|
58
|
+
query: {
|
|
59
|
+
type: "string",
|
|
60
|
+
description: "Natural language query describing what you're looking for (e.g., 'UserDTO class', 'authentication service', 'database connection')",
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
required: ["projectId", "query"],
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
];
|
|
68
|
+
/**
|
|
69
|
+
* Executes a tool call from the orchestrator
|
|
70
|
+
*/
|
|
71
|
+
async function executeToolCall(toolName, args, allProjects, indexManager) {
|
|
72
|
+
if (toolName === "semantic_search") {
|
|
73
|
+
const { projectId, query } = args;
|
|
74
|
+
// Verify project exists
|
|
75
|
+
const projectExists = allProjects.some(p => p.projectId === projectId);
|
|
76
|
+
if (!projectExists) {
|
|
77
|
+
return JSON.stringify({
|
|
78
|
+
error: `Project '${projectId}' not found. Available: ${allProjects.map(p => p.projectId).join(', ')}`
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
try {
|
|
82
|
+
console.error(` [Tool] Searching in ${projectId}: "${query}"`);
|
|
83
|
+
const result = await searchMemory({
|
|
84
|
+
projectId,
|
|
85
|
+
query,
|
|
86
|
+
topK: 5,
|
|
87
|
+
minScore: 0.5,
|
|
88
|
+
}, indexManager);
|
|
89
|
+
if (!result.success || result.results.length === 0) {
|
|
90
|
+
return JSON.stringify({
|
|
91
|
+
found: false,
|
|
92
|
+
message: `No results found for "${query}" in project ${projectId}`
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
// Return summarized results (not full code, just locations and snippets)
|
|
96
|
+
const summary = result.results.map(r => ({
|
|
97
|
+
file: r.filePath,
|
|
98
|
+
type: r.chunkType,
|
|
99
|
+
name: r.name,
|
|
100
|
+
score: r.score.toFixed(2),
|
|
101
|
+
preview: r.content.slice(0, 200) + (r.content.length > 200 ? '...' : ''),
|
|
102
|
+
}));
|
|
103
|
+
return JSON.stringify({
|
|
104
|
+
found: true,
|
|
105
|
+
count: result.results.length,
|
|
106
|
+
results: summary
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
return JSON.stringify({ error: error.message });
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return JSON.stringify({ error: `Unknown tool: ${toolName}` });
|
|
114
|
+
}
|
|
38
115
|
/**
|
|
39
116
|
* The main routing prompt for the AI orchestrator
|
|
40
117
|
*/
|
|
41
118
|
const ROUTING_PROMPT = `You are a Task Routing Orchestrator for a multi-project workspace. Your job is to analyze a task and determine which parts belong to which project based on their responsibilities.
|
|
42
119
|
|
|
120
|
+
You have access to a semantic_search tool that allows you to search for code in any project. USE IT when:
|
|
121
|
+
- You need to verify if something already exists
|
|
122
|
+
- A task could belong to multiple projects and you need to check where the related code is
|
|
123
|
+
- You want to confirm where implementations are located before making routing decisions
|
|
124
|
+
|
|
43
125
|
{projectsContext}
|
|
44
126
|
|
|
45
127
|
## Task to Analyze
|
|
46
128
|
**From Project**: {currentProject}
|
|
47
129
|
**Task Description**: {taskDescription}
|
|
48
130
|
|
|
49
|
-
## Your Analysis
|
|
131
|
+
## Your Analysis Process
|
|
50
132
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
133
|
+
1. First, identify what components/code need to be created or modified
|
|
134
|
+
2. Check the declared responsibilities of each project
|
|
135
|
+
3. If there's ambiguity (task could match multiple projects), USE semantic_search to verify:
|
|
136
|
+
- Search for related existing code
|
|
137
|
+
- Check which project actually has the relevant implementations
|
|
138
|
+
4. Make your routing decision based on BOTH responsibilities AND actual code location
|
|
56
139
|
|
|
57
140
|
## Rules
|
|
58
141
|
- If a project is responsible for DTOs, ALL DTOs must be created there, not in the API
|
|
59
142
|
- If a project is responsible for services, shared services go there
|
|
60
143
|
- If a project is responsible for utils/common code, shared utilities go there
|
|
61
144
|
- The requesting project can ONLY implement what falls within its responsibilities
|
|
62
|
-
- When in doubt,
|
|
145
|
+
- When in doubt, USE semantic_search to verify where similar code exists
|
|
146
|
+
- If code exists in a project, new related code should likely go there too
|
|
63
147
|
|
|
64
|
-
## Response Format
|
|
148
|
+
## Response Format (after your analysis and any tool calls)
|
|
65
149
|
Respond with a JSON object:
|
|
66
150
|
{
|
|
67
151
|
"action": "proceed" | "delegate" | "mixed",
|
|
@@ -76,21 +160,24 @@ Respond with a JSON object:
|
|
|
76
160
|
],
|
|
77
161
|
"suggestedImports": ["packages or modules to import after delegations complete"],
|
|
78
162
|
"architectureNotes": "Explanation of the distribution decision",
|
|
79
|
-
"warning": "Optional warning if something seems off"
|
|
163
|
+
"warning": "Optional warning if something seems off",
|
|
164
|
+
"searchesPerformed": ["List of searches you performed to verify the decision"]
|
|
80
165
|
}
|
|
81
166
|
|
|
82
167
|
IMPORTANT:
|
|
83
168
|
- "action" is "proceed" if everything can be done by the requesting project
|
|
84
|
-
- "action" is "delegate" if everything needs to go to other projects
|
|
169
|
+
- "action" is "delegate" if everything needs to go to other projects
|
|
85
170
|
- "action" is "mixed" if some work is local and some needs delegation
|
|
86
|
-
-
|
|
87
|
-
-
|
|
171
|
+
- Use semantic_search when responsibilities are ambiguous or could match multiple projects
|
|
172
|
+
- Document what searches you performed in "searchesPerformed"
|
|
173
|
+
- Responde siempre en ESPAÑOL
|
|
88
174
|
|
|
89
|
-
Respond ONLY with the JSON object.`;
|
|
175
|
+
Respond ONLY with the JSON object after completing your analysis.`;
|
|
90
176
|
/**
|
|
91
177
|
* Routes a task to the appropriate project(s) based on responsibilities
|
|
178
|
+
* Uses function calling to allow the AI to perform semantic searches when needed
|
|
92
179
|
*/
|
|
93
|
-
export async function routeTaskTool(params) {
|
|
180
|
+
export async function routeTaskTool(params, indexManager) {
|
|
94
181
|
const { projectId, taskDescription } = params;
|
|
95
182
|
if (!taskDescription || taskDescription.trim() === '') {
|
|
96
183
|
return {
|
|
@@ -145,35 +232,78 @@ export async function routeTaskTool(params) {
|
|
|
145
232
|
.replace('{projectsContext}', projectsContext)
|
|
146
233
|
.replace('{currentProject}', projectId)
|
|
147
234
|
.replace('{taskDescription}', taskDescription);
|
|
148
|
-
console.error(`Calling AI orchestrator...`);
|
|
149
|
-
// Use
|
|
150
|
-
const model = process.env.
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
235
|
+
console.error(`Calling AI orchestrator with tool access...`);
|
|
236
|
+
// Use chat completions with function calling
|
|
237
|
+
const model = process.env.MEMORYBANK_ROUTING_MODEL || "gpt-4o";
|
|
238
|
+
// Initialize conversation
|
|
239
|
+
const messages = [
|
|
240
|
+
{
|
|
241
|
+
role: "system",
|
|
242
|
+
content: "You are a Task Routing Orchestrator. Analyze tasks and route them to appropriate projects. You can use semantic_search to verify where code exists before making decisions. Always respond with JSON after your analysis.",
|
|
155
243
|
},
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
244
|
+
{
|
|
245
|
+
role: "user",
|
|
246
|
+
content: prompt,
|
|
247
|
+
},
|
|
248
|
+
];
|
|
249
|
+
// Tool calling loop (max 5 iterations to prevent infinite loops)
|
|
250
|
+
let iterations = 0;
|
|
251
|
+
const maxIterations = 5;
|
|
252
|
+
let finalResponse = null;
|
|
253
|
+
while (iterations < maxIterations) {
|
|
254
|
+
iterations++;
|
|
255
|
+
console.error(` Iteration ${iterations}/${maxIterations}`);
|
|
256
|
+
const response = await client.chat.completions.create({
|
|
257
|
+
model,
|
|
258
|
+
messages,
|
|
259
|
+
tools: ORCHESTRATOR_TOOLS,
|
|
260
|
+
tool_choice: "auto",
|
|
261
|
+
max_tokens: 4000,
|
|
262
|
+
});
|
|
263
|
+
const message = response.choices[0]?.message;
|
|
264
|
+
if (!message) {
|
|
265
|
+
console.error(` No message in response`);
|
|
266
|
+
break;
|
|
267
|
+
}
|
|
268
|
+
// Check if there are tool calls
|
|
269
|
+
if (message.tool_calls && message.tool_calls.length > 0) {
|
|
270
|
+
console.error(` Model requested ${message.tool_calls.length} tool call(s)`);
|
|
271
|
+
// Add assistant message with tool calls
|
|
272
|
+
messages.push(message);
|
|
273
|
+
// Execute each tool call
|
|
274
|
+
for (const toolCall of message.tool_calls) {
|
|
275
|
+
const toolName = toolCall.function.name;
|
|
276
|
+
const toolArgs = JSON.parse(toolCall.function.arguments);
|
|
277
|
+
const toolResult = await executeToolCall(toolName, toolArgs, allProjects, indexManager);
|
|
278
|
+
// Add tool result to messages
|
|
279
|
+
messages.push({
|
|
280
|
+
role: "tool",
|
|
281
|
+
tool_call_id: toolCall.id,
|
|
282
|
+
content: toolResult,
|
|
283
|
+
});
|
|
172
284
|
}
|
|
173
285
|
}
|
|
286
|
+
else {
|
|
287
|
+
// No tool calls, this is the final response
|
|
288
|
+
finalResponse = message.content;
|
|
289
|
+
console.error(` Final response received`);
|
|
290
|
+
break;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
if (!finalResponse) {
|
|
294
|
+
console.error(` No final response after ${iterations} iterations`);
|
|
295
|
+
return {
|
|
296
|
+
success: false,
|
|
297
|
+
action: 'proceed',
|
|
298
|
+
myResponsibilities: [],
|
|
299
|
+
delegations: [],
|
|
300
|
+
suggestedImports: [],
|
|
301
|
+
architectureNotes: 'Orchestrator did not produce a final response.',
|
|
302
|
+
warning: 'Analysis incomplete. Review task manually.',
|
|
303
|
+
};
|
|
174
304
|
}
|
|
175
305
|
// Parse JSON response
|
|
176
|
-
const jsonMatch =
|
|
306
|
+
const jsonMatch = finalResponse.match(/\{[\s\S]*\}/);
|
|
177
307
|
if (!jsonMatch) {
|
|
178
308
|
console.error(`Failed to parse orchestrator response`);
|
|
179
309
|
return {
|
|
@@ -191,6 +321,9 @@ export async function routeTaskTool(params) {
|
|
|
191
321
|
console.error(` Action: ${result.action}`);
|
|
192
322
|
console.error(` My responsibilities: ${result.myResponsibilities?.length || 0}`);
|
|
193
323
|
console.error(` Delegations: ${result.delegations?.length || 0}`);
|
|
324
|
+
if (result.searchesPerformed?.length > 0) {
|
|
325
|
+
console.error(` Searches performed: ${result.searchesPerformed.length}`);
|
|
326
|
+
}
|
|
194
327
|
if (result.delegations && result.delegations.length > 0) {
|
|
195
328
|
console.error(`\n Delegations:`);
|
|
196
329
|
for (const d of result.delegations) {
|
|
@@ -209,47 +342,6 @@ export async function routeTaskTool(params) {
|
|
|
209
342
|
}
|
|
210
343
|
catch (error) {
|
|
211
344
|
console.error(`Error in task routing: ${error.message}`);
|
|
212
|
-
// Fallback to chat completions if responses API fails
|
|
213
|
-
if (error?.status === 404 || error?.code === "model_not_found") {
|
|
214
|
-
try {
|
|
215
|
-
const client = new OpenAI({ apiKey });
|
|
216
|
-
const prompt = ROUTING_PROMPT
|
|
217
|
-
.replace('{projectsContext}', projectsContext)
|
|
218
|
-
.replace('{currentProject}', projectId)
|
|
219
|
-
.replace('{taskDescription}', taskDescription);
|
|
220
|
-
const response = await client.chat.completions.create({
|
|
221
|
-
model: "gpt-4o",
|
|
222
|
-
messages: [
|
|
223
|
-
{
|
|
224
|
-
role: "system",
|
|
225
|
-
content: "You are a Task Routing Orchestrator. Analyze tasks and route them to the appropriate projects based on responsibilities. Respond with JSON only.",
|
|
226
|
-
},
|
|
227
|
-
{
|
|
228
|
-
role: "user",
|
|
229
|
-
content: prompt,
|
|
230
|
-
},
|
|
231
|
-
],
|
|
232
|
-
max_tokens: 4000,
|
|
233
|
-
});
|
|
234
|
-
const content = response.choices[0]?.message?.content || "";
|
|
235
|
-
const jsonMatch = content.match(/\{[\s\S]*\}/);
|
|
236
|
-
if (jsonMatch) {
|
|
237
|
-
const result = JSON.parse(jsonMatch[0]);
|
|
238
|
-
return {
|
|
239
|
-
success: true,
|
|
240
|
-
action: result.action || 'proceed',
|
|
241
|
-
myResponsibilities: result.myResponsibilities || [],
|
|
242
|
-
delegations: result.delegations || [],
|
|
243
|
-
suggestedImports: result.suggestedImports || [],
|
|
244
|
-
architectureNotes: result.architectureNotes || '',
|
|
245
|
-
warning: result.warning,
|
|
246
|
-
};
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
catch (fallbackError) {
|
|
250
|
-
console.error(`Fallback also failed: ${fallbackError}`);
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
345
|
return {
|
|
254
346
|
success: false,
|
|
255
347
|
action: 'proceed',
|