obsidian-mcp-server 3.6.1 → 3.7.1
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 -22
- package/CLAUDE.md +40 -22
- package/Dockerfile +3 -3
- package/README.md +29 -17
- package/changelog/3.7.x/3.7.0.md +34 -0
- package/changelog/3.7.x/3.7.1.md +40 -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 +5 -1
- package/dist/config/server-config.js.map +1 -1
- package/dist/index.js +35 -35
- package/dist/index.js.map +1 -1
- package/dist/instructions.d.ts +20 -0
- package/dist/instructions.d.ts.map +1 -0
- package/dist/instructions.js +40 -0
- package/dist/instructions.js.map +1 -0
- 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 +69 -9
- package/dist/mcp-server/tools/definitions/_shared/suggest-paths.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/_shared/suggest-paths.js +88 -7
- package/dist/mcp-server/tools/definitions/_shared/suggest-paths.js.map +1 -1
- package/dist/mcp-server/tools/definitions/index.d.ts +256 -309
- 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.d.ts +6 -0
- package/dist/mcp-server/tools/definitions/obsidian-append-to-note.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/obsidian-append-to-note.tool.js +12 -4
- 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 +107 -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 +237 -162
- 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 +70 -24
- package/dist/mcp-server/tools/definitions/obsidian-get-note.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 +8 -10
- 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 +13 -7
- 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 +6 -4
- package/dist/mcp-server/tools/definitions/obsidian-manage-frontmatter.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/obsidian-manage-tags.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/obsidian-manage-tags.tool.js +4 -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-patch-note.tool.js +2 -2
- package/dist/mcp-server/tools/definitions/obsidian-patch-note.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 +4 -2
- 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 +26 -2
- 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 +47 -15
- package/dist/mcp-server/tools/definitions/obsidian-search-notes.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/obsidian-write-note.tool.d.ts +5 -0
- package/dist/mcp-server/tools/definitions/obsidian-write-note.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/obsidian-write-note.tool.js +21 -4
- package/dist/mcp-server/tools/definitions/obsidian-write-note.tool.js.map +1 -1
- package/dist/services/obsidian/frontmatter-ops.d.ts +15 -1
- package/dist/services/obsidian/frontmatter-ops.d.ts.map +1 -1
- package/dist/services/obsidian/frontmatter-ops.js +55 -10
- package/dist/services/obsidian/frontmatter-ops.js.map +1 -1
- package/dist/services/obsidian/jsonlogic-evaluator.d.ts +83 -0
- package/dist/services/obsidian/jsonlogic-evaluator.d.ts.map +1 -0
- package/dist/services/obsidian/jsonlogic-evaluator.js +192 -0
- package/dist/services/obsidian/jsonlogic-evaluator.js.map +1 -0
- package/dist/services/obsidian/jsonlogic-worker.d.ts +53 -0
- package/dist/services/obsidian/jsonlogic-worker.d.ts.map +1 -0
- package/dist/services/obsidian/jsonlogic-worker.js +237 -0
- package/dist/services/obsidian/jsonlogic-worker.js.map +1 -0
- package/dist/services/obsidian/obsidian-service.d.ts +61 -6
- package/dist/services/obsidian/obsidian-service.d.ts.map +1 -1
- package/dist/services/obsidian/obsidian-service.js +301 -53
- 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 +55 -5
- package/dist/services/obsidian/path-policy.d.ts.map +1 -1
- package/dist/services/obsidian/path-policy.js +143 -19
- 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/dist/services/obsidian/types.d.ts +12 -3
- package/dist/services/obsidian/types.d.ts.map +1 -1
- package/manifest.json +10 -2
- package/package.json +18 -14
- package/server.json +19 -5
|
@@ -7,8 +7,12 @@
|
|
|
7
7
|
* module free of eager config reads. `obsidian_search_notes` is exposed as a
|
|
8
8
|
* factory (`buildSearchNotesTool`) because its mode enum is conditional on
|
|
9
9
|
* Omnisearch reachability, which is only known after the startup probe runs.
|
|
10
|
+
* `obsidian_delete_note` is exposed as a factory (`buildDeleteNoteTool`)
|
|
11
|
+
* because its description and confirmation round follow
|
|
12
|
+
* `OBSIDIAN_DELETE_ELICITATION`, which the entry point reads.
|
|
10
13
|
* @module mcp-server/tools/definitions/index
|
|
11
14
|
*/
|
|
15
|
+
export { buildDeleteNoteTool } from './obsidian-delete-note.tool.js';
|
|
12
16
|
export { buildSearchNotesTool } from './obsidian-search-notes.tool.js';
|
|
13
17
|
/**
|
|
14
18
|
* Tools that don't depend on runtime probes — always registered, even with
|
|
@@ -165,36 +169,8 @@ export declare const readToolDefinitions: (import("@cyanheads/mcp-ts-core").Tool
|
|
|
165
169
|
readonly when: "The path contains a `.` or `..` segment, which is rejected to prevent vault escape.";
|
|
166
170
|
readonly recovery: "Supply a vault-relative path with no `.` or `..` segments, e.g. \"Projects/Note.md\". Use obsidian_list_notes to browse the vault.";
|
|
167
171
|
}], {
|
|
172
|
+
readonly requestedPath: import("zod").ZodOptional<import("zod").ZodString>;
|
|
168
173
|
readonly notice: import("zod").ZodOptional<import("zod").ZodString>;
|
|
169
|
-
}> | import("@cyanheads/mcp-ts-core").ToolDefinition<import("zod").ZodObject<{
|
|
170
|
-
nameRegex: import("zod").ZodOptional<import("zod").ZodString>;
|
|
171
|
-
minCount: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
172
|
-
limit: import("zod").ZodDefault<import("zod").ZodNumber>;
|
|
173
|
-
}, import("zod/v4/core").$strip>, import("zod").ZodObject<{
|
|
174
|
-
tags: import("zod").ZodArray<import("zod").ZodObject<{
|
|
175
|
-
name: import("zod").ZodString;
|
|
176
|
-
count: import("zod").ZodNumber;
|
|
177
|
-
}, import("zod/v4/core").$strip>>;
|
|
178
|
-
appliedFilters: import("zod").ZodObject<{
|
|
179
|
-
nameRegex: import("zod").ZodOptional<import("zod").ZodString>;
|
|
180
|
-
minCount: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
181
|
-
limit: import("zod").ZodNumber;
|
|
182
|
-
}, import("zod/v4/core").$strip>;
|
|
183
|
-
}, import("zod/v4/core").$strip>, readonly [{
|
|
184
|
-
readonly reason: "regex_invalid";
|
|
185
|
-
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
|
|
186
|
-
readonly when: "The supplied `nameRegex` is not a valid ECMAScript regex.";
|
|
187
|
-
readonly recovery: "Use a valid ECMAScript regex (e.g. `^mcp/.*`), or omit nameRegex to disable filtering.";
|
|
188
|
-
}, {
|
|
189
|
-
readonly reason: "regex_unsafe";
|
|
190
|
-
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
|
|
191
|
-
readonly when: "The supplied `nameRegex` is well-formed but exceeds the 256-character limit or contains nested quantifiers known to cause catastrophic backtracking.";
|
|
192
|
-
readonly recovery: "Avoid nested quantifiers like `(a+)+` or `(.*)*`. Use a simpler pattern (e.g. `^mcp/.*`), or omit nameRegex to disable filtering.";
|
|
193
|
-
}], {
|
|
194
|
-
readonly notice: import("zod").ZodOptional<import("zod").ZodString>;
|
|
195
|
-
readonly truncated: import("zod").ZodOptional<import("zod").ZodBoolean>;
|
|
196
|
-
readonly shown: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
197
|
-
readonly cap: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
198
174
|
}> | import("@cyanheads/mcp-ts-core").ToolDefinition<import("zod").ZodObject<{
|
|
199
175
|
path: import("zod").ZodOptional<import("zod").ZodString>;
|
|
200
176
|
extension: import("zod").ZodOptional<import("zod").ZodString>;
|
|
@@ -239,7 +215,7 @@ export declare const readToolDefinitions: (import("@cyanheads/mcp-ts-core").Tool
|
|
|
239
215
|
readonly reason: "path_forbidden";
|
|
240
216
|
readonly thrownBy: "service";
|
|
241
217
|
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.Forbidden;
|
|
242
|
-
readonly when: "The supplied `path` is outside OBSIDIAN_READ_PATHS
|
|
218
|
+
readonly when: "The supplied `path` is outside OBSIDIAN_READ_PATHS and is not a folder on the way to it. The vault root and the folders leading to a scoped path always list, showing only in-scope entries.";
|
|
243
219
|
readonly recovery: "List a directory inside the configured read scope, or omit `path` to list from the vault root. The error data echoes the active scope.";
|
|
244
220
|
}, {
|
|
245
221
|
readonly reason: "directory_missing";
|
|
@@ -255,6 +231,35 @@ export declare const readToolDefinitions: (import("@cyanheads/mcp-ts-core").Tool
|
|
|
255
231
|
readonly recovery: "Read the file with obsidian_get_note instead, or list its parent directory to browse alongside it.";
|
|
256
232
|
}], {
|
|
257
233
|
readonly notice: import("zod").ZodOptional<import("zod").ZodString>;
|
|
234
|
+
}> | import("@cyanheads/mcp-ts-core").ToolDefinition<import("zod").ZodObject<{
|
|
235
|
+
nameRegex: import("zod").ZodOptional<import("zod").ZodString>;
|
|
236
|
+
minCount: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
237
|
+
limit: import("zod").ZodDefault<import("zod").ZodNumber>;
|
|
238
|
+
}, import("zod/v4/core").$strip>, import("zod").ZodObject<{
|
|
239
|
+
tags: import("zod").ZodArray<import("zod").ZodObject<{
|
|
240
|
+
name: import("zod").ZodString;
|
|
241
|
+
count: import("zod").ZodNumber;
|
|
242
|
+
}, import("zod/v4/core").$strip>>;
|
|
243
|
+
appliedFilters: import("zod").ZodObject<{
|
|
244
|
+
nameRegex: import("zod").ZodOptional<import("zod").ZodString>;
|
|
245
|
+
minCount: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
246
|
+
limit: import("zod").ZodNumber;
|
|
247
|
+
}, import("zod/v4/core").$strip>;
|
|
248
|
+
}, import("zod/v4/core").$strip>, readonly [{
|
|
249
|
+
readonly reason: "regex_invalid";
|
|
250
|
+
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
|
|
251
|
+
readonly when: "The supplied `nameRegex` is not a valid ECMAScript regex.";
|
|
252
|
+
readonly recovery: "Use a valid ECMAScript regex (e.g. `^mcp/.*`), or omit nameRegex to disable filtering.";
|
|
253
|
+
}, {
|
|
254
|
+
readonly reason: "regex_unsafe";
|
|
255
|
+
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
|
|
256
|
+
readonly when: "The supplied `nameRegex` is well-formed but exceeds the 256-character limit or contains nested quantifiers known to cause catastrophic backtracking.";
|
|
257
|
+
readonly recovery: "Avoid nested quantifiers like `(a+)+` or `(.*)*`. Use a simpler pattern (e.g. `^mcp/.*`), or omit nameRegex to disable filtering.";
|
|
258
|
+
}], {
|
|
259
|
+
readonly notice: import("zod").ZodOptional<import("zod").ZodString>;
|
|
260
|
+
readonly truncated: import("zod").ZodOptional<import("zod").ZodBoolean>;
|
|
261
|
+
readonly shown: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
262
|
+
readonly cap: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
258
263
|
}> | import("@cyanheads/mcp-ts-core").ToolDefinition<import("zod").ZodObject<{
|
|
259
264
|
path: import("zod").ZodString;
|
|
260
265
|
failIfMissing: import("zod").ZodDefault<import("zod").ZodBoolean>;
|
|
@@ -292,9 +297,21 @@ export declare const readToolDefinitions: (import("@cyanheads/mcp-ts-core").Tool
|
|
|
292
297
|
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
|
|
293
298
|
readonly when: "The path contains a `.` or `..` segment, which is rejected to prevent vault escape.";
|
|
294
299
|
readonly recovery: "Supply a vault-relative path with no `.` or `..` segments, e.g. \"Projects/Note.md\". Use obsidian_list_notes to browse the vault.";
|
|
295
|
-
}],
|
|
296
|
-
|
|
300
|
+
}], {
|
|
301
|
+
readonly requestedPath: import("zod").ZodOptional<import("zod").ZodString>;
|
|
302
|
+
readonly notice: import("zod").ZodOptional<import("zod").ZodString>;
|
|
303
|
+
}>)[];
|
|
304
|
+
/**
|
|
305
|
+
* Write tools — wrapped with `disabledTool()` when `OBSIDIAN_READ_ONLY=true`.
|
|
306
|
+
* `obsidian_delete_note` joins this set in the entry point, built via
|
|
307
|
+
* `buildDeleteNoteTool`.
|
|
308
|
+
*/
|
|
297
309
|
export declare const writeToolDefinitions: (import("@cyanheads/mcp-ts-core").ToolDefinition<import("zod").ZodObject<{
|
|
310
|
+
operation: import("zod").ZodEnum<{
|
|
311
|
+
delete: "delete";
|
|
312
|
+
get: "get";
|
|
313
|
+
set: "set";
|
|
314
|
+
}>;
|
|
298
315
|
target: import("zod").ZodDiscriminatedUnion<[import("zod").ZodObject<{
|
|
299
316
|
type: import("zod").ZodLiteral<"path">;
|
|
300
317
|
path: import("zod").ZodString;
|
|
@@ -311,39 +328,52 @@ export declare const writeToolDefinitions: (import("@cyanheads/mcp-ts-core").Too
|
|
|
311
328
|
}>;
|
|
312
329
|
date: import("zod").ZodOptional<import("zod").ZodString>;
|
|
313
330
|
}, import("zod/v4/core").$strip>], "type">;
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
type: import("zod").ZodEnum<{
|
|
317
|
-
block: "block";
|
|
318
|
-
frontmatter: "frontmatter";
|
|
319
|
-
heading: "heading";
|
|
320
|
-
}>;
|
|
321
|
-
target: import("zod").ZodString;
|
|
322
|
-
}, import("zod/v4/core").$strip>>;
|
|
323
|
-
contentType: import("zod").ZodDefault<import("zod").ZodEnum<{
|
|
324
|
-
json: "json";
|
|
325
|
-
markdown: "markdown";
|
|
326
|
-
}>>;
|
|
327
|
-
createTargetIfMissing: import("zod").ZodDefault<import("zod").ZodBoolean>;
|
|
331
|
+
key: import("zod").ZodString;
|
|
332
|
+
value: import("zod").ZodOptional<import("zod").ZodUnknown>;
|
|
328
333
|
}, import("zod/v4/core").$strip>, import("zod").ZodObject<{
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
334
|
+
result: import("zod").ZodDiscriminatedUnion<[import("zod").ZodObject<{
|
|
335
|
+
operation: import("zod").ZodLiteral<"get">;
|
|
336
|
+
path: import("zod").ZodString;
|
|
337
|
+
key: import("zod").ZodString;
|
|
338
|
+
exists: import("zod").ZodBoolean;
|
|
339
|
+
value: import("zod").ZodUnknown;
|
|
340
|
+
}, import("zod/v4/core").$strip>, import("zod").ZodObject<{
|
|
341
|
+
operation: import("zod").ZodLiteral<"set">;
|
|
342
|
+
path: import("zod").ZodString;
|
|
343
|
+
key: import("zod").ZodString;
|
|
344
|
+
frontmatter: import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnknown>;
|
|
345
|
+
previousSizeInBytes: import("zod").ZodNumber;
|
|
346
|
+
currentSizeInBytes: import("zod").ZodNumber;
|
|
347
|
+
}, import("zod/v4/core").$strip>, import("zod").ZodObject<{
|
|
348
|
+
operation: import("zod").ZodLiteral<"delete">;
|
|
349
|
+
path: import("zod").ZodString;
|
|
350
|
+
key: import("zod").ZodString;
|
|
351
|
+
frontmatter: import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnknown>;
|
|
352
|
+
previousSizeInBytes: import("zod").ZodNumber;
|
|
353
|
+
currentSizeInBytes: import("zod").ZodNumber;
|
|
354
|
+
}, import("zod/v4/core").$strip>], "operation">;
|
|
335
355
|
}, import("zod/v4/core").$strip>, readonly [{
|
|
336
356
|
readonly reason: "path_forbidden";
|
|
337
357
|
readonly thrownBy: "service";
|
|
338
358
|
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.Forbidden;
|
|
339
|
-
readonly when: "
|
|
340
|
-
readonly recovery: "Use a path inside the configured
|
|
359
|
+
readonly when: "`get` requires the path to be readable; `set`/`delete` require it to be inside OBSIDIAN_WRITE_PATHS, with OBSIDIAN_READ_ONLY=false.";
|
|
360
|
+
readonly recovery: "Use a path inside the configured scope. The error data echoes the active scope.";
|
|
361
|
+
}, {
|
|
362
|
+
readonly reason: "value_required";
|
|
363
|
+
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
|
|
364
|
+
readonly when: "`operation` is \"set\" but no `value` was supplied.";
|
|
365
|
+
readonly recovery: "Pass `value` as any JSON-typed value: string, number, boolean, array, or object (e.g. `\"draft\"`, `42`, `true`, `[\"a\",\"b\"]`).";
|
|
366
|
+
}, {
|
|
367
|
+
readonly reason: "frontmatter_invalid";
|
|
368
|
+
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
|
|
369
|
+
readonly when: "`operation` is \"delete\" and the note's existing frontmatter does not parse as a mapping of properties, or removing the key would leave YAML that cannot be re-emitted (an alias whose anchor went with it). Nothing is written — the note keeps its original bytes.";
|
|
370
|
+
readonly recovery: "Read the block with obsidian_get_note (format \"content\"), repair the YAML between the `---` fences, then retry the delete.";
|
|
341
371
|
}, {
|
|
342
372
|
readonly reason: "note_missing";
|
|
343
373
|
readonly thrownBy: "service";
|
|
344
374
|
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.NotFound;
|
|
345
|
-
readonly when: "
|
|
346
|
-
readonly recovery: "Verify the path with obsidian_list_notes
|
|
375
|
+
readonly when: "The vault path does not resolve to an existing note.";
|
|
376
|
+
readonly recovery: "Verify the path with obsidian_list_notes or use obsidian_search_notes to locate the note.";
|
|
347
377
|
}, {
|
|
348
378
|
readonly reason: "no_active_file";
|
|
349
379
|
readonly thrownBy: "service";
|
|
@@ -368,36 +398,6 @@ export declare const writeToolDefinitions: (import("@cyanheads/mcp-ts-core").Too
|
|
|
368
398
|
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
|
|
369
399
|
readonly when: "Target was `periodic` but the requested period is not enabled in Obsidian's Periodic Notes plugin settings.";
|
|
370
400
|
readonly recovery: "Pass an explicit path target — the requested period is disabled in the operator's Periodic Notes plugin.";
|
|
371
|
-
}, {
|
|
372
|
-
readonly reason: "section_target_missing";
|
|
373
|
-
readonly thrownBy: "service";
|
|
374
|
-
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
|
|
375
|
-
readonly when: "`section` was provided but the named heading/block/frontmatter field does not exist in the note.";
|
|
376
|
-
readonly recovery: "Call obsidian_get_note with format document-map to discover available targets, or pass createTargetIfMissing: true to bring it into existence.";
|
|
377
|
-
}, {
|
|
378
|
-
readonly reason: "ambiguous_section";
|
|
379
|
-
readonly thrownBy: "service";
|
|
380
|
-
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.Conflict;
|
|
381
|
-
readonly when: "A bare heading leaf name matches more than one heading in the note, or the resolved full heading path occurs more than once, so the append target is undetermined.";
|
|
382
|
-
readonly recovery: "Retry with a distinct full Parent::Child heading path from `candidates` on the error data; when every candidate is the same path, rename the repeated headings first.";
|
|
383
|
-
}, {
|
|
384
|
-
readonly reason: "content_preexists";
|
|
385
|
-
readonly thrownBy: "service";
|
|
386
|
-
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
|
|
387
|
-
readonly when: "Section append where the supplied content already appears at the target — rejected to keep retries idempotent (the default for the section path).";
|
|
388
|
-
readonly recovery: "Change the content to something not already present at the target, or use obsidian_patch_note with `patchOptions.applyIfContentPreexists: true` if a duplicate is intended.";
|
|
389
|
-
}, {
|
|
390
|
-
readonly reason: "heading_outside_section";
|
|
391
|
-
readonly thrownBy: "service";
|
|
392
|
-
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
|
|
393
|
-
readonly when: "On Local REST API v5.0 and later, content appended to a heading carries a heading at or above that section’s own level, which would have to sit outside the section.";
|
|
394
|
-
readonly recovery: "Append the heading at the parent section or at the end of the note (no `section`), or write it one level below the target section or deeper.";
|
|
395
|
-
}, {
|
|
396
|
-
readonly reason: "patch_rejected";
|
|
397
|
-
readonly thrownBy: "service";
|
|
398
|
-
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
|
|
399
|
-
readonly when: "The section exists but the plugin refused the content for it — table rows for a block that is not a table, a row with the wrong cell count, a frontmatter value that cannot merge, or content of the wrong shape.";
|
|
400
|
-
readonly recovery: "Read the target with obsidian_get_note format section, then send content that fits it — rows matching the table columns, or a value of the field’s own type.";
|
|
401
401
|
}, {
|
|
402
402
|
readonly reason: "path_is_directory";
|
|
403
403
|
readonly thrownBy: "service";
|
|
@@ -427,52 +427,52 @@ export declare const writeToolDefinitions: (import("@cyanheads/mcp-ts-core").Too
|
|
|
427
427
|
}>;
|
|
428
428
|
date: import("zod").ZodOptional<import("zod").ZodString>;
|
|
429
429
|
}, import("zod/v4/core").$strip>], "type">;
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
heading: "heading";
|
|
435
|
-
}>;
|
|
436
|
-
target: import("zod").ZodString;
|
|
437
|
-
}, import("zod/v4/core").$strip>;
|
|
438
|
-
operation: import("zod").ZodEnum<{
|
|
439
|
-
append: "append";
|
|
440
|
-
prepend: "prepend";
|
|
441
|
-
replace: "replace";
|
|
442
|
-
}>;
|
|
443
|
-
content: import("zod").ZodString;
|
|
444
|
-
contentType: import("zod").ZodDefault<import("zod").ZodEnum<{
|
|
445
|
-
json: "json";
|
|
446
|
-
markdown: "markdown";
|
|
430
|
+
scope: import("zod").ZodDefault<import("zod").ZodEnum<{
|
|
431
|
+
body: "body";
|
|
432
|
+
both: "both";
|
|
433
|
+
frontmatter: "frontmatter";
|
|
447
434
|
}>>;
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
435
|
+
replacements: import("zod").ZodArray<import("zod").ZodObject<{
|
|
436
|
+
search: import("zod").ZodString;
|
|
437
|
+
replace: import("zod").ZodString;
|
|
438
|
+
useRegex: import("zod").ZodDefault<import("zod").ZodBoolean>;
|
|
439
|
+
caseSensitive: import("zod").ZodDefault<import("zod").ZodBoolean>;
|
|
440
|
+
wholeWord: import("zod").ZodDefault<import("zod").ZodBoolean>;
|
|
441
|
+
flexibleWhitespace: import("zod").ZodDefault<import("zod").ZodBoolean>;
|
|
442
|
+
replaceAll: import("zod").ZodDefault<import("zod").ZodBoolean>;
|
|
452
443
|
}, import("zod/v4/core").$strip>>;
|
|
453
444
|
}, import("zod/v4/core").$strip>, import("zod").ZodObject<{
|
|
454
445
|
path: import("zod").ZodString;
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
}, import("zod/v4/core").$strip>;
|
|
463
|
-
operation: import("zod").ZodEnum<{
|
|
464
|
-
append: "append";
|
|
465
|
-
prepend: "prepend";
|
|
466
|
-
replace: "replace";
|
|
467
|
-
}>;
|
|
446
|
+
totalReplacements: import("zod").ZodNumber;
|
|
447
|
+
perReplacement: import("zod").ZodArray<import("zod").ZodObject<{
|
|
448
|
+
search: import("zod").ZodString;
|
|
449
|
+
count: import("zod").ZodNumber;
|
|
450
|
+
bodyCount: import("zod").ZodNumber;
|
|
451
|
+
frontmatterCount: import("zod").ZodNumber;
|
|
452
|
+
}, import("zod/v4/core").$strip>>;
|
|
468
453
|
previousSizeInBytes: import("zod").ZodNumber;
|
|
469
454
|
currentSizeInBytes: import("zod").ZodNumber;
|
|
470
455
|
}, import("zod/v4/core").$strip>, readonly [{
|
|
471
456
|
readonly reason: "path_forbidden";
|
|
472
457
|
readonly thrownBy: "service";
|
|
473
458
|
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.Forbidden;
|
|
474
|
-
readonly when: "The target path is outside OBSIDIAN_WRITE_PATHS, or OBSIDIAN_READ_ONLY=true denies all writes.";
|
|
459
|
+
readonly when: "The target path is outside OBSIDIAN_WRITE_PATHS, or OBSIDIAN_READ_ONLY=true denies all writes. The pre-read also requires the path to be readable.";
|
|
475
460
|
readonly recovery: "Use a path inside the configured write scope. The error data echoes the active scope.";
|
|
461
|
+
}, {
|
|
462
|
+
readonly reason: "regex_invalid";
|
|
463
|
+
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
|
|
464
|
+
readonly when: "A `useRegex: true` replacement supplied a `search` pattern that is not a valid ECMAScript regex.";
|
|
465
|
+
readonly recovery: "Use a valid ECMAScript regex, or set useRegex to false to match `search` as a literal string.";
|
|
466
|
+
}, {
|
|
467
|
+
readonly reason: "regex_unsafe";
|
|
468
|
+
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
|
|
469
|
+
readonly when: "A `useRegex: true` replacement supplied a `search` pattern that is well-formed but exceeds the 1024-character limit or contains nested quantifiers known to cause catastrophic backtracking against the note body.";
|
|
470
|
+
readonly recovery: "Avoid nested quantifiers like `(a+)+` or `(.*)*`. Use a simpler pattern, or set useRegex to false to match `search` as a literal string.";
|
|
471
|
+
}, {
|
|
472
|
+
readonly reason: "frontmatter_invalid";
|
|
473
|
+
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
|
|
474
|
+
readonly when: "A `scope` of \"frontmatter\" or \"both\" produced YAML that no longer parses as a mapping of properties, or that parses but cannot be re-emitted (an alias whose anchor the replacement removed). Nothing is written — the note keeps its original bytes. The check reads the rewritten YAML only, so a replacement that renames a key or changes a scalar's type while still parsing is not caught by it.";
|
|
475
|
+
readonly recovery: "Narrow the search so it cannot match inside the YAML, or leave scope at \"body\" and edit the property with obsidian_manage_frontmatter.";
|
|
476
476
|
}, {
|
|
477
477
|
readonly reason: "note_missing";
|
|
478
478
|
readonly thrownBy: "service";
|
|
@@ -504,43 +504,13 @@ export declare const writeToolDefinitions: (import("@cyanheads/mcp-ts-core").Too
|
|
|
504
504
|
readonly when: "Target was `periodic` but the requested period is not enabled in Obsidian's Periodic Notes plugin settings.";
|
|
505
505
|
readonly recovery: "Pass an explicit path target — the requested period is disabled in the operator's Periodic Notes plugin.";
|
|
506
506
|
}, {
|
|
507
|
-
readonly reason: "
|
|
508
|
-
readonly thrownBy: "service";
|
|
509
|
-
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
|
|
510
|
-
readonly when: "The named heading/block/frontmatter field does not exist in the note. Use `obsidian_get_note` with `format: \"document-map\"` to discover available targets.";
|
|
511
|
-
readonly recovery: "Call obsidian_get_note with format document-map to discover the available targets.";
|
|
512
|
-
}, {
|
|
513
|
-
readonly reason: "ambiguous_section";
|
|
514
|
-
readonly thrownBy: "service";
|
|
515
|
-
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.Conflict;
|
|
516
|
-
readonly when: "A bare heading leaf name matches more than one heading in the note, or the resolved full heading path occurs more than once, so the write target is undetermined.";
|
|
517
|
-
readonly recovery: "Retry with a distinct full Parent::Child heading path from `candidates` on the error data; when every candidate is the same path, rename the repeated headings first.";
|
|
518
|
-
}, {
|
|
519
|
-
readonly reason: "content_preexists";
|
|
520
|
-
readonly thrownBy: "service";
|
|
521
|
-
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
|
|
522
|
-
readonly when: "The supplied content already appears at the target — the patch was rejected to keep retries idempotent (the default).";
|
|
523
|
-
readonly recovery: "Pass `patchOptions.applyIfContentPreexists: true` to force-apply over preexisting content, or change the content to something not already present.";
|
|
524
|
-
}, {
|
|
525
|
-
readonly reason: "heading_outside_section";
|
|
507
|
+
readonly reason: "path_is_directory";
|
|
526
508
|
readonly thrownBy: "service";
|
|
527
509
|
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
|
|
528
|
-
readonly when: "
|
|
529
|
-
readonly recovery: "
|
|
510
|
+
readonly when: "The supplied path names a folder rather than a note file.";
|
|
511
|
+
readonly recovery: "Call obsidian_list_notes with this path to list the folder, then retry with the full path of one of the files it returns.";
|
|
530
512
|
}, {
|
|
531
|
-
readonly reason: "
|
|
532
|
-
readonly thrownBy: "service";
|
|
533
|
-
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
|
|
534
|
-
readonly when: "The target exists but the plugin refused the content for it — table rows for a block that is not a table, a row with the wrong cell count, a frontmatter value that cannot merge, or content of the wrong shape.";
|
|
535
|
-
readonly recovery: "Read the target with obsidian_get_note format section, then send content that fits it — rows matching the table columns, or a value of the field’s own type.";
|
|
536
|
-
}, {
|
|
537
|
-
readonly reason: "path_is_directory";
|
|
538
|
-
readonly thrownBy: "service";
|
|
539
|
-
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
|
|
540
|
-
readonly when: "The supplied path names a folder rather than a note file.";
|
|
541
|
-
readonly recovery: "Call obsidian_list_notes with this path to list the folder, then retry with the full path of one of the files it returns.";
|
|
542
|
-
}, {
|
|
543
|
-
readonly reason: "path_traversal";
|
|
513
|
+
readonly reason: "path_traversal";
|
|
544
514
|
readonly thrownBy: "service";
|
|
545
515
|
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
|
|
546
516
|
readonly when: "The path contains a `.` or `..` segment, which is rejected to prevent vault escape.";
|
|
@@ -588,6 +558,11 @@ export declare const writeToolDefinitions: (import("@cyanheads/mcp-ts-core").Too
|
|
|
588
558
|
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.Conflict;
|
|
589
559
|
readonly when: "Whole-file write was attempted against an existing note and `overwrite` was not set to `true`.";
|
|
590
560
|
readonly recovery: "Retry with overwrite true or use obsidian_patch_note for in-place edits.";
|
|
561
|
+
}, {
|
|
562
|
+
readonly reason: "case_variant_exists";
|
|
563
|
+
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.Conflict;
|
|
564
|
+
readonly when: "Whole-file write to a path that differs from an existing note only in letter case, on a case-insensitive filesystem (macOS, Windows) where both name one file. `existingPath` names that note when the parent folder listing shows exactly one case match; it is omitted when several match, and when a file Obsidian does not index, such as a dot-file, already sits at the path.";
|
|
565
|
+
readonly recovery: "Retry with the path in `existingPath` on the error data, which names the same file. Without `existingPath`, list the folder with obsidian_list_notes and use the spelling it shows, or choose another path.";
|
|
591
566
|
}, {
|
|
592
567
|
readonly reason: "path_forbidden";
|
|
593
568
|
readonly thrownBy: "service";
|
|
@@ -677,58 +652,45 @@ export declare const writeToolDefinitions: (import("@cyanheads/mcp-ts-core").Too
|
|
|
677
652
|
}>;
|
|
678
653
|
date: import("zod").ZodOptional<import("zod").ZodString>;
|
|
679
654
|
}, import("zod/v4/core").$strip>], "type">;
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
useRegex: import("zod").ZodDefault<import("zod").ZodBoolean>;
|
|
689
|
-
caseSensitive: import("zod").ZodDefault<import("zod").ZodBoolean>;
|
|
690
|
-
wholeWord: import("zod").ZodDefault<import("zod").ZodBoolean>;
|
|
691
|
-
flexibleWhitespace: import("zod").ZodDefault<import("zod").ZodBoolean>;
|
|
692
|
-
replaceAll: import("zod").ZodDefault<import("zod").ZodBoolean>;
|
|
655
|
+
content: import("zod").ZodString;
|
|
656
|
+
section: import("zod").ZodOptional<import("zod").ZodObject<{
|
|
657
|
+
type: import("zod").ZodEnum<{
|
|
658
|
+
block: "block";
|
|
659
|
+
frontmatter: "frontmatter";
|
|
660
|
+
heading: "heading";
|
|
661
|
+
}>;
|
|
662
|
+
target: import("zod").ZodString;
|
|
693
663
|
}, import("zod/v4/core").$strip>>;
|
|
664
|
+
contentType: import("zod").ZodDefault<import("zod").ZodEnum<{
|
|
665
|
+
json: "json";
|
|
666
|
+
markdown: "markdown";
|
|
667
|
+
}>>;
|
|
668
|
+
createTargetIfMissing: import("zod").ZodDefault<import("zod").ZodBoolean>;
|
|
694
669
|
}, import("zod/v4/core").$strip>, import("zod").ZodObject<{
|
|
695
670
|
path: import("zod").ZodString;
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
count: import("zod").ZodNumber;
|
|
700
|
-
bodyCount: import("zod").ZodNumber;
|
|
701
|
-
frontmatterCount: import("zod").ZodNumber;
|
|
702
|
-
}, import("zod/v4/core").$strip>>;
|
|
671
|
+
sectionTargeted: import("zod").ZodBoolean;
|
|
672
|
+
sectionTarget: import("zod").ZodOptional<import("zod").ZodString>;
|
|
673
|
+
created: import("zod").ZodBoolean;
|
|
703
674
|
previousSizeInBytes: import("zod").ZodNumber;
|
|
704
675
|
currentSizeInBytes: import("zod").ZodNumber;
|
|
705
676
|
}, import("zod/v4/core").$strip>, readonly [{
|
|
677
|
+
readonly reason: "case_variant_exists";
|
|
678
|
+
readonly thrownBy: "service";
|
|
679
|
+
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.Conflict;
|
|
680
|
+
readonly when: "Whole-file append to a path that differs from an existing note only in letter case, on a case-insensitive filesystem (macOS, Windows) where both name one file. `existingPath` names that note when the parent folder listing shows exactly one case match; it is omitted when several match, and when a file Obsidian does not index, such as a dot-file, already sits at the path.";
|
|
681
|
+
readonly recovery: "Retry with the path in `existingPath` on the error data, which names the same file. Without `existingPath`, list the folder with obsidian_list_notes and use the spelling it shows, or choose another path.";
|
|
682
|
+
}, {
|
|
706
683
|
readonly reason: "path_forbidden";
|
|
707
684
|
readonly thrownBy: "service";
|
|
708
685
|
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.Forbidden;
|
|
709
|
-
readonly when: "The target path is outside OBSIDIAN_WRITE_PATHS, or OBSIDIAN_READ_ONLY=true denies all writes.
|
|
686
|
+
readonly when: "The target path is outside OBSIDIAN_WRITE_PATHS, or OBSIDIAN_READ_ONLY=true denies all writes.";
|
|
710
687
|
readonly recovery: "Use a path inside the configured write scope. The error data echoes the active scope.";
|
|
711
|
-
}, {
|
|
712
|
-
readonly reason: "regex_invalid";
|
|
713
|
-
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
|
|
714
|
-
readonly when: "A `useRegex: true` replacement supplied a `search` pattern that is not a valid ECMAScript regex.";
|
|
715
|
-
readonly recovery: "Use a valid ECMAScript regex, or set useRegex to false to match `search` as a literal string.";
|
|
716
|
-
}, {
|
|
717
|
-
readonly reason: "regex_unsafe";
|
|
718
|
-
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
|
|
719
|
-
readonly when: "A `useRegex: true` replacement supplied a `search` pattern that is well-formed but exceeds the 1024-character limit or contains nested quantifiers known to cause catastrophic backtracking against the note body.";
|
|
720
|
-
readonly recovery: "Avoid nested quantifiers like `(a+)+` or `(.*)*`. Use a simpler pattern, or set useRegex to false to match `search` as a literal string.";
|
|
721
|
-
}, {
|
|
722
|
-
readonly reason: "frontmatter_invalid";
|
|
723
|
-
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
|
|
724
|
-
readonly when: "A `scope` of \"frontmatter\" or \"both\" produced YAML that no longer parses as a mapping of properties, or that parses but cannot be re-emitted (an alias whose anchor the replacement removed). Nothing is written — the note keeps its original bytes. The check reads the rewritten YAML only, so a replacement that renames a key or changes a scalar's type while still parsing is not caught by it.";
|
|
725
|
-
readonly recovery: "Narrow the search so it cannot match inside the YAML, or leave scope at \"body\" and edit the property with obsidian_manage_frontmatter.";
|
|
726
688
|
}, {
|
|
727
689
|
readonly reason: "note_missing";
|
|
728
690
|
readonly thrownBy: "service";
|
|
729
691
|
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.NotFound;
|
|
730
|
-
readonly when: "
|
|
731
|
-
readonly recovery: "Verify the path with obsidian_list_notes or
|
|
692
|
+
readonly when: "Section append targets a path that does not resolve to an existing note (PATCH requires the file to exist).";
|
|
693
|
+
readonly recovery: "Verify the path with obsidian_list_notes, or omit `section` to fall back to whole-file append (which creates the note if missing).";
|
|
732
694
|
}, {
|
|
733
695
|
readonly reason: "no_active_file";
|
|
734
696
|
readonly thrownBy: "service";
|
|
@@ -753,6 +715,36 @@ export declare const writeToolDefinitions: (import("@cyanheads/mcp-ts-core").Too
|
|
|
753
715
|
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
|
|
754
716
|
readonly when: "Target was `periodic` but the requested period is not enabled in Obsidian's Periodic Notes plugin settings.";
|
|
755
717
|
readonly recovery: "Pass an explicit path target — the requested period is disabled in the operator's Periodic Notes plugin.";
|
|
718
|
+
}, {
|
|
719
|
+
readonly reason: "section_target_missing";
|
|
720
|
+
readonly thrownBy: "service";
|
|
721
|
+
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
|
|
722
|
+
readonly when: "`section` was provided but the named heading/block/frontmatter field does not exist in the note.";
|
|
723
|
+
readonly recovery: "Call obsidian_get_note with format document-map to discover available targets, or pass createTargetIfMissing: true to bring it into existence.";
|
|
724
|
+
}, {
|
|
725
|
+
readonly reason: "ambiguous_section";
|
|
726
|
+
readonly thrownBy: "service";
|
|
727
|
+
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.Conflict;
|
|
728
|
+
readonly when: "A bare heading leaf name matches more than one heading in the note, or the resolved full heading path occurs more than once, so the append target is undetermined.";
|
|
729
|
+
readonly recovery: "Retry with a distinct full Parent::Child heading path from `candidates` on the error data; when every candidate is the same path, rename the repeated headings first.";
|
|
730
|
+
}, {
|
|
731
|
+
readonly reason: "content_preexists";
|
|
732
|
+
readonly thrownBy: "service";
|
|
733
|
+
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
|
|
734
|
+
readonly when: "Section append where the supplied content already appears at the target — rejected to keep retries idempotent (the default for the section path).";
|
|
735
|
+
readonly recovery: "Change the content to something not already present at the target, or use obsidian_patch_note with `patchOptions.applyIfContentPreexists: true` if a duplicate is intended.";
|
|
736
|
+
}, {
|
|
737
|
+
readonly reason: "heading_outside_section";
|
|
738
|
+
readonly thrownBy: "service";
|
|
739
|
+
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
|
|
740
|
+
readonly when: "On Local REST API v5.0 and later, content appended to a heading carries a heading at or above that section’s own level, which would have to sit outside the section.";
|
|
741
|
+
readonly recovery: "Append the heading at the parent section or at the end of the note (no `section`), or write it one level below the target section or deeper.";
|
|
742
|
+
}, {
|
|
743
|
+
readonly reason: "patch_rejected";
|
|
744
|
+
readonly thrownBy: "service";
|
|
745
|
+
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
|
|
746
|
+
readonly when: "The section exists but the plugin refused the content for it — table rows for a block that is not a table, a row with the wrong cell count, a frontmatter value that cannot merge, or content of the wrong shape.";
|
|
747
|
+
readonly recovery: "Read the target with obsidian_get_note format section, then send content that fits it — rows matching the table columns, or a value of the field’s own type.";
|
|
756
748
|
}, {
|
|
757
749
|
readonly reason: "path_is_directory";
|
|
758
750
|
readonly thrownBy: "service";
|
|
@@ -766,11 +758,6 @@ export declare const writeToolDefinitions: (import("@cyanheads/mcp-ts-core").Too
|
|
|
766
758
|
readonly when: "The path contains a `.` or `..` segment, which is rejected to prevent vault escape.";
|
|
767
759
|
readonly recovery: "Supply a vault-relative path with no `.` or `..` segments, e.g. \"Projects/Note.md\". Use obsidian_list_notes to browse the vault.";
|
|
768
760
|
}], undefined> | import("@cyanheads/mcp-ts-core").ToolDefinition<import("zod").ZodObject<{
|
|
769
|
-
operation: import("zod").ZodEnum<{
|
|
770
|
-
delete: "delete";
|
|
771
|
-
get: "get";
|
|
772
|
-
set: "set";
|
|
773
|
-
}>;
|
|
774
761
|
target: import("zod").ZodDiscriminatedUnion<[import("zod").ZodObject<{
|
|
775
762
|
type: import("zod").ZodLiteral<"path">;
|
|
776
763
|
path: import("zod").ZodString;
|
|
@@ -787,46 +774,52 @@ export declare const writeToolDefinitions: (import("@cyanheads/mcp-ts-core").Too
|
|
|
787
774
|
}>;
|
|
788
775
|
date: import("zod").ZodOptional<import("zod").ZodString>;
|
|
789
776
|
}, import("zod/v4/core").$strip>], "type">;
|
|
790
|
-
|
|
791
|
-
|
|
777
|
+
section: import("zod").ZodObject<{
|
|
778
|
+
type: import("zod").ZodEnum<{
|
|
779
|
+
block: "block";
|
|
780
|
+
frontmatter: "frontmatter";
|
|
781
|
+
heading: "heading";
|
|
782
|
+
}>;
|
|
783
|
+
target: import("zod").ZodString;
|
|
784
|
+
}, import("zod/v4/core").$strip>;
|
|
785
|
+
operation: import("zod").ZodEnum<{
|
|
786
|
+
append: "append";
|
|
787
|
+
prepend: "prepend";
|
|
788
|
+
replace: "replace";
|
|
789
|
+
}>;
|
|
790
|
+
content: import("zod").ZodString;
|
|
791
|
+
contentType: import("zod").ZodDefault<import("zod").ZodEnum<{
|
|
792
|
+
json: "json";
|
|
793
|
+
markdown: "markdown";
|
|
794
|
+
}>>;
|
|
795
|
+
patchOptions: import("zod").ZodOptional<import("zod").ZodObject<{
|
|
796
|
+
createTargetIfMissing: import("zod").ZodDefault<import("zod").ZodBoolean>;
|
|
797
|
+
applyIfContentPreexists: import("zod").ZodDefault<import("zod").ZodBoolean>;
|
|
798
|
+
trimTargetWhitespace: import("zod").ZodDefault<import("zod").ZodBoolean>;
|
|
799
|
+
}, import("zod/v4/core").$strip>>;
|
|
792
800
|
}, import("zod/v4/core").$strip>, import("zod").ZodObject<{
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
}
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
key: import("zod").ZodString;
|
|
810
|
-
frontmatter: import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnknown>;
|
|
811
|
-
previousSizeInBytes: import("zod").ZodNumber;
|
|
812
|
-
currentSizeInBytes: import("zod").ZodNumber;
|
|
813
|
-
}, import("zod/v4/core").$strip>], "operation">;
|
|
801
|
+
path: import("zod").ZodString;
|
|
802
|
+
section: import("zod").ZodObject<{
|
|
803
|
+
type: import("zod").ZodEnum<{
|
|
804
|
+
block: "block";
|
|
805
|
+
frontmatter: "frontmatter";
|
|
806
|
+
heading: "heading";
|
|
807
|
+
}>;
|
|
808
|
+
target: import("zod").ZodString;
|
|
809
|
+
}, import("zod/v4/core").$strip>;
|
|
810
|
+
operation: import("zod").ZodEnum<{
|
|
811
|
+
append: "append";
|
|
812
|
+
prepend: "prepend";
|
|
813
|
+
replace: "replace";
|
|
814
|
+
}>;
|
|
815
|
+
previousSizeInBytes: import("zod").ZodNumber;
|
|
816
|
+
currentSizeInBytes: import("zod").ZodNumber;
|
|
814
817
|
}, import("zod/v4/core").$strip>, readonly [{
|
|
815
818
|
readonly reason: "path_forbidden";
|
|
816
819
|
readonly thrownBy: "service";
|
|
817
820
|
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.Forbidden;
|
|
818
|
-
readonly when: "
|
|
819
|
-
readonly recovery: "Use a path inside the configured scope. The error data echoes the active scope.";
|
|
820
|
-
}, {
|
|
821
|
-
readonly reason: "value_required";
|
|
822
|
-
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
|
|
823
|
-
readonly when: "`operation` is \"set\" but no `value` was supplied.";
|
|
824
|
-
readonly recovery: "Pass `value` as any JSON-typed value: string, number, boolean, array, or object (e.g. `\"draft\"`, `42`, `true`, `[\"a\",\"b\"]`).";
|
|
825
|
-
}, {
|
|
826
|
-
readonly reason: "frontmatter_invalid";
|
|
827
|
-
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
|
|
828
|
-
readonly when: "`operation` is \"delete\" and the note's existing frontmatter does not parse as a mapping of properties, or removing the key would leave YAML that cannot be re-emitted (an alias whose anchor went with it). Nothing is written — the note keeps its original bytes.";
|
|
829
|
-
readonly recovery: "Read the block with obsidian_get_note (format \"content\"), repair the YAML between the `---` fences, then retry the delete.";
|
|
821
|
+
readonly when: "The target path is outside OBSIDIAN_WRITE_PATHS, or OBSIDIAN_READ_ONLY=true denies all writes.";
|
|
822
|
+
readonly recovery: "Use a path inside the configured write scope. The error data echoes the active scope.";
|
|
830
823
|
}, {
|
|
831
824
|
readonly reason: "note_missing";
|
|
832
825
|
readonly thrownBy: "service";
|
|
@@ -857,6 +850,36 @@ export declare const writeToolDefinitions: (import("@cyanheads/mcp-ts-core").Too
|
|
|
857
850
|
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
|
|
858
851
|
readonly when: "Target was `periodic` but the requested period is not enabled in Obsidian's Periodic Notes plugin settings.";
|
|
859
852
|
readonly recovery: "Pass an explicit path target — the requested period is disabled in the operator's Periodic Notes plugin.";
|
|
853
|
+
}, {
|
|
854
|
+
readonly reason: "section_target_missing";
|
|
855
|
+
readonly thrownBy: "service";
|
|
856
|
+
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
|
|
857
|
+
readonly when: "The named heading/block/frontmatter field does not exist in the note. Use `obsidian_get_note` with `format: \"document-map\"` to discover available targets.";
|
|
858
|
+
readonly recovery: "Call obsidian_get_note with format document-map to discover the available targets.";
|
|
859
|
+
}, {
|
|
860
|
+
readonly reason: "ambiguous_section";
|
|
861
|
+
readonly thrownBy: "service";
|
|
862
|
+
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.Conflict;
|
|
863
|
+
readonly when: "A bare heading leaf name matches more than one heading in the note, or the resolved full heading path occurs more than once, so the write target is undetermined.";
|
|
864
|
+
readonly recovery: "Retry with a distinct full Parent::Child heading path from `candidates` on the error data; when every candidate is the same path, rename the repeated headings first.";
|
|
865
|
+
}, {
|
|
866
|
+
readonly reason: "content_preexists";
|
|
867
|
+
readonly thrownBy: "service";
|
|
868
|
+
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
|
|
869
|
+
readonly when: "The supplied content already appears at the target — the patch was rejected to keep retries idempotent (the default).";
|
|
870
|
+
readonly recovery: "Pass `patchOptions.applyIfContentPreexists: true` to force-apply over preexisting content, or change the content to something not already present.";
|
|
871
|
+
}, {
|
|
872
|
+
readonly reason: "heading_outside_section";
|
|
873
|
+
readonly thrownBy: "service";
|
|
874
|
+
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
|
|
875
|
+
readonly when: "On Local REST API v5.0 and later, the content of a heading write carries a heading at or above the target section’s own level, which would have to sit outside the section.";
|
|
876
|
+
readonly recovery: "Append the heading at the parent section or at the end of the note with obsidian_append_to_note, or write it one level below the target section or deeper.";
|
|
877
|
+
}, {
|
|
878
|
+
readonly reason: "patch_rejected";
|
|
879
|
+
readonly thrownBy: "service";
|
|
880
|
+
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
|
|
881
|
+
readonly when: "The target exists but the plugin refused the content for it — table rows for a block that is not a table, a row with the wrong cell count, a frontmatter value that cannot merge, or content of the wrong shape.";
|
|
882
|
+
readonly recovery: "Read the target with obsidian_get_note format section, then send content that fits it — rows matching the table columns, or a value of the field’s own type.";
|
|
860
883
|
}, {
|
|
861
884
|
readonly reason: "path_is_directory";
|
|
862
885
|
readonly thrownBy: "service";
|
|
@@ -981,82 +1004,6 @@ export declare const writeToolDefinitions: (import("@cyanheads/mcp-ts-core").Too
|
|
|
981
1004
|
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
|
|
982
1005
|
readonly when: "The path contains a `.` or `..` segment, which is rejected to prevent vault escape.";
|
|
983
1006
|
readonly recovery: "Supply a vault-relative path with no `.` or `..` segments, e.g. \"Projects/Note.md\". Use obsidian_list_notes to browse the vault.";
|
|
984
|
-
}], undefined> | import("@cyanheads/mcp-ts-core").ToolDefinition<import("zod").ZodObject<{
|
|
985
|
-
target: import("zod").ZodDiscriminatedUnion<[import("zod").ZodObject<{
|
|
986
|
-
type: import("zod").ZodLiteral<"path">;
|
|
987
|
-
path: import("zod").ZodString;
|
|
988
|
-
}, import("zod/v4/core").$strip>, import("zod").ZodObject<{
|
|
989
|
-
type: import("zod").ZodLiteral<"active">;
|
|
990
|
-
}, import("zod/v4/core").$strip>, import("zod").ZodObject<{
|
|
991
|
-
type: import("zod").ZodLiteral<"periodic">;
|
|
992
|
-
period: import("zod").ZodEnum<{
|
|
993
|
-
daily: "daily";
|
|
994
|
-
monthly: "monthly";
|
|
995
|
-
quarterly: "quarterly";
|
|
996
|
-
weekly: "weekly";
|
|
997
|
-
yearly: "yearly";
|
|
998
|
-
}>;
|
|
999
|
-
date: import("zod").ZodOptional<import("zod").ZodString>;
|
|
1000
|
-
}, import("zod/v4/core").$strip>], "type">;
|
|
1001
|
-
}, import("zod/v4/core").$strip>, import("zod").ZodObject<{
|
|
1002
|
-
path: import("zod").ZodString;
|
|
1003
|
-
deleted: import("zod").ZodBoolean;
|
|
1004
|
-
previousSizeInBytes: import("zod").ZodNumber;
|
|
1005
|
-
currentSizeInBytes: import("zod").ZodNumber;
|
|
1006
|
-
}, import("zod/v4/core").$strip>, readonly [{
|
|
1007
|
-
readonly reason: "path_forbidden";
|
|
1008
|
-
readonly thrownBy: "service";
|
|
1009
|
-
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.Forbidden;
|
|
1010
|
-
readonly when: "The target path is outside OBSIDIAN_WRITE_PATHS, or OBSIDIAN_READ_ONLY=true denies all writes.";
|
|
1011
|
-
readonly recovery: "Use a path inside the configured write scope. The error data echoes the active scope.";
|
|
1012
|
-
}, {
|
|
1013
|
-
readonly reason: "cancelled";
|
|
1014
|
-
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.InvalidRequest;
|
|
1015
|
-
readonly when: "User declined, cancelled, or answered false to the confirmation request.";
|
|
1016
|
-
readonly severity: "notice";
|
|
1017
|
-
readonly recovery: "Re-run the tool when the user is ready to confirm deletion.";
|
|
1018
|
-
}, {
|
|
1019
|
-
readonly reason: "note_missing";
|
|
1020
|
-
readonly thrownBy: "service";
|
|
1021
|
-
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.NotFound;
|
|
1022
|
-
readonly when: "The vault path does not resolve to an existing note.";
|
|
1023
|
-
readonly recovery: "Verify the path with obsidian_list_notes or use obsidian_search_notes to locate the note.";
|
|
1024
|
-
}, {
|
|
1025
|
-
readonly reason: "no_active_file";
|
|
1026
|
-
readonly thrownBy: "service";
|
|
1027
|
-
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.NotFound;
|
|
1028
|
-
readonly when: "Target was `active` but no file is currently open in Obsidian.";
|
|
1029
|
-
readonly recovery: "Call obsidian_open_in_ui to focus a file, or pass an explicit path target instead.";
|
|
1030
|
-
}, {
|
|
1031
|
-
readonly reason: "periodic_unsupported";
|
|
1032
|
-
readonly thrownBy: "service";
|
|
1033
|
-
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.NotFound;
|
|
1034
|
-
readonly when: "Target was `periodic` and this vault runs Local REST API v5.0.2 or later without the companion periodic-notes extension, so the `/periodic/` routes are not served at all.";
|
|
1035
|
-
readonly recovery: "Install the periodic-notes extension from https://github.com/coddingtonbear/obsidian-local-rest-api-periodic-notes, or address the note by an explicit vault path.";
|
|
1036
|
-
}, {
|
|
1037
|
-
readonly reason: "periodic_not_found";
|
|
1038
|
-
readonly thrownBy: "service";
|
|
1039
|
-
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.NotFound;
|
|
1040
|
-
readonly when: "Target was `periodic`, the `/periodic/` routes are served on this vault, and no note exists for the requested period.";
|
|
1041
|
-
readonly recovery: "Pass an explicit path target — periodic notes must already exist.";
|
|
1042
|
-
}, {
|
|
1043
|
-
readonly reason: "periodic_disabled";
|
|
1044
|
-
readonly thrownBy: "service";
|
|
1045
|
-
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
|
|
1046
|
-
readonly when: "Target was `periodic` but the requested period is not enabled in Obsidian's Periodic Notes plugin settings.";
|
|
1047
|
-
readonly recovery: "Pass an explicit path target — the requested period is disabled in the operator's Periodic Notes plugin.";
|
|
1048
|
-
}, {
|
|
1049
|
-
readonly reason: "path_is_directory";
|
|
1050
|
-
readonly thrownBy: "service";
|
|
1051
|
-
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
|
|
1052
|
-
readonly when: "The supplied path names a folder rather than a note file. Deleting a folder is not offered — the upstream removes it and everything inside it in one unrecoverable step.";
|
|
1053
|
-
readonly recovery: "Call obsidian_list_notes with this path to list the folder, then delete files one at a time by their full paths.";
|
|
1054
|
-
}, {
|
|
1055
|
-
readonly reason: "path_traversal";
|
|
1056
|
-
readonly thrownBy: "service";
|
|
1057
|
-
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
|
|
1058
|
-
readonly when: "The path contains a `.` or `..` segment, which is rejected to prevent vault escape.";
|
|
1059
|
-
readonly recovery: "Supply a vault-relative path with no `.` or `..` segments, e.g. \"Projects/Note.md\". Use obsidian_list_notes to browse the vault.";
|
|
1060
1007
|
}], undefined>)[];
|
|
1061
1008
|
/** Command-palette tools — opt-in via `OBSIDIAN_ENABLE_COMMANDS=true`; suppressed by `OBSIDIAN_READ_ONLY=true`. */
|
|
1062
1009
|
export declare const commandToolDefinitions: (import("@cyanheads/mcp-ts-core").ToolDefinition<import("zod").ZodObject<{
|