# MCP Memory Service (Rust Implementation) This is a Rust implementation of the Model Context Protocol (MCP) Memory Service, using the official [Rust MCP SDK](https://github.com/modelcontextprotocol/rust-sdk). ## Features - Implements an MCP server that provides memory storage and retrieval functionality - Communicates over stdio for easy integration with MCP clients - Provides the following tools: - `store_memory`: Store a new memory with content, tags, and metadata - `retrieve_memory`: Retrieve memories semantically similar to a query - `search_by_tag`: Search memories by tags - `delete_memory`: Delete a memory by its hash - Supports multiple storage backends: - In-memory storage (for testing and development) - ChromaDB storage (for production use) - Supports multiple embedding models: - Dummy embedding generator (for testing and development) - ONNX embedding model (transformer-based embeddings using ONNX Runtime) ## Prerequisites - Rust and Cargo (1.75.0 or later) - Node.js and npm (for testing with the MCP inspector) - Optional: ChromaDB server (for production use) ## Building ```bash cargo build ``` For a release build: ```bash cargo build --release ``` ## Running To run the server directly: ```bash cargo run ``` With environment variables for configuration: ```bash MCP_MEMORY_STORAGE_BACKEND=chromadb \ MCP_MEMORY_CHROMA_PATH=/path/to/chroma \ MCP_MEMORY_EMBEDDING_MODEL=onnx \ cargo run ``` ## Configuration The server can be configured using environment variables: | Variable | Description | Default | |----------|-------------|---------| | `MCP_MEMORY_STORAGE_BACKEND` | Storage backend (`inmemory` or `chromadb`) | `inmemory` | | `MCP_MEMORY_CHROMA_PATH` | Path to ChromaDB data directory | Platform-specific data directory | | `MCP_MEMORY_CHROMA_URL` | URL to ChromaDB server (optional) | None | | `MCP_MEMORY_CHROMA_COLLECTION` | ChromaDB collection name | `memory_collection` | | `MCP_MEMORY_EMBEDDING_MODEL` | Embedding model (`dummy` or `onnx`) | `dummy` | | `MCP_MEMORY_EMBEDDING_MODEL_PATH` | Path to ONNX model file (optional) | None | | `MCP_MEMORY_EMBEDDING_SIZE` | Embedding vector size | 384 | | `MCP_MEMORY_LOG_LEVEL` | Log level | `info` | ## Testing This project includes a simple Node.js test script for testing the server. To run the tests: ```bash npm test ``` ## Project Structure - `src/main.rs`: The main server implementation - `src/config.rs`: Configuration handling - `src/models.rs`: Data models - `src/storage/`: Storage implementations - `mod.rs`: Storage trait and in-memory implementation - `chroma.rs`: ChromaDB storage implementation - `src/embeddings.rs`: Embedding model implementations - `src/utils.rs`: Utility functions - `Cargo.toml`: Rust project configuration - `package.json`: Node.js project configuration for testing tools - `test-mcp-server.js`: A simple Node.js script to test the server programmatically ## Implementation Details The server is implemented using the `rmcp` crate from the Rust MCP SDK. It uses: - The `#[tool(tool_box)]` attribute macro to define tools - The `ServerHandler` trait to implement the MCP protocol - The `stdio()` transport for CLI usage - Asynchronous Rust with Tokio for concurrent operations - Tracing for structured logging ## Example Usage After starting the server with `cargo run`, you can send JSON-RPC requests to its stdin. For example: ```json {"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocol_version":"2024-11-05","capabilities":{"tools":true},"client_info":{"name":"test-client","version":"0.1.0"}}} {"jsonrpc":"2.0","id":2,"method":"list_tools","params":{}} {"jsonrpc":"2.0","id":3,"method":"call_tool","params":{"name":"store_memory","arguments":{"content":"This is a test memory","tags":["test","example"]}}} ``` ## ONNX Embedding Implementation The ONNX embedding model implementation uses the ONNX Runtime to run transformer-based models for generating embeddings. Here's how it works: 1. **Model Loading**: The `OnnxEmbeddingGenerator` loads a pre-trained transformer model in ONNX format and a tokenizer from the specified paths. 2. **Tokenization**: Input text is tokenized using the HuggingFace `tokenizers` library, which converts text into token IDs, attention masks, and token type IDs. 3. **Inference**: The tokenized inputs are passed to the ONNX model, which produces the transformer's hidden states. 4. **Mean Pooling**: The last hidden state is processed using mean pooling (weighted by the attention mask) to create a fixed-size embedding vector. 5. **Normalization**: The resulting embedding is L2-normalized to ensure consistent vector magnitudes. To use the ONNX embedding model: 1. Export a transformer model (like BERT, RoBERTa, etc.) to ONNX format using a tool like HuggingFace's `transformers.onnx`. 2. Save the tokenizer as a `tokenizer.json` file in the same directory as the model or specify a separate path. 3. Set the environment variables: ```bash MCP_MEMORY_EMBEDDING_MODEL=onnx MCP_MEMORY_EMBEDDING_MODEL_PATH=/path/to/model.onnx MCP_MEMORY_EMBEDDING_SIZE=768 # Adjust based on your model's output size ``` ## Registering with an MCP Client To register this server with an MCP client (like Claude), you need to add it to the client's MCP configuration. Here's an example JSON configuration: ```json { "mcpServers": { "memory-service": { "command": "/path/to/mcp-rust-server", "args": [], "env": { "MCP_MEMORY_STORAGE_BACKEND": "inmemory", "MCP_MEMORY_EMBEDDING_MODEL": "onnx", "MCP_MEMORY_EMBEDDING_MODEL_PATH": "/path/to/model.onnx", "MCP_MEMORY_EMBEDDING_SIZE": "768", "MCP_MEMORY_LOG_LEVEL": "info" }, "disabled": false, "autoApprove": [] } } } ``` For Claude Desktop, this configuration would be added to: - macOS: `~/Library/Application Support/Claude/claude_desktop_config.json` - Windows: `%APPDATA%\Claude\claude_desktop_config.json` - Linux: `~/.config/Claude/claude_desktop_config.json` For Claude VSCode extension, the configuration would be added to: - `~/Library/Application Support/Code/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json` ## Future Improvements - Add support for more transformer architectures - Add more storage backends - Add more embedding models - Add more tools for memory management - Add authentication and authorization - Add support for more transports (HTTP, WebSocket, etc.) ## Architecture ```mermaid graph TD subgraph "External Interactions" direction LR Client([MCP Client]) -. JSON-RPC .-> StdioTransport[Stdio Transport] EnvVars[(Environment Variables)] -.-> Config ChromaDBServer[(ChromaDB Server)] <-. HTTP API .-> ChromaStorage OnnxModel[("ONNX Model File (.onnx)")] <-. Loads .-> OnnxEmbed TokenizerFile[("Tokenizer File (tokenizer.json)")] <-. Loads .-> OnnxEmbed end subgraph "MCP Memory Service (Rust Application)" direction TB StdioTransport -- Forwards Requests --> ServerCore{MCP Server Core} ServerCore -- Reads --> Config(Configuration) ServerCore -- Instantiates --> EmbeddingImpl{{Selected Embedding Generator}} ServerCore -- Instantiates --> StorageImpl{{Selected Storage Backend}} ServerCore -- Uses Tool Impls --> ToolLogic(Tool Logic: store, retrieve, search, delete) ToolLogic -- Uses --> StorageImpl ToolLogic -- Uses --> EmbeddingImpl ToolLogic -- Uses --> Models(Data Models) ToolLogic -- Uses --> Utils(Utilities) %% FIX: Added IDs EL and SL to subgraphs below subgraph EL [Embedding Layer] direction TB EmbeddingImpl -- Is an instance of --> EmbeddingTrait(EmbeddingGenerator Trait) DummyEmbed(DummyEmbeddingGenerator) -- Implements --> EmbeddingTrait OnnxEmbed(OnnxEmbeddingGenerator) -- Implements --> EmbeddingTrait OnnxEmbed -- Uses Lib --> OrtLib[ort crate] OnnxEmbed -- Uses Lib --> TokenizersLib[tokenizers crate] end subgraph SL [Storage Layer] direction TB StorageImpl -- Is an instance of --> StorageTrait(MemoryStorage Trait) InMemoryStorage(InMemoryStorage) -- Implements --> StorageTrait ChromaStorage(ChromaMemoryStorage) -- Implements --> StorageTrait StorageImpl -- Uses --> EmbeddingImpl StorageImpl -- Uses --> Models ChromaStorage -- Uses Lib --> ReqwestLib[reqwest crate] end end %% Styling classDef external fill:#f9f,stroke:#333,stroke-width:1px; classDef rust_app fill:#e6ffed,stroke:#333,stroke-width:1px; classDef trait fill:#lightblue,stroke:#333,stroke-width:1px; classDef impl fill:#lightgrey,stroke:#333,stroke-width:1px; classDef module fill:#whitesmoke,stroke:#333,stroke-width:1px; classDef lib fill:#cornsilk,stroke:#333,stroke-width:1px; class Client,EnvVars,ChromaDBServer,OnnxModel,TokenizerFile external; class StdioTransport,ServerCore,ToolLogic,Config,Models,Utils rust_app; class EmbeddingTrait,StorageTrait trait; class EmbeddingImpl,StorageImpl,DummyEmbed,OnnxEmbed,InMemoryStorage,ChromaStorage impl; class OrtLib,TokenizersLib,ReqwestLib lib; %% FIX: Used subgraph IDs EL and SL below class EL,SL module ``` ## License This project is licensed under the MIT License - see the LICENSE file for details.