MeshMind
# πΈοΈ MeshMind
[](https://www.npmjs.com/package/meshmind)
[](https://github.com/AntoniovanDijck/meshmind/actions/workflows/ci.yml)
[](LICENSE)
[](https://nodejs.org)
**One MCP server. Three superpowers for your AI agent β keyless, local-first, no setup.**
> Built for **AI engineers, senior devs, and power users** who want their coding agent to understand large codebases, stay current with fast-moving topics, and stop wasting the context window.
---
## π¬ See it in action
Ask your agent in plain language β MeshMind picks the right tool:
```
You: "Map this repo and show me hub modules and import cycles."
Agent: Scanning 87 files⦠(AST: 71, regex: 16)
π¦ 4 communities detected
π Hub nodes: server.ts (degree 12), mapper.ts (degree 9)
β οΈ Import cycle: crusher.ts β server.ts β crusher.ts
Summary: 312 edges, 6 orphan files, 2 god nodes
```
```
You: "What's the latest on Bun vs Node in the last 30 days?"
Agent: Researched 12 sources (847 results β 42 after fusion + dedup)
π₯ Top corroborated theme: Bun 1.2 HTTP perf benchmarks
Sources: HN (score 847), Reddit r/javascript, Dev.to (3 posts)
π Entities: Bun, Node 22, Deno, WinterTC
π‘ Diverging signal: GitHub issues show Node winning on compatibility
```
```
You: "I have ~400 tokens of room left. Crush this 8k-line log to fit."
Agent: crush_file β targetTokens=400 (auto-escalation)
[strip,whitespace,line-dedup,json-min] β 6,210 tok
[+stopwords] β 4,980 tok
[+summarize] β 1,520 tok
[+truncate maxLines=44] β 353 tok β
53,000 tokens β 353 tokens (-99.3%)
ref: cf_a3f9β¦ (persisted β retrieve anytime, even tomorrow)
```
---
## β‘ Three superpowers
```
π§ MAP YOUR CODE π° RESEARCH WHAT'S NEW ποΈ CRUSH THE TOKENS
βββββββββββββββββββββ ββββββββββββββββββββββββββ βββββββββββββββββββββββββ
Real AST dependency Last-N-days signal from Reversible compression
& call graph 12 keyless public sources with exact BPE counts
TS/JS via TypeScript HN Β· Reddit Β· GitHub 7 composable algorithms
compiler API Lobsters Β· Bluesky strip Β· dedup Β· truncate
Stack Overflow Β· Lemmy json-min Β· stopwords
Python/Go/Rust via Dev.to Β· Mastodon summarize (host LLM)
ast-grep/tree-sitter YouTube (via Piped)
Community clustering Cross-source fusion LRU-bounded reversible
Cycle/hub detection Relevance reranking cache β get originals
Mermaid/JSON export Entity extraction back anytime via ref
```
The killer combo: pipe research output **straight through the compressor** β agent reads the signal, not the token bill.
---
## π― Who this is for
**Use MeshMind if you are:**
- An AI engineer or developer who uses Claude Code, Cursor, or a similar coding agent daily
- Working on large or unfamiliar codebases where the agent needs structural context fast
- Researching fast-moving topics (new frameworks, API changes, community debates) without paying for search APIs
- Hitting context window limits and want reversible, measurable compression
**When NOT to use MeshMind:**
- You need **real-time data** (research window is 30 days by default, not live search)
- You need **authenticated sources** (all 12 sources are public/keyless β no paywalled content)
- You need **code execution or modification** (MeshMind is read-only: maps, reads, compresses)
- Your codebase is **gigantic** (100k+ files) β use `maxFiles` to scope it, or a dedicated code-index tool
---
## β‘ Quick start (60 seconds)
```bash
# Claude Code β one command, done:
claude mcp add meshmind -- npx -y meshmind
```
No API keys. No build step. `npx` fetches it on first run. For other clients see [Install in an MCP client](#install-in-an-mcp-client) below.
---
## π Security & privacy
**Everything runs locally. Nothing is stored. Nothing is sent to third parties.**
- **Codebase mapping** β reads files on your machine, builds graph in memory, returns summary. No data leaves the process.
- **Research** β fetches public URLs (HN, Reddit, GitHub, etc.) the same way your browser would. No auth tokens required or stored.
- **Compression** β runs entirely in-process. The `ref` cache is in-memory only and cleared when the process exits.
- **Summarization** β when `summarize: true`, your text is sent to your **own MCP client's LLM** via standard MCP sampling (i.e. the same model your agent already uses). If your client doesn't support sampling, MeshMind falls back to local extractive summarization β nothing leaves the process.
MeshMind intentionally skips `.env` files, secrets-pattern filenames, `node_modules`, and dotdirs during codebase scans. Full threat model: [`SECURITY.md`](SECURITY.md).
---
## Tools
### `scan_local_codebase`
`{ path, raw?, maxFiles? }` β dependency graph with real AST extraction.
- **TS/JS/TSX/JSX** β TypeScript compiler API (true AST, not regex)
- **Python, Go, Rust** β ast-grep / tree-sitter grammars
- **Everything else** β regex fallback
- Edges carry `EXTRACTED / INFERRED / AMBIGUOUS` confidence labels
- Community clustering (label propagation), hub/god node detection, import cycle detection, orphan detection
- Skips `node_modules`, build dirs, dotdirs, secrets-pattern files
- Default: compact summary with `ast=N` coverage; `raw: true` returns full JSON
**Example output:**
```json
{
"fileCount": 87,
"astFiles": 71,
"edges": 312,
"analysis": {
"hubs": ["server.ts", "mapper.ts"],
"cycles": [["crusher.ts", "server.ts"]],
"orphans": ["legacy/old-api.ts"],
"communityCount": 4
}
}
```
---
### `export_codebase_graph`
`{ path, format? }` β export the dependency graph.
- `"mermaid"` β paste directly into docs, GitHub, or Obsidian
- `"json"` β nodes + edges for D3, Obsidian Canvas, or custom tooling
**Example Mermaid output:**
```
graph LR
server.ts --> mapper.ts
server.ts --> crusher.ts
mapper.ts --> astgrep.ts
crusher.ts -.-> server.ts
```
---
### `research_last_30_days`
`{ topic, windowDays?, sources?, perSource?, compress? }` β multi-source community signal.
- **12 keyless sources:** `hackernews`, `reddit`, `github`, `github_issues`, `web`, `lobsters`, `bluesky`, `stackoverflow`, `lemmy`, `devto`, `mastodon`, `youtube`
- Entity extraction β surfaces salient names, libs, keywords
- Cross-source fusion β clusters results into themes, boosts items corroborated by β₯2 independent sources
- Fail-soft β a blocked source returns nothing instead of crashing the run
- `compress: true` β pipes result through the crusher before returning
**Example output (truncated):**
```json
{
"topic": "Bun vs Node",
"totalResults": 42,
"themes": [
{
"label": "Bun 1.2 HTTP performance benchmarks",
"sources": ["hackernews", "reddit", "devto"],
"topItem": { "title": "Bun 1.2 is faster than Node on HTTP", "score": 847 }
}
],
"entities": ["Bun", "Node 22", "Deno", "WinterTC"]
}
```
---
### `get_optimized_context`
`{ text? | filePath?, mode?, targetTokens?, algorithms?, maxLines?, summarize?, preview? }` β reversible compression.
**Three ways to drive it:**
- **Budget mode** β set `targetTokens` and MeshMind auto-escalates the pipeline (lossless-ish β stopwords β summarize β truncate) until the output fits. Returns an escalation log so you see how it got there.
- **Explicit** β pick your own `algorithms`.
- **Default** β leave both for the sensible lossless-ish pipeline.
Other options:
- **Algorithms (composable):** `strip` Β· `whitespace` Β· `line-dedup` Β· `json-min` Β· `truncate` Β· `stopwords` Β· `summarize`
- **Modes:** `code` Β· `web` Β· `auto`
- `summarize: true` β delegates to host LLM via MCP sampling; falls back to local extractive
- `preview: true` β per-step savings breakdown **without** storing a ref or touching stats
**Example output (budget mode):**
```
[meshmind] budget=400 tok β 353 tok β within budget | 52999β353 (-99.3%) | ref=cf_a3f9β¦
Escalation:
[strip,whitespace,line-dedup,json-min] β 6210 tok
[+stopwords] β 4980 tok
[+stopwords,summarize] β 1520 tok
[+truncate maxLines=44] β 353 tok
```
---
### `crush_file`
`{ path, targetTokens?, mode? }` β read a file and compress it in one call.
The shortcut for "this file is too big to read." With `targetTokens`, auto-escalates until it fits; otherwise applies the default pipeline. Returns compressed payload + exact BPE savings + a reversible `ref`.
---
### `retrieve_context`
`{ ref }` β recover the original uncompressed text from a `ref`.
**Persistent:** refs are stored on disk under `MESHMIND_HOME` (default `~/.meshmind`), so you can retrieve a blob you compressed in a previous session β even after a restart. LRU-bounded (default 500 entries; tune via `MESHMIND_CACHE_MAX`).
---
### `context_stats`
`{}` β token savings, both **session** (this process) and **lifetime** (persisted across restarts).
```json
{
"session": { "calls": 14, "originalTokens": 84200, "crushedTokens": 12300, "savedPercent": 85.4, "cachedRefs": 312 },
"lifetime": { "calls": 1840, "originalTokens": 9_400_000, "crushedTokens": 1_900_000, "savedPercent": 79.8, "cachedRefs": 312, "firstSeen": "2026-05-01Tβ¦", "lastSeen": "2026-06-16Tβ¦" }
}
```
---
## Recipes
| You say⦠| MeshMind does⦠|
|---|---|
| "Map this repo and flag hub modules and import cycles." | `scan_local_codebase` β AST graph + analysis |
| "Export the dependency graph as Mermaid so I can paste it in the docs." | `export_codebase_graph` β Mermaid |
| "What did people say about `bun` vs `node` in the last 30 days?" | `research_last_30_days` β ranked, fused, multi-source digest |
| "Research Rust async, but compress it before you read it." | `research_last_30_days` with `compress: true` |
| "This stack trace is huge β dedupe and trim it before reading." | `get_optimized_context` with `line-dedup` + `truncate` |
| "Summarize this 20-page doc into the key facts." | `get_optimized_context` with `summarize: true` (host-LLM) |
| "Give me back the full original of that compressed blob." | `retrieve_context` with the `ref` |
| "How many tokens have we saved this session?" | `context_stats` |
**Tip:** chain them. "Research X, compress it, and tell me the 3 corroborated themes" hits research β fusion β compression in one turn, and the agent only reads the crushed output.
---
## Install in an MCP client
MeshMind is on npm: <https://www.npmjs.com/package/meshmind>. No clone or build needed β `npx` fetches and runs it. The command is always `npx -y meshmind`; only the config location differs per client.
**Claude Code** (CLI β registers it for you):
```bash
claude mcp add meshmind -- npx -y meshmind
```
**Cursor** β `~/.cursor/mcp.json` (or `.cursor/mcp.json` in a project):
```json
{
"mcpServers": {
"meshmind": { "command": "npx", "args": ["-y", "meshmind"] }
}
}
```
**Claude Desktop** β `claude_desktop_config.json` (macOS: `~/Library/Application Support/Claude/`, Windows: `%APPDATA%\Claude\`):
```json
{
"mcpServers": {
"meshmind": { "command": "npx", "args": ["-y", "meshmind"] }
}
}
```
**VS Code** (Copilot/MCP) β `.vscode/mcp.json`:
```json
{
"servers": {
"meshmind": { "type": "stdio", "command": "npx", "args": ["-y", "meshmind"] }
}
}
```
Any other MCP host (Codex, Gemini CLI, Windsurf, Zed, β¦) uses the same `command` + `args` pair in its own config format. See [`mcp.example.json`](mcp.example.json) for the canonical block.
Prefer a pinned global binary? `npm i -g meshmind`, then use `meshmind` as the command instead of `npx -y meshmind`.
### From source (for development)
```bash
git clone https://github.com/AntoniovanDijck/meshmind.git
cd meshmind
npm install && npm run build # runnable server at build/server.js
```
Then point the client at `node /ABS/PATH/TO/meshmind/build/server.js`.
---
## Benchmarks
Real numbers from `npm run benchmark` (Node 22, Apple Silicon) on representative
payloads β not mocked. **Default pipeline** is deliberately conservative
(lossless-ish: strip/whitespace/line-dedup/json-min):
| Fixture | Orig tokens | Crushed | Saved | Time |
|---|---:|---:|---:|---:|
| HTML listing (1k rows) | 37,091 | 7,001 | **81.1%** | 5 ms |
| Source code (this repo) | 28,194 | 22,745 | 19.3% | 20 ms |
| Verbose log (2k lines) | 52,999 | 45,399 | 14.3% | 26 ms |
| JSON array (2k objects) | 149,998 | 146,002 | 2.7% | 33 ms |
| RAG concat (200 chunks) | 18,000 | 17,800 | 1.1% | 5 ms |
The default pipeline only removes provably-safe noise β that's why structured
JSON and near-duplicate prose barely move. **Budget mode** is where the savings
live: it escalates through lossy stages until your target is hit.
| Target | Result | Hit? | Time |
|---:|---:|:---:|---:|
| 2,000 | 1,715 | β | 132 ms |
| 1,000 | 868 | β | 130 ms |
| 400 | 353 | β | 131 ms |
| 150 | 126 | β | 113 ms |
*(52,999-token verbose log β any budget you ask for.)* Reproduce with
`npm run benchmark`.
## Build & test
```bash
npm install
npm run build # tsc β build/
npm test # offline: unit tests + MCP integration (no network)
npm run test:network # also exercises the live research sources
npm run benchmark # reproduce the compression benchmarks above
```
Live network sources are **opt-in** (`RUN_NETWORK_TESTS=1`) so the default suite is deterministic and CI-safe.
---
## Architecture
```
src/
crusher.ts # compression pipeline + budget escalation β headroom
store.ts # persistent reversible store + lifetime stats
mapper.ts # collect β extract β graph β cluster/analyze β graphify
astgrep.ts # multi-language AST (Python/Go/Rust) β graphify
recency_engine.ts # parallel keyless source fetchers + fusion β last30days
server.ts # MCP server: registers the 7 tools
benchmark.ts # reproducible compression benchmarks
test-unit.ts # deterministic offline unit tests
test-client.ts # MCP integration tests over stdio
```
Runtime dependencies: `@modelcontextprotocol/sdk`, `zod`, `gpt-tokenizer` (exact BPE counts), `typescript` (TS/JS AST), `@ast-grep/napi` + `@ast-grep/lang-{python,go,rust}` (multi-language AST). Networking uses the Node stdlib `fetch`. Summarization delegates to the host LLM via MCP sampling β no ONNX, no model downloads.
---
## FAQ
**Do I need any API keys?**
No. Every research source is keyless/public, and compression + mapping are fully local.
**Which languages does the codebase mapper understand?**
TS/JS/TSX/JSX via the TypeScript compiler API. Python, Go, Rust via ast-grep (tree-sitter). Everything else falls back to regex. The summary's `ast=N` tells you how many files got a real AST.
**Is the compression lossy? Can I get the original back?**
Lossy steps exist (strip, dedupe, summarize), but every compression is stored under a `ref`. Call `retrieve_context` with that `ref` to recover the exact original. Refs are **persisted to disk** under `MESHMIND_HOME` (default `~/.meshmind`), so they survive restarts β retrieve a blob you compressed yesterday. LRU-bounded (default 500 entries β tune via `MESHMIND_CACHE_MAX`). If the disk is unavailable, the store falls back to in-memory for the session.
**A research source returned nothing / errored.**
Sources are fail-soft: a blocked or rate-limited source returns nothing instead of crashing the run. The result lists per-source errors so you know what was skipped.
**Does `summarize` send my data anywhere?**
Only to your own MCP client's LLM, via standard MCP sampling. If the client doesn't support sampling, MeshMind falls back to local extractive summarization. See [`SECURITY.md`](SECURITY.md).
**Can it read files outside my project?**
It reads whatever path you give it, with the privileges of the process. Run it in a sandbox if you need to constrain that β details in [`SECURITY.md`](SECURITY.md).
**Why "MeshMind"?**
It meshes three separate context tools into one mind for your agent. πΈοΈπ§
---
## Credits & License
MeshMind is MIT-licensed. Its three pillars are *conceptually* derived from
[graphify](https://github.com/safishamsi/graphify),
[headroom](https://github.com/chopratejas/headroom), and
[last30days-skill](https://github.com/mvanhorn/last30days-skill) β see
[`CREDITS.md`](CREDITS.md) for full attribution. Contributions welcome β see
[`CONTRIBUTING.md`](CONTRIBUTING.md).
TDQS
Scored across 7 tools
Tools have largely distinct purposes, with some overlap between crush_file and get_optimized_context as both compress, but they target different use cases (file shortcut vs. general pipeline). export_codebase_graph and scan_local_codebase are related but differ in output format and depth. Overall, agents can distinguish most tools.
All tool names use snake_case with a consistent verb_noun or descriptive pattern (e.g., crush_file, get_optimized_context, research_last_30_days). No mixing of conventions, making naming predictable and clear.
Seven tools cover the advertised functionalityβcontext compression, codebase analysis, and researchβwithout being excessive. Each tool has a defined role, and the count is appropriate for the server's purpose.
The tool set covers key operations: compression, decompression, stats, codebase scanning, graph export, and research. Minor gaps exist, such as no tool to list or manage stored refs, and no direct configuration update, but core workflows are well-supported.