obsidian-mcp-server 3.5.1 → 3.5.3

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 (71) hide show
  1. package/AGENTS.md +21 -19
  2. package/CLAUDE.md +21 -19
  3. package/README.md +9 -7
  4. package/changelog/3.5.x/3.5.2.md +27 -0
  5. package/changelog/3.5.x/3.5.3.md +26 -0
  6. package/changelog/template.md +7 -24
  7. package/dist/config/server-config.d.ts +2 -2
  8. package/dist/config/server-config.d.ts.map +1 -1
  9. package/dist/config/server-config.js +4 -4
  10. package/dist/config/server-config.js.map +1 -1
  11. package/dist/mcp-server/resources/definitions/index.d.ts +5 -0
  12. package/dist/mcp-server/resources/definitions/index.d.ts.map +1 -1
  13. package/dist/mcp-server/resources/definitions/obsidian-status.resource.d.ts +11 -4
  14. package/dist/mcp-server/resources/definitions/obsidian-status.resource.d.ts.map +1 -1
  15. package/dist/mcp-server/resources/definitions/obsidian-status.resource.js +21 -12
  16. package/dist/mcp-server/resources/definitions/obsidian-status.resource.js.map +1 -1
  17. package/dist/mcp-server/tools/definitions/index.d.ts +88 -39
  18. package/dist/mcp-server/tools/definitions/index.d.ts.map +1 -1
  19. package/dist/mcp-server/tools/definitions/obsidian-append-to-note.tool.d.ts +6 -1
  20. package/dist/mcp-server/tools/definitions/obsidian-append-to-note.tool.d.ts.map +1 -1
  21. package/dist/mcp-server/tools/definitions/obsidian-append-to-note.tool.js +7 -1
  22. package/dist/mcp-server/tools/definitions/obsidian-append-to-note.tool.js.map +1 -1
  23. package/dist/mcp-server/tools/definitions/obsidian-delete-note.tool.d.ts +6 -1
  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 +7 -1
  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 +11 -2
  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 +41 -15
  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 +8 -3
  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 +12 -5
  34. package/dist/mcp-server/tools/definitions/obsidian-list-notes.tool.js.map +1 -1
  35. package/dist/mcp-server/tools/definitions/obsidian-manage-frontmatter.tool.d.ts +6 -1
  36. package/dist/mcp-server/tools/definitions/obsidian-manage-frontmatter.tool.d.ts.map +1 -1
  37. package/dist/mcp-server/tools/definitions/obsidian-manage-frontmatter.tool.js +7 -1
  38. package/dist/mcp-server/tools/definitions/obsidian-manage-frontmatter.tool.js.map +1 -1
  39. package/dist/mcp-server/tools/definitions/obsidian-manage-tags.tool.d.ts +8 -3
  40. package/dist/mcp-server/tools/definitions/obsidian-manage-tags.tool.d.ts.map +1 -1
  41. package/dist/mcp-server/tools/definitions/obsidian-manage-tags.tool.js +10 -4
  42. package/dist/mcp-server/tools/definitions/obsidian-manage-tags.tool.js.map +1 -1
  43. package/dist/mcp-server/tools/definitions/obsidian-patch-note.tool.d.ts +6 -1
  44. package/dist/mcp-server/tools/definitions/obsidian-patch-note.tool.d.ts.map +1 -1
  45. package/dist/mcp-server/tools/definitions/obsidian-patch-note.tool.js +7 -1
  46. package/dist/mcp-server/tools/definitions/obsidian-patch-note.tool.js.map +1 -1
  47. package/dist/mcp-server/tools/definitions/obsidian-replace-in-note.tool.d.ts +6 -1
  48. package/dist/mcp-server/tools/definitions/obsidian-replace-in-note.tool.d.ts.map +1 -1
  49. package/dist/mcp-server/tools/definitions/obsidian-replace-in-note.tool.js +7 -1
  50. package/dist/mcp-server/tools/definitions/obsidian-replace-in-note.tool.js.map +1 -1
  51. package/dist/mcp-server/tools/definitions/obsidian-write-note.tool.d.ts +6 -1
  52. package/dist/mcp-server/tools/definitions/obsidian-write-note.tool.d.ts.map +1 -1
  53. package/dist/mcp-server/tools/definitions/obsidian-write-note.tool.js +7 -1
  54. package/dist/mcp-server/tools/definitions/obsidian-write-note.tool.js.map +1 -1
  55. package/dist/services/obsidian/frontmatter-ops.d.ts +9 -5
  56. package/dist/services/obsidian/frontmatter-ops.d.ts.map +1 -1
  57. package/dist/services/obsidian/frontmatter-ops.js +70 -16
  58. package/dist/services/obsidian/frontmatter-ops.js.map +1 -1
  59. package/dist/services/obsidian/obsidian-service.d.ts +10 -7
  60. package/dist/services/obsidian/obsidian-service.d.ts.map +1 -1
  61. package/dist/services/obsidian/obsidian-service.js +179 -31
  62. package/dist/services/obsidian/obsidian-service.js.map +1 -1
  63. package/dist/services/obsidian/section-extractor.d.ts +17 -1
  64. package/dist/services/obsidian/section-extractor.d.ts.map +1 -1
  65. package/dist/services/obsidian/section-extractor.js +109 -40
  66. package/dist/services/obsidian/section-extractor.js.map +1 -1
  67. package/dist/services/obsidian/types.d.ts +17 -0
  68. package/dist/services/obsidian/types.d.ts.map +1 -1
  69. package/manifest.json +11 -11
  70. package/package.json +11 -10
  71. package/server.json +3 -3
package/AGENTS.md CHANGED
@@ -1,11 +1,11 @@
1
1
  # Agent Protocol
2
2
 
3
3
  **Server:** obsidian-mcp-server
4
- **Version:** 3.5.1
5
- **Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.12.5`
6
- **Engines:** Bun ≥1.3.0, Node ≥24.0.0
4
+ **Version:** 3.5.3
5
+ **Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.13.0`
6
+ **Engines:** Bun ≥1.4.0, Node ≥24.0.0
7
7
  **MCP SDK:** `@modelcontextprotocol/server` ^2.0.0
8
- **Zod:** ^4.5.4
8
+ **Zod:** ^4.6.1
9
9
 
10
10
  > **Read the framework docs first:** `node_modules/@cyanheads/mcp-ts-core/CLAUDE.md` contains the full API reference — builders, Context, error codes, exports, patterns. This file covers server-specific conventions only.
11
11
 
@@ -189,7 +189,7 @@ The framework also provides `ctx.state`. It isn't used by this server — Obsidi
189
189
 
190
190
  Handlers throw — the framework catches, classifies, and formats.
191
191
 
192
- **Recommended: typed error contract.** Declare `errors: [{ reason, code, when, recovery, retryable? }]` on `tool()` / `resource()` to receive a typed `ctx.fail(reason, …)` keyed by the declared reason union. TypeScript catches `ctx.fail('typo')` at compile time, `data.reason` is auto-populated for observability, and the linter enforces conformance against the handler body. The `recovery` field is required descriptive metadata (≥ 5 words, lint-validated) — it's the single source of truth for the recovery hint that flows to the wire. Spread `ctx.recoveryFor('reason')` into `data` to opt the contract recovery onto the wire (the framework mirrors `data.recovery.hint` into `content[]` text). Override with explicit `{ recovery: { hint: '...' } }` when runtime context matters. Baseline codes (`InternalError`, `ServiceUnavailable`, `Timeout`, `ValidationError`, `SerializationError`) bubble freely and don't need declaring.
192
+ **Recommended: typed error contract.** Declare `errors: [{ reason, code, when, recovery, retryable? }]` on `tool()` / `resource()` to receive a typed `ctx.fail(reason, …)` keyed by the declared reason union. TypeScript catches `ctx.fail('typo')` at compile time, `data.reason` is auto-populated for observability, and the linter enforces conformance against the handler body. The `recovery` field is required descriptive metadata (≥ 5 words, lint-validated) — it's the single source of truth for the recovery hint that flows to the wire. Spread `ctx.recoveryFor('reason')` into `data` to opt the contract recovery onto the wire (the framework mirrors `data.recovery.hint` into `content[]` text). Override with explicit `{ recovery: { hint: '...' } }` when runtime context matters. Baseline codes (`InternalError`, `ServiceUnavailable`, `Timeout`, `ValidationError`, `SerializationError`, `RequestCancelled`) bubble freely and don't need declaring.
193
193
 
