Skip to main content
Glama

mem0 Memory System

#!/usr/bin/env node /** * MCP server for interacting with Mem0.ai memory storage. * Provides tools to add and search memories. * * Supports two modes: * 1. Cloud mode: Uses Mem0's hosted API with MEM0_API_KEY * 2. Local mode: Uses in-memory storage with OPENAI_API_KEY for embeddings */ // Complete console logging suppression for MCP protocol compatibility // This ensures no library logs interfere with the MCP communication protocol const noOp = () => {}; console.log = noOp; console.error = noOp; console.warn = noOp; console.info = noOp; console.debug = noOp; console.trace = noOp; // Environment variables to disable logging in various libraries process.env.DEBUG = ''; process.env.NODE_DEBUG = ''; process.env.DEBUG_COLORS = 'no'; process.env.NODE_ENV = process.env.NODE_ENV || 'production'; process.env.LOG_LEVEL = 'silent'; process.env.SILENT = 'true'; process.env.QUIET = 'true'; process.env.MEM0_TELEMETRY = 'false'; process.env.DISABLE_LOGGING = 'true'; process.env.NO_COLOR = 'true'; import { Server } from "@modelcontextprotocol/sdk/server/index.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { CallToolRequestSchema, ListToolsRequestSchema, McpError, ErrorCode, } from "@modelcontextprotocol/sdk/types.js"; import type { Memory as MemoryType } from "mem0ai/oss"; // Load Mem0 library after configuring environment to avoid unwanted telemetry let Memory: typeof import("mem0ai/oss").Memory; // Using dynamic import for cloud API to avoid TypeScript issues let MemoryClient: any = null; // Initialize Memory synchronously to avoid race conditions let memoryInitialized = false; async function initializeMemory() { if (memoryInitialized) return; try { const mod = await import("mem0ai/oss"); Memory = mod.Memory; memoryInitialized = true; } catch (error) { // Silent failure - let the constructor handle missing dependencies } } // Type for the arguments received by the MCP tool handlers interface Mem0AddToolArgs { content: string; userId?: string; sessionId?: string; // This maps to run_id in Mem0 API agentId?: string; // The LLM/agent making the tool call appId?: string; // Application identifier (legacy parameter) projectId?: string; // Project identifier (for mem0 Pro plan project organization) orgId?: string; // Organization identifier (for mem0 organization-level management) metadata?: any; // Advanced Mem0 API parameters includes?: string; excludes?: string; infer?: boolean; outputFormat?: string; customCategories?: any; customInstructions?: string; immutable?: boolean; expirationDate?: string; } interface Mem0SearchToolArgs { query: string; userId?: string; sessionId?: string; // This maps to run_id in Mem0 API agentId?: string; // The LLM/agent making the tool call appId?: string; // Application identifier (legacy parameter) projectId?: string; // Project identifier (for mem0 Pro plan project organization) orgId?: string; // Organization identifier (for mem0 organization-level management) filters?: any; threshold?: number; // Advanced Mem0 API search parameters topK?: number; fields?: string[]; rerank?: boolean; keywordSearch?: boolean; filterMemories?: boolean; } interface Mem0DeleteToolArgs { memoryId: string; userId?: string; agentId?: string; // The LLM/agent making the tool call appId?: string; // Application identifier (legacy parameter) projectId?: string; // Project identifier (for mem0 Pro plan project organization) orgId?: string; // Organization identifier (for mem0 organization-level management) } // Message type for Mem0 API type Mem0Message = { role: "user" | "assistant" | "system"; content: string; }; class Mem0MCPServer { private server: Server; private isCloudMode: boolean = false; private isSupabaseMode: boolean = false; private localClient?: MemoryType; private cloudClient?: any; private supabaseClient?: MemoryType; private isReady: boolean = false; constructor() { // Initialize MCP Server this.server = new Server( { // These should match package.json name: "@pinkpixel/mem0-mcp", version: "0.6.4", }, { capabilities: { // Only tools capability needed for now tools: {}, }, } ); this.setupToolHandlers(); // Initialize clients asynchronously but don't block constructor this.initializeClients(); process.on('SIGINT', async () => { await this.server.close(); process.exit(0); }); process.on('SIGTERM', async () => { await this.server.close(); process.exit(0); }); // Cleanup on uncaught exceptions process.on('uncaughtException', (error) => { process.exit(1); }); } private async initializeClients(): Promise<void> { // Check for environment variables const mem0ApiKey = process.env.MEM0_API_KEY; const supabaseUrl = process.env.SUPABASE_URL; const supabaseKey = process.env.SUPABASE_KEY; const openaiApiKey = process.env.OPENAI_API_KEY; // Ensure Memory is initialized await initializeMemory(); // Determine the mode based on available keys (priority: Cloud > Supabase > Local) if (mem0ApiKey) { this.isCloudMode = true; // Dynamic import for cloud client try { const module = await import('mem0ai'); MemoryClient = module.default; const clientOptions: any = { apiKey: mem0ApiKey, debug: false, verbose: false, silent: true }; this.cloudClient = new MemoryClient(clientOptions); this.isReady = true; } catch (error) { process.exit(1); } } else if (supabaseUrl && supabaseKey) { this.isSupabaseMode = true; try { // Initialize Supabase client with vector store and history store const supabaseConfig = { vectorStore: { provider: "supabase", config: { collectionName: "memories", embeddingModelDims: 1536, supabaseUrl: supabaseUrl, supabaseKey: supabaseKey, tableName: "memories", }, }, historyStore: { provider: 'supabase', config: { supabaseUrl: supabaseUrl, supabaseKey: supabaseKey, tableName: 'memory_history', }, }, // Embedder configuration for OpenAI embedder: { provider: 'openai', config: { apiKey: process.env.OPENAI_API_KEY, model: 'text-embedding-3-small', }, }, }; this.supabaseClient = new Memory(supabaseConfig); this.isReady = true; } catch (error) { process.exit(1); } } else if (openaiApiKey) { this.isCloudMode = false; try { // Initialize with silent options if available this.localClient = new Memory({ vectorStore: { provider: "memory", config: { collectionName: "mem0_default_collection" } } }); this.isReady = true; } catch (error) { process.exit(1); } } else { process.exit(1); } } /** * Sets up handlers for MCP tool-related requests. */ private setupToolHandlers(): void { // Handler for listing available tools this.server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ { name: "add_memory", description: "Stores a piece of text as a memory in Mem0.", inputSchema: { type: "object", properties: { content: { type: "string", description: "The text content to store as memory.", }, userId: { type: "string", description: "User ID to associate with the memory. If not provided, uses DEFAULT_USER_ID environment variable.", }, sessionId: { type: "string", description: "Optional session ID to associate with the memory.", }, agentId: { type: "string", description: "Optional agent ID - identifies the LLM/agent making the tool call. If not provided, uses DEFAULT_AGENT_ID environment variable.", }, appId: { type: "string", description: "Optional app ID - application identifier (legacy parameter). If not provided, uses DEFAULT_APP_ID environment variable.", }, projectId: { type: "string", description: "Optional project ID - for mem0 Pro plan project organization (e.g., proj_ABC123). If not provided, uses DEFAULT_PROJECT_ID environment variable.", }, orgId: { type: "string", description: "Optional organization ID - for mem0 organization-level management. If not provided, uses DEFAULT_ORG_ID environment variable.", }, metadata: { type: "object", description: "Optional key-value metadata.", }, includes: { type: "string", description: "Optional specific preferences to include in the memory (for cloud API).", }, excludes: { type: "string", description: "Optional specific preferences to exclude from the memory (for cloud API).", }, infer: { type: "boolean", description: "Optional whether to infer memories or directly store messages (default: true, for cloud API).", }, outputFormat: { type: "string", description: "Optional format version, either v1.0 (deprecated) or v1.1 (recommended, for cloud API).", }, customCategories: { type: "object", description: "Optional list of categories with names and descriptions (for cloud API).", }, customInstructions: { type: "string", description: "Optional project-specific guidelines for handling and organizing memories (for cloud API).", }, immutable: { type: "boolean", description: "Optional whether the memory is immutable (default: false, for cloud API).", }, expirationDate: { type: "string", description: "Optional when the memory will expire (format: YYYY-MM-DD, for cloud API).", }, }, required: ["content"], }, }, { name: "search_memory", description: "Searches stored memories in Mem0 based on a query.", inputSchema: { type: "object", properties: { query: { type: "string", description: "The search query.", }, userId: { type: "string", description: "User ID to filter search. If not provided, uses DEFAULT_USER_ID environment variable.", }, sessionId: { type: "string", description: "Optional session ID to filter search.", }, agentId: { type: "string", description: "Optional agent ID - identifies the LLM/agent making the tool call. If not provided, uses DEFAULT_AGENT_ID environment variable.", }, appId: { type: "string", description: "Optional app ID - application identifier (legacy parameter). If not provided, uses DEFAULT_APP_ID environment variable.", }, projectId: { type: "string", description: "Optional project ID - for mem0 Pro plan project organization (e.g., proj_ABC123). If not provided, uses DEFAULT_PROJECT_ID environment variable.", }, orgId: { type: "string", description: "Optional organization ID - for mem0 organization-level management. If not provided, uses DEFAULT_ORG_ID environment variable.", }, filters: { type: "object", description: "Optional key-value filters for metadata.", }, threshold: { type: "number", description: "Optional similarity threshold for results (for cloud API).", }, topK: { type: "number", description: "Optional number of top results to return (default: 10, for cloud API).", }, fields: { type: "array", items: { type: "string" }, description: "Optional specific fields to include in the response (for cloud API).", }, rerank: { type: "boolean", description: "Optional whether to rerank the memories (default: false, for cloud API).", }, keywordSearch: { type: "boolean", description: "Optional whether to search based on keywords (default: false, for cloud API).", }, filterMemories: { type: "boolean", description: "Optional whether to filter the memories (default: false, for cloud API).", }, }, required: ["query"], }, }, { name: "delete_memory", description: "Deletes a specific memory by ID from Mem0.", inputSchema: { type: "object", properties: { memoryId: { type: "string", description: "The unique ID of the memory to delete.", }, userId: { type: "string", description: "User ID associated with the memory. If not provided, uses DEFAULT_USER_ID environment variable.", }, agentId: { type: "string", description: "Optional agent ID - identifies the LLM/agent making the tool call. If not provided, uses DEFAULT_AGENT_ID environment variable.", }, appId: { type: "string", description: "Optional app ID - application identifier (legacy parameter). If not provided, uses DEFAULT_APP_ID environment variable.", }, projectId: { type: "string", description: "Optional project ID - for mem0 Pro plan project organization (e.g., proj_ABC123). If not provided, uses DEFAULT_PROJECT_ID environment variable.", }, orgId: { type: "string", description: "Optional organization ID - for mem0 organization-level management. If not provided, uses DEFAULT_ORG_ID environment variable.", }, }, required: ["memoryId"], }, }, ], }; }); // Handler for call tool requests this.server.setRequestHandler(CallToolRequestSchema, async (request) => { if (!this.isReady) { throw new McpError(ErrorCode.InternalError, "Memory client is still initializing. Please try again in a moment."); } try { const { name } = request.params; const args = request.params.arguments || {}; if (name === "add_memory") { const toolArgs = args as unknown as Mem0AddToolArgs; return await this.handleAddMemory(toolArgs); } else if (name === "search_memory") { const toolArgs = args as unknown as Mem0SearchToolArgs; return await this.handleSearchMemory(toolArgs); } else if (name === "delete_memory") { const toolArgs = args as unknown as Mem0DeleteToolArgs; return await this.handleDeleteMemory(toolArgs); } else { throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${name}`); } } catch (error: any) { if (error instanceof McpError) { throw error; } throw new McpError(ErrorCode.InternalError, `Error executing tool: ${error.message || 'Unknown error'}`); } }); } /** * Handles adding a memory using either local or cloud client. */ private async handleAddMemory(args: Mem0AddToolArgs): Promise<any> { const { content, userId, sessionId, agentId, appId, projectId, orgId, metadata, includes, excludes, infer, outputFormat, customCategories, customInstructions, immutable, expirationDate } = args; if (!content) { throw new McpError(ErrorCode.InvalidParams, "Missing required argument: content"); } // Use DEFAULT_USER_ID as fallback if userId is not provided const finalUserId = userId || process.env.DEFAULT_USER_ID; if (!finalUserId) { throw new McpError(ErrorCode.InvalidParams, "Missing required argument: userId (and no DEFAULT_USER_ID environment variable set)"); } if (this.isCloudMode && this.cloudClient) { try { // Get all parameters - parameter takes precedence over environment const finalAppId = appId || process.env.DEFAULT_APP_ID; const finalAgentId = agentId || process.env.DEFAULT_AGENT_ID; const finalProjectId = projectId || process.env.DEFAULT_PROJECT_ID; const finalOrgId = orgId || process.env.DEFAULT_ORG_ID; // Format message for the cloud API const messages: Mem0Message[] = [{ role: "user", content }]; // Cloud API options - using snake_case for API parameters // Note: Mem0 docs recommend version="v2" for add operations (v1 is deprecated) const options: any = { user_id: finalUserId, version: "v2" }; // Add all parameters if available (using snake_case for API) if (finalAppId) options.app_id = finalAppId; if (finalAgentId) options.agent_id = finalAgentId; if (finalProjectId) options.project_id = finalProjectId; if (finalOrgId) options.org_id = finalOrgId; // Map sessionId to run_id (using snake_case) if (sessionId) options.run_id = sessionId; if (metadata) options.metadata = metadata; // Add advanced Mem0 API parameters (using snake_case) if (includes) options.includes = includes; if (excludes) options.excludes = excludes; if (infer !== undefined) options.infer = infer; if (outputFormat) options.output_format = outputFormat; if (customCategories) options.custom_categories = customCategories; if (customInstructions) options.custom_instructions = customInstructions; if (immutable !== undefined) options.immutable = immutable; if (expirationDate) options.expiration_date = expirationDate; // API call - try direct REST API approach first for better parameter support let result; let usedDirectAPI = false; // Always try direct REST API first when app_id or run_id are provided if (finalAppId || sessionId) { try { const apiUrl = 'https://api.mem0.ai/v1/memories/'; const requestBody = { messages: messages, ...options }; const response = await fetch(apiUrl, { method: 'POST', headers: { 'Authorization': `Token ${process.env.MEM0_API_KEY}`, 'Content-Type': 'application/json' }, body: JSON.stringify(requestBody) }); if (!response.ok) { const errorText = await response.text(); throw new Error(`Direct API call failed: ${response.status} ${response.statusText} - ${errorText}`); } result = await response.json(); usedDirectAPI = true; } catch (directError: any) { // Fall through to SDK attempt } } // Try SDK if direct API wasn't used or failed if (!usedDirectAPI) { try { result = await this.cloudClient.add(messages, options); } catch (sdkError: any) { throw sdkError; } } return { content: [{ type: "text", text: `Memory added successfully. Result: ${JSON.stringify(result)}` }], }; } catch (error: any) { throw new McpError(ErrorCode.InternalError, `Error adding memory: ${error.message}`); } } else if (this.isSupabaseMode && this.supabaseClient) { try { // Format message for the Supabase storage API const messages: Mem0Message[] = [{ role: "user", content }]; // Supabase storage options - using camelCase for local SDK const options: any = { userId: finalUserId, sessionId, metadata }; // Add all parameters if available const finalAppId = appId || process.env.DEFAULT_APP_ID; const finalAgentId = agentId || process.env.DEFAULT_AGENT_ID; const finalProjectId = projectId || process.env.DEFAULT_PROJECT_ID; const finalOrgId = orgId || process.env.DEFAULT_ORG_ID; if (finalAppId) options.appId = finalAppId; if (finalAgentId) options.agentId = finalAgentId; if (finalProjectId) options.projectId = finalProjectId; if (finalOrgId) options.orgId = finalOrgId; // API call const result = await this.supabaseClient.add(messages, options); return { content: [{ type: "text", text: `Memory added successfully. Result: ${JSON.stringify(result)}` }], }; } catch (error: any) { throw new McpError(ErrorCode.InternalError, `Error adding memory: ${error.message}`); } } else if (this.localClient) { try { // Format message for the local storage API const messages: Mem0Message[] = [{ role: "user", content }]; // Local storage options - using camelCase const options: any = { userId: finalUserId, sessionId, metadata }; // API call const result = await this.localClient.add(messages, options); return { content: [{ type: "text", text: `Memory added successfully. Result: ${JSON.stringify(result)}` }], }; } catch (error: any) { throw new McpError(ErrorCode.InternalError, `Error adding memory: ${error.message}`); } } else { throw new McpError(ErrorCode.InternalError, "No memory client is available"); } } /** * Handles searching memories using either local or cloud client. */ private async handleSearchMemory(args: Mem0SearchToolArgs): Promise<any> { const { query, userId, sessionId, agentId, appId, projectId, orgId, filters, threshold, topK, fields, rerank, keywordSearch, filterMemories } = args; if (!query) { throw new McpError(ErrorCode.InvalidParams, "Missing required argument: query"); } // Use DEFAULT_USER_ID as fallback if userId is not provided const finalUserId = userId || process.env.DEFAULT_USER_ID; if (!finalUserId) { throw new McpError(ErrorCode.InvalidParams, "Missing required argument: userId (and no DEFAULT_USER_ID environment variable set)"); } if (this.isCloudMode && this.cloudClient) { try { // Get all parameters - parameter takes precedence over environment const finalAppId = appId || process.env.DEFAULT_APP_ID; const finalAgentId = agentId || process.env.DEFAULT_AGENT_ID; const finalProjectId = projectId || process.env.DEFAULT_PROJECT_ID; const finalOrgId = orgId || process.env.DEFAULT_ORG_ID; // Cloud API options - using snake_case for API parameters // Note: Search operations don't use version parameter (only for add operations) const options: any = { user_id: finalUserId }; // Add all parameters if available (using snake_case) if (finalAppId) options.app_id = finalAppId; if (finalAgentId) options.agent_id = finalAgentId; if (finalProjectId) options.project_id = finalProjectId; if (finalOrgId) options.org_id = finalOrgId; // Map sessionId to run_id and other parameters (using snake_case) if (sessionId) options.run_id = sessionId; if (filters) options.filters = filters; // Only add threshold if it's a valid number (not null or undefined) if (threshold !== undefined && threshold !== null) { options.threshold = threshold; } // Don't set a default threshold - let the API use its own defaults // Add advanced search parameters (using snake_case) if (topK !== undefined) options.top_k = topK; if (fields) options.fields = fields; if (rerank !== undefined) options.rerank = rerank; if (keywordSearch !== undefined) options.keyword_search = keywordSearch; if (filterMemories !== undefined) options.filter_memories = filterMemories; // API call - try direct REST API approach first for better parameter support let results; let usedDirectAPI = false; // Always try direct REST API first when app_id or run_id are provided if (finalAppId || sessionId) { try { const apiUrl = 'https://api.mem0.ai/v1/memories/search'; const requestBody = { query: query, ...options }; const response = await fetch(apiUrl, { method: 'POST', headers: { 'Authorization': `Token ${process.env.MEM0_API_KEY}`, 'Content-Type': 'application/json' }, body: JSON.stringify(requestBody) }); if (!response.ok) { const errorText = await response.text(); throw new Error(`Direct search API call failed: ${response.status} ${response.statusText} - ${errorText}`); } results = await response.json(); usedDirectAPI = true; } catch (directError: any) { // Fall through to SDK attempt } } // Try SDK if direct API wasn't used or failed if (!usedDirectAPI) { try { results = await this.cloudClient.search(query, options); } catch (sdkError: any) { throw sdkError; } } // Handle potential array or object result const resultsArray = Array.isArray(results) ? results : [results]; return { content: [{ type: "text", text: JSON.stringify(results, null, 2) }], }; } catch (error: any) { throw new McpError(ErrorCode.InternalError, `Error searching memories: ${error.message}`); } } else if (this.isSupabaseMode && this.supabaseClient) { try { // Get all parameters - parameter takes precedence over environment const finalAppId = appId || process.env.DEFAULT_APP_ID; const finalAgentId = agentId || process.env.DEFAULT_AGENT_ID; const finalProjectId = projectId || process.env.DEFAULT_PROJECT_ID; const finalOrgId = orgId || process.env.DEFAULT_ORG_ID; // Supabase storage options - using camelCase for local SDK const options: any = { userId: finalUserId, sessionId, filters }; // Add all parameters if available if (finalAppId) options.appId = finalAppId; if (finalAgentId) options.agentId = finalAgentId; if (finalProjectId) options.projectId = finalProjectId; if (finalOrgId) options.orgId = finalOrgId; // API call const results = await this.supabaseClient.search(query, options); // Handle potential array or object result const resultsArray = Array.isArray(results) ? results : [results]; return { content: [{ type: "text", text: JSON.stringify(results, null, 2) }], }; } catch (error: any) { throw new McpError(ErrorCode.InternalError, `Error searching memories: ${error.message}`); } } else if (this.localClient) { try { // Local storage options const options: any = { userId: finalUserId, sessionId, filters }; // API call const results = await this.localClient.search(query, options); // Handle potential array or object result const resultsArray = Array.isArray(results) ? results : [results]; return { content: [{ type: "text", text: JSON.stringify(results, null, 2) }], }; } catch (error: any) { throw new McpError(ErrorCode.InternalError, `Error searching memories: ${error.message}`); } } else { throw new McpError(ErrorCode.InternalError, "No memory client is available"); } } /** * Handles deleting a memory using either local or cloud client. */ private async handleDeleteMemory(args: Mem0DeleteToolArgs): Promise<any> { const { memoryId, userId, agentId, appId, projectId, orgId } = args; if (!memoryId) { throw new McpError(ErrorCode.InvalidParams, "Missing required argument: memoryId"); } // Use DEFAULT_USER_ID as fallback if userId is not provided const finalUserId = userId || process.env.DEFAULT_USER_ID; if (!finalUserId) { throw new McpError(ErrorCode.InvalidParams, "Missing required argument: userId (and no DEFAULT_USER_ID environment variable set)"); } if (this.isCloudMode && this.cloudClient) { try { // Get all parameters - parameter takes precedence over environment const finalAppId = appId || process.env.DEFAULT_APP_ID; const finalAgentId = agentId || process.env.DEFAULT_AGENT_ID; const finalProjectId = projectId || process.env.DEFAULT_PROJECT_ID; const finalOrgId = orgId || process.env.DEFAULT_ORG_ID; // Cloud API options - using snake_case for API parameters // Note: Delete memory uses v1 API, no version parameter needed const options: any = { memory_id: memoryId, user_id: finalUserId }; // Add all parameters if available (using snake_case) if (finalAppId) options.app_id = finalAppId; if (finalAgentId) options.agent_id = finalAgentId; if (finalProjectId) options.project_id = finalProjectId; if (finalOrgId) options.org_id = finalOrgId; // Try to use the API's deleteMemory method through the client try { // @ts-ignore - We'll try to access this method even if TypeScript doesn't recognize it await this.cloudClient.deleteMemory(memoryId); } catch (innerError) { // If that fails, try to use a generic request method await fetch(`https://api.mem0.ai/v1/memories/${memoryId}/`, { method: 'DELETE', headers: { 'Authorization': `Token ${process.env.MEM0_API_KEY}`, 'Content-Type': 'application/json' }, body: JSON.stringify(options) }); } return { content: [{ type: "text", text: `Memory ${memoryId} deleted successfully` }], }; } catch (error: any) { throw new McpError(ErrorCode.InternalError, `Error deleting memory: ${error.message}`); } } else if (this.isSupabaseMode && this.supabaseClient) { try { // For Supabase storage, try to use the deleteMemory method try { // @ts-ignore - We'll try to access this method even if TypeScript doesn't recognize it await this.supabaseClient.deleteMemory(memoryId); } catch (innerError) { // If direct method fails, try to access through any internal methods // @ts-ignore - Accessing potentially private properties if (this.supabaseClient._vectorstore && typeof this.supabaseClient._vectorstore.delete === 'function') { // @ts-ignore await this.supabaseClient._vectorstore.delete({ ids: [memoryId] }); } else { throw new Error("Supabase client does not support memory deletion"); } } return { content: [{ type: "text", text: `Memory ${memoryId} deleted successfully` }], }; } catch (error: any) { throw new McpError(ErrorCode.InternalError, `Error deleting memory: ${error.message || "Supabase client does not support memory deletion"}`); } } else if (this.localClient) { try { // For local storage, we need to find a way to delete the memory // Since we don't have direct access to deleteMemory, we'll try to access it indirectly try { // @ts-ignore - We'll try to access this method even if TypeScript doesn't recognize it await this.localClient.deleteMemory(memoryId); } catch (innerError) { // @ts-ignore - Accessing potentially private properties if (this.localClient._vectorstore && typeof this.localClient._vectorstore.delete === 'function') { // @ts-ignore await this.localClient._vectorstore.delete({ ids: [memoryId] }); } else { throw new Error("Local client does not support memory deletion"); } } return { content: [{ type: "text", text: `Memory ${memoryId} deleted successfully` }], }; } catch (error: any) { throw new McpError(ErrorCode.InternalError, `Error deleting memory: ${error.message || "Local client does not support memory deletion"}`); } } else { throw new McpError(ErrorCode.InternalError, "No memory client is available"); } } /** * Starts the MCP server. */ public async start(): Promise<void> { const transport = new StdioServerTransport(); await this.server.connect(transport); } } // Start the server const server = new Mem0MCPServer(); server.start().catch((error) => { process.exit(1); });

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/pinkpixel-dev/mem0-mcp'

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