obsidian-mcp-server 3.6.1 → 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.
Files changed (63) hide show
  1. package/AGENTS.md +27 -17
  2. package/CLAUDE.md +27 -17
  3. package/README.md +22 -13
  4. package/changelog/3.7.x/3.7.0.md +34 -0
  5. package/dist/config/server-config.d.ts +1 -0
  6. package/dist/config/server-config.d.ts.map +1 -1
  7. package/dist/config/server-config.js +4 -0
  8. package/dist/config/server-config.js.map +1 -1
  9. package/dist/index.js +28 -9
  10. package/dist/index.js.map +1 -1
  11. package/dist/mcp-server/resources/definitions/obsidian-tags.resource.d.ts +7 -5
  12. package/dist/mcp-server/resources/definitions/obsidian-tags.resource.d.ts.map +1 -1
  13. package/dist/mcp-server/resources/definitions/obsidian-tags.resource.js +12 -8
  14. package/dist/mcp-server/resources/definitions/obsidian-tags.resource.js.map +1 -1
  15. package/dist/mcp-server/tools/definitions/_shared/suggest-paths.d.ts +30 -9
  16. package/dist/mcp-server/tools/definitions/_shared/suggest-paths.d.ts.map +1 -1
  17. package/dist/mcp-server/tools/definitions/_shared/suggest-paths.js +28 -6
  18. package/dist/mcp-server/tools/definitions/_shared/suggest-paths.js.map +1 -1
  19. package/dist/mcp-server/tools/definitions/index.d.ts +230 -294
  20. package/dist/mcp-server/tools/definitions/index.d.ts.map +1 -1
  21. package/dist/mcp-server/tools/definitions/index.js +9 -3
  22. package/dist/mcp-server/tools/definitions/index.js.map +1 -1
  23. package/dist/mcp-server/tools/definitions/obsidian-delete-note.tool.d.ts +107 -10
  24. package/dist/mcp-server/tools/definitions/obsidian-delete-note.tool.d.ts.map +1 -1
  25. package/dist/mcp-server/tools/definitions/obsidian-delete-note.tool.js +237 -162
  26. package/dist/mcp-server/tools/definitions/obsidian-delete-note.tool.js.map +1 -1
  27. package/dist/mcp-server/tools/definitions/obsidian-get-note.tool.d.ts +1 -0
  28. package/dist/mcp-server/tools/definitions/obsidian-get-note.tool.d.ts.map +1 -1
  29. package/dist/mcp-server/tools/definitions/obsidian-get-note.tool.js +61 -19
  30. package/dist/mcp-server/tools/definitions/obsidian-get-note.tool.js.map +1 -1
  31. package/dist/mcp-server/tools/definitions/obsidian-list-notes.tool.d.ts +6 -1
  32. package/dist/mcp-server/tools/definitions/obsidian-list-notes.tool.d.ts.map +1 -1
  33. package/dist/mcp-server/tools/definitions/obsidian-list-notes.tool.js +8 -10
  34. package/dist/mcp-server/tools/definitions/obsidian-list-notes.tool.js.map +1 -1
  35. package/dist/mcp-server/tools/definitions/obsidian-list-tags.tool.d.ts +7 -5
  36. package/dist/mcp-server/tools/definitions/obsidian-list-tags.tool.d.ts.map +1 -1
  37. package/dist/mcp-server/tools/definitions/obsidian-list-tags.tool.js +13 -7
  38. package/dist/mcp-server/tools/definitions/obsidian-list-tags.tool.js.map +1 -1
  39. package/dist/mcp-server/tools/definitions/obsidian-open-in-ui.tool.d.ts +4 -1
  40. package/dist/mcp-server/tools/definitions/obsidian-open-in-ui.tool.d.ts.map +1 -1
  41. package/dist/mcp-server/tools/definitions/obsidian-open-in-ui.tool.js +15 -4
  42. package/dist/mcp-server/tools/definitions/obsidian-open-in-ui.tool.js.map +1 -1
  43. package/dist/mcp-server/tools/definitions/obsidian-search-notes.tool.js +1 -1
  44. package/dist/mcp-server/tools/definitions/obsidian-search-notes.tool.js.map +1 -1
  45. package/dist/services/obsidian/obsidian-service.d.ts +7 -0
  46. package/dist/services/obsidian/obsidian-service.d.ts.map +1 -1
  47. package/dist/services/obsidian/obsidian-service.js +57 -15
  48. package/dist/services/obsidian/obsidian-service.js.map +1 -1
  49. package/dist/services/obsidian/patch-instruction.d.ts +20 -1
  50. package/dist/services/obsidian/patch-instruction.d.ts.map +1 -1
  51. package/dist/services/obsidian/patch-instruction.js +30 -0
  52. package/dist/services/obsidian/patch-instruction.js.map +1 -1
  53. package/dist/services/obsidian/path-policy.d.ts +23 -1
  54. package/dist/services/obsidian/path-policy.d.ts.map +1 -1
  55. package/dist/services/obsidian/path-policy.js +45 -3
  56. package/dist/services/obsidian/path-policy.js.map +1 -1
  57. package/dist/services/obsidian/section-extractor.d.ts +24 -0
  58. package/dist/services/obsidian/section-extractor.d.ts.map +1 -1
  59. package/dist/services/obsidian/section-extractor.js +37 -0
  60. package/dist/services/obsidian/section-extractor.js.map +1 -1
  61. package/manifest.json +9 -1
  62. package/package.json +2 -2
  63. package/server.json +17 -3
