#
tokens: 5392/50000 13/13 files
lines: off (toggle) GitHub
raw markdown copy
# Directory Structure

```
├── .env
├── .python-version
├── main.py
├── node
│   └── mem0
│       ├── .gitignore
│       ├── package.json
│       ├── pnpm-lock.yaml
│       ├── pnpm-workspace.yaml
│       ├── README.md
│       ├── smithery.yaml
│       ├── src
│       │   └── index.ts
│       ├── tsconfig.json
│       └── tsup.config.ts
├── pyproject.toml
├── README.md
└── uv.lock
```

# Files

--------------------------------------------------------------------------------
/.python-version:
--------------------------------------------------------------------------------

```
3.12

```

--------------------------------------------------------------------------------
/.env:
--------------------------------------------------------------------------------

```
MEM0_API_KEY=<your-api-key>
```

--------------------------------------------------------------------------------
/node/mem0/.gitignore:
--------------------------------------------------------------------------------

```
**/.env
**/.env.local
**/.env.development.local
**/.env.test.local
**/.env.production.local
**/.env.development
**/.env.test

node_modules
build
dist

```

--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------

```markdown
# MCP Server with Mem0 for Managing Coding Preferences

This demonstrates a structured approach for using an [MCP](https://modelcontextprotocol.io/introduction) server with [mem0](https://mem0.ai) to manage coding preferences efficiently. The server can be used with Cursor and provides essential tools for storing, retrieving, and searching coding preferences.

## Installation

1. Clone this repository
2. Initialize the `uv` environment:

```bash
uv venv
```

3. Activate the virtual environment:

```bash
source .venv/bin/activate
```

4. Install the dependencies using `uv`:

```bash
# Install in editable mode from pyproject.toml
uv pip install -e .
```

5. Update `.env` file in the root directory with your mem0 API key:

```bash
MEM0_API_KEY=your_api_key_here
```

## Usage

1. Start the MCP server:

```bash
uv run main.py
```

2. In Cursor, connect to the SSE endpoint, follow this [doc](https://docs.cursor.com/context/model-context-protocol) for reference:

```
http://0.0.0.0:8080/sse
```

3. Open the Composer in Cursor and switch to `Agent` mode.

## Demo with Cursor

https://github.com/user-attachments/assets/56670550-fb11-4850-9905-692d3496231c

## Features

The server provides three main tools for managing code preferences:

1. `add_coding_preference`: Store code snippets, implementation details, and coding patterns with comprehensive context including:
   - Complete code with dependencies
   - Language/framework versions
   - Setup instructions
   - Documentation and comments
   - Example usage
   - Best practices

2. `get_all_coding_preferences`: Retrieve all stored coding preferences to analyze patterns, review implementations, and ensure no relevant information is missed.

3. `search_coding_preferences`: Semantically search through stored coding preferences to find relevant:
   - Code implementations
   - Programming solutions
   - Best practices
   - Setup guides
   - Technical documentation

## Why?

This implementation allows for a persistent coding preferences system that can be accessed via MCP. The SSE-based server can run as a process that agents connect to, use, and disconnect from whenever needed. This pattern fits well with "cloud-native" use cases where the server and clients can be decoupled processes on different nodes.

### Server

By default, the server runs on 0.0.0.0:8080 but is configurable with command line arguments like:

```
uv run main.py --host <your host> --port <your port>
```

The server exposes an SSE endpoint at `/sse` that MCP clients can connect to for accessing the coding preferences management tools.


```

--------------------------------------------------------------------------------
/node/mem0/README.md:
--------------------------------------------------------------------------------

