Open Brain — Personal Semantic Memory over MCP
DRAFT — pending Harsh's verification.
This page documents Open Brain — Harsh's personal semantic-memory system. It is the memory backbone that lets context persist across his AI agents' sessions: any client that speaks MCP can read existing memories, write new ones, and load his standing quality preferences. It is also, separately, the thing this website's corpus store is patterned on (see §6).
1. What it is
Open Brain is a personal semantic memory system integrated via the Model Context Protocol (MCP). It acts as a persistent, queryable knowledge base that any AI agent can read from and write to across sessions — so context accumulated in one conversation, one tool, or one day survives into the next instead of evaporating when the session ends.
The protocol surface is MCP over HTTP/SSE (Server-Sent Events). An AI
client connects to a remote MCP endpoint, discovers the brain's tools, and
calls them like any other tool: capture_thought, search_thoughts,
list_thoughts, thought_stats, and get_preferences. The brain is not a
single chatbot's scratchpad — it is a shared, durable substrate that several
different clients write to and read from.
flowchart TD
clients["Claude Code · Cowork · claude.ai chat"]
brain["Open Brain (MCP)\nedge-function logic plane"]
postgres["Postgres + pgvector\ndata plane · thoughts + taste_preferences"]
clients -->|"MCP over HTTP/SSE"| brain
brain --> postgres
The payoff is continuity: a decision recorded by Claude Code on Tuesday is retrievable by claude.ai on Wednesday, with no copy-paste and no re-prompting.
2. The three-plane architecture
Open Brain separates three concerns onto three planes. The split keeps the heavy linguistic work off the request path of a simple list or stats call, and keeps the storage layer a plain database — not a vector DB service — so it can be reasoned about and queried directly.
Logic plane — Supabase Edge Functions
Two serverless functions carry the intelligence and routing:
open-brain-mcp— the core MCP server. It translates AI tool calls into database queries and manages authentication: every request must present a secret access key (validated server-side), and Row-Level Security policies ensure only the server's service role can perform CRUD against the tables. The client never speaks SQL; it speaks MCP tools, and this function is where "tool call" becomes "query."ingest-thought— a specialized capture function, integrated with Slack, that asynchronously processes incoming text. This is the human-in-the-loop ingest path: a thought dropped into Slack gets turned into a properly embedded, metadata-tagged row without an AI session being open at all.
AI services — OpenRouter
Linguistic heavy lifting is offloaded to models through OpenRouter, a unified API gateway, rather than run on the edge function itself:
- Embeddings —
openai/text-embedding-3-small, producing 1536-dimensional vectors. One vector per thought, one per query, so the two can be compared by similarity. - Metadata extraction —
openai/gpt-4o-mini, which reads raw text and returns structured context: the people mentioned, the topics, and the action items. This is what makeslist_thoughtsfilterable by topic, person, or type rather than only by semantic similarity.
Data plane — Postgres + pgvector
The physical long-term memory is a Supabase-hosted Postgres database with the pgvector extension. There is no separate vector database service; the vectors live in the same relational store as everything else, which keeps the schema, the access control, and the joins in one place. This plane is described in §3.
flowchart LR
slack[Slack] --> ingest[ingest-thought]
client[AI client] -->|MCP| mcp[open-brain-mcp]
ingest --> openrouter["OpenRouter\nembeddings + metadata"]
mcp --> openrouter
openrouter --> postgres["Postgres + pgvector\nthoughts · taste_preferences"]
3. The data model — a thought stream and a preference registry
Open Brain stores two different kinds of thing in two different tables, and the distinction is load-bearing: one is a timestamped stream you search semantically, the other is a deliberately maintained registry you query deterministically. Together they answer two different questions.
thoughts — the thought stream
Append-only, timestamped, semantically searchable. Each row is one captured unit of knowledge.
| Column | Type | Description |
|---|---|---|
id | uuid | Primary key |
content | text | The raw thought or information string — written to be a clear, standalone statement that makes sense when retrieved later |
embedding | vector(1536) | Semantic representation for similarity search |
metadata | jsonb | Extracted context: people, topics, action items |
type | text | observation · idea · task · reference · person_note |
topics | — | Auto-extracted tags (e.g. AI, DevOps, SRE) |
people | — | Mentioned persons |
created_at | timestamptz | Timeline management |
The type taxonomy is the system's notion of what kind of thing a thought is:
an observation versus a task to do versus a reference to look up. Topics and
people are auto-extracted by the metadata-extraction model rather than
hand-tagged, so capture stays low-friction.
taste_preferences — the preference registry
Structured, deliberate, domain-filtered — not a thought stream. This is where Harsh's standing standards live, maintained on purpose rather than accumulated as a byproduct.
| Column | Type | Description |
|---|---|---|
preference_name | text | Short label (e.g. "Structured outputs over prose") |
domain | text | Scope: writing · code · strategy · general |
reject | text | The specific thing to avoid |
want | text | What to do instead |
constraint_type | text | domain rule · quality standard · business logic · formatting |
created_at | timestamptz | Timestamp |
A row is a want / reject pair scoped to a domain: "in writing, want this, reject that." As of the source material this registry held 41 rows across the four domains, covering work tooling, writing style, investing, lifestyle habits, culture, and creative preferences.
Two layers, two questions
| Layer | Table | Tools | Answers |
|---|---|---|---|
| Thought stream | thoughts | search_thoughts, list_thoughts, capture_thought | "What do I know?" — semantic, append-only, timestamped |
| Preference registry | taste_preferences | get_preferences | "How should I work?" — structured, deterministic, domain-filtered |
The thought stream is similarity-ranked and time-ordered; the preference
registry is a direct lookup with no embeddings involved. get_preferences hits
the table by domain and/or constraint_type and returns formatted output
ready to drop into an AI's context — so any session can load Harsh's exact
standards before starting work, without re-prompting.
Reusable pattern: keep "what happened" and "how to behave" in different stores. The first wants semantic recall over a growing stream; the second wants deterministic, scoped retrieval of a deliberately maintained set. Stuffing both into one table forces every behavioral rule to compete with every passing observation for similarity rank — and the rules lose.
4. The semantic search flow
Capture (capture_thought)
- Input — raw text arrives from an AI client or, asynchronously, from
Slack via
ingest-thought. - Vectorization — OpenRouter generates a 1536-dimensional embedding for the content.
- Extraction — the metadata-extraction LLM parses the text for people,
topics, and action items, and assigns a
type. - Storage — content, vector, and the JSON metadata are committed together
to the
thoughtsrow.
Retrieval (search_thoughts)
- Query — the AI client sends a natural-language question.
- Embedding — the query is converted into its own 1536-dimensional vector.
- Similarity match — a pgvector similarity function (
match_thoughts) ranks stored thoughts by cosine distance to the query vector, with an optional similaritythresholdfloor and alimit(default 10). - Results — the most semantically relevant memories are returned into the AI's context window, with their extracted topics, people, and type.
list_thoughts complements search with structured access — recent entries by
days, limit, topic, person, or type — for the cases where "most
recent thoughts tagged DevOps" is a better question than "thoughts most
similar to this sentence." thought_stats returns aggregate counts, type
breakdown, top topics, and people mentioned — a dashboard of what's in the
brain, not a search of it.
The capture→retrieve pair is the whole loop: every capture_thought makes a
future search_thoughts more useful, and because capture is cheap (type a line,
the system does the rest), the brain compounds.
5. Clients
Open Brain is client-agnostic by construction — anything that speaks MCP can use it. In practice it is wired into the tools Harsh already lives in:
- Claude Code and Claude Cowork are configured to both query
historical context and capture new thoughts at end-of-day and sprint
boundaries, via
CLAUDE.mdhooks. So a sprint's worth of decisions gets written down without anyone remembering to write it down. - claude.ai chat connects to the same MCP endpoint, so a browser conversation has access to the same memory the terminal sessions do.
Because the tool surface is MCP and the auth is a key validated at the server, adding a new client is "point it at the endpoint, give it the key" — no per-client integration work, no client holds a copy of the data, and every client sees the same single source of truth.
6. Relationship to this site
This website is not a brochure about Harsh's work; where it can be, it is an
instance of it. The site's corpus store — the RAG backing the /chat and
/fit agents — reuses the same Supabase Postgres + pgvector semantic-retrieval
pattern that Open Brain validated (per PRD §6.1). The shape is the same:
content with embeddings in Postgres, a pgvector similarity match for retrieval,
a threshold and a limit bounding the returned slice.
Two deliberate differences sit on top of the shared pattern:
- Embeddings provider. Open Brain uses OpenAI's
text-embedding-3-smallthrough OpenRouter; the site selects Voyage embeddings (ADR-001 pending, PRD §16 open question #2). The pgvector retrieval pattern is provider-agnostic — swap the embedding model and the dimension, keep the match function. - Trust posture. Open Brain is personal memory; the site's corpus is a public artifact the agent is grounded in. The site inherits the storage pattern but adds the trust layer the PRD mandates: citation-mandatory prompting, an eval harness that blocks deploys, and a sanitization denylist in CI. Open Brain has no such adversary; its only user is Harsh.
The point of the reuse is the one the strategy docs make: Open Brain was built for productivity, but its latent adjacent value is that it is itself the demo of what the site sells — a pgvector-backed RAG agent exposed over MCP. The site does not describe that work; it stands one up.
7. What it demonstrates
Open Brain is the most legible instance of the working thesis behind this whole project: fingertip awareness from hands-on frontier work is the input, and distribution is what's missing. The system was built to solve a real, daily problem — context evaporating between AI sessions — and the fact that it exists, works, and is exposed over an open protocol is the distribution. Anyone who wants to evaluate whether Harsh can build this kind of thing does not have to take a bullet point's word for it; the architecture above is the answer.
Specifically it demonstrates, in one deployed system:
- pgvector semantic retrieval in production — Postgres as the vector store, not a managed vector DB, with a cosine match function and a threshold floor.
- MCP-over-HTTP/SSE as a real integration surface — the same agent-tool protocol used to expose memory to multiple independent clients.
- A two-layer memory design — semantic stream vs. deterministic preference registry, each with the tool that fits it.
- Asynchronous ingest — Slack-driven capture that runs the full embed-and-extract pipeline without an open AI session.
- Edge-function logic over a managed Postgres — the Supabase pattern the site's own corpus store reuses (§6).
It is, in the terms of the porch case study, the porch: a thing built for one purpose whose value in an adjacent market is unlocked by someone who already has it built.
Sources
This page was distilled from two Open Brain technical specifications — a usage context doc and a system-architecture doc — both read-only source material. Every architectural claim above traces to those two documents. No Supabase project refs, dashboard URLs, access-key names, or credential values from the specs appear here; the system is described by its architecture, not by its deployment coordinates. Usage statistics (thought count, preference count, date range, top topics) are quoted from the source as illustrative state, not live figures.