@@ -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 (root listings always pass; specific subdirectories must be readable).";
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,8 +297,15 @@ 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
- }], undefined>)[];
296
- /** Write tools — wrapped with `disabledTool()` when `OBSIDIAN_READ_ONLY=true`. */
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<{
298
310
  target: import("zod").ZodDiscriminatedUnion<[import("zod").ZodObject<{
299
311
  type: import("zod").ZodLiteral<"path">;
@@ -411,6 +423,11 @@ export declare const writeToolDefinitions: (import("@cyanheads/mcp-ts-core").Too
411
423
  readonly when: "The path contains a `.` or `..` segment, which is rejected to prevent vault escape.";
412
424
  readonly recovery: "Supply a vault-relative path with no `.` or `..` segments, e.g. \"Projects/Note.md\". Use obsidian_list_notes to browse the vault.";
413
425
  }], undefined> | import("@cyanheads/mcp-ts-core").ToolDefinition<import("zod").ZodObject<{
426
+ operation: import("zod").ZodEnum<{
427
+ delete: "delete";
428
+ get: "get";
429
+ set: "set";
430
+ }>;
414
431
  target: import("zod").ZodDiscriminatedUnion<[import("zod").ZodObject<{
415
432
  type: import("zod").ZodLiteral<"path">;
416
433
  path: import("zod").ZodString;
@@ -427,52 +444,46 @@ export declare const writeToolDefinitions: (import("@cyanheads/mcp-ts-core").Too
427
444
  }>;
428
445
  date: import("zod").ZodOptional<import("zod").ZodString>;
429
446
  }, import("zod/v4/core").$strip>], "type">;
430
- section: import("zod").ZodObject<{
431
- type: import("zod").ZodEnum<{
432
- block: "block";
433
- frontmatter: "frontmatter";
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";
447
- }>>;
448
- patchOptions: import("zod").ZodOptional<import("zod").ZodObject<{
449
- createTargetIfMissing: import("zod").ZodDefault<import("zod").ZodBoolean>;
450
- applyIfContentPreexists: import("zod").ZodDefault<import("zod").ZodBoolean>;
451
- trimTargetWhitespace: import("zod").ZodDefault<import("zod").ZodBoolean>;
452
- }, import("zod/v4/core").$strip>>;
447
+ key: import("zod").ZodString;
448
+ value: import("zod").ZodOptional<import("zod").ZodUnknown>;
453
449
  }, import("zod/v4/core").$strip>, import("zod").ZodObject<{
454
- path: import("zod").ZodString;
455
- section: import("zod").ZodObject<{
456
- type: import("zod").ZodEnum<{
457
- block: "block";
458
- frontmatter: "frontmatter";
459
- heading: "heading";
460
- }>;
461
- target: import("zod").ZodString;
462
- }, import("zod/v4/core").$strip>;
463
- operation: import("zod").ZodEnum<{
464
- append: "append";
465
- prepend: "prepend";
466
- replace: "replace";
467
- }>;
468
- previousSizeInBytes: import("zod").ZodNumber;
469
- currentSizeInBytes: import("zod").ZodNumber;
450
+ result: import("zod").ZodDiscriminatedUnion<[import("zod").ZodObject<{
451
+ operation: import("zod").ZodLiteral<"get">;
452
+ path: import("zod").ZodString;
453
+ key: import("zod").ZodString;
454
+ exists: import("zod").ZodBoolean;
455
+ value: import("zod").ZodUnknown;
456
+ }, import("zod/v4/core").$strip>, import("zod").ZodObject<{
457
+ operation: import("zod").ZodLiteral<"set">;
458
+ path: import("zod").ZodString;
459
+ key: import("zod").ZodString;
460
+ frontmatter: import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnknown>;
461
+ previousSizeInBytes: import("zod").ZodNumber;
462
+ currentSizeInBytes: import("zod").ZodNumber;
463
+ }, import("zod/v4/core").$strip>, import("zod").ZodObject<{
464
+ operation: import("zod").ZodLiteral<"delete">;
465
+ path: import("zod").ZodString;
466
+ key: import("zod").ZodString;
467
+ frontmatter: import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnknown>;
468
+ previousSizeInBytes: import("zod").ZodNumber;
469
+ currentSizeInBytes: import("zod").ZodNumber;
470
+ }, import("zod/v4/core").$strip>], "operation">;
470
471
  }, import("zod/v4/core").$strip>, readonly [{
471
472
  readonly reason: "path_forbidden";
472
473
  readonly thrownBy: "service";
473
474
  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.";
475
- readonly recovery: "Use a path inside the configured write scope. The error data echoes the active scope.";
475
+ readonly when: "`get` requires the path to be readable; `set`/`delete` require it to be inside OBSIDIAN_WRITE_PATHS, with OBSIDIAN_READ_ONLY=false.";
476
+ readonly recovery: "Use a path inside the configured scope. The error data echoes the active scope.";
477
+ }, {
478
+ readonly reason: "value_required";
479
+ readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
480
+ readonly when: "`operation` is \"set\" but no `value` was supplied.";
481
+ readonly recovery: "Pass `value` as any JSON-typed value: string, number, boolean, array, or object (e.g. `\"draft\"`, `42`, `true`, `[\"a\",\"b\"]`).";
482
+ }, {
483
+ readonly reason: "frontmatter_invalid";
484
+ readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
485
+ 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.";
486
+ readonly recovery: "Read the block with obsidian_get_note (format \"content\"), repair the YAML between the `---` fences, then retry the delete.";
476
487
  }, {
477
488
  readonly reason: "note_missing";
478
489
  readonly thrownBy: "service";
@@ -504,35 +515,110 @@ export declare const writeToolDefinitions: (import("@cyanheads/mcp-ts-core").Too
504
515
  readonly when: "Target was `periodic` but the requested period is not enabled in Obsidian's Periodic Notes plugin settings.";
505
516
  readonly recovery: "Pass an explicit path target — the requested period is disabled in the operator's Periodic Notes plugin.";
506
517
  }, {
507
- readonly reason: "section_target_missing";
518
+ readonly reason: "path_is_directory";
508
519
  readonly thrownBy: "service";
509
520
  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.";
521
+ readonly when: "The supplied path names a folder rather than a note file.";
522
+ 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.";
512
523
  }, {
513
- readonly reason: "ambiguous_section";
524
+ readonly reason: "path_traversal";
514
525
  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";
526
+ readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
527
+ readonly when: "The path contains a `.` or `..` segment, which is rejected to prevent vault escape.";
528
+ readonly recovery: "Supply a vault-relative path with no `.` or `..` segments, e.g. \"Projects/Note.md\". Use obsidian_list_notes to browse the vault.";
529
+ }], undefined> | import("@cyanheads/mcp-ts-core").ToolDefinition<import("zod").ZodObject<{
530
+ target: import("zod").ZodDiscriminatedUnion<[import("zod").ZodObject<{
531
+ type: import("zod").ZodLiteral<"path">;
532
+ path: import("zod").ZodString;
533
+ }, import("zod/v4/core").$strip>, import("zod").ZodObject<{
534
+ type: import("zod").ZodLiteral<"active">;
535
+ }, import("zod/v4/core").$strip>, import("zod").ZodObject<{
536
+ type: import("zod").ZodLiteral<"periodic">;
537
+ period: import("zod").ZodEnum<{
538
+ daily: "daily";
539
+ monthly: "monthly";
540
+ quarterly: "quarterly";
541
+ weekly: "weekly";
542
+ yearly: "yearly";
543
+ }>;
544
+ date: import("zod").ZodOptional<import("zod").ZodString>;
545
+ }, import("zod/v4/core").$strip>], "type">;
546
+ scope: import("zod").ZodDefault<import("zod").ZodEnum<{
547
+ body: "body";
548
+ both: "both";
549
+ frontmatter: "frontmatter";
550
+ }>>;
551
+ replacements: import("zod").ZodArray<import("zod").ZodObject<{
552
+ search: import("zod").ZodString;
553
+ replace: import("zod").ZodString;
554
+ useRegex: import("zod").ZodDefault<import("zod").ZodBoolean>;
555
+ caseSensitive: import("zod").ZodDefault<import("zod").ZodBoolean>;
556
+ wholeWord: import("zod").ZodDefault<import("zod").ZodBoolean>;
557
+ flexibleWhitespace: import("zod").ZodDefault<import("zod").ZodBoolean>;
558
+ replaceAll: import("zod").ZodDefault<import("zod").ZodBoolean>;
559
+ }, import("zod/v4/core").$strip>>;
560
+ }, import("zod/v4/core").$strip>, import("zod").ZodObject<{
561
+ path: import("zod").ZodString;
562
+ totalReplacements: import("zod").ZodNumber;
563
+ perReplacement: import("zod").ZodArray<import("zod").ZodObject<{
564
+ search: import("zod").ZodString;
565
+ count: import("zod").ZodNumber;
566
+ bodyCount: import("zod").ZodNumber;
567
+ frontmatterCount: import("zod").ZodNumber;
568
+ }, import("zod/v4/core").$strip>>;
569
+ previousSizeInBytes: import("zod").ZodNumber;
570
+ currentSizeInBytes: import("zod").ZodNumber;
571
+ }, import("zod/v4/core").$strip>, readonly [{
572
+ readonly reason: "path_forbidden";
520
573
  readonly thrownBy: "service";
574
+ readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.Forbidden;
575
+ 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.";
576
+ readonly recovery: "Use a path inside the configured write scope. The error data echoes the active scope.";
577
+ }, {
578
+ readonly reason: "regex_invalid";
521
579
  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.";
580
+ readonly when: "A `useRegex: true` replacement supplied a `search` pattern that is not a valid ECMAScript regex.";
581
+ readonly recovery: "Use a valid ECMAScript regex, or set useRegex to false to match `search` as a literal string.";
524
582
  }, {
525
- readonly reason: "heading_outside_section";
526
- readonly thrownBy: "service";
583
+ readonly reason: "regex_unsafe";
527
584
  readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
528
- 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.";
529
- 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.";
585
+ 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.";
586
+ readonly recovery: "Avoid nested quantifiers like `(a+)+` or `(.*)*`. Use a simpler pattern, or set useRegex to false to match `search` as a literal string.";
530
587
  }, {
531
- readonly reason: "patch_rejected";
588
+ readonly reason: "frontmatter_invalid";
589
+ readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
590
+ 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.";
591
+ 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.";
592
+ }, {
593
+ readonly reason: "note_missing";
594
+ readonly thrownBy: "service";
595
+ readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.NotFound;
596
+ readonly when: "The vault path does not resolve to an existing note.";
597
+ readonly recovery: "Verify the path with obsidian_list_notes or use obsidian_search_notes to locate the note.";
598
+ }, {
599
+ readonly reason: "no_active_file";
600
+ readonly thrownBy: "service";
601
+ readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.NotFound;
602
+ readonly when: "Target was `active` but no file is currently open in Obsidian.";
603
+ readonly recovery: "Call obsidian_open_in_ui to focus a file, or pass an explicit path target instead.";
604
+ }, {
605
+ readonly reason: "periodic_unsupported";
606
+ readonly thrownBy: "service";
607
+ readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.NotFound;
608
+ 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.";
609
+ 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.";
610
+ }, {
611
+ readonly reason: "periodic_not_found";
612
+ readonly thrownBy: "service";
613
+ readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.NotFound;
614
+ readonly when: "Target was `periodic`, the `/periodic/` routes are served on this vault, and no note exists for the requested period.";
615
+ readonly recovery: "Create the periodic note first or pass an explicit path target.";
616
+ }, {
617
+ readonly reason: "periodic_disabled";
532
618
  readonly thrownBy: "service";
533
619
  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.";
620
+ readonly when: "Target was `periodic` but the requested period is not enabled in Obsidian's Periodic Notes plugin settings.";
621
+ readonly recovery: "Pass an explicit path target — the requested period is disabled in the operator's Periodic Notes plugin.";
536
622
  }, {
537
623
  readonly reason: "path_is_directory";
538
624
  readonly thrownBy: "service";
@@ -677,52 +763,52 @@ export declare const writeToolDefinitions: (import("@cyanheads/mcp-ts-core").Too
677
763
  }>;
678
764
  date: import("zod").ZodOptional<import("zod").ZodString>;
679
765
  }, import("zod/v4/core").$strip>], "type">;
680
- scope: import("zod").ZodDefault<import("zod").ZodEnum<{
681
- body: "body";
682
- both: "both";
683
- frontmatter: "frontmatter";
766
+ section: import("zod").ZodObject<{
767
+ type: import("zod").ZodEnum<{
768
+ block: "block";
769
+ frontmatter: "frontmatter";
770
+ heading: "heading";
771
+ }>;
772
+ target: import("zod").ZodString;
773
+ }, import("zod/v4/core").$strip>;
774
+ operation: import("zod").ZodEnum<{
775
+ append: "append";
776
+ prepend: "prepend";
777
+ replace: "replace";
778
+ }>;
779
+ content: import("zod").ZodString;
780
+ contentType: import("zod").ZodDefault<import("zod").ZodEnum<{
781
+ json: "json";
782
+ markdown: "markdown";
684
783
  }>>;
685
- replacements: import("zod").ZodArray<import("zod").ZodObject<{
686
- search: import("zod").ZodString;
687
- replace: import("zod").ZodString;
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>;
784
+ patchOptions: import("zod").ZodOptional<import("zod").ZodObject<{
785
+ createTargetIfMissing: import("zod").ZodDefault<import("zod").ZodBoolean>;
786
+ applyIfContentPreexists: import("zod").ZodDefault<import("zod").ZodBoolean>;
787
+ trimTargetWhitespace: import("zod").ZodDefault<import("zod").ZodBoolean>;
693
788
  }, import("zod/v4/core").$strip>>;
694
789
  }, import("zod/v4/core").$strip>, import("zod").ZodObject<{
695
790
  path: import("zod").ZodString;
696
- totalReplacements: import("zod").ZodNumber;
697
- perReplacement: import("zod").ZodArray<import("zod").ZodObject<{
698
- search: import("zod").ZodString;
699
- count: import("zod").ZodNumber;
700
- bodyCount: import("zod").ZodNumber;
701
- frontmatterCount: import("zod").ZodNumber;
702
- }, import("zod/v4/core").$strip>>;
791
+ section: import("zod").ZodObject<{
792
+ type: import("zod").ZodEnum<{
793
+ block: "block";
794
+ frontmatter: "frontmatter";
795
+ heading: "heading";
796
+ }>;
797
+ target: import("zod").ZodString;
798
+ }, import("zod/v4/core").$strip>;
799
+ operation: import("zod").ZodEnum<{
800
+ append: "append";
801
+ prepend: "prepend";
802
+ replace: "replace";
803
+ }>;
703
804
  previousSizeInBytes: import("zod").ZodNumber;
704
805
  currentSizeInBytes: import("zod").ZodNumber;
705
806
  }, import("zod/v4/core").$strip>, readonly [{
706
807
  readonly reason: "path_forbidden";
707
808
  readonly thrownBy: "service";
708
809
  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. The pre-read also requires the path to be readable.";
810
+ readonly when: "The target path is outside OBSIDIAN_WRITE_PATHS, or OBSIDIAN_READ_ONLY=true denies all writes.";
710
811
  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
812
  }, {
727
813
  readonly reason: "note_missing";
728
814
  readonly thrownBy: "service";
@@ -754,109 +840,35 @@ export declare const writeToolDefinitions: (import("@cyanheads/mcp-ts-core").Too
754
840
  readonly when: "Target was `periodic` but the requested period is not enabled in Obsidian's Periodic Notes plugin settings.";
755
841
  readonly recovery: "Pass an explicit path target — the requested period is disabled in the operator's Periodic Notes plugin.";
756
842
  }, {
757
- readonly reason: "path_is_directory";
758
- readonly thrownBy: "service";
759
- readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
760
- readonly when: "The supplied path names a folder rather than a note file.";
761
- 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.";
762
- }, {
763
- readonly reason: "path_traversal";
764
- readonly thrownBy: "service";
765
- readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
766
- readonly when: "The path contains a `.` or `..` segment, which is rejected to prevent vault escape.";
767
- 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
- }], 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
- target: import("zod").ZodDiscriminatedUnion<[import("zod").ZodObject<{
775
- type: import("zod").ZodLiteral<"path">;
776
- path: import("zod").ZodString;
777
- }, import("zod/v4/core").$strip>, import("zod").ZodObject<{
778
- type: import("zod").ZodLiteral<"active">;
779
- }, import("zod/v4/core").$strip>, import("zod").ZodObject<{
780
- type: import("zod").ZodLiteral<"periodic">;
781
- period: import("zod").ZodEnum<{
782
- daily: "daily";
783
- monthly: "monthly";
784
- quarterly: "quarterly";
785
- weekly: "weekly";
786
- yearly: "yearly";
787
- }>;
788
- date: import("zod").ZodOptional<import("zod").ZodString>;
789
- }, import("zod/v4/core").$strip>], "type">;
790
- key: import("zod").ZodString;
791
- value: import("zod").ZodOptional<import("zod").ZodUnknown>;
792
- }, import("zod/v4/core").$strip>, import("zod").ZodObject<{
793
- result: import("zod").ZodDiscriminatedUnion<[import("zod").ZodObject<{
794
- operation: import("zod").ZodLiteral<"get">;
795
- path: import("zod").ZodString;
796
- key: import("zod").ZodString;
797
- exists: import("zod").ZodBoolean;
798
- value: import("zod").ZodUnknown;
799
- }, import("zod/v4/core").$strip>, import("zod").ZodObject<{
800
- operation: import("zod").ZodLiteral<"set">;
801
- path: import("zod").ZodString;
802
- key: import("zod").ZodString;
803
- frontmatter: import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnknown>;
804
- previousSizeInBytes: import("zod").ZodNumber;
805
- currentSizeInBytes: import("zod").ZodNumber;
806
- }, import("zod/v4/core").$strip>, import("zod").ZodObject<{
807
- operation: import("zod").ZodLiteral<"delete">;
808
- path: import("zod").ZodString;
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">;
814
- }, import("zod/v4/core").$strip>, readonly [{
815
- readonly reason: "path_forbidden";
843
+ readonly reason: "section_target_missing";
816
844
  readonly thrownBy: "service";
817
- readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.Forbidden;
818
- readonly when: "`get` requires the path to be readable; `set`/`delete` require it to be inside OBSIDIAN_WRITE_PATHS, with OBSIDIAN_READ_ONLY=false.";
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
845
  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.";
830
- }, {
831
- readonly reason: "note_missing";
832
- readonly thrownBy: "service";
833
- readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.NotFound;
834
- readonly when: "The vault path does not resolve to an existing note.";
835
- readonly recovery: "Verify the path with obsidian_list_notes or use obsidian_search_notes to locate the note.";
846
+ 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.";
847
+ readonly recovery: "Call obsidian_get_note with format document-map to discover the available targets.";
836
848
  }, {
837
- readonly reason: "no_active_file";
849
+ readonly reason: "ambiguous_section";
838
850
  readonly thrownBy: "service";
839
- readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.NotFound;
840
- readonly when: "Target was `active` but no file is currently open in Obsidian.";
841
- readonly recovery: "Call obsidian_open_in_ui to focus a file, or pass an explicit path target instead.";
851
+ readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.Conflict;
852
+ 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.";
853
+ 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.";
842
854
  }, {
843
- readonly reason: "periodic_unsupported";
855
+ readonly reason: "content_preexists";
844
856
  readonly thrownBy: "service";
845
- readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.NotFound;
846
- 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.";
847
- 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.";
857
+ readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
858
+ readonly when: "The supplied content already appears at the target — the patch was rejected to keep retries idempotent (the default).";
859
+ readonly recovery: "Pass `patchOptions.applyIfContentPreexists: true` to force-apply over preexisting content, or change the content to something not already present.";
848
860
  }, {
849
- readonly reason: "periodic_not_found";
861
+ readonly reason: "heading_outside_section";
850
862
  readonly thrownBy: "service";
851
- readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.NotFound;
852
- readonly when: "Target was `periodic`, the `/periodic/` routes are served on this vault, and no note exists for the requested period.";
853
- readonly recovery: "Create the periodic note first or pass an explicit path target.";
863
+ readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
864
+ 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.";
865
+ 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.";
854
866
  }, {
855
- readonly reason: "periodic_disabled";
867
+ readonly reason: "patch_rejected";
856
868
  readonly thrownBy: "service";
857
869
  readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
858
- readonly when: "Target was `periodic` but the requested period is not enabled in Obsidian's Periodic Notes plugin settings.";
859
- readonly recovery: "Pass an explicit path target — the requested period is disabled in the operator's Periodic Notes plugin.";
870
+ 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.";
871
+ 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
872
  }, {
861
873
  readonly reason: "path_is_directory";
862
874
  readonly thrownBy: "service";
@@ -981,82 +993,6 @@ export declare const writeToolDefinitions: (import("@cyanheads/mcp-ts-core").Too
981
993
  readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
982
994
  readonly when: "The path contains a `.` or `..` segment, which is rejected to prevent vault escape.";
983
995
  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
996
  }], undefined>)[];
1061
997
  /** Command-palette tools — opt-in via `OBSIDIAN_ENABLE_COMMANDS=true`; suppressed by `OBSIDIAN_READ_ONLY=true`. */
1062
998
  export declare const commandToolDefinitions: (import("@cyanheads/mcp-ts-core").ToolDefinition<import("zod").ZodObject<{