obsidian-mcp-server 3.2.9 → 3.2.11

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 (69) hide show
  1. package/AGENTS.md +19 -12
  2. package/CLAUDE.md +19 -12
  3. package/Dockerfile +11 -7
  4. package/README.md +6 -3
  5. package/changelog/3.2.x/3.2.10.md +47 -0
  6. package/changelog/3.2.x/3.2.11.md +29 -0
  7. package/changelog/template.md +5 -3
  8. package/dist/index.js +1 -1
  9. package/dist/index.js.map +1 -1
  10. package/dist/mcp-server/resources/definitions/index.d.ts +25 -20
  11. package/dist/mcp-server/resources/definitions/index.d.ts.map +1 -1
  12. package/dist/mcp-server/resources/definitions/obsidian-vault-note.resource.d.ts +5 -0
  13. package/dist/mcp-server/resources/definitions/obsidian-vault-note.resource.d.ts.map +1 -1
  14. package/dist/mcp-server/resources/definitions/obsidian-vault-note.resource.js +6 -0
  15. package/dist/mcp-server/resources/definitions/obsidian-vault-note.resource.js.map +1 -1
  16. package/dist/mcp-server/tools/definitions/_shared/schemas.d.ts +3 -3
  17. package/dist/mcp-server/tools/definitions/_shared/schemas.js +1 -1
  18. package/dist/mcp-server/tools/definitions/_shared/schemas.js.map +1 -1
  19. package/dist/mcp-server/tools/definitions/index.d.ts +333 -219
  20. package/dist/mcp-server/tools/definitions/index.d.ts.map +1 -1
  21. package/dist/mcp-server/tools/definitions/index.js +11 -4
  22. package/dist/mcp-server/tools/definitions/index.js.map +1 -1
  23. package/dist/mcp-server/tools/definitions/obsidian-append-to-note.tool.d.ts +19 -3
  24. package/dist/mcp-server/tools/definitions/obsidian-append-to-note.tool.d.ts.map +1 -1
  25. package/dist/mcp-server/tools/definitions/obsidian-append-to-note.tool.js +26 -3
  26. package/dist/mcp-server/tools/definitions/obsidian-append-to-note.tool.js.map +1 -1
  27. package/dist/mcp-server/tools/definitions/obsidian-delete-note.tool.d.ts +11 -1
  28. package/dist/mcp-server/tools/definitions/obsidian-delete-note.tool.d.ts.map +1 -1
  29. package/dist/mcp-server/tools/definitions/obsidian-delete-note.tool.js +12 -0
  30. package/dist/mcp-server/tools/definitions/obsidian-delete-note.tool.js.map +1 -1
  31. package/dist/mcp-server/tools/definitions/obsidian-get-note.tool.d.ts +16 -6
  32. package/dist/mcp-server/tools/definitions/obsidian-get-note.tool.d.ts.map +1 -1
  33. package/dist/mcp-server/tools/definitions/obsidian-get-note.tool.js +13 -1
  34. package/dist/mcp-server/tools/definitions/obsidian-get-note.tool.js.map +1 -1
  35. package/dist/mcp-server/tools/definitions/obsidian-list-notes.tool.d.ts +1 -1
  36. package/dist/mcp-server/tools/definitions/obsidian-manage-frontmatter.tool.d.ts +12 -2
  37. package/dist/mcp-server/tools/definitions/obsidian-manage-frontmatter.tool.d.ts.map +1 -1
  38. package/dist/mcp-server/tools/definitions/obsidian-manage-frontmatter.tool.js +12 -0
  39. package/dist/mcp-server/tools/definitions/obsidian-manage-frontmatter.tool.js.map +1 -1
  40. package/dist/mcp-server/tools/definitions/obsidian-manage-tags.tool.d.ts +13 -3
  41. package/dist/mcp-server/tools/definitions/obsidian-manage-tags.tool.d.ts.map +1 -1
  42. package/dist/mcp-server/tools/definitions/obsidian-manage-tags.tool.js +12 -0
  43. package/dist/mcp-server/tools/definitions/obsidian-manage-tags.tool.js.map +1 -1
  44. package/dist/mcp-server/tools/definitions/obsidian-open-in-ui.tool.d.ts +18 -2
  45. package/dist/mcp-server/tools/definitions/obsidian-open-in-ui.tool.d.ts.map +1 -1
  46. package/dist/mcp-server/tools/definitions/obsidian-open-in-ui.tool.js +49 -26
  47. package/dist/mcp-server/tools/definitions/obsidian-open-in-ui.tool.js.map +1 -1
  48. package/dist/mcp-server/tools/definitions/obsidian-patch-note.tool.d.ts +21 -6
  49. package/dist/mcp-server/tools/definitions/obsidian-patch-note.tool.d.ts.map +1 -1
  50. package/dist/mcp-server/tools/definitions/obsidian-patch-note.tool.js +22 -4
  51. package/dist/mcp-server/tools/definitions/obsidian-patch-note.tool.js.map +1 -1
  52. package/dist/mcp-server/tools/definitions/obsidian-replace-in-note.tool.d.ts +11 -1
  53. package/dist/mcp-server/tools/definitions/obsidian-replace-in-note.tool.d.ts.map +1 -1
  54. package/dist/mcp-server/tools/definitions/obsidian-replace-in-note.tool.js +12 -0
  55. package/dist/mcp-server/tools/definitions/obsidian-replace-in-note.tool.js.map +1 -1
  56. package/dist/mcp-server/tools/definitions/obsidian-search-notes.tool.d.ts +58 -58
  57. package/dist/mcp-server/tools/definitions/obsidian-search-notes.tool.d.ts.map +1 -1
  58. package/dist/mcp-server/tools/definitions/obsidian-write-note.tool.d.ts +19 -3
  59. package/dist/mcp-server/tools/definitions/obsidian-write-note.tool.d.ts.map +1 -1
  60. package/dist/mcp-server/tools/definitions/obsidian-write-note.tool.js +26 -3
  61. package/dist/mcp-server/tools/definitions/obsidian-write-note.tool.js.map +1 -1
  62. package/dist/services/obsidian/obsidian-service.d.ts +19 -1
  63. package/dist/services/obsidian/obsidian-service.d.ts.map +1 -1
  64. package/dist/services/obsidian/obsidian-service.js +138 -6
  65. package/dist/services/obsidian/obsidian-service.js.map +1 -1
  66. package/dist/services/obsidian/path-policy.d.ts.map +1 -1
  67. package/manifest.json +1 -1
  68. package/package.json +14 -13
  69. package/server.json +3 -3
@@ -11,17 +11,24 @@
11
11
  */
12
12
  export { buildSearchNotesTool } from './obsidian-search-notes.tool.js';
