obsidian-mcp-server 3.6.0 → 3.7.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/AGENTS.md +40 -27
- package/CLAUDE.md +40 -27
- package/Dockerfile +90 -47
- package/README.md +130 -151
- package/changelog/3.6.x/3.6.1.md +29 -0
- package/changelog/3.7.x/3.7.0.md +34 -0
- package/dist/config/server-config.d.ts +1 -0
- package/dist/config/server-config.d.ts.map +1 -1
- package/dist/config/server-config.js +4 -0
- package/dist/config/server-config.js.map +1 -1
- package/dist/index.js +30 -10
- package/dist/index.js.map +1 -1
- package/dist/mcp-server/resources/definitions/obsidian-tags.resource.d.ts +7 -5
- package/dist/mcp-server/resources/definitions/obsidian-tags.resource.d.ts.map +1 -1
- package/dist/mcp-server/resources/definitions/obsidian-tags.resource.js +12 -8
- package/dist/mcp-server/resources/definitions/obsidian-tags.resource.js.map +1 -1
- package/dist/mcp-server/tools/definitions/_shared/suggest-paths.d.ts +32 -10
- package/dist/mcp-server/tools/definitions/_shared/suggest-paths.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/_shared/suggest-paths.js +30 -8
- package/dist/mcp-server/tools/definitions/_shared/suggest-paths.js.map +1 -1
- package/dist/mcp-server/tools/definitions/index.d.ts +230 -294
- package/dist/mcp-server/tools/definitions/index.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/index.js +9 -3
- package/dist/mcp-server/tools/definitions/index.js.map +1 -1
- package/dist/mcp-server/tools/definitions/obsidian-append-to-note.tool.js +1 -1
- package/dist/mcp-server/tools/definitions/obsidian-append-to-note.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/obsidian-delete-note.tool.d.ts +108 -10
- package/dist/mcp-server/tools/definitions/obsidian-delete-note.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/obsidian-delete-note.tool.js +254 -133
- package/dist/mcp-server/tools/definitions/obsidian-delete-note.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/obsidian-get-note.tool.d.ts +1 -0
- package/dist/mcp-server/tools/definitions/obsidian-get-note.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/obsidian-get-note.tool.js +62 -21
- package/dist/mcp-server/tools/definitions/obsidian-get-note.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/obsidian-list-commands.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/obsidian-list-commands.tool.js +1 -2
- package/dist/mcp-server/tools/definitions/obsidian-list-commands.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/obsidian-list-notes.tool.d.ts +6 -1
- package/dist/mcp-server/tools/definitions/obsidian-list-notes.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/obsidian-list-notes.tool.js +9 -12
- package/dist/mcp-server/tools/definitions/obsidian-list-notes.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/obsidian-list-tags.tool.d.ts +7 -5
- package/dist/mcp-server/tools/definitions/obsidian-list-tags.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/obsidian-list-tags.tool.js +14 -9
- package/dist/mcp-server/tools/definitions/obsidian-list-tags.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/obsidian-manage-frontmatter.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/obsidian-manage-frontmatter.tool.js +1 -2
- package/dist/mcp-server/tools/definitions/obsidian-manage-frontmatter.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/obsidian-manage-tags.tool.js +2 -2
- package/dist/mcp-server/tools/definitions/obsidian-manage-tags.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/obsidian-open-in-ui.tool.d.ts +4 -1
- package/dist/mcp-server/tools/definitions/obsidian-open-in-ui.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/obsidian-open-in-ui.tool.js +15 -4
- package/dist/mcp-server/tools/definitions/obsidian-open-in-ui.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/obsidian-replace-in-note.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/obsidian-replace-in-note.tool.js +2 -3
- package/dist/mcp-server/tools/definitions/obsidian-replace-in-note.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/obsidian-search-notes.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/obsidian-search-notes.tool.js +2 -5
- package/dist/mcp-server/tools/definitions/obsidian-search-notes.tool.js.map +1 -1
- package/dist/services/obsidian/obsidian-service.d.ts +7 -0
- package/dist/services/obsidian/obsidian-service.d.ts.map +1 -1
- package/dist/services/obsidian/obsidian-service.js +72 -35
- package/dist/services/obsidian/obsidian-service.js.map +1 -1
- package/dist/services/obsidian/patch-instruction.d.ts +20 -1
- package/dist/services/obsidian/patch-instruction.d.ts.map +1 -1
- package/dist/services/obsidian/patch-instruction.js +30 -0
- package/dist/services/obsidian/patch-instruction.js.map +1 -1
- package/dist/services/obsidian/path-policy.d.ts +23 -1
- package/dist/services/obsidian/path-policy.d.ts.map +1 -1
- package/dist/services/obsidian/path-policy.js +45 -3
- package/dist/services/obsidian/path-policy.js.map +1 -1
- package/dist/services/obsidian/section-extractor.d.ts +24 -0
- package/dist/services/obsidian/section-extractor.d.ts.map +1 -1
- package/dist/services/obsidian/section-extractor.js +37 -0
- package/dist/services/obsidian/section-extractor.js.map +1 -1
- package/manifest.json +9 -1
- package/package.json +13 -10
- package/server.json +24 -24
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
summary: "obsidian_delete_note now deletes on the first call unless OBSIDIAN_DELETE_ELICITATION=true, and obsidian_list_tags and obsidian_list_notes no longer expose tag names or folder and note names outside OBSIDIAN_READ_PATHS."
|
|
3
|
+
breaking: false
|
|
4
|
+
security: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# 3.7.0 — 2026-10-05
|
|
8
|
+
|
|
9
|
+
## Added
|
|
10
|
+
|
|
11
|
+
- **`OBSIDIAN_DELETE_ELICITATION`** (default `false`) turns the `obsidian_delete_note` confirmation round on ([#153](https://github.com/cyanheads/obsidian-mcp-server/issues/153)). Declared in `server.json`, `manifest.json`, and `.env.example`; the startup log reports the delete mode.
|
|
12
|
+
- **`requestedPath` and a `notice` on `obsidian_get_note` and `obsidian_open_in_ui`** when a path with no exact match reads or opens its single case-insensitive match instead ([#149](https://github.com/cyanheads/obsidian-mcp-server/issues/149)). Write and delete tools still match the exact path.
|
|
13
|
+
|
|
14
|
+
## Changed
|
|
15
|
+
|
|
16
|
+
- **`obsidian_delete_note` now deletes on the first call, with no confirmation round** ([#153](https://github.com/cyanheads/obsidian-mcp-server/issues/153)). Set `OBSIDIAN_DELETE_ELICITATION=true` to keep the confirmation; the stateful-session requirement over HTTP then applies only in that mode, and not under `OBSIDIAN_READ_ONLY=true` (which disables the tool), so `MCP_SESSION_MODE=stateless` starts otherwise. `OBSIDIAN_WRITE_PATHS` and `OBSIDIAN_READ_ONLY` bound what a delete reaches.
|
|
17
|
+
- **`obsidian_delete_note` checks write scope before it reads the note or builds a prompt**, so a readable note outside `OBSIDIAN_WRITE_PATHS` fails `path_forbidden` without asking ([#153](https://github.com/cyanheads/obsidian-mcp-server/issues/153)).
|
|
18
|
+
- **`obsidian_search_notes` backlink recipe** also matches `[[Target Note\|Alias]]`, the table-safe alias form.
|
|
19
|
+
|
|
20
|
+
## Fixed
|
|
21
|
+
|
|
22
|
+
- **`obsidian_get_note` `includeLinks` returns the target Obsidian resolves for `[[Note\|Alias]]`**, with no trailing backslash ([#126](https://github.com/cyanheads/obsidian-mcp-server/issues/126)). Wikilink and markdown-link scanning now follows Obsidian's own shapes (`[[Note|see [1]]]`, `Note(1).md`) and stays linear on unclosed brackets.
|
|
23
|
+
- **Heading writes on Local REST API v4.x keep their line breaks** ([#146](https://github.com/cyanheads/obsidian-mcp-server/issues/146)). An append, prepend, or replace no longer runs into the next heading or the line before. CRLF notes still land mid-line, a plugin limitation.
|
|
24
|
+
- **`obsidian_delete_note` no longer deletes a differently-cased note on a case-insensitive filesystem.** A wrong-case path fails `note_missing`, listing near matches in `suggestions`, and sends no DELETE.
|
|
25
|
+
|
|
26
|
+
## Security
|
|
27
|
+
|
|
28
|
+
- **`obsidian_list_tags` and `obsidian://tags` list only tags from readable notes when `OBSIDIAN_READ_PATHS` is set** ([#154](https://github.com/cyanheads/obsidian-mcp-server/issues/154)). Before, tag names and vault-wide counts from out-of-scope notes were returned. `count` is now the number of readable notes carrying the tag or a nested tag; write paths and read-only alone leave listings vault-wide.
|
|
29
|
+
- **`obsidian_list_notes` returns only readable entries and the folders leading to the read scope** ([#155](https://github.com/cyanheads/obsidian-mcp-server/issues/155)). Before, out-of-scope folder and root-level note names were listed. A nested scope can now be browsed to from the root, and `truncated` marks only depth-limited folders.
|
|
30
|
+
|
|
31
|
+
## Dependencies
|
|
32
|
+
|
|
33
|
+
- dev: `ignore` ^7.0.11 → ^7.0.12
|
|
34
|
+
- `marked` stays pinned at `17.0.6` (the Local REST API's markdown-patch engine depends on marked 17; marked 18 parses some blocks differently, which would split section targeting from the plugin's)
|
|
@@ -13,6 +13,7 @@ declare const ServerConfigSchema: z.ZodObject<{
|
|
|
13
13
|
readPaths: z.ZodPreprocess<z.ZodPipe<z.ZodOptional<z.ZodArray<z.ZodString>>, z.ZodTransform<string[] | undefined, string[] | undefined>>, unknown>;
|
|
14
14
|
writePaths: z.ZodPreprocess<z.ZodPipe<z.ZodOptional<z.ZodArray<z.ZodString>>, z.ZodTransform<string[] | undefined, string[] | undefined>>, unknown>;
|
|
15
15
|
readOnly: z.ZodDefault<z.ZodUnion<readonly [z.ZodBoolean, z.ZodCodec<z.ZodString, z.ZodBoolean>]>>;
|
|
16
|
+
deleteElicitation: z.ZodDefault<z.ZodUnion<readonly [z.ZodBoolean, z.ZodCodec<z.ZodString, z.ZodBoolean>]>>;
|
|
16
17
|
omnisearchUrl: z.ZodOptional<z.ZodString>;
|
|
17
18
|
}, z.core.$strip>;
|
|
18
19
|
export type ServerConfig = z.infer<typeof ServerConfigSchema>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server-config.d.ts","sourceRoot":"","sources":["../../src/config/server-config.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAgF3C,QAAA,MAAM,kBAAkB
|
|
1
|
+
{"version":3,"file":"server-config.d.ts","sourceRoot":"","sources":["../../src/config/server-config.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAgF3C,QAAA,MAAM,kBAAkB;;;;;;;;;;;iBA4DtB,CAAC;AAEH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAI9D,wBAAgB,eAAe,IAAI,YAAY,CAc9C;AAED,iEAAiE;AACjE,wBAAgB,iBAAiB,IAAI,IAAI,CAExC"}
|
|
@@ -116,6 +116,9 @@ const ServerConfigSchema = z.object({
|
|
|
116
116
|
readOnly: envBoolean
|
|
117
117
|
.default(false)
|
|
118
118
|
.describe('Global kill switch. When true, denies every write regardless of OBSIDIAN_WRITE_PATHS, and suppresses the OBSIDIAN_ENABLE_COMMANDS pair (commands can mutate). Defaults to false.'),
|
|
119
|
+
deleteElicitation: envBoolean
|
|
120
|
+
.default(false)
|
|
121
|
+
.describe('When true, `obsidian_delete_note` asks the user to confirm each delete through an elicitation round, and HTTP startup requires a stateful session (MCP_SESSION_MODE=stateless is refused) unless OBSIDIAN_READ_ONLY=true, which disables the tool. Defaults to false: the delete runs on the first call, bounded by OBSIDIAN_WRITE_PATHS and OBSIDIAN_READ_ONLY.'),
|
|
119
122
|
omnisearchUrl: z
|
|
120
123
|
.string()
|
|
121
124
|
.url()
|
|
@@ -133,6 +136,7 @@ export function getServerConfig() {
|
|
|
133
136
|
readPaths: 'OBSIDIAN_READ_PATHS',
|
|
134
137
|
writePaths: 'OBSIDIAN_WRITE_PATHS',
|
|
135
138
|
readOnly: 'OBSIDIAN_READ_ONLY',
|
|
139
|
+
deleteElicitation: 'OBSIDIAN_DELETE_ELICITATION',
|
|
136
140
|
omnisearchUrl: 'OBSIDIAN_OMNISEARCH_URL',
|
|
137
141
|
});
|
|
138
142
|
return _config;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server-config.js","sourceRoot":"","sources":["../../src/config/server-config.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"server-config.js","sourceRoot":"","sources":["../../src/config/server-config.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -12,7 +12,7 @@ import { requestContextService } from '@cyanheads/mcp-ts-core/utils';
|
|
|
12
12
|
import { getServerConfig } from './config/server-config.js';
|
|
13
13
|
import { allPromptDefinitions } from './mcp-server/prompts/definitions/index.js';
|
|
14
14
|
import { allResourceDefinitions } from './mcp-server/resources/definitions/index.js';
|
|
15
|
-
import { buildSearchNotesTool, commandToolDefinitions, readToolDefinitions, writeToolDefinitions, } from './mcp-server/tools/definitions/index.js';
|
|
15
|
+
import { buildDeleteNoteTool, buildSearchNotesTool, commandToolDefinitions, readToolDefinitions, writeToolDefinitions, } from './mcp-server/tools/definitions/index.js';
|
|
16
16
|
import { getObsidianService, initObsidianService } from './services/obsidian/obsidian-service.js';
|
|
17
17
|
import { PathPolicy } from './services/obsidian/path-policy.js';
|
|
18
18
|
const config = getServerConfig();
|
|
@@ -53,12 +53,22 @@ function buildInstructions() {
|
|
|
53
53
|
}
|
|
54
54
|
return sections.join('\n\n');
|
|
55
55
|
}
|
|
56
|
+
const writeToolSet = [
|
|
57
|
+
...writeToolDefinitions,
|
|
58
|
+
buildDeleteNoteTool({ elicitation: config.deleteElicitation }),
|
|
59
|
+
];
|
|
60
|
+
/**
|
|
61
|
+
* The delete confirmation can run only when `obsidian_delete_note` is
|
|
62
|
+
* registered: `OBSIDIAN_READ_ONLY=true` disables it below, so the gate — and
|
|
63
|
+
* the session it needs — exists only with elicitation on and writes allowed.
|
|
64
|
+
*/
|
|
65
|
+
const deleteGateActive = config.deleteElicitation && !config.readOnly;
|
|
56
66
|
const writeTools = config.readOnly
|
|
57
|
-
?
|
|
67
|
+
? writeToolSet.map((def) => disabledTool(def, {
|
|
58
68
|
reason: 'Disabled by OBSIDIAN_READ_ONLY=true.',
|
|
59
69
|
hint: 'Unset OBSIDIAN_READ_ONLY (or set it to false) to enable write tools.',
|
|
60
70
|
}))
|
|
61
|
-
:
|
|
71
|
+
: writeToolSet;
|
|
62
72
|
const commandTools = config.enableCommands && !config.readOnly
|
|
63
73
|
? commandToolDefinitions
|
|
64
74
|
: commandToolDefinitions.map((def) => disabledTool(def, {
|
|
@@ -78,27 +88,37 @@ const { services } = await createApp({
|
|
|
78
88
|
prompts: allPromptDefinitions,
|
|
79
89
|
instructions: buildInstructions(),
|
|
80
90
|
/**
|
|
91
|
+
* With `OBSIDIAN_DELETE_ELICITATION=true` (and writes allowed),
|
|
81
92
|
* `obsidian_delete_note` confirms through `ctx.requestInput`, which a
|
|
82
|
-
* 2025-era HTTP client can only answer on a stateful session
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
* `
|
|
93
|
+
* 2025-era HTTP client can only answer on a stateful session — under
|
|
94
|
+
* stateless HTTP the tool would be unusable for them. Required, not just
|
|
95
|
+
* defaulted, in that mode: over HTTP, a resolved `stateless` mode (an
|
|
96
|
+
* explicit `MCP_SESSION_MODE=stateless`) fails startup with a
|
|
97
|
+
* `ConfigurationError`. With the confirmation off, or the tool disabled by
|
|
98
|
+
* `OBSIDIAN_READ_ONLY=true`, nothing needs a session and `stateful` is only
|
|
99
|
+
* the default. stdio is never refused; `MCP_SESSION_MODE` has no effect there.
|
|
86
100
|
*/
|
|
87
|
-
sessionMode:
|
|
101
|
+
sessionMode: deleteGateActive
|
|
102
|
+
? { default: 'stateful', require: 'stateful' }
|
|
103
|
+
: { default: 'stateful' },
|
|
88
104
|
teardown: () => obsidian.close(),
|
|
89
105
|
});
|
|
90
106
|
/**
|
|
91
107
|
* Startup banner — emitted after createApp() returns so the framework's
|
|
92
108
|
* `logger.initialize()` has run; calls inside `setup()` happen pre-init and
|
|
93
109
|
* are dropped. Operators check this against their config to verify the active
|
|
94
|
-
* path policy
|
|
95
|
-
*
|
|
110
|
+
* path policy and whether `obsidian_delete_note` asks before deleting
|
|
111
|
+
* (`deleteElicitation`, false under read-only like `enableCommands`, since
|
|
112
|
+
* the tool is disabled there). The active scope on `path_forbidden` errors echoes
|
|
113
|
+
* the same data so the LLM (or operator) can self-correct without scrolling
|
|
114
|
+
* the log.
|
|
96
115
|
*/
|
|
97
116
|
const bannerCtx = requestContextService.createRequestContext({
|
|
98
117
|
operation: 'startup',
|
|
99
118
|
additionalContext: {
|
|
100
119
|
...policy.describe(),
|
|
101
120
|
enableCommands: config.enableCommands && !config.readOnly,
|
|
121
|
+
deleteElicitation: deleteGateActive,
|
|
102
122
|
omnisearchUrl: obsidian.omnisearchUrl,
|
|
103
123
|
omnisearchReachable,
|
|
104
124
|
},
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;;GAOG;AAEH,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,sBAAsB,EAAE,MAAM,6CAA6C,CAAC;AACrF,OAAO,EACL,oBAAoB,EACpB,sBAAsB,EACtB,mBAAmB,EACnB,oBAAoB,GACrB,MAAM,yCAAyC,CAAC;AACjD,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,yCAAyC,CAAC;AAClG,OAAO,EAAE,UAAU,EAAE,MAAM,oCAAoC,CAAC;AAEhE,MAAM,MAAM,GAAG,eAAe,EAAE,CAAC;AACjC,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC;AAEtC;;;;;GAKG;AACH,mBAAmB,CAAC,MAAM,CAAC,CAAC;AAC5B,MAAM,QAAQ,GAAG,kBAAkB,EAAE,CAAC;AACtC,MAAM,mBAAmB,GAAG,MAAM,QAAQ,CAAC,eAAe,EAAE,CAAC;AAE7D,MAAM,eAAe,GAAG,oBAAoB,CAAC,EAAE,mBAAmB,EAAE,CAAC,CAAC;AAEtE;;;;;GAKG;AACH,SAAS,iBAAiB;IACxB,MAAM,QAAQ,GAAa;QACzB,qXAAqX;KACtX,CAAC;IACF,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;QACpB,QAAQ,CAAC,IAAI,CACX,oQAAoQ,CACrQ,CAAC;IACJ,CAAC;SAAM,IAAI,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC;QAClC,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;QACpD,MAAM,MAAM,GAAG,CAAC,KAAiC,EAAU,EAAE,CAC3D,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5E,QAAQ,CAAC,IAAI,CACX,4CAA4C,MAAM,CAAC,SAAS,CAAC,eAAe,MAAM,CAAC,UAAU,CAAC,qHAAqH,CACpN,CAAC;IACJ,CAAC;IACD,IAAI,MAAM,CAAC,cAAc,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;QAC9C,QAAQ,CAAC,IAAI,CACX,gNAAgN,CACjN,CAAC;IACJ,CAAC;IACD,IAAI,mBAAmB,EAAE,CAAC;QACxB,QAAQ,CAAC,IAAI,CACX,mQAAmQ,CACpQ,CAAC;IACJ,CAAC;IACD,OAAO,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,GAAG,MAAM,CAAC,QAAQ;IAChC,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,11 +2,13 @@
|
|
|
2
2
|
* @fileoverview obsidian://tags — vault tag listing with usage counts, for
|
|
3
3
|
* clients that prefer attaching resources.
|
|
4
4
|
*
|
|
5
|
-
* Not a mirror of `obsidian_list_tags`: this is a snapshot of
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
5
|
+
* Not a mirror of `obsidian_list_tags`: this is a snapshot of
|
|
6
|
+
* `ObsidianService.listTags`, returned whole and unsorted — the upstream
|
|
7
|
+
* `/tags/` payload in upstream order, or under OBSIDIAN_READ_PATHS the tags of
|
|
8
|
+
* readable notes in order of first appearance. The tool shapes the same
|
|
9
|
+
* payload for an LLM caller — count-descending, capped, filterable — and that
|
|
10
|
+
* shaping deliberately lives in the tool handler rather than the shared
|
|
11
|
+
* service call both make.
|
|
10
12
|
* @module mcp-server/resources/definitions/obsidian-tags.resource
|
|
11
13
|
*/
|
|
12
14
|
import { z } from '@cyanheads/mcp-ts-core';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"obsidian-tags.resource.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/resources/definitions/obsidian-tags.resource.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"obsidian-tags.resource.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/resources/definitions/obsidian-tags.resource.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAY,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAGrD,eAAO,MAAM,YAAY;;;;;6BA+BvB,CAAC"}
|
|
@@ -2,18 +2,20 @@
|
|
|
2
2
|
* @fileoverview obsidian://tags — vault tag listing with usage counts, for
|
|
3
3
|
* clients that prefer attaching resources.
|
|
4
4
|
*
|
|
5
|
-
* Not a mirror of `obsidian_list_tags`: this is a snapshot of
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
5
|
+
* Not a mirror of `obsidian_list_tags`: this is a snapshot of
|
|
6
|
+
* `ObsidianService.listTags`, returned whole and unsorted — the upstream
|
|
7
|
+
* `/tags/` payload in upstream order, or under OBSIDIAN_READ_PATHS the tags of
|
|
8
|
+
* readable notes in order of first appearance. The tool shapes the same
|
|
9
|
+
* payload for an LLM caller — count-descending, capped, filterable — and that
|
|
10
|
+
* shaping deliberately lives in the tool handler rather than the shared
|
|
11
|
+
* service call both make.
|
|
10
12
|
* @module mcp-server/resources/definitions/obsidian-tags.resource
|
|
11
13
|
*/
|
|
12
14
|
import { resource, z } from '@cyanheads/mcp-ts-core';
|
|
13
15
|
import { getObsidianService } from '../../../services/obsidian/obsidian-service.js';
|
|
14
16
|
export const obsidianTags = resource('obsidian://tags', {
|
|
15
17
|
name: 'obsidian-tags',
|
|
16
|
-
description: 'All tags found in the Obsidian vault, with usage counts,
|
|
18
|
+
description: 'All tags found in the Obsidian vault, with usage counts, unsorted and uncapped — a full snapshot. When OBSIDIAN_READ_PATHS is set, only tags carried by readable notes. Includes hierarchical parents (e.g. `work` for `work/tasks`). Use the `obsidian_list_tags` tool for a count-ranked, capped, filterable view.',
|
|
17
19
|
mimeType: 'application/json',
|
|
18
20
|
params: z.object({}),
|
|
19
21
|
output: z.object({
|
|
@@ -21,10 +23,12 @@ export const obsidianTags = resource('obsidian://tags', {
|
|
|
21
23
|
.array(z
|
|
22
24
|
.object({
|
|
23
25
|
name: z.string().describe('Tag name without the leading `#`.'),
|
|
24
|
-
count: z
|
|
26
|
+
count: z
|
|
27
|
+
.number()
|
|
28
|
+
.describe('Times the tag, or a tag nested under it, occurs across the vault. When OBSIDIAN_READ_PATHS is set: the number of readable notes carrying the tag or a tag nested under it.'),
|
|
25
29
|
})
|
|
26
30
|
.describe('A tag with its usage count.'))
|
|
27
|
-
.describe('Every tag in the vault, in
|
|
31
|
+
.describe('Every tag in the vault, in the order the Local REST API reports them. When OBSIDIAN_READ_PATHS is set: every tag carried by a readable note, in order of first appearance.'),
|
|
28
32
|
}),
|
|
29
33
|
auth: ['resource:obsidian-tags:read'],
|
|
30
34
|
async handler(_params, ctx) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"obsidian-tags.resource.js","sourceRoot":"","sources":["../../../../src/mcp-server/resources/definitions/obsidian-tags.resource.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"obsidian-tags.resource.js","sourceRoot":"","sources":["../../../../src/mcp-server/resources/definitions/obsidian-tags.resource.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAC;AAE7E,MAAM,CAAC,MAAM,YAAY,GAAG,QAAQ,CAAC,iBAAiB,EAAE;IACtD,IAAI,EAAE,eAAe;IACrB,WAAW,EACT,sTAAsT;IACxT,QAAQ,EAAE,kBAAkB;IAC5B,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;IACpB,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC;QACf,IAAI,EAAE,CAAC;aACJ,KAAK,CACJ,CAAC;aACE,MAAM,CAAC;YACN,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,mCAAmC,CAAC;YAC9D,KAAK,EAAE,CAAC;iBACL,MAAM,EAAE;iBACR,QAAQ,CACP,4KAA4K,CAC7K;SACJ,CAAC;aACD,QAAQ,CAAC,6BAA6B,CAAC,CAC3C;aACA,QAAQ,CACP,4KAA4K,CAC7K;KACJ,CAAC;IACF,IAAI,EAAE,CAAC,6BAA6B,CAAC;IAErC,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG;QACxB,MAAM,GAAG,GAAG,kBAAkB,EAAE,CAAC;QACjC,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QACrC,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC;IACvE,CAAC;CACF,CAAC,CAAC"}
|
|
@@ -4,20 +4,35 @@
|
|
|
4
4
|
* 1. **Case-insensitive fallback.** If a path lookup 404s, list the parent
|
|
5
5
|
* directory and look for a single case-insensitive filename match. If
|
|
6
6
|
* found, retry against the canonical filesystem path (matches v2.x
|
|
7
|
-
* behavior)
|
|
8
|
-
*
|
|
7
|
+
* behavior) and report the path that was asked for as `requestedPath`, so
|
|
8
|
+
* the caller can disclose the substitution. The fallback is reachable on
|
|
9
|
+
* every host: the plugin's `note+json` and document-map reads resolve
|
|
10
|
+
* through Obsidian's case-sensitive vault index even on a case-insensitive
|
|
11
|
+
* filesystem (macOS, Windows). Only the raw-markdown read case-folds there,
|
|
12
|
+
* answering 200 for a wrong-case path before any fallback runs.
|
|
9
13
|
*
|
|
10
14
|
* 2. **"Did you mean" suggestions.** When no case match exists but the parent
|
|
11
15
|
* directory has near-matches (e.g., extension-stripped variants), re-throw
|
|
12
16
|
* NotFound enriched with the candidates in the message and
|
|
13
17
|
* `error.data.suggestions[]`.
|
|
14
18
|
*
|
|
15
|
-
*
|
|
19
|
+
* `obsidian_get_note` and `obsidian_open_in_ui` wrap their service calls with
|
|
20
|
+
* `withCaseFallback`; writes and deletes match the exact path.
|
|
16
21
|
* @module mcp-server/tools/definitions/_shared/suggest-paths
|
|
17
22
|
*/
|
|
18
23
|
import type { Context } from '@cyanheads/mcp-ts-core';
|
|
19
24
|
import type { ObsidianService } from '../../../../services/obsidian/obsidian-service.js';
|
|
20
25
|
import type { NoteTarget } from '../../../../services/obsidian/types.js';
|
|
26
|
+
/** Outcome of {@link withCaseFallback}; `requestedPath` is present only when another path was read. */
|
|
27
|
+
export type CaseFallback<T> = {
|
|
28
|
+
result: T;
|
|
29
|
+
resolvedPath: string | undefined;
|
|
30
|
+
requestedPath?: never;
|
|
31
|
+
} | {
|
|
32
|
+
result: T;
|
|
33
|
+
resolvedPath: string;
|
|
34
|
+
requestedPath: string;
|
|
35
|
+
};
|
|
21
36
|
/**
|
|
22
37
|
* Wrap a service call with case-insensitive path fallback and "did you mean"
|
|
23
38
|
* enrichment. Non-path targets pass through — their paths are resolved
|
|
@@ -26,7 +41,7 @@ import type { NoteTarget } from '../../../../services/obsidian/types.js';
|
|
|
26
41
|
* For path targets:
|
|
27
42
|
* - **Exact match** → returns `{ result, resolvedPath: target.path }`.
|
|
28
43
|
* - **Single case match** → retries with the canonical path and returns
|
|
29
|
-
* `{ result, resolvedPath: <canonical
|
|
44
|
+
* `{ result, resolvedPath: <canonical>, requestedPath: target.path }`.
|
|
30
45
|
* - **Multiple case matches** → throws `Conflict` with the candidates so the
|
|
31
46
|
* agent can disambiguate.
|
|
32
47
|
* - **No case match, extension-stripped near-matches** → throws `NotFound`
|
|
@@ -35,17 +50,24 @@ import type { NoteTarget } from '../../../../services/obsidian/types.js';
|
|
|
35
50
|
*
|
|
36
51
|
* `resolvedPath` is `undefined` for non-path targets — callers derive the
|
|
37
52
|
* canonical path from the result itself (typically `NoteJson.path`).
|
|
53
|
+
* `requestedPath` is present only on the single-case-match branch.
|
|
38
54
|
*/
|
|
39
|
-
export declare function withCaseFallback<T>(ctx: Context, svc: ObsidianService, target: NoteTarget, fn: (target: NoteTarget) => Promise<T>): Promise<
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
55
|
+
export declare function withCaseFallback<T>(ctx: Context, svc: ObsidianService, target: NoteTarget, fn: (target: NoteTarget) => Promise<T>): Promise<CaseFallback<T>>;
|
|
56
|
+
/**
|
|
57
|
+
* Disclose a `withCaseFallback` substitution on the caller's enrichment: the
|
|
58
|
+
* `requestedPath` field plus a one-line notice naming both paths. `action` is
|
|
59
|
+
* what the tool did with the canonical file. Returns the notice — `notice` is
|
|
60
|
+
* last-wins, so a caller that sets another one must fold this text into it —
|
|
61
|
+
* or `undefined` when nothing was substituted.
|
|
62
|
+
*/
|
|
63
|
+
export declare function discloseCaseSubstitution(ctx: Context, fallback: CaseFallback<unknown>, action: 'read' | 'opened'): string | undefined;
|
|
43
64
|
/**
|
|
44
65
|
* List the parent directory of `path` and return up to {@link MAX_SUGGESTIONS}
|
|
45
66
|
* close-match candidates. Match order: case-insensitive equality first, then
|
|
46
67
|
* extension-stripped equality. Returns `[]` on listing failure or empty
|
|
47
|
-
* basename. Used by callers that need suggestions without
|
|
48
|
-
*
|
|
68
|
+
* basename. Used by callers that need suggestions without substituting a
|
|
69
|
+
* match (e.g., `obsidian_delete_note`'s exact-case miss, which names the
|
|
70
|
+
* candidates but never deletes one in place of the requested path).
|
|
49
71
|
*/
|
|
50
72
|
export declare function findSimilarPaths(ctx: Context, svc: ObsidianService, path: string): Promise<string[]>;
|
|
51
73
|
//# sourceMappingURL=suggest-paths.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"suggest-paths.d.ts","sourceRoot":"","sources":["../../../../../src/mcp-server/tools/definitions/_shared/suggest-paths.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"suggest-paths.d.ts","sourceRoot":"","sources":["../../../../../src/mcp-server/tools/definitions/_shared/suggest-paths.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAEtD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;AAC/E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAW/D,uGAAuG;AACvG,MAAM,MAAM,YAAY,CAAC,CAAC,IACtB;IAAE,MAAM,EAAE,CAAC,CAAC;IAAC,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,aAAa,CAAC,EAAE,KAAK,CAAA;CAAE,GACtE;IAAE,MAAM,EAAE,CAAC,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,CAAC;AAE/D;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,gBAAgB,CAAC,CAAC,EACtC,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,eAAe,EACpB,MAAM,EAAE,UAAU,EAClB,EAAE,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,OAAO,CAAC,CAAC,CAAC,GACrC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAsC1B;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACtC,GAAG,EAAE,OAAO,EACZ,QAAQ,EAAE,YAAY,CAAC,OAAO,CAAC,EAC/B,MAAM,EAAE,MAAM,GAAG,QAAQ,GACxB,MAAM,GAAG,SAAS,CAOpB;AAED;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,eAAe,EACpB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,MAAM,EAAE,CAAC,CAGnB"}
|
|
@@ -4,15 +4,20 @@
|
|
|
4
4
|
* 1. **Case-insensitive fallback.** If a path lookup 404s, list the parent
|
|
5
5
|
* directory and look for a single case-insensitive filename match. If
|
|
6
6
|
* found, retry against the canonical filesystem path (matches v2.x
|
|
7
|
-
* behavior)
|
|
8
|
-
*
|
|
7
|
+
* behavior) and report the path that was asked for as `requestedPath`, so
|
|
8
|
+
* the caller can disclose the substitution. The fallback is reachable on
|
|
9
|
+
* every host: the plugin's `note+json` and document-map reads resolve
|
|
10
|
+
* through Obsidian's case-sensitive vault index even on a case-insensitive
|
|
11
|
+
* filesystem (macOS, Windows). Only the raw-markdown read case-folds there,
|
|
12
|
+
* answering 200 for a wrong-case path before any fallback runs.
|
|
9
13
|
*
|
|
10
14
|
* 2. **"Did you mean" suggestions.** When no case match exists but the parent
|
|
11
15
|
* directory has near-matches (e.g., extension-stripped variants), re-throw
|
|
12
16
|
* NotFound enriched with the candidates in the message and
|
|
13
17
|
* `error.data.suggestions[]`.
|
|
14
18
|
*
|
|
15
|
-
*
|
|
19
|
+
* `obsidian_get_note` and `obsidian_open_in_ui` wrap their service calls with
|
|
20
|
+
* `withCaseFallback`; writes and deletes match the exact path.
|
|
16
21
|
* @module mcp-server/tools/definitions/_shared/suggest-paths
|
|
17
22
|
*/
|
|
18
23
|
import { conflict, JsonRpcErrorCode, McpError, notFound } from '@cyanheads/mcp-ts-core/errors';
|
|
@@ -25,7 +30,7 @@ const MAX_SUGGESTIONS = 5;
|
|
|
25
30
|
* For path targets:
|
|
26
31
|
* - **Exact match** → returns `{ result, resolvedPath: target.path }`.
|
|
27
32
|
* - **Single case match** → retries with the canonical path and returns
|
|
28
|
-
* `{ result, resolvedPath: <canonical
|
|
33
|
+
* `{ result, resolvedPath: <canonical>, requestedPath: target.path }`.
|
|
29
34
|
* - **Multiple case matches** → throws `Conflict` with the candidates so the
|
|
30
35
|
* agent can disambiguate.
|
|
31
36
|
* - **No case match, extension-stripped near-matches** → throws `NotFound`
|
|
@@ -34,6 +39,7 @@ const MAX_SUGGESTIONS = 5;
|
|
|
34
39
|
*
|
|
35
40
|
* `resolvedPath` is `undefined` for non-path targets — callers derive the
|
|
36
41
|
* canonical path from the result itself (typically `NoteJson.path`).
|
|
42
|
+
* `requestedPath` is present only on the single-case-match branch.
|
|
37
43
|
*/
|
|
38
44
|
export async function withCaseFallback(ctx, svc, target, fn) {
|
|
39
45
|
if (target.type !== 'path') {
|
|
@@ -50,7 +56,7 @@ export async function withCaseFallback(ctx, svc, target, fn) {
|
|
|
50
56
|
const sole = probe.caseMatches.length === 1 ? probe.caseMatches[0] : undefined;
|
|
51
57
|
if (sole !== undefined) {
|
|
52
58
|
const result = await fn({ type: 'path', path: sole });
|
|
53
|
-
return { result, resolvedPath: sole };
|
|
59
|
+
return { result, resolvedPath: sole, requestedPath: target.path };
|
|
54
60
|
}
|
|
55
61
|
if (probe.caseMatches.length > 1) {
|
|
56
62
|
const list = probe.caseMatches.map((m) => `"${m}"`).join(', ');
|
|
@@ -58,7 +64,6 @@ export async function withCaseFallback(ctx, svc, target, fn) {
|
|
|
58
64
|
path: target.path,
|
|
59
65
|
reason: 'ambiguous_path',
|
|
60
66
|
matches: probe.caseMatches,
|
|
61
|
-
...ctx.recoveryFor('ambiguous_path'),
|
|
62
67
|
}, { cause: err });
|
|
63
68
|
}
|
|
64
69
|
if (probe.extInsensitive.length === 0)
|
|
@@ -69,12 +74,29 @@ export async function withCaseFallback(ctx, svc, target, fn) {
|
|
|
69
74
|
throw notFound(`${prefix}. Did you mean: ${list}?`, { ...(err.data ?? {}), suggestions }, { cause: err });
|
|
70
75
|
}
|
|
71
76
|
}
|
|
77
|
+
/**
|
|
78
|
+
* Disclose a `withCaseFallback` substitution on the caller's enrichment: the
|
|
79
|
+
* `requestedPath` field plus a one-line notice naming both paths. `action` is
|
|
80
|
+
* what the tool did with the canonical file. Returns the notice — `notice` is
|
|
81
|
+
* last-wins, so a caller that sets another one must fold this text into it —
|
|
82
|
+
* or `undefined` when nothing was substituted.
|
|
83
|
+
*/
|
|
84
|
+
export function discloseCaseSubstitution(ctx, fallback, action) {
|
|
85
|
+
if (fallback.requestedPath === undefined)
|
|
86
|
+
return;
|
|
87
|
+
const { requestedPath, resolvedPath } = fallback;
|
|
88
|
+
const notice = `\`${requestedPath}\` has no exact match; ${action} \`${resolvedPath}\`, the one file in that folder whose name matches it ignoring case. Write and delete tools match paths exactly — pass them \`${resolvedPath}\`.`;
|
|
89
|
+
ctx.enrich({ requestedPath });
|
|
90
|
+
ctx.enrich.notice(notice);
|
|
91
|
+
return notice;
|
|
92
|
+
}
|
|
72
93
|
/**
|
|
73
94
|
* List the parent directory of `path` and return up to {@link MAX_SUGGESTIONS}
|
|
74
95
|
* close-match candidates. Match order: case-insensitive equality first, then
|
|
75
96
|
* extension-stripped equality. Returns `[]` on listing failure or empty
|
|
76
|
-
* basename. Used by callers that need suggestions without
|
|
77
|
-
*
|
|
97
|
+
* basename. Used by callers that need suggestions without substituting a
|
|
98
|
+
* match (e.g., `obsidian_delete_note`'s exact-case miss, which names the
|
|
99
|
+
* candidates but never deletes one in place of the requested path).
|
|
78
100
|
*/
|
|
79
101
|
export async function findSimilarPaths(ctx, svc, path) {
|
|
80
102
|
const probe = await probeParentDir(ctx, svc, path);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"suggest-paths.js","sourceRoot":"","sources":["../../../../../src/mcp-server/tools/definitions/_shared/suggest-paths.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"suggest-paths.js","sourceRoot":"","sources":["../../../../../src/mcp-server/tools/definitions/_shared/suggest-paths.ts"],"names":[],"mappings":"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"}
|