brain
Can use Auth0 as an OIDC issuer to enable OAuth access tokens alongside the static bearer token for protected MCP and REST access.
Can use Authentik as an OIDC issuer to enable OAuth access tokens alongside the static bearer token for protected MCP and REST access.
Ingests git history from configured repositories through the git_log connector, tracking cursors and upserting new commits into the brain.
Can use Keycloak as an OIDC issuer to enable OAuth access tokens alongside the static bearer token for protected MCP and REST access.
Imports markdown vaults and directories as notes and exports the brain back to plain markdown; supports a markdown_dir connector.
Can use Ollama as an OpenAI-compatible local enrichment backend to generate item summaries, questions, and atoms.
Supports OpenAI-compatible enrichment endpoints, including OpenAI, to generate summaries, search questions, and atoms for ingested items.
This server does not currently have a deployable release on Glama. Follow the repository's setup instructions to install and configure it for your MCP client, including any required credentials and local dependencies.
brain — a self-hosted second brain for agents
A small server that holds your notes and automatically ingested history in one place, and lets any MCP-capable agent (Claude, self-hosted agents) search, read and write it from any device — no git syncing.
laptop / desktop Kubernetes (namespace: brain)
┌────────────────────┐ HTTPS + token ┌─────────────────────────────────────┐
│ brain push (cron) │ ─────────────────► │ pod │
│ • Claude sessions │ POST /api/items │ ┌─────────────┐ ┌──────────────┐ │
│ • git history │ │ │ server │ │ worker │ │
│ • markdown vault │ │ │ MCP /mcp │ │ connectors │ │
└────────────────────┘ │ │ REST /api │ │ enrichment │ │
Claude Code / Desktop / agents │ │ UI / │ │ prune/backup │ │
┌────────────────────┐ MCP over HTTP │ └──────┬──────┘ └──────┬───────┘ │
│ brain_search/read/ │ ─────────────────► │ └─── SQLite+FTS5 ──┘ │
│ write/append/... │ │ PVC /data │
└────────────────────┘ └─────────────────────────────────────┘How it works (the ideas from the video, minus the hype)
Idea | Here |
Consistent pipelines in | Connectors pull only what's new, stamp it with a date, upsert by |
Cheap model writes summaries | Each item gets a |
Plain-text search, no vector DB | SQLite FTS5 with BM25, columns weighted toward the enriched fields |
Recency weighting | Score × exponential decay (90-day half-life, floor 0.35). Pinned items are exempt |
Keep it fresh | Worker records every run; |
Sweep stale stuff | Daily: archive (never delete) old, unpinned, never-read items from automated sources. Hand-written notes are never auto-archived |
Start here (5 minutes, with Docker)
You need Docker and (optionally) Claude Code. Nothing here is tied to anyone's accounts or data.
git clone <this repo> brain && cd brain
cp .env.example .env
echo "BRAIN_TOKEN=$(openssl rand -hex 32)" >> .env # or edit .env by hand
docker compose up -d --build
open http://localhost:8080 # paste the token from .env when askedLoad the demo notes (7 example notes so you can try search right away):
docker compose cp examples/demo-notes server:/tmp/demo
docker compose exec server brain import-md /tmp/demo --source demoTry it in the UI: search docker permission, vlan, postgres. Delete the demo notes when you start your own
(each has source demo).
Connect Claude Code (any machine that can reach the server):
export BRAIN_TOKEN=... # the value in your .env
claude mcp add --transport http brain http://localhost:8080/mcp --header "Authorization: Bearer $BRAIN_TOKEN"Then start a new Claude Code chat and say "search my brain for docker permission" or "remember that my router is 192.168.10.1".
The server sends usage instructions to the agent on connect, so it knows when to search and when to skip the brain
(general questions). For extra reinforcement paste examples/CLAUDE.md into your global ~/.claude/CLAUDE.md.
claude.ai (web/mobile): custom connectors are called from Anthropic's cloud, so the server needs a public HTTPS URL
and OAuth (a static token is not enough). Put the server behind HTTPS, then follow "Configuration" below
(BRAIN_OAUTH_*) with any OIDC provider (Pocket ID, Authentik, Keycloak, Auth0...). Optional; Claude Code works without it.
Make it smarter later (optional):
brain pushingests git history and notes from your laptop (examples/device-connectors.yaml).BRAIN_ENRICH=claude-cliwrites better summaries using your own Claude subscription (setBRAIN_ENRICH_BIN, defaultclaude);brain enrich-remote --limit 25enriches pending items in small batches. These use your plan quota, so keep batches small. Default is free local heuristics.Back up the
brain-datavolume (it also keeps 7 daily copies under/data/backups).
Safety: never put passwords or tokens in notes. Do not expose the server without HTTPS. Do not mix work and personal data in one instance.
Related MCP server: Capture MCP Server
Quickstart (local, 1 minute)
pip install . # Python 3.11+
export BRAIN_DB=./brain.db BRAIN_TOKEN=$(openssl rand -hex 32)
brain add "Router VLANs" --body "vlan 20 = iot, vlan 30 = guests" --kind reference
brain search vlan iot
brain serve --port 8080 # UI at http://localhost:8080 (paste the token)Deploy to Kubernetes
# 1. build + push the image to a registry your cluster can pull from
docker build -t REGISTRY/brain:0.1.0 . && docker push REGISTRY/brain:0.1.0
# 2. set that image in k8s/kustomization.yaml (replace REGISTRY) and a storageClassName in k8s/brain.yaml
# 3. create the namespace and secret, then apply
kubectl apply -f k8s/namespace.yaml
kubectl -n brain create secret generic brain-secrets --from-literal=BRAIN_TOKEN="$(openssl rand -hex 32)"
kubectl apply -k k8s/
# 4. try it without any ingress
kubectl -n brain port-forward svc/brain 8080:80
curl localhost:8080/healthzDesign notes: one replica with Recreate (SQLite is single-host). The server and
worker share the volume as two containers in one pod, which is what makes SQLite
WAL safe. Do not use an NFS/SMB-backed volume for the database. Use local-path,
Longhorn, Ceph RBD or similar. Keep the Service private (tailnet / LAN / VPN):
the bearer token is the only gate. k8s/ingress.example.yaml is opt-in.
Connect agents
Claude Code (on a machine that can reach the server):
claude mcp add --transport http brain https://YOUR-HOST/mcp --header "Authorization: Bearer $BRAIN_TOKEN"(checkclaude mcp add --helpfor the current flag names), then pasteexamples/CLAUDE.mdinto your global instructions so agents search first and write back durable facts.Self-hosted / other agents: any MCP client over streamable HTTP, or plain REST:
GET /api/search?q=…,POST /api/items,GET /api/items/{id},PUT,DELETE(archive),POST /api/items/{id}/append,GET /api/status. Header:Authorization: Bearer <token>.claude.ai web / mobile app: custom connectors are called from Anthropic's cloud, so they need a publicly reachable HTTPS URL and whatever auth scheme claude.ai supports for custom connectors (I have not verified that a static bearer token is accepted; OAuth may be required). Treat this as an open item. Until then, use Claude Code / Desktop on devices that can reach the server.
Tools exposed: brain_search, brain_read, brain_write, brain_append,
brain_recent, brain_status. The server also sends usage instructions to the client.
Getting data in
From a device (things that only exist on your laptop): run the same connectors there and push:
export BRAIN_URL=https://YOUR-HOST BRAIN_TOKEN=... brain push --config examples/device-connectors.yaml # Claude sessions, git repos, a markdown vault # every 15 min: */15 * * * * brain push --config ~/.brain/connectors.yamlCursor state stays in
~/.brain/state.json; failures keep the cursor so it retries.From the cluster: edit the ConfigMap's
connectors.yaml(a drop-foldermarkdown_diris preconfigured).One-off import (e.g. your old project notes):
brain import-md ./old-notes --source notion-export.Export anytime as plain markdown:
brain export-md ./out(portable; no lock-in).Write your own connector: subclass
Connectorinsrc/brain/connectors.py, yield dicts of item fields fromcollect(cursor), setself.cursor. Gmail/Slack/calendar are natural next ones — use read-only credentials.
Connector types today: markdown_dir, claude_sessions, git_log.
Enrichment and privacy
Default is heuristic (no model, nothing leaves your network). To use a model:
| needs | notes |
| — | lead text as summary; error/command lines as atoms |
|
| any OpenAI-compatible server (Ollama, vLLM, llama.cpp) — stays on your network |
| the | uses your Claude subscription, no API key (run via |
|
| sends item text to the API; model via |
BRAIN_ENRICH_SCOPES=personal restricts the model to those scopes; other items use the heuristic.
If the model fails, enrichment falls back to the heuristic so ingestion never stalls.
Work data: don't ingest it here. If you ever do, run a separate instance (separate DB, token and namespace)
rather than relying on scope — scopes are a filter, not a security boundary. Don't store secrets in notes;
the agent instructions tell agents the same.
Configuration
env | default | |
| required | bearer token (server refuses to start without it unless |
|
| SQLite path |
| — | connectors / maintenance YAML |
| off | comma list; enables Host/Origin pinning |
| off | OIDC issuer (e.g. Pocket ID). Enables OAuth access tokens next to the static token; needs the next three |
| — | public base URL, e.g. |
| — | comma list of accepted |
| — | comma list of accepted |
| — | daily consistent backups, 7 kept |
| heuristic | see above |
Config YAML keys: connectors[] (name, type, interval_minutes, scope, options),
enrich_batch, poll_seconds, maintenance (prune_sources, archive_after_days, backup_dir, backup_keep).
Restore: stop the pod, copy a brain-*.db from /data/backups over /data/brain.db, start.
Pruning dry run: brain maintain --sources claude-sessions git (add --apply to archive).
Tests
pip install -e '.[dev]' && pytest # 52 tests: store, search/ranking, connectors, enrichment,
# auth, REST, MCP over HTTP, device push, 3-process concurrency, CLIStatus / known gaps (alpha)
Verified here: unit/integration tests, a two-process server+worker simulation, and the UI in headless Chrome.
Not verified here:
docker build(no registry/network in the build sandbox), applying the manifests to a real cluster (YAML validated only), real Anthropic/Ollama calls (tested against local fakes that check request shape), and the Claude session log parser against your real files (it is tolerant of unknown lines, but check the first run).Single user, single token, no OAuth. Search is keyword-only by design; add embeddings later only if BM25 misses things.
No Gmail/Slack/calendar connectors yet.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
This server cannot be deployed
Maintenance
Related MCP Connectors
Agent-native notes, tasks, dev-docs, vaults, sync & handoffs. MCP + OpenAPI dual surface.
Hosted agent memory: store, search, and recall facts across sessions from any MCP client.
Private-by-default, local-first memory/context/task orchestrator for MCP apps and agents.
Notes, files, GitHub, and Drive through one MCP connection.
Related MCP Servers
- AlicenseAqualityBmaintenanceEnables MCP-compatible agents to remember, recall, link, and forget durable notes across devices, with local SQLite storage and optional libSQL/Turso sync.429 PyPI1MIT
- AlicenseNot gradedqualityBmaintenanceEnables MCP-capable agents to add, search, edit, archive, and delete locally stored notes over streamable HTTP without using the web UI.MIT
- AlicenseNot gradedqualityCmaintenanceEnables agents to read and write an in-memory notes store through reliable MCP tools, with configurable profiles, response budgets, capability gating, self-documentation resources, session recovery, and stdio/Streamable HTTP transports.6 npmMIT
- AlicenseBqualityBmaintenanceEnables MCP-capable agents to record, search, update, and export durable project notes from a local SQLite store and coordinate asynchronously through a shared blackboard, all over stdio without cloud infrastructure.8MIT