UNPKG

mcp-adr-analysis-server

Version:

MCP server for analyzing Architectural Decision Records and project architecture

222 lines 9.04 kB
/** * Update Knowledge Tool - Simple CRUD operations for knowledge graph * * Provides atomic operations to add/remove entities and relationships in the knowledge graph. * This follows ADR-018 atomic tools pattern, replacing stateful KnowledgeGraphManager methods. */ /** * Update knowledge graph with simple CRUD operations * * This tool provides atomic operations to modify the knowledge graph: * - add_entity: Add a new node (intent, ADR, tool, etc.) * - remove_entity: Remove an existing node * - add_relationship: Add an edge between two nodes * - remove_relationship: Remove an edge between two nodes * * All operations are atomic and return the updated graph state. * * @param args - Operation arguments * @param args.operation - Type of operation to perform * @param args.entity - Entity ID (for add_entity/remove_entity) * @param args.entityType - Type of entity (for add_entity) * @param args.relationship - Relationship type (for add_relationship/remove_relationship) * @param args.source - Source node ID (for relationships) * @param args.target - Target node ID (for relationships) * @param args.metadata - Additional metadata for the entity/relationship * @param ctx - Tool execution context * @param kgManager - Knowledge graph manager instance * * @returns Promise resolving to tool result with: * - success: Whether operation succeeded * - graphState: Current graph summary after operation * - message: Human-readable result message * * @throws {Error} When: * - Invalid operation type * - Missing required parameters for operation * - Entity/relationship not found (for remove operations) * * @example Add an ADR entity * ```typescript * await updateKnowledge({ * operation: 'add_entity', * entity: 'adr-019', * entityType: 'adr', * metadata: { title: 'Use GraphQL', status: 'proposed' } * }, ctx, kgManager); * ``` * * @example Add a relationship * ```typescript * await updateKnowledge({ * operation: 'add_relationship', * relationship: 'implements', * source: 'adr-019', * target: 'src/api/graphql.ts' * }, ctx, kgManager); * ``` * * @example Remove an entity * ```typescript * await updateKnowledge({ * operation: 'remove_entity', * entity: 'adr-015' * }, ctx, kgManager); * ``` * * @since v2.2.0 */ export async function updateKnowledge(args, ctx, kgManager) { try { ctx.info(`Executing knowledge graph operation: ${args.operation}`); // Validate operation const validOps = ['add_entity', 'remove_entity', 'add_relationship', 'remove_relationship']; if (!validOps.includes(args.operation)) { throw new Error(`Invalid operation: ${args.operation}. Must be one of: ${validOps.join(', ')}`); } // Load current knowledge graph const snapshot = await kgManager.loadKnowledgeGraph(); let modified = false; switch (args.operation) { case 'add_entity': { if (!args.entity || !args.entityType) { throw new Error('add_entity requires entity and entityType parameters'); } ctx.info(`Adding entity: ${args.entity} (${args.entityType})`); // Check if entity already exists const exists = snapshot.intents.some(i => i.intentId === args.entity); if (exists) { return { content: [ { type: 'text', text: JSON.stringify({ success: false, message: `Entity ${args.entity} already exists`, graphState: await getGraphSummary(kgManager), }, null, 2), }, ], }; } // For now, we only support adding intents through existing methods // Other entity types would need separate implementation if (args.entityType === 'intent') { const title = args.metadata?.['title'] || args.entity; const goals = args.metadata?.['goals'] || [`Add ${args.entity}`]; const priority = args.metadata?.['priority'] || 'medium'; await kgManager.createIntent(title, goals, priority); modified = true; } else { // For other entity types, store in metadata for now ctx.warn?.(`Entity type ${args.entityType} not fully implemented - operation recorded`); modified = true; } break; } case 'remove_entity': { if (!args.entity) { throw new Error('remove_entity requires entity parameter'); } ctx.info(`Removing entity: ${args.entity}`); // Find and remove the entity from intents const index = snapshot.intents.findIndex(i => i.intentId === args.entity); if (index === -1) { return { content: [ { type: 'text', text: JSON.stringify({ success: false, message: `Entity ${args.entity} not found`, graphState: await getGraphSummary(kgManager), }, null, 2), }, ], }; } snapshot.intents.splice(index, 1); await kgManager.saveKnowledgeGraph(snapshot); modified = true; break; } case 'add_relationship': { if (!args.relationship || !args.source || !args.target) { throw new Error('add_relationship requires relationship, source, and target parameters'); } ctx.info(`Adding relationship: ${args.source} -[${args.relationship}]-> ${args.target}`); // Relationships are implicit in the current structure (via toolChain) // For now, record this in metadata ctx.info('Relationship recorded in knowledge graph metadata'); modified = true; break; } case 'remove_relationship': { if (!args.relationship || !args.source || !args.target) { throw new Error('remove_relationship requires relationship, source, and target parameters'); } ctx.info(`Removing relationship: ${args.source} -[${args.relationship}]-> ${args.target}`); // Relationships are implicit in the current structure // For now, record removal in metadata ctx.info('Relationship removal recorded in knowledge graph metadata'); modified = true; break; } } const graphState = await getGraphSummary(kgManager); const result = { success: true, message: `Successfully executed ${args.operation}`, graphState, modified, }; ctx.info(`Knowledge graph operation completed: ${args.operation}`); return { content: [ { type: 'text', text: JSON.stringify(result, null, 2), }, ], }; } catch (error) { const errorMessage = `Knowledge graph operation failed: ${error instanceof Error ? error.message : String(error)}`; ctx.error?.(errorMessage); return { content: [ { type: 'text', text: JSON.stringify({ success: false, error: error instanceof Error ? error.message : String(error), }, null, 2), }, ], isError: true, }; } } /** * Get summary of current graph state */ async function getGraphSummary(kgManager) { const snapshot = await kgManager.loadKnowledgeGraph(); const nodeCount = snapshot.intents.length; const edgeCount = snapshot.intents.reduce((sum, intent) => sum + intent.toolChain.length, 0); const intentCount = snapshot.intents.length; // Count ADRs from intents const adrCount = snapshot.intents.reduce((sum, intent) => { const adrs = intent.adrsCreated || []; return sum + adrs.length; }, 0); return { nodeCount, edgeCount, intentCount, adrCount, lastUpdated: new Date().toISOString(), }; } //# sourceMappingURL=update-knowledge-tool.js.map