neuro-vault-mcp 1.7.2 → 3.0.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/README.md +25 -347
- package/dist/cli.d.ts +30 -22
- package/dist/cli.js +549 -192
- package/dist/cli.js.map +1 -1
- package/package.json +4 -1
package/README.md
CHANGED
|
@@ -15,43 +15,34 @@
|
|
|
15
15
|
- 🧠 **Semantic search over your existing vault** — reuses [Smart Connections](https://github.com/brianpetro/obsidian-smart-connections) embeddings already in your vault. No re-indexing, no API keys, no extra infrastructure.
|
|
16
16
|
- 🎯 **Mode-aware retrieval** — `quick` for direct lookups, `deep` for exploratory questions with block-level results and semantic expansion of related notes.
|
|
17
17
|
- ✍️ **Direct vault operations** — read, create, append, and prepend notes; manage frontmatter properties and inspect tags (including daily notes) straight from your AI assistant via the [Obsidian CLI](https://github.com/AlexMost/obsidian-cli).
|
|
18
|
+
- 🔎 **Structured queries** — one MongoDB-style call (`query_notes`) replaces N+1 chains like "list tags → read each note's property". Ask "active projects with #ai" or "todo tasks created this week" and get a single ranked response.
|
|
18
19
|
- ⚡ **Zero infrastructure** — local stdio MCP server, in-memory index, no database, no background processes, no watchers.
|
|
19
20
|
- 🔌 **Drop-in for any MCP client** — Claude Code, Cursor, Windsurf — configuration is a single JSON block.
|
|
20
21
|
|
|
21
22
|
---
|
|
22
23
|
|
|
23
|
-
|
|
24
|
-
<summary><b>📦 Install & MCP client config</b></summary>
|
|
25
|
-
|
|
26
|
-
### Requirements
|
|
24
|
+
## 🏗 How it works
|
|
27
25
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
26
|
+
```mermaid
|
|
27
|
+
flowchart LR
|
|
28
|
+
You([You]) --> AI[AI assistant]
|
|
29
|
+
AI <-->|MCP| NV[Neuro Vault]
|
|
30
|
+
NV <--> Vault[(Obsidian vault)]
|
|
31
|
+
```
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
You ask, the assistant calls Neuro Vault, Neuro Vault reads your vault — semantic search uses embeddings already in `.smart-env/`, vault operations go through the `obsidian` CLI. No database, no background processes.
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
npm install -g neuro-vault-mcp
|
|
37
|
-
```
|
|
35
|
+
For module wiring and internal data flow, see [docs/architecture/module-structure.md](./docs/architecture/module-structure.md).
|
|
38
36
|
|
|
39
|
-
|
|
37
|
+
---
|
|
40
38
|
|
|
41
|
-
|
|
39
|
+
## ⚡ Quickstart
|
|
42
40
|
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
"mcpServers": {
|
|
46
|
-
"neuro-vault": {
|
|
47
|
-
"command": "neuro-vault-mcp",
|
|
48
|
-
"args": ["--vault", "/absolute/path/to/your/vault"]
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
}
|
|
41
|
+
```bash
|
|
42
|
+
npm install -g neuro-vault-mcp
|
|
52
43
|
```
|
|
53
44
|
|
|
54
|
-
|
|
45
|
+
Add to your MCP client config (here: Claude Code's `~/.claude/settings.json`):
|
|
55
46
|
|
|
56
47
|
```json
|
|
57
48
|
{
|
|
@@ -64,340 +55,27 @@ For Cursor or Windsurf (`.cursor/mcp.json` / `.windsurf/mcp.json`):
|
|
|
64
55
|
}
|
|
65
56
|
```
|
|
66
57
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
```json
|
|
70
|
-
{
|
|
71
|
-
"mcpServers": {
|
|
72
|
-
"neuro-vault": {
|
|
73
|
-
"command": "npx",
|
|
74
|
-
"args": ["-y", "neuro-vault-mcp", "--vault", "/absolute/path/to/your/vault"]
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
### 3. Try it
|
|
81
|
-
|
|
82
|
-
Ask your assistant:
|
|
58
|
+
Then ask your assistant:
|
|
83
59
|
|
|
84
60
|
> "What did I write about building AI agents?"
|
|
85
|
-
>
|
|
86
|
-
> "Find my notes on productivity systems"
|
|
87
|
-
>
|
|
88
|
-
> "What are all my ideas related to embeddings?"
|
|
89
61
|
|
|
90
62
|
On first run the embedding model downloads automatically (~40 MB). Subsequent starts are fast.
|
|
91
63
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
---
|
|
95
|
-
|
|
96
|
-
## 🔍 Semantic Search
|
|
97
|
-
|
|
98
|
-
Find notes by meaning, not by filename. The server embeds your query with `TaylorAI/bge-micro-v2`, runs cosine similarity against the Smart Connections corpus loaded into memory at startup, and returns ranked results with optional block-level matches and semantic expansion.
|
|
99
|
-
|
|
100
|
-
### Tools
|
|
101
|
-
|
|
102
|
-
#### `search_notes`
|
|
103
|
-
|
|
104
|
-
Search the vault by semantic similarity.
|
|
105
|
-
|
|
106
|
-
```typescript
|
|
107
|
-
search_notes({
|
|
108
|
-
query: string, // short keyword query (1-4 words)
|
|
109
|
-
mode?: "quick" | "deep", // default: "quick"
|
|
110
|
-
threshold?: number, // override mode default (0–1)
|
|
111
|
-
expansion?: boolean, // override mode default
|
|
112
|
-
expansion_limit?: number, // how many top results to expand (default: 3)
|
|
113
|
-
})
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
Returns `results` (ranked notes) and `blockResults` (ranked sections — scoped to matched notes in `quick` mode, all sources in `deep` mode).
|
|
117
|
-
|
|
118
|
-
#### `get_similar_notes`
|
|
119
|
-
|
|
120
|
-
Find notes similar to a given note path. Use this after `search_notes` finds a relevant note — it discovers related content without needing a text query.
|
|
121
|
-
|
|
122
|
-
```typescript
|
|
123
|
-
get_similar_notes({
|
|
124
|
-
note_path: string, // vault-relative POSIX path, e.g. "Projects/neuro-vault.md"
|
|
125
|
-
limit?: number, // default: 10
|
|
126
|
-
threshold?: number, // default: 0.5
|
|
127
|
-
})
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
#### `find_duplicates`
|
|
131
|
-
|
|
132
|
-
Find note pairs with high embedding similarity. Useful for vault maintenance: identifies notes that cover the same topic and could be merged.
|
|
133
|
-
|
|
134
|
-
```typescript
|
|
135
|
-
find_duplicates({
|
|
136
|
-
threshold?: number, // default: 0.9
|
|
137
|
-
})
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
#### `get_stats`
|
|
141
|
-
|
|
142
|
-
Report loaded corpus statistics. Returns `{ totalNotes, totalBlocks, embeddingDimension, modelKey }`.
|
|
143
|
-
|
|
144
|
-
### Behavior
|
|
145
|
-
|
|
146
|
-
Every search picks a mode that controls retrieval depth:
|
|
147
|
-
|
|
148
|
-
| Mode | Use when | Limit | Threshold | Expansion |
|
|
149
|
-
| ------- | --------------------------------- | ----- | --------- | --------- |
|
|
150
|
-
| `quick` | Specific question, need 1-2 notes | 3 | 0.50 | off |
|
|
151
|
-
| `deep` | Broad topic, need an overview | 8 | 0.35 | on |
|
|
152
|
-
|
|
153
|
-
The AI assistant picks the mode automatically based on your question, or you can pass it explicitly.
|
|
154
|
-
|
|
155
|
-
- **Block-level results (deep mode)** — the server also searches by individual note sections, surfacing the exact paragraphs that match, not just the notes that contain them.
|
|
156
|
-
- **Expansion (deep mode)** — after finding top results, the server uses their embeddings to discover neighboring notes that don't directly match your query but are semantically close to what you found.
|
|
157
|
-
- **Automatic fallback** — when vector search returns nothing, the server retries with a lower similarity threshold (0.3). If still nothing, the assistant can fall back to its own file-search tools.
|
|
158
|
-
|
|
159
|
-
### Tips for better results
|
|
160
|
-
|
|
161
|
-
- Use short keyword queries (1–4 words), not full sentences.
|
|
162
|
-
- Call multiple times for synonyms and translations: `"embeddings"`, then `"векторний пошук"`, then `"vector search"`.
|
|
163
|
-
- Lower the threshold to `0.3` if nothing comes back.
|
|
164
|
-
- Use `deep` mode for exploratory questions.
|
|
165
|
-
|
|
166
|
-
---
|
|
167
|
-
|
|
168
|
-
## 🗂 Vault Operations
|
|
169
|
-
|
|
170
|
-
> Requires the [Obsidian CLI](https://github.com/AlexMost/obsidian-cli) on `PATH` and Obsidian running. Pass `--no-operations` to disable.
|
|
171
|
-
|
|
172
|
-
Read and write notes through Obsidian itself — the operations module shells out to the `obsidian` CLI, so changes are picked up by Smart Connections, sync, and any other plugin you have installed. No bypass of Obsidian's own state.
|
|
173
|
-
|
|
174
|
-
### Tools
|
|
175
|
-
|
|
176
|
-
#### `read_note`
|
|
177
|
-
|
|
178
|
-
Read a note's contents. Provide exactly one of `name` or `path`.
|
|
179
|
-
|
|
180
|
-
```typescript
|
|
181
|
-
read_note({
|
|
182
|
-
name?: string, // wikilink-style: "My Note"
|
|
183
|
-
path?: string, // vault-relative: "Folder/My Note.md"
|
|
184
|
-
})
|
|
185
|
-
```
|
|
186
|
-
|
|
187
|
-
Returns `{ path, content }`.
|
|
188
|
-
|
|
189
|
-
#### `create_note`
|
|
190
|
-
|
|
191
|
-
Create a new note. `overwrite: true` is destructive — the AI assistant will ask before passing it.
|
|
192
|
-
|
|
193
|
-
```typescript
|
|
194
|
-
create_note({
|
|
195
|
-
name?: string,
|
|
196
|
-
path?: string,
|
|
197
|
-
content?: string,
|
|
198
|
-
template?: string,
|
|
199
|
-
overwrite?: boolean,
|
|
200
|
-
})
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
#### `edit_note`
|
|
204
|
-
|
|
205
|
-
Add content to an existing note.
|
|
206
|
-
|
|
207
|
-
```typescript
|
|
208
|
-
edit_note({
|
|
209
|
-
name?: string,
|
|
210
|
-
path?: string,
|
|
211
|
-
content: string,
|
|
212
|
-
position: 'append' | 'prepend',
|
|
213
|
-
})
|
|
214
|
-
```
|
|
215
|
-
|
|
216
|
-
#### `read_daily`
|
|
217
|
-
|
|
218
|
-
Read today's daily note. Returns `{ path, content }`.
|
|
219
|
-
|
|
220
|
-
#### `append_daily`
|
|
221
|
-
|
|
222
|
-
Append content to today's daily note.
|
|
223
|
-
|
|
224
|
-
```typescript
|
|
225
|
-
append_daily({ content: string });
|
|
226
|
-
```
|
|
227
|
-
|
|
228
|
-
### Properties & Tags
|
|
229
|
-
|
|
230
|
-
Inspect and modify frontmatter without paying the token cost of reading whole notes. Properties and tags are the metadata an LLM agent checks dozens of times per session — _"what's the `status` on Quarterly review?"_, _"mark this task done"_, _"how many notes tagged #mcp?"_. Short request, precise answer, no full-note reads.
|
|
231
|
-
|
|
232
|
-
#### `set_property`
|
|
233
|
-
|
|
234
|
-
Set a frontmatter property on a note. The YAML type is inferred from the JS value (`string` → text, `number` → number, `boolean` → checkbox, `Array` → list). For `date` / `datetime` pass `type` explicitly. List items must not contain commas (obsidian-cli limitation).
|
|
235
|
-
|
|
236
|
-
```typescript
|
|
237
|
-
set_property({
|
|
238
|
-
file?: string, // wikilink-style: "My Note"
|
|
239
|
-
path?: string, // vault-relative: "Tasks/Quarterly review.md"
|
|
240
|
-
name: string, // property key, e.g. "status"
|
|
241
|
-
value: string | number | boolean | string[] | number[],
|
|
242
|
-
type?: 'text' | 'list' | 'number' | 'checkbox' | 'date' | 'datetime',
|
|
243
|
-
})
|
|
244
|
-
```
|
|
245
|
-
|
|
246
|
-
Returns `{ ok: true }`. Existing properties are overwritten.
|
|
247
|
-
|
|
248
|
-
#### `read_property`
|
|
249
|
-
|
|
250
|
-
Read a single frontmatter property value. Use `read_note` if you need the full frontmatter or accurate type information.
|
|
251
|
-
|
|
252
|
-
```typescript
|
|
253
|
-
read_property({
|
|
254
|
-
file?: string,
|
|
255
|
-
path?: string,
|
|
256
|
-
name: string,
|
|
257
|
-
})
|
|
258
|
-
```
|
|
259
|
-
|
|
260
|
-
Returns `{ value }`.
|
|
261
|
-
|
|
262
|
-
#### `remove_property`
|
|
263
|
-
|
|
264
|
-
Remove a frontmatter property. Idempotent — calling it on an absent property succeeds.
|
|
265
|
-
|
|
266
|
-
```typescript
|
|
267
|
-
remove_property({
|
|
268
|
-
file?: string,
|
|
269
|
-
path?: string,
|
|
270
|
-
name: string,
|
|
271
|
-
})
|
|
272
|
-
```
|
|
273
|
-
|
|
274
|
-
Returns `{ ok: true }`.
|
|
275
|
-
|
|
276
|
-
#### `list_properties`
|
|
277
|
-
|
|
278
|
-
List all frontmatter properties used across the vault, sorted by occurrence count desc. Useful for understanding the vault's metadata ontology before calling `set_property`.
|
|
279
|
-
|
|
280
|
-
Returns `[{ name, count }, ...]`.
|
|
281
|
-
|
|
282
|
-
#### `list_tags`
|
|
283
|
-
|
|
284
|
-
List all tags used across the vault, sorted by occurrence count desc.
|
|
285
|
-
|
|
286
|
-
Returns `[{ name, count }, ...]`.
|
|
287
|
-
|
|
288
|
-
#### `get_tag`
|
|
289
|
-
|
|
290
|
-
Get count and (optionally) the file list for a single tag. Pass `include_files: false` for popular tags where the file list would be large.
|
|
291
|
-
|
|
292
|
-
```typescript
|
|
293
|
-
get_tag({
|
|
294
|
-
name: string, // with or without leading "#"
|
|
295
|
-
include_files?: boolean, // default true
|
|
296
|
-
})
|
|
297
|
-
```
|
|
298
|
-
|
|
299
|
-
Returns `{ name, count, files? }`.
|
|
300
|
-
|
|
301
|
-
---
|
|
302
|
-
|
|
303
|
-
## 🏗 How it works
|
|
304
|
-
|
|
305
|
-
```mermaid
|
|
306
|
-
flowchart LR
|
|
307
|
-
You([You]) --> AI[AI assistant]
|
|
308
|
-
AI <-->|MCP| NV[Neuro Vault]
|
|
309
|
-
NV <--> Vault[(Obsidian vault)]
|
|
310
|
-
```
|
|
311
|
-
|
|
312
|
-
You ask, the assistant calls Neuro Vault, Neuro Vault reads your vault — semantic search uses embeddings already in `.smart-env/`, vault operations go through the `obsidian` CLI. No database, no background processes.
|
|
313
|
-
|
|
314
|
-
For module wiring and internal data flow, see [docs/architecture/module-structure.md](./docs/architecture/module-structure.md).
|
|
64
|
+
For other clients (Cursor / Windsurf / npx), see [docs/guide/installation.md](./docs/guide/installation.md).
|
|
315
65
|
|
|
316
66
|
---
|
|
317
67
|
|
|
318
|
-
|
|
319
|
-
<summary><b>🧭 Search routing guidance</b></summary>
|
|
320
|
-
|
|
321
|
-
Tool routing and retrieval policy are related, but not the same thing.
|
|
322
|
-
|
|
323
|
-
- Use **structural tools** first (your assistant's own file/path/title tools, or vault operations) for exact file, title, path, daily note, tag, property, wikilink, backlink, and link-traversal requests.
|
|
324
|
-
- Use `search_notes` for fuzzy topic, concept, and semantic retrieval.
|
|
325
|
-
- Use `get_similar_notes` after you already have a relevant note and want semantic expansion.
|
|
326
|
-
- Treat the routing guidance as behavior, not enforcement; the server does not hard-block other tool choices.
|
|
327
|
-
- Use semantic retrieval to find likely notes, then switch to structural tools when you need exact anchors.
|
|
328
|
-
|
|
329
|
-
</details>
|
|
330
|
-
|
|
331
|
-
<details>
|
|
332
|
-
<summary><b>⚙️ Configuration</b></summary>
|
|
333
|
-
|
|
334
|
-
### CLI Arguments
|
|
335
|
-
|
|
336
|
-
| Argument | Required | Default | Description |
|
|
337
|
-
| ---------------- | -------- | ---------- | ------------------------------------------------------- |
|
|
338
|
-
| `--vault` | yes | — | Absolute path to the Obsidian vault directory |
|
|
339
|
-
| `--semantic` | no | `true` | Enable semantic search module (`--no-semantic` to skip) |
|
|
340
|
-
| `--operations` | no | `true` | Enable vault operations module (`--no-operations`) |
|
|
341
|
-
| `--obsidian-cli` | no | `obsidian` | Path to the `obsidian` CLI binary (override only) |
|
|
342
|
-
| `--help` | no | — | Show help |
|
|
343
|
-
|
|
344
|
-
### Startup Behavior
|
|
345
|
-
|
|
346
|
-
- Smart Connections `.ajson` files are loaded into memory once at startup.
|
|
347
|
-
- The embedding model (`TaylorAI/bge-micro-v2`) is downloaded on first run and cached by `@xenova/transformers`.
|
|
348
|
-
- If the vault path is missing or Smart Connections data is absent, the server exits immediately with an error.
|
|
349
|
-
|
|
350
|
-
### AGENTS.md / CLAUDE.md snippet
|
|
351
|
-
|
|
352
|
-
Add this to your `AGENTS.md` or `CLAUDE.md` to help the AI assistant use the vault effectively:
|
|
353
|
-
|
|
354
|
-
```markdown
|
|
355
|
-
## Vault search
|
|
356
|
-
|
|
357
|
-
Use vault-aware tools when vault context matters.
|
|
358
|
-
Do not guess about note contents when the vault can be searched.
|
|
359
|
-
Follow the Neuro Vault MCP server instructions for routing between semantic search (`search_notes`, `get_similar_notes`) and operations (`read_note`, `create_note`, `edit_note`, `read_daily`, `append_daily`).
|
|
360
|
-
```
|
|
361
|
-
|
|
362
|
-
</details>
|
|
363
|
-
|
|
364
|
-
<details>
|
|
365
|
-
<summary><b>🩺 Troubleshooting</b></summary>
|
|
366
|
-
|
|
367
|
-
**"Smart Connections directory does not exist"** — make sure the Smart Connections plugin has run and generated embeddings. Open Obsidian, let Smart Connections finish indexing, then restart the MCP server.
|
|
368
|
-
|
|
369
|
-
**First startup is slow** — the embedding model (~40 MB) is downloading. Subsequent starts use the cached model.
|
|
370
|
-
|
|
371
|
-
**Search returns nothing** — try lowering the threshold: `threshold: 0.3`. Also check that `get_stats` shows a non-zero `totalNotes`.
|
|
372
|
-
|
|
373
|
-
**Vault operations fail with `CLI_NOT_FOUND` / `CLI_UNAVAILABLE`** — the `obsidian` CLI isn't on `PATH`, or Obsidian isn't running. Install the [Obsidian CLI](https://github.com/AlexMost/obsidian-cli), or pass `--obsidian-cli /absolute/path/to/obsidian`. Disable the module with `--no-operations` if you only want semantic search.
|
|
374
|
-
|
|
375
|
-
</details>
|
|
376
|
-
|
|
377
|
-
<details>
|
|
378
|
-
<summary><b>🛠 Development</b></summary>
|
|
379
|
-
|
|
380
|
-
```bash
|
|
381
|
-
npm run build # compile TypeScript to dist/
|
|
382
|
-
npm run test # run tests with vitest
|
|
383
|
-
npm run lint # ESLint
|
|
384
|
-
npm run format # check formatting with Prettier
|
|
385
|
-
npm run format:write # fix formatting
|
|
386
|
-
```
|
|
387
|
-
|
|
388
|
-
</details>
|
|
68
|
+
## 📚 Documentation
|
|
389
69
|
|
|
390
|
-
|
|
391
|
-
<summary><b>🚧 Limitations</b></summary>
|
|
70
|
+
User guide lives in [`docs/guide/`](./docs/guide/README.md):
|
|
392
71
|
|
|
393
|
-
-
|
|
394
|
-
-
|
|
395
|
-
-
|
|
396
|
-
-
|
|
397
|
-
-
|
|
398
|
-
- Operations tools require the Obsidian CLI and a running Obsidian instance — they fail gracefully per call when unavailable.
|
|
72
|
+
- [Installation](./docs/guide/installation.md)
|
|
73
|
+
- [Semantic Search](./docs/guide/semantic-search.md) — `search_notes`, `get_similar_notes`, `find_duplicates`, `get_stats`
|
|
74
|
+
- [Vault Operations](./docs/guide/vault-operations.md) — note CRUD, daily notes, properties, tags, structured queries (`query_notes`)
|
|
75
|
+
- [Routing Between Tools](./docs/guide/routing.md)
|
|
76
|
+
- [Configuration](./docs/guide/configuration.md) — CLI args, troubleshooting, limitations, **migration to 2.0**, development
|
|
399
77
|
|
|
400
|
-
|
|
78
|
+
Architecture / internals: [`docs/architecture/`](./docs/architecture/).
|
|
401
79
|
|
|
402
80
|
---
|
|
403
81
|
|
package/dist/cli.d.ts
CHANGED
|
@@ -67,11 +67,9 @@ interface SearchNotesInput {
|
|
|
67
67
|
mode?: SearchMode;
|
|
68
68
|
limit?: number;
|
|
69
69
|
threshold?: number;
|
|
70
|
-
expansion?: boolean;
|
|
71
|
-
expansion_limit?: number;
|
|
72
70
|
}
|
|
73
71
|
interface GetSimilarNotesInput {
|
|
74
|
-
|
|
72
|
+
path: string;
|
|
75
73
|
limit?: number;
|
|
76
74
|
threshold?: number;
|
|
77
75
|
}
|
|
@@ -126,14 +124,6 @@ type NoteIdentifier = {
|
|
|
126
124
|
kind: 'path';
|
|
127
125
|
value: string;
|
|
128
126
|
};
|
|
129
|
-
interface ReadNoteInput {
|
|
130
|
-
identifier: NoteIdentifier;
|
|
131
|
-
}
|
|
132
|
-
interface ReadNoteResult {
|
|
133
|
-
path: string;
|
|
134
|
-
frontmatter: Record<string, unknown> | null;
|
|
135
|
-
content: string;
|
|
136
|
-
}
|
|
137
127
|
interface CreateNoteInput {
|
|
138
128
|
name?: string;
|
|
139
129
|
path?: string;
|
|
@@ -185,17 +175,7 @@ interface TagListEntry {
|
|
|
185
175
|
name: string;
|
|
186
176
|
count: number;
|
|
187
177
|
}
|
|
188
|
-
interface GetTagInput {
|
|
189
|
-
name: string;
|
|
190
|
-
includeFiles?: boolean;
|
|
191
|
-
}
|
|
192
|
-
interface GetTagResult {
|
|
193
|
-
name: string;
|
|
194
|
-
count: number;
|
|
195
|
-
files?: string[];
|
|
196
|
-
}
|
|
197
178
|
interface VaultProvider {
|
|
198
|
-
readNote(input: ReadNoteInput): Promise<ReadNoteResult>;
|
|
199
179
|
createNote(input: CreateNoteInput): Promise<CreateNoteResult>;
|
|
200
180
|
editNote(input: EditNoteInput): Promise<void>;
|
|
201
181
|
readDaily(): Promise<DailyNoteResult>;
|
|
@@ -205,7 +185,6 @@ interface VaultProvider {
|
|
|
205
185
|
removeProperty(input: RemovePropertyInput): Promise<void>;
|
|
206
186
|
listProperties(): Promise<PropertyListEntry[]>;
|
|
207
187
|
listTags(): Promise<TagListEntry[]>;
|
|
208
|
-
getTag(input: GetTagInput): Promise<GetTagResult>;
|
|
209
188
|
}
|
|
210
189
|
|
|
211
190
|
type ExecFn = (binary: string, args: string[], options: {
|
|
@@ -221,8 +200,37 @@ interface ObsidianCLIProviderOptions {
|
|
|
221
200
|
exec?: ExecFn;
|
|
222
201
|
}
|
|
223
202
|
|
|
203
|
+
type ReadNotesField = 'frontmatter' | 'content';
|
|
204
|
+
interface ReadNotesItemSuccess {
|
|
205
|
+
path: string;
|
|
206
|
+
frontmatter: Record<string, unknown> | null;
|
|
207
|
+
content: string;
|
|
208
|
+
}
|
|
209
|
+
interface ReadNotesItemError {
|
|
210
|
+
path: string;
|
|
211
|
+
error: {
|
|
212
|
+
code: 'NOT_FOUND' | 'INVALID_ARGUMENT' | 'READ_FAILED';
|
|
213
|
+
message: string;
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
type ReadNotesItem = ReadNotesItemSuccess | ReadNotesItemError;
|
|
217
|
+
interface ReadNotesInput {
|
|
218
|
+
paths: string[];
|
|
219
|
+
fields: ReadNotesField[];
|
|
220
|
+
}
|
|
221
|
+
interface ScanOptions {
|
|
222
|
+
pathPrefix?: string;
|
|
223
|
+
}
|
|
224
|
+
interface VaultReader {
|
|
225
|
+
readNotes(input: ReadNotesInput): Promise<ReadNotesItem[]>;
|
|
226
|
+
scan(opts?: ScanOptions): Promise<string[]>;
|
|
227
|
+
}
|
|
228
|
+
|
|
224
229
|
interface OperationsModuleDeps {
|
|
225
230
|
vaultProviderFactory?: (opts: ObsidianCLIProviderOptions) => VaultProvider;
|
|
231
|
+
vaultReaderFactory?: (opts: {
|
|
232
|
+
vaultRoot: string;
|
|
233
|
+
}) => VaultReader;
|
|
226
234
|
}
|
|
227
235
|
|
|
228
236
|
type ToolServer = Pick<McpServer, 'registerTool' | 'connect'>;
|