engram

engram

A self-hosted MCP server that provides a personal semantic memory layer for AI tools. It enables storing, searching, and managing memories using hybrid vector and keyword search, allowing AI assistants to recall information by meaning.

Category
访问服务器

README

<p align="center"> <img src="docs/assets/engram-banner.svg" alt="Engram — Personal Semantic Memory for AI" width="800" /> </p>

<p align="center"> <strong>A self-hosted semantic memory layer that gives any AI tool persistent, searchable recall.</strong> </p>

<p align="center"> <a href="https://pypi.org/project/engram-semantic/"><img src="https://img.shields.io/pypi/v/engram-semantic?color=blue&logo=pypi&logoColor=white" alt="PyPI" /></a> <img src="https://img.shields.io/badge/python-3.12+-3776AB?logo=python&logoColor=white" alt="Python 3.12+" /> <img src="https://img.shields.io/badge/django-5.1-092E20?logo=django&logoColor=white" alt="Django 5" /> <img src="https://img.shields.io/badge/postgresql-16+pgvector-4169E1?logo=postgresql&logoColor=white" alt="PostgreSQL + pgvector" /> <img src="https://img.shields.io/badge/MCP-compatible-6c63ff" alt="MCP Compatible" /> <img src="https://img.shields.io/badge/license-MIT-green" alt="License: MIT" /> </p>


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.

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 runserver

The 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_server

Start the frontend (separate terminal):

cd frontend && npm install && npm run dev

Dashboard 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/mcp

Cursor / 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
GET /api/health/ Health check
GET /api/memories/ List memories (paginated)
POST /api/memories/ Create a memory
GET /api/memories/<id>/ Get memory by UUID
PATCH /api/memories/<id>/ Update memory
DELETE /api/memories/<id>/ Delete memory
POST /api/search/ Hybrid semantic + keyword search
GET /api/stats/ Memory statistics
GET /api/tags/ List all tags
POST /api/ingest/file/ Ingest a file (PDF, DOCX, TXT, etc.)
POST /api/ingest/url/ Scrape and ingest a URL
POST /api/ingest/batch/ Batch ingest files and URLs

Auth: Authorization: Bearer <REST_API_KEY> (disabled when env var is empty).

MCP Tools

Tool Description
store_memory Store a new memory with optional tags and importance
get_memory Retrieve a memory by UUID
update_memory Update content, tags, or importance
delete_memory Delete a memory
search_brain Hybrid search with configurable semantic/keyword weight, filterable by tags and source
find_related Find semantically similar memories, filterable by tags and source
list_recent_memories List recent memories, optionally filtered by source and/or tags
store_from_url Fetch and ingest a URL
ingest_file Ingest a base64-encoded file
get_stats 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:

  1. A scoping tag in the tags field — domain:<name>, optionally refined with project:<slug>. Examples:
    • tags=["domain:qa", "project:my-app"]
    • tags=["domain:personal"]
  2. The source field — already part of the schema — to identify the writer (e.g. "aegis", "qaagent", "mcp", "manual"). source is 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 tags source
MCP search_brain yes yes
MCP find_related yes yes
MCP list_recent_memories yes yes
REST POST /api/search/ 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/tenant field exists. If you later need hard isolation, options are: run two Engram instances on separate databases, or add a workspace schema 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 config

Configuration

Key environment variables (see .env.example for the full list):

Variable Default Description
DJANGO_SECRET_KEY — Django secret key
DJANGO_SETTINGS_MODULE engram.settings.development Settings module
POSTGRES_DB engram Database name
POSTGRES_HOST localhost Database host
OLLAMA_BASE_URL http://localhost:11434 Ollama API URL
OLLAMA_EMBED_MODEL nomic-embed-text Embedding model
OLLAMA_CHAT_MODEL llama3.2:3b Chat model for enrichment
OPENROUTER_API_KEY — Fallback embedding provider
MCP_API_KEY — MCP auth token (empty = open)
REST_API_KEY — REST auth token (empty = open)
AUTO_ENRICH_ON_CREATE false Auto-tag and extract entities

Production Deployment

docker compose -f docker-compose.prod.yml up -d

This 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
Connecting Clients Claude Desktop, Claude Code, Cursor setup
Embedding Providers Ollama, OpenRouter, OpenAI, Cohere comparison
Docker Setup Local and production Docker guide
Supabase Setup Cloud PostgreSQL with Supabase
Schema Database schema deep dive
Workflows Daily capture and search patterns
Extending Adding providers, tools, and importers
Windows LAN Deploy Deploy on a Windows server for home LAN access
Troubleshooting Common issues and fixes
Roadmap Feature roadmap

License

MIT

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选