Skip to content

Commit 1038bcc

Browse files
committed
docs: update CLAUDE.md, README, CHANGELOG for v1.3
1 parent 3d954a2 commit 1038bcc

3 files changed

Lines changed: 138 additions & 12 deletions

File tree

CHANGELOG.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,23 @@
11
# Changelog
22

3+
## v1.3.0 — HTTP/REST Transport (2026-03-26)
4+
5+
### Added
6+
- **HTTP REST API** (`http.rs`) — axum-based HTTP server alongside MCP, enabled via `engraph serve --http`
7+
- **20 REST endpoints** mirroring all 19 MCP tools + update-metadata
8+
- **API key authentication**`eg_` prefixed keys with read/write permission levels
9+
- **Rate limiting** — configurable per-key token bucket (requests/minute)
10+
- **CORS** — configurable allowed origins for web-based agents
11+
- **Graceful shutdown** — CancellationToken coordinates MCP + HTTP + watcher exit
12+
- **API key management CLI**`engraph configure --add-api-key/--list-api-keys/--revoke-api-key`
13+
- **`--no-auth` mode** — local development without API keys (127.0.0.1 only)
14+
15+
### Changed
16+
- `engraph serve` gains `--http`, `--port`, `--host`, `--no-auth` flags
17+
- Module count: 23 → 24
18+
- Test count: 361 → 385
19+
- New dependencies: axum, tower-http, tower, rand, tokio-util
20+
321
## v1.2.0 — Temporal Search (2026-03-26)
422

523
### Added

CLAUDE.md

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Local knowledge graph + intelligence layer for Obsidian vaults. Rust CLI + MCP s
44

55
## Architecture
66

7-
Single binary with 23 modules behind a lib crate:
7+
Single binary with 24 modules behind a lib crate:
88

