Local Brain MCP
Provides embedding generation for semantic search via OpenAI's API, enabling RAG-style memory retrieval.
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., "@Local Brain MCPRemember that I like hiking on weekends."
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.
Local Brain MCP
Local Brain MCP is a small MCP server that you run locally on your machine. It lets AI assistants store and retrieve personal memories on your own disk, and optionally use semantic (embedding) search for RAG‑style workflows.
You run the server on your computer (e.g. python server.py); Cursor and other MCP clients connect to it at http://localhost:3000/mcp. Optionally, you can expose it via something like Cloudflare Tunnel to use the same memory from other devices.
Features
Local, transparent storage
SQLite database file on disk (
memory.dbby default).DB location is configured via environment variables (see “Database layout”). The
dbUrltool argument is intentionally ignored so all clients share the same configured DB.Simple schema:
memoriestable withtitle,content,tags,source, timestamps, and IDs.
MCP tools
save_memory— insert a memory row (optionally generating an embedding).update_memory— patchtitle/content/tags/sourceon an existing row; optional embedding refresh whencontentchanges.delete_memory— remove a row by id (embeddings removed with it).fetch_memories— RAG-style retrieval (use_vector_search, default on). A query is ranked by similarity, not by date. A blank query returns the newest saved rows first. There is no sort parameter. Each row includesid,created_at,title,content,tags,source,mode(vector,keyword, orrecent), andscore.backfill_all_embeddings— generate embeddings for older memories that don’t have one yet (after you configure an embedding provider).doctor— database path, embedding coverage, vector index, and whether the embedding API responds.
Embeddings / vector search
The server does not run an embedding model itself. Embeddings are handled by OpenAI (or optionally OpenRouter) via their APIs.
Optional embeddings are stored in a separate
memory_embeddingstable.OpenAI is the default: set
OPENAI_API_KEYand the server will use OpenAI’s embeddings API. Optionally, setEMBEDDING_PROVIDER=openrouterandOPENROUTER_API_KEYto use OpenRouter instead.
Related MCP server: local-memory-mcp
Quick start
Install dependencies
Create and activate a virtual environment, then install Python deps.
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txtConfigure embeddings (optional but recommended)
Embeddings are generated by OpenAI’s API (the server has no built‑in embedding model). Set OPENAI_API_KEY and the server will call OpenAI to create and store embeddings for semantic search.
Option A: OpenAI
export EMBEDDING_PROVIDER=openai # default, can be omitted
export OPENAI_API_KEY=sk-...
export EMBEDDING_MODEL=text-embedding-3-small # optional overrideOption B: OpenRouter
export EMBEDDING_PROVIDER=openrouter
export OPENROUTER_API_KEY=sk-or-...
# Any OpenRouter embedding model (example shown):
export EMBEDDING_MODEL=openai/text-embedding-3-small
# Optional but recommended for OpenRouter analytics:
export OPENROUTER_SITE_URL="https://your-site-or-localhost"
export OPENROUTER_APP_NAME="Local Brain MCP"Run the MCP server
From the project root:
source .venv/bin/activate
python server.pyYou should see FastMCP start up and log something like:
Local Brain MCPlistening onhttp://0.0.0.0:3000MCP endpoint:
http://localhost:3000/mcp
You can then point Cursor (or another MCP client) at http://localhost:3000/mcp as a remote MCP server.
Run with Docker Compose
If you prefer running this in Docker, use the included docker-compose.yml.
Set env vars (optional, for embeddings)
Create a .env file in the project root (or export env vars in your shell):
# .env example
EMBEDDING_PROVIDER=openai
OPENAI_API_KEY=sk-...
EMBEDDING_MODEL=text-embedding-3-smallBuild and start
docker compose up -d --build
# or, on systems with the legacy CLI:
docker-compose up -d --buildUse the MCP endpoint
The server is available at:
http://localhost:3000/mcp
Stop the service
docker compose down
# or:
docker-compose downNotes:
SQLite data is persisted in the Docker volume
memory_data.Inside the container, the DB path is set to
MEMORY_DB_URL=/data/memory.db.
Cursor integration note (local env auto-load)
When you run server.py locally, it will also try to load environment overrides from ~/.cursor/mcp.json (specifically the mcpServers.local-brain-mcp.env block), if present. This helps you keep your server configuration in one place.
Database layout
By default, the SQLite file is ~/.local/share/local-brain/memory.db, outside any git checkout. Override it with an absolute path:
Env vars:
dbUrl,DB_URL, orMEMORY_DB_URL(first non‑empty wins).
Notes:
The
dbUrltool parameter is intentionally ignored for path resolution.A relative path is rejected, including when the server starts. That keeps a second checkout from creating another database.
Tables:
memoriesid(INTEGER, primary key)created_at(TEXT, ISO datetime, defaultdatetime('now'))title(TEXT, nullable)content(TEXT, required)tags(TEXT, JSON‑encoded list of strings)source(TEXT, optional source identifier)
MCP tools
save_memory
Purpose: Insert a new memory row (and optionally its embedding).
Parameters:
content(str, required): main text content of the memory.title(str, optional): short title.tags(List[str], optional): arbitrary tags, stored as JSON.source(str, optional): where the memory came from (e.g."cursor","cli","web").dbUrl(str, optional): accepted for API compatibility, but ignored for database path resolution.generate_embedding(bool, optional, defaultTrue):If
True, and an embedding API is configured (e.g.OPENAI_API_KEY), the server calls OpenAI (or OpenRouter) to generate an embedding and stores it.
Returns:
A dict with
id,title,content,tags,source,embedded.embeddedistruewhen a vector was stored for this save.falsemeans the text was kept and vector search will not see it until a later backfill.
update_memory
Purpose: Update fields on an existing memory (omit fields you do not want to change).
Parameters:
memory_id(int, required): id of the row to update.title,content,tags,source(optional): new values; at least one must be provided.generate_embedding(bool, defaultTrue): whencontentchanges, ifTruerecompute the embedding; ifFalse, drop the stored embedding so vector search cannot use stale vectors.
Returns: dict with id, title, content, tags, source, embedded. embedded is whether a vector exists after the update.
delete_memory
Purpose: Delete a memory by id.
Parameters:
memory_id(int, required).
Returns: { "id": <int>, "deleted": <bool> } (deleted is False if no row existed).
fetch_memories
Purpose: Retrieve memories relevant to a query, or the most recent rows when the query is empty.
Parameters:
query(str, optional): text query. A non-blank query is ranked by similarity (use_vector_search) or keyword match. There is no sort or date parameter. Ifqueryis omitted or blank, results are the newest saved rows first (created_atdescending).limit(int, optional, default5, max50): max number of results.dbUrl(str, optional): accepted for API compatibility, but ignored for database path resolution.use_vector_search(bool, optional, defaultTrue): RAG-style retrieval.True(default): embed the query and return memories ranked by semantic similarity; falls back to keyword search if embeddings are unavailable.False: keyword-only — SQLLIKEoncontentandtitle, ordered by recency.
fields(list of str, optional): if set, each result includes only these keys. Allowed:id,created_at,title,content,tags,source,mode,retrieval,score. Omit for all fields. Useful to shrink MCP tool payloads (e.g. excludecontentwhen listing or probing).tags_any(list of str, optional): if set, return only rows containing at least one of the provided tags (case-insensitive).source_prefix(str, optional): if set, return only rows wheresourcestarts with this prefix.
Returns:
A list of dicts. By default each includes
id,created_at,title,content,tags,source,mode,retrieval, andscore.modeisvector(embedding similarity),keyword(text match, including when the embedding API is unavailable), orrecent(no query).retrievalrepeats that same value.scoreis cosine similarity for vector hits. It isnullfor keyword and recent results.With
fields, only the requested keys are present.
doctor
Purpose: Check the database path, how many memories lack a vector, whether stored vectors match EMBEDDING_MODEL, which index is in use (sqlite-vec or Python), and whether a live embedding call succeeds.
Parameters:
ping(bool, defaultTrue): send a short embedding request.
Using this as a RAG memory
Typical pattern for an AI assistant:
On new long‑term information
Callsave_memorywith:content: the text snippet you want to remember.title/tags: short descriptors.generate_embedding=True(default) so it’s indexed semantically.
Before answering a user query
Callfetch_memorieswith the user’s question (or a brief summary) asquery. By default it uses RAG (semantic retrieval); use the top results as context when generating the answer.Fallback behavior
If embeddings are not configured or not yet stored, vector search cleanly degrades to keyword search, so the tools remain usable.Hygiene
Useupdate_memoryto correct a row without duplicating it; usedelete_memoryto drop obsolete entries.
Embedding backfill (recommended after enabling embeddings)
If you set an embedding provider/API key after you already have memories saved, run backfill_all_embeddings once to generate embeddings for older rows so semantic search works across your full history. If EMBEDDING_MODEL changes, run python cli.py reembed so older vectors are rebuilt and included in search.
Command line
cli.py uses the same database as the server:
python cli.py list
python cli.py search "how do we start a campaign from a folder"
python cli.py search "exact error text" --keyword
python cli.py doctor
python cli.py reembed
python cli.py dashboarddashboard serves a live graph at http://127.0.0.1:8765. Each memory is a node, and each line connects it to the two notes with the closest embeddings. The page polls GET /events?after=<id> every second and reads new rows from retrieval_events. Those rows are written by _log_activity inside save_memory, update_memory, delete_memory, retrieve_memories (which fetch_memories calls), backfill_embeddings, and reembed_embeddings. A save adds a node, an update moves it, a delete removes it, and a search lights up the matches.
Run python server.py from this checkout. The copy at /Users/ej/Desktop/work/memory-mcp does not write retrieval_events, so the graph stays still even though both processes use ~/.local/share/local-brain/memory.db.
Development notes
The server is implemented in
server.pyusing FastMCP.All schema creation is performed on connection; deleting
memory.dbwill recreate an empty database on next start.Embeddings are handled by OpenAI (or OpenRouter); configuration is via environment variables only.
This server cannot be deployed
Maintenance
Related MCP Connectors
Persistent, portable memory for AI assistants — your private memory graph, from any MCP client.
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 memory, knowledge graph, task management and more for AI agents via MCP.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceA 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.47 npmMIT
- FlicenseNot gradedqualityDmaintenanceA local MCP server that provides semantic memory storage and retrieval for coding and AI agents, enabling durable context across chat sessions.20 npm4-
- FlicenseNot gradedqualityDmaintenanceAn MCP server for managing persistent AI memory using hybrid search (keyword + semantic vector) with SQLite storage and offline-first local embeddings.-
- AlicenseNot gradedqualityBmaintenanceA 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.MIT