engram
Supports ingesting notes and content from Obsidian vaults into the semantic memory store.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@engramremember that my dog's name is Max"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
What is Engram?
Engram is a personal knowledge base that stores your notes, conversations, documents, and web pages as vector embeddings — then lets any MCP-compatible AI assistant (Claude, Cursor, Windsurf, etc.) search and recall them by meaning, not just keywords. Everything lives in a PostgreSQL database you control, runs locally or in the cloud, and costs near-zero to self-host.
Related MCP server: mcp-recall
Features
Hybrid Search — Combines vector similarity (pgvector HNSW) with PostgreSQL full-text BM25, fused via Reciprocal Rank Fusion
MCP Server — Any MCP-compatible client can store, search, and manage memories over HTTP
REST API — Full CRUD + search, with OpenAPI docs at
/api/docs/Multi-format Ingestion — Ingest PDFs, DOCX, TXT, Markdown, URLs, and Obsidian vaults
Auto-Enrichment — Optional LLM-powered tagging, entity extraction, and memory decay
React Dashboard — Browse, search, and visualize your memory graph
Privacy-First — Runs 100% locally with Ollama; no data leaves your machine
Pluggable Embeddings — Ollama (default, free), OpenRouter, or bring your own provider
Architecture
┌──────────────────────────────┐
│ AI Clients │
│ (Claude, Cursor, Windsurf) │
└─────────────┬────────────────┘
│ MCP / REST
▼
┌──────────────────────────────────────┐
│ MCP Server (FastMCP :8080) │
│ REST API (Django DRF :8000) │
│ Dashboard (React + Vite :5173) │
└─────────────┬────────────────────────┘
│
┌──────────┴──────────┐
│ Application Layer │
│ Embedder ─→ Ollama │
│ Auto-Tagger │
│ Entity Extractor │
│ Memory Decay │
└──────────┬──────────┘
│
┌──────────▼──────────┐
│ PostgreSQL 16 │
│ + pgvector (768d) │
│ + Full-text search │
│ + HNSW index │
└──────────────────────┘Quick Start
Prerequisites: Python 3.12+, PostgreSQL 16 with pgvector, Ollama (or Docker)
# Install from PyPI
pip install engram-semantic
# Or clone for development
git clone https://github.com/jblacketter/engram.git && cd engram
# 2. Start database + Ollama via Docker
docker compose up -d
# 3. Pull the embedding model
ollama pull nomic-embed-text
# 4. Install Python dependencies
pip install -e ".[dev]"
# 5. Copy environment config
cp .env.example .env
# 6. Run migrations and start the server
python manage.py migrate
python manage.py runserverThe API is now live at http://localhost:8000/api/ and docs at http://localhost:8000/api/docs/.
Start the MCP server (separate terminal):
python -m mcp_serverStart the frontend (separate terminal):
cd frontend && npm install && npm run devDashboard at http://localhost:5173.
Connecting AI Clients
Claude Desktop
Add to ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"engram": {
"url": "http://localhost:8080/mcp"
}
}
}Claude Code
claude mcp add engram http://localhost:8080/mcpCursor / Windsurf
Add to your MCP settings:
{
"mcpServers": {
"engram": {
"url": "http://localhost:8080/mcp"
}
}
}See docs/connecting-clients.md for authenticated setups and advanced config.
API Reference
REST Endpoints
Method | Endpoint | Description |
|
| Health check |
|
| List memories (paginated) |
|
| Create a memory |
|
| Get memory by UUID |
|
| Update memory |
|
| Delete memory |
|
| Hybrid semantic + keyword search |
|
| Memory statistics |
|
| List all tags |
|
| Ingest a file (PDF, DOCX, TXT, etc.) |
|
| Scrape and ingest a URL |
|
| Batch ingest files and URLs |
Auth: Authorization: Bearer <REST_API_KEY> (disabled when env var is empty).
MCP Tools
Tool | Description |
| Store a new memory with optional tags and importance |
| Retrieve a memory by UUID |
| Update content, tags, or importance |
| Delete a memory |
| Hybrid search with configurable semantic/keyword weight, filterable by |
| Find semantically similar memories, filterable by |
| List recent memories, optionally filtered by |
| Fetch and ingest a URL |
| Ingest a base64-encoded file |
| System statistics |
Scoping memories across domains
A single Engram instance can host memories from multiple domains (e.g. QA-tool output and personal notes) without cross-contamination, using tag-based soft scoping. The convention is documented here so any client can follow it.
The convention
Every write should set two things:
A scoping tag in the
tagsfield —domain:<name>, optionally refined withproject:<slug>. Examples:tags=["domain:qa", "project:my-app"]tags=["domain:personal"]
The
sourcefield — already part of the schema — to identify the writer (e.g."aegis","qaagent","mcp","manual").sourceis a distinct top-level field, not a tag; the two are complementary.
Reading with scope
The MCP tools and REST search honor these on read. Examples:
# MCP
await search_brain("flaky test", tags=["domain:qa"])
await find_related(memory_id, tags=["domain:qa"])
await list_recent_memories(tags=["domain:qa"])
# REST
POST /api/search/ {"query": "flaky test", "tags": ["domain:qa"]}Scoped read surfaces (filterable)
The following read surfaces accept tags and/or source filters, so callers
that pass them can stay inside one domain:
Surface |
|
|
MCP | yes | yes |
MCP | yes | yes |
MCP | yes | yes |
REST | yes | yes |
Residual surfaces (intentionally unscoped)
These surfaces return data across all domains regardless of caller. They are acceptable for a single-user instance; if you ever expose Engram beyond a trusted boundary, treat them as gaps to close:
REST
GET /api/memories/— paginated memory list, no filter args.REST
GET /api/memories/<id>/— direct fetch by UUID; no tag check.REST
GET /api/stats/— counts and date range across all memories.REST
GET /api/tags/— full tag enumeration across all domains.MCP
get_stats— same as the REST stats endpoint.MCP
get_memory— direct UUID fetch; no tag check.React dashboard — single-user view that displays all memories, recent-feed, and analytics across all domains.
Limits of soft scoping
Discipline-based. Engram does not enforce that writes carry a domain tag. Clients that omit it produce un-scopable memories.
No per-user auth. The instance is single-user; auth is global API-key.
No migrations involved. No
workspace/tenantfield exists. If you later need hard isolation, options are: run two Engram instances on separate databases, or add aworkspaceschema column.
Project Structure
engram/
├── api/ # REST API (DRF views, serializers, auth)
├── core/ # Data models, services (memory CRUD, search)
├── embeddings/ # Embedding providers (Ollama, OpenRouter)
├── intelligence/ # Auto-tagger, entity extraction, decay, reports
├── ingestion/ # File, URL, batch, and Obsidian importers
├── mcp_server/ # FastMCP server with tool definitions
├── engram/ # Django project settings and URL config
├── frontend/ # React + TypeScript + Tailwind SPA
├── docker/ # Entrypoint scripts, pgvector init SQL
├── nginx/ # Reverse proxy config (production)
├── docs/ # Extended documentation
├── tests/ # Test suite
├── Dockerfile # Django production image
├── Dockerfile.mcp # MCP server image
├── docker-compose.yml # Dev: PostgreSQL + Ollama
└── pyproject.toml # Python package configConfiguration
Key environment variables (see .env.example for the full list):
Variable | Default | Description |
| — | Django secret key |
|
| Settings module |
|
| Database name |
|
| Database host |
|
| Ollama API URL |
|
| Embedding model |
|
| Chat model for enrichment |
| — | Fallback embedding provider |
| — | MCP auth token (empty = open) |
| — | REST auth token (empty = open) |
|
| Auto-tag and extract entities |
Production Deployment
docker compose -f docker-compose.prod.yml up -dThis starts PostgreSQL, Ollama (with GPU support), Django (gunicorn), the MCP server, and nginx with TLS. See docs/setup-docker.md for full production setup and docs/setup-supabase.md for cloud-hosted PostgreSQL.
Tech Stack
Backend: Django 5.1 • Django REST Framework • FastMCP 2.0 • PostgreSQL 16 + pgvector • Ollama Frontend: React 18 • TypeScript • Vite • Tailwind CSS • D3 • Recharts Infra: Docker • nginx • gunicorn • uvicorn
Documentation
Guide | Description |
Claude Desktop, Claude Code, Cursor setup | |
Ollama, OpenRouter, OpenAI, Cohere comparison | |
Local and production Docker guide | |
Cloud PostgreSQL with Supabase | |
Database schema deep dive | |
Daily capture and search patterns | |
Adding providers, tools, and importers | |
Deploy on a Windows server for home LAN access | |
Common issues and fixes | |
Feature roadmap |
License
MIT
This server cannot be deployed
Maintenance
Related MCP Connectors
Persistent personal memory for AI assistants — save, search, and recall across every MCP client.
An MCP memory server. One memory your agents share — across models, devices and apps.
Persistent, portable memory for AI assistants — your private memory graph, from any MCP client.
Private persistent memory for Claude, ChatGPT & Gemini via MCP - semantic search, zero-code setup.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceA local MCP server for AI assistants to store and retrieve personal memories on disk, with optional semantic search using embeddings.-
- AlicenseNot gradedqualityCmaintenanceA self-hosted MCP memory server that gives AI assistants persistent, semantic memory by storing facts as vector embeddings locally, supporting semantic search and swappable embedding models.437 npmMIT
- AlicenseNot gradedqualityBmaintenanceA self-hosted MCP memory server with hybrid semantic and keyword search, providing persistent memory for AI coding assistants like Claude Code, Cursor, and Windsurf.6 npm3MIT
- AlicenseNot gradedqualityDmaintenanceA local-first memory MCP server that enables storing, searching, and managing personal memories with hybrid keyword and semantic recall, all on-device.138 npmMIT