neuro-vault-mcp 3.2.0 → 3.3.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 +21 -4
- package/dist/cli.js +28 -8
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -12,10 +12,11 @@
|
|
|
12
12
|
|
|
13
13
|
## ✨ Why Neuro Vault?
|
|
14
14
|
|
|
15
|
-
- 🧠 **Semantic search
|
|
16
|
-
- 🎯 **
|
|
17
|
-
-
|
|
18
|
-
- 🔎 **
|
|
15
|
+
- 🧠 **Semantic search that already knows your vault** — reuses [Smart Connections](https://github.com/brianpetro/obsidian-smart-connections) embeddings. No re-indexing, no API keys, no extra infrastructure.
|
|
16
|
+
- 🎯 **Quick or deep, your call** — fast direct lookups for "find that note", or exploratory mode with related-note expansion when the question is fuzzy.
|
|
17
|
+
- 🧭 **A real navigation toolkit for your agent** — instead of grepping files and opening notes one by one, your assistant walks the vault like a database: filter by tags and properties, batch-read metadata, discover the structure, jump to semantic neighbours.
|
|
18
|
+
- 🔎 **Ask structured questions in plain language** — _"active projects tagged #ai"_, _"todo tasks with a deadline this week"_, _"meeting notes from `Work/` newest first"_ — one call, ranked answer, no chains of reads.
|
|
19
|
+
- ✍️ **Read and write through Obsidian itself** — create, append, edit notes, manage frontmatter and daily notes via the [Obsidian CLI](https://github.com/AlexMost/obsidian-cli), so Smart Connections, sync, and other plugins stay in the loop.
|
|
19
20
|
- ⚡ **Zero infrastructure** — local stdio MCP server, in-memory index, no database, no background processes, no watchers.
|
|
20
21
|
- 🔌 **Drop-in for any MCP client** — Claude Code, Cursor, Windsurf — configuration is a single JSON block.
|
|
21
22
|
|
|
@@ -36,6 +37,22 @@ For module wiring and internal data flow, see [docs/architecture/module-structur
|
|
|
36
37
|
|
|
37
38
|
---
|
|
38
39
|
|
|
40
|
+
## 🧭 Your vault, but queryable
|
|
41
|
+
|
|
42
|
+
A plain-text vault is great for humans and rough on agents. Without the right tools, an assistant ends up listing folders, opening dozens of notes, and grepping inside each one just to answer a simple question.
|
|
43
|
+
|
|
44
|
+
Neuro Vault gives your assistant a way to **ask the vault directly** — by tag, by frontmatter property, by folder, by similarity. Things like:
|
|
45
|
+
|
|
46
|
+
> _"What are my active projects tagged #ai with a deadline this quarter?"_
|
|
47
|
+
> _"Show meeting notes from `Work/` from the last two weeks."_
|
|
48
|
+
> _"Find notes similar to this one I'm reading."_
|
|
49
|
+
|
|
50
|
+
One question, one answer. Your assistant stops being a file browser and starts being an actual second brain.
|
|
51
|
+
|
|
52
|
+
→ See [docs/guide/vault-operations.md](./docs/guide/vault-operations.md#query_notes) for the full query language and examples.
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
39
56
|
## ⚡ Quickstart
|
|
40
57
|
|
|
41
58
|
```bash
|
package/dist/cli.js
CHANGED
|
@@ -15368,10 +15368,18 @@ function normalizePath(raw) {
|
|
|
15368
15368
|
var VALID_FIELDS = ["frontmatter", "content"];
|
|
15369
15369
|
var DEFAULT_FIELDS = ["frontmatter", "content"];
|
|
15370
15370
|
function validateReadNotesInput(input) {
|
|
15371
|
-
|
|
15372
|
-
|
|
15371
|
+
let paths;
|
|
15372
|
+
if (typeof input.paths === "string") {
|
|
15373
|
+
if (input.paths === "") {
|
|
15374
|
+
throw invalidArgument("paths must not be empty", "paths");
|
|
15375
|
+
}
|
|
15376
|
+
paths = [input.paths];
|
|
15377
|
+
} else if (Array.isArray(input.paths)) {
|
|
15378
|
+
paths = input.paths;
|
|
15379
|
+
} else {
|
|
15380
|
+
throw invalidArgument("paths must be a string or an array of strings", "paths");
|
|
15373
15381
|
}
|
|
15374
|
-
if (
|
|
15382
|
+
if (paths.length < 1 || paths.length > 50) {
|
|
15375
15383
|
throw invalidArgument("paths must contain between 1 and 50 entries", "paths");
|
|
15376
15384
|
}
|
|
15377
15385
|
let fields;
|
|
@@ -15391,7 +15399,7 @@ function validateReadNotesInput(input) {
|
|
|
15391
15399
|
}
|
|
15392
15400
|
fields = input.fields;
|
|
15393
15401
|
}
|
|
15394
|
-
return { paths
|
|
15402
|
+
return { paths, fields };
|
|
15395
15403
|
}
|
|
15396
15404
|
|
|
15397
15405
|
// src/modules/operations/tools/append-daily.ts
|
|
@@ -15901,7 +15909,7 @@ function buildReadDailyTool(deps) {
|
|
|
15901
15909
|
// src/modules/operations/tools/read-notes.ts
|
|
15902
15910
|
var readNotesFieldSchema = external_exports.enum(["frontmatter", "content"]);
|
|
15903
15911
|
var inputSchema12 = external_exports.object({
|
|
15904
|
-
paths: external_exports.array(external_exports.string()).min(1).max(50),
|
|
15912
|
+
paths: external_exports.union([external_exports.string().min(1), external_exports.array(external_exports.string()).min(1).max(50)]),
|
|
15905
15913
|
fields: external_exports.array(readNotesFieldSchema).min(1).optional()
|
|
15906
15914
|
});
|
|
15907
15915
|
function buildReadNotesTool(deps) {
|
|
@@ -15909,7 +15917,7 @@ function buildReadNotesTool(deps) {
|
|
|
15909
15917
|
return {
|
|
15910
15918
|
name: "read_notes",
|
|
15911
15919
|
title: "Read Notes",
|
|
15912
|
-
description: "Read
|
|
15920
|
+
description: "Read one or more notes in one call. `paths` is a vault-relative POSIX path string or an array of 1\u201350 such paths; duplicates are de-duplicated and results returned in input order. `fields` projects which parts of each note to return \u2014 choose from `frontmatter` and `content`; default `['frontmatter','content']`. One missing or unreadable path does not fail the others \u2014 per-item errors come back inline. A single MCP roundtrip with parallel disk reads. Reads are direct from disk and do not require Obsidian to be running.",
|
|
15913
15921
|
inputSchema: inputSchema12,
|
|
15914
15922
|
handler: async (input) => {
|
|
15915
15923
|
const { paths, fields } = validateReadNotesInput(input);
|
|
@@ -16067,12 +16075,24 @@ var require2 = createRequire(import.meta.url);
|
|
|
16067
16075
|
var { name: SERVER_NAME, version: SERVER_VERSION } = require2("../package.json");
|
|
16068
16076
|
var SERVER_INSTRUCTIONS = `This server provides two capability sets for an Obsidian vault: semantic search (when enabled) and direct vault operations (when enabled). Use the right one based on the user's intent.
|
|
16069
16077
|
|
|
16078
|
+
## Role: a second brain alongside the project
|
|
16079
|
+
|
|
16080
|
+
This vault is the user's personal knowledge base \u2014 planning notes, brainstorm artifacts, decisions, reflections, drafts \u2014 that often predates and outlives any single project they bring to you. Before brainstorming new directions, drafting retrospectives, or answering "why did we decide X", check the vault first; the answer is often there but lives nowhere else.
|
|
16081
|
+
|
|
16082
|
+
You don't know on your own how the user scopes notes for the current project \u2014 the same vault is typically connected to many, and different users organise differently (a tag, a folder, a frontmatter property like \`project\`, or a combination). The user's project-level instructions should name that scope and tell you how to query for it. If they don't, you have three ways forward, in order of preference:
|
|
16083
|
+
|
|
16084
|
+
1. **Probe the vault structure** via \`list_tags\`, \`list_properties\`, and exploratory \`query_notes\` calls \u2014 common conventions (a \`project\` frontmatter field, a \`Projects/\` folder, a recurring tag) usually surface immediately and tell you how this vault is organised.
|
|
16085
|
+
2. **Use \`search_notes\`** with the project name and key concepts as a fuzzy entry point \u2014 relevant material may exist under unrelated names.
|
|
16086
|
+
3. **Ask the user**, and the first time they save project-specific notes propose a scoping scheme so future sessions have an explicit entry point.
|
|
16087
|
+
|
|
16088
|
+
When operating directly inside the vault itself (not from an external project that connects to it), you have both filesystem access and MCP access to the same files. Prefer MCP tools \u2014 \`query_notes\` for structured filters, \`search_notes\` for semantic recall \u2014 over manually scanning files; they exist so frontmatter and similarity queries don't require reading every note.
|
|
16089
|
+
|
|
16070
16090
|
## When to use vault operations
|
|
16071
16091
|
|
|
16072
16092
|
### Notes (body)
|
|
16073
16093
|
|
|
16074
16094
|
Use \`read_notes\`, \`create_note\`, \`edit_note\`, \`read_daily\`, \`append_daily\` when the user asks to:
|
|
16075
|
-
- Read one or more notes by path (\`read_notes\` \u2014 accepts an array of 1\u201350
|
|
16095
|
+
- Read one or more notes by path (\`read_notes\` \u2014 accepts a single vault-relative POSIX path string or an array of 1\u201350 such paths; prefer this over multiple sequential reads)
|
|
16076
16096
|
- Create a new note, task, or idea (\`create_note\`)
|
|
16077
16097
|
- Add content to an existing note (\`edit_note\`)
|
|
16078
16098
|
- Read or update today's daily note (\`read_daily\` / \`append_daily\`)
|
|
@@ -16124,7 +16144,7 @@ Use \`search_notes\` when the user is recalling a topic fuzzily, asking a concep
|
|
|
16124
16144
|
|
|
16125
16145
|
## Routing between operations and semantic
|
|
16126
16146
|
|
|
16127
|
-
If the user gives an exact anchor (note path, daily note, tag, frontmatter field), prefer operations tools. If the user is recalling fuzzily or asking a conceptual question, prefer \`search_notes\`. After semantic search finds a relevant note, you can read it with \`read_notes\` (passing the path
|
|
16147
|
+
If the user gives an exact anchor (note path, daily note, tag, frontmatter field), prefer operations tools. If the user is recalling fuzzily or asking a conceptual question, prefer \`search_notes\`. After semantic search finds a relevant note, you can read it with \`read_notes\` (passing the path as a single string, or batching with sibling paths in an array) to see the details.
|
|
16128
16148
|
|
|
16129
16149
|
For tag-driven questions ("which notes are tagged X?", "show me everything in #ai") use \`query_notes\` with \`{ filter: { tags: '<name>' } }\`, not \`search_notes\` \u2014 the answer is exact, not fuzzy.
|
|
16130
16150
|
`;
|