```markdown
# Mem0 Memory MCP Server

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 informed decisions based on past interactions.

## Features

- Store memories with user-specific context
- Search through stored memories with relevance scoring
- Simple and intuitive API
- Built on the Model Context Protocol
- Automatic error handling
- Support for multiple user contexts

## Usage

This server now supports StreamableHTTP via Smithery CLI while retaining optional STDIO compatibility.

### StreamableHTTP (recommended)

- Development (opens Smithery Playground and exposes HTTP transport):

```bash
npm run dev
```

- Build for HTTP/StreamableHTTP (Smithery):

```bash
npm run build
```

- Start the HTTP server locally (Smithery-built entrypoint):

```bash
npm run start:http
```

You can configure the server using Smithery’s generated form in the playground or by setting environment variables (e.g., `MEM0_API_KEY`).

### STDIO (backward compatible)

Run the server over STDIO (useful for local clients that only support STDIO):

```bash
env MEM0_API_KEY=your-api-key-here npm run build:stdio && npm run start:stdio
```

## Configuration for AI Tools

### Running on Cursor (STDIO)

#### Configuring Cursor 🖥️

To configure Mem0 MCP in Cursor:

1. Open Cursor Settings
2. Go to Features > MCP Servers
3. Click "+ Add New MCP Server"
4. Enter the following:
   - Name: "mem0-mcp" (or your preferred name)
   - Type: "command"
   - Command: `env MEM0_API_KEY=your-api-key-here npx -y @mem0/mcp` (or use `start:stdio` from this repo)

To configure Mem0 MCP using JSON configuration:

```json
{
  "mcpServers": {
    "mem0-mcp": {
      "command": "npx",
      "args": ["-y", "@mem0/mcp"],
      "env": {
        "MEM0_API_KEY": "YOUR-API-KEY-HERE"
      }
    }
  }
}
```

### Running on VS Code (STDIO)

Add the following JSON block to your User Settings (JSON) file in VS Code:

```json
{
  "mcp": {
    "inputs": [
      {
        "type": "promptString",
        "id": "apiKey",
        "description": "Mem0 API Key",
        "password": true
      }
    ],
    "servers": {
      "mem0-memory": {
        "command": "npx",
        "args": ["-y", "@mem0/mcp"],
        "env": {
          "MEM0_API_KEY": "${input:apiKey}"
        }
      }
    }
  }
}
```

## Available Tools

### 1. Add Memory Tool (add-memory)

Store new memories with user-specific context.

```json
{
  "name": "add-memory",
  "arguments": {
    "content": "User prefers dark mode interface",
    "userId": "user123"
  }
}
```

### 2. Search Memories Tool (search-memories)

Search through stored memories to retrieve relevant information.

```json
{
  "name": "search-memories",
  "arguments": {
    "query": "What are the user's interface preferences?",
    "userId": "user123"
  }
}
```

## Response Format

### Add Memory Response

```json
{
  "content": [
    {
      "type": "text",
      "text": "Memory added successfully"
    }
  ],
  "isError": false
}
```

### Search Memory Response

```json
{
  "content": [
    {
      "type": "text",
      "text": "Memory: User prefers dark mode interface\nRelevance: 0.95\n---\nMemory: User mentioned liking minimal UI\nRelevance: 0.82\n---"
    }
  ],
  "isError": false
}
```

## Configuration

### Environment Variables

- `MEM0_API_KEY`: Your Mem0 API key (required)
  - Required for operation
  - Can be obtained from [Mem0 Dashboard](https://app.mem0.ai/dashboard/api-keys)

## Development

### Prerequisites

- Node.js >= 18
- A Mem0 API key

### Setup

1. Install dependencies:

```bash
npm install
```

2. Optionally create a `.env` file in the project directory and add your Mem0 API key:

```bash
MEM0_API_KEY=your-api-key-here
DEFAULT_USER_ID=mem0-mcp-user
```

### HTTP/StreamableHTTP Dev

```bash
npm run dev
```

### STDIO Dev

```bash
npm run build:stdio
npm run start:stdio
```

## Error Handling

The server includes error handling for:

- API connection issues
- Invalid memory operations
- Search errors
- Authentication failures

Example error response:

```json
{
  "content": [
    {
      "type": "text",
      "text": "Error: Failed to search memories: Invalid API key"
    }
  ],
  "isError": true
}
```

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

## License

MIT 

```

--------------------------------------------------------------------------------
/node/mem0/smithery.yaml:
--------------------------------------------------------------------------------

```yaml
runtime: typescript
entry: src/index.ts

```

--------------------------------------------------------------------------------
/node/mem0/pnpm-workspace.yaml:
--------------------------------------------------------------------------------

```yaml
onlyBuiltDependencies:
  - esbuild
  - sqlite3

```

--------------------------------------------------------------------------------
/node/mem0/tsup.config.ts:
--------------------------------------------------------------------------------

