@oomkapwn/enquire-mcp 0.10.3 → 0.12.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 +115 -0
- package/README.md +25 -13
- package/SECURITY.md +11 -0
- package/assets/social-preview.png +0 -0
- package/dist/fts5.d.ts +6 -1
- package/dist/fts5.d.ts.map +1 -1
- package/dist/fts5.js +44 -13
- package/dist/fts5.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +56 -8
- package/dist/index.js.map +1 -1
- package/dist/tools.d.ts +66 -5
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +262 -6
- package/dist/tools.js.map +1 -1
- package/dist/vault.d.ts +18 -0
- package/dist/vault.d.ts.map +1 -1
- package/dist/vault.js +71 -0
- package/dist/vault.js.map +1 -1
- package/docs/api.md +39 -10
- package/package.json +7 -4
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,121 @@
|
|
|
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
|
+
## [0.12.0] — 2026-05-05
|
|
6
|
+
|
|
7
|
+
Anti-slop write validator — closes the #1 LLM-write pain found across forum #111443, Eleanor Konik's blog, and every chatforest review: *"AI generates structurally-broken notes — bad YAML, fake wikilinks, inconsistent tags — and I spend 10 minutes reformatting per note"*.
|
|
8
|
+
|
|
9
|
+
### Added — `obsidian_validate_note_proposal` tool
|
|
10
|
+
Lint a draft note BEFORE the LLM commits to writing. Inputs: `path` + `content` (full markdown including frontmatter) + optional `mode` ("create" | "overwrite" | "append"). Returns a structured diagnostic so the LLM can fix-and-retry rather than ship a broken note.
|
|
11
|
+
|
|
12
|
+
What it checks:
|
|
13
|
+
- **YAML parse** via `gray-matter` (the same parser used at write time). Reports `parsed: true|false` + error string + observed keys.
|
|
14
|
+
- **Every `[[wikilink]]`** resolved against the live vault via `findBestMatch`. Each link tagged `resolved` / `broken` with `resolved_path` or `did-you-mean` suggestions (top-3 nearest by prefix/contains rank).
|
|
15
|
+
- **Every tag** (frontmatter + inline) pre-classified as `existing` (case-insensitive match against `listTags()`) or `new` — flags `new` ones so the LLM doesn't fork a tag forest (`#productivity` vs `#productive` vs `#prod`).
|
|
16
|
+
- **Path collision**:
|
|
17
|
+
- `mode: "create"` (default) — exact path exists → blocking `path-collision` error.
|
|
18
|
+
- `mode: "overwrite"` / `"append"` — path exists → soft warning, validation passes.
|
|
19
|
+
- Title collision (note with same basename at a different path) → soft warning regardless of mode.
|
|
20
|
+
- **Path traversal** caught and returned as a structured error (not an exception) — validator never throws on input shape.
|
|
21
|
+
|
|
22
|
+
This is a **read-only tool**. Always available, even without `--enable-write`. Recommended workflow: `validate → fix → obsidian_create_note`.
|
|
23
|
+
|
|
24
|
+
Why it's a moat: nobody else in the obsidian-MCP space ships this. Closes the gap between "scary LLM that touches my vault" and "LLM that drafts notes that arrive ready-to-merge".
|
|
25
|
+
|
|
26
|
+
### Tests
|
|
27
|
+
- 220 unit tests (was 213). 7 new for the validator: happy path, broken-wikilinks, new-tag classification, path-collision modes, invalid YAML pass-through, path traversal as structured error, auto `.md` append.
|
|
28
|
+
|
|
29
|
+
### Repo state
|
|
30
|
+
- 11 read tools (was 10). Smoke + docs-consistency tests updated.
|
|
31
|
+
- README comparison-table row added — "Anti-slop write validator".
|
|
32
|
+
|
|
33
|
+
## [0.11.0] — 2026-05-05
|
|
34
|
+
|
|
35
|
+
Competitive feature set — borrowed/synthesized from a deep audit of the obsidian-MCP space (StevenStavrakis, MarkusPfundstein, cyanheads, marcelmarais, aaronsb, mcpvault) and Obsidian community pain-point research (forum, HN, Reddit). Four user-visible features land here, none of them invented from scratch — each closes a gap real users complain about with the existing tools.
|
|
36
|
+
|
|
37
|
+
### Added — privacy
|
|
38
|
+
- **`--exclude-glob <pattern...>`** CLI flag (repeatable). Glob patterns matching vault-relative paths make those notes invisible to *every* tool — `list_notes`, `read_note`, `search_text`, `dataview_query`, even direct path reads. Closes the most-frequent forum complaint about Obsidian-MCP setups: *"the AI can see my whole vault and that isn't something I have enabled permanently in my main vault"*. Supports `*` (within-segment), `**` (cross-segment), `?` (single char). Example: `--exclude-glob '02_Personal/**' '*.private.md' 'Inbox/*.draft.md'`. Backed by 7 unit tests for both glob semantics and Vault filtering.
|
|
39
|
+
|
|
40
|
+
### Added — daily-note workflow
|
|
41
|
+
- **Periodic-note aliases on `obsidian_read_note`** — `title: "today"` (or `"daily"` / `"weekly"` / `"monthly"`) resolves to today's daily/weekly/monthly note using the standard Daily-Notes-plugin formats: `YYYY-MM-DD` / `YYYY-Www` (ISO week) / `YYYY-MM`. Literal title takes priority — if you have an actual `Daily.md`, that one wins. Borrowed from cyanheads/obsidian-mcp-server, made standalone (no Local REST API plugin needed).
|
|
42
|
+
|
|
43
|
+
### Added — LLM-friendly errors
|
|
44
|
+
- **`Did you mean: …` suggestions** on every `Note not found` error from `obsidian_read_note`, `obsidian_create_note`, and `obsidian_append_to_note`. Up to 3 nearest paths by case-insensitive prefix/contains/relpath ranking. Closes the cyanheads-style "case-insensitive retry plus closest-match hint" UX gap that LLMs hit when they paraphrase a note name.
|
|
45
|
+
|
|
46
|
+
### Added — projection format
|
|
47
|
+
- **`obsidian_read_note` accepts `format: "map"`** for a document-map projection: returns headings (with `level` + `text` + `line`) + frontmatter keys + wikilink/embed/tag counts + `byte_size` *without* the body. Lets an LLM plan a surgical edit without paying the token cost of reading the full note. Default `format: "full"` preserves the v0.10 shape.
|
|
48
|
+
|
|
49
|
+
### Tests
|
|
50
|
+
- 213 unit tests (was 195). 18 new across 4 features:
|
|
51
|
+
- `globToRegex` semantics (4 tests)
|
|
52
|
+
- `--exclude-glob` filtering at `listNotes` + `readNote` paths (4 tests)
|
|
53
|
+
- Document-map projection — headings inside fences correctly skipped (2 tests)
|
|
54
|
+
- Periodic-note aliases — `today`/`daily`/`weekly`/`monthly` resolution + literal-priority + error-message format (5 tests)
|
|
55
|
+
- Did-you-mean — typo path/title suggestions, exact match doesn't include hint (3 tests)
|
|
56
|
+
|
|
57
|
+
### Why this matters
|
|
58
|
+
Each of these four features came directly from the competitor + community research:
|
|
59
|
+
- **`--exclude-glob`**: the privacy concern was the #1 unmet user want from the forum thread; nobody else ships per-folder ACL.
|
|
60
|
+
- **Periodic aliases**: daily-note workflow is one of the top reasons people use Obsidian; cyanheads had this, nobody else with the standalone-FS architecture did.
|
|
61
|
+
- **Did-you-mean + map projection**: cyanheads' UX patterns the rest of the field hadn't borrowed yet.
|
|
62
|
+
|
|
63
|
+
## [0.10.6] — 2026-05-03
|
|
64
|
+
|
|
65
|
+
CI re-release of v0.10.5. Same content + applied biome's auto-format wrap on the SQL string in `src/fts5.ts` (line was just past biome's 120-col `lineWidth`, CI strict where local was lenient until I re-ran `npm run lint`). v0.10.5 git tag exists pointing at 6039dc6 but never reached npm.
|
|
66
|
+
|
|
67
|
+
This is a CI-pipeline issue, not a code or branding change — v0.10.6 functionality is identical to v0.10.5.
|
|
68
|
+
|
|
69
|
+
## [0.10.5] — 2026-05-03
|
|
70
|
+
|
|
71
|
+
CI re-release of v0.10.4 (lint failed on the same biome severity divergence that bit v0.10.2 — `useTemplate` rule registers as `info` locally but `error` on the GitHub Actions image). Same code as v0.10.4 plus:
|
|
72
|
+
|
|
73
|
+
### Added — marketing surface for OpenClaw
|
|
74
|
+
- README, package.json description, and GitHub repo description now feature **OpenClaw** alongside Claude Code, Cursor, and Codex as primary MCP clients. The reference deployment for the FTS5 search backend (issue #10) is the SZBOX trading-system memory layer running on OpenClaw — explicit attribution makes that pairing discoverable.
|
|
75
|
+
- Devin moves from the headline list to "any other MCP-compatible client" — kept as a supported target, just not the lead example.
|
|
76
|
+
- Per-client install table gains an OpenClaw row.
|
|
77
|
+
- npm `keywords` adds `openclaw`. GitHub repo `topics` adds `openclaw` (now at the 20-topic max).
|
|
78
|
+
|
|
79
|
+
### Fixed (vs the broken v0.10.4 npm publish)
|
|
80
|
+
- `src/fts5.ts` `getChunk()`: collapsed the multi-line `prepare("…")` into one line via a `sql` const. Same biome `useTemplate`/format edge that bit v0.10.2.
|
|
81
|
+
|
|
82
|
+
## [0.10.4] — 2026-05-03
|
|
83
|
+
|
|
84
|
+
External-audit pass on top of v0.10.3 — closes one P1 (chunk-resource leaking FTS5 internal enrichment), tightens privacy posture for the FTS5 path, plugs a folder-filter pattern issue, hardens the release pipeline, and clears doc drift accumulated across the v0.10.x range.
|
|
85
|
+
|
|
86
|
+
### Fixed
|
|
87
|
+
- **P1 — `obsidian://chunk/{n}/{path}` resource was returning the FTS5-enriched chunk text, not the raw note text.** The FTS5 `content` column carries an appended `[wikilink_targets: …]` synthetic line for recall (so a search for a target name surfaces notes that link out to it without naming it inline). The resource handler returned that enriched text — meaning MCP clients were seeing a synthetic line that doesn't exist in the source note, breaking quoting and creating ambiguity in deep-link responses. Fix: schema bump (v2 → v3) adds an UNINDEXED `raw_content` column carrying the verbatim chunk; `getChunk()` now selects `raw_content`. Existing v0.10.x indexes auto-rebuild on first v0.10.4 boot. Negative-assertion regression test added in `tests/fts5.test.ts`.
|
|
88
|
+
- **P2 — FTS5 folder filter used SQLite `GLOB`** which interprets `*?[]` as pattern syntax. A folder named `Project [A]` or `Q?A` would expand into wider matches. Switched to `substr(rel_path, 1, ?) = ?` for prefix-equality with no pattern semantics.
|
|
89
|
+
|
|
90
|
+
### Added — privacy
|
|
91
|
+
- **DB + WAL + SHM file mode `0600`** on every `FtsIndex.open()` (was: only the parent dir got `0700`, and only when first created). Closes the audit gap that the FTS5 index — which stores chunked note content + tag list + wikilink targets — wasn't getting the same explicit chmod that the persistent parse cache does.
|
|
92
|
+
- **New CLI subcommand `enquire-mcp clear-index`** for full privacy purge: removes `.fts5.db`, `.fts5.db-wal`, `.fts5.db-shm`. Symmetric to `clear-cache`.
|
|
93
|
+
- **`SECURITY.md` gains a "Persistent FTS5 index: privacy posture" section** mirroring the existing persistent-cache section. Covers what the index stores, file modes, the WAL/SHM gotcha, the cross-vault contamination guard, and the manual purge path.
|
|
94
|
+
|
|
95
|
+
### Added — release pipeline
|
|
96
|
+
- **`.github/workflows/release.yml` now runs the full quality gate before `npm publish`**: lint, build, test, **`check-version-consistency`**, **`npm audit --audit-level=high`**, and a **JSON-RPC smoke test against a synthetic vault**. Previously a bad commit could publish to npm if it passed lint+build+test alone. (v0.10.2 already showed how brittle the slimmer gate was.)
|
|
97
|
+
|
|
98
|
+
### Added — server hardening
|
|
99
|
+
- **`startServer()` wraps FTS5 sync in try/catch** that closes the SQLite handle if `syncFtsIndex` throws — was leaking the connection until process exit.
|
|
100
|
+
|
|
101
|
+
### Docs cleanup (drift across the v0.10.x range)
|
|
102
|
+
- `docs/api.md` header was still `# enquire — API (v0.7)` and claimed `12 MCP tools (10 read + 2 opt-in write)` — actually 13 tools when both opt-ins are enabled (10 always-on read + 1 opt-in FTS read + 2 opt-in write). Header de-versioned, count corrected, link to CHANGELOG added.
|
|
103
|
+
- `docs/api.md` `obsidian_full_text_search` schema was missing the `tag` and `since` filters (shipped in v0.10.1) and the `applied_filters` field of the response shape. Added.
|
|
104
|
+
- `docs/api.md` `obsidian_full_text_search` returns shape: `chunk_index` no longer says "can address with obsidian://chunk URI later" — that resource shipped in v0.10.2 and is documented in its own section now.
|
|
105
|
+
- `docs/api.md` Roadmap reorganized: shipped items moved to "Shipped in 0.10" with checkmarks; only unshipped items remain in "Open".
|
|
106
|
+
- `README.md`: line 202 example used `"Shipped enquire v0.7.1"` — now version-agnostic. Line 304 said `npm test # 130+ unit tests` — generalized to "full suite (count in the badge)". Line 332 historical block claimed `0.7.x — current` — replaced with current 0.10.x → 0.7.x narrative.
|
|
107
|
+
- `README.md`: dependency claim updated from "four runtime dependencies" to "four mandatory + one optional (`better-sqlite3`)".
|
|
108
|
+
- `README.md`: 10k+ vault story now points at the FTS5 path (which shipped) instead of the prior "would help, on the Phase 3 roadmap" wording.
|
|
109
|
+
- `assets/social-preview.svg`: terminal mockup said `"You shipped the v0.7 spec."` — now version-agnostic.
|
|
110
|
+
|
|
111
|
+
### Tests
|
|
112
|
+
- 186 unit tests (was 185). 1 new negative-assertion regression test for the chunk-resource raw-content fix.
|
|
113
|
+
|
|
114
|
+
### What I'd done as a meta-pass: why was the chunk leak missed?
|
|
115
|
+
- The v0.10.0 wikilink-recall test asserted *positive* recall (search finds the file). It didn't assert *absence* of the synthetic enrichment in resource output.
|
|
116
|
+
- The v0.10.2 `getChunk` test used `toContain("first paragraph")`, which silently passes even when the chunk has extra trailing content.
|
|
117
|
+
- Storage column and API response field were treated as the same thing by default — nothing in the test discipline caught the divergence. Lesson: round-trip exact-equality assertions for any "fetch what you stored" path.
|
|
118
|
+
- A `grep` of `src/` for similar "store enriched / serve to user" patterns found this was the ONLY occurrence; no other path returns indexed-form data via a user-facing resource or tool.
|
|
119
|
+
|
|
5
120
|
## [0.10.3] — 2026-05-03
|
|
6
121
|
|
|
7
122
|
Re-release of v0.10.2. The v0.10.2 git tag exists, but the auto-publish workflow's `npm run lint` step failed on CI (a biome `useTemplate` finding that registered as `info` locally but was `error` on the CI image). v0.10.2 never reached npm; v0.10.3 contains the same code plus the lint fix and is the first npm-published version with chunk-level addressing.
|
package/README.md
CHANGED
|
@@ -6,14 +6,14 @@
|
|
|
6
6
|
|
|
7
7
|
### MCP server for Obsidian vaults
|
|
8
8
|
|
|
9
|
-
**Give Claude Code, Cursor,
|
|
9
|
+
**Give Claude Code, Cursor, OpenClaw, and Codex first-class access to your Obsidian vault — wikilinks resolved, frontmatter typed, backlinks indexed, Dataview queries, MCP resources, and read-only safety by default.** Works with Devin and any other MCP-compatible client.
|
|
10
10
|
|
|
11
11
|
[](https://github.com/oomkapwn/enquire-mcp/actions/workflows/ci.yml)
|
|
12
12
|
[](https://www.npmjs.com/package/@oomkapwn/enquire-mcp)
|
|
13
13
|
[](./LICENSE)
|
|
14
14
|
[](#develop)
|
|
15
15
|
[](https://modelcontextprotocol.io/)
|
|
16
|
-
[](#develop)
|
|
17
17
|
[](#develop)
|
|
18
18
|
[](https://biomejs.dev/)
|
|
19
19
|
|
|
@@ -53,9 +53,14 @@ There are several Obsidian-MCP servers out there. enquire differentiates on thre
|
|
|
53
53
|
| **Read-only by default** (write tools require explicit flag) | ❌ usually write-default | ✅ `--enable-write` |
|
|
54
54
|
| Symlink-escape safety, realpath-checked reads & writes | rare | ✅ |
|
|
55
55
|
| Persistent on-disk cache for warm cold-starts | ❌ | ✅ `--persistent-cache` |
|
|
56
|
-
|
|
|
56
|
+
| **Per-folder privacy filter** (`--exclude-glob '02_Personal/**'`) | ❌ | ✅ |
|
|
57
|
+
| **Periodic-note aliases** (`title: "today"` resolves to today's daily-note) | rare | ✅ |
|
|
58
|
+
| **`Did you mean: ...`** suggestions on note-not-found errors | rare | ✅ |
|
|
59
|
+
| **Document-map projection** (`format: "map"`: headings + counts, no body) | ❌ | ✅ |
|
|
60
|
+
| **Anti-slop write validator** (`obsidian_validate_note_proposal` lints YAML + wikilinks + tags before write) | ❌ | ✅ |
|
|
61
|
+
| TypeScript strict + Biome lint + 220 unit tests | varies | ✅ |
|
|
57
62
|
|
|
58
|
-
That's the gap. enquire closes it in ~
|
|
63
|
+
That's the gap. enquire closes it in ~2800 lines of TypeScript with four mandatory runtime dependencies (`@modelcontextprotocol/sdk`, `commander`, `gray-matter`, `zod`) plus one optional (`better-sqlite3`, only loaded when `--persistent-index` is passed).
|
|
59
64
|
|
|
60
65
|
> **Not affiliated with Obsidian.md.** Obsidian and the Obsidian logo are trademarks of Dynalist Inc. enquire-mcp is an independent open-source project that reads Obsidian-format vaults. The name «enquire» is a tribute to Tim Berners-Lee's 1980 hypertext system, not a trademark claim against any party.
|
|
61
66
|
|
|
@@ -63,7 +68,7 @@ That's the gap. enquire closes it in ~2000 lines of TypeScript and four runtime
|
|
|
63
68
|
|
|
64
69
|
## Who is this for?
|
|
65
70
|
|
|
66
|
-
- **Obsidian users on Claude Code / Cursor /
|
|
71
|
+
- **Obsidian users on Claude Code / Cursor / OpenClaw / Codex** (or Devin or any other MCP-compatible client) who want the assistant to draft notes that actually link properly, follow `[[…]]`, and respect frontmatter.
|
|
67
72
|
- **Agentic workflow builders** who need a structured layer over a markdown vault — `dataview_query`, `get_backlinks`, `list_tags` are the kind of primitives that compose into real automations.
|
|
68
73
|
- **Tinkerers** who want to wire their PKM into LLM pipelines without writing a parser. We did the parsing.
|
|
69
74
|
|
|
@@ -91,8 +96,9 @@ That's the gap. enquire closes it in ~2000 lines of TypeScript and four runtime
|
|
|
91
96
|
| **Claude Desktop** | macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`<br>Windows: `%APPDATA%\Claude\claude_desktop_config.json` |
|
|
92
97
|
| **Claude Code (CLI)** | `~/.claude.json` (global) or `.mcp.json` (per-project) |
|
|
93
98
|
| **Cursor** | `~/.cursor/mcp.json` (global) or `.cursor/mcp.json` (per-project) |
|
|
99
|
+
| **OpenClaw** | per your OpenClaw shared-memory MCP config |
|
|
94
100
|
| **Codex / Codex CLI** | per-project `.mcp.json` or environment-specific config |
|
|
95
|
-
| **
|
|
101
|
+
| **Devin / any other MCP client** | wherever your client expects MCP server JSON |
|
|
96
102
|
|
|
97
103
|
To enable write tools (`obsidian_create_note`, `obsidian_append_to_note`), add `"--enable-write"` to the `args` array.
|
|
98
104
|
|
|
@@ -126,7 +132,7 @@ Restart your client. The server logs `enquire <version> ready (read-only, vault=
|
|
|
126
132
|
|
|
127
133
|
## What you get
|
|
128
134
|
|
|
129
|
-
###
|
|
135
|
+
### 11 read tools (always on) + 1 opt-in (`--persistent-index`)
|
|
130
136
|
|
|
131
137
|
| Tool | What it does |
|
|
132
138
|
|---|---|
|
|
@@ -140,6 +146,7 @@ Restart your client. The server logs `enquire <version> ready (read-only, vault=
|
|
|
140
146
|
| `obsidian_get_unresolved_wikilinks` | Vault-hygiene: every `[[broken]]` link in the vault. |
|
|
141
147
|
| `obsidian_list_tags` | Every unique tag with frontmatter / inline counts. |
|
|
142
148
|
| `obsidian_dataview_query` | `LIST` / `TABLE` with `FROM`, `WHERE`, `SORT`, `LIMIT`. Supports `AND` / `OR` / `=` / `!=` / `contains` / `like`. |
|
|
149
|
+
| `obsidian_validate_note_proposal` | **Anti-slop write linter.** Lint a draft note BEFORE writing — parses YAML, resolves every `[[wikilink]]` against the live vault, pre-classifies every tag (existing vs new), checks path/title collisions. Returns errors + warnings + per-link/tag diagnostics. Closes the #1 LLM-write pain ("AI generates structurally-broken notes"). |
|
|
143
150
|
| `obsidian_full_text_search` | _Opt-in via `--persistent-index`._ BM25-ranked full-text search backed by SQLite FTS5 inverted index. Sub-100ms on multi-thousand-note vaults. Hyphenated tokens (`claude-telegram`) auto-quoted. Returns chunk-level hits with `«…»`-bracketed snippets. |
|
|
144
151
|
|
|
145
152
|
### 2 write tools (opt-in via `--enable-write`)
|
|
@@ -199,7 +206,7 @@ TABLE status FROM #idea WHERE status = "active" SORT file.mtime DESC
|
|
|
199
206
|
### 6. Daily journaling (write mode)
|
|
200
207
|
> "Append a 'shipped today' bullet to today's daily note."
|
|
201
208
|
|
|
202
|
-
With `--enable-write`: `obsidian_append_to_note({ title: "2026-05-03", content: "-
|
|
209
|
+
With `--enable-write`: `obsidian_append_to_note({ title: "2026-05-03", content: "- shipped a thing" })`
|
|
203
210
|
|
|
204
211
|
---
|
|
205
212
|
|
|
@@ -208,7 +215,9 @@ With `--enable-write`: `obsidian_append_to_note({ title: "2026-05-03", content:
|
|
|
208
215
|
```
|
|
209
216
|
┌─────────────────┐ stdio JSON-RPC ┌─────────────────────┐
|
|
210
217
|
│ Claude Code / │ ◄────────────────────► │ enquire │
|
|
211
|
-
│ Cursor /
|
|
218
|
+
│ Cursor / │ tools/resources/ │ (this server) │
|
|
219
|
+
│ OpenClaw / │ │ │
|
|
220
|
+
│ Codex │ │ │
|
|
212
221
|
└─────────────────┘ prompts └─────────┬───────────┘
|
|
213
222
|
│
|
|
214
223
|
┌───────────┼────────────┐
|
|
@@ -291,7 +300,7 @@ Verify the source. `LIST FROM "01_Projects"` matches notes whose path starts wit
|
|
|
291
300
|
We implement a deliberately small subset (`LIST` / `TABLE`, `FROM "folder" | #tag`, `WHERE pred (AND|OR pred)*`, `SORT`, `LIMIT`; ops `=`, `!=`, `contains`, `like`). No arithmetic / functions / `FLATTEN` / `GROUP BY` / joins / parenthesized precedence. PRs that close those gaps are welcome — see [CONTRIBUTING.md](./CONTRIBUTING.md).
|
|
292
301
|
|
|
293
302
|
**How big a vault can it handle?**
|
|
294
|
-
Tested daily against a
|
|
303
|
+
Tested daily against a ~120-note vault; benched up to 1000 synthetic notes (see [`scripts/bench-search.mjs`](./scripts/bench-search.mjs)). The walker is O(notes) per call; the in-memory cache makes repeat reads O(1). For multi-thousand-note vaults pass `--persistent-index` — the SQLite FTS5 backend gives sub-millisecond BM25 search (37–103x faster than the linear-scan path on 100–1000 notes).
|
|
295
304
|
|
|
296
305
|
**Why scoped npm name (`@oomkapwn/enquire-mcp`)?**
|
|
297
306
|
A scoped name protects the brand and side-steps the very crowded `obsidian-mcp` / `mcp-obsidian` namespace on npm. The CLI binary is `enquire-mcp` to match the npm package name.
|
|
@@ -301,7 +310,7 @@ A scoped name protects the brand and side-steps the very crowded `obsidian-mcp`
|
|
|
301
310
|
## Develop
|
|
302
311
|
|
|
303
312
|
```bash
|
|
304
|
-
npm test #
|
|
313
|
+
npm test # full suite (count in the badge)
|
|
305
314
|
npm run test:coverage # vitest --coverage (v8 provider)
|
|
306
315
|
npm run lint # biome check
|
|
307
316
|
npm run lint:fix # biome check --write (auto-fixes)
|
|
@@ -329,8 +338,11 @@ Build runs `tsc` and marks `dist/index.js` executable. CI tests Node 20 / 22 / 2
|
|
|
329
338
|
|
|
330
339
|
Semantic versioning. See [CHANGELOG.md](./CHANGELOG.md) for the full history.
|
|
331
340
|
|
|
332
|
-
- **0.
|
|
333
|
-
- **
|
|
341
|
+
- **0.10.x** — SQLite FTS5 inverted index (opt-in via `--persistent-index`), BM25 ranking, sub-millisecond search on multi-thousand-note vaults (37–103x faster than the linear scan path), chunk-level addressing via `obsidian://chunk/{n}/{path}` resource. Filter API on full-text search (`tag`, `since`, `folder`).
|
|
342
|
+
- **0.9.x** — `search_text` switched to AND-tokenizer default with structured response (BREAKING). Parallel file reads in scan path.
|
|
343
|
+
- **0.8.x** — DQL `contains` semantics for arrays (membership, not substring). Code of Conduct.
|
|
344
|
+
- **0.7.x** — Renamed `obsidian-mcp` → `enquire-mcp` (via brief `memex` detour) to escape the crowded `obsidian-mcp` npm namespace and to land on a name with a clear historical referent — Tim Berners-Lee's 1980 ENQUIRE prototype of the Web.
|
|
345
|
+
- **Roadmap (beyond 0.10)** — graph queries (multi-hop, hub/orphan detection); refactoring tools (`rename_note`, `rename_tag` with wikilink rewrite); DQL expressions / parentheses / `FLATTEN` / `GROUP BY`; benchmarks at 10k+ vaults.
|
|
334
346
|
|
|
335
347
|
---
|
|
336
348
|
|
package/SECURITY.md
CHANGED
|
@@ -47,3 +47,14 @@ When `--persistent-cache` is enabled, full note bodies are written to a JSON fil
|
|
|
47
47
|
- Deleted notes: on load, entries whose source file no longer exists are dropped from memory AND the cache is marked dirty so the next save rewrites the file without those entries.
|
|
48
48
|
- Manual purge: `enquire-mcp clear-cache --vault <path>` deletes the cache file.
|
|
49
49
|
- **Caveat:** anyone with read access to your user account can read the cache file. If your threat model includes other local users on the same machine, do not use `--persistent-cache`.
|
|
50
|
+
|
|
51
|
+
## Persistent FTS5 index: privacy posture
|
|
52
|
+
|
|
53
|
+
When `--persistent-index` is enabled, the search-index file at `<vault-hash>.fts5.db` (alongside the parse cache) stores **chunked note content** (paragraph-level, ~4 KB each), the **comma-serialized tag list** of each note, and the **list of wikilink targets** as part of the FTS5 enrichment for recall.
|
|
54
|
+
|
|
55
|
+
- DB file + WAL (`<file>-wal`) + SHM (`<file>-shm`) sidecar files are all chmod'd to **`0600`** on every `open()`.
|
|
56
|
+
- Parent directory mode is **`0700`**.
|
|
57
|
+
- `obsidian://chunk/{n}/{path}` resource returns the **raw original chunk text only** — the synthetic `[wikilink_targets: …]` enrichment used for FTS5 recall does NOT leak into the resource response.
|
|
58
|
+
- Cross-vault contamination guard: a `meta` table stores `vault_root` and `tokenize_mode`; if either changes between runs, the index is dropped and rebuilt with a stderr warning.
|
|
59
|
+
- Manual purge: `enquire-mcp clear-index --vault <path>` removes the `.fts5.db`, `.fts5.db-wal`, and `.fts5.db-shm` files.
|
|
60
|
+
- **Caveat:** SQLite WAL mode keeps the most-recent uncommitted writes in `<file>-wal`. If you delete only `<file>` manually (not via `clear-index`), some recently-indexed chunks may persist in the sidecar. Always use `clear-index` for full removal.
|
|
Binary file
|
package/dist/fts5.d.ts
CHANGED
|
@@ -25,6 +25,8 @@ export declare class FtsIndex {
|
|
|
25
25
|
tokenize?: TokenizeMode;
|
|
26
26
|
});
|
|
27
27
|
open(): Promise<void>;
|
|
28
|
+
/** Remove the index file + WAL/SHM sidecar files. Idempotent. */
|
|
29
|
+
clearOnDisk(): Promise<boolean>;
|
|
28
30
|
close(): void;
|
|
29
31
|
private bootstrapSchema;
|
|
30
32
|
private readMeta;
|
|
@@ -57,7 +59,10 @@ export declare class FtsIndex {
|
|
|
57
59
|
/**
|
|
58
60
|
* Fetch a single chunk by (rel_path, chunk_index). Backs the
|
|
59
61
|
* `obsidian://chunk/{chunkIndex}/{+notePath}` resource so MCP clients can
|
|
60
|
-
* deep-link into specific chunks returned by a prior search.
|
|
62
|
+
* deep-link into specific chunks returned by a prior search. Returns the
|
|
63
|
+
* RAW chunk text (the unenriched original); the FTS5 `content` column
|
|
64
|
+
* additionally carries a synthetic wikilink-targets meta-line for recall,
|
|
65
|
+
* which would otherwise pollute resource responses (audit v0.10.4 P1).
|
|
61
66
|
*/
|
|
62
67
|
getChunk(relPath: string, chunkIndex: number): {
|
|
63
68
|
content: string;
|
package/dist/fts5.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fts5.d.ts","sourceRoot":"","sources":["../src/fts5.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"fts5.d.ts","sourceRoot":"","sources":["../src/fts5.ts"],"names":[],"mappings":"AAwBA,MAAM,MAAM,YAAY,GAAG,WAAW,GAAG,SAAS,CAAC;AAEnD,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;CACtB;AAyCD,qBAAa,QAAQ;IACnB,OAAO,CAAC,EAAE,CAAmB;IAC7B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAe;IACxC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;gBAEvB,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,YAAY,CAAA;KAAE;IAMxE,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAiB3B,iEAAiE;IAC3D,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAcrC,KAAK,IAAI,IAAI;IAOb,OAAO,CAAC,eAAe;IAqDvB,OAAO,CAAC,QAAQ;IAQhB,OAAO,CAAC,SAAS;IAMjB,OAAO,CAAC,SAAS;IAKjB;;;;OAIG;IACH,IAAI,CAAC,WAAW,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,GAAG;QAC9D,KAAK,EAAE,MAAM,EAAE,CAAC;QAChB,OAAO,EAAE,MAAM,EAAE,CAAC;QAClB,OAAO,EAAE,MAAM,EAAE,CAAC;QAClB,SAAS,EAAE,MAAM,EAAE,CAAC;KACrB;IAuBD,oDAAoD;IACpD,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAM/B,wEAAwE;IACxE,WAAW,CACT,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,eAAe,GAAE,MAAM,EAAO,EAC9B,IAAI,GAAE,MAAM,EAAO,GAClB,MAAM;IA2BT,MAAM,CACJ,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAO,GAClF,YAAY,EAAE;IAyDjB;;;;;;;OAOG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAQ/G,WAAW,IAAI,MAAM;IAMrB,UAAU,IAAI,MAAM;CAKrB;AAMD,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAe/C;AAED,UAAU,YAAY;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAID;;;GAGG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,SAAkB,GAAG,YAAY,EAAE,CA4CxF;AAuBD,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAM1D"}
|
package/dist/fts5.js
CHANGED
|
@@ -14,7 +14,7 @@ import { createHash } from "node:crypto";
|
|
|
14
14
|
import { promises as fs } from "node:fs";
|
|
15
15
|
import * as os from "node:os";
|
|
16
16
|
import * as path from "node:path";
|
|
17
|
-
const SCHEMA_VERSION =
|
|
17
|
+
const SCHEMA_VERSION = 3;
|
|
18
18
|
// Lazy-loaded better-sqlite3 binding so missing native module surfaces only
|
|
19
19
|
// when --persistent-index is actually used.
|
|
20
20
|
let BetterSqliteCtor = null;
|
|
@@ -53,6 +53,25 @@ export class FtsIndex {
|
|
|
53
53
|
this.db.pragma("journal_mode = WAL");
|
|
54
54
|
this.db.pragma("synchronous = NORMAL");
|
|
55
55
|
this.bootstrapSchema();
|
|
56
|
+
// Best-effort: tighten perms on the DB and its WAL/SHM sidecar files to
|
|
57
|
+
// 0600. The index stores chunked note content so it deserves the same
|
|
58
|
+
// privacy posture as the persistent parse cache (see SECURITY.md).
|
|
59
|
+
await Promise.all([this.file, `${this.file}-wal`, `${this.file}-shm`].map((p) => fs.chmod(p, 0o600).catch(() => { })));
|
|
60
|
+
}
|
|
61
|
+
/** Remove the index file + WAL/SHM sidecar files. Idempotent. */
|
|
62
|
+
async clearOnDisk() {
|
|
63
|
+
this.close();
|
|
64
|
+
let removed = false;
|
|
65
|
+
for (const p of [this.file, `${this.file}-wal`, `${this.file}-shm`]) {
|
|
66
|
+
try {
|
|
67
|
+
await fs.unlink(p);
|
|
68
|
+
removed = true;
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
// missing files are fine
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return removed;
|
|
56
75
|
}
|
|
57
76
|
close() {
|
|
58
77
|
if (this.db) {
|
|
@@ -95,6 +114,7 @@ export class FtsIndex {
|
|
|
95
114
|
line_start UNINDEXED,
|
|
96
115
|
line_end UNINDEXED,
|
|
97
116
|
tags UNINDEXED,
|
|
117
|
+
raw_content UNINDEXED,
|
|
98
118
|
tokenize='${tokenizeArg}'
|
|
99
119
|
);
|
|
100
120
|
CREATE TABLE IF NOT EXISTS source_state (
|
|
@@ -172,15 +192,20 @@ export class FtsIndex {
|
|
|
172
192
|
const db = this.requireDb();
|
|
173
193
|
const chunks = chunkContent(content);
|
|
174
194
|
db.prepare("DELETE FROM chunks WHERE rel_path = ?").run(relPath);
|
|
175
|
-
const insert = db.prepare("INSERT INTO chunks (content, rel_path, chunk_index, line_start, line_end, tags) VALUES (?, ?, ?, ?, ?, ?)");
|
|
176
|
-
//
|
|
177
|
-
//
|
|
195
|
+
const insert = db.prepare("INSERT INTO chunks (content, rel_path, chunk_index, line_start, line_end, tags, raw_content) VALUES (?, ?, ?, ?, ?, ?, ?)");
|
|
196
|
+
// `tags` is a comma-delimited list so the filter LIKE pattern can wrap it
|
|
197
|
+
// with leading/trailing commas for exact-tag matching at query time.
|
|
178
198
|
const tagsSerialized = tags.length ? tags.join(",") : "";
|
|
179
199
|
chunks.forEach((c, i) => {
|
|
180
|
-
//
|
|
181
|
-
//
|
|
200
|
+
// FTS5 column `content` carries an enriched form: original text + a
|
|
201
|
+
// synthetic `[wikilink_targets: …]` meta-line so a search for a link
|
|
202
|
+
// target name recalls notes that link out without naming it inline.
|
|
203
|
+
// The unindexed `raw_content` keeps the *original* chunk so the
|
|
204
|
+
// `obsidian://chunk/{n}/{path}` resource can return verbatim text
|
|
205
|
+
// (the audit P1 — without raw_content the resource was leaking the
|
|
206
|
+
// synthetic line into MCP-client view, breaking quoting).
|
|
182
207
|
const enriched = wikilinkTargets.length ? `${c.text}\n[wikilink_targets: ${wikilinkTargets.join(", ")}]` : c.text;
|
|
183
|
-
insert.run(enriched, relPath, i, c.lineStart, c.lineEnd, tagsSerialized);
|
|
208
|
+
insert.run(enriched, relPath, i, c.lineStart, c.lineEnd, tagsSerialized, c.text);
|
|
184
209
|
});
|
|
185
210
|
db.prepare("INSERT OR REPLACE INTO source_state (rel_path, mtime_ms, n_chunks, indexed_at) VALUES (?, ?, ?, ?)").run(relPath, mtimeMs, chunks.length, new Date().toISOString());
|
|
186
211
|
return chunks.length;
|
|
@@ -194,8 +219,12 @@ export class FtsIndex {
|
|
|
194
219
|
const where = ["chunks MATCH ?"];
|
|
195
220
|
const params = [safe];
|
|
196
221
|
if (opts.folder) {
|
|
197
|
-
|
|
198
|
-
|
|
222
|
+
// Prefix-equality via substr — avoids GLOB pattern semantics so folder
|
|
223
|
+
// names containing `*`, `?`, `[`, `]` (rare but possible in Obsidian)
|
|
224
|
+
// don't expand into wider matches.
|
|
225
|
+
const prefix = `${opts.folder.replace(/\/+$/, "")}/`;
|
|
226
|
+
where.push("substr(chunks.rel_path, 1, ?) = ?");
|
|
227
|
+
params.push(prefix.length, prefix);
|
|
199
228
|
}
|
|
200
229
|
if (opts.tag) {
|
|
201
230
|
// Exact-tag membership inside the comma-separated `tags` column —
|
|
@@ -234,13 +263,15 @@ export class FtsIndex {
|
|
|
234
263
|
/**
|
|
235
264
|
* Fetch a single chunk by (rel_path, chunk_index). Backs the
|
|
236
265
|
* `obsidian://chunk/{chunkIndex}/{+notePath}` resource so MCP clients can
|
|
237
|
-
* deep-link into specific chunks returned by a prior search.
|
|
266
|
+
* deep-link into specific chunks returned by a prior search. Returns the
|
|
267
|
+
* RAW chunk text (the unenriched original); the FTS5 `content` column
|
|
268
|
+
* additionally carries a synthetic wikilink-targets meta-line for recall,
|
|
269
|
+
* which would otherwise pollute resource responses (audit v0.10.4 P1).
|
|
238
270
|
*/
|
|
239
271
|
getChunk(relPath, chunkIndex) {
|
|
240
272
|
const db = this.requireDb();
|
|
241
|
-
const
|
|
242
|
-
|
|
243
|
-
.get(relPath, chunkIndex);
|
|
273
|
+
const sql = "SELECT raw_content AS content, line_start, line_end FROM chunks WHERE rel_path = ? AND chunk_index = ?";
|
|
274
|
+
const row = db.prepare(sql).get(relPath, chunkIndex);
|
|
244
275
|
return row ?? null;
|
|
245
276
|
}
|
|
246
277
|
totalChunks() {
|
package/dist/fts5.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fts5.js","sourceRoot":"","sources":["../src/fts5.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"fts5.js","sourceRoot":"","sources":["../src/fts5.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AA4BA,UAAU,YAAY;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;IACnC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,iBAAe,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CA6FnC;AAED,iBAAe,WAAW,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAqF5D;AAumBD,iBAAS,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAM3D;AAsCD,OAAO,EAAE,IAAI,EAAE,gBAAgB,EAAE,WAAW,EAAE,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -7,9 +7,9 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
|
|
|
7
7
|
import { Command } from "commander";
|
|
8
8
|
import { z } from "zod";
|
|
9
9
|
import { defaultIndexFile, FtsIndex } from "./fts5.js";
|
|
10
|
-
import { appendToNote, createNote, dataviewQuery, getBacklinks, getOutboundLinks, getRecentEdits, getUnresolvedWikilinks, listNotes, listTags, readNote, resolveWikilink, searchText } from "./tools.js";
|
|
10
|
+
import { appendToNote, createNote, dataviewQuery, getBacklinks, getOutboundLinks, getRecentEdits, getUnresolvedWikilinks, listNotes, listTags, readNote, resolveWikilink, searchText, validateNoteProposal } from "./tools.js";
|
|
11
11
|
import { Vault } from "./vault.js";
|
|
12
|
-
const VERSION = "0.
|
|
12
|
+
const VERSION = "0.12.0";
|
|
13
13
|
async function main() {
|
|
14
14
|
const program = new Command();
|
|
15
15
|
program
|
|
@@ -28,6 +28,7 @@ async function main() {
|
|
|
28
28
|
.option("--persistent-index", "Maintain a SQLite FTS5 inverted index for sub-100ms BM25-ranked search. Registers obsidian_full_text_search.")
|
|
29
29
|
.option("--index-file <path>", "Override the FTS5 index file location")
|
|
30
30
|
.option("--tokenize <mode>", "FTS5 tokenize mode: 'unicode61' (default; Latin/Cyrillic) or 'trigram' (CJK/mixed-script)")
|
|
31
|
+
.option("--exclude-glob <pattern...>", "Glob pattern(s) — paths matching any pattern are invisible to all tools and refuse direct reads. Supports `*`, `**`, `?`. Repeatable. Example: `--exclude-glob '02_Personal/**' '*.private.md'`.")
|
|
31
32
|
.action(async (opts) => {
|
|
32
33
|
await startServer(opts);
|
|
33
34
|
});
|
|
@@ -47,6 +48,24 @@ async function main() {
|
|
|
47
48
|
process.stdout.write(`enquire: no cache file at ${vault.cacheFile}\n`);
|
|
48
49
|
}
|
|
49
50
|
});
|
|
51
|
+
program
|
|
52
|
+
.command("clear-index")
|
|
53
|
+
.description("Delete the FTS5 search-index files (.fts5.db + WAL/SHM sidecar) for a given vault")
|
|
54
|
+
.requiredOption("--vault <path>", "Vault whose index to delete")
|
|
55
|
+
.option("--index-file <path>", "Override the FTS5 index file location")
|
|
56
|
+
.action(async (opts) => {
|
|
57
|
+
const vault = new Vault(opts.vault);
|
|
58
|
+
await vault.ensureExists();
|
|
59
|
+
const indexFile = opts.indexFile ?? defaultIndexFile(vault.root);
|
|
60
|
+
const idx = new FtsIndex({ file: indexFile, vaultRoot: vault.root });
|
|
61
|
+
const removed = await idx.clearOnDisk();
|
|
62
|
+
if (removed) {
|
|
63
|
+
process.stdout.write(`enquire: removed fts5 index files at ${indexFile}\n`);
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
process.stdout.write(`enquire: no fts5 index files at ${indexFile}\n`);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
50
69
|
program
|
|
51
70
|
.command("index")
|
|
52
71
|
.description("Cold-build (or refresh) the FTS5 search index for a vault. Useful before first --persistent-index use.")
|
|
@@ -76,7 +95,8 @@ async function startServer(opts) {
|
|
|
76
95
|
maxFileBytes: opts.maxFileBytes !== undefined ? parsePositiveInt(opts.maxFileBytes, "--max-file-bytes") : undefined,
|
|
77
96
|
maxCacheEntries: opts.cacheSize !== undefined ? parsePositiveInt(opts.cacheSize, "--cache-size") : undefined,
|
|
78
97
|
persistentCache: !!opts.persistentCache,
|
|
79
|
-
cacheFile: opts.cacheFile
|
|
98
|
+
cacheFile: opts.cacheFile,
|
|
99
|
+
excludeGlobs: opts.excludeGlob
|
|
80
100
|
});
|
|
81
101
|
await vault.ensureExists();
|
|
82
102
|
// Optional FTS5 index. Sync on boot so the first MCP call sees a fresh
|
|
@@ -87,8 +107,15 @@ async function startServer(opts) {
|
|
|
87
107
|
const tokenize = opts.tokenize === "trigram" ? "trigram" : "unicode61";
|
|
88
108
|
const indexFile = opts.indexFile ?? defaultIndexFile(vault.root);
|
|
89
109
|
ftsIndex = new FtsIndex({ file: indexFile, vaultRoot: vault.root, tokenize });
|
|
90
|
-
|
|
91
|
-
|
|
110
|
+
try {
|
|
111
|
+
await ftsIndex.open();
|
|
112
|
+
await syncFtsIndex(vault, ftsIndex);
|
|
113
|
+
}
|
|
114
|
+
catch (err) {
|
|
115
|
+
// Don't leak the SQLite handle if open() succeeded but sync threw.
|
|
116
|
+
ftsIndex.close();
|
|
117
|
+
throw err;
|
|
118
|
+
}
|
|
92
119
|
}
|
|
93
120
|
const server = new McpServer({
|
|
94
121
|
name: "enquire",
|
|
@@ -138,7 +165,8 @@ async function startServer(opts) {
|
|
|
138
165
|
const writeMode = vault.writeEnabled ? "WRITE-ENABLED" : "read-only";
|
|
139
166
|
const cacheMode = vault.persistentCacheEnabled ? `, persistent-cache=${vault.cacheFile}` : "";
|
|
140
167
|
const ftsMode = ftsIndex ? `, fts5-index (${ftsIndex.totalFiles()} files / ${ftsIndex.totalChunks()} chunks)` : "";
|
|
141
|
-
|
|
168
|
+
const privacyMode = vault.excludeGlobs.length > 0 ? `, exclude-globs=${vault.excludeGlobs.length}` : "";
|
|
169
|
+
process.stderr.write(`enquire ${VERSION} ready (${writeMode}, vault=${vault.root}${cacheMode}${ftsMode}${privacyMode})\n`);
|
|
142
170
|
if (ftsIndex) {
|
|
143
171
|
const closeFts = () => ftsIndex?.close();
|
|
144
172
|
process.once("SIGINT", closeFts);
|
|
@@ -237,11 +265,18 @@ function registerReadTools(server, vault) {
|
|
|
237
265
|
}, async (args) => textResult(await listNotes(vault, args)));
|
|
238
266
|
server.registerTool("obsidian_read_note", {
|
|
239
267
|
title: "Read note",
|
|
240
|
-
description:
|
|
268
|
+
description: 'Read a note by relative path or by title (filename without .md). Default `format: "full"` returns content + frontmatter + wikilinks + embeds + tags. `format: "map"` returns just headings + frontmatter keys + counts (no body) — useful for planning a surgical edit without paying token cost for the body. Title accepts periodic-note aliases ("today"/"daily"/"weekly"/"monthly") that resolve to the standard `YYYY-MM-DD`/`YYYY-Www`/`YYYY-MM` names. Errors include `Did you mean: ...` suggestions on near-misses.',
|
|
241
269
|
annotations: { ...READ_ONLY, title: "Read note" },
|
|
242
270
|
inputSchema: {
|
|
243
271
|
path: z.string().optional().describe("Path relative to vault root, with or without .md"),
|
|
244
|
-
title: z
|
|
272
|
+
title: z
|
|
273
|
+
.string()
|
|
274
|
+
.optional()
|
|
275
|
+
.describe('Note title (filename without .md). Aliases: "today"/"daily"/"weekly"/"monthly".'),
|
|
276
|
+
format: z
|
|
277
|
+
.enum(["full", "map"])
|
|
278
|
+
.optional()
|
|
279
|
+
.describe('"full" (default) returns body + parsed metadata. "map" returns just headings + counts.')
|
|
245
280
|
}
|
|
246
281
|
}, async (args) => textResult(await readNote(vault, args)));
|
|
247
282
|
server.registerTool("obsidian_resolve_wikilink", {
|
|
@@ -339,6 +374,19 @@ function registerReadTools(server, vault) {
|
|
|
339
374
|
include_unresolved: z.boolean().optional().describe("Include links that don't resolve (default true)")
|
|
340
375
|
}
|
|
341
376
|
}, async (args) => textResult(await getOutboundLinks(vault, args)));
|
|
377
|
+
server.registerTool("obsidian_validate_note_proposal", {
|
|
378
|
+
title: "Validate a proposed new note (anti-slop)",
|
|
379
|
+
description: "Lint a draft note BEFORE writing. Closes the #1 LLM-write pain: AI generates structurally-broken notes (bad YAML, fake wikilinks, inconsistent tags). This tool parses the proposed YAML, resolves every [[wikilink]] against the live vault (broken/resolved with did-you-mean), pre-classifies every tag (existing vs new), and checks for path/title collisions. Returns errors (blocking) + warnings (non-blocking) + per-link/tag diagnostics. Always available — does NOT require --enable-write. Recommended workflow: validate → fix → obsidian_create_note.",
|
|
380
|
+
annotations: { ...READ_ONLY, title: "Validate note proposal" },
|
|
381
|
+
inputSchema: {
|
|
382
|
+
path: z.string().describe("Vault-relative path the LLM intends to write to (e.g. 'Inbox/idea.md')"),
|
|
383
|
+
content: z.string().describe("Full proposed markdown content including any frontmatter block"),
|
|
384
|
+
mode: z
|
|
385
|
+
.enum(["create", "overwrite", "append"])
|
|
386
|
+
.optional()
|
|
387
|
+
.describe('"create" (default) errors if path exists. "overwrite"/"append" allow existing path.')
|
|
388
|
+
}
|
|
389
|
+
}, async (args) => textResult(await validateNoteProposal(vault, args)));
|
|
342
390
|
}
|
|
343
391
|
function registerWriteTools(server, vault) {
|
|
344
392
|
// destructiveHint=true: `obsidian_create_note` with overwrite=true replaces a
|