Bookmark Context
Type to search documentation.

Architecture

How the daemon, extension, and MCP server relate.

Chrome extension ──HTTP (Bearer token)──▶ Daemon ──▶ SQLite ─┐
(side panel) :7331 ──▶ Chroma │
│ shared
AI client ──stdio──▶ MCP server ─────────────────▶ SQLite ───┤ on-disk
(spawned per session) (direct) ─▶ Chroma ─┘ stores

Two readers, two stores, no coupling

  • SQLite (bookmarks.db) — collections, bookmarks, chunk text, saved page HTML, index status.
  • Chroma (chroma/) — one vector collection per bookmark collection.

The daemon owns writes: it runs the indexing pipeline and exposes the REST API the extension uses. It is the only process that fetches pages.

The MCP server is read-only and reaches SQLite and Chroma directly. It never calls the daemon, needs no API token, and works even when the daemon is stopped (as long as something has already indexed the collection). Editors spawn one MCP process per session, so several run at once — see Tracing.

Why the split

The extension talks to a long-lived local server because saving a page needs a server-side fetch and a background job queue. The MCP server is short-lived and latency-sensitive, so it skips HTTP and reads the stores it needs. Keeping them decoupled means an MCP query never waits on the daemon, and the daemon never blocks on an editor.

Next

Last updated Sep 9, 2026