99
- `config.rs` — loads `~/.engraph/config.toml` and `vault.toml`, merges CLI args, provides `data_dir()`. Includes `intelligence: Option<bool>`, `[models]` section for model overrides, `[obsidian]` section (CLI path, enabled flag), and `[agents]` section (registered AI agent names). `Config::save()` writes back to disk.
1010
- `chunker.rs` — smart chunking with break-point scoring algorithm. Finds optimal split points considering headings, code fences, blank lines, and thematic breaks. `split_oversized_chunks()` handles token-aware secondary splitting with overlap
@@ -23,14 +23,15 @@ Single binary with 23 modules behind a lib crate:
2323
- `writer.rs` — write pipeline orchestrator. 5-step pipeline: resolve tags (fuzzy match + register new), discover links (exact + fuzzy), place in folder, atomic file write (temp + rename), and index update. Supports create, append, update_metadata, move_note, archive, unarchive, edit (section-level replace/prepend/append), rewrite (full content with frontmatter preservation), edit_frontmatter (granular set/remove/add_tag/remove_tag/add_alias/remove_alias ops), and delete (soft archive or hard permanent) operations with mtime-based conflict detection and crash recovery via temp file cleanup
2424
- `watcher.rs` — file watcher for `engraph serve`. OS thread producer (notify-debouncer-full, 2s debounce) sends `Vec<WatchEvent>` over tokio::mpsc to async consumer task. Two-pass batch processing: mutations (index_file/remove_file/rename_file) then edge rebuild. Move detection via content hash matching. Placement correction on file moves. Centroid adjustment on file add/remove. Startup reconciliation via `run_index_shared`. `recent_writes` map coordination with MCP server to prevent double re-indexing of files written through the write pipeline
2525
- `serve.rs` — MCP stdio server via rmcp SDK. Exposes 19 tools: 8 read (search, read, read_section, list, vault_map, who, project, context) + 10 write (create, append, update_metadata, move_note, archive, unarchive, edit, rewrite, edit_frontmatter, delete) + 1 diagnostic (health). `edit_frontmatter` replaces `update_metadata` for granular frontmatter mutations. EngraphServer struct with Arc+Mutex wrapping for async handlers. Loads intelligence models (orchestrator + reranker) when enabled, wires into `search_with_intelligence`. Spawns file watcher on startup. CLI events table provides audit log for write operations. `recent_writes` map prevents double re-indexing of MCP-written files
26+
- `http.rs` — axum-based HTTP REST API server, enabled via `engraph serve --http`. 20 REST endpoints mirroring all 19 MCP tools + update-metadata. API key authentication with `eg_` prefixed keys and read/write permission levels. Per-key token bucket rate limiting (configurable requests/minute). CORS with configurable allowed origins for web-based agents. `--no-auth` mode for local development (127.0.0.1 only). Graceful shutdown via `CancellationToken` coordinating MCP + HTTP + watcher exit
2627
- `graph.rs` — vault graph agent. Extracts wikilink targets, expands search results by following graph connections 1-2 hops. Relevance filtering via FTS5 term check and shared tags
2728
- `profile.rs` — vault profile detection. Auto-detects PARA/Folders/Flat structure, vault type (Obsidian/Logseq/Plain), wikilinks, frontmatter, tags. Content-based role detection for people/daily/archive folders by content patterns (not just names). Writes/loads `vault.toml`
2829
- `store.rs` — SQLite persistence. Tables: `meta`, `files` (with docid, created_by), `chunks` (with vector BLOBs), `chunks_fts` (FTS5), `edges` (vault graph), `tombstones`, `tag_registry`, `folder_centroids`, `placement_corrections`, `link_skiplist` (reserved), `llm_cache` (orchestrator result cache), `cli_events` (audit log for CLI operations). `vec_chunks` virtual table (sqlite-vec) for KNN search. Dynamic embedding dimension stored in meta. `has_dimension_mismatch()` and `reset_for_reindex()` for migration. Enhanced `resolve_file()` with fuzzy Levenshtein matching as final fallback
2930
- `indexer.rs` — orchestrates vault walking (via `ignore` crate for `.gitignore` support), diffing, chunking, embedding, writes to store + sqlite-vec + FTS5, vault graph edge building (wikilinks + people detection), and folder centroid computation. Exposes `index_file`, `remove_file`, `rename_file` as public per-file functions. `run_index_shared` accepts external store/embedder for watcher FullRescan. Dimension migration on model change.
3031
- `temporal.rs` — temporal search lane. Extracts note dates from frontmatter `date:` field or `YYYY-MM-DD` filename patterns. Heuristic date parsing for natural language ("today", "yesterday", "last week", "this month", "recent", month names, ISO dates, date ranges). Smooth decay scoring for files near but outside target date range. Provides `extract_note_date()` for indexing and `score_temporal()` + `parse_date_range_heuristic()` for search
3132
- `search.rs` — hybrid search orchestrator. `search_with_intelligence()` runs the full pipeline: orchestrate (intent + expansions) → 5-lane RRF retrieval (semantic + FTS5 + graph + reranker + temporal) per expansion → two-pass RRF fusion. `search_internal()` is a thin wrapper without intelligence models. Adaptive lane weights per query intent including temporal (1.5 weight for time-aware queries). Results display normalized confidence percentages (0-100%) instead of raw RRF scores.
3233

33-
`main.rs` is a thin clap CLI (async via `#[tokio::main]`). Subcommands: `index` (with progress bar), `search` (with `--explain`, loads intelligence models when enabled), `status` (shows intelligence state + date coverage stats), `clear`, `init` (intelligence onboarding prompt, detects Obsidian CLI + AI agents), `configure` (`--enable-intelligence`, `--disable-intelligence`, `--model`, `--obsidian-cli`, `--no-obsidian-cli`, `--agent`), `models`, `graph` (show/stats), `context` (read/list/vault-map/who/project/topic), `write` (create/append/update-metadata/move/edit/rewrite/edit-frontmatter/delete), `serve` (MCP stdio server with file watcher + intelligence).
34+
`main.rs` is a thin clap CLI (async via `#[tokio::main]`). Subcommands: `index` (with progress bar), `search` (with `--explain`, loads intelligence models when enabled), `status` (shows intelligence state + date coverage stats), `clear`, `init` (intelligence onboarding prompt, detects Obsidian CLI + AI agents), `configure` (`--enable-intelligence`, `--disable-intelligence`, `--model`, `--obsidian-cli`, `--no-obsidian-cli`, `--agent`, `--add-api-key`, `--list-api-keys`, `--revoke-api-key`), `models`, `graph` (show/stats), `context` (read/list/vault-map/who/project/topic), `write` (create/append/update-metadata/move/edit/rewrite/edit-frontmatter/delete), `serve` (MCP stdio server with file watcher + intelligence + optional `--http`/`--port`/`--host`/`--no-auth` for HTTP REST API).
3435

