thought-search
Click on "Install 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., "@thought-searchfind the financial memo from yesterday"
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.
thought-search
Find any file on your Mac by a vague memory of it. Spotlight for names, a
local semantic index for meaning, and results shaped for agents: a path:line
to start reading from, not a chunk dump. Nothing leaves the machine.
$ thought grep "the essay about calculating the punch force that could snap a jaw"
~/Documents/college/fermi-estimates-draft.pdf:118 (0.68) — assume the fist decelerates over ~2cm of jaw...
$ thought find "financial memo" --kind presentation
Found 2 in your work folders (newest first):
1. ~/Documents/Acme Financial - One Page Memo.pptx — 3d ago — 4.2MB
2. ~/Downloads/memo-draft-old.pptx — 2mo ago — 3.9MBThis is the file-search layer of Apprentice, a macOS AI apprentice, extracted as a standalone tool. It shipped to real users first; the code here is the shipped code, war-story comments included.
The problem
You know the file exists. You wrote it. You just can't produce the one thing every search interface demands: its name.
Two tools already live on your Mac, and each is broken alone:
Spotlight is fast and literal. It finds
fermi-estimates-draft.pdfif you type "fermi". You didn't remember "fermi". You remembered punch force and jaw.An agent with shell access can
ls,cat, andgrepits way around — powerful, but blind. Every wrong folder it opens burns seconds and context window, and an unscopedmdfindorfind /is a 30-60 second walk.
Semantic search should fix this, and in RAG form it half does: one query pulls content by meaning. But it hands back top-K chunks ripped out of their files — an answer fragment with no neighbors, no thread to pull, nowhere to stand.
The whole point is: you shouldn't have to pick.
Related MCP server: FilePulse-CLI
The bet
Supermemory's SMFS work put numbers on the right design: let semantic search land on a path, then let the agent read, grep, and reason from that path with the tools it already has. Reach of semantic search, control of agentic search, one motion. (Their write-up is worth your time.)
SMFS mounts a cloud memory backend as a filesystem, so half their system is a sync engine: push queues, delta pulls, watermarks, FUSE/NFS mounts.
We took the other half of the idea and inverted the premise: your Mac is already the filesystem. The files are already local, already canonical, already yours. What's missing is not a mount — it's the semantic layer over what's there. So thought-search is the retrieval model without the cloud: no daemon, no sync, no account. An index in SQLite, a matrix in RAM, and two primitives.
Two primitives
find_file — the lexical leg. Name + kind + time + folder, straight off
the OS's own Spotlight index (mdfind, always scoped with -onlyin, never a
directory walk). Multi-word queries are tokenized so "financial memo" matches
Acme Financial - One Page Memo.pptx. Temporal queries use
kMDItemLastUsedDate — when you last opened the file, not when some
background process touched it — so "the deck I worked on yesterday" means what
you meant. On a miss it escalates: work folders → whole home directory →
external drives. It never dead-ends silently; it tells you where it looked.
semantic_grep — the semantic leg. File contents, chunked and embedded
locally (ONNX MiniLM, no PyTorch, ~15MB of runtime), searched by cosine over
an in-RAM matrix. A hit is path:line (score) — excerpt: a launch point. Open
the file, read around the line, follow the thread.
The router between them is not code — it's the model. find_file for
name/metadata references, semantic_grep for content references, and the
agent picks per query, exactly the way you reach for grep vs grep -r.
docs/AGENT_PROMPT.md is the battle-tested routing
doctrine to put in your agent's system prompt.
Install
pip install git+https://github.com/Reppin123/thought-search.git
thought index # crawl Downloads/Desktop/Documents, embed locally
thought grep "that doc about our pricing model"
thought find "contract" --since 'last week'
thought statusThe embedding model (~90MB, all-MiniLM-L6-v2, Apache-2.0) downloads once on first use. After that the tool runs fully offline. macOS only — the lexical leg is Spotlight.
For agents (MCP)
pip install "thought-search[mcp]"
claude mcp add thought-search -- thought-mcpAny MCP client works: {"mcpServers": {"thought-search": {"command": "thought-mcp"}}}.
Then wire docs/AGENT_PROMPT.md into your system
prompt — the tools are half the product; the routing doctrine is the other
half.
As a library
import asyncio
from thought_search import find_files, index_paths, search, start_background_index
index_paths(["~/Documents"]) # foreground crawl
start_background_index() # or: polite daemon-thread crawl
hits = search("unit economics assumptions") # [{path, score, snippet, start_line}]
res = asyncio.run(find_files("financial memo", kind="presentation"))What makes it fast (and keeps it fast)
Everything below was a measured failure first. The numbers come from the machine this shipped on — a real corpus that grew to 7,207 files / 280k chunks / 1.2GB of index — not a synthetic benchmark.
Content-hash freshness. Every file's text is hashed with a settings fingerprint (model, dims, chunking params). Identical bytes never re-embed: unchanged files skip on an mtime+size gate without even being read, and a moved/renamed/copied file reuses its vectors for free. Steady-state re-crawls cost approximately nothing.
Progressive commits. The index commits every 20 embedded files. The first version committed at the end of the crawl — 26 minutes in, the WAL held 71MB and every search said "index empty." Partial results should be searchable during the first crawl, and a killed process should keep its progress.
A polite background crawl. The first cut pegged ~4 cores for 26 minutes.
Now: os.nice(10) plus a per-embed throttle. An index that makes the laptop
fans spin is an index that gets uninstalled.
One matrix in RAM. Brute-force cosine is a single matmul — if the
vectors are already in memory. Reloading 388MB from SQLite per query cost
3.5-5.8s; cached, a query is ~40ms at 252k chunks. The cache key is the chunk
count, not SQLite's data_version — that pragma is per-connection, and
keying on it silently rebuilt the cache on every single query.
Best-chunk-per-file, lazily. Results are files, not chunks: argsort once, walk until top-k distinct files, early-exit. The cache holds no Python strings — at 252k rows, six 252k-element Python lists were a 73s warm-up cost by themselves. Snippets are fetched from SQLite only for the winners.
No type filter on semantic search. An inferred file-type filter is a
silent excluder — a wrong kind guess once dropped the exact PDF the query
was about, and the agent thrashed for 8 turns on a file the index had.
semantic_grep returns every type and shows the extension; choosing is the
caller's job.
bf16 storage: evaluated, rejected. Halving vector RAM sounds free until you notice numpy has no BLAS f16 matmul — you pay a 2-3s per-query upcast or you upcast at load and the RAM comes back. Honest dead ends stay in the comments so nobody re-walks them.
What it deliberately doesn't do
No cloud, no sync engine, no account. SMFS needs push queues and delta pulls because it mirrors to a backend. There is no backend here. Your files never leave your machine; neither do their embeddings.
No daemon, no FUSE/NFS mount. It's a library, a CLI, and an MCP server. The OS filesystem is already mounted.
No hardcoded query planner. The model decomposes "the pdf about X from last week" into parameters inline. Speed comes from the indexes; smarts stay in the model.
Status and honest limitations
macOS only. The lexical leg is Spotlight. A Linux leg would need
locate/plocateor similar.Index freshness is crawl-based (session start /
thought index), not a live file-watcher. Watcher is the natural next step.Text, code, PDF, and docx are indexed today. Images/audio/video want transcription siblings (
talk.mp3→talk.mp3.transcript.md) — designed, not built.MiniLM is the floor. 384-dim, 256-token context; it lands on the right files but scores are modest. The embedder is a deliberate seam — swapping in a longer-context model is a two-constant change plus a re-index.
start_lineis chunk-start, not an exact span.The eval is an A/B gate, not a benchmark.
evals/find_file_ab.pyscores hit@1 / found / latency against a bare-lscontrol on your files; there is no xAFS-style public corpus here yet. Numbers above are one real machine, disclosed as such.
Credits
The retrieval philosophy — semantic search as a navigation aid that lands on paths — is SMFS's (technical report), here reimplemented local-first. Embeddings by all-MiniLM-L6-v2 over ONNX Runtime. Extracted from Apprentice.
MIT.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/Reppin123/thought-search'
If you have feedback or need assistance with the MCP directory API, please join our Discord server