exo
An MCP server that ingests various data sources and uses LLMs to compile them into structured knowledge pages, enabling hybrid search and integration with AI coding tools like Claude Code and Cursor.
README
<div align="center">
exo
Your exocortex. CLI + MCP server for personal knowledge management.
</div>
AI coding sessions close and the experience disappears. ChatGPT threads pile up with nowhere to go. Notes accumulate but never get flagged as stale. exo solves all three.
Ingest ChatGPT exports, PDFs, images, and markdown files. Let LLMs compile raw sessions and conversations into structured knowledge pages. Search everything with hybrid FTS5 + vector search and LLM query expansion. Wire it into Claude Code or Cursor as an MCP server so your AI tools can read and write your brain directly.
Table of Contents
- Install
- Quick start
- Commands
- Configuration
- Page format
- Hybrid search
- AI ingestion
- MCP server
- Lint
- Development
Install
bun install -g @guqings/exo
Requires Bun 1.x.
Quick start
# Initialize your brain (default: ~/.exo/brain.db)
exo init
# Configure AI provider (OpenAI-compatible)
exo config set embed.api_key sk-...
exo config set embed.base_url https://api.openai.com/v1
exo config set compile.api_key sk-...
# Capture a quick note (no LLM, instant)
exo capture "Redis rate limiting: token bucket at 100 req/s per user"
# Or write a full page
echo '---
title: Redis Rate Limiting
type: concept
tags: [redis, backend]
---
Token bucket at 100 req/s per user. Use INCR + EXPIRE for sliding window.
' | exo put concepts/redis-rate-limiting
# Keyword search
exo search "redis rate limit"
# Hybrid search with AI query expansion (requires embed config)
exo query "how to prevent API abuse"
# Read a page
exo get concepts/redis-rate-limiting
# Open the local Web UI
exo ui
# Wire up to Claude Code / Cursor (one-time)
exo setup-mcp
Data flow
flowchart TD
subgraph Sources["Data Sources"]
A[Markdown files / dirs]
B[Quick notes / text]
C["Claude Code / Copilot / Codex session logs"]
D[ChatGPT export JSON]
E["Mixed directory (MD + PDF + images)"]
F[PDF / image / audio / DOCX]
end
subgraph Ingest["Ingestion"]
I1["exo import / exo sync"]
I2["exo capture"]
I3["exo harvest"]
I4["exo digest / exo import-chatgpt"]
I5["exo ingest"]
I6["exo attach / exo describe"]
end
subgraph Store["Brain — brain.db"]
INBOX["📥 inbox (staging area)"]
CONCEPT["🧠 concept / learning / project (knowledge pages)"]
FILES["📎 files (binary attachments)"]
end
subgraph Pipeline["AI Pipeline"]
COMPILE["exo compile (LLM: create / update / discard)"]
end
subgraph Out["Access"]
SEARCH["exo search / query"]
UI["exo ui (web browser)"]
MCP["exo serve (MCP / Claude Code)"]
EXPORT["exo export"]
end
A --> I1 --> CONCEPT
B --> I2 --> INBOX
C --> I3 --> INBOX
D --> I4 --> INBOX
E --> I5 --> INBOX
F --> I6 --> FILES --> CONCEPT
INBOX --> COMPILE --> CONCEPT
CONCEPT --> SEARCH
CONCEPT --> UI
CONCEPT --> MCP
CONCEPT --> EXPORT
style INBOX fill:#fef3c7,stroke:#d97706
style CONCEPT fill:#d1fae5,stroke:#059669
style COMPILE fill:#ede9fe,stroke:#7c3aed
Key insight:
importandsyncwrite directly to knowledge pages (no LLM needed).capture,harvest,digest, andingestland in the inbox staging area first. Runexo compileto let the LLM distill inbox items into your knowledge graph — it merges related items, creates new concept pages, and discards noise.
Commands
Core
| Command | Description |
|---|---|
exo init [path] |
Create brain.db (default: ~/.exo/brain.db) |
exo get <slug> |
Read a page as markdown |
exo put <slug> |
Write or update a page (stdin or --file) |
exo delete <slug> |
Delete a page |
exo list |
List pages (--type, --tag, --limit) |
exo stats |
Brain statistics (page counts, DB size) |
exo health |
Brain health metrics |
exo config |
View and set configuration |
Search
| Command | Description |
|---|---|
exo search <query> |
FTS5 keyword search (--type, --limit) |
exo query <question> |
Hybrid search: FTS5 + vector RRF + LLM query expansion |
Web UI
| Command | Description |
|---|---|
exo ui |
Start the local web UI (--port, --no-open) |
AI Ingestion Pipeline
| Command | Description |
|---|---|
exo capture [text] |
Instantly capture a note to the inbox (no LLM, <100ms) |
exo inbox |
View the inbox queue (items waiting to be compiled) |
exo compile |
Run LLM pipeline: inbox items → structured knowledge pages |
exo harvest |
Harvest learnings from Claude Code / Copilot / Codex session logs |
exo ingest <dir> |
Ingest a mixed directory into inbox (.md/.txt direct; PDF/image/audio auto-extracted) |
exo digest <file> |
Import conversations from a ChatGPT export JSON |
exo import-chatgpt <dir> |
Import a full ChatGPT export directory (conversations + images) |
Files & Multimodal
| Command | Description |
|---|---|
exo attach <slug> <file> |
Attach a file to a page (PDF, image, DOCX, audio, video) |
exo detach <slug> <file> |
Detach a file from a page |
exo files |
List all files attached to your brain |
exo describe [file-slug] |
Extract and embed content from files via AI (images, PDFs, DOCX, audio) |
Embeddings & Sync
| Command | Description |
|---|---|
exo embed |
Generate vector embeddings for pages (--all, --rebuild) |
exo sync <dir> |
Sync a directory of markdown files into the brain |
exo import <file|dir> |
Import a markdown file or directory |
exo export |
Export pages to markdown files |
Knowledge Graph
| Command | Description |
|---|---|
exo link <from> <to> |
Create a cross-reference between two pages |
exo unlink <from> <to> |
Remove a cross-reference |
exo backlinks <slug> |
Show pages linking to a slug |
exo tag <slug> <tag> |
Add a tag |
exo untag <slug> <tag> |
Remove a tag |
exo tags [slug] |
List all tags, or tags for a specific page |
exo graph <slug> |
Traverse the knowledge graph from a slug |
exo timeline <slug> |
View or add timeline entries for a page |
exo versions <slug> |
Manage page versions (snapshot, list, revert) |
Maintenance
| Command | Description |
|---|---|
exo lint |
Check for stale, orphaned, and low-confidence pages |
exo doctor |
Run health checks on the database and configuration |
exo check-update |
Check for a newer version on npm |
MCP / Agent
| Command | Description |
|---|---|
exo serve |
Start the MCP stdio server |
exo setup-mcp |
Auto-configure MCP in Claude Code and Cursor |
exo call <tool> |
Invoke any MCP tool directly from the CLI |
exo tools-json |
Print all MCP tool definitions as JSON |
Configuration
exo reads ~/.exo/config.toml. Use exo config to view and exo config set <key> <value> to edit.
[db]
path = "~/.exo/brain.db"
[embed]
base_url = "https://api.openai.com/v1"
api_key = "sk-..."
model = "text-embedding-3-large"
[compile]
base_url = "https://api.openai.com/v1"
api_key = "sk-..."
model = "gpt-4o"
[vision]
base_url = "https://api.openai.com/v1"
api_key = "sk-..."
model = "gpt-4o"
[ui]
port = 7499
Any OpenAI-compatible provider works (Vercel AI Gateway, Azure OpenAI, Ollama, etc.).
DB path resolution
Priority order:
--db <path>flag (per-command override)EXO_DBenvironment variabledb.pathin~/.exo/config.toml- Default:
~/.exo/brain.db
# Per-command
exo query "rate limiting" --db ~/work/brain.db
# Shell session
export EXO_DB=~/work/brain.db
Page format
Pages use YAML frontmatter. A --- separator (with blank lines around it) splits compiled knowledge from timeline entries.
---
title: Redis Rate Limiting
type: concept
confidence: 9
valid_until: 2027-01-01
tags: [redis, backend, rate-limiting]
sources: [https://redis.io/docs/manual/patterns/]
---
# Redis Rate Limiting
Token bucket at 100 req/s per user. Use INCR + EXPIRE for sliding window.
Lua scripts ensure atomicity across INCR + EXPIRE.
---
## Timeline
- **2024-03-15**: Deployed to production. Token bucket chosen over leaky bucket.
- **2024-06-01**: Switched to sliding window after P99 spike analysis.
Slug prefixes and page types
| Prefix | Type |
|---|---|
concepts/ |
concept |
learnings/ |
learning |
people/ |
person |
projects/ |
project |
sources/ |
source |
Frontmatter fields
| Field | Type | Description |
|---|---|---|
title |
string | Page title (required) |
type |
string | Page type (inferred from slug prefix if absent) |
confidence |
0–10 | How sure you are this is still accurate |
valid_until |
YYYY-MM-DD | Flag as stale after this date |
tags |
string[] | Arbitrary labels |
sources |
string[] | URLs or references |
Hybrid search
exo query combines three signals via Reciprocal Rank Fusion (RRF):
- FTS5 keyword search — exact term matching, supports Chinese via LIKE fallback
- Vector search — cosine similarity on
text-embedding-3-largeembeddings (requiresexo embed) - LLM query expansion — rewrites your query into synonyms and related terms before searching
# Full hybrid (requires embeddings)
exo query "how to prevent API abuse"
# Keyword only (no API calls, instant)
exo search "redis rate limit"
# Disable query expansion (faster, exact terms)
exo query "redis INCR EXPIRE" --no-expand
Run exo embed --all after ingesting new content to keep vector search current.
AI ingestion
Capture → Compile pipeline
# 1. Capture anything instantly (no LLM, goes to inbox)
exo capture "Bun 1.2 ships native S3 client"
echo "Long note from stdin" | exo capture --title "My Note"
# 2. Check inbox
exo inbox
# 3. Compile inbox → structured knowledge pages (uses LLM)
exo compile
exo compile --yes # skip confirmations
Harvest from AI session logs
# Harvest Claude Code sessions (default)
exo harvest
# Harvest from all supported tools
exo harvest --source all
# Preview without writing
exo harvest --dry-run
Supported sources: Claude Code, GitHub Copilot CLI, Codex.
Import ChatGPT conversations
# Export from ChatGPT settings → import
exo digest conversations.json
# Full export directory (conversations + images)
exo import-chatgpt ~/Downloads/chatgpt-export/
Attach files
# Attach and describe an image (calls vision API)
exo attach concepts/my-page screenshot.png --describe
# Attach a PDF (auto-extracts and indexes text per page)
exo attach concepts/my-page paper.pdf
# Attach audio with transcription (calls Whisper API)
exo attach concepts/my-page meeting.mp3 --transcribe
# Process all unprocessed attached files
exo describe --all
MCP server
exo exposes a Model Context Protocol server so Claude Code and Cursor can read and write your brain directly.
exo setup-mcp # auto-writes ~/.claude/mcp.json and ~/.cursor/mcp.json
To configure manually in ~/.claude/mcp.json:
{
"mcpServers": {
"exo": {
"command": "exo",
"args": ["serve"]
}
}
}
Available MCP tools: brain_search, brain_query, brain_get, brain_put, brain_list, brain_link, brain_stats, brain_lint_summary, brain_capture, brain_timeline.
Lint
exo lint surfaces three classes of issues:
- Stale —
valid_untilis in the past - Low confidence —
confidence <= 3 - Orphaned — no links in or out, no tags
exo lint # all issues
exo lint --json # machine-readable output
Development
git clone https://github.com/guqing/exo
cd exo
bun install
bun run dev # run from source: bun src/cli.ts
bun run ui:dev -- --db ~/path/to/brain.db
# API on 7499, Vite UI on 5173, /api proxied automatically
bun test ./src/tests/ # run test suite
bun run build # compile to single binary → bin/exo
License
MIT
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。