3536
## Key patterns
3637

@@ -69,12 +70,17 @@ Single vault only. Re-indexing a different vault path triggers a confirmation pr
6970
- `ignore` (0.4) — vault walking with `.gitignore` support
7071
- `rusqlite` (0.32) — bundled SQLite with FTS5 support
7172
- `rmcp` (1.2) — MCP server SDK for stdio transport
73+
- `axum` — HTTP framework for REST API server
74+
- `tower-http` — CORS middleware for axum
75+
- `tower` — middleware layer utilities
76+
- `rand` — random API key generation
77+
- `tokio-util``CancellationToken` for graceful multi-server shutdown
7278
- `notify` (7.0) — cross-platform filesystem notification (FSEvents on macOS, inotify on Linux)
7379
- `notify-debouncer-full` (0.4) — debouncing + best-effort inode-based rename tracking
7480

7581
## Testing
7682

77-
- Unit tests in each module (`cargo test --lib`) — 361 tests, no network required
83+
- Unit tests in each module (`cargo test --lib`) — 385 tests, no network required
7884
- Integration tests (`cargo test --test integration -- --ignored`) — require GGUF model download
7985
- Build requires CMake (for llama.cpp C++ compilation)
8086

README.md

Lines changed: 111 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ Plain vector search treats your notes as isolated documents. But knowledge isn't
1818

