Skip to main content
Glama
sascodiego

MCP Vibe Coding Knowledge Graph

by sascodiego
knowledgeGraph.js8.65 kB
import { logger } from '../utils/logger.js'; export class KnowledgeGraphHandler { constructor(server) { this.server = server; this.kuzu = server.kuzu; } async defineDomainOntology(args) { const { entities, relationships, businessRules = [], codingStandards = {} } = args; try { const results = { entitiesCreated: 0, relationshipsCreated: 0, rulesCreated: 0, standardsCreated: 0 }; // Create entities for (const entity of entities) { await this.createEntity(entity); results.entitiesCreated++; } // Create relationships if (relationships) { for (const relationship of relationships) { await this.createRelationship(relationship); results.relationshipsCreated++; } } // Create business rules for (const rule of businessRules) { await this.createBusinessRule(rule); results.rulesCreated++; } // Create coding standards for (const [name, value] of Object.entries(codingStandards)) { await this.createCodingStandard(name, value); results.standardsCreated++; } return { content: [ { type: 'text', text: JSON.stringify({ message: 'Domain ontology defined successfully', results, timestamp: new Date().toISOString() }, null, 2) } ] }; } catch (error) { logger.error('Error defining domain ontology:', error); throw error; } } async updateFromCode(args) { const { codeAnalysis, decisions = [], learnedPatterns = [] } = args; try { const results = { entitiesUpdated: 0, decisionsRecorded: 0, patternsLearned: 0 }; // Update entities from code analysis if (codeAnalysis.entities) { for (const entity of codeAnalysis.entities) { await this.updateCodeEntity(entity); results.entitiesUpdated++; } } // Record architectural decisions for (const decision of decisions) { await this.recordDecision(decision); results.decisionsRecorded++; } // Learn new patterns for (const pattern of learnedPatterns) { await this.learnPattern(pattern); results.patternsLearned++; } return { content: [ { type: 'text', text: JSON.stringify({ message: 'Knowledge graph updated from code analysis', results, timestamp: new Date().toISOString() }, null, 2) } ] }; } catch (error) { logger.error('Error updating KG from code:', error); throw error; } } async createEntity(entity) { const { type, name, properties = {}, labels = [] } = entity; const nodeProperties = { id: this.generateEntityId(type, name), type, name, createdAt: new Date().toISOString(), ...properties }; const allLabels = ['DomainEntity', type, ...labels].filter(Boolean); const labelString = allLabels.map(l => `:${l}`).join(''); const query = ` MERGE (e${labelString} {id: $id}) SET e += $properties RETURN e `; await this.kuzu.query(query, { id: nodeProperties.id, properties: nodeProperties }); logger.info(`Created entity: ${type}:${name}`); } async createRelationship(relationship) { const { from, to, type, properties = {} } = relationship; const query = ` MATCH (a {id: $fromId}), (b {id: $toId}) MERGE (a)-[r:${type}]->(b) SET r += $properties RETURN r `; await this.kuzu.query(query, { fromId: from, toId: to, properties: { createdAt: new Date().toISOString(), ...properties } }); logger.info(`Created relationship: ${from} -[${type}]-> ${to}`); } async createBusinessRule(rule) { const ruleId = this.generateRuleId(rule); const nodeProperties = { id: ruleId, description: rule.description || rule, type: rule.type || 'business', severity: rule.severity || 'medium', domain: rule.domain || 'general', createdAt: new Date().toISOString() }; await this.kuzu.createNode('Rule', nodeProperties); logger.info(`Created business rule: ${ruleId}`); } async createCodingStandard(name, value) { const standardProperties = { id: `standard:${name}`, name, value: typeof value === 'string' ? value : JSON.stringify(value), type: this.inferStandardType(name), createdAt: new Date().toISOString() }; await this.kuzu.createNode('Standard', standardProperties); logger.info(`Created coding standard: ${name}`); } async updateCodeEntity(entity) { const { id, filePath, type, name, properties = {} } = entity; const nodeProperties = { id: id || `${filePath}:${name}`, filePath, type, name, lastAnalyzed: new Date().toISOString(), ...properties }; const query = ` MERGE (e:CodeEntity {id: $id}) SET e += $properties RETURN e `; await this.kuzu.query(query, { id: nodeProperties.id, properties: nodeProperties }); } async recordDecision(decision) { const { title, description, context, alternatives = [], chosen, rationale } = decision; const decisionProperties = { id: this.generateDecisionId(title), title, description, context, alternatives: JSON.stringify(alternatives), chosen, rationale, decidedAt: new Date().toISOString() }; await this.kuzu.createNode('ArchitecturalDecision', decisionProperties); // Link to related entities if context includes entity references if (context && context.entities) { for (const entityId of context.entities) { await this.kuzu.createRelationship( decisionProperties.id, 'AFFECTS', entityId, { impact: context.impact || 'medium' } ); } } } async learnPattern(pattern) { const { name, description, implementation, examples = [], category } = pattern; const patternProperties = { id: `pattern:${name}`, name, description, implementation: typeof implementation === 'string' ? implementation : JSON.stringify(implementation), category: category || 'learned', confidence: pattern.confidence || 0.8, learnedAt: new Date().toISOString() }; const query = ` MERGE (p:Pattern {id: $id}) SET p += $properties RETURN p `; await this.kuzu.query(query, { id: patternProperties.id, properties: patternProperties }); // Link pattern to examples for (const example of examples) { if (example.entityId) { await this.kuzu.createRelationship( example.entityId, 'IMPLEMENTS', patternProperties.id, { quality: example.quality || 'good' } ); } } } generateEntityId(type, name) { return `${type}:${name}`.toLowerCase().replace(/[^a-z0-9:]/g, '_'); } generateRuleId(rule) { const description = rule.description || rule; const hash = this.simpleHash(description); return `rule:${hash}`; } generateDecisionId(title) { const hash = this.simpleHash(title); return `decision:${hash}`; } inferStandardType(name) { const nameLower = name.toLowerCase(); if (nameLower.includes('naming') || nameLower.includes('name')) return 'naming'; if (nameLower.includes('format') || nameLower.includes('style')) return 'formatting'; if (nameLower.includes('structure') || nameLower.includes('architecture')) return 'architectural'; if (nameLower.includes('test') || nameLower.includes('spec')) return 'testing'; return 'general'; } simpleHash(str) { let hash = 0; for (let i = 0; i < str.length; i++) { const char = str.charCodeAt(i); hash = ((hash << 5) - hash) + char; hash = hash & hash; // Convert to 32-bit integer } return Math.abs(hash).toString(36); } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/sascodiego/KGsMCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server