@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.
@@ -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": ["COMPLETE list of ALL things this project is responsible for - do NOT limit, include everything"],
1038
- "owns": ["ALL file patterns or directories this project owns, e.g., '*DTO.ts', 'services/', 'controllers/'"],
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
- IMPORTANT:
1045
- - responsibilities MUST be COMPLETE - list ALL responsibilities, not just 3-5. Missing responsibilities will cause the orchestrator to fail at delegating tasks correctly.
1046
- - For "owns", include ALL file patterns and directories that ONLY this project should create/modify
1047
- - If it's a library, identify what it exports/provides to other projects
1048
- - Be thorough - incomplete information leads to incorrect task routing
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 {
@@ -1,2 +1,2 @@
1
1
  // Version of the MCP Kanban server
2
- export const VERSION = "0.2.1";
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
  };
@@ -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
- Analyze the task and determine:
52
- 1. What components/code need to be created or modified?
53
- 2. Which project is responsible for each component based on their declared responsibilities?
54
- 3. If something doesn't exist in any project, it can be created by the requesting project
55
- 4. If something SHOULD exist in another project (based on responsibilities), it must be delegated
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, check the "owns" patterns to see what file types belong where
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
- - Be specific in taskDescription so the receiving project knows exactly what to create
87
- - Always explain the reasoning based on project responsibilities
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 reasoning model for better analysis
150
- const model = process.env.MEMORYBANK_REASONING_MODEL || "gpt-5-mini";
151
- const response = await client.responses.create({
152
- model,
153
- reasoning: {
154
- effort: "medium",
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
- input: [
157
- {
158
- role: "user",
159
- content: prompt,
160
- },
161
- ],
162
- max_output_tokens: 4000,
163
- });
164
- // Extract content from response
165
- let content = "";
166
- for (const item of response.output || []) {
167
- if (item.type === "message" && item.content) {
168
- for (const contentItem of item.content) {
169
- if (contentItem.type === "output_text") {
170
- content += contentItem.text;
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 = content.match(/\{[\s\S]*\}/);
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',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@grec0/memory-bank-mcp",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
4
4
  "description": "MCP server for semantic code indexing with Memory Bank - AI-powered codebase understanding",
5
5
  "license": "MIT",
6
6
  "author": "@grec0",