obsidian-mcp-server 3.7.2 → 3.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +20 -15
- package/CLAUDE.md +20 -15
- package/README.md +31 -19
- package/changelog/3.8.x/3.8.0.md +38 -0
- package/changelog/3.9.x/3.9.0.md +43 -0
- package/changelog/template.md +10 -3
- package/dist/config/server-config.d.ts +1 -0
- package/dist/config/server-config.d.ts.map +1 -1
- package/dist/config/server-config.js +30 -19
- package/dist/config/server-config.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +27 -15
- package/dist/index.js.map +1 -1
- package/dist/instructions.d.ts +4 -3
- package/dist/instructions.d.ts.map +1 -1
- package/dist/instructions.js +23 -12
- package/dist/instructions.js.map +1 -1
- package/dist/mcp-server/resources/definitions/index.d.ts +2 -2
- package/dist/mcp-server/resources/definitions/obsidian-tags.resource.d.ts +3 -2
- package/dist/mcp-server/resources/definitions/obsidian-tags.resource.d.ts.map +1 -1
- package/dist/mcp-server/resources/definitions/obsidian-tags.resource.js +6 -5
- package/dist/mcp-server/resources/definitions/obsidian-tags.resource.js.map +1 -1
- package/dist/mcp-server/resources/definitions/obsidian-vault-note.resource.d.ts +2 -2
- package/dist/mcp-server/resources/definitions/obsidian-vault-note.resource.js +2 -2
- package/dist/mcp-server/resources/definitions/obsidian-vault-note.resource.js.map +1 -1
- package/dist/mcp-server/tools/definitions/_shared/suggest-paths.d.ts +15 -6
- package/dist/mcp-server/tools/definitions/_shared/suggest-paths.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/_shared/suggest-paths.js +24 -12
- package/dist/mcp-server/tools/definitions/_shared/suggest-paths.js.map +1 -1
- package/dist/mcp-server/tools/definitions/index.d.ts +250 -230
- package/dist/mcp-server/tools/definitions/index.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/index.js +6 -4
- package/dist/mcp-server/tools/definitions/index.js.map +1 -1
- package/dist/mcp-server/tools/definitions/obsidian-append-to-note.tool.d.ts +8 -2
- 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 -3
- 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 -6
- 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 +7 -7
- package/dist/mcp-server/tools/definitions/obsidian-delete-note.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/obsidian-get-note.tool.d.ts +2 -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 +8 -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 +6 -6
- package/dist/mcp-server/tools/definitions/obsidian-list-notes.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/obsidian-list-notes.tool.js +8 -8
- package/dist/mcp-server/tools/definitions/obsidian-list-notes.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/obsidian-list-tags.tool.d.ts +4 -4
- package/dist/mcp-server/tools/definitions/obsidian-list-tags.tool.js +7 -7
- package/dist/mcp-server/tools/definitions/obsidian-list-tags.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/obsidian-manage-frontmatter.tool.d.ts +2 -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 +2 -2
- 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 +2 -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 +2 -2
- package/dist/mcp-server/tools/definitions/obsidian-manage-tags.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/obsidian-open-in-ui.tool.d.ts +2 -2
- package/dist/mcp-server/tools/definitions/obsidian-open-in-ui.tool.js +3 -3
- 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 +8 -2
- 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 -3
- 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 +2 -2
- package/dist/mcp-server/tools/definitions/obsidian-replace-in-note.tool.js +2 -2
- package/dist/mcp-server/tools/definitions/obsidian-replace-in-note.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/obsidian-search-notes.tool.d.ts +185 -35
- 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 +145 -82
- 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 +8 -2
- 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 +12 -5
- package/dist/mcp-server/tools/definitions/obsidian-write-note.tool.js.map +1 -1
- package/dist/services/obsidian/jsonlogic-evaluator.d.ts +33 -8
- package/dist/services/obsidian/jsonlogic-evaluator.d.ts.map +1 -1
- package/dist/services/obsidian/jsonlogic-evaluator.js +171 -32
- package/dist/services/obsidian/jsonlogic-evaluator.js.map +1 -1
- package/dist/services/obsidian/jsonlogic-worker.d.ts +6 -5
- package/dist/services/obsidian/jsonlogic-worker.d.ts.map +1 -1
- package/dist/services/obsidian/jsonlogic-worker.js +7 -5
- package/dist/services/obsidian/jsonlogic-worker.js.map +1 -1
- package/dist/services/obsidian/obsidian-service.d.ts +90 -36
- package/dist/services/obsidian/obsidian-service.d.ts.map +1 -1
- package/dist/services/obsidian/obsidian-service.js +748 -248
- package/dist/services/obsidian/obsidian-service.js.map +1 -1
- package/dist/services/obsidian/patch-instruction.d.ts +4 -1
- package/dist/services/obsidian/patch-instruction.d.ts.map +1 -1
- package/dist/services/obsidian/patch-instruction.js +5 -2
- package/dist/services/obsidian/patch-instruction.js.map +1 -1
- package/dist/services/obsidian/path-policy.d.ts +67 -23
- package/dist/services/obsidian/path-policy.d.ts.map +1 -1
- package/dist/services/obsidian/path-policy.js +183 -80
- package/dist/services/obsidian/path-policy.js.map +1 -1
- package/dist/services/obsidian/section-extractor.d.ts +62 -1
- package/dist/services/obsidian/section-extractor.d.ts.map +1 -1
- package/dist/services/obsidian/section-extractor.js +387 -51
- package/dist/services/obsidian/section-extractor.js.map +1 -1
- package/dist/services/obsidian/simple-search.d.ts +62 -0
- package/dist/services/obsidian/simple-search.d.ts.map +1 -0
- package/dist/services/obsidian/simple-search.js +264 -0
- package/dist/services/obsidian/simple-search.js.map +1 -0
- package/manifest.json +12 -4
- package/package.json +9 -9
- package/server.json +23 -11
- package/skills/obsidian-guide/SKILL.md +61 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
---
|
|
2
|
+
summary: "Request timeouts are enforced on Bun and Node, Omnisearch is withheld under a read scope, and heading writes below a repeated link definition are refused before any PATCH. Scoped text searches evaluate once per walk, and the server publishes its first skill, obsidian-guide."
|
|
3
|
+
breaking: true
|
|
4
|
+
security: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# 3.9.0 — 2026-11-11
|
|
8
|
+
|
|
9
|
+
## Added
|
|
10
|
+
|
|
11
|
+
- **The `obsidian-guide` skill**, the server's first published skill, served as `skill://obsidian-guide/SKILL.md` through `createApp({ skills: 'skills' })`. The server `instructions` point at it.
|
|
12
|
+
|
|
13
|
+
## Changed
|
|
14
|
+
|
|
15
|
+
- **`obsidian_search_notes` with `mode: "omnisearch"` under `OBSIDIAN_READ_PATHS` or `OBSIDIAN_DENY_PATHS` is rejected as invalid params (-32602)** before any Omnisearch request, the startup probe included. The mode is withheld from the `mode` enum and the tool description, and the output enum `truncatedReason` no longer has `read_scope`. Scoped callers search with `text` or `jsonlogic`. ([#173](https://github.com/cyanheads/obsidian-mcp-server/issues/173))
|
|
16
|
+
- **Heading writes below a repeated link definition fail `repeated_link_definition` before any PATCH**, from `obsidian_patch_note` and from `obsidian_append_to_note` and `obsidian_write_note` with `section`. For a section that runs to the end of the note, the repeat must sit above the target heading itself; a repeat inside that last section is not refused. ([#175](https://github.com/cyanheads/obsidian-mcp-server/issues/175))
|
|
17
|
+
- **The refusal also covers writes no plugin engine would have misplaced**: a prepend whose repeat sits inside the target section; an append to a section that runs to the end of the note, with the repeat above its heading; a heading created under an ancestor heading path that occurs more than once in the note, which the check places at the farther of the two engines' candidate positions, so it can refuse a create only the other wire format would misplace; a write that would have left the note unchanged; and labels the check folds more coarsely than the parser does, a lazy blockquote continuation included. On plugin 5.x a heading write now reads the note before the PATCH, so a read of it that fails persistently or with a 4xx fails a write 3.8.0 sent. ([#175](https://github.com/cyanheads/obsidian-mcp-server/issues/175))
|
|
18
|
+
- **A request attempt that runs past `OBSIDIAN_REQUEST_TIMEOUT_MS`, headers or body, fails `obsidian_timeout` on Bun and Node.** On Bun an Omnisearch query past it now fails `omnisearch_unreachable`, where 3.8.0 had no bound and let it finish. ([#176](https://github.com/cyanheads/obsidian-mcp-server/issues/176))
|
|
19
|
+
- **A call whose requests together pass max(45 s, `OBSIDIAN_REQUEST_TIMEOUT_MS`) fails `obsidian_timeout`.** ([#176](https://github.com/cyanheads/obsidian-mcp-server/issues/176))
|
|
20
|
+
- **`OBSIDIAN_REQUEST_TIMEOUT_MS` above 2147483647 fails at startup.**
|
|
21
|
+
- **A connection dropped mid-body fails `obsidian_unreachable` and is retried on GET, PUT, and DELETE.** ([#176](https://github.com/cyanheads/obsidian-mcp-server/issues/176))
|
|
22
|
+
- **A scoped `text` search is searched once.** Later pages come from the stored hit list, kept up to 5 minutes past the last page read and 32 Mi characters across walks, and show the first page's snapshot. A walk is stored only when the hits run past the page being served. ([#177](https://github.com/cyanheads/obsidian-mcp-server/issues/177))
|
|
23
|
+
- **The Omnisearch-mode `matches`, `excerpt`, and `score` descriptions are corrected**, and `tools/list` declares `omnisearch_unreachable` only where the mode is offered. ([#173](https://github.com/cyanheads/obsidian-mcp-server/issues/173))
|
|
24
|
+
- **The `obsidian_list_tags` description gains JSONLogic tag-matching examples**, and the server `instructions` point at the `obsidian-guide` skill.
|
|
25
|
+
|
|
26
|
+
## Fixed
|
|
27
|
+
|
|
28
|
+
- **A call waiting on the plugin-version read another call started no longer fails when that other call is cancelled**; it reads the version itself.
|
|
29
|
+
- **The did-you-mean, ambiguous-path, and case-variant path suggestions in `content[]` render as code spans.**
|
|
30
|
+
- **Creating a heading under an existing ancestor finds that ancestor in time linear in the note.**
|
|
31
|
+
|
|
32
|
+
## Security
|
|
33
|
+
|
|
34
|
+
- **Under `OBSIDIAN_READ_PATHS` or `OBSIDIAN_DENY_PATHS`, Omnisearch ranked and selected its results over the whole vault**, so notes outside the scope changed what a scoped caller saw. The mode is now withheld under either. ([#173](https://github.com/cyanheads/obsidian-mcp-server/issues/173))
|
|
35
|
+
|
|
36
|
+
## Dependencies
|
|
37
|
+
|
|
38
|
+
- `@cyanheads/mcp-ts-core` ^0.13.18 → ^0.13.22
|
|
39
|
+
- `engines.bun` >=1.4.0 → >=1.4.4
|
|
40
|
+
- `undici` ^8.12.3 → ^8.12.4
|
|
41
|
+
- `@biomejs/biome` ^2.6.4 → ^2.6.6 (dev)
|
|
42
|
+
- `vitest`, `@vitest/coverage-istanbul` ^5.0.5 → ^5.1.0 (dev)
|
|
43
|
+
- `tsc-alias` ^1.9.9 → ^1.9.10 (dev)
|
package/changelog/template.md
CHANGED
|
@@ -116,14 +116,21 @@ security: false
|
|
|
116
116
|
resolves to whatever real item already owns 42, and timeline previews pull
|
|
117
117
|
in that unrelated item's metadata.
|
|
118
118
|
|
|
119
|
+
Outside reporters: when the issue or PR came from outside the project
|
|
120
|
+
(`git-wrapup` step 5 says how to tell), thank its author in the same
|
|
121
|
+
parenthetical, profile linked by full URL for the same reason:
|
|
122
|
+
|
|
123
|
+
([#38](https://github.com/cyanheads/mcp-ts-core/issues/38), thanks [@octocat](https://github.com/octocat)!)
|
|
124
|
+
|
|
119
125
|
TAG ANNOTATIONS — the annotated tag body renders as the GitHub Release body
|
|
120
126
|
via `gh release create --notes-from-tag`. It is a condensed digest of this
|
|
121
127
|
entry, never a copy, and its format is owned by the `release-and-publish`
|
|
122
128
|
skill (step 4, "Create the annotated tag"): a short subject line without the
|
|
123
129
|
version, flat headline bullets — no Keep-a-Changelog section headers, no
|
|
124
|
-
gates line — at most one deps line, issue backlinks
|
|
125
|
-
last. In release-PR mode the `git-wrapup`
|
|
126
|
-
PR body's `## Changes` and the tag copies
|
|
130
|
+
gates line — at most one deps line, issue backlinks with any outside-reporter
|
|
131
|
+
thanks, and the changelog link last. In release-PR mode the `git-wrapup`
|
|
132
|
+
skill authors those bullets as the PR body's `## Changes` and the tag copies
|
|
133
|
+
them.
|
|
127
134
|
-->
|
|
128
135
|
|
|
129
136
|
## Added
|
|
@@ -12,6 +12,7 @@ declare const ServerConfigSchema: z.ZodObject<{
|
|
|
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
|
+
denyPaths: z.ZodPreprocess<z.ZodPipe<z.ZodOptional<z.ZodArray<z.ZodString>>, z.ZodTransform<string[] | undefined, string[] | undefined>>, unknown>;
|
|
15
16
|
readOnly: z.ZodDefault<z.ZodUnion<readonly [z.ZodBoolean, z.ZodCodec<z.ZodString, z.ZodBoolean>]>>;
|
|
16
17
|
deleteElicitation: z.ZodDefault<z.ZodUnion<readonly [z.ZodBoolean, z.ZodCodec<z.ZodString, z.ZodBoolean>]>>;
|
|
17
18
|
omnisearchUrl: z.ZodOptional<z.ZodString>;
|
|
@@ -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;AAwF3C,QAAA,MAAM,kBAAkB;;;;;;;;;;;;iBAmEtB,CAAC;AAEH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAI9D,wBAAgB,eAAe,IAAI,YAAY,CAe9C;AAED,iEAAiE;AACjE,wBAAgB,iBAAiB,IAAI,IAAI,CAExC"}
|
|
@@ -12,18 +12,20 @@ import { parseEnvConfig } from '@cyanheads/mcp-ts-core/config';
|
|
|
12
12
|
*/
|
|
13
13
|
const envBoolean = z.union([z.boolean(), z.stringbool()]);
|
|
14
14
|
/**
|
|
15
|
-
* Comma-separated path-list preprocessor
|
|
16
|
-
*
|
|
15
|
+
* Comma-separated path-list preprocessor, shared by OBSIDIAN_READ_PATHS,
|
|
16
|
+
* OBSIDIAN_WRITE_PATHS, and OBSIDIAN_DENY_PATHS. Semantics (see issues #40, #76):
|
|
17
|
+
* - undefined / `''` / whitespace-only → undefined (treat as unset)
|
|
17
18
|
* - `,` / `,,,` (separators only, no path content) → throw ZodError → ConfigurationError
|
|
18
19
|
* - mixed empties (`a,,b`) → drop empties → `['a', 'b']`
|
|
19
|
-
* - absolute path / `..` traversal → throw
|
|
20
|
-
* - valid: `\` →
|
|
20
|
+
* - absolute path / `..` traversal / an entry naming the vault root (`.`, `./`) → throw
|
|
21
|
+
* - valid: `\` → `/`, empty and `.` segments dropped, lower-case, NFC, dedupe
|
|
22
|
+
* (preserves first occurrence order)
|
|
21
23
|
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
24
|
+
* The stored form is `PathPolicy.normalize()`'s — the form a vault path
|
|
25
|
+
* reaches the plugin in — so a prefix and a candidate compare directly. A
|
|
26
|
+
* prefix kept as written (`foo\bar`, `./private`, `journal//therapy`) would
|
|
27
|
+
* match no vault path: a refusal for an allowlist, and a deny entry that
|
|
28
|
+
* silently denies nothing.
|
|
27
29
|
*/
|
|
28
30
|
const envPathList = z
|
|
29
31
|
.preprocess((val) => {
|
|
@@ -63,7 +65,7 @@ const envPathList = z
|
|
|
63
65
|
});
|
|
64
66
|
return z.NEVER;
|
|
65
67
|
}
|
|
66
|
-
const segments = raw.split(/[\\/]/);
|
|
68
|
+
const segments = raw.split(/[\\/]/).filter((s) => s !== '' && s !== '.');
|
|
67
69
|
if (segments.includes('..')) {
|
|
68
70
|
ctx.addIssue({
|
|
69
71
|
code: 'custom',
|
|
@@ -71,9 +73,14 @@ const envPathList = z
|
|
|
71
73
|
});
|
|
72
74
|
return z.NEVER;
|
|
73
75
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
76
|
+
if (segments.length === 0) {
|
|
77
|
+
ctx.addIssue({
|
|
78
|
+
code: 'custom',
|
|
79
|
+
message: `must name a folder or note, not the vault root; got '${raw}'`,
|
|
80
|
+
});
|
|
81
|
+
return z.NEVER;
|
|
82
|
+
}
|
|
83
|
+
const normalized = segments.join('/').toLowerCase().normalize('NFC');
|
|
77
84
|
if (seen.has(normalized))
|
|
78
85
|
continue;
|
|
79
86
|
seen.add(normalized);
|
|
@@ -95,8 +102,8 @@ const ServerConfigSchema = z.object({
|
|
|
95
102
|
/**
|
|
96
103
|
* Normalized here rather than at each `${baseUrl}${path}` join: the schema
|
|
97
104
|
* is the one place that runs before anything reads the value, so a single
|
|
98
|
-
* transform covers `#request
|
|
99
|
-
* and `deriveOmnisearchUrl` alike (issue #121).
|
|
105
|
+
* transform covers `#request` (the HEAD size probe included), the
|
|
106
|
+
* capability probe, and `deriveOmnisearchUrl` alike (issue #121).
|
|
100
107
|
*/
|
|
101
108
|
.transform((url) => url.replace(/\/+$/, '')),
|
|
102
109
|
verifySsl: envBoolean
|
|
@@ -106,13 +113,16 @@ const ServerConfigSchema = z.object({
|
|
|
106
113
|
.number()
|
|
107
114
|
.int()
|
|
108
115
|
.positive()
|
|
116
|
+
// The longest delay a timer takes; past it both runtimes fire after 1 ms.
|
|
117
|
+
.max(2_147_483_647)
|
|
109
118
|
.default(30_000)
|
|
110
|
-
.describe('
|
|
119
|
+
.describe('Milliseconds (at most 2147483647) one attempt at a Local REST API request — headers and body — may take before it fails with `obsidian_timeout`; an Omnisearch query past it fails with `omnisearch_unreachable`. GET, PUT, and DELETE retry a timed-out attempt, and every Local REST API request one tool or resource call makes shares a budget of 45 s, or of this value when it is longer.'),
|
|
111
120
|
enableCommands: envBoolean
|
|
112
121
|
.default(false)
|
|
113
122
|
.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.'),
|
|
114
|
-
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.'),
|
|
115
|
-
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, or the read scope when reads are restricted.'),
|
|
123
|
+
readPaths: envPathList.describe('Optional vault-relative folder allowlist for read operations. Comma-separated; prefix-based with implicit recursion; case-insensitive; backslashes read as slashes, repeated and trailing slashes and `.` segments dropped, and names normalized to Unicode NFC; an entry naming the vault root (`.`) is rejected at startup. Unset = full vault.'),
|
|
124
|
+
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, or the read scope when reads are restricted; paths in OBSIDIAN_DENY_PATHS stay denied.'),
|
|
125
|
+
denyPaths: envPathList.describe('Optional vault-relative blocklist for reads and writes alike. Same syntax as OBSIDIAN_READ_PATHS. Wins over both allowlists: a denied path is unreadable and unwritable, and absent from listings, search results, and tag counts. Unset = nothing denied.'),
|
|
116
126
|
readOnly: envBoolean
|
|
117
127
|
.default(false)
|
|
118
128
|
.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.'),
|
|
@@ -123,7 +133,7 @@ const ServerConfigSchema = z.object({
|
|
|
123
133
|
.string()
|
|
124
134
|
.url()
|
|
125
135
|
.optional()
|
|
126
|
-
.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.'),
|
|
136
|
+
.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. Under OBSIDIAN_READ_PATHS or OBSIDIAN_DENY_PATHS the mode is withheld and the URL is never called: Omnisearch ranks and selects its results over the whole vault, so they depend on notes outside the scope.'),
|
|
127
137
|
});
|
|
128
138
|
let _config;
|
|
129
139
|
export function getServerConfig() {
|
|
@@ -135,6 +145,7 @@ export function getServerConfig() {
|
|
|
135
145
|
enableCommands: 'OBSIDIAN_ENABLE_COMMANDS',
|
|
136
146
|
readPaths: 'OBSIDIAN_READ_PATHS',
|
|
137
147
|
writePaths: 'OBSIDIAN_WRITE_PATHS',
|
|
148
|
+
denyPaths: 'OBSIDIAN_DENY_PATHS',
|
|
138
149
|
readOnly: 'OBSIDIAN_READ_ONLY',
|
|
139
150
|
deleteElicitation: 'OBSIDIAN_DELETE_ELICITATION',
|
|
140
151
|
omnisearchUrl: 'OBSIDIAN_OMNISEARCH_URL',
|
|
@@ -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;;;;GAIG;AACH,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;AAE1D
|
|
1
|
+
{"version":3,"file":"server-config.js","sourceRoot":"","sources":["../../src/config/server-config.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
3
|
* @fileoverview obsidian-mcp-server entry point. Initializes the Obsidian
|
|
4
|
-
* Local REST API service at module load so
|
|
4
|
+
* Local REST API service at module load so Omnisearch availability is decided
|
|
5
5
|
* before tools are constructed — `obsidian_search_notes` is built via a
|
|
6
|
-
* factory that takes
|
|
7
|
-
*
|
|
6
|
+
* factory that takes it as input, so the `omnisearch` mode appears in the tool
|
|
7
|
+
* schema only with reads unscoped and the plugin actually reachable.
|
|
8
8
|
* @module index
|
|
9
9
|
*/
|
|
10
10
|
export {};
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
3
|
* @fileoverview obsidian-mcp-server entry point. Initializes the Obsidian
|
|
4
|
-
* Local REST API service at module load so
|
|
4
|
+
* Local REST API service at module load so Omnisearch availability is decided
|
|
5
5
|
* before tools are constructed — `obsidian_search_notes` is built via a
|
|
6
|
-
* factory that takes
|
|
7
|
-
*
|
|
6
|
+
* factory that takes it as input, so the `omnisearch` mode appears in the tool
|
|
7
|
+
* schema only with reads unscoped and the plugin actually reachable.
|
|
8
8
|
* @module index
|
|
9
9
|
*/
|
|
10
10
|
import { createApp, disabledTool } from '@cyanheads/mcp-ts-core';
|
|
@@ -13,21 +13,22 @@ import { getServerConfig } from './config/server-config.js';
|
|
|
13
13
|
import { buildInstructions } from './instructions.js';
|
|
14
14
|
import { allPromptDefinitions } from './mcp-server/prompts/definitions/index.js';
|
|
15
15
|
import { allResourceDefinitions } from './mcp-server/resources/definitions/index.js';
|
|
16
|
-
import { buildDeleteNoteTool, buildSearchNotesTool, commandToolDefinitions, readToolDefinitions, writeToolDefinitions, } from './mcp-server/tools/definitions/index.js';
|
|
16
|
+
import { buildDeleteNoteTool, buildSearchNotesTool, commandToolDefinitions, omnisearchAvailability, readToolDefinitions, writeToolDefinitions, } from './mcp-server/tools/definitions/index.js';
|
|
17
17
|
import { getObsidianService, initObsidianService } from './services/obsidian/obsidian-service.js';
|
|
18
18
|
import { PathPolicy } from './services/obsidian/path-policy.js';
|
|
19
19
|
const config = getServerConfig();
|
|
20
20
|
const policy = new PathPolicy(config);
|
|
21
21
|
/**
|
|
22
|
-
* Init the service at module load (rather than inside `setup()`) so
|
|
23
|
-
* Omnisearch
|
|
24
|
-
*
|
|
22
|
+
* Init the service at module load (rather than inside `setup()`) so
|
|
23
|
+
* Omnisearch availability — the probe, or `withheld` under a read scope with
|
|
24
|
+
* no probe — is known before tool construction. `setup()` runs after tools
|
|
25
|
+
* are passed into `createApp()`, which is too late to influence the
|
|
25
26
|
* search-notes schema.
|
|
26
27
|
*/
|
|
27
28
|
initObsidianService(config);
|
|
28
29
|
const obsidian = getObsidianService();
|
|
29
|
-
const
|
|
30
|
-
const searchNotesTool = buildSearchNotesTool({
|
|
30
|
+
const omnisearch = await omnisearchAvailability(obsidian);
|
|
31
|
+
const searchNotesTool = buildSearchNotesTool({ omnisearch });
|
|
31
32
|
const writeToolSet = [
|
|
32
33
|
...writeToolDefinitions,
|
|
33
34
|
buildDeleteNoteTool({ elicitation: config.deleteElicitation }),
|
|
@@ -63,10 +64,12 @@ const { services } = await createApp({
|
|
|
63
64
|
prompts: allPromptDefinitions,
|
|
64
65
|
instructions: buildInstructions({
|
|
65
66
|
enableCommands: config.enableCommands,
|
|
66
|
-
|
|
67
|
+
omnisearch,
|
|
67
68
|
policy,
|
|
68
69
|
readOnly: config.readOnly,
|
|
69
70
|
}),
|
|
71
|
+
/** Root `skills/`, served as `skill://<name>/SKILL.md` to clients without the plugin. */
|
|
72
|
+
skills: 'skills',
|
|
70
73
|
/**
|
|
71
74
|
* With `OBSIDIAN_DELETE_ELICITATION=true` (and writes allowed),
|
|
72
75
|
* `obsidian_delete_note` confirms through `ctx.requestInput`, which a
|
|
@@ -92,7 +95,11 @@ const { services } = await createApp({
|
|
|
92
95
|
* the tool is disabled there). The server `instructions` and the active scope
|
|
93
96
|
* on `path_forbidden` errors state the effective scope instead (write paths
|
|
94
97
|
* are readable; a write needs read access), so the LLM (or operator) can
|
|
95
|
-
* self-correct without scrolling the log.
|
|
98
|
+
* self-correct without scrolling the log. The deny list (`denyPaths`, present
|
|
99
|
+
* when set) appears only here: the agent-facing surfaces say paths are
|
|
100
|
+
* withheld without naming them. `omnisearch` is the startup
|
|
101
|
+
* `omnisearchAvailability`; under a read scope it is `withheld` and the
|
|
102
|
+
* plugin was never probed.
|
|
96
103
|
*/
|
|
97
104
|
const bannerCtx = requestContextService.createRequestContext({
|
|
98
105
|
operation: 'startup',
|
|
@@ -101,14 +108,19 @@ const bannerCtx = requestContextService.createRequestContext({
|
|
|
101
108
|
enableCommands: config.enableCommands && !config.readOnly,
|
|
102
109
|
deleteElicitation: deleteGateActive,
|
|
103
110
|
omnisearchUrl: obsidian.omnisearchUrl,
|
|
104
|
-
|
|
111
|
+
omnisearch,
|
|
105
112
|
},
|
|
106
113
|
});
|
|
107
114
|
services.logger.info('Path policy', bannerCtx);
|
|
108
|
-
services.logger.info(
|
|
109
|
-
|
|
110
|
-
: `Omnisearch not reachable at ${obsidian.omnisearchUrl} — \`omnisearch\` mode omitted from \`obsidian_search_notes\`. Set OBSIDIAN_OMNISEARCH_URL or enable the Omnisearch plugin's HTTP server to use it.`,
|
|
115
|
+
services.logger.info({
|
|
116
|
+
offered: `Omnisearch reachable at ${obsidian.omnisearchUrl} — \`omnisearch\` mode enabled on \`obsidian_search_notes\`.`,
|
|
117
|
+
unreachable: `Omnisearch not reachable at ${obsidian.omnisearchUrl} — \`omnisearch\` mode omitted from \`obsidian_search_notes\`. Set OBSIDIAN_OMNISEARCH_URL or enable the Omnisearch plugin's HTTP server to use it.`,
|
|
118
|
+
withheld: 'Omnisearch not probed — `omnisearch` mode withheld from `obsidian_search_notes` because OBSIDIAN_READ_PATHS or OBSIDIAN_DENY_PATHS scopes reads. Omnisearch ranks and selects its results over the whole vault, so they depend on notes outside the scope; `text` and `jsonlogic` modes search the readable notes alone.',
|
|
119
|
+
}[omnisearch], bannerCtx);
|
|
111
120
|
if (policy.readOnlyShadowsWritePaths) {
|
|
112
121
|
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);
|
|
113
122
|
}
|
|
123
|
+
for (const { variable, prefix } of policy.denyShadowedPaths) {
|
|
124
|
+
services.logger.warning(`${variable} entry '${prefix}' lies inside OBSIDIAN_DENY_PATHS and grants nothing. Remove it, or narrow the deny entry that covers it.`, bannerCtx);
|
|
125
|
+
}
|
|
114
126
|
//# 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;;;;;;;GAOG;AAEH,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,sBAAsB,EAAE,MAAM,6CAA6C,CAAC;AACrF,OAAO,EACL,mBAAmB,EACnB,oBAAoB,EACpB,sBAAsB,EACtB,mBAAmB,EACnB,oBAAoB,GACrB,MAAM,yCAAyC,CAAC;AACjD,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,yCAAyC,CAAC;AAClG,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
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;;GAOG;AAEH,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,sBAAsB,EAAE,MAAM,6CAA6C,CAAC;AACrF,OAAO,EACL,mBAAmB,EACnB,oBAAoB,EACpB,sBAAsB,EAEtB,sBAAsB,EACtB,mBAAmB,EACnB,oBAAoB,GACrB,MAAM,yCAAyC,CAAC;AACjD,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,yCAAyC,CAAC;AAClG,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;;;;;;GAMG;AACH,mBAAmB,CAAC,MAAM,CAAC,CAAC;AAC5B,MAAM,QAAQ,GAAG,kBAAkB,EAAE,CAAC;AACtC,MAAM,UAAU,GAAG,MAAM,sBAAsB,CAAC,QAAQ,CAAC,CAAC;AAE1D,MAAM,eAAe,GAAG,oBAAoB,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC;AAE7D,MAAM,YAAY,GAAG;IACnB,GAAG,oBAAoB;IACvB,mBAAmB,CAAC,EAAE,WAAW,EAAE,MAAM,CAAC,iBAAiB,EAAE,CAAC;CAC/D,CAAC;AAEF;;;;GAIG;AACH,MAAM,gBAAgB,GAAG,MAAM,CAAC,iBAAiB,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC;AAEtE,MAAM,UAAU,GAAG,MAAM,CAAC,QAAQ;IAChC,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CACvB,YAAY,CAAC,GAAG,EAAE;QAChB,MAAM,EAAE,sCAAsC;QAC9C,IAAI,EAAE,sEAAsE;KAC7E,CAAC,CACH;IACH,CAAC,CAAC,YAAY,CAAC;AAEjB,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,eAAe,EAAE,GAAG,UAAU,EAAE,GAAG,YAAY,CAAC,CAAC;AAExF,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,SAAS,CAAC;IACnC,IAAI,EAAE,qBAAqB;IAC3B,KAAK,EAAE,qBAAqB;IAC5B,KAAK;IACL,SAAS,EAAE,sBAAsB;IACjC,OAAO,EAAE,oBAAoB;IAC7B,YAAY,EAAE,iBAAiB,CAAC;QAC9B,cAAc,EAAE,MAAM,CAAC,cAAc;QACrC,UAAU;QACV,MAAM;QACN,QAAQ,EAAE,MAAM,CAAC,QAAQ;KAC1B,CAAC;IACF,yFAAyF;IACzF,MAAM,EAAE,QAAQ;IAChB;;;;;;;;;;OAUG;IACH,WAAW,EAAE,gBAAgB;QAC3B,CAAC,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,EAAE;QAC9C,CAAC,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE;IAC3B,QAAQ,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,KAAK,EAAE;CACjC,CAAC,CAAC;AAEH;;;;;;;;;;;;;;GAcG;AACH,MAAM,SAAS,GAAG,qBAAqB,CAAC,oBAAoB,CAAC;IAC3D,SAAS,EAAE,SAAS;IACpB,iBAAiB,EAAE;QACjB,GAAG,MAAM,CAAC,QAAQ,EAAE;QACpB,cAAc,EAAE,MAAM,CAAC,cAAc,IAAI,CAAC,MAAM,CAAC,QAAQ;QACzD,iBAAiB,EAAE,gBAAgB;QACnC,aAAa,EAAE,QAAQ,CAAC,aAAa;QACrC,UAAU;KACX;CACF,CAAC,CAAC;AACH,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC;AAC/C,QAAQ,CAAC,MAAM,CAAC,IAAI,CAEhB;IACE,OAAO,EAAE,2BAA2B,QAAQ,CAAC,aAAa,8DAA8D;IACxH,WAAW,EAAE,+BAA+B,QAAQ,CAAC,aAAa,qJAAqJ;IACvN,QAAQ,EACN,0TAA0T;CAE/T,CAAC,UAAU,CAAC,EACb,SAAS,CACV,CAAC;AACF,IAAI,MAAM,CAAC,yBAAyB,EAAE,CAAC;IACrC,QAAQ,CAAC,MAAM,CAAC,OAAO,CACrB,uHAAuH,EACvH,SAAS,CACV,CAAC;AACJ,CAAC;AACD,KAAK,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,MAAM,CAAC,iBAAiB,EAAE,CAAC;IAC5D,QAAQ,CAAC,MAAM,CAAC,OAAO,CACrB,GAAG,QAAQ,WAAW,MAAM,2GAA2G,EACvI,SAAS,CACV,CAAC;AACJ,CAAC"}
|
package/dist/instructions.d.ts
CHANGED
|
@@ -2,18 +2,19 @@
|
|
|
2
2
|
* @fileoverview The server-level `instructions` string sent on every
|
|
3
3
|
* `initialize`: baseline orientation, then deployment-specific lines for
|
|
4
4
|
* read-only mode, the effective path scope, the command-palette toggle, and
|
|
5
|
-
*
|
|
5
|
+
* the `omnisearch` mode when it is offered.
|
|
6
6
|
* @module instructions
|
|
7
7
|
*/
|
|
8
|
+
import type { OmnisearchAvailability } from './mcp-server/tools/definitions/obsidian-search-notes.tool.js';
|
|
8
9
|
import type { PathPolicy } from './services/obsidian/path-policy.js';
|
|
9
10
|
/**
|
|
10
11
|
* Build the instructions. The scope lines state what `path_forbidden`
|
|
11
12
|
* enforces (`PathPolicy.effectiveScope`), not the configured lists the
|
|
12
|
-
* startup banner reports.
|
|
13
|
+
* startup banner reports. Omnisearch appears only when the mode is `offered`.
|
|
13
14
|
*/
|
|
14
15
|
export declare function buildInstructions(opts: {
|
|
15
16
|
enableCommands: boolean;
|
|
16
|
-
|
|
17
|
+
omnisearch: OmnisearchAvailability;
|
|
17
18
|
policy: PathPolicy;
|
|
18
19
|
readOnly: boolean;
|
|
19
20
|
}): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instructions.d.ts","sourceRoot":"","sources":["../src/instructions.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oCAAoC,CAAC;
|
|
1
|
+
{"version":3,"file":"instructions.d.ts","sourceRoot":"","sources":["../src/instructions.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,8DAA8D,CAAC;AAC3G,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oCAAoC,CAAC;AAsBrE;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE;IACtC,cAAc,EAAE,OAAO,CAAC;IACxB,UAAU,EAAE,sBAAsB,CAAC;IACnC,MAAM,EAAE,UAAU,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;CACnB,GAAG,MAAM,CA+BT"}
|
package/dist/instructions.js
CHANGED
|
@@ -2,38 +2,49 @@
|
|
|
2
2
|
* @fileoverview The server-level `instructions` string sent on every
|
|
3
3
|
* `initialize`: baseline orientation, then deployment-specific lines for
|
|
4
4
|
* read-only mode, the effective path scope, the command-palette toggle, and
|
|
5
|
-
*
|
|
5
|
+
* the `omnisearch` mode when it is offered.
|
|
6
6
|
* @module instructions
|
|
7
7
|
*/
|
|
8
|
-
const BASELINE = 'Use the `obsidian_*` tools to access the Obsidian vault via the Local REST API plugin: search, read, write, and patch notes, including targeted edits to headings, blocks, and YAML frontmatter. Notes are addressed by vault-relative path including the file extension (e.g. `Folder/Note.md`); tags support hierarchical `parent/child` notation, and counts roll up to parents.';
|
|
8
|
+
const BASELINE = 'Use the `obsidian_*` tools to access the Obsidian vault via the Local REST API plugin: search, read, write, and patch notes, including targeted edits to headings, blocks, and YAML frontmatter. Notes are addressed by vault-relative path including the file extension (e.g. `Folder/Note.md`); tags support hierarchical `parent/child` notation, and counts roll up to parents. The obsidian-guide skill (`skill://obsidian-guide/SKILL.md`) carries the gates for edits that span calls: pinning `active` and `periodic` targets, round-tripping heading sections, paging a search before editing its hits, matching tags, and repeating a write after a timeout or a dropped connection.';
|
|
9
9
|
const SCOPE_RECOVERY = 'Paths outside scope reject with `path_forbidden` — error data carries the active scope so you can self-correct.';
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
const WITHHELD_RECOVERY = 'Withheld paths reject with subreason `denied_path` and carry no scope.';
|
|
11
|
+
/**
|
|
12
|
+
* Prefixes as the instructions quote them; `undefined` is an unrestricted op,
|
|
13
|
+
* `[]` an op that reaches nothing. `withheld` notes that OBSIDIAN_DENY_PATHS
|
|
14
|
+
* carves paths out of the scope, without naming them: the deny prefixes name
|
|
15
|
+
* exactly what the list hides.
|
|
16
|
+
*/
|
|
17
|
+
function renderScope(scope, withheld) {
|
|
18
|
+
if (scope?.length === 0)
|
|
19
|
+
return 'none';
|
|
20
|
+
const reach = scope === undefined ? 'full vault' : scope.map((p) => `'${p}'`).join(', ');
|
|
21
|
+
return withheld ? `${reach}, except paths the operator withholds` : reach;
|
|
13
22
|
}
|
|
14
23
|
/**
|
|
15
24
|
* Build the instructions. The scope lines state what `path_forbidden`
|
|
16
25
|
* enforces (`PathPolicy.effectiveScope`), not the configured lists the
|
|
17
|
-
* startup banner reports.
|
|
26
|
+
* startup banner reports. Omnisearch appears only when the mode is `offered`.
|
|
18
27
|
*/
|
|
19
28
|
export function buildInstructions(opts) {
|
|
20
|
-
const { enableCommands,
|
|
29
|
+
const { enableCommands, omnisearch, policy, readOnly } = opts;
|
|
21
30
|
const { readable, writable } = policy.effectiveScope();
|
|
31
|
+
const withheld = policy.withholdsPaths;
|
|
32
|
+
const recovery = withheld ? `${SCOPE_RECOVERY} ${WITHHELD_RECOVERY}` : SCOPE_RECOVERY;
|
|
22
33
|
const sections = [BASELINE];
|
|
23
34
|
if (readOnly) {
|
|
24
35
|
sections.push('Read-only mode is active (OBSIDIAN_READ_ONLY=true): write tools are unavailable. `obsidian_open_in_ui` still opens notes that exist, but rejects an open against a missing path — Obsidian would create the file.');
|
|
25
|
-
if (readable !== undefined) {
|
|
26
|
-
sections.push(`Vault path policy is enforced. Readable: ${renderScope(readable)}. ${
|
|
36
|
+
if (readable !== undefined || withheld) {
|
|
37
|
+
sections.push(`Vault path policy is enforced. Readable: ${renderScope(readable, withheld)}. ${recovery}`);
|
|
27
38
|
}
|
|
28
39
|
}
|
|
29
40
|
else if (!policy.isUnrestricted) {
|
|
30
|
-
sections.push(`Vault path policy is enforced. Readable: ${renderScope(readable)}. Writable: ${renderScope(writable)}. ${
|
|
41
|
+
sections.push(`Vault path policy is enforced. Readable: ${renderScope(readable, withheld)}. Writable: ${renderScope(writable, withheld)}. ${recovery}`);
|
|
31
42
|
}
|
|
32
43
|
if (enableCommands && !readOnly) {
|
|
33
44
|
sections.push('Command-palette tools (`obsidian_list_commands`, `obsidian_execute_command`) are enabled and can fire any Obsidian command. Commands are opaque and may be destructive — prefer dedicated tools when one fits.');
|
|
34
45
|
}
|
|
35
|
-
if (
|
|
36
|
-
sections.push('`obsidian_search_notes` includes an `omnisearch` mode: BM25-ranked, typo-tolerant, with PDF/OCR coverage (via the Text Extractor plugin).
|
|
46
|
+
if (omnisearch === 'offered') {
|
|
47
|
+
sections.push('`obsidian_search_notes` includes an `omnisearch` mode: BM25-ranked, typo-tolerant, with PDF/OCR coverage (via the Text Extractor plugin). Omnisearch keeps only its top 50 matches: narrow with `path:` / `ext:` filters or more plain terms, which apply before that cap. Quoted phrases and `-exclusion` filter only those 50, so a result using them is marked `truncated`.');
|
|
37
48
|
}
|
|
38
49
|
return sections.join('\n\n');
|
|
39
50
|
}
|
package/dist/instructions.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instructions.js","sourceRoot":"","sources":["../src/instructions.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;
|
|
1
|
+
{"version":3,"file":"instructions.js","sourceRoot":"","sources":["../src/instructions.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,MAAM,QAAQ,GACZ,gqBAAgqB,CAAC;AAEnqB,MAAM,cAAc,GAClB,iHAAiH,CAAC;AAEpH,MAAM,iBAAiB,GAAG,wEAAwE,CAAC;AAEnG;;;;;GAKG;AACH,SAAS,WAAW,CAAC,KAAoC,EAAE,QAAiB;IAC1E,IAAI,KAAK,EAAE,MAAM,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC;IACvC,MAAM,KAAK,GAAG,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACzF,OAAO,QAAQ,CAAC,CAAC,CAAC,GAAG,KAAK,uCAAuC,CAAC,CAAC,CAAC,KAAK,CAAC;AAC5E,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAKjC;IACC,MAAM,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC;IAC9D,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,MAAM,CAAC,cAAc,EAAE,CAAC;IACvD,MAAM,QAAQ,GAAG,MAAM,CAAC,cAAc,CAAC;IACvC,MAAM,QAAQ,GAAG,QAAQ,CAAC,CAAC,CAAC,GAAG,cAAc,IAAI,iBAAiB,EAAE,CAAC,CAAC,CAAC,cAAc,CAAC;IACtF,MAAM,QAAQ,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC5B,IAAI,QAAQ,EAAE,CAAC;QACb,QAAQ,CAAC,IAAI,CACX,mNAAmN,CACpN,CAAC;QACF,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,EAAE,CAAC;YACvC,QAAQ,CAAC,IAAI,CACX,4CAA4C,WAAW,CAAC,QAAQ,EAAE,QAAQ,CAAC,KAAK,QAAQ,EAAE,CAC3F,CAAC;QACJ,CAAC;IACH,CAAC;SAAM,IAAI,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC;QAClC,QAAQ,CAAC,IAAI,CACX,4CAA4C,WAAW,CAAC,QAAQ,EAAE,QAAQ,CAAC,eAAe,WAAW,CAAC,QAAQ,EAAE,QAAQ,CAAC,KAAK,QAAQ,EAAE,CACzI,CAAC;IACJ,CAAC;IACD,IAAI,cAAc,IAAI,CAAC,QAAQ,EAAE,CAAC;QAChC,QAAQ,CAAC,IAAI,CACX,gNAAgN,CACjN,CAAC;IACJ,CAAC;IACD,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;QAC7B,QAAQ,CAAC,IAAI,CACX,gXAAgX,CACjX,CAAC;IACJ,CAAC;IACD,OAAO,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAC/B,CAAC"}
|
|
@@ -17,8 +17,8 @@ export declare const allResourceDefinitions: (import("@cyanheads/mcp-ts-core").R
|
|
|
17
17
|
}, import("zod/v4/core").$strip>, readonly [{
|
|
18
18
|
readonly reason: "path_forbidden";
|
|
19
19
|
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.Forbidden;
|
|
20
|
-
readonly when: "The requested path is outside OBSIDIAN_READ_PATHS (and OBSIDIAN_WRITE_PATHS, since write paths imply read access).";
|
|
21
|
-
readonly recovery: "Use a path inside the configured read scope. The error data echoes the active scope.";
|
|
20
|
+
readonly when: "The requested path is outside OBSIDIAN_READ_PATHS (and OBSIDIAN_WRITE_PATHS, since write paths imply read access), or inside OBSIDIAN_DENY_PATHS.";
|
|
21
|
+
readonly recovery: "Use a path inside the configured read scope. The error data echoes the active scope; a `denied_path` denial carries none, since the operator withholds that path.";
|
|
22
22
|
}, {
|
|
23
23
|
readonly reason: "note_missing";
|
|
24
24
|
readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.NotFound;
|
|
@@ -4,8 +4,9 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Not a mirror of `obsidian_list_tags`: this is a snapshot of
|
|
6
6
|
* `ObsidianService.listTags`, returned whole and unsorted — the upstream
|
|
7
|
-
* `/tags/` payload in upstream order, or under OBSIDIAN_READ_PATHS
|
|
8
|
-
* readable notes in order of first
|
|
7
|
+
* `/tags/` payload in upstream order, or under OBSIDIAN_READ_PATHS or
|
|
8
|
+
* OBSIDIAN_DENY_PATHS the tags of readable notes in order of first
|
|
9
|
+
* appearance. The tool shapes the same
|
|
9
10
|
* payload for an LLM caller — count-descending, capped, filterable — and that
|
|
10
11
|
* shaping deliberately lives in the tool handler rather than the shared
|
|
11
12
|
* service call both make.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"obsidian-tags.resource.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/resources/definitions/obsidian-tags.resource.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"obsidian-tags.resource.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/resources/definitions/obsidian-tags.resource.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAY,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAGrD,eAAO,MAAM,YAAY;;;;;6BA+BvB,CAAC"}
|
|
@@ -4,8 +4,9 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Not a mirror of `obsidian_list_tags`: this is a snapshot of
|
|
6
6
|
* `ObsidianService.listTags`, returned whole and unsorted — the upstream
|
|
7
|
-
* `/tags/` payload in upstream order, or under OBSIDIAN_READ_PATHS
|
|
8
|
-
* readable notes in order of first
|
|
7
|
+
* `/tags/` payload in upstream order, or under OBSIDIAN_READ_PATHS or
|
|
8
|
+
* OBSIDIAN_DENY_PATHS the tags of readable notes in order of first
|
|
9
|
+
* appearance. The tool shapes the same
|
|
9
10
|
* payload for an LLM caller — count-descending, capped, filterable — and that
|
|
10
11
|
* shaping deliberately lives in the tool handler rather than the shared
|
|
11
12
|
* service call both make.
|
|
@@ -15,7 +16,7 @@ import { resource, z } from '@cyanheads/mcp-ts-core';
|
|
|
15
16
|
import { getObsidianService } from '../../../services/obsidian/obsidian-service.js';
|
|
16
17
|
export const obsidianTags = resource('obsidian://tags', {
|
|
17
18
|
name: 'obsidian-tags',
|
|
18
|
-
description: 'All tags found in the Obsidian vault, with usage counts, unsorted and uncapped — a full snapshot. When OBSIDIAN_READ_PATHS is set, only tags carried by readable notes. Includes hierarchical parents (e.g. `work` for `work/tasks`). Use the `obsidian_list_tags` tool for a count-ranked, capped, filterable view.',
|
|
19
|
+
description: 'All tags found in the Obsidian vault, with usage counts, unsorted and uncapped — a full snapshot. When OBSIDIAN_READ_PATHS or OBSIDIAN_DENY_PATHS is set, only tags carried by readable notes. Includes hierarchical parents (e.g. `work` for `work/tasks`). Use the `obsidian_list_tags` tool for a count-ranked, capped, filterable view.',
|
|
19
20
|
mimeType: 'application/json',
|
|
20
21
|
params: z.object({}),
|
|
21
22
|
output: z.object({
|
|
@@ -25,10 +26,10 @@ export const obsidianTags = resource('obsidian://tags', {
|
|
|
25
26
|
name: z.string().describe('Tag name without the leading `#`.'),
|
|
26
27
|
count: z
|
|
27
28
|
.number()
|
|
28
|
-
.describe('Times the tag, or a tag nested under it, occurs across the vault. When OBSIDIAN_READ_PATHS is set: the number of readable notes carrying the tag or a tag nested under it.'),
|
|
29
|
+
.describe('Times the tag, or a tag nested under it, occurs across the vault. When OBSIDIAN_READ_PATHS or OBSIDIAN_DENY_PATHS is set: the number of readable notes carrying the tag or a tag nested under it.'),
|
|
29
30
|
})
|
|
30
31
|
.describe('A tag with its usage count.'))
|
|
31
|
-
.describe('Every tag in the vault, in the order the Local REST API reports them. When OBSIDIAN_READ_PATHS is set: every tag carried by a readable note, in order of first appearance.'),
|
|
32
|
+
.describe('Every tag in the vault, in the order the Local REST API reports them. When OBSIDIAN_READ_PATHS or OBSIDIAN_DENY_PATHS is set: every tag carried by a readable note, in order of first appearance.'),
|
|
32
33
|
}),
|
|
33
34
|
auth: ['resource:obsidian-tags:read'],
|
|
34
35
|
async handler(_params, ctx) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"obsidian-tags.resource.js","sourceRoot":"","sources":["../../../../src/mcp-server/resources/definitions/obsidian-tags.resource.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"obsidian-tags.resource.js","sourceRoot":"","sources":["../../../../src/mcp-server/resources/definitions/obsidian-tags.resource.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAC;AAE7E,MAAM,CAAC,MAAM,YAAY,GAAG,QAAQ,CAAC,iBAAiB,EAAE;IACtD,IAAI,EAAE,eAAe;IACrB,WAAW,EACT,6UAA6U;IAC/U,QAAQ,EAAE,kBAAkB;IAC5B,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;IACpB,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC;QACf,IAAI,EAAE,CAAC;aACJ,KAAK,CACJ,CAAC;aACE,MAAM,CAAC;YACN,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,mCAAmC,CAAC;YAC9D,KAAK,EAAE,CAAC;iBACL,MAAM,EAAE;iBACR,QAAQ,CACP,mMAAmM,CACpM;SACJ,CAAC;aACD,QAAQ,CAAC,6BAA6B,CAAC,CAC3C;aACA,QAAQ,CACP,mMAAmM,CACpM;KACJ,CAAC;IACF,IAAI,EAAE,CAAC,6BAA6B,CAAC;IAErC,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG;QACxB,MAAM,GAAG,GAAG,kBAAkB,EAAE,CAAC;QACjC,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QACrC,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC;IACvE,CAAC;CACF,CAAC,CAAC"}
|
|
@@ -21,8 +21,8 @@ export declare const obsidianVaultNote: import("@cyanheads/mcp-ts-core").Resourc
|
|
|
21
21
|
}, z.core.$strip>, readonly [{
|
|
22
22
|
readonly reason: "path_forbidden";
|
|
23
23
|
readonly code: JsonRpcErrorCode.Forbidden;
|
|
24
|
-
readonly when: "The requested path is outside OBSIDIAN_READ_PATHS (and OBSIDIAN_WRITE_PATHS, since write paths imply read access).";
|
|
25
|
-
readonly recovery: "Use a path inside the configured read scope. The error data echoes the active scope.";
|
|
24
|
+
readonly when: "The requested path is outside OBSIDIAN_READ_PATHS (and OBSIDIAN_WRITE_PATHS, since write paths imply read access), or inside OBSIDIAN_DENY_PATHS.";
|
|
25
|
+
readonly recovery: "Use a path inside the configured read scope. The error data echoes the active scope; a `denied_path` denial carries none, since the operator withholds that path.";
|
|
26
26
|
}, {
|
|
27
27
|
readonly reason: "note_missing";
|
|
28
28
|
readonly code: JsonRpcErrorCode.NotFound;
|
|
@@ -34,8 +34,8 @@ export const obsidianVaultNote = resource('obsidian://vault/{+path}', {
|
|
|
34
34
|
{
|
|
35
35
|
reason: 'path_forbidden',
|
|
36
36
|
code: JsonRpcErrorCode.Forbidden,
|
|
37
|
-
when: 'The requested path is outside OBSIDIAN_READ_PATHS (and OBSIDIAN_WRITE_PATHS, since write paths imply read access).',
|
|
38
|
-
recovery: 'Use a path inside the configured read scope. The error data echoes the active scope.',
|
|
37
|
+
when: 'The requested path is outside OBSIDIAN_READ_PATHS (and OBSIDIAN_WRITE_PATHS, since write paths imply read access), or inside OBSIDIAN_DENY_PATHS.',
|
|
38
|
+
recovery: 'Use a path inside the configured read scope. The error data echoes the active scope; a `denied_path` denial carries none, since the operator withholds that path.',
|
|
39
39
|
},
|
|
40
40
|
{
|
|
41
41
|
reason: 'note_missing',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"obsidian-vault-note.resource.js","sourceRoot":"","sources":["../../../../src/mcp-server/resources/definitions/obsidian-vault-note.resource.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAC;AAE7E,MAAM,CAAC,MAAM,iBAAiB,GAAG,QAAQ,CAAC,0BAA0B,EAAE;IACpE,IAAI,EAAE,qBAAqB;IAC3B,WAAW,EACT,yJAAyJ;IAC3J,QAAQ,EAAE,kBAAkB;IAC5B,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC;QACf,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,uDAAuD,CAAC;KAC1F,CAAC;IACF,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC;QACf,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,kCAAkC,CAAC;QAC7D,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,oBAAoB,CAAC;QAClD,WAAW,EAAE,CAAC;aACX,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC;aAC/B,QAAQ,CACP,4FAA4F,CAC7F;QACH,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,CAAC,+CAA+C,CAAC;QACnF,IAAI,EAAE,CAAC;aACJ,MAAM,CAAC;YACN,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,+BAA+B,CAAC;YAC3D,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,gCAAgC,CAAC;YAC5D,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,qBAAqB,CAAC;SACjD,CAAC;aACD,QAAQ,CAAC,gBAAgB,CAAC;KAC9B,CAAC;IACF,IAAI,EAAE,CAAC,mCAAmC,CAAC;IAC3C,MAAM,EAAE;QACN;YACE,MAAM,EAAE,gBAAgB;YACxB,IAAI,EAAE,gBAAgB,CAAC,SAAS;YAChC,IAAI,EAAE,
|
|
1
|
+
{"version":3,"file":"obsidian-vault-note.resource.js","sourceRoot":"","sources":["../../../../src/mcp-server/resources/definitions/obsidian-vault-note.resource.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAC;AAE7E,MAAM,CAAC,MAAM,iBAAiB,GAAG,QAAQ,CAAC,0BAA0B,EAAE;IACpE,IAAI,EAAE,qBAAqB;IAC3B,WAAW,EACT,yJAAyJ;IAC3J,QAAQ,EAAE,kBAAkB;IAC5B,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC;QACf,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,uDAAuD,CAAC;KAC1F,CAAC;IACF,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC;QACf,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,kCAAkC,CAAC;QAC7D,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,oBAAoB,CAAC;QAClD,WAAW,EAAE,CAAC;aACX,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC;aAC/B,QAAQ,CACP,4FAA4F,CAC7F;QACH,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,CAAC,+CAA+C,CAAC;QACnF,IAAI,EAAE,CAAC;aACJ,MAAM,CAAC;YACN,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,+BAA+B,CAAC;YAC3D,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,gCAAgC,CAAC;YAC5D,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,qBAAqB,CAAC;SACjD,CAAC;aACD,QAAQ,CAAC,gBAAgB,CAAC;KAC9B,CAAC;IACF,IAAI,EAAE,CAAC,mCAAmC,CAAC;IAC3C,MAAM,EAAE;QACN;YACE,MAAM,EAAE,gBAAgB;YACxB,IAAI,EAAE,gBAAgB,CAAC,SAAS;YAChC,IAAI,EAAE,mJAAmJ;YACzJ,QAAQ,EACN,mKAAmK;SACtK;QACD;YACE,MAAM,EAAE,cAAc;YACtB,IAAI,EAAE,gBAAgB,CAAC,QAAQ;YAC/B,IAAI,EAAE,sDAAsD;YAC5D,QAAQ,EACN,2FAA2F;SAC9F;QACD;YACE,MAAM,EAAE,mBAAmB;YAC3B,IAAI,EAAE,gBAAgB,CAAC,eAAe;YACtC,IAAI,EAAE,4DAA4D;YAClE,QAAQ,EACN,kHAAkH;SACrH;KACF;IAED,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG;QACvB,MAAM,GAAG,GAAG,kBAAkB,EAAE,CAAC;QACjC,MAAM,IAAI,GAAG,kBAAkB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC7C,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,WAAW,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QAChE,OAAO,IAAI,CAAC;IACd,CAAC;CACF,CAAC,CAAC;AAEH;;;;;;GAMG;AACH,SAAS,kBAAkB,CAAC,QAAgB;IAC1C,OAAO,QAAQ,CAAC,OAAO,CAAC,uBAAuB,EAAE,CAAC,GAAG,EAAE,EAAE;QACvD,IAAI,CAAC;YACH,OAAO,kBAAkB,CAAC,GAAG,CAAC,CAAC;QACjC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,GAAG,CAAC;QACb,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC"}
|