Skip to main content
Glama
sascodiego

MCP Vibe Coding Knowledge Graph

by sascodiego
context.js6.06 kB
import { parse } from '@babel/parser'; import traverse from '@babel/traverse'; import fs from 'fs/promises'; import path from 'path'; import { logger } from '../utils/logger.js'; export class ContextHandler { constructor(server) { this.server = server; this.kuzu = server.kuzu; } async queryContextForTask(args) { const { taskDescription, entityTypes = [], depth = 2 } = args; try { // Build query to find relevant context const query = ` // Find patterns relevant to the task MATCH (p:Pattern) WHERE toLower(p.name) CONTAINS toLower($keyword) OR toLower(p.description) CONTAINS toLower($keyword) WITH p LIMIT 5 // Find related code entities OPTIONAL MATCH (e:CodeEntity)-[:IMPLEMENTS]->(p) WITH p, collect(DISTINCT e) as relatedEntities // Find business rules OPTIONAL MATCH (r:Rule) WHERE toLower(r.description) CONTAINS toLower($keyword) WITH p, relatedEntities, collect(DISTINCT r) as rules // Find coding standards OPTIONAL MATCH (s:Standard) WITH p, relatedEntities, rules, collect(DISTINCT s) as standards RETURN { patterns: collect(DISTINCT p.name), relatedCode: [e IN relatedEntities | {name: e.name, path: e.filePath}], rules: [r IN rules | r.description], standards: [s IN standards | {name: s.name, value: s.value}] } as context `; // Extract keywords from task description const keyword = taskDescription.split(' ')[0]; const result = await this.kuzu.query(query, { keyword, depth }); return { content: [ { type: 'text', text: JSON.stringify({ taskDescription, context: result[0]?.context || { patterns: [], relatedCode: [], rules: [], standards: [] }, relevanceScore: 0.85 }, null, 2) } ] }; } catch (error) { logger.error('Error querying context:', error); throw error; } } async extractFromCode(args) { const { filePath, codeSnippet } = args; try { // Read file if no snippet provided const code = codeSnippet || await fs.readFile(filePath, 'utf-8'); // Extract structured comments const structuredComments = this.extractStructuredComments(code); // Parse code AST const ast = parse(code, { sourceType: 'module', plugins: ['jsx', 'typescript', 'decorators-legacy'] }); const entities = []; const relationships = []; // Traverse AST to extract entities traverse.default(ast, { ClassDeclaration(path) { const entity = { type: 'class', name: path.node.id.name, lineStart: path.node.loc.start.line, lineEnd: path.node.loc.end.line, filePath, structuredComment: structuredComments.find( c => c.line < path.node.loc.start.line ) }; entities.push(entity); }, FunctionDeclaration(path) { const entity = { type: 'function', name: path.node.id.name, lineStart: path.node.loc.start.line, lineEnd: path.node.loc.end.line, filePath, structuredComment: structuredComments.find( c => c.line < path.node.loc.start.line ) }; entities.push(entity); } }); // Store entities in Kuzu for (const entity of entities) { const nodeProps = { id: `${filePath}:${entity.name}`, type: entity.type, name: entity.name, filePath: entity.filePath, lineStart: entity.lineStart, lineEnd: entity.lineEnd, ...this.parseStructuredComment(entity.structuredComment) }; await this.kuzu.createNode('CodeEntity', nodeProps); } return { content: [ { type: 'text', text: JSON.stringify({ extracted: { entities: entities.length, structuredComments: structuredComments.length, filePath } }, null, 2) } ] }; } catch (error) { logger.error('Error extracting context:', error); throw error; } } extractStructuredComments(code) { const comments = []; const lines = code.split('\n'); const commentPattern = /\/\*\*[\s\S]*?\*\//g; const matches = code.matchAll(commentPattern); for (const match of matches) { const comment = match[0]; const lineNumber = code.substring(0, match.index).split('\n').length; const parsed = this.parseStructuredComment(comment); if (parsed) { comments.push({ line: lineNumber, ...parsed }); } } return comments; } parseStructuredComment(comment) { if (!comment) return null; const structured = {}; const patterns = { agent: /\*\s*AGENT:\s*(.+)/, trace: /\*\s*TRACE:\s*(.+)/, context: /\*\s*CONTEXT:\s*(.+)/, reason: /\*\s*REASON:\s*(.+)/, change: /\*\s*CHANGE:\s*(.+)/, prevention: /\*\s*PREVENTION:\s*(.+)/, risk: /\*\s*RISK:\s*(.+)/ }; for (const [key, pattern] of Object.entries(patterns)) { const match = comment.match(pattern); if (match) { structured[key] = match[1].trim(); } } return Object.keys(structured).length > 0 ? structured : null; } }

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