```typescript
import { defineConfig } from 'tsup'

export default defineConfig([
  {
    dts: true,
    entry: ['src/index.ts'],
    format: ['cjs', 'esm'],
    sourcemap: true,
  },
])
```

--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------

```toml
[project]
name = "mem0-mcp"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.12"
dependencies = [
    "httpx>=0.28.1",
    "mcp[cli]>=1.3.0",
    "mem0ai>=0.1.55",
]

```

--------------------------------------------------------------------------------
/node/mem0/tsconfig.json:
--------------------------------------------------------------------------------

```json
{
    "compilerOptions": {
      "target": "ES2022",
      "module": "Node16",
      "moduleResolution": "Node16",
      "outDir": "./build",
      "rootDir": "./src",
      "strict": true,
      "esModuleInterop": true,
      "skipLibCheck": true,
      "forceConsistentCasingInFileNames": true
    },
    "include": ["src/**/*"],
    "exclude": ["node_modules"]
  }
```

--------------------------------------------------------------------------------
/node/mem0/package.json:
--------------------------------------------------------------------------------

```json
{
  "name": "@mem0/mcp-server",
  "version": "0.0.1",
  "main": "dist/index.js",
  "type": "module",
  "module": "src/index.ts",
  "bin": {
    "mem0-mcp": "dist/index.js"
  },
  "scripts": {
    "dev": "npx @smithery/cli dev",
    "build": "npm run build:http",
    "build:stdio": "tsup",
    "build:http": "npx @smithery/cli build",
    "start": "npm run start:http",
    "start:http": "node .smithery/index.cjs",
    "start:stdio": "node dist/index.js",
    "clean": "rm -rf dist",
    "prepublishOnly": "npm run build:stdio"
  },
  "files": [
    "dist"
  ],
  "publishConfig": {
    "access": "public"
  },
  "keywords": [
    "mcp",
    "mem0",
    "memory",
    "ai",
    "agents"
  ],
  "author": "",
  "license": "ISC",
  "description": "",
  "dependencies": {
    "@modelcontextprotocol/sdk": "^1.17.4",
    "dotenv": "^16.5.0",
    "mem0ai": "^2.1.38",
    "tsup": "^8.4.0",
    "zod": "^3.24.2"
  },
  "devDependencies": {
    "@types/node": "^22.13.13",
    "typescript": "^5.8.2",
    "tsx": "^4.19.0"
  },
  "packageManager": "[email protected]+sha512.6540583f41cc5f628eb3d9773ecee802f4f9ef9923cc45b69890fb47991d4b092964694ec3a4f738a420c918a333062c8b925d312f42e4f0c263eb603551f977"
}

```

--------------------------------------------------------------------------------
/node/mem0/src/index.ts:
--------------------------------------------------------------------------------

