Skip to main content
Glama
server.js10.6 kB
import { McpServer, ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { z } from "zod"; import MemoryClient from 'mem0ai'; import * as dotenv from 'dotenv'; import { createHash } from 'crypto'; // Load environment variables from .env file dotenv.config(); // Polyfill for window.crypto.subtle.digest if (typeof window === 'undefined') { global.window = { crypto: { subtle: { digest: async (algorithm, data) => { const hash = createHash('sha-256'); hash.update(Buffer.from(data)); return hash.digest(); } } } }; } // Initialize Mem0 client console.log("Initializing Mem0 client with:"); console.log("- API Key:", process.env.MEM0_API_KEY?.substring(0, 8) + "..."); console.log("- Organization ID:", process.env.MEM0_ORG_ID); console.log("- Project ID:", process.env.MEM0_PROJECT_ID); const mem0Client = new MemoryClient({ apiKey: process.env.MEM0_API_KEY || '', organizationId: process.env.MEM0_ORG_ID, projectId: process.env.MEM0_PROJECT_ID }); // Validate configuration if (!process.env.MEM0_API_KEY) { console.error("Error: MEM0_API_KEY environment variable is not set"); process.exit(1); } if (!process.env.MEM0_ORG_ID) { console.error("Error: MEM0_ORG_ID environment variable is not set"); process.exit(1); } if (!process.env.MEM0_PROJECT_ID) { console.error("Error: MEM0_PROJECT_ID environment variable is not set"); process.exit(1); } const memoryStreams = new Map(); // Create MCP server instance const server = new McpServer({ name: "mem0-server", version: "1.0.0", description: "Memory stream management server with Mem0 integration" }); // Define memory stream resource with template server.resource("memory-stream", new ResourceTemplate("memory://{streamId}", { list: async () => ({ resources: Array.from(memoryStreams.values()).map(stream => ({ name: stream.name, uri: `memory://${stream.id}`, description: `Memory stream with ${stream.content.length} messages`, mimeType: "application/json" })) }) }), async (uri, params) => { const streamId = typeof params.streamId === 'string' ? params.streamId : params.streamId[0]; const stream = memoryStreams.get(streamId); if (!stream) { throw new Error(`Stream ${streamId} not found`); } return { contents: [{ uri: uri.href, text: JSON.stringify({ id: stream.id, name: stream.name, contentLength: stream.content.length, createdAt: stream.createdAt, userId: stream.userId, agentId: stream.agentId }, null, 2) }] }; }); // List available streams server.resource("memory-streams", "memory://", async () => ({ contents: [{ uri: "memory://", text: JSON.stringify(Array.from(memoryStreams.values()).map(stream => ({ id: stream.id, name: stream.name, contentLength: stream.content.length, createdAt: stream.createdAt, userId: stream.userId, agentId: stream.agentId })), null, 2) }] })); // Create a new memory stream with Mem0 integration server.tool("create-memory-stream", { name: z.string(), initialContent: z.string().optional(), userId: z.string().optional(), agentId: z.string().optional() }, async ({ name, initialContent, userId, agentId }) => { console.log(`Creating memory stream: ${name}`); console.log(`User ID: ${userId}, Agent ID: ${agentId}`); const streamId = Math.random().toString(36).substring(7); const stream = { id: streamId, name, content: initialContent ? [initialContent] : [], createdAt: new Date(), userId, agentId }; memoryStreams.set(streamId, stream); // If userId and agentId are provided, store in Mem0 if (userId && agentId && initialContent) { const messages = [ { role: "user", content: initialContent } ]; const memoryOptions = { user_id: userId, agent_id: agentId }; try { console.log("Storing memory in Mem0:", { messages, options: memoryOptions, projectId: process.env.MEM0_PROJECT_ID, organizationId: process.env.MEM0_ORG_ID }); // Test Mem0 client connection console.log("Testing Mem0 client connection..."); const testSearch = await mem0Client.search("test", { user_id: userId, agent_id: agentId, threshold: 0.1 }); console.log("Mem0 connection test result:", testSearch); // Add the actual memory const result = await mem0Client.add(messages, memoryOptions); console.log("Successfully stored in Mem0:", result); } catch (error) { console.error("Failed to store memory in Mem0:", error); if (error instanceof Error) { console.error("Error details:", { name: error.name, message: error.message, stack: error.stack }); } throw error; } } return { content: [{ type: "text", text: JSON.stringify({ streamId, name, contentLength: stream.content.length, createdAt: stream.createdAt, userId, agentId }, null, 2) }] }; }); // Append content to a memory stream with Mem0 integration server.tool("append-to-stream", { streamId: z.string(), content: z.string(), role: z.enum(["user", "assistant"]).optional() }, async ({ streamId, content, role = "user" }) => { console.log(`Appending to stream ${streamId} with role ${role}`); const stream = memoryStreams.get(streamId); if (!stream) { return { content: [{ type: "text", text: `Stream ${streamId} not found` }], isError: true }; } stream.content.push(content); // If stream has Mem0 integration, store the new message if (stream.userId && stream.agentId) { const messages = [ { role, content } ]; const memoryOptions = { user_id: stream.userId, agent_id: stream.agentId }; try { console.log("Storing message in Mem0:", { messages, options: memoryOptions }); const result = await mem0Client.add(messages, memoryOptions); console.log("Successfully stored message in Mem0:", result); } catch (error) { console.error("Failed to store message in Mem0:", error); throw error; // Re-throw to see the full error in the response } } return { content: [{ type: "text", text: JSON.stringify({ streamId, contentLength: stream.content.length, lastContent: content }, null, 2) }] }; }); // Search memories in Mem0 server.tool("search-memories", { query: z.string(), userId: z.string(), agentId: z.string().optional(), threshold: z.number().optional() }, async ({ query, userId, agentId, threshold = 0.1 }) => { console.log(`Searching memories: "${query}"`); console.log(`User ID: ${userId}, Agent ID: ${agentId}, Threshold: ${threshold}`); try { const searchOptions = { user_id: userId, filters: agentId ? { OR: [ { agent_id: agentId }, { user_id: userId } ] } : undefined, threshold, api_version: 'v2' }; console.log("Search options:", searchOptions); const results = await mem0Client.search(query, searchOptions); console.log("Search results:", results); return { content: [{ type: "text", text: JSON.stringify(results, null, 2) }] }; } catch (error) { console.error("Error searching memories:", error); throw error; // Re-throw to see the full error in the response } }); // Read from a memory stream server.tool("read-stream", { streamId: z.string(), startIndex: z.number().optional(), endIndex: z.number().optional() }, async ({ streamId, startIndex = 0, endIndex }) => { const stream = memoryStreams.get(streamId); if (!stream) { return { content: [{ type: "text", text: `Stream ${streamId} not found` }], isError: true }; } const end = endIndex ?? stream.content.length; const content = stream.content.slice(startIndex, end); return { content: [{ type: "text", text: JSON.stringify({ streamId, content, range: { startIndex, endIndex: end }, totalLength: stream.content.length, userId: stream.userId, agentId: stream.agentId }, null, 2) }] }; }); // Delete a memory stream server.tool("delete-stream", { streamId: z.string() }, async ({ streamId }) => { const stream = memoryStreams.get(streamId); if (!stream) { return { content: [{ type: "text", text: `Stream ${streamId} not found` }], isError: true }; } memoryStreams.delete(streamId); return { content: [{ type: "text", text: JSON.stringify({ streamId, status: "deleted", name: stream.name, userId: stream.userId, agentId: stream.agentId }, null, 2) }] }; }); // Connect to transport and start server const transport = new StdioServerTransport(); await server.connect(transport); console.log("mem0 MCP server started...");

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/sadiuysal/mem0-mcp-server-ts'

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