UNPKG

openmemory

Version:

A Model Context Protocol (MCP) server that provides memory storage and retrieval capabilities using [Mem0](https://github.com/mem0ai/mem0). This tool allows you to store and search through memories, making it useful for maintaining context and making info

283 lines (282 loc) 8.25 kB
#!/usr/bin/env node // src/index.ts import { Server } from "@modelcontextprotocol/sdk/server/index.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js"; import dotenv from "dotenv"; dotenv.config(); var OPENMEMORY_API_KEY = process?.env?.OPENMEMORY_API_KEY || ""; var HOST = process?.env?.HOST || "api.openmemory.dev"; var CLIENT_NAME = process?.env?.CLIENT_NAME || "openmemory"; var HTTP_PROTOCOL = process?.env?.HTTP_PROTOCOL || "https"; var ASYNC_MODE = process?.env?.ASYNC_MODE || true; var API_BASE_URL = `${HTTP_PROTOCOL}://${HOST}`; var ADD_MEMORY_TOOL = { name: "add-memory", description: "Add a new memory. This method is called everytime the user informs anything about themselves, their preferences, or anything that has any relevent information whcih can be useful in the future conversation. This can also be called when the user asks you to remember something.", inputSchema: { type: "object", properties: { content: { type: "string", description: "The content to store in memory" } }, required: ["content"] } }; var SEARCH_MEMORIES_TOOL = { name: "search-memories", description: "Search through stored memories. This method is called ANYTIME the user asks anything.", inputSchema: { type: "object", properties: { query: { type: "string", description: "The search query. This is the query that the user has asked for. Example: 'What did I tell you about the weather last week?' or 'What did I tell you about my friend John?'" } }, required: ["query"] } }; var LIST_MEMORIES_TOOL = { name: "list-memories", description: "List all memories in the user's memory storage.", inputSchema: { type: "object", properties: {}, required: [] } }; var DELETE_ALL_MEMORIES_TOOL = { name: "delete-all-memories", description: "Delete all memories in the user's memory storage. Use with caution as this action cannot be undone.", inputSchema: { type: "object", properties: {}, required: [] } }; var server = new Server( { name: "openmemory", version: "0.0.1" }, { capabilities: { tools: {}, logging: {} } } ); async function addMemory(content) { try { const response = await fetch(`${API_BASE_URL}/mcp/add_memories`, { method: "POST", headers: { "Content-Type": "application/json", "Authorization": `Bearer ${OPENMEMORY_API_KEY}` }, body: JSON.stringify({ text: content, client_name: CLIENT_NAME, async_mode: ASYNC_MODE || true }) }); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const result = await response.json(); return result.status === "success"; } catch (error) { console.error("Error adding memory:", error); return false; } } async function searchMemories(query) { try { const response = await fetch(`${API_BASE_URL}/mcp/search_memory`, { method: "POST", headers: { "Content-Type": "application/json", "Authorization": `Bearer ${OPENMEMORY_API_KEY}` }, body: JSON.stringify({ query, client_name: CLIENT_NAME }) }); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const result = await response.json(); return result.memories || []; } catch (error) { console.error("Error searching memories:", error); return []; } } async function listMemories() { try { const response = await fetch(`${API_BASE_URL}/mcp/list_memories`, { method: "POST", headers: { "Content-Type": "application/json", "Authorization": `Bearer ${OPENMEMORY_API_KEY}` }, body: JSON.stringify({ client_name: CLIENT_NAME }) }); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const result = await response.json(); return result.memories || []; } catch (error) { console.error("Error listing memories:", error); return []; } } async function deleteAllMemories() { try { const response = await fetch(`${API_BASE_URL}/mcp/delete_all_memories`, { method: "POST", headers: { "Content-Type": "application/json", "Authorization": `Bearer ${OPENMEMORY_API_KEY}` }, body: JSON.stringify({ client_name: CLIENT_NAME }) }); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const result = await response.json(); return result; } catch (error) { console.error("Error deleting all memories:", error); return { status: "error", message: "Failed to delete memories" }; } } server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: [ADD_MEMORY_TOOL, SEARCH_MEMORIES_TOOL, LIST_MEMORIES_TOOL, DELETE_ALL_MEMORIES_TOOL] })); server.setRequestHandler(CallToolRequestSchema, async (request) => { try { const { name, arguments: args } = request.params; if (!args) { throw new Error("No arguments provided"); } switch (name) { case "add-memory": { const { content } = args; await addMemory(content); return { content: [ { type: "text", text: "Memory added successfully" } ], isError: false }; } case "search-memories": { const { query } = args; const results = await searchMemories(query); const formattedResults = results.map( (result) => `Memory: ${result.memory || result.text} Relevance: ${result.score || "N/A"} ---` ).join("\n"); return { content: [ { type: "text", text: formattedResults || "No memories found" } ], isError: false }; } case "list-memories": { const results = await listMemories(); const formattedResults = results.map( (result, index) => `${index + 1}. Memory: ${result.memory || result.text} ID: ${result.id || "N/A"} ---` ).join("\n"); return { content: [ { type: "text", text: formattedResults || "No memories found" } ], isError: false }; } case "delete-all-memories": { const result = await deleteAllMemories(); const message = result.status === "success" ? result.message || "All memories deleted successfully" : result.message || "Failed to delete memories"; return { content: [ { type: "text", text: message } ], isError: result.status !== "success" }; } default: return { content: [ { type: "text", text: `Unknown tool: ${name}` } ], isError: true }; } } catch (error) { return { content: [ { type: "text", text: `Error: ${error instanceof Error ? error.message : String(error)}` } ], isError: true }; } }); function safeLog(level, data) { console.error(`[${level}] ${typeof data === "object" ? JSON.stringify(data) : data}`); try { server.sendLoggingMessage({ level, data }); } catch (error) { } } async function main() { try { console.error("Initializing OpenMemory MCP Server..."); console.error(`Connecting to OpenMemory API at: ${API_BASE_URL}`); console.error(`Using client name: ${CLIENT_NAME}`); const transport = new StdioServerTransport(); await server.connect(transport); safeLog("info", "OpenMemory MCP Server initialized successfully"); console.error("OpenMemory MCP Server running on stdio"); } catch (error) { console.error("Fatal error running server:", error); process.exit(1); } } main().catch((error) => { console.error("Fatal error in main():", error); process.exit(1); }); //# sourceMappingURL=index.js.map