```typescript
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { MemoryClient, Message } from 'mem0ai';
import dotenv from 'dotenv';
import { z } from 'zod';

dotenv.config();

// Session configuration schema (used by Smithery CLI for HTTP/StreamableHTTP)
export const configSchema = z.object({
  mem0ApiKey: z
    .string()
    .describe('Mem0 API key. Defaults to MEM0_API_KEY env var if not provided.'),
  defaultUserId: z
    .string()
    .optional()
    .default('mem0-mcp-user')
    .describe("Default user ID when not provided in tool input"),
});

// Factory to create the MCP server. Smithery CLI will call this for HTTP transport.
export default function createServer({
  config,
}: {
  config: z.infer<typeof configSchema>;
}) {
  const apiKey = config.mem0ApiKey || process?.env?.MEM0_API_KEY || '';
  const defaultUserId = config.defaultUserId || 'mem0-mcp-user';

  const memoryClient = new MemoryClient({ apiKey });

  const server = new McpServer({
    name: 'mem0-mcp',
    version: '0.0.1',
  });

  // add-memory tool
  server.tool(
    'add-memory',
    'Add a new memory about the user. Call this whenever the user shares preferences, facts about themselves, or explicitly asks you to remember something.',
    {
      content: z.string().describe('The content to store in memory'),
      userId: z
        .string()
        .optional()
        .describe("User ID for memory storage. If omitted, uses config.defaultUserId."),
    },
    async ({ content, userId }) => {
      const resolvedUserId = userId || defaultUserId;
      try {
        const messages: Message[] = [
          { role: 'user', content: content }
        ];
        memoryClient.add(messages, { user_id: resolvedUserId, async_mode: true, version: "v2", output_format: "v1.1" });
        return {
          content: [
            {
              type: 'text',
              text: 'Memory added successfully',
            },
          ],
        };
      } catch (error) {
        return {
          content: [
            {
              type: 'text',
              text:
                'Error adding memory: ' +
                (error instanceof Error ? error.message : String(error)),
            },
          ],
          isError: true,
        } as const;
      }
    }
  );

  // search-memories tool
  server.tool(
    'search-memories',
    'Search through stored memories. Call this whenever you need to recall prior information relevant to the user query.',
    {
      query: z
        .string()
        .describe(
          "The search query, typically derived from the user's current question."
        ),
      userId: z
        .string()
        .optional()
        .describe("User ID for memory storage. If omitted, uses config.defaultUserId."),
    },
    async ({ query, userId }) => {
      const resolvedUserId = userId || defaultUserId;
      try {
        const results: any[] = await memoryClient.search(query, {
          user_id: resolvedUserId,
        });
        const formattedResults = (results || [])
          .map((result: any) => `Memory: ${result.memory}\nRelevance: ${result.score}\n---`)
          .join('\n');

        return {
          content: [
            {
              type: 'text',
              text: formattedResults || 'No memories found',
            },
          ],
        };
      } catch (error) {
        return {
          content: [
            {
              type: 'text',
              text:
                'Error searching memories: ' +
                (error instanceof Error ? error.message : String(error)),
            },
          ],
          isError: true,
        } as const;
      }
    }
  );

  return server.server;
}

// Optional: keep STDIO compatibility for local usage
async function main() {
  try {
    console.error('Initializing Mem0 Memory MCP Server (stdio mode)...');

    const server = createServer({
      config: {
        mem0ApiKey: process?.env?.MEM0_API_KEY,
        defaultUserId: process?.env?.DEFAULT_USER_ID || 'mem0-mcp-user',
      },
    });

    const transport = new StdioServerTransport();
    await server.connect(transport);

    console.error('Memory MCP Server running on stdio');
  } catch (error) {
    console.error('Fatal error running server:', error);
    process.exit(1);
  }
}

// Execute main when launched directly via node dist/index.js
if (process.argv[1] && process.argv[1].includes('index.js')) {
  // best-effort detection; avoids executing during smithery-cli runtime
  main().catch((error) => {
    console.error('Fatal error in main():', error);
    process.exit(1);
  });
}

```

--------------------------------------------------------------------------------
/main.py:
--------------------------------------------------------------------------------

