UNPKG

mcp-server-debug-thinking

Version:

Graph-based MCP server for systematic debugging using Problem-Solution Trees and Hypothesis-Experiment-Learning cycles

212 lines 8.97 kB
import { describe, it, expect, beforeEach, afterEach } from "vitest"; import { GraphService } from "../../services/GraphService.js"; import { ActionType } from "../../types/graphActions.js"; describe("Debug Session Integration Tests", () => { let graphService; beforeEach(async () => { process.env.DEBUG_DATA_DIR = `.test-integration-${Date.now()}`; graphService = new GraphService(); await graphService.initialize(); }); afterEach(async () => { if (process.env.DEBUG_DATA_DIR) { const fs = await import("fs/promises"); try { await fs.rm(process.env.DEBUG_DATA_DIR, { recursive: true, force: true }); } catch (_error) { // Directory might not exist } delete process.env.DEBUG_DATA_DIR; } }); it("should handle a complete debugging workflow", async () => { // 1. Create a problem const problemResult = await graphService.create({ action: ActionType.CREATE, nodeType: "problem", content: 'TypeError: Cannot read property "data" of undefined in UserList component', metadata: { tags: ["react", "frontend", "production-bug"], severity: "high", }, }); const problem = JSON.parse(problemResult.content[0].text); expect(problem.success).toBe(true); // Check if similar problems were found if (problem.similarProblems) { console.log(`Found ${problem.similarProblems.length} similar problems`); } // 2. Create hypotheses const hypothesis1Result = await graphService.create({ action: ActionType.CREATE, nodeType: "hypothesis", content: "API response might be returning null instead of empty object", parentId: problem.nodeId, metadata: { confidence: 85, }, }); const hypothesis1 = JSON.parse(hypothesis1Result.content[0].text); const hypothesis2Result = await graphService.create({ action: ActionType.CREATE, nodeType: "hypothesis", content: "Component might be rendering before data is loaded", parentId: problem.nodeId, metadata: { confidence: 70, }, }); const _hypothesis2 = JSON.parse(hypothesis2Result.content[0].text); // 3. Create and conduct experiments const experimentResult = await graphService.create({ action: ActionType.CREATE, nodeType: "experiment", content: "Add console.log to check API response structure", parentId: hypothesis1.nodeId, metadata: { code: 'console.log("API Response:", response.data);', }, }); const experiment = JSON.parse(experimentResult.content[0].text); // 4. Record observations const observationResult = await graphService.create({ action: ActionType.CREATE, nodeType: "observation", content: "API returns undefined when user has no data, not an empty object", parentId: experiment.nodeId, }); const observation = JSON.parse(observationResult.content[0].text); // Connect observation supports hypothesis await graphService.connect({ action: ActionType.CONNECT, from: observation.nodeId, to: hypothesis1.nodeId, type: "supports", }); // 5. Extract learning const learningResult = await graphService.create({ action: ActionType.CREATE, nodeType: "learning", content: "Always use optional chaining or default values when accessing API response data", metadata: { confidence: 95, applicability: "All API response handling", }, }); const learning = JSON.parse(learningResult.content[0].text); // Connect observation leads to learning await graphService.connect({ action: ActionType.CONNECT, from: observation.nodeId, to: learning.nodeId, type: "learns", }); // 6. Apply solution const solutionResult = await graphService.create({ action: ActionType.CREATE, nodeType: "solution", content: "Use optional chaining: response?.data || {}", metadata: { code: "const userData = response?.data || {};", verified: true, }, }); const solution = JSON.parse(solutionResult.content[0].text); // Connect solution solves problem await graphService.connect({ action: ActionType.CONNECT, from: solution.nodeId, to: problem.nodeId, type: "solves", }); // 7. Check recent activity const recentResult = await graphService.query({ action: ActionType.QUERY, type: "recent-activity", parameters: { limit: 5, }, }); const recent = JSON.parse(recentResult.content[0].text); expect(recent.success).toBe(true); expect(recent.results.nodes.length).toBeGreaterThan(0); // 最新のノードは solution か learning のいずれか(同じタイミングで作成される可能性があるため) const recentTypes = recent.results.nodes.map((n) => n.type); expect(recentTypes).toContain("solution"); expect(recentTypes).toContain("learning"); // 8. Verify persistence await graphService.saveGraph(); // Create new instance and verify data persists const newGraphService = new GraphService(); await newGraphService.initialize(); const similarResult = await newGraphService.query({ action: ActionType.QUERY, type: "similar-problems", parameters: { pattern: "TypeError property undefined", limit: 5, }, }); const similar = JSON.parse(similarResult.content[0].text); expect(similar.success).toBe(true); expect(similar.results.problems.length).toBeGreaterThan(0); expect(similar.results.problems[0].solutions.length).toBeGreaterThan(0); }); it("should efficiently handle similar problem search", async () => { // Create multiple similar problems with solutions const problems = [ { content: 'TypeError: Cannot read property "id" of null', solution: "Add null check for id", }, { content: 'TypeError: Cannot read property "name" of undefined', solution: "Use optional chaining for name", }, { content: "ReferenceError: user is not defined", solution: "Define user variable" }, { content: 'TypeError: Cannot access property "email" of null', solution: "Add null check for email", }, ]; for (const { content, solution } of problems) { const problemResult = await graphService.create({ action: ActionType.CREATE, nodeType: "problem", content, }); const problem = JSON.parse(problemResult.content[0].text); const solutionResult = await graphService.create({ action: ActionType.CREATE, nodeType: "solution", content: solution, metadata: { verified: true }, }); const sol = JSON.parse(solutionResult.content[0].text); await graphService.connect({ action: ActionType.CONNECT, from: sol.nodeId, to: problem.nodeId, type: "solves", }); } // Search for similar TypeError problems const searchResult = await graphService.query({ action: ActionType.QUERY, type: "similar-problems", parameters: { pattern: "TypeError property", limit: 10, }, }); const search = JSON.parse(searchResult.content[0].text); expect(search.success).toBe(true); expect(search.results.problems.length).toBeGreaterThanOrEqual(3); // Should find at least 3 TypeErrors // Verify that similar problems have solutions const typeErrorProblems = search.results.problems.filter((p) => p.content.includes("TypeError")); expect(typeErrorProblems.length).toBeGreaterThanOrEqual(3); expect(typeErrorProblems.every((p) => p.solutions.length > 0)).toBe(true); }); }); //# sourceMappingURL=debugSession.test.js.map