Apple Notes search & connection-discovery
apple-notes is an MCP server for semantic search and connection-discovery across the
user's own Apple Notes — hybrid search, Swanson-ABC bridges, entity threads, and cited
synthesis over everything they've written. Embeddings, search, BM25, clustering, and
bridges run on-device; only synthesis generation calls an LLM (local OR cloud,
the user's choice).
This skill covers (1) the one-time setup you must walk the user through, and (2) which
tool to reach for, since the server exposes many.
When to Use This Skill
- Use when the user wants to find, recall, or look up something from their own Apple
Notes ("search my notes for X", "what did I write about X", "did I ever note Y").
- Use when the user wants to surface non-obvious connections across their notes
("find bridges/connections across my notes", "what links X and Y", "show related notes").
- Use when the user wants to synthesize a position from their notes ("summarize what I
think about X from my notes", "pull together everything I've written on X").
- Also use for "index my Apple Notes", tag/folder queries, and "what's connected to X".
- Do not use for creating reminders, or for non-Apple-Notes note systems.
First: is the MCP connected?
If apple-notes tools are not available, the server isn't registered yet — do the
Setup below before anything else. If tools exist but a search returns "not indexed"
or empty, run index-notes first (see Ranking caveats).
Setup (walk the user through this — it's the skill's real value)
The server reads Apple Notes' SQLite store directly, so the bun binary needs Full
Disk Access. Steps, in order:
- Install bun (if absent):
brew install oven-sh/bun/bun
- Clone + install deps:
git clone https://github.com/connerkward/mcp-apple-notes
cd mcp-apple-notes && bun install
- Grant Full Disk Access to bun. Run
which bun, then open System Settings →
Privacy & Security → Full Disk Access, click +, and add that exact bun binary
path (commonly /opt/homebrew/bin/bun or /usr/local/bin/bun). Without this the
server cannot read NoteStore.sqlite and every call fails with a permissions error.
(bun install's postinstall tries to open this pane automatically.)
- Register the MCP server (pick the user's client):
- Restart the client, then tell the user to ask "Index my Apple Notes" (or call
index-notes). First index of ~1,800 notes takes a few seconds.
Tool map — which tool for which job
| Tool |
Use when |
index-notes |
First run, or to force a rebuild. Background job with live progress. |
search-notes |
Default search. Hybrid semantic + BM25, re-ranked. Optional folder, modifiedAfter, modifiedBefore. "What did I write about X." |
find-notes |
Exact substring match (like the Apple Notes search box). Use when the user wants a literal string, not meaning. Optional folder, date range. |
get-note |
Fetch one full note by title (fuzzy fallback). |
list-notes |
Notes by recency. Optional folder, date range, limit. |
list-folders |
All folders + note counts. |
list-tags / search-by-tag |
#hashtag inventory / notes carrying a given tag. |
related-notes |
Notes related to a given one via shared tags, [[wikilinks]], and vector similarity. "Show me related notes." |
bridge-notes |
Swanson-ABC bridges — non-obvious connections: pairs (A, C) not directly similar but both strongly tied to a shared intermediary B. "Find non-obvious connections across my notes." Optional folder, limit. No LLM. |
feed |
Ranked evidence-first connection stream (bridges + abstraction pairs + entity threads) as JSON. Optional limit. |
entity-notes / list-entities |
"Where else do I talk about Mercedes?" Entity chips → notes by mention weight. Needs the optional entity graph db (~/.mcp-apple-notes/layered_graph.db); if absent these report how to generate it. |
get-tables |
Pull pipe/tab tables out of a note. |
create-note / update-note |
Create or edit a note. |
check-changes |
Did notes change since last index? (does not trigger re-index) |
index-health |
Sync status, last-indexed time, note count. Run this if results seem stale. |
For "synthesize what I think about X" the synthesis lives in the web app endpoint
(GET /api/synthesize?q= at http://localhost:3741/ when run with bun index.ts),
which writes a grounded answer with inline [n] citations back to source notes.
Ranking caveats (state these when results look off)
- Index before the first search. No index → empty/garbage results; run
index-notes.
- Auto re-index: each search does ~1ms change detection and kicks ONE background
incremental index if notes changed — search returns immediately from the current index
and catches up when the job lands. If a just-edited note is missing, it's the catch-up
lag; re-run the search.
- Score:
score = RRF(vector, BM25) × title_boost × recency_factor.
- Temporal queries (
recent, latest, today) auto-shift to a 1-day recency
half-life at 70% weight; normal queries keep relevance primary (90-day half-life, 10%).
- Synthesis is the only cloud-capable part. It needs an LLM: local via LM Studio /
Ollama (
SYNTH_BASE_URL=http://localhost:1234/v1 SYNTH_MODEL=<model> OPENAI_API_KEY=local,
notes stay on-device) or real OpenAI (funded OPENAI_API_KEY, defaults to gpt-4o-mini).
Everything else — embeddings, search, BM25, clustering, bridges, entities — is on-device.
Limitations
- macOS and Apple Notes only; it does not search Obsidian, Notion, Google Docs, or other note stores.
- The MCP server needs local filesystem permissions to read Apple Notes data, so setup cannot be completed purely inside a remote shell.
- Search quality depends on a fresh local index. Recently edited notes may require
check-changes, index-health, or a rerun after background indexing catches up.
- Entity tools require the optional layered graph database; without it, use hybrid search, exact search, related notes, or bridges instead.
Credits
Fork of RafalWilinski/mcp-apple-notes;
this fork reads SQLite + protobuf directly and adds bridges, entities, feed, and synthesis.
Authored by Conner K Ward. License MIT.
1---2name: apple-notes-search3description: Semantic + keyword search and connection-discovery across the user's own Apple Notes via the apple-notes MCP server. Use when the user wants to find, recall, or synthesize something from their notes, or surface non-obvious bridges/related notes. m...4license: MIT5---67# Apple Notes search & connection-discovery89`apple-notes` is an MCP server for semantic search and connection-discovery across the10user's own Apple Notes — hybrid search, Swanson-ABC bridges, entity threads, and cited11synthesis over everything they've written. Embeddings, search, BM25, clustering, and12bridges run **on-device**; only **synthesis generation** calls an LLM (local OR cloud,13the user's choice).1415This skill covers (1) the one-time setup you must walk the user through, and (2) which16tool to reach for, since the server exposes many.1718## When to Use This Skill1920- Use when the user wants to **find, recall, or look up** something from their own Apple21 Notes ("search my notes for X", "what did I write about X", "did I ever note Y").22- Use when the user wants to surface **non-obvious connections** across their notes23 ("find bridges/connections across my notes", "what links X and Y", "show related notes").24- Use when the user wants to **synthesize a position** from their notes ("summarize what I25 think about X from my notes", "pull together everything I've written on X").26- Also use for "index my Apple Notes", tag/folder queries, and "what's connected to X".27- Do **not** use for creating reminders, or for non-Apple-Notes note systems.2829## First: is the MCP connected?3031If `apple-notes` tools are not available, the server isn't registered yet — do the32**Setup** below before anything else. If tools exist but a search returns "not indexed"33or empty, run `index-notes` first (see Ranking caveats).3435## Setup (walk the user through this — it's the skill's real value)3637The server reads Apple Notes' SQLite store directly, so the **bun** binary needs Full38Disk Access. Steps, in order:39401. **Install bun** (if absent): `brew install oven-sh/bun/bun`412. **Clone + install deps:**42 ```bash43 git clone https://github.com/connerkward/mcp-apple-notes44 cd mcp-apple-notes && bun install45 ```463. **Grant Full Disk Access to bun.** Run `which bun`, then open System Settings →47 Privacy & Security → Full Disk Access, click `+`, and add that exact `bun` binary48 path (commonly `/opt/homebrew/bin/bun` or `/usr/local/bin/bun`). Without this the49 server cannot read NoteStore.sqlite and every call fails with a permissions error.50 (`bun install`'s postinstall tries to open this pane automatically.)514. **Register the MCP server** (pick the user's client):52 - Claude Code: `claude mcp add apple-notes -- bun /absolute/path/to/mcp-apple-notes/index.ts --stdio`53 - Claude Desktop: add to `claude_desktop_config.json`:54 ```json55 { "mcpServers": { "apple-notes": {56 "command": "/Users/<you>/.bun/bin/bun",57 "args": ["/Users/<you>/mcp-apple-notes/index.ts", "--stdio"] } } }58 ```59 - As a Claude Code plugin (bundles this skill too): `/plugin marketplace add connerkward/ckw-skills` then `/plugin install apple-notes@connerkward`.605. **Restart the client**, then tell the user to ask **"Index my Apple Notes"** (or call61 `index-notes`). First index of ~1,800 notes takes a few seconds.6263## Tool map — which tool for which job6465| Tool | Use when |66|------|----------|67| `index-notes` | First run, or to force a rebuild. Background job with live progress. |68| `search-notes` | **Default search.** Hybrid semantic + BM25, re-ranked. Optional `folder`, `modifiedAfter`, `modifiedBefore`. "What did I write about X." |69| `find-notes` | Exact substring match (like the Apple Notes search box). Use when the user wants a literal string, not meaning. Optional `folder`, date range. |70| `get-note` | Fetch one full note by title (fuzzy fallback). |71| `list-notes` | Notes by recency. Optional `folder`, date range, `limit`. |72| `list-folders` | All folders + note counts. |73| `list-tags` / `search-by-tag` | `#hashtag` inventory / notes carrying a given tag. |74| `related-notes` | Notes related to a given one via shared tags, `[[wikilinks]]`, and vector similarity. "Show me related notes." |75| `bridge-notes` | **Swanson-ABC bridges** — non-obvious connections: pairs (A, C) not directly similar but both strongly tied to a shared intermediary B. "Find non-obvious connections across my notes." Optional `folder`, `limit`. No LLM. |76| `feed` | Ranked evidence-first connection stream (bridges + abstraction pairs + entity threads) as JSON. Optional `limit`. |77| `entity-notes` / `list-entities` | "Where else do I talk about Mercedes?" Entity chips → notes by mention weight. **Needs the optional entity graph db** (`~/.mcp-apple-notes/layered_graph.db`); if absent these report how to generate it. |78| `get-tables` | Pull pipe/tab tables out of a note. |79| `create-note` / `update-note` | Create or edit a note. |80| `check-changes` | Did notes change since last index? (does not trigger re-index) |81| `index-health` | Sync status, last-indexed time, note count. Run this if results seem stale. |8283For "synthesize what I think about X" the synthesis lives in the **web app** endpoint84(`GET /api/synthesize?q=` at `http://localhost:3741/` when run with `bun index.ts`),85which writes a grounded answer with inline `[n]` citations back to source notes.8687## Ranking caveats (state these when results look off)8889- **Index before the first search.** No index → empty/garbage results; run `index-notes`.90- **Auto re-index:** each search does ~1ms change detection and kicks ONE background91 incremental index if notes changed — search returns immediately from the current index92 and catches up when the job lands. If a just-edited note is missing, it's the catch-up93 lag; re-run the search.94- **Score:** `score = RRF(vector, BM25) × title_boost × recency_factor`.95- **Temporal queries** (`recent`, `latest`, `today`) auto-shift to a 1-day recency96 half-life at 70% weight; normal queries keep relevance primary (90-day half-life, 10%).97- **Synthesis is the only cloud-capable part.** It needs an LLM: local via LM Studio /98 Ollama (`SYNTH_BASE_URL=http://localhost:1234/v1 SYNTH_MODEL=<model> OPENAI_API_KEY=local`,99 notes stay on-device) or real OpenAI (funded `OPENAI_API_KEY`, defaults to `gpt-4o-mini`).100 Everything else — embeddings, search, BM25, clustering, bridges, entities — is on-device.101102## Limitations103104- macOS and Apple Notes only; it does not search Obsidian, Notion, Google Docs, or other note stores.105- The MCP server needs local filesystem permissions to read Apple Notes data, so setup cannot be completed purely inside a remote shell.106- Search quality depends on a fresh local index. Recently edited notes may require `check-changes`, `index-health`, or a rerun after background indexing catches up.107- Entity tools require the optional layered graph database; without it, use hybrid search, exact search, related notes, or bridges instead.108109## Credits110111Fork of [RafalWilinski/mcp-apple-notes](https://github.com/RafalWilinski/mcp-apple-notes);112this fork reads SQLite + protobuf directly and adds bridges, entities, feed, and synthesis.113Authored by [Conner K Ward](https://github.com/connerkward). License MIT.