```python
from mcp.server.fastmcp import FastMCP
from starlette.applications import Starlette
from mcp.server.sse import SseServerTransport
from starlette.requests import Request
from starlette.routing import Mount, Route
from mcp.server import Server
import uvicorn
from mem0 import MemoryClient
from dotenv import load_dotenv
import json

load_dotenv()

# Initialize FastMCP server for mem0 tools
mcp = FastMCP("mem0-mcp")

# Initialize mem0 client and set default user
mem0_client = MemoryClient()
DEFAULT_USER_ID = "cursor_mcp"
CUSTOM_INSTRUCTIONS = """
Extract the Following Information:  

- Code Snippets: Save the actual code for future reference.  
- Explanation: Document a clear description of what the code does and how it works.
- Related Technical Details: Include information about the programming language, dependencies, and system specifications.  
- Key Features: Highlight the main functionalities and important aspects of the snippet.
"""
mem0_client.update_project(custom_instructions=CUSTOM_INSTRUCTIONS)

@mcp.tool(
    description="""Add a new coding preference to mem0. This tool stores code snippets, implementation details,
    and coding patterns for future reference. Store every code snippet. When storing code, you should include:
    - Complete code with all necessary imports and dependencies
    - Language/framework version information (e.g., "Python 3.9", "React 18")
    - Full implementation context and any required setup/configuration
    - Detailed comments explaining the logic, especially for complex sections
    - Example usage or test cases demonstrating the code
    - Any known limitations, edge cases, or performance considerations
    - Related patterns or alternative approaches
    - Links to relevant documentation or resources
    - Environment setup requirements (if applicable)
    - Error handling and debugging tips
    The preference will be indexed for semantic search and can be retrieved later using natural language queries."""
)
async def add_coding_preference(text: str) -> str:
    """Add a new coding preference to mem0.

    This tool is designed to store code snippets, implementation patterns, and programming knowledge.
    When storing code, it's recommended to include:
    - Complete code with imports and dependencies
    - Language/framework information
    - Setup instructions if needed
    - Documentation and comments
    - Example usage

    Args:
        text: The content to store in memory, including code, documentation, and context
    """
    try:
        messages = [{"role": "user", "content": text}]
        mem0_client.add(messages, user_id=DEFAULT_USER_ID, output_format="v1.1")
        return f"Successfully added preference: {text}"
    except Exception as e:
        return f"Error adding preference: {str(e)}"

@mcp.tool(
    description="""Retrieve all stored coding preferences for the default user. Call this tool when you need 
    complete context of all previously stored preferences. This is useful when:
    - You need to analyze all available code patterns
    - You want to check all stored implementation examples
    - You need to review the full history of stored solutions
    - You want to ensure no relevant information is missed
    Returns a comprehensive list of:
    - Code snippets and implementation patterns
    - Programming knowledge and best practices
    - Technical documentation and examples
    - Setup and configuration guides
    Results are returned in JSON format with metadata."""
)
async def get_all_coding_preferences() -> str:
    """Get all coding preferences for the default user.

    Returns a JSON formatted list of all stored preferences, including:
    - Code implementations and patterns
    - Technical documentation
    - Programming best practices
    - Setup guides and examples
    Each preference includes metadata about when it was created and its content type.
    """
    try:
        memories = mem0_client.get_all(user_id=DEFAULT_USER_ID, page=1, page_size=50)
        flattened_memories = [memory["memory"] for memory in memories["results"]]
        return json.dumps(flattened_memories, indent=2)
    except Exception as e:
        return f"Error getting preferences: {str(e)}"

@mcp.tool(
    description="""Search through stored coding preferences using semantic search. This tool should be called 
    for EVERY user query to find relevant code and implementation details. It helps find:
    - Specific code implementations or patterns
    - Solutions to programming problems
    - Best practices and coding standards
    - Setup and configuration guides
    - Technical documentation and examples
    The search uses natural language understanding to find relevant matches, so you can
    describe what you're looking for in plain English. Always search the preferences before 
    providing answers to ensure you leverage existing knowledge."""
)
async def search_coding_preferences(query: str) -> str:
    """Search coding preferences using semantic search.

    The search is powered by natural language understanding, allowing you to find:
    - Code implementations and patterns
    - Programming solutions and techniques
    - Technical documentation and guides
    - Best practices and standards
    Results are ranked by relevance to your query.

    Args:
        query: Search query string describing what you're looking for. Can be natural language
              or specific technical terms.
    """
    try:
        memories = mem0_client.search(query, user_id=DEFAULT_USER_ID, output_format="v1.1")
        flattened_memories = [memory["memory"] for memory in memories["results"]]
        return json.dumps(flattened_memories, indent=2)
    except Exception as e:
        return f"Error searching preferences: {str(e)}"

def create_starlette_app(mcp_server: Server, *, debug: bool = False) -> Starlette:
    """Create a Starlette application that can server the provied mcp server with SSE."""
    sse = SseServerTransport("/messages/")

    async def handle_sse(request: Request) -> None:
        async with sse.connect_sse(
                request.scope,
                request.receive,
                request._send,  # noqa: SLF001
        ) as (read_stream, write_stream):
            await mcp_server.run(
                read_stream,
                write_stream,
                mcp_server.create_initialization_options(),
            )

    return Starlette(
        debug=debug,
        routes=[
            Route("/sse", endpoint=handle_sse),
            Mount("/messages/", app=sse.handle_post_message),
        ],
    )


if __name__ == "__main__":
    mcp_server = mcp._mcp_server

    import argparse

    parser = argparse.ArgumentParser(description='Run MCP SSE-based server')
    parser.add_argument('--host', default='0.0.0.0', help='Host to bind to')
    parser.add_argument('--port', type=int, default=8080, help='Port to listen on')
    args = parser.parse_args()

    # Bind SSE request handling to MCP server
    starlette_app = create_starlette_app(mcp_server, debug=True)

    uvicorn.run(starlette_app, host=args.host, port=args.port)

```