@oomkapwn/enquire-mcp 2.9.0 → 2.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +121 -0
- package/README.md +182 -196
- package/dist/doctor.d.ts +54 -0
- package/dist/doctor.d.ts.map +1 -0
- package/dist/doctor.js +369 -0
- package/dist/doctor.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +118 -3
- package/dist/index.js.map +1 -1
- package/dist/ocr.d.ts +66 -0
- package/dist/ocr.d.ts.map +1 -0
- package/dist/ocr.js +199 -0
- package/dist/ocr.js.map +1 -0
- package/dist/tools.d.ts +41 -0
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +40 -0
- package/dist/tools.js.map +1 -1
- package/docs/api.md +3 -1
- package/package.json +4 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,127 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented here. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and the project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
4
4
|
|
|
5
|
+
## [2.11.0] — 2026-05-08
|
|
6
|
+
|
|
7
|
+
**Sprint 11 — zero-touch onboarding (`doctor` + `setup`).** Closes the biggest UX gap in the project: setup friction. Before this, getting full hybrid retrieval required 3 separate commands (`install-model` → `build-embeddings` → `serve --persistent-index`), and there was no quick way to see "is everything ready?" without triggering each codepath.
|
|
8
|
+
|
|
9
|
+
### Added — `enquire-mcp doctor --vault <path>`
|
|
10
|
+
|
|
11
|
+
Read-only health check. Verifies every prerequisite for full hybrid retrieval:
|
|
12
|
+
- Vault path exists + is readable, with note/PDF/canvas counts (privacy filter applied)
|
|
13
|
+
- All 5 optional deps load cleanly: `better-sqlite3` (FTS5 + embed-db), `@huggingface/transformers` (ML embeddings + reranker), `pdfjs-dist` (PDF read + indexing), `tesseract.js` + `@napi-rs/canvas` (OCR for scanned PDFs)
|
|
14
|
+
- Embedding model cache — probes 5+ candidate paths (transformers.js v3 default `node_modules/@huggingface/transformers/.cache/Xenova/`, HF_HOME, TRANSFORMERS_CACHE env vars, `~/.cache/huggingface/`, macOS XDG `~/Library/Caches/huggingface/`)
|
|
15
|
+
- FTS5 BM25 index existence + per-vault file/chunk counts
|
|
16
|
+
- Embed-db existence + size
|
|
17
|
+
|
|
18
|
+
Color-coded ✓ / ⚠ / ✗ output (auto-detects TTY so piped output stays clean). Returns 0 if everything is ready, 1 if any critical piece is missing. `--json` flag for machine-readable output (useful for CI / scripted setup checks).
|
|
19
|
+
|
|
20
|
+
### Added — `enquire-mcp setup --vault <path>`
|
|
21
|
+
|
|
22
|
+
Zero-touch onboarding. Runs the install + build sequence in one command:
|
|
23
|
+
|
|
24
|
+
1. **Step 1/3:** Cold-build FTS5 BM25 index (`syncFtsIndex` + optional `syncPdfFtsIndex` if `--include-pdfs`)
|
|
25
|
+
2. **Step 2/3:** Install embedding model (downloads ~120 MB for `multilingual` default, cached for reuse)
|
|
26
|
+
3. **Step 3/3:** Build embedding index (`syncEmbedDb` + optional `syncPdfEmbedDb`)
|
|
27
|
+
|
|
28
|
+
Idempotent — re-running on a fully set-up vault is a fast no-op pass that just reports the existing state. `--skip-embeddings` for users who only want BM25. `--include-pdfs` for vaults with PDFs.
|
|
29
|
+
|
|
30
|
+
After successful setup, prints the exact `serve` command to run.
|
|
31
|
+
|
|
32
|
+
### Surface delta vs v2.10.0
|
|
33
|
+
|
|
34
|
+
- **+2 CLI subcommands** (`doctor`, `setup`)
|
|
35
|
+
- **+1 source module** (`src/doctor.ts`, ~310 lines)
|
|
36
|
+
- **No new tools, no new prompts, no schema changes, no new deps.**
|
|
37
|
+
|
|
38
|
+
### Tests
|
|
39
|
+
|
|
40
|
+
522 unit tests pass (was 509 in v2.10.0, +13 new):
|
|
41
|
+
- **runDoctor (+8):** result shape contract, vault check ok-vs-error, optional-dep checks (5 deps), model-cache check missing-vs-ok with synthetic Xenova dir, FTS5 + embed-db checks not-built status, ready boolean correctness against summary tally.
|
|
42
|
+
- **formatCheck + formatDoctorResult (+5):** non-empty output for each status, detail + hint inclusion, hint omission for ok status, banner shape, NOT-READY verdict on failures.
|
|
43
|
+
|
|
44
|
+
### Migration
|
|
45
|
+
|
|
46
|
+
**No-op for default users.** Both new subcommands are opt-in. Existing `serve` / `serve-http` / `index` / `build-embeddings` behavior unchanged.
|
|
47
|
+
|
|
48
|
+
### Strategic position
|
|
49
|
+
|
|
50
|
+
v2.11.0 is a UX-focused sprint, not a capability sprint. The retrieval moats (hybrid RRF, graph-boost, PDF + OCR, cross-encoder reranking) all stayed put. What changed: the **time-to-first-useful-result** drops from ~5 minutes (figure out 3 commands, paste them, wait) to ~30 seconds (`enquire-mcp setup --vault <path>` and you're done).
|
|
51
|
+
|
|
52
|
+
Demo flow:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
$ enquire-mcp doctor --vault ~/Obsidian
|
|
56
|
+
NOT READY — 1 missing/error, 0 warnings, 7 ok
|
|
57
|
+
✗ Embedding model cache → enquire-mcp install-model multilingual
|
|
58
|
+
|
|
59
|
+
$ enquire-mcp setup --vault ~/Obsidian
|
|
60
|
+
>> Step 1/3: Cold-build FTS5 index ...
|
|
61
|
+
>> Step 2/3: Install embedding model ...
|
|
62
|
+
>> Step 3/3: Build embedding index ...
|
|
63
|
+
✓ Setup complete. Now run:
|
|
64
|
+
enquire-mcp serve --vault ~/Obsidian --persistent-index
|
|
65
|
+
|
|
66
|
+
$ enquire-mcp doctor --vault ~/Obsidian
|
|
67
|
+
READY — all critical checks pass (8 ok, 0 warnings)
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## [2.10.0] — 2026-05-08
|
|
71
|
+
|
|
72
|
+
**Sprint 10 — OCR for image-only / scanned PDFs.** Closes the v2.7-v2.8-v2.9 PDF retrieval story. v2.7.0 added text-extraction tools; v2.8.0 blended PDF chunks into hybrid search; v2.9.0 added cross-encoder reranking. v2.10.0 makes the **scanned / camera-captured** PDFs in your vault searchable too — Tesseract.js OCR over each page bitmap.
|
|
73
|
+
|
|
74
|
+
### Added — `obsidian_ocr_pdf`
|
|
75
|
+
|
|
76
|
+
Runs Tesseract OCR over each page of an image-only / scanned PDF and returns the same shape as `obsidian_read_pdf` plus a per-page `confidence` score (0-100) and a doc-level `mean_confidence`. Use this when `obsidian_read_pdf` returns `has_text: false` (typical for scans, photographed paper, image-only PDFs).
|
|
77
|
+
|
|
78
|
+
- **Multilingual** via `lang` (default `'eng'`; multi-lang via `'+'`, e.g. `'eng+rus'` for English+Russian mixed scans). Trained-data files for each language download on first use into Tesseract's local cache (~10 MB per language).
|
|
79
|
+
- **Optional `pages` range** for partial OCR of long docs — OCR is the slowest step in the pipeline (~1-2s per page on M1 CPU), so a 100-page paper takes minutes.
|
|
80
|
+
- **Optional `scale`** (DPI multiplier, default 2 ~ 150 DPI, capped at 4 server-side to prevent adversarial-PDF OOM).
|
|
81
|
+
- **Per-page failure isolation** — one bad page doesn't sink the document.
|
|
82
|
+
- **Tesseract worker terminated after each call** so HTTP transport doesn't accumulate per-request state.
|
|
83
|
+
|
|
84
|
+
### Added — two new optional dependencies
|
|
85
|
+
|
|
86
|
+
`tesseract.js@^7.0.0` (~1.4 MB unpacked, pure WebAssembly OCR engine) and `@napi-rs/canvas@^1.0.0` (~125 KB unpacked, native PDF→bitmap rendering with platform-specific binaries downloading conditionally) — both `optionalDependencies` so the markdown-only path stays zero-cost.
|
|
87
|
+
|
|
88
|
+
Lazy-imported via the same pattern as `pdfjs-dist` (v2.7.0), `better-sqlite3` (v1.x), and `@huggingface/transformers` (v2.0.0). Missing-deps surface a clean install-hint error rather than a cryptic module-not-found stack.
|
|
89
|
+
|
|
90
|
+
### Server-side hardening
|
|
91
|
+
|
|
92
|
+
- `isEvalSupported: false`, `useSystemFonts: false`, `verbosity: 0` on pdfjs's `loadingTask` (matches v2.7.0 PDF read path).
|
|
93
|
+
- Render scale clamped to `[0.5, 4]` so adversarial PDFs claiming 100-DPI multipliers don't OOM the server.
|
|
94
|
+
- Tesseract worker terminated in a `finally` block so WebAssembly state never leaks even if a render or recognize call throws mid-page.
|
|
95
|
+
- Same path-safety + privacy filter (`--exclude-glob` / `--read-paths` / `vault.stat`) as `obsidian_read_note` and `obsidian_read_pdf`. Audit-tested at every read boundary.
|
|
96
|
+
|
|
97
|
+
### Tests
|
|
98
|
+
|
|
99
|
+
507 unit tests pass (was 502 in v2.9.0, +5 new):
|
|
100
|
+
- **ocrPdf path + privacy contract (+5):** rejects missing path arg, rejects non-existent file, refuses paths excluded by `--exclude-glob`, refuses paths outside `--read-paths` allowlist, accepts both `.pdf` and bare-stem paths consistently.
|
|
101
|
+
|
|
102
|
+
End-to-end OCR validation (loading a real Tesseract worker against a synthetic image-only PDF) is deferred to manual smoke — Tesseract.js + @napi-rs/canvas startup is heavy (~2s) and a real synthetic image-PDF fixture would inflate the test repo.
|
|
103
|
+
|
|
104
|
+
### Surface delta vs v2.9.0
|
|
105
|
+
|
|
106
|
+
- **+1 read tool** (`obsidian_ocr_pdf`)
|
|
107
|
+
- **+2 optional deps** (`tesseract.js`, `@napi-rs/canvas`) — both lazy-loaded, markdown-only path zero-cost
|
|
108
|
+
- **Total surface:** 39 tools (28 always-on read + 1 opt-in `--persistent-index` + 3 opt-in diagnostic + 7 opt-in write) + 17 prompts
|
|
109
|
+
|
|
110
|
+
### Migration
|
|
111
|
+
|
|
112
|
+
**No-op for default users.** OCR runs only when an agent explicitly calls `obsidian_ocr_pdf`. Existing `obsidian_read_pdf` behavior unchanged — it still returns `has_text: false` for scanned PDFs and now points at `obsidian_ocr_pdf` in its tool description.
|
|
113
|
+
|
|
114
|
+
Users on `--omit=optional` who try to call `obsidian_ocr_pdf` get a clean error message naming exactly what to install (`npm install tesseract.js @napi-rs/canvas`).
|
|
115
|
+
|
|
116
|
+
### Strategic position
|
|
117
|
+
|
|
118
|
+
The PDF retrieval story is now complete:
|
|
119
|
+
- v2.7.0 — extraction tools (`obsidian_list_pdfs` / `obsidian_read_pdf`)
|
|
120
|
+
- v2.8.0 — blended into hybrid search (`obsidian_search` returns PDF chunks with `kind: "pdf"` + page citations)
|
|
121
|
+
- v2.9.0 — cross-encoder reranking on the blended candidate set
|
|
122
|
+
- **v2.10.0 — OCR for the image-only / scanned PDFs** the v2.8.0 pipeline previously skipped
|
|
123
|
+
|
|
124
|
+
**No other Obsidian-MCP currently does OCR for scanned PDFs.** Combined with the v2.0-v2.9 retrieval moats, enquire is now the only Obsidian-MCP that gives an agent searchable access to **every** PDF in your vault — text-PDFs, scanned-PDFs, multilingual content — with hybrid retrieval + cross-encoder reranking on top.
|
|
125
|
+
|
|
5
126
|
## [2.9.0] — 2026-05-08
|
|
6
127
|
|
|
7
128
|
**Sprint 9 — BGE cross-encoder reranking on top of RRF.** Cross-encoder reranking is the SOTA technique in IR for boosting retrieval quality over bi-encoder candidates: after RRF fusion, the top-N hits are re-scored by a model that sees query+document interaction directly (instead of comparing pre-computed embeddings). Typical wins: +5-10 NDCG@10 on real-world retrieval. **No other Obsidian-MCP currently does cross-encoder reranking** — this extends our retrieval quality leadership claim.
|
package/README.md
CHANGED
|
@@ -1,284 +1,270 @@
|
|
|
1
1
|
<div align="center">
|
|
2
2
|
|
|
3
|
-
<a href="https://github.com/oomkapwn/enquire-mcp"><img src="./assets/social-preview.png" alt="enquire — MCP server for Obsidian vaults. Hybrid retrieval (BM25 + TF-IDF + ML embeddings via RRF). Wikilinks, frontmatter, backlinks, Dataview, multilingual semantic search. For Claude Code, Cursor, Codex." width="100%"></a>
|
|
3
|
+
<a href="https://github.com/oomkapwn/enquire-mcp"><img src="./assets/social-preview.png" alt="enquire — MCP server for Obsidian vaults. Hybrid retrieval (BM25 + TF-IDF + ML embeddings via RRF + cross-encoder reranking). Wikilinks, frontmatter, backlinks, Dataview, multilingual semantic search, PDFs, remote MCP. For Claude Code, Cursor, Codex." width="100%"></a>
|
|
4
4
|
|
|
5
|
-
# enquire —
|
|
5
|
+
# enquire — give your AI a search engine for your Obsidian vault
|
|
6
6
|
|
|
7
|
-
**Hybrid retrieval
|
|
7
|
+
**Hybrid retrieval. Cross-encoder reranking. PDFs. Multilingual. Remote MCP. Free.**
|
|
8
|
+
|
|
9
|
+
The most advanced Obsidian-MCP you can run today — drop into Claude Code, Claude.ai web, Cursor, ChatGPT, or any MCP client and your agent gets a single `obsidian_search` tool that fuses BM25 + TF-IDF + ML embeddings, reranks with a BGE cross-encoder, and surfaces blended markdown + PDF hits with page citations.
|
|
8
10
|
|
|
9
11
|
[](https://github.com/oomkapwn/enquire-mcp/actions/workflows/ci.yml)
|
|
10
|
-
[](https://www.npmjs.com/package/@oomkapwn/enquire-mcp)
|
|
11
|
-
[](#engineering)
|
|
13
|
-
[](./LICENSE)
|
|
14
|
-
[](https://modelcontextprotocol.io/)
|
|
12
|
+
[](https://www.npmjs.com/package/@oomkapwn/enquire-mcp)
|
|
13
|
+
[](#trust)
|
|
15
14
|
[](https://slsa.dev/spec/v1.0/levels#build-l3)
|
|
15
|
+
[](https://modelcontextprotocol.io/)
|
|
16
|
+
[](./LICENSE)
|
|
17
|
+
[](https://nodejs.org)
|
|
16
18
|
|
|
17
19
|
</div>
|
|
18
20
|
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## ⚡ 30-second quick start
|
|
24
|
+
|
|
19
25
|
```bash
|
|
20
26
|
npm install -g @oomkapwn/enquire-mcp
|
|
21
27
|
enquire-mcp serve --vault ~/Documents/Obsidian\ Vault
|
|
22
28
|
```
|
|
23
29
|
|
|
24
|
-
That's it. Your AI now has structured access to wikilinks, backlinks, frontmatter, Dataview
|
|
30
|
+
That's it. Your AI now has structured access to wikilinks, backlinks, frontmatter, Dataview, and **`obsidian_search`** — the umbrella retrieval tool.
|
|
31
|
+
|
|
32
|
+
**For Claude Code / Cursor / Codex / any MCP client:**
|
|
33
|
+
|
|
34
|
+
```json
|
|
35
|
+
{
|
|
36
|
+
"mcpServers": {
|
|
37
|
+
"obsidian": {
|
|
38
|
+
"command": "npx",
|
|
39
|
+
"args": ["-y", "@oomkapwn/enquire-mcp", "serve", "--vault", "/path/to/vault"]
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**Want hybrid retrieval at full power?** One command (v2.11.0):
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
enquire-mcp setup --vault <path> # downloads model, builds FTS5 + embed indexes
|
|
49
|
+
# then: serve --persistent-index for BM25 + --enable-reranker for cross-encoder
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Already set up? Check status anytime:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
enquire-mcp doctor --vault <path> # color-coded ✓/⚠/✗ health check
|
|
56
|
+
```
|
|
25
57
|
|
|
26
58
|
---
|
|
27
59
|
|
|
28
|
-
##
|
|
60
|
+
## 🎯 The only Obsidian-MCP with…
|
|
29
61
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
| **Hybrid (BM25+TF-IDF+embeddings, RRF)** | ❌ | ❌ | ✅ **only here** |
|
|
41
|
-
| **PDFs blended into hybrid search** | ❌ | ❌ | ✅ **only here** (v2.8.0) |
|
|
42
|
-
| **Cross-encoder reranking on top of RRF** | ❌ | ❌ | ✅ **only here** (v2.9.0) |
|
|
43
|
-
| Per-signal observability on each hit | ❌ | ❌ | ✅ |
|
|
44
|
-
| Privacy filter (`--exclude-glob` / `--read-paths`) | ❌ | n/a | ✅ verified at search + write paths |
|
|
45
|
-
| Standalone (no Obsidian plugin) | varies | ❌ requires Obsidian | ✅ direct vault read |
|
|
46
|
-
| MCP-native (any agent) | varies | ❌ Obsidian-only | ✅ stdio JSON-RPC |
|
|
47
|
-
| **Remote MCP (HTTP transport, bearer auth)** | ❌ | ❌ | ✅ **only here** (v2.6.0) |
|
|
48
|
-
| SLSA-3 provenance | ❌ | n/a | ✅ |
|
|
49
|
-
| Test suite | rare | n/a | ✅ 502 unit tests |
|
|
62
|
+
- ✅ **Hybrid retrieval** (BM25 + TF-IDF + ML embeddings, RRF-fused)
|
|
63
|
+
- ✅ **Cross-encoder reranking** on top of RRF (+5-10 NDCG@10) — `v2.9.0`
|
|
64
|
+
- ✅ **PDFs blended into hybrid search** with `[page: N]` citation markers — `v2.8.0`
|
|
65
|
+
- ✅ **OCR for scanned / image-only PDFs** (Tesseract.js, multilingual) — `v2.10.0`
|
|
66
|
+
- ✅ **Wikilink graph-boost** as a retrieval signal (1-step personalised PageRank seeded by RRF top-K)
|
|
67
|
+
- ✅ **Remote MCP** over HTTP with bearer auth + rate-limit + CORS — `v2.6.0`
|
|
68
|
+
- ✅ **Multilingual** semantic search (50+ languages, runs on CPU, free)
|
|
69
|
+
- ✅ **Note-tethered AI chat threads** persisted as markdown — Smart Connections' #1 paid feature, free here
|
|
70
|
+
|
|
71
|
+
**Read-only by default.** All 7 write tools gated behind `--enable-write`. Privacy filter (`--exclude-glob` / `--read-paths`) verified at every search + write path. SLSA-3 release provenance.
|
|
50
72
|
|
|
51
73
|
---
|
|
52
74
|
|
|
53
|
-
##
|
|
75
|
+
## 🏗️ How retrieval works
|
|
54
76
|
|
|
55
77
|
```mermaid
|
|
56
78
|
graph LR
|
|
57
79
|
Q[Query]
|
|
58
80
|
Q --> S[obsidian_search]
|
|
59
|
-
S --> BM25[BM25 / FTS5<br
|
|
81
|
+
S --> BM25[BM25 / FTS5<br/>--persistent-index]
|
|
60
82
|
S --> TFIDF[TF-IDF<br/>always on]
|
|
61
|
-
S --> EMB[ML embeddings<br/>
|
|
83
|
+
S --> EMB[ML embeddings<br/>build-embeddings]
|
|
62
84
|
BM25 --> RRF{RRF fusion<br/>k=60}
|
|
63
85
|
TFIDF --> RRF
|
|
64
86
|
EMB --> RRF
|
|
65
|
-
RRF -->
|
|
87
|
+
RRF --> GB[Graph boost<br/>α × in-degree]
|
|
88
|
+
GB --> RR[Cross-encoder<br/>reranker<br/>--enable-reranker]
|
|
89
|
+
RR --> R[Ranked hits<br/>per_signal observability]
|
|
66
90
|
```
|
|
67
91
|
|
|
68
|
-
`obsidian_search` auto-detects available signals and fuses them via Reciprocal Rank Fusion (Cormack et al, 2009).
|
|
92
|
+
`obsidian_search` auto-detects available signals and fuses them via Reciprocal Rank Fusion (Cormack et al, 2009). Wikilink graph-boost reranks top-K by 1-step personalised PageRank. Optional cross-encoder reranking (BGE) re-scores top-N for +5-10 NDCG@10. Every hit returns `per_signal` observability so you see WHY each result ranked.
|
|
69
93
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
```
|
|
94
|
+
| Tier | Setup | What you get |
|
|
95
|
+
|---|---|---|
|
|
96
|
+
| **1** | `serve --vault <path>` | TF-IDF (zero setup, instant) |
|
|
97
|
+
| **2** | + `--persistent-index` | + BM25 (sub-100ms top-10) |
|
|
98
|
+
| **3** | + `install-model` + `build-embeddings` | + multilingual ML embeddings |
|
|
99
|
+
| **4** | + `--enable-reranker` | + BGE cross-encoder reranking |
|
|
100
|
+
| **5** | + `--include-pdfs` | + PDFs blended into all of the above |
|
|
101
|
+
| **6** | `serve-http --bearer-token …` | + remote MCP for Claude.ai web, ChatGPT, Cursor HTTP, mobile |
|
|
79
102
|
|
|
80
103
|
---
|
|
81
104
|
|
|
82
|
-
##
|
|
105
|
+
## 🆚 vs alternatives
|
|
83
106
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
107
|
+
| | Other Obsidian-MCPs | Smart Connections (paid) | **enquire** |
|
|
108
|
+
|---|:---:|:---:|:---:|
|
|
109
|
+
| Wikilinks (alias / section / block) | partial | n/a | ✅ full |
|
|
110
|
+
| Backlinks ranked + snippeted | rare | n/a | ✅ |
|
|
111
|
+
| Dataview-style queries | needs plugin | n/a | ✅ first-class |
|
|
112
|
+
| Canvas (`.canvas`) read | rare | n/a | ✅ typed nodes + edges |
|
|
113
|
+
| BM25 full-text | rare | ❌ | ✅ FTS5 SQLite |
|
|
114
|
+
| TF-IDF semantic | ❌ | ❌ | ✅ |
|
|
115
|
+
| ML embeddings (multilingual) | ❌ | 💰 paid | ✅ **free** |
|
|
116
|
+
| **Hybrid (BM25+TF-IDF+embeddings, RRF)** | ❌ | ❌ | ✅ **only here** |
|
|
117
|
+
| **Wikilink graph-boost retrieval signal** | ❌ | ❌ | ✅ **only here** |
|
|
118
|
+
| **PDFs blended into hybrid search** | ❌ | ❌ | ✅ **only here** |
|
|
119
|
+
| **OCR for scanned / image-only PDFs** | ❌ | ❌ | ✅ **only here** |
|
|
120
|
+
| **Cross-encoder reranking** | ❌ | ❌ | ✅ **only here** |
|
|
121
|
+
| **Remote MCP (HTTP + bearer auth)** | ❌ | ❌ | ✅ **only here** |
|
|
122
|
+
| Per-signal observability per hit | ❌ | ❌ | ✅ |
|
|
123
|
+
| Privacy filter (exclude/allow globs) | ❌ | n/a | ✅ verified at search + write paths |
|
|
124
|
+
| Standalone (no Obsidian plugin) | varies | ❌ requires Obsidian | ✅ direct vault read |
|
|
125
|
+
| MCP-native (any agent) | varies | ❌ Obsidian-only | ✅ stdio + HTTP |
|
|
126
|
+
| SLSA-3 release provenance | ❌ | n/a | ✅ |
|
|
127
|
+
| Test suite | rare | n/a | ✅ 522 unit tests |
|
|
87
128
|
|
|
88
|
-
|
|
89
|
-
{
|
|
90
|
-
"mcpServers": {
|
|
91
|
-
"obsidian": {
|
|
92
|
-
"command": "npx",
|
|
93
|
-
"args": ["-y", "@oomkapwn/enquire-mcp", "serve", "--vault", "/path/to/vault"]
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
```
|
|
129
|
+
> **Strategic claim:** enquire is the open-source backend for [Karpathy-style LLM Wikis](https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f) on top of your existing Obsidian vault. The `vault_synth` / `vault_wiki_compile` / `vault_lint_extended` prompts implement the ingest → query → lint → compile workflow natively over `.md` + `[[wikilinks]]`. Knowledge that compounds, traceable to sources.
|
|
98
130
|
|
|
99
|
-
|
|
100
|
-
|---|---|
|
|
101
|
-
| Claude Desktop | macOS `~/Library/Application Support/Claude/claude_desktop_config.json` · Windows `%APPDATA%\Claude\claude_desktop_config.json` |
|
|
102
|
-
| Claude Code (CLI) | `~/.claude.json` (global) or `.mcp.json` (per-project) |
|
|
103
|
-
| Cursor | `~/.cursor/mcp.json` (global) or `.cursor/mcp.json` (per-project) |
|
|
104
|
-
| Codex / OpenClaw / Devin | per-tool MCP config |
|
|
131
|
+
---
|
|
105
132
|
|
|
106
|
-
|
|
133
|
+
## 🛠️ All 39 tools at a glance
|
|
107
134
|
|
|
108
|
-
|
|
109
|
-
enquire-mcp install-model multilingual # ~120MB, 50+ languages
|
|
110
|
-
enquire-mcp build-embeddings --vault <path> # ~30ms/chunk on M1
|
|
111
|
-
# Add --persistent-index to your serve invocation for BM25.
|
|
112
|
-
```
|
|
135
|
+
The umbrella `obsidian_search` plus 38 specialized tools for wikilinks, backlinks, Dataview, frontmatter, canvas, PDFs, OCR, vault stats, graph navigation, and writes.
|
|
113
136
|
|
|
114
|
-
|
|
137
|
+
<details>
|
|
138
|
+
<summary><b>28 always-on read tools</b> — click to expand</summary>
|
|
115
139
|
|
|
116
|
-
|
|
117
|
-
enquire-mcp gen-token > ~/.enquire/token # 256-bit bearer
|
|
118
|
-
enquire-mcp serve-http \
|
|
119
|
-
--vault ~/Obsidian \
|
|
120
|
-
--bearer-token "$(cat ~/.enquire/token)" \
|
|
121
|
-
--persistent-index
|
|
122
|
-
# Front with Tailscale Funnel / Cloudflare Tunnel for HTTPS — see
|
|
123
|
-
# docs/http-transport.md.
|
|
124
|
-
```
|
|
140
|
+
`obsidian_search` · `obsidian_context_pack` · `obsidian_chat_thread_read` · `obsidian_frontmatter_get` · `obsidian_frontmatter_search` · `obsidian_read_note` · `obsidian_list_notes` · `obsidian_resolve_wikilink` · `obsidian_get_backlinks` · `obsidian_get_outbound_links` · `obsidian_get_unresolved_wikilinks` · `obsidian_get_recent_edits` · `obsidian_list_tags` · `obsidian_dataview_query` · `obsidian_find_path` · `obsidian_find_similar` · `obsidian_get_note_neighbors` · `obsidian_stats` · `obsidian_lint_wiki` · `obsidian_open_questions` · `obsidian_paper_audit` · `obsidian_validate_note_proposal` · `obsidian_list_canvases` · `obsidian_read_canvas` · `obsidian_list_pdfs` · `obsidian_read_pdf` · `obsidian_ocr_pdf` · `obsidian_open_in_ui`
|
|
125
141
|
|
|
126
|
-
|
|
142
|
+
</details>
|
|
127
143
|
|
|
128
|
-
|
|
144
|
+
<details>
|
|
145
|
+
<summary><b>4 opt-in read tools</b> (diagnostic single-rankers) — click to expand</summary>
|
|
129
146
|
|
|
130
|
-
|
|
147
|
+
`obsidian_full_text_search` (`--persistent-index`) · `obsidian_search_text` · `obsidian_semantic_search` · `obsidian_embeddings_search` (all 3 require `--diagnostic-search-tools`)
|
|
131
148
|
|
|
132
|
-
|
|
149
|
+
</details>
|
|
133
150
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
| `obsidian_search` | **Hybrid retrieval** — fuses BM25 + TF-IDF + ML embeddings via RRF. The default search tool. Auto-detects available signals. v2.2.0: `granularity: "block"` arg returns chunks instead of notes. **v2.8.0:** with `--include-pdfs`, PDF chunks blend in alongside markdown — every hit carries `kind: "md" \| "pdf"` and PDF snippets include `[page: N]` markers for citation. **v2.9.0:** with `--enable-reranker`, top-N RRF candidates are re-scored by a BGE cross-encoder for +5-10 NDCG@10 typical retrieval quality. |
|
|
137
|
-
| `obsidian_context_pack` | **v2.2.0.** Token-budgeted context bundling: takes a question, runs hybrid search, gathers note bodies + backlinks + optionally recent dailies, returns one ready-to-paste markdown bundle. Saves ~5 tool calls. |
|
|
138
|
-
| `obsidian_chat_thread_read` | **v2.2.0.** Parse a note's `## Chat: <title>` block into structured messages (role/timestamp/content/line-range). Pair with `_append` (write) for note-tethered AI conversations. |
|
|
139
|
-
| `obsidian_frontmatter_get` | **v2.3.0.** Read parsed YAML frontmatter for a note. With `key`, returns just that field. |
|
|
140
|
-
| `obsidian_frontmatter_search` | **v2.3.0.** Find notes by frontmatter predicate (`equals` / `exists` / `contains`). Useful as a precursor to bulk `_set`. |
|
|
141
|
-
| `obsidian_read_note` | Full content + frontmatter + wikilinks + embeds + tags. Also accepts periodic-note aliases (`title: "today"` / `"weekly"` / `"monthly"`). |
|
|
142
|
-
| `obsidian_list_notes` | Vault-wide or folder-scoped. Includes title + tags + mtime + counts. |
|
|
143
|
-
| `obsidian_resolve_wikilink` | Resolves `[[Note]]`, `[[Note\|Alias]]`, `[[Note#Section]]`, `[[Note#^block]]`, with did-you-mean on near-miss. |
|
|
144
|
-
| `obsidian_get_backlinks` | Every note linking to X, ranked + snippeted. |
|
|
145
|
-
| `obsidian_get_outbound_links` | Outbound `[[wikilinks]]` from one note, with resolution status. |
|
|
146
|
-
| `obsidian_get_unresolved_wikilinks` | Vault-wide broken-link audit. |
|
|
147
|
-
| `obsidian_get_recent_edits` | Notes modified in the last N minutes. |
|
|
148
|
-
| `obsidian_list_tags` | Tag census across vault (frontmatter + inline). |
|
|
149
|
-
| `obsidian_dataview_query` | First-class Dataview-style queries (`LIST` / `TABLE`, `WHERE`, `AND` / `OR` / `LIKE` / `contains`). |
|
|
150
|
-
| `obsidian_find_path` | Multi-hop graph BFS between two notes (with alternatives). |
|
|
151
|
-
| `obsidian_find_similar` | Note-to-note similarity (tag + folder + content signals). |
|
|
152
|
-
| `obsidian_get_note_neighbors` | Outbound + inbound + tag-sibling for one note. |
|
|
153
|
-
| `obsidian_stats` | Vault dashboard: note count, tag count, broken links. |
|
|
154
|
-
| `obsidian_lint_wiki` | Karpathy LLM-Wiki `/lint` workflow (orphans / broken / stubs / stale). |
|
|
155
|
-
| `obsidian_open_questions` | Find open `?` questions across the vault. |
|
|
156
|
-
| `obsidian_paper_audit` | Track arXiv references and read-status. |
|
|
157
|
-
| `obsidian_validate_note_proposal` | Lint a draft note before writing (closes the #1 LLM-write pain). |
|
|
158
|
-
| `obsidian_list_canvases` | List `.canvas` files with node + edge counts. |
|
|
159
|
-
| `obsidian_read_canvas` | Parse `.canvas` into typed nodes (text/file/link/group) + edges. |
|
|
160
|
-
| `obsidian_list_pdfs` | **v2.7.0.** List `.pdf` files with size + mtime. PDFs are the #1 non-markdown content kind in real vaults; no other Obsidian-MCP indexes them. |
|
|
161
|
-
| `obsidian_read_pdf` | **v2.7.0.** Extract page-by-page text + doc metadata (title/author/etc) from a PDF. Optional 1-indexed page-range slice. Image-only / scanned PDFs surface `has_text: false`. Powered by Mozilla PDF.js (Apache-2.0, pinned to `optionalDependencies` so the markdown-only path stays zero-cost). |
|
|
162
|
-
| `obsidian_open_in_ui` | Emit `obsidian://open?vault=...` URI. |
|
|
163
|
-
|
|
164
|
-
### 4 opt-in read tools
|
|
165
|
-
|
|
166
|
-
| Tool | Flag | Notes |
|
|
167
|
-
|---|---|---|
|
|
168
|
-
| `obsidian_full_text_search` | `--persistent-index` + `--diagnostic-search-tools` | BM25 ranking, sub-100ms. |
|
|
169
|
-
| `obsidian_search_text` | `--diagnostic-search-tools` | Token search (all/any/phrase modes). |
|
|
170
|
-
| `obsidian_semantic_search` | `--diagnostic-search-tools` | TF-IDF cosine standalone. |
|
|
171
|
-
| `obsidian_embeddings_search` | `--diagnostic-search-tools` | ML embeddings standalone. |
|
|
151
|
+
<details>
|
|
152
|
+
<summary><b>7 opt-in write tools</b> (require <code>--enable-write</code>) — click to expand</summary>
|
|
172
153
|
|
|
173
|
-
|
|
154
|
+
`obsidian_create_note` · `obsidian_append_to_note` · `obsidian_rename_note` (rewrites every wikilink across vault, code-fence-aware) · `obsidian_replace_in_notes` (bulk find/replace) · `obsidian_archive_note` · `obsidian_chat_thread_append` · `obsidian_frontmatter_set` (atomic YAML manipulation, `dry_run` supported)
|
|
174
155
|
|
|
175
|
-
|
|
176
|
-
|---|---|
|
|
177
|
-
| `obsidian_create_note` | Refuses overwrite without `overwrite=true`. Empty path rejected. |
|
|
178
|
-
| `obsidian_append_to_note` | Symlink-safe; respects `--max-file-bytes`. |
|
|
179
|
-
| `obsidian_rename_note` | Rewrites every wikilink across vault. Code-fence-aware. `dry_run` available. |
|
|
180
|
-
| `obsidian_replace_in_notes` | Bulk find/replace. Per-file errors collected; `partial: true` on mid-loop fail. |
|
|
181
|
-
| `obsidian_archive_note` | Wraps rename to `Archive/`. Preserves backlinks. |
|
|
182
|
-
| `obsidian_chat_thread_append` | **v2.2.0.** Append a user/assistant/system message to a note's `## Chat:` block. Creates note + heading if absent. Threads stored as markdown — searchable, version-controllable, survive sessions. |
|
|
183
|
-
| `obsidian_frontmatter_set` | **v2.3.0.** Surgical YAML manipulation — set/unset keys on a note atomically. Pass `null` as value to delete. Round-trips through gray-matter so YAML formatting stays consistent. `dry_run` supported. |
|
|
156
|
+
</details>
|
|
184
157
|
|
|
185
|
-
Plus
|
|
158
|
+
**Plus:** 2 + 1 opt-in MCP resources, and **17 MCP prompts** (`summarize_recent_edits`, `weekly_review`, `monthly_review`, `find_orphans`, `extract_todos`, `process_inbox`, `review_tag`, `consolidate_tags`, `find_duplicates`, `lint_wiki`, `search_with_query_expansion`, `vault_synth`, `vault_wiki_compile`, `vault_lint_extended`, `vault_capture`, `vault_persona_search`, `vault_automation_setup`).
|
|
186
159
|
|
|
187
|
-
|
|
160
|
+
📖 Full reference: **[docs/api.md](./docs/api.md)** · Remote-MCP deployment guide: **[docs/http-transport.md](./docs/http-transport.md)**
|
|
188
161
|
|
|
189
162
|
---
|
|
190
163
|
|
|
191
|
-
## Configuration
|
|
164
|
+
## ⚙️ Configuration
|
|
165
|
+
|
|
166
|
+
The flags you'll actually use:
|
|
192
167
|
|
|
193
|
-
| Flag | Default |
|
|
168
|
+
| Flag | Default | What it does |
|
|
194
169
|
|---|---|---|
|
|
195
|
-
| `--vault <path>` | required | Path to Obsidian vault root
|
|
196
|
-
| `--
|
|
197
|
-
| `--
|
|
198
|
-
| `--
|
|
199
|
-
| `--
|
|
200
|
-
| `--
|
|
201
|
-
| `--
|
|
202
|
-
| `--
|
|
203
|
-
| `--
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
170
|
+
| `--vault <path>` | required | Path to Obsidian vault root |
|
|
171
|
+
| `--persistent-index` | off | SQLite FTS5 BM25, sub-100ms top-10 |
|
|
172
|
+
| `--include-pdfs` | off | Index PDFs into FTS5 + embeddings |
|
|
173
|
+
| `--enable-reranker` | off | BGE cross-encoder reranking on RRF top-N |
|
|
174
|
+
| `--enable-write` | off | Register the 7 write tools |
|
|
175
|
+
| `--exclude-glob <pat...>` | none | Privacy denylist (e.g. `'02_Personal/**'`) |
|
|
176
|
+
| `--read-paths <pat...>` | none | Privacy allowlist (only matching paths visible) |
|
|
177
|
+
| `--watch` | off | Live invalidation on `.md` add/change/unlink |
|
|
178
|
+
| `--persistent-cache` | off | Survive cold starts |
|
|
179
|
+
|
|
180
|
+
Subcommands: `serve` · `serve-http` · `gen-token` · `doctor` (v2.11) · `setup` (v2.11) · `clear-cache` · `clear-index` · `clear-embeddings` · `index` · `install-model` · `build-embeddings`.
|
|
181
|
+
|
|
182
|
+
**Remote MCP** for Claude.ai web / ChatGPT / Cursor HTTP / mobile:
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
enquire-mcp gen-token > ~/.enquire/token # one-time
|
|
186
|
+
enquire-mcp serve-http \
|
|
187
|
+
--vault ~/Obsidian \
|
|
188
|
+
--bearer-token "$(cat ~/.enquire/token)" \
|
|
189
|
+
--persistent-index --include-pdfs --enable-reranker
|
|
190
|
+
# Front with Tailscale Funnel / Cloudflare Tunnel for HTTPS.
|
|
191
|
+
```
|
|
211
192
|
|
|
212
193
|
---
|
|
213
194
|
|
|
214
|
-
##
|
|
195
|
+
## 🛡️ Trust
|
|
215
196
|
|
|
216
|
-
- **Read-only by default.**
|
|
217
|
-
- **Path traversal blocked.** Realpath check on every read+write target. Symlinks
|
|
218
|
-
- **Privacy boundary verified across all paths
|
|
197
|
+
- **Read-only by default.** Every write tool requires `--enable-write`.
|
|
198
|
+
- **Path traversal blocked.** Realpath check on every read+write target. Symlinks resolving outside the vault are rejected.
|
|
199
|
+
- **Privacy boundary verified across all paths** including persistent FTS5 + embed indexes and the `obsidian://chunk/...` resource. Privacy fail-closed: empty `--read-paths` / `--exclude-glob` patterns refuse to start.
|
|
200
|
+
- **HTTP transport hardened.** Bearer auth (constant-time SHA-256 + `timingSafeEqual`), per-token sliding rate-limit, strict CORS allowlist with credential-leak guard.
|
|
219
201
|
- **`gray-matter` (`js-yaml` safeLoad)** — no code execution via frontmatter.
|
|
220
|
-
- **DQL parser** — no shell, no `eval`, no template expansion.
|
|
221
202
|
- **Cache + index files** — chmod 0600, parent dir 0700.
|
|
222
203
|
- **SLSA-3 provenance** on every npm release.
|
|
223
|
-
- **Branch protection
|
|
224
|
-
|
|
225
|
-
Full posture: [SECURITY.md](./SECURITY.md). Report vulnerabilities to `oomkapwn@gmail.com`.
|
|
226
|
-
|
|
227
|
-
---
|
|
228
|
-
|
|
229
|
-
## Engineering
|
|
204
|
+
- **Branch protection** with `bypass_mode: pull_request` — every change goes through PR review. Release pipeline verifies tagged SHA is on `main` AND all 8 required CI checks reported `success` on it.
|
|
230
205
|
|
|
231
206
|
| Surface | Posture |
|
|
232
207
|
|---|---|
|
|
233
|
-
|
|
|
234
|
-
| Lint | Biome 2 (zero-warning policy) |
|
|
235
|
-
| Tests | 502 unit tests across 24 files |
|
|
236
|
-
| CI | ubuntu × {Node 20, 22, 24} required + macOS advisory job |
|
|
208
|
+
| Tests | 522 unit tests across 26 files, 8 required CI gates per PR |
|
|
237
209
|
| Coverage | Lines ≥86%, statements ≥82%, functions ≥75%, branches ≥73% (gated) |
|
|
238
210
|
| Audit | `npm audit --audit-level=moderate` for prod; high for dev |
|
|
239
|
-
|
|
|
240
|
-
|
|
|
211
|
+
| CI | Ubuntu × {Node 20, 22, 24} required + macOS advisory job |
|
|
212
|
+
| Lint | Biome 2 (zero-warning policy) |
|
|
213
|
+
| Language | TypeScript strict + `noUncheckedIndexedAccess` |
|
|
214
|
+
| Runtime deps | 5 mandatory, 3 optional (FTS5 + ML embeddings + PDF parser — markdown-only path stays zero-cost) |
|
|
215
|
+
| Releases | npm + GitHub release per tag · semver · SLSA-3 provenance |
|
|
241
216
|
|
|
242
|
-
|
|
243
|
-
git clone https://github.com/oomkapwn/enquire-mcp.git
|
|
244
|
-
cd enquire-mcp && npm install
|
|
245
|
-
npm test # full suite
|
|
246
|
-
npm run lint # zero warnings
|
|
247
|
-
npm run build # tsc → dist/
|
|
248
|
-
```
|
|
217
|
+
Full posture: **[SECURITY.md](./SECURITY.md)**. Report vulnerabilities to `oomkapwn@gmail.com`.
|
|
249
218
|
|
|
250
219
|
---
|
|
251
220
|
|
|
252
|
-
## FAQ
|
|
221
|
+
## ❓ FAQ
|
|
222
|
+
|
|
223
|
+
**Do I need Obsidian installed?**
|
|
224
|
+
No. enquire reads `.md` + `.canvas` + `.pdf` files directly. Works against any Obsidian-format vault.
|
|
225
|
+
|
|
226
|
+
**Will this write to my vault?**
|
|
227
|
+
Not unless you start with `--enable-write`. Even then, all 7 write tools are gated by privacy filters and refuse to overwrite without `overwrite: true`. `dry_run` modes available on the destructive ones.
|
|
228
|
+
|
|
229
|
+
**Is my data sent anywhere?**
|
|
230
|
+
Only on `enquire-mcp install-model` (downloads ONNX weights from HuggingFace, one-time). Serve mode itself never makes outbound HTTP. Embeddings + reranker run on CPU locally.
|
|
231
|
+
|
|
232
|
+
**How is this different from Smart Connections?**
|
|
233
|
+
Smart Connections is a paid Obsidian plugin that runs ML embeddings inside Obsidian. enquire is a standalone MCP server: free, MCP-native (works with Claude / Cursor / Codex / any agent), and fuses 3 retrieval signals + cross-encoder reranking for higher recall + precision than embeddings alone. PDFs index too.
|
|
234
|
+
|
|
235
|
+
**Performance on large vaults?**
|
|
236
|
+
Cold-build of FTS5 on a 1k-note vault: ~5s. Warm BM25 top-10: sub-100ms. Embedding build: ~30ms/chunk on M1 (~8min for 8k chunks). Hybrid query latency: <200ms typical. Reranker adds ~30-50ms at top-50. Maintainer dogfoods on a 128-note bilingual vault with all of the above on.
|
|
253
237
|
|
|
254
|
-
**
|
|
255
|
-
|
|
238
|
+
**Languages?**
|
|
239
|
+
Default embedding model is `paraphrase-multilingual-MiniLM-L12-v2` (50+ languages). Multilingual cross-encoder reranker (`mxbai-rerank-xsmall-v1`) is the default too. Validated end-to-end on Russian + English bilingual vaults. CJK / Thai / Khmer / Lao tokenization via `Intl.Segmenter` (Node 16+ ICU).
|
|
256
240
|
|
|
257
|
-
**
|
|
258
|
-
|
|
241
|
+
**Can I run it remotely?**
|
|
242
|
+
Yes. `serve-http` exposes the same server over [Streamable HTTP](https://modelcontextprotocol.io/specification/2025-06-18/basic/transports#streamable-http) with bearer auth. Front with Tailscale Funnel or Cloudflare Tunnel for HTTPS — works with claude.ai web, ChatGPT custom GPT, Cursor HTTP mode, mobile MCP clients. See [docs/http-transport.md](./docs/http-transport.md).
|
|
259
243
|
|
|
260
|
-
|
|
261
|
-
Only on `enquire-mcp install-model` (downloads ONNX weights from HuggingFace). The serve mode itself never makes outbound HTTP. Embeddings run on CPU locally.
|
|
244
|
+
---
|
|
262
245
|
|
|
263
|
-
|
|
264
|
-
Smart Connections is a paid Obsidian plugin that does ML embeddings inside Obsidian. enquire-mcp is a standalone MCP server: free, MCP-native (works with Claude / Cursor / Codex / any agent), and adds hybrid retrieval (BM25 + TF-IDF + embeddings via RRF) for higher recall than embeddings alone.
|
|
246
|
+
## 🚀 Releases
|
|
265
247
|
|
|
266
|
-
|
|
267
|
-
Cold-build of FTS5 on a 1k-note vault: ~5s. Warm BM25 top-10: sub-100ms. Embedding build: ~30ms/chunk on M1 (8s for 256 chunks, ~8min for 8k chunks). Hybrid query latency: <200ms typical.
|
|
248
|
+
`v2.0.0` (stable) · `v2.5.0` (5-sprint roadmap consolidated) · `v2.6.0` (remote MCP) · `v2.7.0` (PDF read tools) · `v2.8.0` (PDFs blended into hybrid search) · `v2.9.0` (BGE cross-encoder reranking)
|
|
268
249
|
|
|
269
|
-
|
|
270
|
-
Yes. Default embedding model is `paraphrase-multilingual-MiniLM-L12-v2` (50+ languages). Validated end-to-end on Russian + English bilingual vaults. CJK requires the upcoming Intl.Segmenter pre-pass (v2.1 backlog).
|
|
250
|
+
Channel: `npm install @oomkapwn/enquire-mcp` → latest stable. Full changelog: [CHANGELOG.md](./CHANGELOG.md).
|
|
271
251
|
|
|
272
252
|
---
|
|
273
253
|
|
|
274
|
-
## Contributing
|
|
254
|
+
## 🤝 Contributing
|
|
275
255
|
|
|
276
|
-
|
|
256
|
+
```bash
|
|
257
|
+
git clone https://github.com/oomkapwn/enquire-mcp.git
|
|
258
|
+
cd enquire-mcp && npm install
|
|
259
|
+
npm test # full suite (502 tests, ~5s)
|
|
260
|
+
npm run lint # zero warnings
|
|
261
|
+
npm run build # tsc → dist/
|
|
262
|
+
```
|
|
277
263
|
|
|
278
|
-
|
|
264
|
+
Issues, PRs, and ideas welcome. Branch protection requires PR review on `main`.
|
|
279
265
|
|
|
280
|
-
|
|
266
|
+
---
|
|
281
267
|
|
|
282
|
-
|
|
268
|
+
## 📜 License & credits
|
|
283
269
|
|
|
284
|
-
|
|
270
|
+
MIT. Built by [Alex (@OomkaBear)](https://github.com/oomkapwn). Named after [Tim Berners-Lee's 1980 prototype of the WWW](https://en.wikipedia.org/wiki/ENQUIRE) — the original hypertext system, before the web. The original spec was that you could ask the system anything; this brings that to your vault.
|