# SelfMemory Docs > Store your memories forever This file contains all documentation content in a single document following the llmstxt.org standard. ## Configuration Guide ## Overview SelfMemory follows Uncle Bob's Clean Code principles with a centralized configuration system. All configuration is managed through environment variables with sensible defaults. **Core Principles:** - ✅ **Single Source of Truth**: All config in one place (`server/config.py`) - ✅ **No Hardcoded Values**: Everything configurable via environment variables - ✅ **Type Safety**: Configuration classes with proper types - ✅ **Validation**: Startup validation catches misconfigurations early - ✅ **Zero Fallbacks**: Explicit errors instead of silent failures ## Quick Start 1. Copy the example environment file: ```bash cp .env.example .env ``` 2. Edit `.env` with your values: ```bash # Minimum required for development MONGODB_URI=mongodb://localhost:27017/selfmemory VECTOR_STORE_PROVIDER=qdrant QDRANT_HOST=localhost QDRANT_PORT=6333 EMBEDDING_PROVIDER=ollama EMBEDDING_MODEL=nomic-embed-text ``` 3. The server will validate configuration on startup and display errors if anything is misconfigured. ## Configuration Structure Configuration is organized into logical sections: ``` config/ ├── ErrorConfig # Error handling and logging ├── DatabaseConfig # MongoDB settings ├── SecurityConfig # CSRF, rate limiting, tokens ├── PaginationConfig # Pagination limits ├── EmailConfig # SMTP settings ├── AppConfig # Application settings ├── ServerConfig # Server host/port ├── VectorStoreConfig # Vector database settings ├── EmbeddingConfig # Embedding model settings ├── ValidationConfig # Input validation rules ├── RateLimitConfig # Rate limit rules ├── HealthConfig # Health check settings ├── MetricsConfig # Monitoring settings └── LoggingConfig # Structured logging ``` ## Configuration Sections ### Server Configuration Controls where the FastAPI server runs: ```bash # Host to bind to (0.0.0.0 = all interfaces) SELFMEMORY_SERVER_HOST=0.0.0.0 # Port to listen on SELFMEMORY_SERVER_PORT=8081 ``` --- ### Application Configuration General application settings: ```bash # Environment: development, staging, or production ENVIRONMENT=development # Frontend URL (for CORS and invitation links) FRONTEND_URL=http://localhost:3000 # Backend URL (for API references) BACKEND_URL=http://localhost:8081 # Timezone settings TIMEZONE=UTC DEFAULT_DISPLAY_TIMEZONE=UTC ``` **Defaults:** - Environment: `development` - Frontend URL: `http://localhost:3000` - Backend URL: `http://localhost:8081` - Timezone: `UTC` **Important:** Set `ENVIRONMENT=production` in production to enable security validations. --- ### Database Configuration (MongoDB) MongoDB connection and pool settings: ```bash # Connection URI MONGODB_URI=mongodb://localhost:27017/selfmemory # Connection timeout in seconds MONGODB_TIMEOUT=30 # Maximum pool size MONGODB_MAX_POOL_SIZE=100 # Transaction timeout in seconds MONGODB_TRANSACTION_TIMEOUT=30 # Enable retry writes MONGODB_RETRY_WRITES=true # Write concern level MONGODB_WRITE_CONCERN=majority ``` **Defaults:** - URI: `mongodb://localhost:27017/selfmemory` - Timeout: `30` seconds - Max Pool Size: `100` - Transaction Timeout: `30` seconds - Retry Writes: `true` - Write Concern: `majority` **Production Notes:** - Use authentication in production - Consider replica sets for high availability - Adjust pool size based on load --- ### Vector Store Configuration (Qdrant) Vector database settings for memory storage: ```bash # Provider name VECTOR_STORE_PROVIDER=qdrant # Qdrant host QDRANT_HOST=localhost # Qdrant port QDRANT_PORT=6333 # Collection name QDRANT_COLLECTION_NAME=selfmemory_memories ``` **Defaults:** - Provider: Not set (required) - Host: Not set (required) - Port: Not set (required) - Collection: `memories` **Required:** You must configure these for the system to work. --- ### Embedding Configuration Embedding model settings: ```bash # Provider (e.g., "ollama", "openai") EMBEDDING_PROVIDER=ollama # Model name EMBEDDING_MODEL=nomic-embed-text # Ollama base URL (if using Ollama) OLLAMA_BASE_URL=http://localhost:11434 ``` **Defaults:** - Provider: Not set (required) - Model: Not set (required) - Ollama Base URL: Not set (required if using Ollama) --- ### Security Configuration CSRF protection, rate limiting, and token expiry: ```bash # CSRF Secret Key - Generate with: # python -c "import secrets; print(secrets.token_urlsafe(32))" CSRF_SECRET_KEY=your_secret_key_here # CSRF Cookie Settings CSRF_COOKIE_SECURE=true CSRF_COOKIE_SAMESITE=strict # Rate Limiting RATE_LIMIT_ENABLED=false RATE_LIMIT_STORAGE_URL=memory:// # Token Expiry INVITATION_TOKEN_EXPIRY_HOURS=24 API_KEY_DEFAULT_EXPIRY_DAYS=90 ``` **Defaults:** - CSRF Cookie Secure: `true` - CSRF Cookie SameSite: `Strict` - Rate Limit Enabled: `false` - Invitation Expiry: `24` hours - API Key Expiry: No default (optional) **Production Requirements:** - MUST set `CSRF_SECRET_KEY` - Enable rate limiting (`RATE_LIMIT_ENABLED=true`) - Use Redis for rate limiting (`redis://localhost:6379`) --- ### Error Handling Configuration Controls error visibility: ```bash # Expose detailed errors to API responses # MUST be false in production ERROR_EXPOSE_DETAILS=false ``` **Defaults:** - Expose Details: `false` **Critical:** NEVER set to `true` in production. This would expose internal error details to users, creating a security vulnerability. --- ### Logging Configuration Structured logging settings: ```bash # Log level: DEBUG, INFO, WARNING, ERROR, CRITICAL LOG_LEVEL=INFO # Log format: json or text LOGGING_FORMAT=json # Log sampling rate (0.0 to 1.0) LOGGING_SAMPLE_RATE=1.0 ``` **Defaults:** - Level: `INFO` - Format: `json` - Sample Rate: `1.0` (log everything) **Production Tips:** - Use `INFO` or `WARNING` in production - Use `json` format for easy parsing - Consider sampling for high-volume logs --- ### Email/SMTP Configuration (Optional) SMTP settings for sending invitation emails: ```bash # SMTP Server SMTP_HOST=smtp.gmail.com SMTP_PORT=587 SMTP_USERNAME=your_email@gmail.com SMTP_PASSWORD=your_app_password # Email Settings SMTP_FROM_EMAIL=noreply@selfmemory.com SMTP_FROM_NAME=SelfMemory SMTP_USE_TLS=true SMTP_TIMEOUT=10 ``` **Defaults:** - Port: `587` - From Email: `noreply@selfmemory.com` - From Name: `SelfMemory` - Use TLS: `true` - Timeout: `10` seconds **Note:** If SMTP is not configured, invitation details are logged instead of emailed. --- ### Pagination Configuration Default and maximum page sizes: ```bash # Default items per page PAGINATION_DEFAULT_LIMIT=10 # Maximum items per page PAGINATION_MAX_LIMIT=100 ``` **Defaults:** - Default Limit: `10` - Max Limit: `100` --- ### Health Check Configuration Health check behavior: ```bash # Enable detailed checks HEALTH_ENABLE_DETAILED_CHECKS=true # Timeout for health checks HEALTH_TIMEOUT_SECONDS=5 # Memory threshold for warnings HEALTH_MEMORY_THRESHOLD_MB=900 ``` **Defaults:** - Enable Detailed: `true` - Timeout: `5` seconds - Memory Threshold: `900` MB --- ### Metrics Configuration Prometheus metrics endpoint: ```bash # Enable metrics endpoint METRICS_ENABLED=false ``` **Defaults:** - Enabled: `false` **Note:** Enable in production for monitoring. Metrics available at `/metrics`. --- ## Validation Rules Input validation is configured in `ValidationConfig`: ### Organization Names - Min Length: 2 characters - Max Length: 100 characters - Pattern: Letters, numbers, spaces, hyphens, underscores ### Project Names - Min Length: 2 characters - Max Length: 100 characters - Pattern: Letters, numbers, spaces, hyphens, underscores ### Tags - Min Length: 1 character - Max Length: 50 characters - Pattern: Letters, numbers, hyphens, underscores ### Memory Content - Max Length: 10,000 characters --- ## Rate Limits Rate limiting rules in `RateLimitConfig`: | Endpoint | Limit | Description | |----------|-------|-------------| | Invitation Create | 5/minute | Prevent spam invitations | | Invitation Accept | 3/minute | Prevent abuse | | Memory Create | 20/minute | Reasonable creation rate | | Memory Read | 60/minute | Higher limit for reads | | Memory Search | 30/minute | Search operations | | Project Create | 10/minute | Project creation | | Organization Create | 10/minute | Org creation | | Default | 120/minute | All other operations | --- ## Configuration Validation The server validates configuration on startup: ### Required Checks - ✅ MongoDB URI is set - ✅ Rate limit storage URL (if rate limiting enabled) - ✅ Valid environment name (development/staging/production) ### Production Checks - ✅ ERROR_EXPOSE_DETAILS must be false - ✅ CSRF_SECRET_KEY must be set **On Validation Failure:** The server will log all errors and refuse to start: ``` ========================================== CONFIGURATION VALIDATION FAILED ========================================== ❌ MONGODB_URI is required ❌ CSRF_SECRET_KEY is required in production ========================================== Please fix the configuration errors before starting the server. ``` --- ## Environment-Specific Configuration ### Development ```bash ENVIRONMENT=development ERROR_EXPOSE_DETAILS=true # OK in dev RATE_LIMIT_ENABLED=false # Disabled in dev LOG_LEVEL=DEBUG # Verbose logging CSRF_SECRET_KEY=dev_key # Simple key OK ``` ### Staging ```bash ENVIRONMENT=staging ERROR_EXPOSE_DETAILS=false RATE_LIMIT_ENABLED=true RATE_LIMIT_STORAGE_URL=redis://staging-redis:6379 LOG_LEVEL=INFO CSRF_SECRET_KEY= ``` ### Production ```bash ENVIRONMENT=production ERROR_EXPOSE_DETAILS=false # REQUIRED RATE_LIMIT_ENABLED=true RATE_LIMIT_STORAGE_URL=redis://prod-redis:6379 LOG_LEVEL=WARNING CSRF_SECRET_KEY= # REQUIRED MONGODB_URI=mongodb://prod-cluster/selfmemory ``` --- ## Accessing Configuration in Code Configuration is accessed through the singleton `config` object: ```python from server.config import config # Access configuration values host = config.server.HOST port = config.server.PORT db_uri = config.database.URI # Check environment if config.app.ENVIRONMENT == "production": # Production-specific logic pass # Use validation rules max_name_length = config.validation.ORG_NAME_MAX_LENGTH # Use rate limits memory_create_limit = config.rate_limit.MEMORY_CREATE ``` **Never:** - ❌ Use `os.getenv()` directly in application code - ❌ Hardcode values in business logic - ❌ Create fallback mechanisms **Always:** - ✅ Use `config` object - ✅ Let configuration errors fail explicitly - ✅ Add new config values to `config.py` --- ## Adding New Configuration To add a new configuration option: 1. **Add to appropriate config class** in `server/config.py`: ```python class SecurityConfig: NEW_OPTION: bool = os.getenv("NEW_OPTION", "false").lower() == "true" ``` 2. **Add to `.env.example`** with documentation: ```bash # Description of what this does NEW_OPTION=false ``` 3. **Add validation** (if required): ```python @classmethod def validate(cls) -> list[str]: errors = [] if not cls.security.NEW_OPTION and cls.app.ENVIRONMENT == "production": errors.append("NEW_OPTION required in production") return errors ``` 4. **Use in code**: ```python from server.config import config if config.security.NEW_OPTION: # Your logic here pass ``` --- ## Troubleshooting ### Server Won't Start **Check validation errors:** ```bash python -m server.main ``` Look for `CONFIGURATION VALIDATION FAILED` message. ### Configuration Not Loading **Check .env file location:** - Must be in project root - Named exactly `.env` - Not `.env.example` **Check environment variables:** ```bash python -c "from dotenv import load_dotenv; import os; load_dotenv(); print(os.getenv('MONGODB_URI'))" ``` ### Rate Limiting Issues **If rate limiting not working:** - Check `RATE_LIMIT_ENABLED=true` - Check `RATE_LIMIT_STORAGE_URL` is set - For development, use `memory://` - For production, use `redis://host:port` ### Email Not Sending **Check SMTP configuration:** - All SMTP_* variables set - Correct port (587 for TLS, 465 for SSL) - Valid credentials - Check logs for detailed error messages --- ## Security Best Practices ### Production Checklist - [ ] `ENVIRONMENT=production` - [ ] `ERROR_EXPOSE_DETAILS=false` - [ ] Strong `CSRF_SECRET_KEY` (use secure random generation) - [ ] `RATE_LIMIT_ENABLED=true` - [ ] Redis for rate limiting (not memory://) - [ ] HTTPS enabled (`CSRF_COOKIE_SECURE=true`) - [ ] MongoDB authentication enabled - [ ] Strong MongoDB credentials - [ ] Firewall rules in place - [ ] Regular backups configured ### Secret Management **NEVER commit:** - ❌ `.env` file - ❌ Credentials - ❌ API keys - ❌ CSRF secrets **DO:** - ✅ Use `.env.example` for templates - ✅ Use secret management tools in production - ✅ Rotate secrets regularly - ✅ Use environment variables in CI/CD --- ## Support For configuration issues: 1. Check this documentation 2. Review `.env.example` for all options 3. Check server logs for validation errors 4. Review `server/config.py` for defaults Remember: **Configuration errors fail fast and explicitly** - this is intentional and helps catch problems early! --- ## CSRF Protection Implementation ## Overview Cross-Site Request Forgery (CSRF) protection has been implemented for the SelfMemory REST API to protect session-based authentication from malicious cross-site requests. ## What is CSRF? CSRF is an attack that tricks a user's browser into making unwanted requests to a web application where the user is authenticated. For example, a malicious website could attempt to make requests to your API using the user's session cookies. ## Implementation Details ### Backend Setup The backend uses `fastapi-csrf-protect` library with the following configuration: **Configuration (in `server/config.py`):** ```python CSRF_SECRET_KEY: str = os.getenv("CSRF_SECRET_KEY", "") CSRF_COOKIE_SECURE: bool = True # Use secure cookies (HTTPS only) CSRF_COOKIE_SAMESITE: str = "Strict" # Prevent cross-site cookie sending CSRF_COOKIE_HTTPONLY: bool = True # Prevent JavaScript access to cookie CSRF_HEADER_NAME: str = "X-CSRF-Token" ``` **Environment Variables (.env):** ```bash # Generate with: python -c "import secrets; print(secrets.token_urlsafe(32))" CSRF_SECRET_KEY=your_generated_secret_key_here CSRF_COOKIE_SECURE=true CSRF_COOKIE_SAMESITE=Strict ``` ### CSRF Token Endpoint **GET `/api/csrf-token`** Generates and returns a CSRF token. The token is also set as a secure HttpOnly cookie. **Response:** ```json { "csrf_token": "generated_token_here", "message": "CSRF token generated successfully" } ``` ### Using CSRF Protection For state-changing operations (POST, PUT, DELETE), include the CSRF token in the `X-CSRF-Token` header: ```javascript fetch('/api/memories', { method: 'POST', headers: { 'Authorization': 'Session user_id', 'X-CSRF-Token': csrfToken, 'Content-Type': 'application/json' }, body: JSON.stringify(data) }) ``` ## Important Considerations for REST APIs ### Current Implementation Status The CSRF infrastructure is set up but **NOT YET ENFORCED** on endpoints to avoid breaking existing functionality. This allows for: 1. **Gradual Rollout**: Endpoints can be protected incrementally 2. **Backward Compatibility**: Existing clients continue to work 3. **Testing**: CSRF protection can be tested without disrupting production ### When to Use CSRF Protection **CSRF Protection is ESSENTIAL for:** - ✅ Session-based authentication (using cookies) - ✅ Dashboard web application - ✅ Any browser-based client **CSRF Protection is NOT NEEDED for:** - ❌ API key authentication (not cookie-based) - ❌ Mobile apps using API keys - ❌ Server-to-server API calls - ❌ OAuth 2.0 Bearer tokens ### Our Multi-Auth Architecture SelfMemory supports two authentication methods: 1. **Session Authentication** (Dashboard) - Uses `Authorization: Session ` header - Browser-based - **Requires CSRF protection** 2. **API Key Authentication** (SDK) - Uses `Authorization: sk_im_...` header - Not cookie-based - **Does not need CSRF protection** ## Enabling CSRF Protection on Endpoints To enable CSRF protection on an endpoint, add the `CsrfProtect` dependency: ```python from fastapi_csrf_protect import CsrfProtect @app.post("/api/memories") async def add_memory( memory_create: MemoryCreate, auth: AuthContext = Depends(authenticate_api_key), csrf_protect: CsrfProtect = Depends() # Add this ): # ONLY validate CSRF for session-based auth if auth.auth_type == "session": await csrf_protect.validate_csrf(request) # Rest of endpoint logic... ``` ## Frontend Integration ### 1. Fetch CSRF Token on App Load ```typescript async function initializeCsrfToken() { const response = await fetch('/api/csrf-token', { credentials: 'include' // Important: include cookies }); const data = await response.json(); return data.csrf_token; } ``` ### 2. Include Token in Requests ```typescript class ApiClient { private csrfToken: string | null = null; async initialize() { this.csrfToken = await initializeCsrfToken(); } async makeRequest(url: string, options: RequestInit) { const headers = { ...options.headers, 'X-CSRF-Token': this.csrfToken || '' }; return fetch(url, { ...options, headers }); } } ``` ### 3. Refresh Token on Expiry If a request fails with 403 CSRF error, refresh the token and retry: ```typescript async makeRequest(url: string, options: RequestInit) { let response = await fetch(url, options); if (response.status === 403) { const error = await response.json(); if (error.error?.code === 'CSRF_TOKEN_INVALID') { // Refresh token and retry this.csrfToken = await initializeCsrfToken(); response = await fetch(url, options); } } return response; } ``` ## Security Best Practices ### 1. HTTPS Only in Production Always use HTTPS in production to protect tokens in transit: ```bash CSRF_COOKIE_SECURE=true ``` ### 2. Strict SameSite Policy Use `Strict` or `Lax` to prevent cross-site attacks: ```bash CSRF_COOKIE_SAMESITE=Strict ``` ### 3. Rotate CSRF Secret Periodically rotate the CSRF secret key and update in production. ### 4. Token Expiry CSRF tokens should have reasonable expiry times (implemented by the library). ## Testing CSRF Protection ### Valid Request ```bash # Get token TOKEN=$(curl -s http://localhost:8081/api/csrf-token | jq -r .csrf_token) # Make request with token curl -X POST http://localhost:8081/api/memories \ -H "Authorization: Session user_123" \ -H "X-CSRF-Token: $TOKEN" \ -H "Content-Type: application/json" \ -d '{"messages": [{"role": "user", "content": "test"}]}' ``` ### Invalid Request (Should Fail) ```bash # Make request WITHOUT token curl -X POST http://localhost:8081/api/memories \ -H "Authorization: Session user_123" \ -H "Content-Type: application/json" \ -d '{"messages": [{"role": "user", "content": "test"}]}' # Response: 403 Forbidden # {"error": {"code": "CSRF_TOKEN_INVALID", ...}} ``` ## Troubleshooting ### Token Validation Fails 1. Ensure cookies are being sent (`credentials: 'include'` in fetch) 2. Check CORS configuration allows credentials 3. Verify token is included in `X-CSRF-Token` header 4. Confirm CSRF_SECRET_KEY is set and consistent ### CORS Issues with Cookies CORS must be configured to allow credentials: ```python app.add_middleware( CORSMiddleware, allow_origins=["http://localhost:3000"], # Specific origin, not "*" allow_credentials=True, # Required for cookies allow_methods=["*"], allow_headers=["*"], ) ``` ### Token Expires Too Quickly Tokens are session-based and managed by the library. If issues persist, check: - Server restarts (clears in-memory tokens) - Secret key changes - Cookie expiry settings ## Migration Path ### Phase 1: Setup (✅ Complete) - Install library - Add configuration - Create token endpoint - Add exception handler ### Phase 2: Frontend Integration (Current) - Update API client to fetch tokens - Include tokens in requests - Handle token refresh ### Phase 3: Gradual Enforcement (Future) - Enable protection on critical endpoints - Monitor for issues - Roll out to all endpoints ### Phase 4: Full Protection (Future) - All state-changing endpoints protected - Remove backward compatibility - Document as required ## References - [OWASP CSRF Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html) - [fastapi-csrf-protect Documentation](https://github.com/aekasitt/fastapi-csrf-protect) - [MDN: SameSite Cookies](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite) ## Status **Current Status:** CSRF infrastructure ready, not yet enforced on endpoints **Next Steps:** 1. Update frontend to fetch and include CSRF tokens 2. Test with dashboard application 3. Gradually enable protection on endpoints 4. Monitor and address any compatibility issues --- ## SelfMemory Documentation **Long-term memory for AI Agents with zero-setup simplicity** ## 🚀 Quick Start Install SelfMemory with a single command: ```bash pip install selfmemory ``` Start using it immediately: ```python from selfmemory import SelfMemory # Works out of the box! memory = SelfMemory() # Add memories memory.add("I love pizza but hate broccoli", user_id="demo") memory.add("Meeting with Bob tomorrow at 3pm", user_id="demo") # Search memories results = memory.search("pizza", user_id="demo") print(results) ``` ## 🔥 Key Features - **Zero Setup**: Install and start using immediately - no configuration required - **Dual Architecture**: Direct library usage OR managed client with REST API - **Advanced Search**: Semantic similarity with vector embeddings - **Flexible Storage**: File-based or MongoDB backend - **NVIDIA NeMo Integration**: Use Mem0, Redis, or Zep as memory backends via NeMo Agent Toolkit - **Production Ready**: Authentication, API keys, and dashboard integration ## 📚 Documentation Sections ### For Developers - **[Quick Start Guide](./Python/QuickStart.md)**: Get started with SelfMemory in 5 minutes - **[Client Usage](./Python/Client.md)**: Using SelfMemoryClient with the REST API - **[Configuration](./Python/Configuration.md)**: Advanced configuration options ### Integrations - **[NVIDIA NeMo Agent Toolkit](./Integrations/nvidia-nemo.md)**: Use Mem0, Redis, or Zep as memory backends ### For Platform Users - **[API Keys](./Platform/API%20Key%20page.md)**: Managing your API keys ## 🏗️ Architecture SelfMemory provides two usage modes: 1. **Direct Library Usage**: Import and use the `SelfMemory` class directly in your Python code 2. **Client/Server Mode**: Run a REST API server and connect with `SelfMemoryClient` Both modes support: - Semantic search with embeddings (Ollama, OpenAI) - Vector storage (Qdrant, ChromaDB) - Metadata and tagging - User isolation ## 💡 Use Cases - **Personal AI Assistants**: Remember user preferences and conversation history - **Customer Support Bots**: Maintain customer interaction history - **Research Tools**: Store and retrieve research notes - **Team Collaboration**: Shared memory across AI agents ## 🔗 Quick Links - [GitHub Repository](https://github.com/selfmemory/selfmemory) - [Discord Community](https://discord.com/invite/YypBvdUpcc) - [X/Twitter](https://x.com/selfmemoryai) - [Brand Assets (Logos, Slides, etc.)](https://drive.google.com/drive/folders/1paB9DkpPGv58_MC3P5C1el_Bw7lzYh-3?usp=sharing) ## 🤝 Contributing We welcome contributions! Check out our [GitHub repository](https://github.com/selfmemory/selfmemory) to get started. ## 📄 License SelfMemory is licensed under the Apache 2.0 License. --- ## NVIDIA NeMo Agent Toolkit SelfMemory integrates with the [NVIDIA NeMo Agent Toolkit](https://github.com/NVIDIA/NeMo-Agent-Toolkit) memory module, giving you access to NeMo's memory providers (Mem0, Redis, Zep) as alternative backends for your SelfMemory instance. ## Overview The NeMo Agent Toolkit is NVIDIA's open-source framework for building teams of AI agents. Its memory subsystem stores and retrieves conversation history, user preferences, and long-term context across agent interactions. SelfMemory's NeMo adapter wraps NeMo's async `MemoryEditor` interface behind the standard `MemoryBase` API, so you can swap between native SelfMemory and NeMo-backed memory with a config change. ### Supported NeMo Memory Providers | Provider | Package | Description | |----------|---------|-------------| | **Mem0** | `nvidia-nat-mem0ai` | Self-improving memory with semantic understanding | | **Redis** | `nvidia-nat-redis` | Fast in-memory operations with vector search | | **Zep** | `nvidia-nat-zep-cloud` | Cloud-hosted conversation memory | ## Installation ```bash # Install SelfMemory with NeMo support pip install selfmemory[nemo] ``` This installs `nvidia-nat` and its dependencies. You also need the specific provider plugin: ```bash # For Mem0 backend pip install nvidia-nat-mem0ai # For Redis backend pip install nvidia-nat-redis # For Zep backend pip install nvidia-nat-zep-cloud ``` ## Quick Start ### Using the Memory Factory ```python from selfmemory.utils.factory import MemoryFactory # Create a NeMo Mem0-backed memory instance memory = MemoryFactory.create("nemo_mem0", { "api_key": "your-mem0-api-key", }) # Use it like any SelfMemory instance memory.add("I love Italian food", user_id="alice") results = memory.search("food preferences", user_id="alice") ``` ### Using Configuration ```python from selfmemory import SelfMemory from selfmemory.configs.base import SelfMemoryConfig from selfmemory.configs.nemo import NemoMemoryConfig from selfmemory.memory.nemo_adapter import NemoMemoryAdapter config = NemoMemoryConfig( provider="mem0", config={ "api_key": "your-mem0-api-key", }, ) memory = NemoMemoryAdapter(config) memory.add("Meeting with Sarah at 3pm", user_id="bob") ``` ### Using YAML Configuration Add to your `~/.selfmemory/config.yaml`: ```yaml nemo_memory: provider: mem0 config: api_key: ${NEMO_MEMORY_API_KEY} ``` ## Provider Configuration ### Mem0 ```python from selfmemory.utils.factory import MemoryFactory memory = MemoryFactory.create("nemo_mem0", { "api_key": "your-mem0-api-key", "organization": "your-org", "project": "your-project", }) ``` **Environment Variables:** ```bash export NEMO_MEMORY_API_KEY="your-mem0-api-key" ``` ### Redis ```python from selfmemory.utils.factory import MemoryFactory memory = MemoryFactory.create("nemo_redis", { "host": "localhost", "port": 6379, "password": "your-redis-password", }) ``` **Starting Redis with vector search:** ```bash docker run -p 6379:6379 redis/redis-stack:latest ``` ### Zep ```python from selfmemory.utils.factory import MemoryFactory memory = MemoryFactory.create("nemo_zep", { "api_key": "your-zep-api-key", "base_url": "https://api.getzep.com", }) ``` ## API Reference The NeMo adapter implements the full `MemoryBase` interface. All operations work identically to native SelfMemory. ### add() ```python memory.add( "I prefer dark mode in all my apps", user_id="alice", tags="preferences,ui", people_mentioned="Alice", topic_category="preferences", metadata={"source": "chat"}, ) ``` **Parameters:** | Parameter | Type | Description | |-----------|------|-------------| | `messages` | `str`, `dict`, or `list[dict]` | Memory content (string, single message, or conversation) | | `user_id` | `str` | Required. User identifier for isolation | | `tags` | `str` | Optional. Comma-separated tags | | `people_mentioned` | `str` | Optional. Comma-separated names | | `topic_category` | `str` | Optional. Topic category | | `metadata` | `dict` | Optional. Additional key-value metadata | ### search() ```python results = memory.search( "ui preferences", user_id="alice", limit=5, tags=["preferences"], topic_category="preferences", ) for result in results["results"]: print(f"{result['content']} (id: {result['id']})") ``` **Parameters:** | Parameter | Type | Default | Description | |-----------|------|---------|-------------| | `query` | `str` | `""` | Search query | | `user_id` | `str` | required | User identifier | | `limit` | `int` | `10` | Max results | | `tags` | `list[str]` | `None` | Filter by tags | | `people_mentioned` | `list[str]` | `None` | Filter by people | | `topic_category` | `str` | `None` | Filter by category | | `threshold` | `float` | `None` | Min similarity score | **Response:** ```json { "results": [ { "id": "mem_abc123", "content": "I prefer dark mode in all my apps", "metadata": { "data": "I prefer dark mode in all my apps", "user_id": "alice", "tags": "preferences,ui", "topic_category": "preferences" } } ] } ``` ### delete() ```python memory.delete("mem_abc123") ``` ### delete_all() ```python memory.delete_all(user_id="alice") ``` ### get_all() ```python results = memory.get_all(user_id="alice", limit=50) ``` ### health_check() ```python status = memory.health_check() # {"status": "healthy", "provider": "nemo_mem0"} ``` ## Data Model Mapping SelfMemory automatically converts between its data format and NeMo's `MemoryItem` model: | SelfMemory | NeMo MemoryItem | Direction | |------------|-----------------|-----------| | `messages` (str/list) | `memory` + `conversation` | SelfMemory -> NeMo | | `user_id` | `user_id` | Bidirectional | | `tags` (comma-separated) | `tags` (list) | Bidirectional | | `metadata` (dict) | `metadata` (dict) | Bidirectional | | `people_mentioned` | `metadata.people_mentioned` | SelfMemory -> NeMo | | `topic_category` | `metadata.topic_category` | SelfMemory -> NeMo | ## Architecture ``` +---------------------+ +-------------------+ +------------------+ | Your Application | ---> | NemoMemoryAdapter | ---> | NeMo MemoryEditor| | | | (MemoryBase) | | (async) | +---------------------+ +-------------------+ +------------------+ | | sync-to-async bridge +------+------+ (asyncio.to_thread / | | | ThreadPoolExecutor) Mem0 Redis Zep ``` The adapter handles: - **Sync-to-async bridging** — NeMo's `MemoryEditor` is fully async. The adapter runs async operations via `asyncio.run()` or `ThreadPoolExecutor` when inside an existing event loop (e.g., FastAPI). - **Data model translation** — Converts between SelfMemory's string-based tags and NeMo's list-based tags, maps metadata fields, and extracts content from conversation lists. - **User isolation** — Passes `user_id` to all NeMo operations, maintaining SelfMemory's per-user memory isolation. ## Environment Variables | Variable | Description | |----------|-------------| | `NEMO_MEMORY_API_KEY` | API key for the NeMo memory provider | | `NEMO_MEMORY_HOST` | Host URL for the memory provider | These are used as fallbacks when not specified in the config dict. ## Python Version Requirements - SelfMemory core: Python 3.10+ - NeMo integration: Python 3.11+ (required by `nvidia-nat`) The NeMo adapter is an optional dependency. Projects on Python 3.10 can use all other SelfMemory features. ## Comparison with Native SelfMemory | Feature | Native SelfMemory | NeMo Adapter | |---------|-------------------|--------------| | Vector stores | 29 providers (Qdrant, Chroma, Pinecone, etc.) | Depends on NeMo provider | | Embeddings | 15+ providers (Ollama, OpenAI, etc.) | Managed by NeMo provider | | Setup complexity | Configure vector store + embeddings separately | Single provider config | | Async support | Sync API | Sync API (wraps NeMo's async internally) | | Encryption | Built-in Fernet encryption | Depends on provider | | LLM extraction | Optional fact extraction via LLM | Depends on provider | **When to use NeMo adapter:** - You are building agents with NVIDIA's NeMo Agent Toolkit - You want a managed memory service (Mem0 Cloud, Zep Cloud) - You need Redis-based memory for high-throughput scenarios - You want to evaluate different memory backends quickly **When to use native SelfMemory:** - You need fine-grained control over vector stores and embeddings - You want to use local/self-hosted infrastructure - You need built-in encryption - You want LLM-based intelligent fact extraction ## Troubleshooting ### ImportError: No module named 'nat' ```bash pip install selfmemory[nemo] ``` The `nvidia-nat` package is required. Make sure you're on Python 3.11+. ### Provider-specific import errors Each NeMo provider requires its own package: ```bash # Missing Mem0 pip install nvidia-nat-mem0ai # Missing Redis pip install nvidia-nat-redis # Missing Zep pip install nvidia-nat-zep-cloud ``` ### Event loop errors in FastAPI The adapter automatically handles this by detecting running event loops and using a `ThreadPoolExecutor` fallback. If you still encounter issues, ensure you're using the latest version of SelfMemory. ## Next Steps - [Getting Started](../getting-started.md) — Set up SelfMemory - [Configuration Guide](../Python/Configuration.md) — Learn about all config options - [API Reference](../api-reference.md) — Full REST API documentation - [NeMo Agent Toolkit Docs](https://docs.nvidia.com/nemo/agent-toolkit/latest/) — NVIDIA's official documentation --- ## MCP Server Configuration Guide SelfMemory implements the Model Context Protocol (MCP) specification, allowing you to connect your memory system to AI applications like Claude Desktop, VS Code, and other MCP-compatible clients. ## Overview The SelfMemory MCP server provides: - **MCP Compliant**: Full implementation of the MCP API specification - **OAuth 2.1 Authentication**: Secure access using RFC 9728 Protected Resource Metadata - **Streamable HTTP Transport**: Remote server access via HTTP - **Memory Tools**: Search and add memories through standardized MCP tools ## Server URL **Production MCP Endpoint**: `https://mcp.selfmemory.com/mcp` ## Authentication The SelfMemory MCP server uses OAuth 2.1 for secure authentication. The authorization flow is fully automated by MCP clients. ### Authorization Server Discovery The server implements RFC 9728 Protected Resource Metadata, allowing clients to automatically discover: - Authorization server endpoints - Supported scopes - Token requirements **Protected Resource Metadata URL**: `https://mcp.selfmemory.com/.well-known/oauth-protected-resource` ### Required Scopes - `memories:read` - Search and retrieve memories - `memories:write` - Add new memories ## Client Configuration ### Claude Desktop Add the following to your Claude Desktop configuration file: **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json` **Windows**: `%APPDATA%\Claude\claude_desktop_config.json` ```json { "mcpServers": { "selfmemory": { "url": "https://mcp.selfmemory.com/mcp", "type": "http" } } } ``` After saving, restart Claude Desktop. On first use, you'll be prompted to: 1. Authorize the application through your browser 2. Log in to your SelfMemory account 3. Grant access to the requested scopes ### VS Code 1. Install the MCP extension for VS Code 2. Press `Cmd/Ctrl + Shift + P` and select **MCP: Add server...** 3. Select **HTTP** as the transport type 4. Enter the server URL: `https://mcp.selfmemory.com/mcp` 5. Give your server a name (e.g., "SelfMemory") VS Code will handle the OAuth flow automatically when you first connect. ### Other MCP Clients For MCP clients using the Python SDK: ```python from mcp import ClientSession from mcp.client.streamable_http import streamablehttp_client async def connect_to_selfmemory(): async with streamablehttp_client("https://mcp.selfmemory.com/mcp") as (read, write, _): async with ClientSession(read, write) as session: # Initialize connection await session.initialize() # List available tools tools = await session.list_tools() print(f"Available tools: {[tool.name for tool in tools.tools]}") # Call a tool result = await session.call_tool( "search", arguments={"query": "python projects", "retrieval_limit": 5} ) ``` For MCP clients using the TypeScript SDK: ```typescript import { Client } from "@modelcontextprotocol/sdk/client/index.js"; import { StreamableHttpClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js"; const transport = new StreamableHttpClientTransport( new URL("https://mcp.selfmemory.com/mcp") ); const client = new Client( { name: "selfmemory-client", version: "1.0.0" }, { capabilities: {} } ); await client.connect(transport); // List tools const tools = await client.listTools(); console.log("Available tools:", tools); // Call a tool const result = await client.callTool({ name: "search", arguments: { query: "python projects", retrieval_limit: 5 } }); ``` ## Available Tools ### search Search through your memories with advanced filtering. **Parameters**: - `query` (required): Search query string - `retrieval_limit` (optional): Maximum results to return (default: 10) - `tags` (optional): Filter by tags (e.g., `["work", "important"]`) - `people_mentioned` (optional): Filter by people (e.g., `["Alice", "Bob"]`) - `topic_category` (optional): Filter by category (e.g., `"food_preferences"`) - `temporal_filter` (optional): Time-based filter (e.g., `"today"`, `"this_week"`) - `threshold` (optional): Minimum similarity score (0.0-1.0) **Example**: ```json { "name": "search", "arguments": { "query": "machine learning projects", "retrieval_limit": 5, "tags": ["work", "research"] } } ``` ### add Store a new memory with rich metadata. **Parameters**: - `content` (required): The memory content to store - `tags` (optional): Comma-separated tags (e.g., `"work,meeting,important"`) - `people_mentioned` (optional): Comma-separated people names (e.g., `"Alice,Bob"`) - `topic_category` (optional): Topic category (e.g., `"food_preferences"`) - `metadata` (optional): Additional custom metadata as key-value pairs **Example**: ```json { "name": "add", "arguments": { "content": "Discussed new ML model architecture with the team", "tags": "work,research,ml", "people_mentioned": "Sarah,Mike", "topic_category": "work" } } ``` ## Usage Examples ### In Claude Desktop Once configured, you can use your memories naturally in conversations: **User**: "What do I know about Python projects?" **Claude**: *Uses the `search` tool to find relevant memories* **User**: "Remember that I prefer using pytest for testing" **Claude**: *Uses the `add` tool to store this preference* ### In VS Code Copilot Chat After connecting the MCP server, use the `#` symbol to invoke tools: ``` #search machine learning notes ``` or let Copilot automatically use memories when relevant to your coding context. ## Project-Specific Memories SelfMemory is multi-tenant and supports project isolation. Memories are automatically scoped to your selected project based on your OAuth token. To work with different projects: 1. Switch projects in the SelfMemory dashboard 2. Generate a new API key or re-authenticate 3. Your MCP client will access that project's memories ## Troubleshooting ### "Authentication failed" or "Token invalid" - Ensure you've completed the OAuth flow in your browser - Check that your SelfMemory account is active - Try removing and re-adding the MCP server in your client ### "No tools available" - Verify the server URL is correct: `https://mcp.selfmemory.com/mcp` - Check your client's MCP configuration file - Restart your MCP client application ### "Permission denied" errors - Verify your OAuth token has the required scopes (`memories:read`, `memories:write`) - Re-authorize the application to refresh permissions - Check project access in the SelfMemory dashboard ### Connection timeouts - Check your internet connection - Verify the server is accessible: `curl https://mcp.selfmemory.com/.well-known/oauth-protected-resource` - Check for firewall or proxy restrictions ## Security Considerations 1. **OAuth Tokens**: Your access tokens are stored securely by the MCP client 2. **HTTPS Only**: All communication uses encrypted HTTPS 3. **Token Validation**: Every request validates token authenticity and scope 4. **Project Isolation**: You can only access memories within your authorized projects 5. **Audience Validation**: Tokens are bound to the SelfMemory MCP server ## Advanced Configuration ### Custom Scopes If you need to limit access, you can request specific scopes during authorization: - `memories:read` - Read-only access to memories - `memories:write` - Ability to create new memories ### Session Management The server uses stateful sessions with the `Mcp-Session-Id` header. Sessions are: - Automatically created on initialization - Cryptographically secure - User-specific (cannot be hijacked) - Automatically refreshed on reconnection ### Rate Limiting The server implements rate limiting to ensure fair usage: - Search operations: Reasonable limits per user - Add operations: Designed for natural usage patterns - Automatic retry with exponential backoff recommended ## API Reference For detailed information about the MCP protocol and specifications: - [MCP Specification](https://modelcontextprotocol.io/specification/latest) - [MCP Python SDK](https://github.com/modelcontextprotocol/python-sdk) - [SelfMemory API Documentation](https://docs.selfmemory.com) ## Support If you encounter issues: 1. Check the [troubleshooting section](#troubleshooting) above 2. Review server logs in your MCP client 3. Visit [SelfMemory Discord](https://discord.com/invite/YypBvdUpcc) 4. Open an issue on [GitHub](https://github.com/selfmemory/selfmemory) ## Additional Resources - [MCP Server Setup Guide](./MCP_SETUP.md) - Technical implementation details - [OAuth Configuration](./CONFIGURATION.md) - Authentication setup - [Python Client Usage](./Python/Client.md) - SDK integration examples --- ## MCP (Model Context Protocol) Setup Guide This guide explains how to use the MCP authentication implementation with Ory Hydra. ## What Was Implemented ✅ **Protected Resource Metadata Endpoint** - RFC 9728 compliant ✅ **Bearer Token Authentication** - Using Ory Hydra token introspection ✅ **OAuth 2.1 Integration** - Full support for MCP authorization flow ✅ **Configuration Management** - Environment-based MCP settings ## Architecture ``` MCP Client (VS Code/Claude) ↓ ↓ 1. Request /.well-known/oauth-protected-resource ↓ SelfMemory Backend (Port 8081) ↓ 2. Client discovers Ory Hydra ↓ Ory Hydra (Port 4444/4445) ↓ 3. OAuth flow (login via dashboard) ↓ Dashboard (Port 3000) - Kratos login ↓ 4. Token issued ↓ MCP Client → Backend with Bearer token ↓ 5. Token validated via Hydra introspection ↓ Access granted to memory operations ``` ## Configuration ### Required Environment Variables Add these to your `selfmemory-core/.env` file: ```bash # MCP Configuration MCP_ENABLED=true MCP_SERVER_URL=http://localhost:8081 HYDRA_PUBLIC_URL=http://127.0.0.1:4444 HYDRA_ADMIN_URL=http://127.0.0.1:4445 MCP_RESOURCE_DOCUMENTATION_URL=https://github.com/yourusername/selfmemory ``` ### Hydra Configuration Your Ory Hydra must have: 1. **Dynamic Client Registration** enabled (already configured in `ory-infrastructure/configs/hydra.yml`) 2. **Consent/Login URLs** pointing to your dashboard (`http://127.0.0.1:3000/auth/...`) 3. **CORS enabled** for MCP clients ## How It Works ### 1. Discovery Phase When an MCP client connects to `http://localhost:8081`, it: ```http GET /.well-known/oauth-protected-resource HTTP/1.1 Host: localhost:8081 ``` Response: ```json { "resource": "http://localhost:8081", "authorization_servers": ["http://127.0.0.1:4444"], "scopes_supported": ["mcp:tools", "mcp:resources"], "bearer_methods_supported": ["header"], "resource_signing_alg_values_supported": ["RS256"], "resource_documentation": "https://github.com/yourusername/selfmemory" } ``` ### 2. Authorization Phase The MCP client: 1. Discovers Hydra's OAuth endpoints 2. Dynamically registers itself (or uses pre-registration) 3. Initiates OAuth authorization code flow with PKCE 4. User logs in via your dashboard (Kratos) 5. Hydra issues access token ### 3. API Access Phase The MCP client includes the token in requests: ```http POST /api/memories/search HTTP/1.1 Host: localhost:8081 Authorization: Bearer eyJhbGciOiJSUzI1NiIs... Content-Type: application/json { "query": "find my notes about project X" } ``` The backend: 1. Extracts bearer token 2. Calls Hydra introspection endpoint 3. Validates token is active 4. Checks audience matches server URL 5. Extracts user_id from token 6. Processes request with user context ## Testing ### Method 1: Manual Test with curl 1. Get an access token from Hydra (you'll need to complete OAuth flow manually) 2. Test the Protected Resource Metadata: ```bash curl http://localhost:8081/.well-known/oauth-protected-resource ``` 3. Test with bearer token: ```bash curl -H "Authorization: Bearer YOUR_TOKEN" \ http://localhost:8081/api/memories ``` ### Method 2: VS Code MCP Client 1. Install VS Code MCP extension 2. Add MCP server configuration: ```json { "mcpServers": { "selfmemory": { "url": "http://localhost:8081", "type": "http" } } } ``` 3. VS Code will handle the OAuth flow automatically ### Method 3: Claude Desktop Add to Claude Desktop's MCP configuration: ```json { "mcpServers": { "selfmemory": { "command": "mcp-client", "args": ["http://localhost:8081"] } } } ``` ## Next Steps The current implementation provides the **authentication foundation**. To make this a complete MCP server, you'll need to: ### Phase 2: MCP Protocol Handler (Not Yet Implemented) 1. **Add JSON-RPC 2.0 Handler** - Create `/mcp` endpoint - Handle `initialize`, `tools/list`, `tools/call` requests 2. **Wrap Memory Operations as MCP Tools** - `search_memories` tool - `add_memory` tool - `list_memories` tool - `delete_memory` tool 3. **Example MCP Tool Definition**: ```python { "name": "search_memories", "description": "Search through your personal memories", "inputSchema": { "type": "object", "properties": { "query": { "type": "string", "description": "Search query" }, "limit": { "type": "integer", "description": "Maximum results" } }, "required": ["query"] } } ``` Would you like me to implement Phase 2 (MCP Protocol Handler)? ## Security Notes ⚠️ **Important Security Considerations**: 1. **Token Validation**: Always validates tokens via Hydra introspection 2. **Audience Checking**: Verifies token is intended for this server 3. **Scope Validation**: Checks required scopes (implement per-tool) 4. **Project Isolation**: User can only access their projects 5. **HTTPS Required**: Use HTTPS in production ## Troubleshooting ### "Token is not active" - Token expired (check `expires_at`) - Token was revoked - Hydra not running ### "Audience mismatch" - Token was issued for different resource - Check `MCP_SERVER_URL` matches Hydra configuration ### "Authentication service unavailable" - Hydra not running on port 4444/4445 - Network connectivity issues - Check `HYDRA_ADMIN_URL` configuration ### "No Authorization header" - MCP client not sending token - OAuth flow not completed - Check MCP client logs ## Current Limitations 1. **No MCP Protocol Handler**: Only OAuth authentication is implemented 2. **No Tool Definitions**: Memory operations not wrapped as MCP tools yet 3. **No Resource Endpoints**: MCP resources not implemented 4. **Testing Required**: No automated tests for MCP flow ## References - [MCP Specification](https://spec.modelcontextprotocol.io/) - [RFC 9728 - Protected Resource Metadata](https://datatracker.ietf.org/doc/html/rfc9728) - [OAuth 2.1](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-13) - [Ory Hydra Documentation](https://www.ory.sh/docs/hydra/) --- ## API Key Page --- ## Client Usage Guide Learn how to use `SelfMemoryClient` to connect to a SelfMemory REST API server. ## Overview `SelfMemoryClient` allows you to connect to a running SelfMemory server with authentication and API key management. This is ideal for: - Dashboard integrations - Multi-user applications - Remote memory access - Production deployments ## Installation ```bash pip install selfmemory ``` ## Starting the Server First, start the SelfMemory server (from selfmemory-core directory): ```bash cd server/ python main.py ``` The server will run on `http://localhost:8081` by default. ## Basic Client Usage ### Initialize the Client ```python from selfmemory import SelfMemoryClient # Connect to the server client = SelfMemoryClient( api_key="sk_im_dxNssuz8hFLfEl6vYofXgbTO9m8awbPCT8C9xWlR", host="http://localhost:8081" ) ``` ### Understanding the Message Format The server expects memories in a specific format with `messages` structure. Here's the correct way to add memories: ```python #!/usr/bin/env python3 """ Fixed SelfMemory Client Example A working example that matches the server's expected data format. The server expects 'messages' format, so we convert our memory content accordingly. """ import os from selfmemory import SelfMemoryClient def main(): # Initialize client with explicit host to avoid discovery issues client = SelfMemoryClient( api_key="sk_im_dxNssuz8hFLfEl6vYofXgbTO9m8awbPCT8C9xWlR", host="http://localhost:8081" ) print("🚀 Starting SelfMemory Client Example with Fixed Format") print("=" * 60) # Add memories using the correct format that the server expects print("\n📝 Adding memories...") # Memory 1: BMW bike memory1_data = { "messages": [ { "role": "user", "content": "I have a BMW bike." } ], "metadata": { "tags": "personal,vehicle", "people_mentioned": "", "topic_category": "personal" } } # Use the client's underlying httpx client to send the correct format try: response1 = client.client.post("/api/memories", json=memory1_data) response1.raise_for_status() result1 = response1.json() print(f"✅ Added memory 1: {result1.get('message', 'Success')}") except Exception as e: print(f"❌ Failed to add memory 1: {e}") # Memory 2: Amazon location memory2_data = { "messages": [ { "role": "user", "content": "I live in Amazon" } ], "metadata": { "tags": "personal,location", "people_mentioned": "", "topic_category": "personal" } } try: response2 = client.client.post("/api/memories", json=memory2_data) response2.raise_for_status() result2 = response2.json() print(f"✅ Added memory 2: {result2.get('message', 'Success')}") except Exception as e: print(f"❌ Failed to add memory 2: {e}") # Search memories using the client's search method print("\n🔍 Searching memories...") try: search_results = client.search("bike") print(f"📋 Search results for 'bike': {len(search_results.get('results', []))} found") if search_results.get('results'): for i, result in enumerate(search_results['results'][:2], 1): content = result.get('content', result.get('memory_content', 'No content')) score = result.get('score', 'N/A') print(f" {i}. {content}... (score: {score})") else: print(" No results found") except Exception as e: print(f"❌ Search failed: {e}") # Get all memories print("\n📚 Getting all memories...") try: all_memories = client.get_all() total_count = len(all_memories.get('results', [])) print(f"📊 Total memories: {total_count}") if all_memories.get('results'): for i, memory in enumerate(all_memories['results'][:3], 1): content = memory.get('content', memory.get('memory_content', 'No content')) print(f" {i}. {content}...") except Exception as e: print(f"❌ Failed to get memories: {e}") # Test search with different queries print("\n🔍 Testing additional searches...") test_queries = ["Amazon", "personal", "location"] for query in test_queries: try: results = client.search(query) count = len(results.get('results', [])) print(f" '{query}': {count} results") except Exception as e: print(f" '{query}': Error - {e}") # Clean up (optional) print("\n🧹 Cleanup options:") print(" Uncomment the line below to delete all memories") # client.delete_all() # Close client client.close() print("\n✅ Client closed successfully") print("🎉 Example completed!") if __name__ == "__main__": main() ``` ## Helper Functions You can create helper functions to make memory creation easier: ```python def create_memory_with_messages_format(content: str, tags: str = "", people: str = "", category: str = ""): """Helper function to create memory data in the server's expected format.""" return { "messages": [ { "role": "user", "content": content } ], "metadata": { "tags": tags, "people_mentioned": people, "topic_category": category } } def add_memory_direct(client, content: str, tags: str = "", people: str = "", category: str = ""): """Helper function to add memory using the correct server format.""" memory_data = create_memory_with_messages_format(content, tags, people, category) try: response = client.client.post("/api/memories", json=memory_data) response.raise_for_status() result = response.json() return {"success": True, "result": result} except Exception as e: return {"success": False, "error": str(e)} ``` ## Client Operations ### Searching Memories ```python # Basic search results = client.search("meeting notes") # Process results for result in results.get('results', []): content = result.get('content', result.get('memory_content')) score = result.get('score') print(f"Memory: {content} (Score: {score})") ``` ### Getting All Memories ```python # Get all memories all_memories = client.get_all() # Iterate through memories for memory in all_memories.get('results', []): print(memory.get('content')) ``` ### Deleting Memories ```python # Delete all memories client.delete_all() ``` ### Closing the Client ```python # Always close the client when done client.close() ``` ## API Key Management To get your API key: 1. Log in to the SelfMemory dashboard 2. Navigate to the API Keys page 3. Generate a new API key 4. Copy and use it in your client initialization See the [API Keys documentation](../Platform/API%20Key%20page.md) for more details. ## Error Handling Always wrap client operations in try-except blocks: ```python try: results = client.search("query") print(f"Found {len(results.get('results', []))} results") except Exception as e: print(f"Error: {e}") ``` ## Next Steps - Explore [Configuration Options](./Configuration.md) for advanced setups - Learn about [API Key Management](../Platform/API%20Key%20page.md) - Return to [Quick Start Guide](./QuickStart.md) for basic usage --- ## Configuration Guide(Python) Learn how to configure SelfMemory for different use cases and environments. ## Configuration Methods SelfMemory can be configured in three ways: 1. **Python Dictionary** - Pass config directly to `SelfMemory(config=...)` 2. **YAML File** - Create `~/.selfmemory/config.yaml` 3. **Environment Variables** - Set environment variables ## Complete Configuration Example ```python from selfmemory import SelfMemory config = { "vector_store": { "provider": "qdrant", "config": { "collection_name": "my_memories", "embedding_model_dims": 768, "host": "localhost", "port": 6333 } }, "embedding": { "provider": "ollama", "config": { "model": "nomic-embed-text", "ollama_base_url": "http://localhost:11434" } }, "storage": { "type": "file", # or "mongodb" "path": "~/.selfmemory/data" }, "auth": { "type": "simple", # or "oauth", "api_key" "default_user": "user123" } } memory = SelfMemory(config=config) ``` ## Vector Store Configuration ### Qdrant (Recommended) ```python config = { "vector_store": { "provider": "qdrant", "config": { "collection_name": "memories", "embedding_model_dims": 768, # nomic-embed-text dimension "host": "localhost", "port": 6333, "url": None, # Optional: use URL instead of host:port "api_key": None # Optional: for Qdrant Cloud } } } ``` **Starting Qdrant:** ```bash docker run -p 6333:6333 qdrant/qdrant ``` ### ChromaDB ```python config = { "vector_store": { "provider": "chroma", "config": { "collection_name": "memories", "persist_directory": "~/.selfmemory/chroma" } } } ``` ## Embedding Configuration ### Ollama (Recommended for Local) ```python config = { "embedding": { "provider": "ollama", "config": { "model": "nomic-embed-text", "ollama_base_url": "http://localhost:11434" } } } ``` **Starting Ollama:** ```bash ollama serve ollama pull nomic-embed-text ``` **Available Models:** - `nomic-embed-text` (768 dims) - Recommended - `mxbai-embed-large` (1024 dims) - `all-minilm` (384 dims) - Faster, smaller ### OpenAI ```python config = { "embedding": { "provider": "openai", "config": { "model": "text-embedding-3-small", "api_key": "sk-..." # Or set OPENAI_API_KEY env var } } } ``` **Available Models:** - `text-embedding-3-small` (1536 dims) - Recommended - `text-embedding-3-large` (3072 dims) - More powerful - `text-embedding-ada-002` (1536 dims) - Legacy ## Storage Configuration ### File-Based Storage (Default) ```python config = { "storage": { "type": "file", "path": "~/.selfmemory/data" } } ``` **Advantages:** - Zero setup required - Perfect for development and testing - Easy to backup and migrate ### MongoDB Storage ```python config = { "storage": { "type": "mongodb", "uri": "mongodb://localhost:27017/selfmemory" } } ``` **Starting MongoDB:** ```bash docker run -p 27017:27017 mongo:latest ``` **Advantages:** - Multi-user support - Better performance at scale - Production-ready - Built-in replication and backup ## Authentication Configuration ### Simple Auth (Development) ```python config = { "auth": { "type": "simple", "default_user": "demo_user" } } ``` ### API Key Auth (Production) ```python config = { "auth": { "type": "api_key", "require_api_key": True } } ``` ### OAuth (Dashboard Integration) ```python config = { "auth": { "type": "oauth", "google_client_id": "your-client-id", "google_client_secret": "your-secret" } } ``` ## NVIDIA NeMo Memory Backend (Optional) Use NeMo Agent Toolkit providers (Mem0, Redis, Zep) instead of the native vector store: ```python config = { "nemo_memory": { "provider": "mem0", # or "redis", "zep" "config": { "api_key": "your-api-key" } } } ``` Or use the `MemoryFactory` directly: ```python from selfmemory.utils.factory import MemoryFactory memory = MemoryFactory.create("nemo_mem0", {"api_key": "your-key"}) ``` Requires `pip install selfmemory[nemo]` and Python 3.11+. See the full [NVIDIA NeMo Integration Guide](../Integrations/nvidia-nemo.md). ## YAML Configuration File Create `~/.selfmemory/config.yaml`: ```yaml vector_store: provider: qdrant config: collection_name: memories embedding_model_dims: 768 host: localhost port: 6333 embedding: provider: ollama config: model: nomic-embed-text ollama_base_url: http://localhost:11434 storage: type: file path: ~/.selfmemory/data auth: type: simple default_user: user123 ``` Then use it: ```python from selfmemory import SelfMemory # Automatically loads from ~/.selfmemory/config.yaml memory = SelfMemory() ``` ## Environment Variables ```bash # Storage backend export SELFMEMORY_STORAGE_TYPE="file" # or "mongodb" export SELFMEMORY_DATA_DIR="~/.selfmemory" export MONGODB_URI="mongodb://localhost:27017/selfmemory" # Qdrant settings export QDRANT_HOST="localhost" export QDRANT_PORT="6333" export QDRANT_API_KEY="" # Optional # Ollama settings export OLLAMA_BASE_URL="http://localhost:11434" export OLLAMA_MODEL="nomic-embed-text" # OpenAI settings export OPENAI_API_KEY="sk-..." export OPENAI_MODEL="text-embedding-3-small" # Server settings (when running REST API) export SELFMEMORY_HOST="0.0.0.0" export SELFMEMORY_PORT="8081" ``` ## Configuration Priority SelfMemory loads configuration in this order (later overrides earlier): 1. Default values 2. YAML config file (`~/.selfmemory/config.yaml`) 3. Environment variables 4. Python config dictionary passed to `SelfMemory(config=...)` ## Common Configuration Patterns ### Development Setup ```python config = { "vector_store": {"provider": "qdrant"}, "embedding": {"provider": "ollama"}, "storage": {"type": "file"}, "auth": {"type": "simple"} } ``` ### Production Setup ```python config = { "vector_store": { "provider": "qdrant", "config": { "url": "https://your-cluster.qdrant.cloud", "api_key": os.getenv("QDRANT_API_KEY") } }, "embedding": { "provider": "openai", "config": { "api_key": os.getenv("OPENAI_API_KEY") } }, "storage": { "type": "mongodb", "uri": os.getenv("MONGODB_URI") }, "auth": { "type": "api_key" } } ``` ### Local Testing (Zero Config) ```python # Uses all defaults - perfect for quick testing memory = SelfMemory() ``` ## Troubleshooting ### Connection Issues ```python # Test Qdrant connection import requests response = requests.get("http://localhost:6333/health") print(response.json()) # Should return {"status": "ok"} # Test Ollama connection response = requests.get("http://localhost:11434/api/tags") print(response.json()) # Should list available models ``` ### Dimension Mismatch Ensure your vector store dimension matches your embedding model: - `nomic-embed-text`: 768 dims - `text-embedding-3-small`: 1536 dims - `text-embedding-3-large`: 3072 dims ```python config = { "vector_store": { "config": { "embedding_model_dims": 768 # Must match model! } } } ``` ## Next Steps - Return to [Quick Start Guide](./QuickStart.md) - Learn about [Client Usage](./Client.md) - Explore [API Keys](../Platform/API%20Key%20page.md) --- ## Quick Start Guide Get started with SelfMemory in 5 minutes! ## Installation ```bash pip install selfmemory ``` ## Basic Usage with Qdrant + Ollama This example shows the recommended setup using Qdrant for vector storage and Ollama for embeddings: ### 1. Start Required Services ```bash # Start Qdrant (vector database) docker run -p 6333:6333 qdrant/qdrant # Start Ollama and pull embedding model ollama serve ollama pull nomic-embed-text ``` ### 2. Configure SelfMemory ```python from selfmemory import SelfMemory config = { "vector_store": { "provider": "qdrant", "config": { "collection_name": "new__memories", "embedding_model_dims": 768, "host": "localhost", "port": 6333 # Default Qdrant Docker port } }, "embedding": { "provider": "ollama", "config": { "model": "nomic-embed-text", "ollama_base_url": "http://localhost:11434" } } } memory = SelfMemory(config=config) ``` ### 3. Add and Search Memories ```python # Add memories result = memory.add("I have a BMW bike.", user_id="demo") result = memory.add("I live in Amazon", user_id="demo") # Search memories results = memory.search("bike", user_id="demo") print(results) ``` ## Zero-Config Usage For quick testing, SelfMemory works without any configuration: ```python from selfmemory import SelfMemory # No config needed - uses defaults memory = SelfMemory() # Add memories with metadata memory.add( "I love pizza but hate broccoli", user_id="demo", tags="food,preferences" ) memory.add( "Meeting with Bob and Carol about Q4 planning tomorrow at 3pm", user_id="demo", tags="work,meeting", people_mentioned="Bob,Carol", topic_category="planning" ) # Search memories results = memory.search("pizza", user_id="demo") for result in results["results"]: print(f"Memory: {result['content']}") print(f"Score: {result['score']}") # Health check health = memory.health_check() print(f"Status: {health['status']}") ``` ## Core Operations ### Adding Memories ```python # Simple add memory.add("Some memory content", user_id="user123") # With metadata memory.add( content="Product launch meeting next week", user_id="user123", tags="work,important", people_mentioned="Alice,Bob", topic_category="business" ) ``` ### Searching Memories ```python # Basic search results = memory.search("meeting", user_id="user123") # Search with limit results = memory.search("meeting", user_id="user123", limit=5) # Search by tags results = memory.search_by_tags( ["work", "important"], user_id="user123", match_all=True ) # Search by people results = memory.search_by_people( ["Alice", "Bob"], user_id="user123" ) ``` ### Getting All Memories ```python # Get all memories for a user memories = memory.get_all(user_id="user123", limit=100) ``` ### Deleting Memories ```python # Delete specific memory result = memory.delete(memory_id="memory_123", user_id="user123") # Delete all memories for a user result = memory.delete_all(user_id="user123") ``` ## Next Steps - Learn about [Client Usage](./Client.md) for REST API integration - Explore [Configuration Options](./Configuration.md) for advanced setups - Check out [API Keys](../Platform/API%20Key%20page.md) for platform usage --- ## API Reference The SelfMemory REST API lets you store, search, and manage memories programmatically. The server runs on `http://localhost:8081` by default. ## Authentication All API requests require authentication via one of these methods: | Method | Header | Use Case | |--------|--------|----------| | API Key | `Authorization: Bearer sk_im_...` | SDK and programmatic access | | Session Cookie | `ory_kratos_session` | Dashboard and browser access | | OAuth 2.1 Token | `Authorization: Bearer ` | MCP and third-party integrations | API keys are scoped to a single project. Generate them from the dashboard under **API Keys**. --- ## Memories ### Create Memory ``` POST /api/memories ``` Store a new memory with optional metadata. **Request Body:** ```json { "messages": [ { "role": "user", "content": "I have a meeting with Alice on Friday" } ], "metadata": { "tags": "work,meeting", "people_mentioned": "Alice", "topic_category": "schedule" } } ``` **Response:** ```json { "message": "Memory created successfully", "memory_id": "mem_abc123" } ``` --- ### List Memories ``` GET /api/memories ``` Retrieve all memories for the authenticated user/project. **Query Parameters:** | Parameter | Type | Description | |-----------|------|-------------| | `limit` | integer | Max results to return | | `offset` | integer | Pagination offset | | `user_id` | string | Filter by user ID | | `project_id` | string | Filter by project ID | **Response:** ```json { "results": [ { "id": "mem_abc123", "content": "I have a meeting with Alice on Friday", "metadata": { "tags": "work,meeting" }, "created_at": "2026-02-22T10:30:00Z" } ] } ``` --- ### Get Memory ``` GET /api/memories/{memory_id} ``` Retrieve a single memory by ID. --- ### Search Memories ``` POST /api/memories/search ``` Semantic search across memories using AI-powered embeddings. **Request Body:** ```json { "query": "meetings this week", "filters": {}, "project_id": "proj_xyz" } ``` **Response:** ```json { "results": [ { "content": "I have a meeting with Alice on Friday", "score": 0.92, "metadata": { "tags": "work,meeting" } } ] } ``` --- ### Delete Memory ``` DELETE /api/memories/{memory_id} ``` Delete a specific memory. Requires write permission. --- ### Delete All Memories ``` DELETE /api/memories ``` Delete all memories for the current project scope. This action is irreversible. --- ## Organizations ### Create Organization ``` POST /api/organizations ``` **Request Body:** ```json { "name": "My Team" } ``` --- ### List Organizations ``` GET /api/organizations ``` Returns all organizations the authenticated user belongs to, along with their role. --- ### Get Organization ``` GET /api/organizations/{org_id} ``` --- ### Delete Organization ``` DELETE /api/organizations/{org_id} ``` Deletes the organization and cascades to all projects, members, invitations, and API keys. Only the owner can perform this action. --- ### List Members ``` GET /api/organizations/{org_id}/members ``` --- ### Update Member Role ``` PUT /api/organizations/{org_id}/members/{user_id} ``` **Request Body:** ```json { "role": "admin" } ``` --- ### Remove Member ``` DELETE /api/organizations/{org_id}/members/{user_id} ``` --- ### Invite User ``` POST /api/organizations/{org_id}/invitations ``` **Request Body:** ```json { "email": "user@example.com", "role": "member", "projectIds": ["proj_xyz"], "projectRoles": { "proj_xyz": "editor" } } ``` --- ### Transfer Ownership ``` PUT /api/organizations/{org_id}/transfer-ownership ``` **Request Body:** ```json { "new_owner_id": "user_abc" } ``` --- ## Projects ### Create Project ``` POST /api/projects ``` **Request Body:** ```json { "name": "My Project", "organization_id": "org_abc" } ``` --- ### List Projects ``` GET /api/projects ``` Returns all projects the user owns or is a member of. --- ### Get Project ``` GET /api/projects/{project_id} ``` --- ### Delete Project ``` DELETE /api/projects/{project_id} ``` Cascades to members, invitations, API keys, and memories. --- ### List Project Members ``` GET /api/projects/{project_id}/members ``` --- ### Add Project Member ``` POST /api/projects/{project_id}/members ``` --- ### Update Project Member Role ``` PUT /api/projects/{project_id}/members/{user_id} ``` --- ### Remove Project Member ``` DELETE /api/projects/{project_id}/members/{user_id} ``` --- ### Invite to Project ``` POST /api/projects/{project_id}/invitations ``` --- ## API Keys ### Create API Key ``` POST /api/projects/{project_id}/api-keys ``` **Request Body:** ```json { "name": "Production Key", "permissions": ["read", "write"], "expires_in_days": 90 } ``` **Response:** ```json { "api_key": "sk_im_abc123...", "prefix": "sk_im_abc", "name": "Production Key", "permissions": ["read", "write"] } ``` :::caution The full API key is only returned once at creation. Store it securely. ::: --- ### List API Keys ``` GET /api/projects/{project_id}/api-keys ``` Returns all keys for the project (secrets are redacted). --- ### Delete API Key ``` DELETE /api/projects/{project_id}/api-keys/{key_id} ``` --- ## Invitations ### List Pending Invitations ``` GET /api/invitations/pending ``` --- ### Get Invitation Details ``` GET /api/invitations/{token} ``` No authentication required — the token itself serves as authorization. --- ### Accept Invitation ``` POST /api/invitations/{token}/accept ``` --- ## Notifications ### List Notifications ``` GET /api/notifications ``` Returns the last 50 notifications with unread count. --- ### Mark as Read ``` PUT /api/notifications/{notification_id}/read ``` --- ### Mark All as Read ``` PUT /api/notifications/read-all ``` --- ## User Account ### Get Current User ``` GET /api/users/me ``` --- ### Delete Account ``` DELETE /api/users/me ``` Deactivates the account and cascades cleanup. The user must not be the sole owner of any organization. --- ## Health Checks | Endpoint | Purpose | |----------|---------| | `GET /health` | Full system health (DB, memory, disk) | | `GET /health/live` | Kubernetes liveness probe | | `GET /health/ready` | Kubernetes readiness probe | --- ## Rate Limiting The API enforces rate limits on the following operations: - Memory creation - Memory search - Organization creation - Project creation - Invitation sending When rate limited, the API returns `429 Too Many Requests`. Retry after the duration specified in the `Retry-After` header. --- ## Errors All error responses follow a consistent format: ```json { "detail": "Error description" } ``` | Status Code | Meaning | |-------------|---------| | `400` | Bad request — invalid parameters | | `401` | Unauthorized — missing or invalid auth | | `403` | Forbidden — insufficient permissions | | `404` | Not found | | `429` | Rate limited | | `500` | Internal server error | --- ## Getting Started Get up and running with SelfMemory in under 5 minutes. ## Installation ```bash pip install selfmemory ``` ## Option 1: Direct Library Usage Use SelfMemory directly in your Python code — no server needed. ### Zero-Config (Quickest) ```python from selfmemory import SelfMemory memory = SelfMemory() # Add memories memory.add("I love pizza but hate broccoli", user_id="demo") memory.add("Meeting with Bob tomorrow at 3pm", user_id="demo") # Search memories results = memory.search("pizza", user_id="demo") for result in results["results"]: print(f"{result['content']} (score: {result['score']})") ``` ### With Qdrant + Ollama (Recommended) For production use, run Qdrant for vector storage and Ollama for local embeddings: ```bash # Start Qdrant docker run -p 6333:6333 qdrant/qdrant # Start Ollama and pull an embedding model ollama serve ollama pull nomic-embed-text ``` ```python from selfmemory import SelfMemory config = { "vector_store": { "provider": "qdrant", "config": { "collection_name": "memories", "embedding_model_dims": 768, "host": "localhost", "port": 6333 } }, "embedding": { "provider": "ollama", "config": { "model": "nomic-embed-text", "ollama_base_url": "http://localhost:11434" } } } memory = SelfMemory(config=config) ``` ## Option 2: Client + Server Mode For multi-user apps, dashboards, and production deployments, run the SelfMemory server and connect via the client. ### Start the Server ```bash cd selfmemory-core/server/ python main.py ``` The server runs on `http://localhost:8081` by default. ### Connect with the Python Client ```python from selfmemory import SelfMemoryClient client = SelfMemoryClient( api_key="your-api-key", host="http://localhost:8081" ) # Search memories results = client.search("meeting notes") # Get all memories all_memories = client.get_all() # Close when done client.close() ``` ### Connect with the TypeScript Client ```typescript import { SelfMemoryClient } from '@selfmemory/client' const client = new SelfMemoryClient({ apiKey: 'your-api-key', host: 'http://localhost:8081' }) // Add a memory await client.add( [{ role: 'user', content: 'Remember this for me' }], { metadata: { tags: 'important' } } ) // Search const results = await client.search('what should I remember?') ``` ## Get Your API Key 1. Sign up at [selfmemory.com](https://selfmemory.com) 2. Create a project in the dashboard 3. Go to **API Keys** and generate a new key 4. Use it in your client initialization See the [API Keys documentation](./Platform/API%20Key%20page.md) for details. ## Next Steps - **[Python SDK → QuickStart](./Python/QuickStart.md)** — Full walkthrough with code examples - **[Python SDK → Client](./Python/Client.md)** — REST API client usage - **[Python SDK → Configuration](./Python/Configuration.md)** — Advanced configuration - **[API Reference](/api-reference)** — Complete REST API documentation - **[SDKs](/sdks)** — All available SDKs --- ## SDKs SelfMemory provides official SDKs for Python and TypeScript/JavaScript. ## Python SDK The Python SDK is the primary client library. It supports both direct library usage and REST API client mode. ### Installation ```bash pip install selfmemory ``` ### Direct Usage (No Server) ```python from selfmemory import SelfMemory memory = SelfMemory() memory.add("I prefer dark mode for all apps", user_id="user_1") results = memory.search("UI preferences", user_id="user_1") ``` ### Client Mode (REST API) ```python from selfmemory import SelfMemoryClient client = SelfMemoryClient( api_key="sk_im_your_key_here", host="http://localhost:8081" ) # Add memory client.add( memory_content="Sprint planning is every Monday at 10am", tags="work,recurring", metadata={"type": "schedule"} ) # Search results = client.search("when is sprint planning?") # Get all memories all_memories = client.get_all() # Delete a memory client.delete(memory_id="mem_abc123") # Close the client client.close() ``` ### Key Classes | Class | Purpose | |-------|---------| | `SelfMemory` | Direct library usage — no server required | | `SelfMemoryClient` | REST API client — connects to a running server | ### Resources - [Quick Start Guide](/Python/QuickStart) - [Client Usage Guide](/Python/Client) - [Configuration Options](/Python/Configuration) - [PyPI Package](https://pypi.org/project/selfmemory/) --- ## TypeScript / JavaScript SDK The TypeScript SDK is available for Node.js and browser environments. ### Installation ```bash npm install @selfmemory/client ``` ### Usage ```typescript import { SelfMemoryClient } from '@selfmemory/client' const client = new SelfMemoryClient({ apiKey: 'sk_im_your_key_here', host: 'http://localhost:8081' }) // Health check await client.ping() // Add a memory await client.add( [{ role: 'user', content: 'Remember to review the PR by Friday' }], { metadata: { tags: 'work,code-review' } } ) // Search memories const results = await client.search('pending code reviews') // Get all memories const allMemories = await client.get_all() ``` ### Key Methods | Method | Description | |--------|-------------| | `ping()` | Health check | | `add(messages, options)` | Store a new memory | | `search(query, options)` | Semantic search across memories | | `get_all(options)` | Retrieve all memories | ### Resources - [npm Package](https://www.npmjs.com/package/@selfmemory/client) - [GitHub Repository](https://github.com/SelfMemory/SelfMemory) --- ## MCP Integration SelfMemory supports the [Model Context Protocol (MCP)](https://modelcontextprotocol.io), allowing AI assistants like Claude, Cursor, and others to read and write memories directly. ### Setup Add SelfMemory as an MCP server in your AI tool's configuration: ```json { "mcpServers": { "selfmemory": { "url": "http://localhost:8081/mcp", "headers": { "Authorization": "Bearer sk_im_your_key_here" } } } } ``` ### Resources - [MCP Setup Guide](https://docs.selfmemory.com) - [Model Context Protocol Spec](https://modelcontextprotocol.io) --- ## REST API All SDKs are thin wrappers around the SelfMemory REST API. If your language isn't covered, you can call the API directly. ```bash # Add a memory curl -X POST http://localhost:8081/api/memories \ -H "Authorization: Bearer sk_im_your_key_here" \ -H "Content-Type: application/json" \ -d '{ "messages": [{"role": "user", "content": "My favorite color is blue"}], "metadata": {"tags": "personal,preferences"} }' # Search memories curl -X POST http://localhost:8081/api/memories/search \ -H "Authorization: Bearer sk_im_your_key_here" \ -H "Content-Type: application/json" \ -d '{"query": "favorite color"}' ``` See the full [API Reference](/api-reference) for all available endpoints.