1919
- **5-lane hybrid search** — semantic embeddings + BM25 full-text + graph expansion + cross-encoder reranking + temporal scoring, fused via [Reciprocal Rank Fusion](https://plg.uwaterloo.ca/~gvcormac/cormacksigir09-rrf.pdf). An LLM orchestrator classifies queries and adapts lane weights per intent. Time-aware queries like "what happened last week" or "March 2026 notes" activate the temporal lane automatically.
2020
- **MCP server for AI agents**`engraph serve` exposes 19 tools (search, read, section-level editing, frontmatter mutations, vault health, context bundles, note creation) that Claude, Cursor, or any MCP client can call directly.
21+
- **HTTP REST API**`engraph serve --http` adds an axum-based HTTP server alongside MCP with 20 REST endpoints, API key authentication, rate limiting, and CORS. Web-based agents and scripts can query your vault with simple `curl` calls.
2122
- **Section-level editing** — AI agents can read, replace, prepend, or append to specific sections by heading. Full note rewriting with frontmatter preservation. Granular frontmatter mutations (set/remove fields, add/remove tags and aliases).
2223
- **Vault health diagnostics** — detect orphan notes, broken wikilinks, stale content, and tag hygiene issues. Available as MCP tool and CLI command.
2324
- **Obsidian CLI integration** — auto-detects running Obsidian and delegates compatible operations. Circuit breaker (Closed/Degraded/Open) ensures graceful fallback.
@@ -51,17 +52,16 @@ Your vault (markdown files)
5152
│ engraph serve │
5253
│ │
5354
│ MCP Server (stdio) + File Watcher │
55+
│ + HTTP REST API (--http, optional) │
5456
│ │
5557
│ Search: Orchestrator → 4-lane retrieval │
5658
│ → Reranker → Two-pass RRF fusion │
5759
│ │
58-
│ 19 tools: search, read, read_section, │
59-
│ edit, rewrite, edit_frontmatter, delete, │
60-
│ health, context, who, project, create... │
60+
│ 19 MCP tools + 20 REST endpoints │
6161
└─────────────────────────────────────────────┘
6262
6363
64-
Claude / Cursor / any MCP client
64+
Claude / Cursor / any MCP client / curl / web agents
6565
```
6666

6767
1. **Index** — walks your vault, chunks markdown by headings, embeds with a local GGUF model via llama.cpp (Metal GPU on macOS), stores everything in SQLite with FTS5 + sqlite-vec + a wikilink graph
@@ -129,6 +129,32 @@ engraph serve
129129

130130
Now Claude can search your vault, read notes, build context bundles, and create new notes — all through structured tool calls.
131131

132+
**Enable HTTP REST API:**
133+
134+
```bash
135+
# Start MCP + HTTP server on port 3030
136+
engraph serve --http
137+
138+
# Custom port and host
139+
engraph serve --http --port 8080 --host 0.0.0.0
140+
141+
# Local development without API keys (127.0.0.1 only)
142+
engraph serve --http --no-auth
143+
```
144+
145+
**API key management:**
146+
147+
```bash
148+
# Add a new API key (read or write permission)
149+
engraph configure --add-api-key
150+
151+
# List existing keys
152+
engraph configure --list-api-keys
153+
154+
# Revoke a key
155+
engraph configure --revoke-api-key eg_abc123...
156+
```
157+
132158
**Enable intelligence (optional, ~1.3GB download):**
133159

134160
```bash
@@ -234,6 +260,81 @@ engraph context health
234260

235261
Returns orphan notes (no links in or out), broken wikilinks, stale notes, and tag hygiene issues.
236262

263+
## HTTP REST API
264+
265+
`engraph serve --http` adds a full REST API alongside the MCP server, exposing the same capabilities over HTTP for web agents, scripts, and integrations.
266+
267+
**20 endpoints:**
268+
269+
| Method | Endpoint | Permission | Description |
270+
|--------|----------|------------|-------------|
271+
| GET | `/api/health-check` | read | Server health check |
272+
| POST | `/api/search` | read | Hybrid search (semantic + FTS5 + graph + reranker + temporal) |
273+
| GET | `/api/read/{file}` | read | Read full note content + metadata |
274+
| GET | `/api/read-section` | read | Read a specific section by heading |
275+
| GET | `/api/list` | read | List notes with optional tag/folder/created_by filters |
276+
| GET | `/api/vault-map` | read | Vault structure overview (folders, tags, recent files) |
277+
| GET | `/api/who/{name}` | read | Person context bundle |
278+
| GET | `/api/project/{name}` | read | Project context bundle |
279+
| POST | `/api/context` | read | Rich topic context with token budget |
280+
| GET | `/api/health` | read | Vault health diagnostics |
281+
| POST | `/api/create` | write | Create a new note |
282+
| POST | `/api/append` | write | Append content to existing note |
283+
| POST | `/api/edit` | write | Section-level editing (replace/prepend/append) |
284+
| POST | `/api/rewrite` | write | Full note rewrite (preserves frontmatter) |
285+
| POST | `/api/edit-frontmatter` | write | Granular frontmatter mutations |
286+
| POST | `/api/move` | write | Move note to different folder |
287+
| POST | `/api/archive` | write | Soft-delete (archive) a note |
288+
| POST | `/api/unarchive` | write | Restore archived note |
289+
| POST | `/api/update-metadata` | write | Update note metadata |
290+
| POST | `/api/delete` | write | Delete note (soft or hard) |
291+
292+
**Authentication:**
293+
294+
All requests require an API key via the `Authorization` header:
295+
296+
```bash
297+
curl -H "Authorization: Bearer eg_abc123..." http://localhost:3030/api/vault-map
298+
```
299+
300+
Keys have either `read` or `write` permission. Write keys can access all endpoints; read keys are restricted to read-only endpoints. Use `--no-auth` for local development without keys (127.0.0.1 only).
301+
302+
**curl examples:**
303+
304+
```bash
305+
# Search
306+
curl -X POST http://localhost:3030/api/search \
307+
-H "Authorization: Bearer eg_..." \
308+
-H "Content-Type: application/json" \
309+
-d '{"query": "authentication architecture", "top_n": 5}'
310+
311+
# Read a note
312+
curl http://localhost:3030/api/read/01-Projects/API-Design.md \
313+
-H "Authorization: Bearer eg_..."
314+
315+
# Create a note
316+
curl -X POST http://localhost:3030/api/create \
317+
-H "Authorization: Bearer eg_..." \
318+
-H "Content-Type: application/json" \
319+
-d '{"content": "# Meeting Notes\n\nDiscussed auth timeline.", "tags": ["meeting", "auth"]}'
320+
```
321+
322+
**Rate limiting:** Configurable per-key token bucket (requests per minute). Defaults to 60 req/min. Returns `429 Too Many Requests` when exceeded.
323+
324+
**CORS:** Configurable allowed origins in `config.toml` under `[http]`. Defaults to allow all origins for local development.
325+
326+
```toml
327+
[http]
328+
port = 3030
329+
host = "127.0.0.1"
330+
cors_origins = ["http://localhost:3000", "https://myapp.example.com"]
331+
rate_limit = 60
332+
333+
[[http.api_keys]]
334+
key = "eg_..."
335+
permission = "write"
336+
```
337+
237338
## Use cases
238339

239340
**AI-assisted knowledge work** — Give Claude or Cursor deep access to your personal knowledge base. Instead of copy-pasting context, the agent searches, reads, and cross-references your notes directly.
@@ -251,7 +352,7 @@ Returns orphan notes (no links in or out), broken wikilinks, stale notes, and ta
251352
| Search method | 5-lane RRF (semantic + BM25 + graph + reranker + temporal) | Vector similarity only | Keyword only |
252353
| Query understanding | LLM orchestrator classifies intent, adapts weights | None | None |
253354
| Understands note links | Yes (wikilink graph traversal) | No | Limited (backlinks panel) |
254-
| AI agent access | MCP server (19 tools) | Custom API needed | No |
355+
| AI agent access | MCP server (19 tools) + HTTP REST API (20 endpoints) | Custom API needed | No |
255356
| Write capability | Create/edit/rewrite/delete with smart filing | No | Manual |
256357
| Vault health | Orphans, broken links, stale notes, tag hygiene | No | Limited |
257358
| Real-time sync | File watcher, 2s debounce | Manual re-index | N/A |
@@ -269,6 +370,7 @@ engraph is not a replacement for Obsidian — it's the intelligence layer that s
269370
- llama.cpp inference via Rust bindings (GGUF models, Metal GPU on macOS, CUDA on Linux)
270371
- Intelligence opt-in: heuristic fallback when disabled, LLM-powered when enabled
271372
- MCP server with 19 tools (8 read, 10 write, 1 diagnostic) via stdio
373+
- HTTP REST API with 20 endpoints, API key auth (`eg_` prefix), rate limiting, CORS — enabled via `engraph serve --http`
272374
- Section-level reading and editing: target specific headings with replace/prepend/append modes
273375
- Full note rewriting with automatic frontmatter preservation
274376
- Granular frontmatter mutations: set/remove fields, add/remove tags and aliases
@@ -283,7 +385,7 @@ engraph is not a replacement for Obsidian — it's the intelligence layer that s
283385
- Enhanced file resolution with fuzzy Levenshtein matching fallback
284386
- Content-based folder role detection (people, daily, archive) by content patterns
285387
- Configurable model overrides for multilingual support
286-
- 361 unit tests, CI on macOS + Ubuntu
388+
- 385 unit tests, CI on macOS + Ubuntu
287389

288390
## Roadmap
289391

@@ -293,7 +395,7 @@ engraph is not a replacement for Obsidian — it's the intelligence layer that s
293395
- [x] ~~Vault health monitor — orphan notes, broken links, stale content, tag hygiene~~ (v1.1)
294396
- [x] ~~Obsidian CLI integration — auto-detect and delegate with circuit breaker~~ (v1.1)
295397
- [x] ~~Temporal search — find notes by time period, date-aware queries~~ (v1.2)
296-
- [ ] HTTP/REST API — complement MCP with a standard web API (v1.3)
398+
- [x] ~~HTTP/REST API — complement MCP with a standard web API~~ (v1.3)
297399
- [ ] Multi-vault — search across multiple vaults (v1.4)
298400

299401
## Configuration
@@ -328,7 +430,7 @@ All data stored in `~/.engraph/` — single SQLite database (~10MB typical), GGU
328430
## Development
329431

330432
```bash
331-
cargo test --lib # 361 unit tests, no network (requires CMake for llama.cpp)
433+
cargo test --lib # 385 unit tests, no network (requires CMake for llama.cpp)
332434
cargo clippy -- -D warnings
333435
cargo fmt --check
334436

@@ -340,7 +442,7 @@ cargo test --test integration -- --ignored
340442

341443
Contributions welcome. Please open an issue first to discuss what you'd like to change.
342444

343-
The codebase is 23 Rust modules behind a lib crate. `CLAUDE.md` in the repo root has detailed architecture documentation for AI-assisted development.
445+
The codebase is 24 Rust modules behind a lib crate. `CLAUDE.md` in the repo root has detailed architecture documentation for AI-assisted development.
344446

345447
## License
346448

0 commit comments

Comments
 (0)