13
13
  /**
14
- * Read-only tools that don't depend on runtime probes — always registered,
15
- * even with `OBSIDIAN_READ_ONLY=true`. `obsidian_search_notes` is constructed
16
- * separately in the entry point via `buildSearchNotesTool` so its mode enum
17
- * can reflect Omnisearch reachability.
14
+ * Tools that don't depend on runtime probes — always registered, even with
15
+ * `OBSIDIAN_READ_ONLY=true`. `obsidian_search_notes` is constructed separately
16
+ * in the entry point via `buildSearchNotesTool` so its mode enum can reflect
17
+ * Omnisearch reachability.
18
+ *
19
+ * `obsidian_open_in_ui` stays here rather than in the write bucket so that
20
+ * opening a note that already exists keeps working on a read-only vault, which
21
+ * is both useful and side-effect-free. Its one create-capable branch — an open
22
+ * against a missing path with `failIfMissing: false`, which Obsidian would
23
+ * materialize — is gated as a write inside `ObsidianService.openInUi`, so
24
+ * read-only mode and `OBSIDIAN_WRITE_PATHS` still bind it.
18
25
  */
19
26
  export declare const readToolDefinitions: (import("@cyanheads/mcp-ts-core").ToolDefinition<import("zod").ZodObject<{
20
27
  format: import("zod").ZodEnum<{
21
28
  content: "content";
22
- section: "section";
23
- full: "full";
24
29
  "document-map": "document-map";
30
+ full: "full";
31
+ section: "section";
25
32
  }>;
26
33
  target: import("zod").ZodDiscriminatedUnion<[import("zod").ZodObject<{
27
34
  type: import("zod").ZodLiteral<"path">;
@@ -32,18 +39,18 @@ export declare const readToolDefinitions: (import("@cyanheads/mcp-ts-core").Tool
32
39
  type: import("zod").ZodLiteral<"periodic">;
33
40
  period: import("zod").ZodEnum<{
34
41
  daily: "daily";
35
- weekly: "weekly";
36
42
  monthly: "monthly";
37
43
  quarterly: "quarterly";
44
+ weekly: "weekly";
38
45
  yearly: "yearly";
39
46
  }>;
40
47
  date: import("zod").ZodOptional<import("zod").ZodString>;
41
48
  }, import("zod/v4/core").$strip>], "type">;
42
49
  section: import("zod").ZodOptional<import("zod").ZodObject<{
43
50
  type: import("zod").ZodEnum<{
44
- heading: "heading";
45
51
  block: "block";
46
52
  frontmatter: "frontmatter";
53
+ heading: "heading";
47
54
  }>;
48
55
  target: import("zod").ZodString;
49
56
  }, import("zod/v4/core").$strip>>;
@@ -82,9 +89,9 @@ export declare const readToolDefinitions: (import("@cyanheads/mcp-ts-core").Tool
82
89
  path: import("zod").ZodString;
83
90
  section: import("zod").ZodObject<{
84
91
  type: import("zod").ZodEnum<{
85
- heading: "heading";
86
92
  block: "block";
87
93
  frontmatter: "frontmatter";
94
+ heading: "heading";
88
95
  }>;
89
96
  target: import("zod").ZodString;
90
97
  }, import("zod/v4/core").$strip>;
@@ -130,7 +137,17 @@ export declare const readToolDefinitions: (import("@cyanheads/mcp-ts-core").Tool
130
137
  readonly reason: "section_missing";
131
138
  readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.NotFound;
132
139
  readonly when: "`format` was `\"section\"` and the named heading, block reference, or frontmatter field does not exist in the resolved note.";
133
- readonly recovery: "Call obsidian_get_note with format \"document-map\" to list available headings, blocks, and frontmatter fields. Nested headings need Parent::Child syntax.";
140
+ readonly recovery: "Call obsidian_get_note with format \"document-map\" to list available headings, blocks, and frontmatter fields, then retry with one of those locators.";
141
+ }, {
142
+ readonly reason: "path_is_directory";
143
+ readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
144
+ readonly when: "The supplied path names a folder rather than a note file.";
145
+ 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.";
146
+ }, {
147
+ readonly reason: "path_traversal";
148
+ readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
149
+ readonly when: "The path contains a `.` or `..` segment, which is rejected to prevent vault escape.";
150
+ readonly recovery: "Supply a vault-relative path with no `.` or `..` segments, e.g. \"Projects/Note.md\". Use obsidian_list_notes to browse the vault.";
134
151
  }], undefined> | import("@cyanheads/mcp-ts-core").ToolDefinition<import("zod").ZodObject<{
135
152
  path: import("zod").ZodOptional<import("zod").ZodString>;
136
153
  extension: import("zod").ZodOptional<import("zod").ZodString>;
@@ -141,8 +158,8 @@ export declare const readToolDefinitions: (import("@cyanheads/mcp-ts-core").Tool
141
158
  entries: import("zod").ZodArray<import("zod").ZodObject<{
142
159
  path: import("zod").ZodString;
143
160
  type: import("zod").ZodEnum<{
144
- file: "file";
145
161
  directory: "directory";
162
+ file: "file";
146
163
  }>;
147
164
  truncated: import("zod").ZodOptional<import("zod").ZodBoolean>;
148
165
  }, import("zod/v4/core").$strip>>;
@@ -216,8 +233,8 @@ export declare const readToolDefinitions: (import("@cyanheads/mcp-ts-core").Tool
216
233
  }, import("zod/v4/core").$strip>, readonly [{
217
234
  readonly reason: "path_forbidden";
218
235
  readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.Forbidden;
219
- readonly when: "The target path is outside OBSIDIAN_READ_PATHS (and OBSIDIAN_WRITE_PATHS, since write paths imply read access).";
220
- readonly recovery: "Use a path inside the configured read scope. The error data echoes the active scope.";
236
+ readonly when: "The path is outside OBSIDIAN_READ_PATHS, or — when the file does not exist and `failIfMissing: false` would have Obsidian create it — outside OBSIDIAN_WRITE_PATHS or blocked by OBSIDIAN_READ_ONLY=true.";
237
+ readonly recovery: "Open a path inside the configured scope. The error data echoes the active scope and whether read or write access was the one denied.";
221
238
  }, {
222
239
  readonly reason: "note_missing";
223
240
  readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.NotFound;
@@ -228,6 +245,16 @@ export declare const readToolDefinitions: (import("@cyanheads/mcp-ts-core").Tool
228
245
  readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.Conflict;
229
246
  readonly when: "The parent directory contains multiple files whose names differ only in case (case-sensitive filesystems only).";
230
247
  readonly recovery: "Retry with one of the exact paths listed in `matches` on the error data.";
248
+ }, {
249
+ readonly reason: "path_is_directory";
250
+ readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
251
+ readonly when: "The supplied path names a folder rather than a file.";
252
+ readonly recovery: "Call obsidian_list_notes with this path to list the folder, then open one of the files it returns.";
253
+ }, {
254
+ readonly reason: "path_traversal";
255
+ readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
256
+ readonly when: "The path contains a `.` or `..` segment, which is rejected to prevent vault escape.";
257
+ readonly recovery: "Supply a vault-relative path with no `.` or `..` segments, e.g. \"Projects/Note.md\". Use obsidian_list_notes to browse the vault.";
231
258
  }], undefined>)[];
232
259
  /** Write tools — wrapped with `disabledTool()` when `OBSIDIAN_READ_ONLY=true`. */
233
260
  export declare const writeToolDefinitions: (import("@cyanheads/mcp-ts-core").ToolDefinition<import("zod").ZodObject<{
@@ -240,9 +267,116 @@ export declare const writeToolDefinitions: (import("@cyanheads/mcp-ts-core").Too
240
267
  type: import("zod").ZodLiteral<"periodic">;
241
268
  period: import("zod").ZodEnum<{
242
269
  daily: "daily";
270
+ monthly: "monthly";
271
+ quarterly: "quarterly";
243
272
  weekly: "weekly";
273
+ yearly: "yearly";
274
+ }>;
275
+ date: import("zod").ZodOptional<import("zod").ZodString>;
276
+ }, import("zod/v4/core").$strip>], "type">;
277
+ section: import("zod").ZodObject<{
278
+ type: import("zod").ZodEnum<{
279
+ block: "block";
280
+ frontmatter: "frontmatter";
281
+ heading: "heading";
282
+ }>;
283
+ target: import("zod").ZodString;
284
+ }, import("zod/v4/core").$strip>;
285
+ operation: import("zod").ZodEnum<{
286
+ append: "append";
287
+ prepend: "prepend";
288
+ replace: "replace";
289
+ }>;
290
+ content: import("zod").ZodString;
291
+ contentType: import("zod").ZodDefault<import("zod").ZodEnum<{
292
+ json: "json";
293
+ markdown: "markdown";
294
+ }>>;
295
+ patchOptions: import("zod").ZodOptional<import("zod").ZodObject<{
296
+ createTargetIfMissing: import("zod").ZodDefault<import("zod").ZodBoolean>;
297
+ applyIfContentPreexists: import("zod").ZodDefault<import("zod").ZodBoolean>;
298
+ trimTargetWhitespace: import("zod").ZodDefault<import("zod").ZodBoolean>;
299
+ }, import("zod/v4/core").$strip>>;
300
+ }, import("zod/v4/core").$strip>, import("zod").ZodObject<{
301
+ path: import("zod").ZodString;
302
+ section: import("zod").ZodObject<{
303
+ type: import("zod").ZodEnum<{
304
+ block: "block";
305
+ frontmatter: "frontmatter";
306
+ heading: "heading";
307
+ }>;
308
+ target: import("zod").ZodString;
309
+ }, import("zod/v4/core").$strip>;
310
+ operation: import("zod").ZodEnum<{
311
+ append: "append";
312
+ prepend: "prepend";
313
+ replace: "replace";
314
+ }>;
315
+ previousSizeInBytes: import("zod").ZodNumber;
316
+ currentSizeInBytes: import("zod").ZodNumber;
317
+ }, import("zod/v4/core").$strip>, readonly [{
318
+ readonly reason: "path_forbidden";
319
+ readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.Forbidden;
320
+ readonly when: "The target path is outside OBSIDIAN_WRITE_PATHS, or OBSIDIAN_READ_ONLY=true denies all writes.";
321
+ readonly recovery: "Use a path inside the configured write scope. The error data echoes the active scope.";
322
+ }, {
323
+ readonly reason: "note_missing";
324
+ readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.NotFound;
325
+ readonly when: "The vault path does not resolve to an existing note.";
326
+ readonly recovery: "Verify the path with obsidian_list_notes or use obsidian_search_notes to locate the note.";
327
+ }, {
328
+ readonly reason: "no_active_file";
329
+ readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.NotFound;
330
+ readonly when: "Target was `active` but no file is currently open in Obsidian.";
331
+ readonly recovery: "Call obsidian_open_in_ui to focus a file, or pass an explicit path target instead.";
332
+ }, {
333
+ readonly reason: "periodic_not_found";
334
+ readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.NotFound;
335
+ readonly when: "Target was `periodic` but no matching periodic note exists.";
336
+ readonly recovery: "Create the periodic note first or pass an explicit path target.";
337
+ }, {
338
+ readonly reason: "periodic_disabled";
339
+ readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
340
+ readonly when: "Target was `periodic` but the requested period is not enabled in Obsidian's Periodic Notes plugin settings.";
341
+ readonly recovery: "Pass an explicit path target — the requested period is disabled in the operator's Periodic Notes plugin.";
342
+ }, {
343
+ readonly reason: "section_target_missing";
344
+ readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
345
+ 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.";
346
+ readonly recovery: "Call obsidian_get_note with format document-map to discover the available targets.";
347
+ }, {
348
+ readonly reason: "ambiguous_section";
349
+ readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.Conflict;
350
+ readonly when: "A bare heading leaf name matches more than one heading in the note, so the write target is undetermined.";
351
+ readonly recovery: "Retry with one of the full Parent::Child heading paths listed in `candidates` on the error data.";
352
+ }, {
353
+ readonly reason: "content_preexists";
354
+ readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
355
+ readonly when: "The supplied content already appears at the target — the patch was rejected to keep retries idempotent (the default).";
356
+ readonly recovery: "Pass `patchOptions.applyIfContentPreexists: true` to force-apply over preexisting content, or change the content to something not already present.";
357
+ }, {
358
+ readonly reason: "path_is_directory";
359
+ readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
360
+ readonly when: "The supplied path names a folder rather than a note file.";
361
+ 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.";
362
+ }, {
363
+ readonly reason: "path_traversal";
364
+ readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
365
+ readonly when: "The path contains a `.` or `..` segment, which is rejected to prevent vault escape.";
366
+ readonly recovery: "Supply a vault-relative path with no `.` or `..` segments, e.g. \"Projects/Note.md\". Use obsidian_list_notes to browse the vault.";
367
+ }], undefined> | import("@cyanheads/mcp-ts-core").ToolDefinition<import("zod").ZodObject<{
368
+ target: import("zod").ZodDiscriminatedUnion<[import("zod").ZodObject<{
369
+ type: import("zod").ZodLiteral<"path">;
370
+ path: import("zod").ZodString;
371
+ }, import("zod/v4/core").$strip>, import("zod").ZodObject<{
372
+ type: import("zod").ZodLiteral<"active">;
373
+ }, import("zod/v4/core").$strip>, import("zod").ZodObject<{
374
+ type: import("zod").ZodLiteral<"periodic">;
375
+ period: import("zod").ZodEnum<{
376
+ daily: "daily";
244
377
  monthly: "monthly";
245
378
  quarterly: "quarterly";
379
+ weekly: "weekly";
246
380
  yearly: "yearly";
247
381
  }>;
248
382
  date: import("zod").ZodOptional<import("zod").ZodString>;
@@ -250,20 +384,109 @@ export declare const writeToolDefinitions: (import("@cyanheads/mcp-ts-core").Too
250
384
  content: import("zod").ZodString;
251
385
  section: import("zod").ZodOptional<import("zod").ZodObject<{
252
386
  type: import("zod").ZodEnum<{
253
- heading: "heading";
254
387
  block: "block";
255
388
  frontmatter: "frontmatter";
389
+ heading: "heading";
256
390
  }>;
257
391
  target: import("zod").ZodString;
258
392
  }, import("zod/v4/core").$strip>>;
259
393
  contentType: import("zod").ZodDefault<import("zod").ZodEnum<{
394
+ json: "json";
260
395
  markdown: "markdown";
396
+ }>>;
397
+ overwrite: import("zod").ZodDefault<import("zod").ZodBoolean>;
398
+ }, import("zod/v4/core").$strip>, import("zod").ZodObject<{
399
+ path: import("zod").ZodString;
400
+ sectionTargeted: import("zod").ZodBoolean;
401
+ sectionTarget: import("zod").ZodOptional<import("zod").ZodString>;
402
+ created: import("zod").ZodBoolean;
403
+ previousSizeInBytes: import("zod").ZodNumber;
404
+ currentSizeInBytes: import("zod").ZodNumber;
405
+ }, import("zod/v4/core").$strip>, readonly [{
406
+ readonly reason: "file_exists";
407
+ readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.Conflict;
408
+ readonly when: "Whole-file write was attempted against an existing note and `overwrite` was not set to `true`.";
409
+ readonly recovery: "Retry with overwrite true or use obsidian_patch_note for in-place edits.";
410
+ }, {
411
+ readonly reason: "path_forbidden";
412
+ readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.Forbidden;
413
+ readonly when: "The target path is outside OBSIDIAN_WRITE_PATHS, or OBSIDIAN_READ_ONLY=true denies all writes.";
414
+ readonly recovery: "Use a path inside the configured write scope. The error data echoes the active scope.";
415
+ }, {
416
+ readonly reason: "note_missing";
417
+ readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.NotFound;
418
+ readonly when: "Section replace targets a path that does not resolve to an existing note (PATCH requires the file to exist).";
419
+ readonly recovery: "Verify the path with obsidian_list_notes, or omit `section` to fall back to whole-file write (which creates the note when it is absent).";
420
+ }, {
421
+ readonly reason: "no_active_file";
422
+ readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.NotFound;
423
+ readonly when: "Target was `active` but no file is currently open in Obsidian.";
424
+ readonly recovery: "Call obsidian_open_in_ui to focus a file, or pass an explicit path target instead.";
425
+ }, {
426
+ readonly reason: "periodic_not_found";
427
+ readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.NotFound;
428
+ readonly when: "Target was `periodic` but no matching periodic note exists.";
429
+ readonly recovery: "Create the periodic note first or pass an explicit path target.";
430
+ }, {
431
+ readonly reason: "periodic_disabled";
432
+ readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
433
+ readonly when: "Target was `periodic` but the requested period is not enabled in Obsidian's Periodic Notes plugin settings.";
434
+ readonly recovery: "Pass an explicit path target — the requested period is disabled in the operator's Periodic Notes plugin.";
435
+ }, {
436
+ readonly reason: "section_target_missing";
437
+ readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
438
+ readonly when: "`section` was provided but the named heading/block/frontmatter field does not exist in the note.";
439
+ readonly recovery: "Call obsidian_get_note with format document-map to discover available targets.";
440
+ }, {
441
+ readonly reason: "ambiguous_section";
442
+ readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.Conflict;
443
+ readonly when: "A bare heading leaf name matches more than one heading in the note, so the replacement target is undetermined.";
444
+ readonly recovery: "Retry with one of the full Parent::Child heading paths listed in `candidates` on the error data.";
445
+ }, {
446
+ readonly reason: "path_is_directory";
447
+ readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
448
+ readonly when: "The supplied path names a folder rather than a note file.";
449
+ 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.";
450
+ }, {
451
+ readonly reason: "path_traversal";
452
+ readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
453
+ readonly when: "The path contains a `.` or `..` segment, which is rejected to prevent vault escape.";
454
+ readonly recovery: "Supply a vault-relative path with no `.` or `..` segments, e.g. \"Projects/Note.md\". Use obsidian_list_notes to browse the vault.";
455
+ }], undefined> | import("@cyanheads/mcp-ts-core").ToolDefinition<import("zod").ZodObject<{
456
+ target: import("zod").ZodDiscriminatedUnion<[import("zod").ZodObject<{
457
+ type: import("zod").ZodLiteral<"path">;
458
+ path: import("zod").ZodString;
459
+ }, import("zod/v4/core").$strip>, import("zod").ZodObject<{
460
+ type: import("zod").ZodLiteral<"active">;
461
+ }, import("zod/v4/core").$strip>, import("zod").ZodObject<{
462
+ type: import("zod").ZodLiteral<"periodic">;
463
+ period: import("zod").ZodEnum<{
464
+ daily: "daily";
465
+ monthly: "monthly";
466
+ quarterly: "quarterly";
467
+ weekly: "weekly";
468
+ yearly: "yearly";
469
+ }>;
470
+ date: import("zod").ZodOptional<import("zod").ZodString>;
471
+ }, import("zod/v4/core").$strip>], "type">;
472
+ content: import("zod").ZodString;
473
+ section: import("zod").ZodOptional<import("zod").ZodObject<{
474
+ type: import("zod").ZodEnum<{
475
+ block: "block";
476
+ frontmatter: "frontmatter";
477
+ heading: "heading";
478
+ }>;
479
+ target: import("zod").ZodString;
480
+ }, import("zod/v4/core").$strip>>;
481
+ contentType: import("zod").ZodDefault<import("zod").ZodEnum<{
261
482
  json: "json";
483
+ markdown: "markdown";
262
484
  }>>;
263
485
  createTargetIfMissing: import("zod").ZodDefault<import("zod").ZodBoolean>;
264
486
  }, import("zod/v4/core").$strip>, import("zod").ZodObject<{
265
487
  path: import("zod").ZodString;
266
488
  sectionTargeted: import("zod").ZodBoolean;
489
+ sectionTarget: import("zod").ZodOptional<import("zod").ZodString>;
267
490
  created: import("zod").ZodBoolean;
268
491
  previousSizeInBytes: import("zod").ZodNumber;
269
492
  currentSizeInBytes: import("zod").ZodNumber;
@@ -297,11 +520,26 @@ export declare const writeToolDefinitions: (import("@cyanheads/mcp-ts-core").Too
297
520
  readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
298
521
  readonly when: "`section` was provided but the named heading/block/frontmatter field does not exist in the note.";
299
522
  readonly recovery: "Call obsidian_get_note with format document-map to discover available targets, or pass createTargetIfMissing: true to bring it into existence.";
523
+ }, {
524
+ readonly reason: "ambiguous_section";
525
+ readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.Conflict;
526
+ readonly when: "A bare heading leaf name matches more than one heading in the note, so the append target is undetermined.";
527
+ readonly recovery: "Retry with one of the full Parent::Child heading paths listed in `candidates` on the error data.";
300
528
  }, {
301
529
  readonly reason: "content_preexists";
302
530
  readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
303
531
  readonly when: "Section append where the supplied content already appears at the target — rejected to keep retries idempotent (the default for the section path).";
304
532
  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.";
533
+ }, {
534
+ readonly reason: "path_is_directory";
535
+ readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
536
+ readonly when: "The supplied path names a folder rather than a note file.";
537
+ 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.";
538
+ }, {
539
+ readonly reason: "path_traversal";
540
+ readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
541
+ readonly when: "The path contains a `.` or `..` segment, which is rejected to prevent vault escape.";
542
+ readonly recovery: "Supply a vault-relative path with no `.` or `..` segments, e.g. \"Projects/Note.md\". Use obsidian_list_notes to browse the vault.";
305
543
  }], undefined> | import("@cyanheads/mcp-ts-core").ToolDefinition<import("zod").ZodObject<{
306
544
  target: import("zod").ZodDiscriminatedUnion<[import("zod").ZodObject<{
307
545
  type: import("zod").ZodLiteral<"path">;
@@ -312,28 +550,46 @@ export declare const writeToolDefinitions: (import("@cyanheads/mcp-ts-core").Too
312
550
  type: import("zod").ZodLiteral<"periodic">;
313
551
  period: import("zod").ZodEnum<{
314
552
  daily: "daily";
315
- weekly: "weekly";
316
553
  monthly: "monthly";
317
554
  quarterly: "quarterly";
555
+ weekly: "weekly";
318
556
  yearly: "yearly";
319
557
  }>;
320
558
  date: import("zod").ZodOptional<import("zod").ZodString>;
321
559
  }, import("zod/v4/core").$strip>], "type">;
560
+ replacements: import("zod").ZodArray<import("zod").ZodObject<{
561
+ search: import("zod").ZodString;
562
+ replace: import("zod").ZodString;
563
+ useRegex: import("zod").ZodDefault<import("zod").ZodBoolean>;
564
+ caseSensitive: import("zod").ZodDefault<import("zod").ZodBoolean>;
565
+ wholeWord: import("zod").ZodDefault<import("zod").ZodBoolean>;
566
+ flexibleWhitespace: import("zod").ZodDefault<import("zod").ZodBoolean>;
567
+ replaceAll: import("zod").ZodDefault<import("zod").ZodBoolean>;
568
+ }, import("zod/v4/core").$strip>>;
322
569
  }, import("zod/v4/core").$strip>, import("zod").ZodObject<{
323
570
  path: import("zod").ZodString;
324
- deleted: import("zod").ZodBoolean;
571
+ totalReplacements: import("zod").ZodNumber;
572
+ perReplacement: import("zod").ZodArray<import("zod").ZodObject<{
573
+ search: import("zod").ZodString;
574
+ count: import("zod").ZodNumber;
575
+ }, import("zod/v4/core").$strip>>;
325
576
  previousSizeInBytes: import("zod").ZodNumber;
326
577
  currentSizeInBytes: import("zod").ZodNumber;
327
578
  }, import("zod/v4/core").$strip>, readonly [{
328
579
  readonly reason: "path_forbidden";
329
580
  readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.Forbidden;
330
- readonly when: "The target path is outside OBSIDIAN_WRITE_PATHS, or OBSIDIAN_READ_ONLY=true denies all writes.";
581
+ 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.)";
331
582
  readonly recovery: "Use a path inside the configured write scope. The error data echoes the active scope.";
332
583
  }, {
333
- readonly reason: "cancelled";
334
- readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.InvalidRequest;
335
- readonly when: "User declined the deletion via interactive elicitation.";
336
- readonly recovery: "Re-run the tool when the user is ready to confirm deletion.";
584
+ readonly reason: "regex_invalid";
585
+ readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
586
+ readonly when: "A `useRegex: true` replacement supplied a `search` pattern that is not a valid ECMAScript regex.";
587
+ readonly recovery: "Use a valid ECMAScript regex, or set useRegex to false to match `search` as a literal string.";
588
+ }, {
589
+ readonly reason: "regex_unsafe";
590
+ readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
591
+ 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.";
592
+ readonly recovery: "Avoid nested quantifiers like `(a+)+` or `(.*)*`. Use a simpler pattern, or set useRegex to false to match `search` as a literal string.";
337
593
  }, {
338
594
  readonly reason: "note_missing";
339
595
  readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.NotFound;
@@ -348,17 +604,27 @@ export declare const writeToolDefinitions: (import("@cyanheads/mcp-ts-core").Too
348
604
  readonly reason: "periodic_not_found";
349
605
  readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.NotFound;
350
606
  readonly when: "Target was `periodic` but no matching periodic note exists.";
351
- readonly recovery: "Pass an explicit path target periodic notes must already exist.";
607
+ readonly recovery: "Create the periodic note first or pass an explicit path target.";
352
608
  }, {
353
609
  readonly reason: "periodic_disabled";
354
610
  readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
355
611
  readonly when: "Target was `periodic` but the requested period is not enabled in Obsidian's Periodic Notes plugin settings.";
356
612
  readonly recovery: "Pass an explicit path target — the requested period is disabled in the operator's Periodic Notes plugin.";
613
+ }, {
614
+ readonly reason: "path_is_directory";
615
+ readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
616
+ readonly when: "The supplied path names a folder rather than a note file.";
617
+ 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.";
618
+ }, {
619
+ readonly reason: "path_traversal";
620
+ readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
621
+ readonly when: "The path contains a `.` or `..` segment, which is rejected to prevent vault escape.";
622
+ readonly recovery: "Supply a vault-relative path with no `.` or `..` segments, e.g. \"Projects/Note.md\". Use obsidian_list_notes to browse the vault.";
357
623
  }], undefined> | import("@cyanheads/mcp-ts-core").ToolDefinition<import("zod").ZodObject<{
358
624
  operation: import("zod").ZodEnum<{
359
- set: "set";
360
625
  delete: "delete";
361
626
  get: "get";
627
+ set: "set";
362
628
  }>;
363
629
  target: import("zod").ZodDiscriminatedUnion<[import("zod").ZodObject<{
364
630
  type: import("zod").ZodLiteral<"path">;
@@ -369,9 +635,9 @@ export declare const writeToolDefinitions: (import("@cyanheads/mcp-ts-core").Too
369
635
  type: import("zod").ZodLiteral<"periodic">;
370
636
  period: import("zod").ZodEnum<{
371
637
  daily: "daily";
372
- weekly: "weekly";
373
638
  monthly: "monthly";
374
639
  quarterly: "quarterly";
640
+ weekly: "weekly";
375
641
  yearly: "yearly";
376
642
  }>;
377
643
  date: import("zod").ZodOptional<import("zod").ZodString>;
@@ -430,6 +696,16 @@ export declare const writeToolDefinitions: (import("@cyanheads/mcp-ts-core").Too
430
696
  readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
431
697
  readonly when: "Target was `periodic` but the requested period is not enabled in Obsidian's Periodic Notes plugin settings.";
432
698
  readonly recovery: "Pass an explicit path target — the requested period is disabled in the operator's Periodic Notes plugin.";
699
+ }, {
700
+ readonly reason: "path_is_directory";
701
+ readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
702
+ readonly when: "The supplied path names a folder rather than a note file.";
703
+ 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.";
704
+ }, {
705
+ readonly reason: "path_traversal";
706
+ readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
707
+ readonly when: "The path contains a `.` or `..` segment, which is rejected to prevent vault escape.";
708
+ readonly recovery: "Supply a vault-relative path with no `.` or `..` segments, e.g. \"Projects/Note.md\". Use obsidian_list_notes to browse the vault.";
433
709
  }], undefined> | import("@cyanheads/mcp-ts-core").ToolDefinition<import("zod").ZodObject<{
434
710
  target: import("zod").ZodDiscriminatedUnion<[import("zod").ZodObject<{
435
711
  type: import("zod").ZodLiteral<"path">;
@@ -440,23 +716,23 @@ export declare const writeToolDefinitions: (import("@cyanheads/mcp-ts-core").Too
440
716
  type: import("zod").ZodLiteral<"periodic">;
441
717
  period: import("zod").ZodEnum<{
442
718
  daily: "daily";
443
- weekly: "weekly";
444
719
  monthly: "monthly";
445
720
  quarterly: "quarterly";
721
+ weekly: "weekly";
446
722
  yearly: "yearly";
447
723
  }>;
448
724
  date: import("zod").ZodOptional<import("zod").ZodString>;
449
725
  }, import("zod/v4/core").$strip>], "type">;
450
726
  operation: import("zod").ZodEnum<{
451
- list: "list";
452
727
  add: "add";
728
+ list: "list";
453
729
  remove: "remove";
454
730
  }>;
455
731
  tags: import("zod").ZodOptional<import("zod").ZodArray<import("zod").ZodString>>;
456
732
  location: import("zod").ZodDefault<import("zod").ZodEnum<{
733
+ both: "both";
457
734
  frontmatter: "frontmatter";
458
735
  inline: "inline";
459
- both: "both";
460
736
  }>>;
461
737
  }, import("zod/v4/core").$strip>, import("zod").ZodObject<{
462
738
  result: import("zod").ZodDiscriminatedUnion<[import("zod").ZodObject<{
@@ -514,98 +790,16 @@ export declare const writeToolDefinitions: (import("@cyanheads/mcp-ts-core").Too
514
790
  readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
515
791
  readonly when: "Target was `periodic` but the requested period is not enabled in Obsidian's Periodic Notes plugin settings.";
516
792
  readonly recovery: "Pass an explicit path target — the requested period is disabled in the operator's Periodic Notes plugin.";
517
- }], undefined> | import("@cyanheads/mcp-ts-core").ToolDefinition<import("zod").ZodObject<{
518
- target: import("zod").ZodDiscriminatedUnion<[import("zod").ZodObject<{
519
- type: import("zod").ZodLiteral<"path">;
520
- path: import("zod").ZodString;
521
- }, import("zod/v4/core").$strip>, import("zod").ZodObject<{
522
- type: import("zod").ZodLiteral<"active">;
523
- }, import("zod/v4/core").$strip>, import("zod").ZodObject<{
524
- type: import("zod").ZodLiteral<"periodic">;
525
- period: import("zod").ZodEnum<{
526
- daily: "daily";
527
- weekly: "weekly";
528
- monthly: "monthly";
529
- quarterly: "quarterly";
530
- yearly: "yearly";
531
- }>;
532
- date: import("zod").ZodOptional<import("zod").ZodString>;
533
- }, import("zod/v4/core").$strip>], "type">;
534
- section: import("zod").ZodObject<{
535
- type: import("zod").ZodEnum<{
536
- heading: "heading";
537
- block: "block";
538
- frontmatter: "frontmatter";
539
- }>;
540
- target: import("zod").ZodString;
541
- }, import("zod/v4/core").$strip>;
542
- operation: import("zod").ZodEnum<{
543
- replace: "replace";
544
- append: "append";
545
- prepend: "prepend";
546
- }>;
547
- content: import("zod").ZodString;
548
- contentType: import("zod").ZodDefault<import("zod").ZodEnum<{
549
- markdown: "markdown";
550
- json: "json";
551
- }>>;
552
- patchOptions: import("zod").ZodOptional<import("zod").ZodObject<{
553
- createTargetIfMissing: import("zod").ZodDefault<import("zod").ZodBoolean>;
554
- applyIfContentPreexists: import("zod").ZodDefault<import("zod").ZodBoolean>;
555
- trimTargetWhitespace: import("zod").ZodDefault<import("zod").ZodBoolean>;
556
- }, import("zod/v4/core").$strip>>;
557
- }, import("zod/v4/core").$strip>, import("zod").ZodObject<{
558
- path: import("zod").ZodString;
559
- section: import("zod").ZodObject<{
560
- type: import("zod").ZodEnum<{
561
- heading: "heading";
562
- block: "block";
563
- frontmatter: "frontmatter";
564
- }>;
565
- target: import("zod").ZodString;
566
- }, import("zod/v4/core").$strip>;
567
- operation: import("zod").ZodEnum<{
568
- replace: "replace";
569
- append: "append";
570
- prepend: "prepend";
571
- }>;
572
- previousSizeInBytes: import("zod").ZodNumber;
573
- currentSizeInBytes: import("zod").ZodNumber;
574
- }, import("zod/v4/core").$strip>, readonly [{
575
- readonly reason: "path_forbidden";
576
- readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.Forbidden;
577
- readonly when: "The target path is outside OBSIDIAN_WRITE_PATHS, or OBSIDIAN_READ_ONLY=true denies all writes.";
578
- readonly recovery: "Use a path inside the configured write scope. The error data echoes the active scope.";
579
- }, {
580
- readonly reason: "note_missing";
581
- readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.NotFound;
582
- readonly when: "The vault path does not resolve to an existing note.";
583
- readonly recovery: "Verify the path with obsidian_list_notes or use obsidian_search_notes to locate the note.";
584
- }, {
585
- readonly reason: "no_active_file";
586
- readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.NotFound;
587
- readonly when: "Target was `active` but no file is currently open in Obsidian.";
588
- readonly recovery: "Call obsidian_open_in_ui to focus a file, or pass an explicit path target instead.";
589
793
  }, {
590
- readonly reason: "periodic_not_found";
591
- readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.NotFound;
592
- readonly when: "Target was `periodic` but no matching periodic note exists.";
593
- readonly recovery: "Create the periodic note first or pass an explicit path target.";
594
- }, {
595
- readonly reason: "periodic_disabled";
794
+ readonly reason: "path_is_directory";
596
795
  readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
597
- readonly when: "Target was `periodic` but the requested period is not enabled in Obsidian's Periodic Notes plugin settings.";
598
- readonly recovery: "Pass an explicit path target the requested period is disabled in the operator's Periodic Notes plugin.";
796
+ readonly when: "The supplied path names a folder rather than a note file.";
797
+ 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.";
599
798
  }, {
600
- readonly reason: "section_target_missing";
601
- readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
602
- 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.";
603
- readonly recovery: "Call obsidian_get_note with format document-map to discover the available targets.";
604
- }, {
605
- readonly reason: "content_preexists";
799
+ readonly reason: "path_traversal";
606
800
  readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
607
- readonly when: "The supplied content already appears at the target the patch was rejected to keep retries idempotent (the default).";
608
- readonly recovery: "Pass `patchOptions.applyIfContentPreexists: true` to force-apply over preexisting content, or change the content to something not already present.";
801
+ readonly when: "The path contains a `.` or `..` segment, which is rejected to prevent vault escape.";
802
+ readonly recovery: "Supply a vault-relative path with no `.` or `..` segments, e.g. \"Projects/Note.md\". Use obsidian_list_notes to browse the vault.";
609
803
  }], undefined> | import("@cyanheads/mcp-ts-core").ToolDefinition<import("zod").ZodObject<{
610
804
  target: import("zod").ZodDiscriminatedUnion<[import("zod").ZodObject<{
611
805
  type: import("zod").ZodLiteral<"path">;
@@ -616,46 +810,28 @@ export declare const writeToolDefinitions: (import("@cyanheads/mcp-ts-core").Too
616
810
  type: import("zod").ZodLiteral<"periodic">;
617
811
  period: import("zod").ZodEnum<{
618
812
  daily: "daily";
619
- weekly: "weekly";
620
813
  monthly: "monthly";
621
814
  quarterly: "quarterly";
815
+ weekly: "weekly";
622
816
  yearly: "yearly";
623
817
  }>;
624
818
  date: import("zod").ZodOptional<import("zod").ZodString>;
625
819
  }, import("zod/v4/core").$strip>], "type">;
626
- replacements: import("zod").ZodArray<import("zod").ZodObject<{
627
- search: import("zod").ZodString;
628
- replace: import("zod").ZodString;
629
- useRegex: import("zod").ZodDefault<import("zod").ZodBoolean>;
630
- caseSensitive: import("zod").ZodDefault<import("zod").ZodBoolean>;
631
- wholeWord: import("zod").ZodDefault<import("zod").ZodBoolean>;
632
- flexibleWhitespace: import("zod").ZodDefault<import("zod").ZodBoolean>;
633
- replaceAll: import("zod").ZodDefault<import("zod").ZodBoolean>;
634
- }, import("zod/v4/core").$strip>>;
635
820
  }, import("zod/v4/core").$strip>, import("zod").ZodObject<{
636
821
  path: import("zod").ZodString;
637
- totalReplacements: import("zod").ZodNumber;
638
- perReplacement: import("zod").ZodArray<import("zod").ZodObject<{
639
- search: import("zod").ZodString;
640
- count: import("zod").ZodNumber;
641
- }, import("zod/v4/core").$strip>>;
822
+ deleted: import("zod").ZodBoolean;
642
823
  previousSizeInBytes: import("zod").ZodNumber;
643
824
  currentSizeInBytes: import("zod").ZodNumber;
644
825
  }, import("zod/v4/core").$strip>, readonly [{
645
826
  readonly reason: "path_forbidden";
646
827
  readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.Forbidden;
647
- 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.)";
828
+ readonly when: "The target path is outside OBSIDIAN_WRITE_PATHS, or OBSIDIAN_READ_ONLY=true denies all writes.";
648
829
  readonly recovery: "Use a path inside the configured write scope. The error data echoes the active scope.";
649
830
  }, {
650
- readonly reason: "regex_invalid";
651
- readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
652
- readonly when: "A `useRegex: true` replacement supplied a `search` pattern that is not a valid ECMAScript regex.";
653
- readonly recovery: "Use a valid ECMAScript regex, or set useRegex to false to match `search` as a literal string.";
654
- }, {
655
- readonly reason: "regex_unsafe";
656
- readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
657
- 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.";
658
- readonly recovery: "Avoid nested quantifiers like `(a+)+` or `(.*)*`. Use a simpler pattern, or set useRegex to false to match `search` as a literal string.";
831
+ readonly reason: "cancelled";
832
+ readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.InvalidRequest;
833
+ readonly when: "User declined the deletion via interactive elicitation.";
834
+ readonly recovery: "Re-run the tool when the user is ready to confirm deletion.";
659
835
  }, {
660
836
  readonly reason: "note_missing";
661
837
  readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.NotFound;
@@ -670,97 +846,25 @@ export declare const writeToolDefinitions: (import("@cyanheads/mcp-ts-core").Too
670
846
  readonly reason: "periodic_not_found";
671
847
  readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.NotFound;
672
848
  readonly when: "Target was `periodic` but no matching periodic note exists.";
673
- readonly recovery: "Create the periodic note first or pass an explicit path target.";
849
+ readonly recovery: "Pass an explicit path target periodic notes must already exist.";
674
850
  }, {
675
851
  readonly reason: "periodic_disabled";
676
852
  readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
677
853
  readonly when: "Target was `periodic` but the requested period is not enabled in Obsidian's Periodic Notes plugin settings.";
678
854
  readonly recovery: "Pass an explicit path target — the requested period is disabled in the operator's Periodic Notes plugin.";
679
- }], undefined> | import("@cyanheads/mcp-ts-core").ToolDefinition<import("zod").ZodObject<{
680
- target: import("zod").ZodDiscriminatedUnion<[import("zod").ZodObject<{
681
- type: import("zod").ZodLiteral<"path">;
682
- path: import("zod").ZodString;
683
- }, import("zod/v4/core").$strip>, import("zod").ZodObject<{
684
- type: import("zod").ZodLiteral<"active">;
685
- }, import("zod/v4/core").$strip>, import("zod").ZodObject<{
686
- type: import("zod").ZodLiteral<"periodic">;
687
- period: import("zod").ZodEnum<{
688
- daily: "daily";
689
- weekly: "weekly";
690
- monthly: "monthly";
691
- quarterly: "quarterly";
692
- yearly: "yearly";
693
- }>;
694
- date: import("zod").ZodOptional<import("zod").ZodString>;
695
- }, import("zod/v4/core").$strip>], "type">;
696
- content: import("zod").ZodString;
697
- section: import("zod").ZodOptional<import("zod").ZodObject<{
698
- type: import("zod").ZodEnum<{
699
- heading: "heading";
700
- block: "block";
701
- frontmatter: "frontmatter";
702
- }>;
703
- target: import("zod").ZodString;
704
- }, import("zod/v4/core").$strip>>;
705
- contentType: import("zod").ZodDefault<import("zod").ZodEnum<{
706
- markdown: "markdown";
707
- json: "json";
708
- }>>;
709
- overwrite: import("zod").ZodDefault<import("zod").ZodBoolean>;
710
- }, import("zod/v4/core").$strip>, import("zod").ZodObject<{
711
- path: import("zod").ZodString;
712
- sectionTargeted: import("zod").ZodBoolean;
713
- created: import("zod").ZodBoolean;
714
- previousSizeInBytes: import("zod").ZodNumber;
715
- currentSizeInBytes: import("zod").ZodNumber;
716
- }, import("zod/v4/core").$strip>, readonly [{
717
- readonly reason: "file_exists";
718
- readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.Conflict;
719
- readonly when: "Whole-file write was attempted against an existing note and `overwrite` was not set to `true`.";
720
- readonly recovery: "Retry with overwrite true or use obsidian_patch_note for in-place edits.";
721
- }, {
722
- readonly reason: "path_forbidden";
723
- readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.Forbidden;
724
- readonly when: "The target path is outside OBSIDIAN_WRITE_PATHS, or OBSIDIAN_READ_ONLY=true denies all writes.";
725
- readonly recovery: "Use a path inside the configured write scope. The error data echoes the active scope.";
726
- }, {
727
- readonly reason: "note_missing";
728
- readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.NotFound;
729
- readonly when: "Section replace targets a path that does not resolve to an existing note (PATCH requires the file to exist).";
730
- readonly recovery: "Verify the path with obsidian_list_notes, or omit `section` to fall back to whole-file write (which creates the note when it is absent).";
731
- }, {
732
- readonly reason: "no_active_file";
733
- readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.NotFound;
734
- readonly when: "Target was `active` but no file is currently open in Obsidian.";
735
- readonly recovery: "Call obsidian_open_in_ui to focus a file, or pass an explicit path target instead.";
736
- }, {
737
- readonly reason: "periodic_not_found";
738
- readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.NotFound;
739
- readonly when: "Target was `periodic` but no matching periodic note exists.";
740
- readonly recovery: "Create the periodic note first or pass an explicit path target.";
741
855
  }, {
742
- readonly reason: "periodic_disabled";
856
+ readonly reason: "path_is_directory";
743
857
  readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
744
- readonly when: "Target was `periodic` but the requested period is not enabled in Obsidian's Periodic Notes plugin settings.";
745
- readonly recovery: "Pass an explicit path target the requested period is disabled in the operator's Periodic Notes plugin.";
858
+ 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.";
859
+ readonly recovery: "Call obsidian_list_notes with this path to list the folder, then delete files one at a time by their full paths.";
746
860
  }, {
747
- readonly reason: "section_target_missing";
861
+ readonly reason: "path_traversal";
748
862
  readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
749
- readonly when: "`section` was provided but the named heading/block/frontmatter field does not exist in the note.";
750
- readonly recovery: "Call obsidian_get_note with format document-map to discover available targets.";
863
+ readonly when: "The path contains a `.` or `..` segment, which is rejected to prevent vault escape.";
864
+ readonly recovery: "Supply a vault-relative path with no `.` or `..` segments, e.g. \"Projects/Note.md\". Use obsidian_list_notes to browse the vault.";
751
865
  }], undefined>)[];
752
866
  /** Command-palette tools — opt-in via `OBSIDIAN_ENABLE_COMMANDS=true`; suppressed by `OBSIDIAN_READ_ONLY=true`. */
753
867
  export declare const commandToolDefinitions: (import("@cyanheads/mcp-ts-core").ToolDefinition<import("zod").ZodObject<{
754
- commandId: import("zod").ZodString;
755
- }, import("zod/v4/core").$strip>, import("zod").ZodObject<{
756
- commandId: import("zod").ZodString;
757
- executed: import("zod").ZodBoolean;
758
- }, import("zod/v4/core").$strip>, readonly [{
759
- readonly reason: "command_unknown";
760
- readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.NotFound;
761
- readonly when: "The supplied `commandId` is not registered in Obsidian. Use `obsidian_list_commands` to discover valid IDs.";
762
- readonly recovery: "Call obsidian_list_commands to discover the registered command IDs.";
763
- }], undefined> | import("@cyanheads/mcp-ts-core").ToolDefinition<import("zod").ZodObject<{
764
868
  nameRegex: import("zod").ZodOptional<import("zod").ZodString>;
765
869
  }, import("zod/v4/core").$strip>, import("zod").ZodObject<{
766
870
  commands: import("zod").ZodArray<import("zod").ZodObject<{
@@ -780,5 +884,15 @@ export declare const commandToolDefinitions: (import("@cyanheads/mcp-ts-core").T
780
884
  readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
781
885
  readonly when: "The supplied `nameRegex` is well-formed but exceeds the 256-character limit or contains nested quantifiers known to cause catastrophic backtracking.";
782
886
  readonly recovery: "Avoid nested quantifiers like `(a+)+` or `(.*)*`. Use a simpler pattern (e.g. `^Templater`), or omit nameRegex to disable filtering.";
887
+ }], undefined> | import("@cyanheads/mcp-ts-core").ToolDefinition<import("zod").ZodObject<{
888
+ commandId: import("zod").ZodString;
889
+ }, import("zod/v4/core").$strip>, import("zod").ZodObject<{
890
+ commandId: import("zod").ZodString;
891
+ executed: import("zod").ZodBoolean;
892
+ }, import("zod/v4/core").$strip>, readonly [{
893
+ readonly reason: "command_unknown";
894
+ readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.NotFound;
895
+ readonly when: "The supplied `commandId` is not registered in Obsidian. Use `obsidian_list_commands` to discover valid IDs.";
896
+ readonly recovery: "Call obsidian_list_commands to discover the registered command IDs.";
783
897
  }], undefined>)[];
784
898
  //# sourceMappingURL=index.d.ts.map