Skip to main content
Glama

meMCP - Memory-Enhanced Model Context Protocol

MIT License
23
2
MemoryOperations.js9.53 kB
export class MemoryOperations { constructor(factStore, qualityScorer) { this.factStore = factStore; this.qualityScorer = qualityScorer; } registerTools(server) { this.registerStoreInsightTool(server); this.registerUpdateFactTool(server); this.registerDeleteFactTool(server); this.registerGetStatsTool(server); this.registerGetRelatedTool(server); } registerStoreInsightTool(server) { server.registerTool( 'memory_store_insight', 'Store a new insight, pattern, or piece of knowledge in the memory system', { type: 'object', properties: { content: { type: 'string', description: 'The insight or knowledge content to store', }, type: { type: 'string', description: 'The type of fact (verified_pattern, anti_pattern, optimization, etc.)', enum: [ 'verified_pattern', 'anti_pattern', 'optimization', 'discovery', 'constraint', 'debugging_solution', 'tool_configuration', 'decision_rationale', 'experimental_approach', 'workflow_improvement', 'security_concern', ], }, domain: { type: 'string', description: 'The domain or area this applies to (e.g., web_development, data_science)', }, tags: { type: 'array', items: { type: 'string' }, description: 'Tags to categorize this insight', }, context: { type: 'object', description: 'Additional context about the technology, framework, or situation', }, }, required: ['content'], }, async (args) => { return await this.handleStoreInsight(args); } ); } registerUpdateFactTool(server) { server.registerTool( 'memory_update_fact', 'Update an existing fact in the memory system', { type: 'object', properties: { factId: { type: 'string', description: 'The ID of the fact to update', }, updates: { type: 'object', description: 'The updates to apply to the fact', }, }, required: ['factId', 'updates'], }, async (args) => { return await this.handleUpdateFact(args); } ); } registerDeleteFactTool(server) { server.registerTool( 'memory_delete_fact', 'Delete a fact from the memory system', { type: 'object', properties: { factId: { type: 'string', description: 'The ID of the fact to delete', }, }, required: ['factId'], }, async (args) => { return await this.handleDeleteFact(args); } ); } registerGetStatsTool(server) { server.registerTool( 'memory_get_stats', 'Get statistics about the memory system', { type: 'object', properties: {}, }, async (args) => { return await this.handleGetStats(args); } ); } registerGetRelatedTool(server) { server.registerTool( 'memory_get_related', 'Get facts related to a specific fact', { type: 'object', properties: { factId: { type: 'string', description: 'The ID of the fact to find related facts for', }, maxDepth: { type: 'number', description: 'Maximum relationship depth to traverse', default: 2, }, }, required: ['factId'], }, async (args) => { return await this.handleGetRelated(args); } ); } async handleStoreInsight(args) { try { const { content, type, domain, tags = [], context = {} } = args; if (!content || content.trim().length === 0) { throw new Error('Content is required and cannot be empty'); } const fact = { content: content.trim(), type, domain, tags, context, metadata: { source: 'manual_input', addedAt: new Date().toISOString(), }, }; const storedFact = await this.factStore.storeFact(fact); const qualityResult = this.qualityScorer.calculateQualityScore(storedFact); return { content: [ { type: 'text', text: `✅ Insight stored successfully!\n\n**ID:** ${storedFact.id}\n**Type:** ${storedFact.type}\n**Quality Score:** ${qualityResult.totalScore}/100\n**Domain:** ${storedFact.domain || 'general'}\n\n**Content:** ${storedFact.content}`, }, ], }; } catch (error) { return { content: [ { type: 'text', text: `Error storing insight: ${error.message}`, }, ], isError: true, }; } } async handleUpdateFact(args) { try { const { factId, updates } = args; const updatedFact = await this.factStore.updateFact(factId, updates); return { content: [ { type: 'text', text: `✅ Fact updated successfully!\n\n**ID:** ${updatedFact.id}\n**Updated:** ${updatedFact.updatedAt}\n\n**Content:** ${updatedFact.content}`, }, ], }; } catch (error) { return { content: [ { type: 'text', text: `Error updating fact: ${error.message}`, }, ], isError: true, }; } } async handleDeleteFact(args) { try { const { factId } = args; await this.factStore.deleteFact(factId); return { content: [ { type: 'text', text: `✅ Fact ${factId} deleted successfully.`, }, ], }; } catch (error) { return { content: [ { type: 'text', text: `Error deleting fact: ${error.message}`, }, ], isError: true, }; } } async handleGetStats(args) { try { const stats = await this.factStore.getStats(); let response = `📊 **Memory System Statistics**\n\n`; response += `**Total Facts:** ${stats.totalFacts}\n`; response += `**Average Quality:** ${stats.averageQualityScore}/100\n\n`; if (Object.keys(stats.factsByType).length > 0) { response += `**Facts by Type:**\n`; for (const [type, count] of Object.entries(stats.factsByType)) { response += `- ${type.replace('_', ' ')}: ${count}\n`; } response += `\n`; } if (Object.keys(stats.factsByDomain).length > 0) { response += `**Facts by Domain:**\n`; for (const [domain, count] of Object.entries(stats.factsByDomain)) { response += `- ${domain}: ${count}\n`; } } return { content: [ { type: 'text', text: response.trim(), }, ], }; } catch (error) { return { content: [ { type: 'text', text: `Error getting stats: ${error.message}`, }, ], isError: true, }; } } async handleGetRelated(args) { try { const { factId, maxDepth = 2 } = args; const related = await this.factStore.getRelatedFacts(factId, maxDepth); if (related.length === 0) { return { content: [ { type: 'text', text: `No related facts found for ${factId}`, }, ], }; } let response = `🔗 **Related Facts for ${factId}:**\n\n`; for (const item of related) { response += `**${item.relationship}** (depth ${item.depth})\n`; response += `${item.fact.type}: ${item.fact.content.substring(0, 100)}...\n\n`; } return { content: [ { type: 'text', text: response.trim(), }, ], }; } catch (error) { return { content: [ { type: 'text', text: `Error getting related facts: ${error.message}`, }, ], isError: true, }; } } async storeInsight(insight) { try { const scoreResult = this.qualityScorer.calculateQualityScore(insight); const qualityScore = scoreResult.totalScore; const fact = { id: `fact_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`, content: insight.content, type: insight.type || 'discovery', domain: insight.domain || 'general', tags: insight.tags || [], context: insight.context || {}, qualityScore, timestamp: new Date().toISOString(), accessCount: 0, lastAccessed: new Date().toISOString(), }; await this.factStore.storeFact(fact); return { success: true, factId: fact.id, qualityScore: fact.qualityScore, message: `Insight stored with quality score ${qualityScore}/100`, ...fact, }; } catch (error) { throw new Error(`Failed to store insight: ${error.message}`); } } }

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/mixelpixx/meMCP'

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