neuro-vault-mcp 7.0.0 → 8.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 +2 -2
- package/dist/cli.js +72 -9
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> 🧠💾 **Make your personal vault usable by agents.** Low-token retrieval, explicit provenance, and safe writes for your Obsidian notes — in Claude Code, Cursor, Windsurf, and any MCP client.
|
|
4
4
|
|
|
5
|
-
https://github.com/user-attachments/assets/25c1bafb-7b90-43ac-aa50-50e85705fb5b
|
|
5
|
+
[https://github.com/user-attachments/assets/25c1bafb-7b90-43ac-aa50-50e85705fb5b](https://github.com/user-attachments/assets/5ac86cd7-2d67-420d-b940-dba4ae1a2ccb)
|
|
6
6
|
|
|
7
7
|
[](https://www.npmjs.com/package/neuro-vault-mcp)
|
|
8
8
|
[](https://nodejs.org)
|
|
@@ -140,7 +140,7 @@ Two vaults cannot share the same directory basename — the basename doubles as
|
|
|
140
140
|
With multiple vaults registered:
|
|
141
141
|
|
|
142
142
|
- **Every tool** accepts an optional `vault: "<name>"` parameter to target a specific vault.
|
|
143
|
-
- **`search_notes`, `query_notes`, and `
|
|
143
|
+
- **`search_notes`, `query_notes`, `get_vault_overview`, `list_tags`, and `list_properties`** fan out across all registered vaults when `vault` is omitted. The response shape switches to `results_by_vault: [...]` (one entry per vault) plus `skipped_vaults: [...]` for any vault the tool could not reach and `failed_vaults: [...]` for per-vault runtime errors (`{ vault, error: { code, message, details? } }`). A single failed vault does not abort the whole call.
|
|
144
144
|
- **All other tools** (writes, reads of specific paths, single-vault diagnostics) require an explicit `vault` in multi-vault mode. Omitting it returns `VAULT_REQUIRED`.
|
|
145
145
|
- **Semantic fan-out** silently skips vaults whose Smart Connections `.smart-env/multi/` index is unavailable. Targeting such a vault explicitly with `vault: "<name>"` returns `SEMANTIC_INDEX_NOT_FOUND`.
|
|
146
146
|
|
package/dist/cli.js
CHANGED
|
@@ -14228,6 +14228,16 @@ var ToolHandlerError = class extends Error {
|
|
|
14228
14228
|
}
|
|
14229
14229
|
}
|
|
14230
14230
|
};
|
|
14231
|
+
var FATAL_TOOL_ERROR_CODES = /* @__PURE__ */ new Set([
|
|
14232
|
+
"INVALID_ARGUMENT",
|
|
14233
|
+
"INVALID_PARAMS",
|
|
14234
|
+
"INVALID_FILTER",
|
|
14235
|
+
"VAULT_REQUIRED",
|
|
14236
|
+
"VAULT_NOT_FOUND"
|
|
14237
|
+
]);
|
|
14238
|
+
function isFatalToolError(error48) {
|
|
14239
|
+
return error48 instanceof ToolHandlerError && FATAL_TOOL_ERROR_CODES.has(error48.code);
|
|
14240
|
+
}
|
|
14231
14241
|
function isPlainRecord(value) {
|
|
14232
14242
|
return typeof value === "object" && value !== null && !Array.isArray(value) && Object.getPrototypeOf(value) === Object.prototype;
|
|
14233
14243
|
}
|
|
@@ -15715,20 +15725,73 @@ function buildGetStatsTool(deps) {
|
|
|
15715
15725
|
}
|
|
15716
15726
|
|
|
15717
15727
|
// src/lib/fan-out.ts
|
|
15728
|
+
function findFatalRejection(settled) {
|
|
15729
|
+
for (const outcome of settled) {
|
|
15730
|
+
if (outcome.status === "rejected" && isFatalToolError(outcome.reason)) {
|
|
15731
|
+
return outcome.reason;
|
|
15732
|
+
}
|
|
15733
|
+
}
|
|
15734
|
+
return void 0;
|
|
15735
|
+
}
|
|
15736
|
+
function mapRejectionToFailedVault(vault, reason) {
|
|
15737
|
+
if (reason instanceof ToolHandlerError) {
|
|
15738
|
+
return {
|
|
15739
|
+
vault,
|
|
15740
|
+
error: {
|
|
15741
|
+
code: reason.code,
|
|
15742
|
+
message: reason.message,
|
|
15743
|
+
...reason.details ? { details: reason.details } : {}
|
|
15744
|
+
}
|
|
15745
|
+
};
|
|
15746
|
+
}
|
|
15747
|
+
return {
|
|
15748
|
+
vault,
|
|
15749
|
+
error: {
|
|
15750
|
+
code: "INTERNAL_ERROR",
|
|
15751
|
+
message: reason instanceof Error ? reason.message : String(reason)
|
|
15752
|
+
}
|
|
15753
|
+
};
|
|
15754
|
+
}
|
|
15718
15755
|
async function runFanOut(registry2, fn) {
|
|
15719
15756
|
const entries = registry2.list();
|
|
15720
|
-
const
|
|
15721
|
-
|
|
15722
|
-
)
|
|
15723
|
-
|
|
15757
|
+
const settled = await Promise.allSettled(entries.map((entry) => fn(entry)));
|
|
15758
|
+
const fatalError = findFatalRejection(settled);
|
|
15759
|
+
if (fatalError) {
|
|
15760
|
+
throw fatalError;
|
|
15761
|
+
}
|
|
15762
|
+
const results = [];
|
|
15763
|
+
const failed = [];
|
|
15764
|
+
for (let i = 0; i < settled.length; i++) {
|
|
15765
|
+
const outcome = settled[i];
|
|
15766
|
+
const vault = entries[i].name;
|
|
15767
|
+
if (outcome.status === "fulfilled") {
|
|
15768
|
+
results.push({ vault, ...outcome.value });
|
|
15769
|
+
} else {
|
|
15770
|
+
failed.push(mapRejectionToFailedVault(vault, outcome.reason));
|
|
15771
|
+
}
|
|
15772
|
+
}
|
|
15773
|
+
return { results_by_vault: results, skipped_vaults: [], failed_vaults: failed };
|
|
15724
15774
|
}
|
|
15725
15775
|
async function runSemanticFanOut(registry2, fn) {
|
|
15726
15776
|
const eligible = registry2.semanticAvailableEntries();
|
|
15727
15777
|
const skipped = registry2.list().filter((e) => !e.semanticAvailable).map((e) => ({ vault: e.name, reason: "SEMANTIC_INDEX_NOT_FOUND" }));
|
|
15728
|
-
const
|
|
15729
|
-
|
|
15730
|
-
)
|
|
15731
|
-
|
|
15778
|
+
const settled = await Promise.allSettled(eligible.map((entry) => fn(entry)));
|
|
15779
|
+
const fatalError = findFatalRejection(settled);
|
|
15780
|
+
if (fatalError) {
|
|
15781
|
+
throw fatalError;
|
|
15782
|
+
}
|
|
15783
|
+
const results = [];
|
|
15784
|
+
const failed = [];
|
|
15785
|
+
for (let i = 0; i < settled.length; i++) {
|
|
15786
|
+
const outcome = settled[i];
|
|
15787
|
+
const vault = eligible[i].name;
|
|
15788
|
+
if (outcome.status === "fulfilled") {
|
|
15789
|
+
results.push({ vault, ...outcome.value });
|
|
15790
|
+
} else {
|
|
15791
|
+
failed.push(mapRejectionToFailedVault(vault, outcome.reason));
|
|
15792
|
+
}
|
|
15793
|
+
}
|
|
15794
|
+
return { results_by_vault: results, skipped_vaults: skipped, failed_vaults: failed };
|
|
15732
15795
|
}
|
|
15733
15796
|
|
|
15734
15797
|
// src/modules/semantic/retrieval-policy.ts
|
|
@@ -17473,7 +17536,7 @@ async function buildServerInstructions(registry2) {
|
|
|
17473
17536
|
|
|
17474
17537
|
## Multi-vault mode
|
|
17475
17538
|
|
|
17476
|
-
This server is registered with multiple vaults: ${names}. Every tool accepts an optional \`vault\` parameter. For broad recall, \`search_notes\`, \`query_notes\`, and \`
|
|
17539
|
+
This server is registered with multiple vaults: ${names}. Every tool accepts an optional \`vault\` parameter. For broad recall, \`search_notes\`, \`query_notes\`, \`get_vault_overview\`, \`list_tags\`, and \`list_properties\` fan out across all vaults when \`vault\` is omitted; other tools (reads of specific paths, writes, single-vault diagnostics) require an explicit \`vault\` \u2014 omitting it returns \`VAULT_REQUIRED\`. Fan-out responses include \`results_by_vault\`, \`skipped_vaults\` (vaults pre-filtered out, e.g. missing semantic index), and \`failed_vaults\` (per-vault runtime errors with \`{ code, message, details? }\`) \u2014 a single failed vault does not abort the whole call. Path-shaped parameters (\`path\`, \`paths\`, \`path_prefix\`) remain vault-relative; vault identity is always carried by \`vault\`.`;
|
|
17477
17540
|
}
|
|
17478
17541
|
for (const entry of registry2.list()) {
|
|
17479
17542
|
const extra = await readExternalAgentInstructions(entry.path);
|