obsidian-mcp-server 3.1.1 → 3.1.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.
- package/CLAUDE.md +10 -1
- package/README.md +30 -8
- package/changelog/3.1.x/3.1.2.md +23 -0
- package/changelog/3.1.x/3.1.3.md +23 -0
- package/dist/config/server-config.d.ts +5 -2
- package/dist/config/server-config.d.ts.map +1 -1
- package/dist/config/server-config.js +73 -0
- package/dist/config/server-config.js.map +1 -1
- package/dist/index.js +39 -5
- package/dist/index.js.map +1 -1
- package/dist/mcp-server/tools/definitions/_shared/schemas.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/_shared/schemas.js +4 -2
- package/dist/mcp-server/tools/definitions/_shared/schemas.js.map +1 -1
- package/dist/mcp-server/tools/definitions/index.d.ts +764 -27
- package/dist/mcp-server/tools/definitions/index.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/index.js +15 -9
- package/dist/mcp-server/tools/definitions/index.js.map +1 -1
- package/dist/mcp-server/tools/definitions/obsidian-append-to-note.tool.d.ts +7 -1
- package/dist/mcp-server/tools/definitions/obsidian-append-to-note.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/obsidian-append-to-note.tool.js +10 -1
- package/dist/mcp-server/tools/definitions/obsidian-append-to-note.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/obsidian-delete-note.tool.d.ts +7 -2
- package/dist/mcp-server/tools/definitions/obsidian-delete-note.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/obsidian-delete-note.tool.js +8 -2
- package/dist/mcp-server/tools/definitions/obsidian-delete-note.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/obsidian-execute-command.tool.js +2 -2
- package/dist/mcp-server/tools/definitions/obsidian-execute-command.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/obsidian-get-note.tool.d.ts +15 -2
- package/dist/mcp-server/tools/definitions/obsidian-get-note.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/obsidian-get-note.tool.js +65 -5
- package/dist/mcp-server/tools/definitions/obsidian-get-note.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/obsidian-list-notes.tool.d.ts +7 -2
- package/dist/mcp-server/tools/definitions/obsidian-list-notes.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/obsidian-list-notes.tool.js +20 -7
- package/dist/mcp-server/tools/definitions/obsidian-list-notes.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/obsidian-list-tags.tool.js +1 -1
- package/dist/mcp-server/tools/definitions/obsidian-list-tags.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/obsidian-manage-frontmatter.tool.d.ts +7 -2
- package/dist/mcp-server/tools/definitions/obsidian-manage-frontmatter.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/obsidian-manage-frontmatter.tool.js +10 -4
- package/dist/mcp-server/tools/definitions/obsidian-manage-frontmatter.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/obsidian-manage-tags.tool.d.ts +7 -2
- package/dist/mcp-server/tools/definitions/obsidian-manage-tags.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/obsidian-manage-tags.tool.js +9 -3
- package/dist/mcp-server/tools/definitions/obsidian-manage-tags.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/obsidian-open-in-ui.tool.d.ts +5 -0
- package/dist/mcp-server/tools/definitions/obsidian-open-in-ui.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/obsidian-open-in-ui.tool.js +6 -0
- package/dist/mcp-server/tools/definitions/obsidian-open-in-ui.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/obsidian-patch-note.tool.d.ts +9 -4
- package/dist/mcp-server/tools/definitions/obsidian-patch-note.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/obsidian-patch-note.tool.js +10 -4
- package/dist/mcp-server/tools/definitions/obsidian-patch-note.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/obsidian-replace-in-note.tool.d.ts +8 -3
- package/dist/mcp-server/tools/definitions/obsidian-replace-in-note.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/obsidian-replace-in-note.tool.js +10 -4
- package/dist/mcp-server/tools/definitions/obsidian-replace-in-note.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/obsidian-search-notes.tool.d.ts +2 -2
- package/dist/mcp-server/tools/definitions/obsidian-search-notes.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/obsidian-search-notes.tool.js +21 -16
- package/dist/mcp-server/tools/definitions/obsidian-search-notes.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/obsidian-write-note.tool.d.ts +5 -0
- package/dist/mcp-server/tools/definitions/obsidian-write-note.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/obsidian-write-note.tool.js +7 -1
- package/dist/mcp-server/tools/definitions/obsidian-write-note.tool.js.map +1 -1
- package/dist/services/obsidian/obsidian-service.d.ts +7 -0
- package/dist/services/obsidian/obsidian-service.d.ts.map +1 -1
- package/dist/services/obsidian/obsidian-service.js +114 -17
- package/dist/services/obsidian/obsidian-service.js.map +1 -1
- package/dist/services/obsidian/path-policy.d.ts +56 -0
- package/dist/services/obsidian/path-policy.d.ts.map +1 -0
- package/dist/services/obsidian/path-policy.js +154 -0
- package/dist/services/obsidian/path-policy.js.map +1 -0
- package/package.json +17 -6
- package/server.json +41 -3
package/CLAUDE.md
CHANGED
|
@@ -34,7 +34,8 @@ Tailor suggestions to what's actually missing or stale — don't recite the full
|
|
|
34
34
|
- **Check `ctx.elicit`** for presence before calling — used by `obsidian_delete_note` to confirm destructive ops.
|
|
35
35
|
- **All Obsidian access goes through `getObsidianService()`.** No direct `fetch()` calls to the Local REST API in tools/resources — the service centralizes auth, TLS, timeouts, and `ctx.signal` propagation.
|
|
36
36
|
- **Secrets in env vars only.** `OBSIDIAN_API_KEY` is required; never hardcoded.
|
|
37
|
-
- **Command-palette tools are opt-in.** `obsidian_list_commands` and `obsidian_execute_command` are
|
|
37
|
+
- **Command-palette tools are opt-in.** `obsidian_list_commands` and `obsidian_execute_command` are callable only when `OBSIDIAN_ENABLE_COMMANDS=true` — Obsidian commands are opaque and can be destructive. When the flag is unset, the entry point wraps both with `disabledTool()` so they're absent from `tools/list` (LLM can't invoke) but visible in the operator-facing manifest with a hint to enable them.
|
|
38
|
+
- **Path-policy gating goes through `PathPolicy`.** Every path-taking method on `ObsidianService` calls `policy.assertReadable` / `assertWritable` before the upstream HTTP call; `obsidian_search_notes` post-filters hits via `svc.policy.filterReadable`. Don't bypass this — `OBSIDIAN_READ_PATHS` / `OBSIDIAN_WRITE_PATHS` / `OBSIDIAN_READ_ONLY` are the single chokepoint, and `path_forbidden` is declared on every path-taking tool's `errors[]` contract.
|
|
38
39
|
|
|
39
40
|
---
|
|
40
41
|
|
|
@@ -138,6 +139,10 @@ const ServerConfigSchema = z.object({
|
|
|
138
139
|
verifySsl: envBoolean.default(false),
|
|
139
140
|
requestTimeoutMs: z.coerce.number().int().positive().default(30_000),
|
|
140
141
|
enableCommands: envBoolean.default(false),
|
|
142
|
+
/** Path-policy allowlists — comma-separated, prefix-based, case-insensitive. Unset = full vault. */
|
|
143
|
+
readPaths: envPathList,
|
|
144
|
+
writePaths: envPathList,
|
|
145
|
+
readOnly: envBoolean.default(false),
|
|
141
146
|
});
|
|
142
147
|
|
|
143
148
|
let _config: z.infer<typeof ServerConfigSchema> | undefined;
|
|
@@ -148,6 +153,9 @@ export function getServerConfig() {
|
|
|
148
153
|
verifySsl: 'OBSIDIAN_VERIFY_SSL',
|
|
149
154
|
requestTimeoutMs: 'OBSIDIAN_REQUEST_TIMEOUT_MS',
|
|
150
155
|
enableCommands: 'OBSIDIAN_ENABLE_COMMANDS',
|
|
156
|
+
readPaths: 'OBSIDIAN_READ_PATHS',
|
|
157
|
+
writePaths: 'OBSIDIAN_WRITE_PATHS',
|
|
158
|
+
readOnly: 'OBSIDIAN_READ_ONLY',
|
|
151
159
|
});
|
|
152
160
|
return _config;
|
|
153
161
|
}
|
|
@@ -287,6 +295,7 @@ Available skills:
|
|
|
287
295
|
| `report-issue-framework` | File a bug or feature request against `@cyanheads/mcp-ts-core` via `gh` CLI |
|
|
288
296
|
| `report-issue-local` | File a bug or feature request against this server's own repo via `gh` CLI |
|
|
289
297
|
| `api-auth` | Auth modes, scopes, JWT/OAuth |
|
|
298
|
+
| `api-canvas` | DataCanvas SQL workspace (Tier 3, DuckDB) — not used by this server |
|
|
290
299
|
| `api-config` | AppConfig, parseConfig, env vars |
|
|
291
300
|
| `api-context` | Context interface, logger, state, progress |
|
|
292
301
|
| `api-errors` | McpError, JsonRpcErrorCode, error patterns |
|
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
<div align="center">
|
|
9
9
|
|
|
10
|
-
[](https://www.npmjs.com/package/obsidian-mcp-server) [](https://www.npmjs.com/package/obsidian-mcp-server) [](./CHANGELOG.md) [](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) [](https://modelcontextprotocol.io/)
|
|
11
11
|
|
|
12
12
|
[](./LICENSE) [](https://www.typescriptlang.org/) [](https://bun.sh/)
|
|
13
13
|
|
|
@@ -126,6 +126,29 @@ Dispatch an Obsidian command-palette command by ID (discoverable via `obsidian_l
|
|
|
126
126
|
|
|
127
127
|
---
|
|
128
128
|
|
|
129
|
+
## Path policy (folder-scoped permissions)
|
|
130
|
+
|
|
131
|
+
Three optional env vars gate which vault paths each tool can target. **Default unset = full vault** for both reads and writes — backwards compatible.
|
|
132
|
+
|
|
133
|
+
| Goal | Config |
|
|
134
|
+
|:---|:---|
|
|
135
|
+
| Default (current behavior) | all unset |
|
|
136
|
+
| Read everywhere, write only in `projects/` and `scratch/` | `OBSIDIAN_WRITE_PATHS=projects/,scratch/` |
|
|
137
|
+
| Read only `public/`, write only `public/inbox/` | `OBSIDIAN_READ_PATHS=public/`, `OBSIDIAN_WRITE_PATHS=public/inbox/` |
|
|
138
|
+
| Read-only deployment — no writes anywhere | `OBSIDIAN_READ_ONLY=true` |
|
|
139
|
+
|
|
140
|
+
**Matching is prefix-based with implicit recursion**, case-insensitive, with trailing slashes normalized. `projects/` matches `projects/a.md`, `projects/sub/b.md`, etc.
|
|
141
|
+
|
|
142
|
+
**Write paths are implicitly readable** — you can't sanely edit what you can't see. So a read passes when the target matches `READ_PATHS` *or* `WRITE_PATHS`.
|
|
143
|
+
|
|
144
|
+
**`OBSIDIAN_READ_ONLY=true` short-circuits before the path checks** — every write is denied regardless of `WRITE_PATHS`, and the command-palette pair is unregistered regardless of `OBSIDIAN_ENABLE_COMMANDS` (commands can mutate).
|
|
145
|
+
|
|
146
|
+
Denies are typed `path_forbidden` (JSON-RPC code `Forbidden`) with the active scope echoed back in `data.recovery.hint` and `data.activeScope`, so the LLM can self-correct without inspecting server logs. Search results from `obsidian_search_notes` are filtered against `READ_PATHS` silently — surfacing a "we hid N hits" indicator would defeat the gate.
|
|
147
|
+
|
|
148
|
+
The startup banner logs the active scope so operators can verify their config at boot.
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
129
152
|
## Resources
|
|
130
153
|
|
|
131
154
|
| Type | URI | Description |
|
|
@@ -155,6 +178,7 @@ Obsidian-specific:
|
|
|
155
178
|
- Tag reconciliation across both representations: frontmatter `tags:` array and inline `#tag` syntax (skipping fenced code blocks)
|
|
156
179
|
- Search across three modes: text, Dataview DQL, JSONLogic — with overflow indicator when results exceed the 100-hit cap
|
|
157
180
|
- Optional human-in-the-loop confirmation for destructive deletes via `ctx.elicit`
|
|
181
|
+
- 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
|
|
158
182
|
- Opt-in command-palette pair (`obsidian_list_commands` + `obsidian_execute_command`) — registered only when `OBSIDIAN_ENABLE_COMMANDS=true`
|
|
159
183
|
- Forgiving path resolution on `obsidian_get_note` and `obsidian_open_in_ui` — silently retries case-mismatched paths against the canonical filename, throws `Conflict` on ambiguous case matches, and enriches `NotFound` with `Did you mean: …?` suggestions when only near-matches exist. `obsidian_delete_note` is deliberately excluded — a destructive op shouldn't silently rewrite the target path.
|
|
160
184
|
|
|
@@ -247,13 +271,18 @@ MCP_TRANSPORT_TYPE=http OBSIDIAN_API_KEY=... bun run start:http
|
|
|
247
271
|
| `OBSIDIAN_VERIFY_SSL` | Verify the TLS certificate. Default `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. | `false` |
|
|
248
272
|
| `OBSIDIAN_REQUEST_TIMEOUT_MS` | Per-request timeout in milliseconds. | `30000` |
|
|
249
273
|
| `OBSIDIAN_ENABLE_COMMANDS` | Opt-in flag for the command-palette pair (`obsidian_list_commands` + `obsidian_execute_command`). Off by default — Obsidian commands are opaque and can be destructive. | `false` |
|
|
274
|
+
| `OBSIDIAN_READ_PATHS` | Comma-separated vault-relative folder allowlist for read operations. Prefix-based with implicit recursion; case-insensitive; trailing slashes normalized. Unset = full vault. Write paths are implicitly readable. | unset |
|
|
275
|
+
| `OBSIDIAN_WRITE_PATHS` | Comma-separated vault-relative folder allowlist for write operations. Same syntax as `OBSIDIAN_READ_PATHS`. Unset = full vault. | unset |
|
|
276
|
+
| `OBSIDIAN_READ_ONLY` | Global kill switch. When `true`, denies every write regardless of `OBSIDIAN_WRITE_PATHS`, and suppresses the `OBSIDIAN_ENABLE_COMMANDS` pair (commands can mutate). | `false` |
|
|
250
277
|
| `MCP_TRANSPORT_TYPE` | Transport: `stdio` or `http`. | `stdio` |
|
|
251
278
|
| `MCP_HTTP_HOST` | Host for the HTTP server. | `127.0.0.1` |
|
|
252
279
|
| `MCP_HTTP_PORT` | Port for the HTTP server. | `3010` |
|
|
253
280
|
| `MCP_HTTP_ENDPOINT_PATH` | Endpoint path for the JSON-RPC handler. | `/mcp` |
|
|
281
|
+
| `MCP_PUBLIC_URL` | Public origin override for TLS-terminating reverse-proxy deployments (landing page, Server Card, RFC 9728 metadata). | unset |
|
|
254
282
|
| `MCP_AUTH_MODE` | Auth mode: `none`, `jwt`, or `oauth`. | `none` |
|
|
255
283
|
| `MCP_AUTH_SECRET_KEY` | **Required when `MCP_AUTH_MODE=jwt`.** ≥32-char shared secret used to verify incoming JWTs. | — |
|
|
256
284
|
| `MCP_LOG_LEVEL` | Log level (RFC 5424). | `info` |
|
|
285
|
+
| `LOGS_DIR` | Directory for log files (Node.js only). | `<project-root>/logs` |
|
|
257
286
|
| `OTEL_ENABLED` | Enable OpenTelemetry. | `false` |
|
|
258
287
|
|
|
259
288
|
See [`.env.example`](./.env.example) for the full list of optional overrides.
|
|
@@ -262,13 +291,6 @@ See [`.env.example`](./.env.example) for the full list of optional overrides.
|
|
|
262
291
|
|
|
263
292
|
### Local development
|
|
264
293
|
|
|
265
|
-
- **Hot-reload dev mode:**
|
|
266
|
-
|
|
267
|
-
```sh
|
|
268
|
-
bun run dev:stdio
|
|
269
|
-
bun run dev:http
|
|
270
|
-
```
|
|
271
|
-
|
|
272
294
|
- **Build and run the production version:**
|
|
273
295
|
|
|
274
296
|
```sh
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
---
|
|
2
|
+
summary: Folder-scoped read/write permissions and a global read-only kill switch — three opt-in env vars (OBSIDIAN_READ_PATHS, OBSIDIAN_WRITE_PATHS, OBSIDIAN_READ_ONLY) gate every path-taking tool and resource, with a new path_forbidden error reason.
|
|
3
|
+
breaking: false
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# 3.1.2 — 2026-05-03
|
|
7
|
+
|
|
8
|
+
Three opt-in env vars now scope which vault paths read and write tools may target. Closes [#40](https://github.com/cyanheads/obsidian-mcp-server/issues/40); resolves the original ask in [discussion #15](https://github.com/cyanheads/obsidian-mcp-server/discussions/15#discussioncomment-13918526). Backwards compatible — all three default unset / false, preserving current full-vault behavior.
|
|
9
|
+
|
|
10
|
+
## Added
|
|
11
|
+
|
|
12
|
+
- **`OBSIDIAN_READ_PATHS` / `OBSIDIAN_WRITE_PATHS`** — comma-separated vault-relative folder allowlists. Prefix-based with implicit recursion (`projects/` matches `projects/a.md`, `projects/sub/b.md`, …); case-insensitive; trailing slashes normalized; deduplicated. Empty / whitespace-only input falls back to unset; separator-only input (`,`, `,,,`) and absolute paths or `..` traversal throw a `ConfigurationError` at startup naming the offending env var.
|
|
13
|
+
- **`OBSIDIAN_READ_ONLY`** — global kill switch. When `true`, denies every write regardless of `OBSIDIAN_WRITE_PATHS`, and suppresses the `OBSIDIAN_ENABLE_COMMANDS` pair (commands can mutate). Useful for shared or public-facing deployments.
|
|
14
|
+
- **`path_forbidden` error reason** declared on every path-taking tool's `errors[]` contract — mapped to `JsonRpcErrorCode.Forbidden`. The wire payload carries `{ path, op, subreason, activeScope, recovery }` where `subreason` is one of `outside_read_paths`, `outside_write_paths`, or `read_only_mode`, and the recovery hint echoes the active scope so the LLM can self-correct without inspecting server logs.
|
|
15
|
+
- **Startup banner** — `core.logger.info('Path policy', …)` echoes the active scope and command-palette enable state at boot, so operators can verify their config. Emits a warning when `OBSIDIAN_READ_ONLY=true` AND `OBSIDIAN_WRITE_PATHS` is non-empty (the boolean wins; the paths are ignored).
|
|
16
|
+
- **`PathPolicy`** module (`src/services/obsidian/path-policy.ts`) — single chokepoint that decides per path: `isReadable`, `isWritable`, `assertReadable`, `assertWritable`, plus a silent `filterReadable` for search post-filtering.
|
|
17
|
+
|
|
18
|
+
## Changed
|
|
19
|
+
|
|
20
|
+
- **`ObsidianService` gates every path-taking method** before the upstream HTTP call: `getNoteContent`, `getNoteJson`, `getDocumentMap`, `listFiles`, `openInUi` (read), and `writeNote`, `appendToNote`, `patchNote`, `deleteNote` (write). For non-`path` targets (`active`, `periodic`) under restrictions, the service routes through a JSON resolution fetch first to learn the path, then gates on the resolved path — costs one extra fetch only for users who configured a path scope.
|
|
21
|
+
- **`obsidian_search_notes` post-filters hits against `OBSIDIAN_READ_PATHS`** silently — surfacing a "we hid N hits" indicator would defeat the gate. The `excluded` overflow indicator continues to count hits trimmed by the 100-hit cap, not policy-dropped hits.
|
|
22
|
+
- **Tool registration in `src/index.ts`** splits read-only tools from write tools at the barrel and wraps the write set with `disabledTool()` when `OBSIDIAN_READ_ONLY=true`. The command-palette pair stays wrapped with `disabledTool()` whenever it's not callable (either `OBSIDIAN_ENABLE_COMMANDS=false` or `OBSIDIAN_READ_ONLY=true`), with a `hint` explaining how to enable it. The LLM never sees disabled tools in `tools/list`; they remain visible in the operator-facing manifest.
|
|
23
|
+
- **`obsidian_list_notes` listing semantics** — the vault root always lists, even with `OBSIDIAN_READ_PATHS` set. Specific subdirectories outside the read scope throw `path_forbidden`. Children aren't filtered at the service level; the per-file read gate on subsequent reads (`obsidian_get_note`, etc.) still catches access to out-of-scope notes.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
---
|
|
2
|
+
summary: obsidian_get_note grows an opt-in includeLinks flag that surfaces the note's outgoing wikilinks and markdown links; tool descriptions, schema defaults, and recovery hints tightened across the surface.
|
|
3
|
+
breaking: false
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# 3.1.3 — 2026-05-04
|
|
7
|
+
|
|
8
|
+
## Added
|
|
9
|
+
|
|
10
|
+
- **`obsidian_get_note` — `includeLinks` flag.** With `format: "full"` and `includeLinks: true`, the response carries `outgoingLinks[]`: an array of `{ target, type: 'wikilink' | 'markdown' }` parsed from the note body. Captures `[[Target]]`, `[[Target|alias]]`, `[[Target#section]]`, `![[embed]]`, and `[text](path.md)`; filters external URIs (`http:`, `mailto:`, etc.). No existence check — this is the link graph as written. Pure regex over content already returned, zero extra HTTP. Default `false` keeps the response compact. Closes [#43](https://github.com/cyanheads/obsidian-mcp-server/issues/43).
|
|
11
|
+
- **`package.json` `funding` field** — GitHub Sponsors and Buy Me a Coffee links so the npm registry surfaces them on the package page.
|
|
12
|
+
|
|
13
|
+
## Changed
|
|
14
|
+
|
|
15
|
+
- **Tool descriptions tightened across the surface.** `obsidian_get_note`, `obsidian_search_notes`, `obsidian_list_notes`, `obsidian_patch_note`, `obsidian_replace_in_note`, `obsidian_write_note`, `obsidian_manage_frontmatter`, `obsidian_manage_tags`, `obsidian_append_to_note`, `obsidian_execute_command`, and `obsidian_list_tags` all received a leaner first-line summary and clearer per-field `.describe()` text. No behavior change — the tools do the same things, the LLM gets a sharper picture of what each one is for.
|
|
16
|
+
- **Schema defaults instead of optional+manual fallback.** `obsidian_list_notes.depth`, `obsidian_search_notes.contextLength`, and `obsidian_search_notes.maxMatchesPerHit` now use Zod `.default(...)` so the default appears in the published schema and the handler reads `input.field` directly.
|
|
17
|
+
- **Recovery hints simplified.** Removed the "check the server startup banner" hint from every `path_forbidden` recovery — the wire payload's `activeScope` is the source of truth. The `no_active_file` recovery now points the LLM at `obsidian_open_in_ui` instead of telling it to open a note manually. The `periodic_disabled` recovery no longer instructs the LLM to change Obsidian plugin settings (which it can't) — it just tells it to switch to a path target.
|
|
18
|
+
- **`SectionSchema.target` description** clarifies that block references are written without the leading caret (`2d9b4a`, not `^2d9b4a`) — matches the Local REST API plugin's expectation.
|
|
19
|
+
|
|
20
|
+
## Fixed
|
|
21
|
+
|
|
22
|
+
- **README env var table** documents `MCP_PUBLIC_URL` (TLS-terminating reverse-proxy origin override) and `LOGS_DIR` (Node.js log directory) — both supported by the framework but missing from the table.
|
|
23
|
+
- **README** drops the stale `bun run dev:stdio` / `bun run dev:http` instructions; those scripts were removed in 3.1.1 but the README still referenced them.
|
|
@@ -7,9 +7,12 @@ import { z } from '@cyanheads/mcp-ts-core';
|
|
|
7
7
|
declare const ServerConfigSchema: z.ZodObject<{
|
|
8
8
|
apiKey: z.ZodString;
|
|
9
9
|
baseUrl: z.ZodDefault<z.ZodString>;
|
|
10
|
-
verifySsl: z.ZodDefault<z.
|
|
10
|
+
verifySsl: z.ZodDefault<z.ZodPreprocess<z.ZodBoolean>>;
|
|
11
11
|
requestTimeoutMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
12
|
-
enableCommands: z.ZodDefault<z.
|
|
12
|
+
enableCommands: z.ZodDefault<z.ZodPreprocess<z.ZodBoolean>>;
|
|
13
|
+
readPaths: z.ZodPreprocess<z.ZodPipe<z.ZodOptional<z.ZodArray<z.ZodString>>, z.ZodTransform<string[] | undefined, string[] | undefined>>>;
|
|
14
|
+
writePaths: z.ZodPreprocess<z.ZodPipe<z.ZodOptional<z.ZodArray<z.ZodString>>, z.ZodTransform<string[] | undefined, string[] | undefined>>>;
|
|
15
|
+
readOnly: z.ZodDefault<z.ZodPreprocess<z.ZodBoolean>>;
|
|
13
16
|
}, z.core.$strip>;
|
|
14
17
|
export type ServerConfig = z.infer<typeof ServerConfigSchema>;
|
|
15
18
|
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;
|
|
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;AA4E3C,QAAA,MAAM,kBAAkB;;;;;;;;;iBAyCtB,CAAC;AAEH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAI9D,wBAAgB,eAAe,IAAI,YAAY,CAY9C;AAED,iEAAiE;AACjE,wBAAgB,iBAAiB,IAAI,IAAI,CAExC"}
|
|
@@ -14,6 +14,71 @@ const envBoolean = z.preprocess((val) => {
|
|
|
14
14
|
}
|
|
15
15
|
return val;
|
|
16
16
|
}, z.boolean());
|
|
17
|
+
/**
|
|
18
|
+
* Comma-separated path-list preprocessor. Semantics (see issue #40):
|
|
19
|
+
* - undefined / `''` / whitespace-only → undefined (treat as unset; default = full vault)
|
|
20
|
+
* - `,` / `,,,` (separators only, no path content) → throw ZodError → ConfigurationError
|
|
21
|
+
* - mixed empties (`a,,b`) → drop empties → `['a', 'b']`
|
|
22
|
+
* - absolute path / `..` traversal → throw
|
|
23
|
+
* - valid: lower-case + trim trailing slash + dedupe (preserves first occurrence order)
|
|
24
|
+
*/
|
|
25
|
+
const envPathList = z
|
|
26
|
+
.preprocess((val) => {
|
|
27
|
+
if (val === undefined || val === null)
|
|
28
|
+
return;
|
|
29
|
+
if (Array.isArray(val))
|
|
30
|
+
return val;
|
|
31
|
+
if (typeof val !== 'string')
|
|
32
|
+
return val;
|
|
33
|
+
if (val.trim() === '')
|
|
34
|
+
return;
|
|
35
|
+
const parts = val
|
|
36
|
+
.split(',')
|
|
37
|
+
.map((s) => s.trim())
|
|
38
|
+
.filter((s) => s.length > 0);
|
|
39
|
+
return parts;
|
|
40
|
+
}, z
|
|
41
|
+
.array(z.string())
|
|
42
|
+
.optional()
|
|
43
|
+
.transform((parts, ctx) => {
|
|
44
|
+
if (parts === undefined)
|
|
45
|
+
return;
|
|
46
|
+
if (parts.length === 0) {
|
|
47
|
+
ctx.addIssue({
|
|
48
|
+
code: 'custom',
|
|
49
|
+
message: 'contained separators but no valid paths after trimming',
|
|
50
|
+
});
|
|
51
|
+
return z.NEVER;
|
|
52
|
+
}
|
|
53
|
+
const seen = new Set();
|
|
54
|
+
const out = [];
|
|
55
|
+
for (const raw of parts) {
|
|
56
|
+
if (raw.startsWith('/') || raw.startsWith('\\')) {
|
|
57
|
+
ctx.addIssue({
|
|
58
|
+
code: 'custom',
|
|
59
|
+
message: `must be vault-relative; got absolute path '${raw}'`,
|
|
60
|
+
});
|
|
61
|
+
return z.NEVER;
|
|
62
|
+
}
|
|
63
|
+
const segments = raw.split(/[\\/]/);
|
|
64
|
+
if (segments.includes('..')) {
|
|
65
|
+
ctx.addIssue({
|
|
66
|
+
code: 'custom',
|
|
67
|
+
message: `must not contain '..' traversal; got '${raw}'`,
|
|
68
|
+
});
|
|
69
|
+
return z.NEVER;
|
|
70
|
+
}
|
|
71
|
+
const normalized = raw.toLowerCase().replace(/[\\/]+$/, '');
|
|
72
|
+
if (normalized.length === 0)
|
|
73
|
+
continue;
|
|
74
|
+
if (seen.has(normalized))
|
|
75
|
+
continue;
|
|
76
|
+
seen.add(normalized);
|
|
77
|
+
out.push(normalized);
|
|
78
|
+
}
|
|
79
|
+
return out.length > 0 ? out : undefined;
|
|
80
|
+
}))
|
|
81
|
+
.describe('Comma-separated list of vault-relative folder prefixes. Empty/whitespace falls back to unset.');
|
|
17
82
|
const ServerConfigSchema = z.object({
|
|
18
83
|
apiKey: z
|
|
19
84
|
.string()
|
|
@@ -36,6 +101,11 @@ const ServerConfigSchema = z.object({
|
|
|
36
101
|
enableCommands: envBoolean
|
|
37
102
|
.default(false)
|
|
38
103
|
.describe('Opt-in flag for the command-palette pair (`obsidian_list_commands` + `obsidian_execute_command`). Off by default — Obsidian commands are opaque and can be destructive.'),
|
|
104
|
+
readPaths: envPathList.describe('Optional vault-relative folder allowlist for read operations. Comma-separated; prefix-based with implicit recursion; case-insensitive; trailing slashes normalized. Unset = full vault.'),
|
|
105
|
+
writePaths: envPathList.describe('Optional vault-relative folder allowlist for write operations. Same syntax as OBSIDIAN_READ_PATHS. Write paths are implicitly readable. Unset = full vault.'),
|
|
106
|
+
readOnly: envBoolean
|
|
107
|
+
.default(false)
|
|
108
|
+
.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.'),
|
|
39
109
|
});
|
|
40
110
|
let _config;
|
|
41
111
|
export function getServerConfig() {
|
|
@@ -45,6 +115,9 @@ export function getServerConfig() {
|
|
|
45
115
|
verifySsl: 'OBSIDIAN_VERIFY_SSL',
|
|
46
116
|
requestTimeoutMs: 'OBSIDIAN_REQUEST_TIMEOUT_MS',
|
|
47
117
|
enableCommands: 'OBSIDIAN_ENABLE_COMMANDS',
|
|
118
|
+
readPaths: 'OBSIDIAN_READ_PATHS',
|
|
119
|
+
writePaths: 'OBSIDIAN_WRITE_PATHS',
|
|
120
|
+
readOnly: 'OBSIDIAN_READ_ONLY',
|
|
48
121
|
});
|
|
49
122
|
return _config;
|
|
50
123
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server-config.js","sourceRoot":"","sources":["../../src/config/server-config.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAE/D,MAAM,UAAU,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,GAAG,EAAE,EAAE;IACtC,IAAI,OAAO,GAAG,KAAK,SAAS;QAAE,OAAO,GAAG,CAAC;IACzC,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC5B,MAAM,GAAG,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC;QACrC,OAAO,GAAG,KAAK,MAAM,IAAI,GAAG,KAAK,GAAG,CAAC;IACvC,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;AAEhB,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IAClC,MAAM,EAAE,CAAC;SACN,MAAM,EAAE;SACR,GAAG,CAAC,CAAC,CAAC;SACN,QAAQ,CACP,sGAAsG,CACvG;IACH,OAAO,EAAE,CAAC;SACP,MAAM,EAAE;SACR,GAAG,EAAE;SACL,OAAO,CAAC,wBAAwB,CAAC;SACjC,QAAQ,CACP,0QAA0Q,CAC3Q;IACH,SAAS,EAAE,UAAU;SAClB,OAAO,CAAC,KAAK,CAAC;SACd,QAAQ,CACP,qXAAqX,CACtX;IACH,gBAAgB,EAAE,CAAC,CAAC,MAAM;SACvB,MAAM,EAAE;SACR,GAAG,EAAE;SACL,QAAQ,EAAE;SACV,OAAO,CAAC,MAAM,CAAC;SACf,QAAQ,CAAC,sCAAsC,CAAC;IACnD,cAAc,EAAE,UAAU;SACvB,OAAO,CAAC,KAAK,CAAC;SACd,QAAQ,CACP,yKAAyK,CAC1K;CACJ,CAAC,CAAC;AAIH,IAAI,OAAiC,CAAC;AAEtC,MAAM,UAAU,eAAe;IAC7B,OAAO,KAAK,cAAc,CAAC,kBAAkB,EAAE;QAC7C,MAAM,EAAE,kBAAkB;QAC1B,OAAO,EAAE,mBAAmB;QAC5B,SAAS,EAAE,qBAAqB;QAChC,gBAAgB,EAAE,6BAA6B;QAC/C,cAAc,EAAE,0BAA0B;
|
|
1
|
+
{"version":3,"file":"server-config.js","sourceRoot":"","sources":["../../src/config/server-config.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -6,16 +6,34 @@
|
|
|
6
6
|
* @module index
|
|
7
7
|
*/
|
|
8
8
|
import { createApp } from '@cyanheads/mcp-ts-core';
|
|
9
|
+
import { disabledTool } from '@cyanheads/mcp-ts-core/tools';
|
|
10
|
+
import { requestContextService } from '@cyanheads/mcp-ts-core/utils';
|
|
9
11
|
import { getServerConfig } from './config/server-config.js';
|
|
10
12
|
import { allPromptDefinitions } from './mcp-server/prompts/definitions/index.js';
|
|
11
13
|
import { allResourceDefinitions } from './mcp-server/resources/definitions/index.js';
|
|
12
|
-
import {
|
|
14
|
+
import { commandToolDefinitions, readToolDefinitions, writeToolDefinitions, } from './mcp-server/tools/definitions/index.js';
|
|
13
15
|
import { initObsidianService } from './services/obsidian/obsidian-service.js';
|
|
16
|
+
import { PathPolicy } from './services/obsidian/path-policy.js';
|
|
14
17
|
const config = getServerConfig();
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
18
|
+
const policy = new PathPolicy(config);
|
|
19
|
+
const writeTools = config.readOnly
|
|
20
|
+
? writeToolDefinitions.map((def) => disabledTool(def, {
|
|
21
|
+
reason: 'Disabled by OBSIDIAN_READ_ONLY=true.',
|
|
22
|
+
hint: 'Unset OBSIDIAN_READ_ONLY (or set it to false) to enable write tools.',
|
|
23
|
+
}))
|
|
24
|
+
: writeToolDefinitions;
|
|
25
|
+
const commandTools = config.enableCommands && !config.readOnly
|
|
26
|
+
? commandToolDefinitions
|
|
27
|
+
: commandToolDefinitions.map((def) => disabledTool(def, {
|
|
28
|
+
reason: config.readOnly
|
|
29
|
+
? 'Disabled by OBSIDIAN_READ_ONLY=true (commands can mutate).'
|
|
30
|
+
: 'Disabled by default — Obsidian commands are opaque and can be destructive.',
|
|
31
|
+
hint: config.readOnly
|
|
32
|
+
? 'Unset OBSIDIAN_READ_ONLY to allow commands; OBSIDIAN_ENABLE_COMMANDS=true is also required.'
|
|
33
|
+
: 'Set OBSIDIAN_ENABLE_COMMANDS=true to enable obsidian_list_commands and obsidian_execute_command.',
|
|
34
|
+
}));
|
|
35
|
+
const tools = [...readToolDefinitions, ...writeTools, ...commandTools];
|
|
36
|
+
const { services } = await createApp({
|
|
19
37
|
tools,
|
|
20
38
|
resources: allResourceDefinitions,
|
|
21
39
|
prompts: allPromptDefinitions,
|
|
@@ -23,4 +41,20 @@ await createApp({
|
|
|
23
41
|
initObsidianService(config);
|
|
24
42
|
},
|
|
25
43
|
});
|
|
44
|
+
/**
|
|
45
|
+
* Startup banner — emitted after createApp() returns so the framework's
|
|
46
|
+
* `logger.initialize()` has run; calls inside `setup()` happen pre-init and
|
|
47
|
+
* are dropped. Operators check this against their config to verify the active
|
|
48
|
+
* path policy. The active scope on `path_forbidden` errors echoes the same
|
|
49
|
+
* data so the LLM (or operator) can self-correct without scrolling the log.
|
|
50
|
+
*/
|
|
51
|
+
const bannerCtx = requestContextService.createRequestContext({
|
|
52
|
+
operation: 'startup',
|
|
53
|
+
...policy.describe(),
|
|
54
|
+
enableCommands: config.enableCommands && !config.readOnly,
|
|
55
|
+
});
|
|
56
|
+
services.logger.info('Path policy', bannerCtx);
|
|
57
|
+
if (policy.readOnlyShadowsWritePaths) {
|
|
58
|
+
services.logger.warning('OBSIDIAN_WRITE_PATHS is set but ignored because OBSIDIAN_READ_ONLY=true. Unset one of the two to remove the conflict.', bannerCtx);
|
|
59
|
+
}
|
|
26
60
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;GAKG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,sBAAsB,EAAE,MAAM,6CAA6C,CAAC;AACrF,OAAO,EACL,mBAAmB,EACnB,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;GAKG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,sBAAsB,EAAE,MAAM,6CAA6C,CAAC;AACrF,OAAO,EACL,sBAAsB,EACtB,mBAAmB,EACnB,oBAAoB,GACrB,MAAM,yCAAyC,CAAC;AACjD,OAAO,EAAE,mBAAmB,EAAE,MAAM,yCAAyC,CAAC;AAC9E,OAAO,EAAE,UAAU,EAAE,MAAM,oCAAoC,CAAC;AAEhE,MAAM,MAAM,GAAG,eAAe,EAAE,CAAC;AACjC,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC;AAEtC,MAAM,UAAU,GAAG,MAAM,CAAC,QAAQ;IAChC,CAAC,CAAC,oBAAoB,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAC/B,YAAY,CAAC,GAAG,EAAE;QAChB,MAAM,EAAE,sCAAsC;QAC9C,IAAI,EAAE,sEAAsE;KAC7E,CAAC,CACH;IACH,CAAC,CAAC,oBAAoB,CAAC;AAEzB,MAAM,YAAY,GAChB,MAAM,CAAC,cAAc,IAAI,CAAC,MAAM,CAAC,QAAQ;IACvC,CAAC,CAAC,sBAAsB;IACxB,CAAC,CAAC,sBAAsB,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CACjC,YAAY,CAAC,GAAG,EAAE;QAChB,MAAM,EAAE,MAAM,CAAC,QAAQ;YACrB,CAAC,CAAC,4DAA4D;YAC9D,CAAC,CAAC,4EAA4E;QAChF,IAAI,EAAE,MAAM,CAAC,QAAQ;YACnB,CAAC,CAAC,6FAA6F;YAC/F,CAAC,CAAC,kGAAkG;KACvG,CAAC,CACH,CAAC;AAER,MAAM,KAAK,GAAG,CAAC,GAAG,mBAAmB,EAAE,GAAG,UAAU,EAAE,GAAG,YAAY,CAAC,CAAC;AAEvE,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,SAAS,CAAC;IACnC,KAAK;IACL,SAAS,EAAE,sBAAsB;IACjC,OAAO,EAAE,oBAAoB;IAC7B,KAAK;QACH,mBAAmB,CAAC,MAAM,CAAC,CAAC;IAC9B,CAAC;CACF,CAAC,CAAC;AAEH;;;;;;GAMG;AACH,MAAM,SAAS,GAAG,qBAAqB,CAAC,oBAAoB,CAAC;IAC3D,SAAS,EAAE,SAAS;IACpB,GAAG,MAAM,CAAC,QAAQ,EAAE;IACpB,cAAc,EAAE,MAAM,CAAC,cAAc,IAAI,CAAC,MAAM,CAAC,QAAQ;CAC1D,CAAC,CAAC;AACH,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC;AAC/C,IAAI,MAAM,CAAC,yBAAyB,EAAE,CAAC;IACrC,QAAQ,CAAC,MAAM,CAAC,OAAO,CACrB,uHAAuH,EACvH,SAAS,CACV,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../../../../../src/mcp-server/tools/definitions/_shared/schemas.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAE3C,4EAA4E;AAC5E,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;2BA4BvB,CAAC;AAEH,yCAAyC;AACzC,eAAO,MAAM,aAAa;;;;;;;
|
|
1
|
+
{"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../../../../../src/mcp-server/tools/definitions/_shared/schemas.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAE3C,4EAA4E;AAC5E,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;2BA4BvB,CAAC;AAEH,yCAAyC;AACzC,eAAO,MAAM,aAAa;;;;;;;iBAUxB,CAAC;AAEH,eAAO,MAAM,kBAAkB;;;;kBAiBlB,CAAC;AAEd,eAAO,MAAM,iBAAiB;;;GAK3B,CAAC;AAEJ,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AACtD,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC"}
|
|
@@ -37,11 +37,13 @@ export const TargetSchema = z.discriminatedUnion('type', [
|
|
|
37
37
|
]);
|
|
38
38
|
/** Sub-document target inside a note. */
|
|
39
39
|
export const SectionSchema = z.object({
|
|
40
|
-
type: z
|
|
40
|
+
type: z
|
|
41
|
+
.enum(['heading', 'block', 'frontmatter'])
|
|
42
|
+
.describe('Heading by name, block by reference, or frontmatter field by key.'),
|
|
41
43
|
target: z
|
|
42
44
|
.string()
|
|
43
45
|
.min(1)
|
|
44
|
-
.describe('Heading name (use "::" for nested headings), block reference (e.g. "2d9b4a"), or frontmatter field name.'),
|
|
46
|
+
.describe('Heading name (use "::" for nested headings), block reference without leading caret (e.g. "2d9b4a", not "^2d9b4a"), or frontmatter field name.'),
|
|
45
47
|
});
|
|
46
48
|
export const PatchOptionsSchema = z
|
|
47
49
|
.object({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schemas.js","sourceRoot":"","sources":["../../../../../src/mcp-server/tools/definitions/_shared/schemas.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAE3C,4EAA4E;AAC5E,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC,kBAAkB,CAAC,MAAM,EAAE;IACvD,CAAC;SACE,MAAM,CAAC;QACN,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,iCAAiC,CAAC;QACnE,IAAI,EAAE,CAAC;aACJ,MAAM,EAAE;aACR,GAAG,CAAC,CAAC,CAAC;aACN,QAAQ,CAAC,kEAAkE,CAAC;KAChF,CAAC;SACD,QAAQ,CAAC,4CAA4C,CAAC;IACzD,CAAC;SACE,MAAM,CAAC;QACN,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,QAAQ,CAAC,8CAA8C,CAAC;KACnF,CAAC;SACD,QAAQ,CAAC,gEAAgE,CAAC;IAC7E,CAAC;SACE,MAAM,CAAC;QACN,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,QAAQ,CAAC,oDAAoD,CAAC;QAC1F,MAAM,EAAE,CAAC;aACN,IAAI,CAAC,CAAC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAC;aAC3D,QAAQ,CAAC,4BAA4B,CAAC;QACzC,IAAI,EAAE,CAAC;aACJ,MAAM,EAAE;aACR,KAAK,CAAC,qBAAqB,CAAC;aAC5B,QAAQ,EAAE;aACV,QAAQ,CAAC,mDAAmD,CAAC;KACjE,CAAC;SACD,QAAQ,CAAC,6CAA6C,CAAC;CAC3D,CAAC,CAAC;AAEH,yCAAyC;AACzC,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAC,MAAM,CAAC;IACpC,IAAI,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"schemas.js","sourceRoot":"","sources":["../../../../../src/mcp-server/tools/definitions/_shared/schemas.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAE3C,4EAA4E;AAC5E,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC,kBAAkB,CAAC,MAAM,EAAE;IACvD,CAAC;SACE,MAAM,CAAC;QACN,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,iCAAiC,CAAC;QACnE,IAAI,EAAE,CAAC;aACJ,MAAM,EAAE;aACR,GAAG,CAAC,CAAC,CAAC;aACN,QAAQ,CAAC,kEAAkE,CAAC;KAChF,CAAC;SACD,QAAQ,CAAC,4CAA4C,CAAC;IACzD,CAAC;SACE,MAAM,CAAC;QACN,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,QAAQ,CAAC,8CAA8C,CAAC;KACnF,CAAC;SACD,QAAQ,CAAC,gEAAgE,CAAC;IAC7E,CAAC;SACE,MAAM,CAAC;QACN,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,QAAQ,CAAC,oDAAoD,CAAC;QAC1F,MAAM,EAAE,CAAC;aACN,IAAI,CAAC,CAAC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAC;aAC3D,QAAQ,CAAC,4BAA4B,CAAC;QACzC,IAAI,EAAE,CAAC;aACJ,MAAM,EAAE;aACR,KAAK,CAAC,qBAAqB,CAAC;aAC5B,QAAQ,EAAE;aACV,QAAQ,CAAC,mDAAmD,CAAC;KACjE,CAAC;SACD,QAAQ,CAAC,6CAA6C,CAAC;CAC3D,CAAC,CAAC;AAEH,yCAAyC;AACzC,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAC,MAAM,CAAC;IACpC,IAAI,EAAE,CAAC;SACJ,IAAI,CAAC,CAAC,SAAS,EAAE,OAAO,EAAE,aAAa,CAAC,CAAC;SACzC,QAAQ,CAAC,mEAAmE,CAAC;IAChF,MAAM,EAAE,CAAC;SACN,MAAM,EAAE;SACR,GAAG,CAAC,CAAC,CAAC;SACN,QAAQ,CACP,+IAA+I,CAChJ;CACJ,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC;KAChC,MAAM,CAAC;IACN,qBAAqB,EAAE,CAAC;SACrB,OAAO,EAAE;SACT,OAAO,CAAC,KAAK,CAAC;SACd,QAAQ,CAAC,yEAAyE,CAAC;IACtF,uBAAuB,EAAE,CAAC;SACvB,OAAO,EAAE;SACT,OAAO,CAAC,KAAK,CAAC;SACd,QAAQ,CACP,wGAAwG,CACzG;IACH,oBAAoB,EAAE,CAAC;SACpB,OAAO,EAAE;SACT,OAAO,CAAC,KAAK,CAAC;SACd,QAAQ,CAAC,wEAAwE,CAAC;CACtF,CAAC;KACD,QAAQ,EAAE,CAAC;AAEd,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC;KAC/B,IAAI,CAAC,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;KAC1B,OAAO,CAAC,UAAU,CAAC;KACnB,QAAQ,CACP,qPAAqP,CACtP,CAAC"}
|