194
194
  ```ts
195
195
  errors: [
@@ -278,9 +278,9 @@ src/
278
278
 
279
279
  ## Skills
280
280
 
281
- Skills are modular instructions in `skills/` at the project root. Read them directly when a task matches — e.g., `skills/add-tool/SKILL.md` when adding a tool.
281
+ Skills are modular instructions in `framework-skills/` at the project root. Read them directly when a task matches — e.g., `framework-skills/add-tool/SKILL.md` when adding a tool. `bun run list-skills` prints the full registry. The directory is deliberately not `skills/`: Claude Code and Codex auto-load a plugin's root `skills/`, so a server that ships `.claude-plugin/` or `.codex-plugin/` would hand these development skills to every agent that installs it. Keep `skills/` free for skills meant for those agents.
282
282
 
283
- **Agent skill directory:** Copy skills into the directory your agent discovers (Claude Code: `.claude/skills/`, others: equivalent). This makes skills available as context without needing to reference `skills/` paths manually. After framework updates, run the `maintenance` skill — it re-syncs the agent directory automatically (Phase B).
283
+ **Agent skill directory:** Copy skills into the directory your agent discovers (Claude Code: `.claude/skills/`, others: equivalent). Skills then load as context without referencing `framework-skills/` paths. After framework updates, run the `maintenance` skill — Phase B re-syncs the agent directory.
284
284
 
285
285
  Available skills:
286
286
 
@@ -299,8 +299,9 @@ Available skills:
299
299
  | `tool-defs-analysis` | Read-only audit of MCP definition language across the surface — voice, leaks, defaults, recovery hints, output descriptions |
300
300
  | `code-simplifier` | Post-session cleanup against `git diff` — modernize syntax, consolidate duplication, align with the codebase |
301
301
  | `polish-docs-meta` | Finalize docs, README, metadata, and agent protocol for shipping |
302
- | `git-wrapup` | Land working-tree changes as a versioned commit + annotated tag — version bump, changelog, verify, tag. Local only. |
303
- | `release-and-publish` | Ship a release end-to-end across npm, MCP Registry, GitHub Releases (`.mcpb`), and GHCR |
302
+ | `git-wrapup` | Land working-tree changes as a commit stack — version bump, changelog, verify, commit by concern, release commit on top. No tag, no push to main; opens the release PR when the project declares release PR mode |
303
+ | `release-pr-review` | Review pass on an open release PR — simplifier + correctness review, fixup commits autosquashed into the stack, PR body kept in sync. Release PR mode only |
304
+ | `release-and-publish` | Fast-forward merge (release PR mode) + tag + push + npm + MCP Registry + GH Release + Docker. Picks up from `git-wrapup` |
304
305
  | `maintenance` | Investigate changelogs, adopt upstream changes, sync skills to agent dirs |
305
306
  | `orchestrations` | Chain task skills into a gated multi-phase pipeline — build-out, QA-fix, update-ship — when you can spawn sub-agents |
306
307
  | `report-issue-framework` | File a bug or feature request against `@cyanheads/mcp-ts-core` via `gh` CLI |
@@ -309,7 +310,7 @@ Available skills:
309
310
  | `api-auth` | Auth modes, scopes, JWT/OAuth |
310
311
  | `api-canvas` | DataCanvas: register tabular data, run SQL, export, plus the `spillover()` helper for big result sets — Tier 3 opt-in |
311
312
  | `api-config` | AppConfig, parseConfig, env vars |
312
- | `api-context` | Context interface, logger, state, progress |
313
+ | `api-context` | Context interface, RequestContext, logger, state, multi-round-trip input |
313
314
  | `api-errors` | McpError, JsonRpcErrorCode, error patterns |
314
315
  | `api-linter` | Definition linter rule catalog — invoked by `bun run lint:mcp` and `devcheck` |
315
316
  | `api-mirror` | MirrorService: persistent self-refreshing local mirror (embedded SQLite + FTS5) of a bulk upstream dataset — Tier 3 opt-in |
@@ -319,7 +320,7 @@ Available skills:
319
320
  | `api-utils` | Formatting, parsing, security, pagination, scheduling, telemetry helpers |
320
321
  | `api-workers` | Cloudflare Workers runtime |
321
322
 
322
- **Chaining skills into pipelines.** When the user wants a multi-phase effort — build this server out, QA-and-fix the surface, update-and-ship — *and you can spawn sub-agents*, `skills/orchestrations/SKILL.md` sequences the task skills above into a gated pipeline with verification at each step. Read it to drive the run. Optional: skip it if you can't orchestrate sub-agents, and ignore it entirely if you were *spawned* as one — you've already been scoped to a single phase.
323
+ **Chaining skills into pipelines.** When the user wants a multi-phase effort — build this server out, QA-and-fix the surface, update-and-ship — *and you can spawn sub-agents*, `framework-skills/orchestrations/SKILL.md` sequences the task skills above into a gated pipeline with verification at each step. Read it to drive the run. Optional: skip it if you can't orchestrate sub-agents, and ignore it entirely if you were *spawned* as one — you've already been scoped to a single phase.
323
324
 
324
325
  When you complete a skill's checklist, check the boxes and add a completion timestamp at the end (e.g., `Completed: 2026-03-11`).
325
326
 
@@ -335,13 +336,14 @@ When you complete a skill's checklist, check the boxes and add a completion time
335
336
  | `bun run rebuild` | Clean + build |
336
337
  | `bun run clean` | Remove build artifacts |
337
338
  | `bun run devcheck` | Lint + format + typecheck + security + changelog sync |
338
- | `bun run audit:refresh` | Delete `bun.lock`, reinstall, and re-run `bun audit`. Use when `devcheck` flags a transitive advisory — Bun's `update` is sticky on transitive resolutions, so the advisory may be a stale-lockfile false positive. If it survives the refresh, it's real. |
339
+ | `bun run audit:fix` | `bun audit fix` — upgrade vulnerable packages to the lowest safe version within existing ranges (`--dry-run` previews, `--latest` rewrites ranges). First response when `devcheck` flags a transitive advisory; then `bun update <name>`, then `bun dedupe` |
340
+ | `bun run audit:refresh` | Delete `bun.lock` and reinstall. Last resort after `audit:fix`, `bun update <name>`, and `bun dedupe` — re-resolves every ranged dep (the framework pin included) and rewrites the lockfile as `lockfileVersion: 2` |
339
341
  | `bun run tree` | Generate `docs/tree.md` |
340
342
  | `bun run list-skills` | Print project skill index (name, version, description) |
341
343
  | `bun run format` | Auto-fix formatting (safe fixes only) |
342
344
  | `bun run format:unsafe` | Also apply Biome's unsafe autofixes — review the diff; they can change behavior |
343
345
  | `bun run lint:mcp` | Validate MCP definitions against the linter rules |
344
- | `bun run lint:packaging` | Validate env var alignment between `manifest.json` and `server.json` |
346
+ | `bun run lint:packaging` | Packaging surface checks — `server.json`/`manifest.json` env-var parity, `user_config` wiring, plugin manifest identity and env contract (run by devcheck) |
345
347
  | `bun run bundle` | Build, pack, and clean a `.mcpb` for one-click Claude Desktop install |
346
348
  | `bun run test` | Run tests (Vitest — use `bun run test`, not `bun test`) |
347
349
  | `bun run start:stdio` | Production mode (stdio) — requires `bun run build` first |
@@ -353,9 +355,9 @@ When you complete a skill's checklist, check the boxes and add a completion time
353
355
 
354
356
  ## Bundling
355
357
 
356
- `bun run bundle` produces a `.mcpb` extension bundle for one-click install in Claude Desktop. The pack step is followed by `scripts/clean-mcpb.ts`, which prunes dev dependencies (`mcpb clean`) and strips two classes of `node_modules/**` content that root-anchored `.mcpbignore` patterns cannot reach: dependency-shipped agent docs (`skills/`, `.claude/`, `.agents/`, `SKILL.md`) and platform-specific native bindings, which would otherwise lock the bundle to the platform it was packed on. MCPB is stdio-only — HTTP deployments are unaffected. Delete `manifest.json` and `.mcpbignore` if not shipping MCPB bundles; `lint:packaging` skips cleanly.
358
+ `bun run bundle` produces a `.mcpb` extension bundle for one-click install in Claude Desktop. The pack step is followed by `scripts/clean-mcpb.ts`, which prunes dev dependencies (`mcpb clean`) and strips two classes of `node_modules/**` content that root-anchored `.mcpbignore` patterns cannot reach: dependency-shipped agent docs (`framework-skills/`, `skills/`, `.claude/`, `.agents/`, `SKILL.md`) and platform-specific native bindings, which would otherwise lock the bundle to the platform it was packed on. MCPB is stdio-only — HTTP deployments are unaffected. Delete `manifest.json` and `.mcpbignore` if not shipping MCPB bundles; `lint:packaging` skips cleanly.
357
359
 
358
- **Adding an env var requires both files:** `server.json` (`environmentVariables[]`) and `manifest.json` (`mcp_config.env` + `user_config`). `lint:packaging` (run by `devcheck`) verifies the env var names match.
360
+ **Adding an env var requires both files:** `server.json` (registry discovery, `environmentVariables[]`) and `manifest.json` (bundle install UX, `mcp_config.env` + `user_config`). `lint:packaging` (run by `devcheck`) verifies the env var names match, that every `user_config` option is wired into `mcp_config.env` as `"X": "${user_config.X}"` (the host substitutes nothing else — `"${X}"` reaches the server as that literal string), and that an optional string option carries `"default": ""`. A user-supplied variable also goes into the plugin manifests: `.claude-plugin/plugin.json` `userConfig` + `${user_config.<option>}` in `env`, and `.codex-plugin/mcp.json` `env_vars`.
359
361
 
360
362
  ---
361
363
 
@@ -380,7 +382,7 @@ security: false # optional — true ONLY for a source
380
382
 
381
383
  `agent-notes` is an optional free-form field for maintenance agents processing the release downstream. Content here won't appear in the rendered CHANGELOG — it's consumed by agents running the `maintenance` skill. Use it for adoption instructions that don't fit the human-facing sections: new files to create, fields to populate, one-time migration steps. Omit entirely when there's nothing to say.
382
384
 
383
- **Section order** (Keep a Changelog): Added, Changed, Deprecated, Removed, Fixed, Security. Include only sections with entries — don't ship empty headers.
385
+ **Section order:** the Keep a Changelog sequence — Added, Changed, Deprecated, Removed, Fixed, Security — then `Dependencies` last. Include only sections with entries — don't ship empty headers.
384
386
 
385
387
  **Tag annotations** render as GitHub Release bodies via `--notes-from-tag`. They must be structured markdown — never a flat comma-separated string. Subject omits the version number (GitHub prepends it). See `changelog/template.md` for the full format reference.
386
388
 
@@ -412,7 +414,7 @@ import { getMyService } from '@/services/my-domain/my-service.js';
412
414
  - [ ] If wrapping external API: tests include at least one sparse payload case with omitted upstream fields
413
415
  - [ ] Registered in `createApp()` arrays (directly or via barrel exports). Conditional registration (e.g. `commandToolDefinitions` behind `OBSIDIAN_ENABLE_COMMANDS`) happens in `src/index.ts`, not in the barrel
414
416
  - [ ] Tests use `createMockContext()` from `@cyanheads/mcp-ts-core/testing`
415
- - [ ] `.codex-plugin/plugin.json` populated — `name`, `version`, `description`, `repository`, `license` from `package.json`; `interface.displayName` = package name; `interface.shortDescription` from `package.json` description
416
- - [ ] `.codex-plugin/mcp.json` updated — server name key matches `package.json` name; env vars added for any required API keys
417
- - [ ] `.claude-plugin/plugin.json` populated — `name`, `version`, `description`, `repository`, `license` from `package.json`; inline `mcpServers` entry with server name key, env vars for any required API keys
417
+ - [ ] `.codex-plugin/plugin.json` populated — `name`, `version`, `description`, `repository`, `license` from `package.json`; `interface.displayName` = the unscoped repo name (never the npm scope — `lint:packaging` enforces this); `interface.shortDescription` from `package.json` description
418
+ - [ ] `.codex-plugin/mcp.json` updated — server name key is the unscoped repo name; every user-supplied variable (API key, instance URL) is listed in `env_vars` so Codex forwards it from the user's environment. Never write `"KEY": ""` into `env` — an empty value replaces the user's exported key and is read as unset
419
+ - [ ] `.claude-plugin/plugin.json` populated — `name`, `version`, `description`, `author`, `repository`, `license`, `keywords` from `package.json`; inline `mcpServers` entry keyed by the unscoped repo name. Every user-supplied variable is declared under `userConfig` (`type`, `title`, `description`; `sensitive: true` for keys and tokens; `required: true` or `default: ""`) and referenced from `env` as `"KEY": "${user_config.<option>}"` — mirror the `user_config` block in `manifest.json`. Never write `"KEY": ""` into `env`
418
420
  - [ ] `bun run devcheck` passes
package/CLAUDE.md CHANGED
@@ -1,11 +1,11 @@
1
1
  # Agent Protocol
2
2
 
3
3
  **Server:** obsidian-mcp-server
4
- **Version:** 3.5.1
5
- **Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.12.5`
6
- **Engines:** Bun ≥1.3.0, Node ≥24.0.0
4
+ **Version:** 3.5.3
5
+ **Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.13.0`
6
+ **Engines:** Bun ≥1.4.0, Node ≥24.0.0
7
7
  **MCP SDK:** `@modelcontextprotocol/server` ^2.0.0
8
- **Zod:** ^4.5.4
8
+ **Zod:** ^4.6.1
9
9
 
10
10
  > **Read the framework docs first:** `node_modules/@cyanheads/mcp-ts-core/CLAUDE.md` contains the full API reference — builders, Context, error codes, exports, patterns. This file covers server-specific conventions only.
11
11
 
@@ -189,7 +189,7 @@ The framework also provides `ctx.state`. It isn't used by this server — Obsidi
189
189
 
190
190
  Handlers throw — the framework catches, classifies, and formats.
191
191
 
192
- **Recommended: typed error contract.** Declare `errors: [{ reason, code, when, recovery, retryable? }]` on `tool()` / `resource()` to receive a typed `ctx.fail(reason, …)` keyed by the declared reason union. TypeScript catches `ctx.fail('typo')` at compile time, `data.reason` is auto-populated for observability, and the linter enforces conformance against the handler body. The `recovery` field is required descriptive metadata (≥ 5 words, lint-validated) — it's the single source of truth for the recovery hint that flows to the wire. Spread `ctx.recoveryFor('reason')` into `data` to opt the contract recovery onto the wire (the framework mirrors `data.recovery.hint` into `content[]` text). Override with explicit `{ recovery: { hint: '...' } }` when runtime context matters. Baseline codes (`InternalError`, `ServiceUnavailable`, `Timeout`, `ValidationError`, `SerializationError`) bubble freely and don't need declaring.
192
+ **Recommended: typed error contract.** Declare `errors: [{ reason, code, when, recovery, retryable? }]` on `tool()` / `resource()` to receive a typed `ctx.fail(reason, …)` keyed by the declared reason union. TypeScript catches `ctx.fail('typo')` at compile time, `data.reason` is auto-populated for observability, and the linter enforces conformance against the handler body. The `recovery` field is required descriptive metadata (≥ 5 words, lint-validated) — it's the single source of truth for the recovery hint that flows to the wire. Spread `ctx.recoveryFor('reason')` into `data` to opt the contract recovery onto the wire (the framework mirrors `data.recovery.hint` into `content[]` text). Override with explicit `{ recovery: { hint: '...' } }` when runtime context matters. Baseline codes (`InternalError`, `ServiceUnavailable`, `Timeout`, `ValidationError`, `SerializationError`, `RequestCancelled`) bubble freely and don't need declaring.
193
193
 
194
194
  ```ts
195
195
  errors: [
@@ -278,9 +278,9 @@ src/
278
278
 
279
279
  ## Skills
280
280
 
281
- Skills are modular instructions in `skills/` at the project root. Read them directly when a task matches — e.g., `skills/add-tool/SKILL.md` when adding a tool.
281
+ Skills are modular instructions in `framework-skills/` at the project root. Read them directly when a task matches — e.g., `framework-skills/add-tool/SKILL.md` when adding a tool. `bun run list-skills` prints the full registry. The directory is deliberately not `skills/`: Claude Code and Codex auto-load a plugin's root `skills/`, so a server that ships `.claude-plugin/` or `.codex-plugin/` would hand these development skills to every agent that installs it. Keep `skills/` free for skills meant for those agents.
282
282
 
283
- **Agent skill directory:** Copy skills into the directory your agent discovers (Claude Code: `.claude/skills/`, others: equivalent). This makes skills available as context without needing to reference `skills/` paths manually. After framework updates, run the `maintenance` skill — it re-syncs the agent directory automatically (Phase B).
283
+ **Agent skill directory:** Copy skills into the directory your agent discovers (Claude Code: `.claude/skills/`, others: equivalent). Skills then load as context without referencing `framework-skills/` paths. After framework updates, run the `maintenance` skill — Phase B re-syncs the agent directory.
284
284
 
285
285
  Available skills:
286
286
 
@@ -299,8 +299,9 @@ Available skills:
299
299
  | `tool-defs-analysis` | Read-only audit of MCP definition language across the surface — voice, leaks, defaults, recovery hints, output descriptions |
300
300
  | `code-simplifier` | Post-session cleanup against `git diff` — modernize syntax, consolidate duplication, align with the codebase |
301
301
  | `polish-docs-meta` | Finalize docs, README, metadata, and agent protocol for shipping |
302
- | `git-wrapup` | Land working-tree changes as a versioned commit + annotated tag — version bump, changelog, verify, tag. Local only. |
303
- | `release-and-publish` | Ship a release end-to-end across npm, MCP Registry, GitHub Releases (`.mcpb`), and GHCR |
302
+ | `git-wrapup` | Land working-tree changes as a commit stack — version bump, changelog, verify, commit by concern, release commit on top. No tag, no push to main; opens the release PR when the project declares release PR mode |
303
+ | `release-pr-review` | Review pass on an open release PR — simplifier + correctness review, fixup commits autosquashed into the stack, PR body kept in sync. Release PR mode only |
304
+ | `release-and-publish` | Fast-forward merge (release PR mode) + tag + push + npm + MCP Registry + GH Release + Docker. Picks up from `git-wrapup` |
304
305
  | `maintenance` | Investigate changelogs, adopt upstream changes, sync skills to agent dirs |
305
306
  | `orchestrations` | Chain task skills into a gated multi-phase pipeline — build-out, QA-fix, update-ship — when you can spawn sub-agents |
306
307
  | `report-issue-framework` | File a bug or feature request against `@cyanheads/mcp-ts-core` via `gh` CLI |
@@ -309,7 +310,7 @@ Available skills:
309
310
  | `api-auth` | Auth modes, scopes, JWT/OAuth |
310
311
  | `api-canvas` | DataCanvas: register tabular data, run SQL, export, plus the `spillover()` helper for big result sets — Tier 3 opt-in |
311
312
  | `api-config` | AppConfig, parseConfig, env vars |
312
- | `api-context` | Context interface, logger, state, progress |
313
+ | `api-context` | Context interface, RequestContext, logger, state, multi-round-trip input |
313
314
  | `api-errors` | McpError, JsonRpcErrorCode, error patterns |
314
315
  | `api-linter` | Definition linter rule catalog — invoked by `bun run lint:mcp` and `devcheck` |
315
316
  | `api-mirror` | MirrorService: persistent self-refreshing local mirror (embedded SQLite + FTS5) of a bulk upstream dataset — Tier 3 opt-in |
@@ -319,7 +320,7 @@ Available skills:
319
320
  | `api-utils` | Formatting, parsing, security, pagination, scheduling, telemetry helpers |
320
321
  | `api-workers` | Cloudflare Workers runtime |
321
322
 
322
- **Chaining skills into pipelines.** When the user wants a multi-phase effort — build this server out, QA-and-fix the surface, update-and-ship — *and you can spawn sub-agents*, `skills/orchestrations/SKILL.md` sequences the task skills above into a gated pipeline with verification at each step. Read it to drive the run. Optional: skip it if you can't orchestrate sub-agents, and ignore it entirely if you were *spawned* as one — you've already been scoped to a single phase.
323
+ **Chaining skills into pipelines.** When the user wants a multi-phase effort — build this server out, QA-and-fix the surface, update-and-ship — *and you can spawn sub-agents*, `framework-skills/orchestrations/SKILL.md` sequences the task skills above into a gated pipeline with verification at each step. Read it to drive the run. Optional: skip it if you can't orchestrate sub-agents, and ignore it entirely if you were *spawned* as one — you've already been scoped to a single phase.
323
324
 
324
325
  When you complete a skill's checklist, check the boxes and add a completion timestamp at the end (e.g., `Completed: 2026-03-11`).
325
326
 
@@ -335,13 +336,14 @@ When you complete a skill's checklist, check the boxes and add a completion time
335
336
  | `bun run rebuild` | Clean + build |
336
337
  | `bun run clean` | Remove build artifacts |
337
338
  | `bun run devcheck` | Lint + format + typecheck + security + changelog sync |
338
- | `bun run audit:refresh` | Delete `bun.lock`, reinstall, and re-run `bun audit`. Use when `devcheck` flags a transitive advisory — Bun's `update` is sticky on transitive resolutions, so the advisory may be a stale-lockfile false positive. If it survives the refresh, it's real. |
339
+ | `bun run audit:fix` | `bun audit fix` — upgrade vulnerable packages to the lowest safe version within existing ranges (`--dry-run` previews, `--latest` rewrites ranges). First response when `devcheck` flags a transitive advisory; then `bun update <name>`, then `bun dedupe` |
340
+ | `bun run audit:refresh` | Delete `bun.lock` and reinstall. Last resort after `audit:fix`, `bun update <name>`, and `bun dedupe` — re-resolves every ranged dep (the framework pin included) and rewrites the lockfile as `lockfileVersion: 2` |
339
341
  | `bun run tree` | Generate `docs/tree.md` |
340
342
  | `bun run list-skills` | Print project skill index (name, version, description) |
341
343
  | `bun run format` | Auto-fix formatting (safe fixes only) |
342
344
  | `bun run format:unsafe` | Also apply Biome's unsafe autofixes — review the diff; they can change behavior |
343
345
  | `bun run lint:mcp` | Validate MCP definitions against the linter rules |
344
- | `bun run lint:packaging` | Validate env var alignment between `manifest.json` and `server.json` |
346
+ | `bun run lint:packaging` | Packaging surface checks — `server.json`/`manifest.json` env-var parity, `user_config` wiring, plugin manifest identity and env contract (run by devcheck) |
345
347
  | `bun run bundle` | Build, pack, and clean a `.mcpb` for one-click Claude Desktop install |
346
348
  | `bun run test` | Run tests (Vitest — use `bun run test`, not `bun test`) |
347
349
  | `bun run start:stdio` | Production mode (stdio) — requires `bun run build` first |
@@ -353,9 +355,9 @@ When you complete a skill's checklist, check the boxes and add a completion time
353
355
 
354
356
  ## Bundling
355
357
 
356
- `bun run bundle` produces a `.mcpb` extension bundle for one-click install in Claude Desktop. The pack step is followed by `scripts/clean-mcpb.ts`, which prunes dev dependencies (`mcpb clean`) and strips two classes of `node_modules/**` content that root-anchored `.mcpbignore` patterns cannot reach: dependency-shipped agent docs (`skills/`, `.claude/`, `.agents/`, `SKILL.md`) and platform-specific native bindings, which would otherwise lock the bundle to the platform it was packed on. MCPB is stdio-only — HTTP deployments are unaffected. Delete `manifest.json` and `.mcpbignore` if not shipping MCPB bundles; `lint:packaging` skips cleanly.
358
+ `bun run bundle` produces a `.mcpb` extension bundle for one-click install in Claude Desktop. The pack step is followed by `scripts/clean-mcpb.ts`, which prunes dev dependencies (`mcpb clean`) and strips two classes of `node_modules/**` content that root-anchored `.mcpbignore` patterns cannot reach: dependency-shipped agent docs (`framework-skills/`, `skills/`, `.claude/`, `.agents/`, `SKILL.md`) and platform-specific native bindings, which would otherwise lock the bundle to the platform it was packed on. MCPB is stdio-only — HTTP deployments are unaffected. Delete `manifest.json` and `.mcpbignore` if not shipping MCPB bundles; `lint:packaging` skips cleanly.
357
359
 
358
- **Adding an env var requires both files:** `server.json` (`environmentVariables[]`) and `manifest.json` (`mcp_config.env` + `user_config`). `lint:packaging` (run by `devcheck`) verifies the env var names match.
360
+ **Adding an env var requires both files:** `server.json` (registry discovery, `environmentVariables[]`) and `manifest.json` (bundle install UX, `mcp_config.env` + `user_config`). `lint:packaging` (run by `devcheck`) verifies the env var names match, that every `user_config` option is wired into `mcp_config.env` as `"X": "${user_config.X}"` (the host substitutes nothing else — `"${X}"` reaches the server as that literal string), and that an optional string option carries `"default": ""`. A user-supplied variable also goes into the plugin manifests: `.claude-plugin/plugin.json` `userConfig` + `${user_config.<option>}` in `env`, and `.codex-plugin/mcp.json` `env_vars`.
359
361
 
360
362
  ---
361
363
 
@@ -380,7 +382,7 @@ security: false # optional — true ONLY for a source
380
382
 
381
383
  `agent-notes` is an optional free-form field for maintenance agents processing the release downstream. Content here won't appear in the rendered CHANGELOG — it's consumed by agents running the `maintenance` skill. Use it for adoption instructions that don't fit the human-facing sections: new files to create, fields to populate, one-time migration steps. Omit entirely when there's nothing to say.
382
384
 
383
- **Section order** (Keep a Changelog): Added, Changed, Deprecated, Removed, Fixed, Security. Include only sections with entries — don't ship empty headers.
385
+ **Section order:** the Keep a Changelog sequence — Added, Changed, Deprecated, Removed, Fixed, Security — then `Dependencies` last. Include only sections with entries — don't ship empty headers.
384
386
 
385
387
  **Tag annotations** render as GitHub Release bodies via `--notes-from-tag`. They must be structured markdown — never a flat comma-separated string. Subject omits the version number (GitHub prepends it). See `changelog/template.md` for the full format reference.
386
388
 
@@ -412,7 +414,7 @@ import { getMyService } from '@/services/my-domain/my-service.js';
412
414
  - [ ] If wrapping external API: tests include at least one sparse payload case with omitted upstream fields
413
415
  - [ ] Registered in `createApp()` arrays (directly or via barrel exports). Conditional registration (e.g. `commandToolDefinitions` behind `OBSIDIAN_ENABLE_COMMANDS`) happens in `src/index.ts`, not in the barrel
414
416
  - [ ] Tests use `createMockContext()` from `@cyanheads/mcp-ts-core/testing`
415
- - [ ] `.codex-plugin/plugin.json` populated — `name`, `version`, `description`, `repository`, `license` from `package.json`; `interface.displayName` = package name; `interface.shortDescription` from `package.json` description
416
- - [ ] `.codex-plugin/mcp.json` updated — server name key matches `package.json` name; env vars added for any required API keys
417
- - [ ] `.claude-plugin/plugin.json` populated — `name`, `version`, `description`, `repository`, `license` from `package.json`; inline `mcpServers` entry with server name key, env vars for any required API keys
417
+ - [ ] `.codex-plugin/plugin.json` populated — `name`, `version`, `description`, `repository`, `license` from `package.json`; `interface.displayName` = the unscoped repo name (never the npm scope — `lint:packaging` enforces this); `interface.shortDescription` from `package.json` description
418
+ - [ ] `.codex-plugin/mcp.json` updated — server name key is the unscoped repo name; every user-supplied variable (API key, instance URL) is listed in `env_vars` so Codex forwards it from the user's environment. Never write `"KEY": ""` into `env` — an empty value replaces the user's exported key and is read as unset
419
+ - [ ] `.claude-plugin/plugin.json` populated — `name`, `version`, `description`, `author`, `repository`, `license`, `keywords` from `package.json`; inline `mcpServers` entry keyed by the unscoped repo name. Every user-supplied variable is declared under `userConfig` (`type`, `title`, `description`; `sensitive: true` for keys and tokens; `required: true` or `default: ""`) and referenced from `env` as `"KEY": "${user_config.<option>}"` — mirror the `user_config` block in `manifest.json`. Never write `"KEY": ""` into `env`
418
420
  - [ ] `bun run devcheck` passes
package/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
 
8
8
  <div align="center">
9
9
 
10
- [![Version](https://img.shields.io/badge/Version-3.5.1-blue.svg?style=flat-square)](./CHANGELOG.md) [![License](https://img.shields.io/badge/License-Apache%202.0-orange.svg?style=flat-square)](./LICENSE) [![Docker](https://img.shields.io/badge/Docker-ghcr.io-2496ED?style=flat-square&logo=docker&logoColor=white)](https://github.com/users/cyanheads/packages/container/package/obsidian-mcp-server) [![MCP SDK](https://img.shields.io/badge/MCP%20SDK-^2.0.0-green.svg?style=flat-square)](https://modelcontextprotocol.io/) [![npm](https://img.shields.io/npm/v/obsidian-mcp-server?style=flat-square&logo=npm&logoColor=white)](https://www.npmjs.com/package/obsidian-mcp-server) [![TypeScript](https://img.shields.io/badge/TypeScript-^7.0.2-3178C6.svg?style=flat-square)](https://www.typescriptlang.org/) [![Bun](https://img.shields.io/badge/Bun-v1.3.0-blueviolet.svg?style=flat-square)](https://bun.sh/)
10
+ [![Version](https://img.shields.io/badge/Version-3.5.3-blue.svg?style=flat-square)](./CHANGELOG.md) [![License](https://img.shields.io/badge/License-Apache%202.0-orange.svg?style=flat-square)](./LICENSE) [![Docker](https://img.shields.io/badge/Docker-ghcr.io-2496ED?style=flat-square&logo=docker&logoColor=white)](https://github.com/users/cyanheads/packages/container/package/obsidian-mcp-server) [![MCP SDK](https://img.shields.io/badge/MCP%20SDK-^2.0.0-green.svg?style=flat-square)](https://modelcontextprotocol.io/) [![npm](https://img.shields.io/npm/v/obsidian-mcp-server?style=flat-square&logo=npm&logoColor=white)](https://www.npmjs.com/package/obsidian-mcp-server) [![TypeScript](https://img.shields.io/badge/TypeScript-^7.0.2-3178C6.svg?style=flat-square)](https://www.typescriptlang.org/) [![Bun](https://img.shields.io/badge/Bun-v1.4.0%2B-blueviolet.svg?style=flat-square)](https://bun.sh/)
11
11
 
12
12
  </div>
13
13
 
@@ -49,7 +49,7 @@ Read a note in one of four projections, addressed by vault path, the active file
49
49
  - `format: "content"` — raw markdown body
50
50
  - `format: "full"` — content, frontmatter, tags, and file metadata; pass `includeLinks: true` to also parse outgoing wiki and markdown link references from the body (vault-internal only — external URLs are filtered)
51
51
  - `format: "document-map"` — catalog of headings, block references, and frontmatter fields
52
- - `format: "section"` — single heading/block/frontmatter section value (requires `section`); heading sections include the full subtree under that heading
52
+ - `format: "section"` — single heading/block/frontmatter section value (requires `section`); heading sections include the full subtree under that heading. The response echoes the locator the read resolved to in `sectionTarget` as a full `Parent::Child` path, and when a bare leaf name matches several headings it lists every colliding path in `candidates` — the read still returns the first match
53
53
 
54
54
  Pair the document-map projection with `obsidian_patch_note` to discover edit targets before patching.
55
55
 
@@ -136,7 +136,9 @@ Add, remove, or list tags on a note. Operates on one of two representations, def
136
136
  - `location: 'inline'` — only inline `#tag` syntax in the body; `add` appends `#tag` at end-of-file
137
137
  - `location: 'both'` — opt-in reconciliation across both representations
138
138
 
139
- `add` ensures the tag is present in the requested location(s); `remove` strips it; `list` ignores the input `tags` array. Inline `#tag` occurrences inside fenced code blocks are intentionally left alone.
139
+ `add` ensures the tag is present in the requested location(s); `remove` strips it; `list` ignores the input `tags` array.
140
+
141
+ Inline `#tag` detection skips code spans (fenced and inline), link spans (`[[...]]`, `[text](...)`, `[text][ref]`) — so a heading anchor, block anchor, or wikilink alias is never read as a tag or rewritten by a removal — and a hash escaped as `\#`. A `#` inside an HTML comment or a math span is still counted. `list` and `remove` run the same detection, so what `list` reports is what `remove` can reach.
140
142
 
141
143
  Inline mode reads and writes the note body only — a `#` inside a YAML scalar is frontmatter, so it is neither listed as an inline tag nor rewritten by a removal. Removing an inline tag takes exactly one adjacent horizontal space with it — the one before the tag, or the one after when no space precedes it; every other byte survives, including nested list indentation, four-space indented code blocks, trailing two-space hard line breaks, and table cell padding.
142
144
 
@@ -210,7 +212,7 @@ Obsidian-specific:
210
212
 
211
213
  - Wraps the [Obsidian Local REST API](https://github.com/coddingtonbear/obsidian-local-rest-api) plugin — typed client, deterministic error mapping
212
214
  - Section-aware editing across headings, block references, and frontmatter fields via `PATCH`-with-target operations
213
- - Tag reconciliation across both representations: frontmatter `tags:` array and inline `#tag` syntax (skipping fenced code blocks)
215
+ - Tag reconciliation across both representations: frontmatter `tags:` array and inline `#tag` syntax (skipping code spans, link spans, and hashes escaped as `\#`)
214
216
  - Search across up to three modes: text, JSONLogic, and (when the plugin is reachable) BM25-ranked Omnisearch — cursor-paginated per the MCP 2025-11-25 spec, with per-file match clipping in text mode
215
217
  - Required human-in-the-loop confirmation for destructive deletes — a multi-round-trip `input_required` round served on both protocol revisions, with no unconfirmed path through the tool
216
218
  - Folder-scoped read/write permissions via `OBSIDIAN_READ_PATHS` / `OBSIDIAN_WRITE_PATHS` and a global `OBSIDIAN_READ_ONLY` kill switch — denies are typed `path_forbidden` with the active scope echoed back in the error data
@@ -266,9 +268,9 @@ MCP_TRANSPORT_TYPE=http OBSIDIAN_API_KEY=... bun run start:http
266
268
 
267
269
  ### Prerequisites
268
270
 
269
- - [Bun v1.3.0](https://bun.sh/) or higher (or Node.js v24+).
271
+ - [Bun v1.4.0](https://bun.sh/) or higher (or Node.js v24+).
270
272
  - The [Obsidian Local REST API](https://github.com/coddingtonbear/obsidian-local-rest-api) plugin, **v4.0.0 through v5.x**, installed and enabled in your vault. Generate an API key in **Settings → Community Plugins → Local REST API** and copy it into `OBSIDIAN_API_KEY`. Plugin v6.0 removes the markdown-patch 1.x wire format this server pins for section-targeted writes and the document map.
271
- - Periodic-note targets (`target: { "type": "periodic" }`) additionally need plugin **v5.0.1 or earlier** — v5.0.2 removed the built-in `/periodic/` routes. Every other target type is unaffected.
273
+ - Periodic-note targets (`target: { "type": "periodic" }`) work across that whole range: natively on plugin **v5.0.1 and earlier**, and on **v5.0.2 and later** — which moved the `/periodic/` routes out of the plugin — once the companion [periodic-notes API extension](https://github.com/coddingtonbear/obsidian-local-rest-api-periodic-notes) is installed. Without that extension on v5.0.2+, periodic targets fail with a `periodic_unsupported` error naming it; `obsidian://status` lists the registered extensions if you want to check first. Every other target type is unaffected.
272
274
  - An MCP client that can answer an input request (elicitation). `obsidian_delete_note` always asks for confirmation before deleting, so a client without that support can read and write notes but cannot delete one.
273
275
  - This server defaults to `http://127.0.0.1:27123` for simplicity. Enable **"Non-encrypted (HTTP) Server"** in the plugin settings to use it. To use the always-on HTTPS port instead, set `OBSIDIAN_BASE_URL=https://127.0.0.1:27124`; the plugin's self-signed cert is handled by `OBSIDIAN_VERIFY_SSL=false` (the default).
274
276
 
@@ -389,7 +391,7 @@ See [`CLAUDE.md`](./CLAUDE.md) for development guidelines and architectural rule
389
391
 
390
392
  Bugs, feature requests, and documentation gaps belong in an issue — see [CONTRIBUTING.md](.github/CONTRIBUTING.md) for what makes one actionable, and [CODE_OF_CONDUCT.md](.github/CODE_OF_CONDUCT.md) for how we work together. Security reports go through [SECURITY.md](.github/SECURITY.md), never a public issue.
391
393
 
392
- Pull requests are welcome for small, self-contained fixes. Run checks and tests before submitting:
394
+ Run checks and tests before submitting:
393
395
 
394
396
  ```sh
395
397
  bun run devcheck
@@ -0,0 +1,27 @@
1
+ ---
2
+ summary: "Frontmatter boundary, inline tag detection, and section reads now share one consistent boundary and resolution logic; list_notes reports directory_missing/path_is_file instead of a generic note_missing; periodic-note targets get a periodic_unsupported error naming the missing plugin extension instead of a bare 404."
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 3.5.2 — 2026-09-09
8
+
9
+ ## Changed
10
+
11
+ - **`obsidian_get_note` section reads echo the resolved heading path** — a bare leaf target reports back the full `Parent::Child` path it matched in `sectionTarget`, and every colliding heading in `candidates` when more than one shares that leaf; the read still returns the first match ([#107](https://github.com/cyanheads/obsidian-mcp-server/issues/107)).
12
+ - **`obsidian_manage_tags` inline `#tag` detection skips link spans and escaped hashes** — `[[wikilink#Heading]]`, `[text](url#frag)`, and `[text][ref]` are no longer read or rewritten as tags, and a `\#` is recognized as an escaped literal hash; `list` and `remove` share the same detection so they agree on what a tag is ([#119](https://github.com/cyanheads/obsidian-mcp-server/issues/119)).
13
+ - **`obsidian_list_notes` reports `directory_missing` and `path_is_file` in place of `note_missing`** — a folder that doesn't exist or holds no files gets `directory_missing`; a `path` that names a file gets `path_is_file` ([#105](https://github.com/cyanheads/obsidian-mcp-server/issues/105)).
14
+
15
+ ## Fixed
16
+
17
+ - **The frontmatter fence regex now agrees with `splice()` on an empty properties block** — `section-extractor`'s line-scan boundary previously used a different rule than `frontmatter-ops`'s splice, so a note with an empty `---\n---` block or a fence carrying trailing whitespace could hide body content from section reads; both now resolve the boundary through the same `splice()` call ([#118](https://github.com/cyanheads/obsidian-mcp-server/issues/118)).
18
+ - **Periodic-note targets get a typed `periodic_unsupported` error on Local REST API v5.0.2+ without the companion extension** — that plugin version removed the built-in `/periodic/` routes, and every periodic-target tool previously surfaced the resulting 404 as `periodic_not_found`, indistinguishable from "no note for that period." A memoized capability probe against `GET /`'s `apiExtensions` now tells the two apart and names `local-rest-api-periodic-notes` in the recovery hint ([#103](https://github.com/cyanheads/obsidian-mcp-server/issues/103)).
19
+
20
+ ## Dependencies
21
+
22
+ - `@cyanheads/mcp-ts-core` ^0.12.5 → ^0.12.8
23
+ - `undici` ^8.10.1 → ^8.10.2
24
+ - `@biomejs/biome` ^2.5.11 → ^2.5.12 (dev)
25
+ - `@types/node` ^26.4.0 → ^26.4.1 (dev)
26
+ - `tsc-alias` ^1.9.3 → ^1.9.4 (dev)
27
+ - `vitest` ^4.1.11 → ^5.0.0 (dev)
@@ -0,0 +1,26 @@
1
+ ---
2
+ summary: "Bun engines floor rises to >=1.4.0 for mcp-ts-core 0.13.0; the development skill tree moves to framework-skills/ so installing the plugin no longer loads it into the agent; empty or placeholder ${...} env values now read as unset, and plugin manifests wire OBSIDIAN_* through userConfig/env_vars instead of empty-string placeholders."
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 3.5.3 — 2026-09-13
8
+
9
+ ## Changed
10
+
11
+ - **Bun engines floor raised to `>=1.4.0`** — required by mcp-ts-core 0.13.0.
12
+ - **Development skills moved from `skills/` to `framework-skills/`** — Claude Code and Codex auto-load a plugin's root `skills/`, so installing this server's plugin no longer loads its development skills into the installing agent ([cyanheads/mcp-ts-core#428](https://github.com/cyanheads/mcp-ts-core/issues/428)).
13
+
14
+ ## Fixed
15
+
16
+ - **An empty or whole-value `${...}` env value now reads as unset** — `OBSIDIAN_REQUEST_TIMEOUT_MS=''` starts with the default timeout and `OBSIDIAN_API_KEY='${OBSIDIAN_API_KEY}'` fails at startup as a missing key rather than as a format error; the server's own redundant empty-string guards on `baseUrl`/`omnisearchUrl` were removed as a result ([cyanheads/mcp-ts-core#427](https://github.com/cyanheads/mcp-ts-core/issues/427)).
17
+ - **A cancelled single-request HTTP POST's SSE stream now closes immediately**, instead of waiting for keep-alive or session expiry ([cyanheads/mcp-ts-core#401](https://github.com/cyanheads/mcp-ts-core/issues/401)).
18
+ - **Plugin manifests no longer ship empty-string env placeholders** — `manifest.json` and `.claude-plugin/plugin.json` set `OBSIDIAN_API_KEY`/`OBSIDIAN_BASE_URL` to `""`, which overrides a user's exported value with an unset one; both now source them via `userConfig` + `${user_config.<key>}`, and `.codex-plugin/mcp.json` lists them in `env_vars`.
19
+
20
+ ## Dependencies
21
+
22
+ - `@cyanheads/mcp-ts-core` ^0.12.8 → ^0.13.0
23
+ - `zod` ^4.5.4 → ^4.6.1
24
+ - `@biomejs/biome` ^2.5.12 → ^2.5.13
25
+ - `@types/node` ^26.4.1 → ^26.5.1
26
+ - `ignore` ^7.0.8 → ^7.0.9
@@ -117,30 +117,13 @@ security: false
117
117
  in that unrelated item's metadata.
118
118
 
119
119
  TAG ANNOTATIONS — the annotated tag body renders as the GitHub Release body
120
- via `gh release create --notes-from-tag`. The tag is a derivative of this
121
- changelog entry — a condensed, scannable version, not a copy. Format:
122
-
123
- <theme — omit version number, GitHub prepends it>
124
- ← blank line
125
- <1-2 sentence context: what this release does>
126
- ← blank line
127
- Dependency bumps: ← section header
128
- ← blank line
129
- - `@cyanheads/mcp-ts-core` ^0.9.1 → ^0.9.6 ← bullet
130
- ← blank line
131
- Changed: ← only sections with entries
132
- ← blank line
133
- - `format()` output includes `query` in text mode
134
- ← blank line
135
- Added:
136
- ← blank line
137
- - `manifest.json` scaffolded for MCPB bundle support
138
- - Install badges (Claude Desktop, Cursor, VS Code)
139
- ← blank line
140
- <N> tests pass; `bun run devcheck` clean. ← footer
141
-
142
- Never a flat comma-separated string. Always structured markdown with
143
- sections. The tag must scan well as a rendered GitHub Release page.
120
+ via `gh release create --notes-from-tag`. It is a condensed digest of this
121
+ entry, never a copy, and its format is owned by the `release-and-publish`
122
+ skill (step 4, "Create the annotated tag"): the entry's `summary:` as the
123
+ theme line without the version, flat headline bullets — no Keep-a-Changelog
124
+ section headers, no gates line — at most one deps line, issue backlinks,
125
+ and the changelog link last. In release-PR mode the `git-wrapup` skill
126
+ authors that digest as the PR body's `## Changes` and the tag copies it.
144
127
  -->
145
128
 
146
129
  ## Added
@@ -6,14 +6,14 @@
6
6
  import { z } from '@cyanheads/mcp-ts-core';
7
7
  declare const ServerConfigSchema: z.ZodObject<{
8
8
  apiKey: z.ZodString;
9
- baseUrl: z.ZodPreprocess<z.ZodDefault<z.ZodString>, unknown>;
9
+ baseUrl: z.ZodDefault<z.ZodString>;
10
10
  verifySsl: z.ZodDefault<z.ZodUnion<readonly [z.ZodBoolean, z.ZodCodec<z.ZodString, z.ZodBoolean>]>>;
11
11
  requestTimeoutMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
12
12
  enableCommands: z.ZodDefault<z.ZodUnion<readonly [z.ZodBoolean, z.ZodCodec<z.ZodString, z.ZodBoolean>]>>;
13
13
  readPaths: z.ZodPreprocess<z.ZodPipe<z.ZodOptional<z.ZodArray<z.ZodString>>, z.ZodTransform<string[] | undefined, string[] | undefined>>, unknown>;
14
14
  writePaths: z.ZodPreprocess<z.ZodPipe<z.ZodOptional<z.ZodArray<z.ZodString>>, z.ZodTransform<string[] | undefined, string[] | undefined>>, unknown>;
15
15
  readOnly: z.ZodDefault<z.ZodUnion<readonly [z.ZodBoolean, z.ZodCodec<z.ZodString, z.ZodBoolean>]>>;
16
- omnisearchUrl: z.ZodPreprocess<z.ZodOptional<z.ZodString>, unknown>;
16
+ omnisearchUrl: z.ZodOptional<z.ZodString>;
17
17
  }, z.core.$strip>;
18
18
  export type ServerConfig = z.infer<typeof ServerConfigSchema>;
19
19
  export declare function getServerConfig(): ServerConfig;
@@ -1 +1 @@
1
- {"version":3,"file":"server-config.d.ts","sourceRoot":"","sources":["../../src/config/server-config.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAgF3C,QAAA,MAAM,kBAAkB;;;;;;;;;;iBAsDtB,CAAC;AAEH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAI9D,wBAAgB,eAAe,IAAI,YAAY,CAa9C;AAED,iEAAiE;AACjE,wBAAgB,iBAAiB,IAAI,IAAI,CAExC"}
1
+ {"version":3,"file":"server-config.d.ts","sourceRoot":"","sources":["../../src/config/server-config.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAgF3C,QAAA,MAAM,kBAAkB;;;;;;;;;;iBAgDtB,CAAC;AAEH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAI9D,wBAAgB,eAAe,IAAI,YAAY,CAa9C;AAED,iEAAiE;AACjE,wBAAgB,iBAAiB,IAAI,IAAI,CAExC"}
@@ -87,11 +87,11 @@ const ServerConfigSchema = z.object({
87
87
  .string()
88
88
  .min(1)
89
89
  .describe('Bearer token for the Obsidian Local REST API plugin (Settings → Community Plugins → Local REST API).'),
90
- baseUrl: z.preprocess((val) => (typeof val === 'string' && val.trim() === '' ? undefined : val), z
90
+ baseUrl: z
91
91
  .string()
92
92
  .url()
93
93
  .default('http://127.0.0.1:27123')
94
- .describe('Base URL of the Obsidian Local REST API. Defaults to http://127.0.0.1:27123 — enable "Non-encrypted (HTTP) Server" in the plugin settings to match. Use https://127.0.0.1:27124 to hit the always-on HTTPS port (self-signed cert; pair with OBSIDIAN_VERIFY_SSL=false).')),
94
+ .describe('Base URL of the Obsidian Local REST API. Defaults to http://127.0.0.1:27123 — enable "Non-encrypted (HTTP) Server" in the plugin settings to match. Use https://127.0.0.1:27124 to hit the always-on HTTPS port (self-signed cert; pair with OBSIDIAN_VERIFY_SSL=false).'),
95
95
  verifySsl: envBoolean
96
96
  .default(false)
97
97
  .describe("Whether to verify the TLS certificate on the Obsidian endpoint. Defaults to false because the plugin uses a self-signed cert. On Node, the dispatcher's `rejectUnauthorized` option handles this without any process-wide change. On Bun, the runtime ignores that option, so the service additionally sets `NODE_TLS_REJECT_UNAUTHORIZED=0` — that fallback is scoped to Bun only."),
@@ -109,11 +109,11 @@ const ServerConfigSchema = z.object({
109
109
  readOnly: envBoolean
110
110
  .default(false)
111
111
  .describe('Global kill switch. When true, denies every write regardless of OBSIDIAN_WRITE_PATHS, and suppresses the OBSIDIAN_ENABLE_COMMANDS pair (commands can mutate). Defaults to false.'),
112
- omnisearchUrl: z.preprocess((val) => (typeof val === 'string' && val.trim() === '' ? undefined : val), z
112
+ omnisearchUrl: z
113
113
  .string()
114
114
  .url()
115
115
  .optional()
116
- .describe('Override URL for the Omnisearch plugin HTTP server. When unset, derives from OBSIDIAN_BASE_URL host with port 51361 (falling back to http://localhost:51361). Used to enable the optional `omnisearch` mode on `obsidian_search_notes`; if the URL is unreachable at startup, the mode is omitted from the tool schema.')),
116
+ .describe('Override URL for the Omnisearch plugin HTTP server. When unset, derives from OBSIDIAN_BASE_URL host with port 51361 (falling back to http://localhost:51361). Used to enable the optional `omnisearch` mode on `obsidian_search_notes`; if the URL is unreachable at startup, the mode is omitted from the tool schema.'),
117
117
  });
118
118
  let _config;
119
119
  export function getServerConfig() {
@@ -1 +1 @@
1
- {"version":3,"file":"server-config.js","sourceRoot":"","sources":["../../src/config/server-config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"server-config.js","sourceRoot":"","sources":["../../src/config/server-config.ts"],"names":[],"mappings":"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"}
@@ -47,5 +47,10 @@ export declare const allResourceDefinitions: (import("@cyanheads/mcp-ts-core").R
47
47
  name: import("zod").ZodString;
48
48
  version: import("zod").ZodString;
49
49
  }, import("zod/v4/core").$strip>>;
50
+ apiExtensions: import("zod").ZodOptional<import("zod").ZodArray<import("zod").ZodObject<{
51
+ id: import("zod").ZodString;
52
+ name: import("zod").ZodOptional<import("zod").ZodString>;
53
+ version: import("zod").ZodOptional<import("zod").ZodString>;
54
+ }, import("zod/v4/core").$strip>>>;
50
55
  }, import("zod/v4/core").$strip>, undefined>)[];
51
56
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/resources/definitions/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+CAAoD,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/resources/definitions/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+CAAoD,CAAC"}
@@ -1,8 +1,10 @@
1
1
  /**
2
- * @fileoverview obsidian://status — reachability + auth check for the Obsidian
3
- * Local REST API plugin. Issues an anonymous probe (so the resource still
4
- * works when the key is wrong) and a separate authenticated probe so the
5
- * `authenticated` field reflects whether the configured key is accepted.
2
+ * @fileoverview obsidian://status — reachability, auth, and capability report
3
+ * for the Obsidian Local REST API plugin. One authenticated `GET /`: the route
4
+ * answers `200` whatever the key is and self-reports whether it was accepted,
5
+ * so a misconfigured key still yields the full reachability payload, and
6
+ * `apiExtensions` — which the plugin omits from the unauthenticated response —
7
+ * comes back on the same request.
6
8
  * @module mcp-server/resources/definitions/obsidian-status.resource
7
9
  */
8
10
  import { z } from '@cyanheads/mcp-ts-core';
@@ -19,5 +21,10 @@ export declare const obsidianStatus: import("@cyanheads/mcp-ts-core").ResourceDe
19
21
  name: z.ZodString;
20
22
  version: z.ZodString;
21
23
  }, z.core.$strip>>;
24
+ apiExtensions: z.ZodOptional<z.ZodArray<z.ZodObject<{
25
+ id: z.ZodString;
26
+ name: z.ZodOptional<z.ZodString>;
27
+ version: z.ZodOptional<z.ZodString>;
28
+ }, z.core.$strip>>>;
22
29
  }, z.core.$strip>, undefined>;
23
30
  //# sourceMappingURL=obsidian-status.resource.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"obsidian-status.resource.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/resources/definitions/obsidian-status.resource.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAY,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAGrD,eAAO,MAAM,cAAc;;;;;;;;;;;;;6BAwCzB,CAAC"}
1
+ {"version":3,"file":"obsidian-status.resource.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/resources/definitions/obsidian-status.resource.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAY,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAGrD,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;6BAmDzB,CAAC"}