obsidian-mcp-server 2.0.7 → 3.0.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/CLAUDE.md +364 -0
- package/Dockerfile +99 -0
- package/LICENSE +4 -6
- package/README.md +246 -206
- package/changelog/3.0.x/3.0.0.md +102 -0
- package/changelog/template.md +51 -0
- package/dist/config/server-config.d.ts +19 -0
- package/dist/config/server-config.d.ts.map +1 -0
- package/dist/config/server-config.js +55 -0
- package/dist/config/server-config.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +23 -295
- package/dist/index.js.map +1 -0
- package/dist/mcp-server/prompts/definitions/index.d.ts +8 -0
- package/dist/mcp-server/prompts/definitions/index.d.ts.map +1 -0
- package/dist/mcp-server/prompts/definitions/index.js +8 -0
- package/dist/mcp-server/prompts/definitions/index.js.map +1 -0
- package/dist/mcp-server/resources/definitions/index.d.ts +36 -0
- package/dist/mcp-server/resources/definitions/index.d.ts.map +1 -0
- package/dist/mcp-server/resources/definitions/index.js +9 -0
- package/dist/mcp-server/resources/definitions/index.js.map +1 -0
- package/dist/mcp-server/resources/definitions/obsidian-status.resource.d.ts +23 -0
- package/dist/mcp-server/resources/definitions/obsidian-status.resource.d.ts.map +1 -0
- package/dist/mcp-server/resources/definitions/obsidian-status.resource.js +47 -0
- package/dist/mcp-server/resources/definitions/obsidian-status.resource.js.map +1 -0
- package/dist/mcp-server/resources/definitions/obsidian-tags.resource.d.ts +13 -0
- package/dist/mcp-server/resources/definitions/obsidian-tags.resource.d.ts.map +1 -0
- package/dist/mcp-server/resources/definitions/obsidian-tags.resource.js +30 -0
- package/dist/mcp-server/resources/definitions/obsidian-tags.resource.js.map +1 -0
- package/dist/mcp-server/resources/definitions/obsidian-vault-note.resource.d.ts +21 -0
- package/dist/mcp-server/resources/definitions/obsidian-vault-note.resource.d.ts.map +1 -0
- package/dist/mcp-server/resources/definitions/obsidian-vault-note.resource.js +38 -0
- package/dist/mcp-server/resources/definitions/obsidian-vault-note.resource.js.map +1 -0
- package/dist/mcp-server/tools/definitions/_shared/schemas.d.ts +45 -0
- package/dist/mcp-server/tools/definitions/_shared/schemas.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/_shared/schemas.js +66 -0
- package/dist/mcp-server/tools/definitions/_shared/schemas.js.map +1 -0
- package/dist/mcp-server/tools/definitions/_shared/suggest-paths.d.ts +51 -0
- package/dist/mcp-server/tools/definitions/_shared/suggest-paths.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/_shared/suggest-paths.js +120 -0
- package/dist/mcp-server/tools/definitions/_shared/suggest-paths.js.map +1 -0
- package/dist/mcp-server/tools/definitions/index.d.ts +531 -0
- package/dist/mcp-server/tools/definitions/index.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/index.js +38 -0
- package/dist/mcp-server/tools/definitions/index.js.map +1 -0
- package/dist/mcp-server/tools/definitions/obsidian-append-to-note.tool.d.ts +42 -0
- package/dist/mcp-server/tools/definitions/obsidian-append-to-note.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/obsidian-append-to-note.tool.js +58 -0
- package/dist/mcp-server/tools/definitions/obsidian-append-to-note.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/obsidian-delete-note.tool.d.ts +46 -0
- package/dist/mcp-server/tools/definitions/obsidian-delete-note.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/obsidian-delete-note.tool.js +66 -0
- package/dist/mcp-server/tools/definitions/obsidian-delete-note.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/obsidian-execute-command.tool.d.ts +19 -0
- package/dist/mcp-server/tools/definitions/obsidian-execute-command.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/obsidian-execute-command.tool.js +43 -0
- package/dist/mcp-server/tools/definitions/obsidian-execute-command.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/obsidian-get-note.tool.d.ts +92 -0
- package/dist/mcp-server/tools/definitions/obsidian-get-note.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/obsidian-get-note.tool.js +245 -0
- package/dist/mcp-server/tools/definitions/obsidian-get-note.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/obsidian-list-commands.tool.d.ts +13 -0
- package/dist/mcp-server/tools/definitions/obsidian-list-commands.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/obsidian-list-commands.tool.js +38 -0
- package/dist/mcp-server/tools/definitions/obsidian-list-commands.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/obsidian-list-notes.tool.d.ts +59 -0
- package/dist/mcp-server/tools/definitions/obsidian-list-notes.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/obsidian-list-notes.tool.js +273 -0
- package/dist/mcp-server/tools/definitions/obsidian-list-notes.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/obsidian-list-tags.tool.d.ts +13 -0
- package/dist/mcp-server/tools/definitions/obsidian-list-tags.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/obsidian-list-tags.tool.js +38 -0
- package/dist/mcp-server/tools/definitions/obsidian-list-tags.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/obsidian-manage-frontmatter.tool.d.ts +68 -0
- package/dist/mcp-server/tools/definitions/obsidian-manage-frontmatter.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/obsidian-manage-frontmatter.tool.js +178 -0
- package/dist/mcp-server/tools/definitions/obsidian-manage-frontmatter.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/obsidian-manage-tags.tool.d.ts +77 -0
- package/dist/mcp-server/tools/definitions/obsidian-manage-tags.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/obsidian-manage-tags.tool.js +172 -0
- package/dist/mcp-server/tools/definitions/obsidian-manage-tags.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/obsidian-open-in-ui.tool.d.ts +22 -0
- package/dist/mcp-server/tools/definitions/obsidian-open-in-ui.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/obsidian-open-in-ui.tool.js +88 -0
- package/dist/mcp-server/tools/definitions/obsidian-open-in-ui.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/obsidian-patch-note.tool.d.ts +81 -0
- package/dist/mcp-server/tools/definitions/obsidian-patch-note.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/obsidian-patch-note.tool.js +83 -0
- package/dist/mcp-server/tools/definitions/obsidian-patch-note.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/obsidian-replace-in-note.tool.d.ts +59 -0
- package/dist/mcp-server/tools/definitions/obsidian-replace-in-note.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/obsidian-replace-in-note.tool.js +167 -0
- package/dist/mcp-server/tools/definitions/obsidian-replace-in-note.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/obsidian-search-notes.tool.d.ts +76 -0
- package/dist/mcp-server/tools/definitions/obsidian-search-notes.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/obsidian-search-notes.tool.js +244 -0
- package/dist/mcp-server/tools/definitions/obsidian-search-notes.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/obsidian-write-note.tool.d.ts +41 -0
- package/dist/mcp-server/tools/definitions/obsidian-write-note.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/obsidian-write-note.tool.js +76 -0
- package/dist/mcp-server/tools/definitions/obsidian-write-note.tool.js.map +1 -0
- package/dist/services/obsidian/frontmatter-ops.d.ts +34 -0
- package/dist/services/obsidian/frontmatter-ops.d.ts.map +1 -0
- package/dist/services/obsidian/frontmatter-ops.js +230 -0
- package/dist/services/obsidian/frontmatter-ops.js.map +1 -0
- package/dist/services/obsidian/obsidian-service.d.ts +73 -0
- package/dist/services/obsidian/obsidian-service.d.ts.map +1 -0
- package/dist/services/obsidian/obsidian-service.js +399 -0
- package/dist/services/obsidian/obsidian-service.js.map +1 -0
- package/dist/services/obsidian/section-extractor.d.ts +13 -0
- package/dist/services/obsidian/section-extractor.d.ts.map +1 -0
- package/dist/services/obsidian/section-extractor.js +124 -0
- package/dist/services/obsidian/section-extractor.js.map +1 -0
- package/dist/services/obsidian/types.d.ts +91 -0
- package/dist/services/obsidian/types.d.ts.map +1 -0
- package/dist/services/obsidian/types.js +7 -0
- package/dist/services/obsidian/types.js.map +1 -0
- package/package.json +63 -69
- package/server.json +167 -0
- package/CHANGELOG.md +0 -124
- package/dist/config/index.d.ts +0 -41
- package/dist/config/index.js +0 -191
- package/dist/mcp-server/server.d.ts +0 -33
- package/dist/mcp-server/server.js +0 -211
- package/dist/mcp-server/tools/obsidianDeleteNoteTool/index.d.ts +0 -12
- package/dist/mcp-server/tools/obsidianDeleteNoteTool/index.js +0 -12
- package/dist/mcp-server/tools/obsidianDeleteNoteTool/logic.d.ts +0 -51
- package/dist/mcp-server/tools/obsidianDeleteNoteTool/logic.js +0 -168
- package/dist/mcp-server/tools/obsidianDeleteNoteTool/registration.d.ts +0 -19
- package/dist/mcp-server/tools/obsidianDeleteNoteTool/registration.js +0 -91
- package/dist/mcp-server/tools/obsidianGlobalSearchTool/index.d.ts +0 -12
- package/dist/mcp-server/tools/obsidianGlobalSearchTool/index.js +0 -12
- package/dist/mcp-server/tools/obsidianGlobalSearchTool/logic.d.ts +0 -77
- package/dist/mcp-server/tools/obsidianGlobalSearchTool/logic.js +0 -341
- package/dist/mcp-server/tools/obsidianGlobalSearchTool/registration.d.ts +0 -18
- package/dist/mcp-server/tools/obsidianGlobalSearchTool/registration.js +0 -69
- package/dist/mcp-server/tools/obsidianListNotesTool/index.d.ts +0 -12
- package/dist/mcp-server/tools/obsidianListNotesTool/index.js +0 -12
- package/dist/mcp-server/tools/obsidianListNotesTool/logic.d.ts +0 -68
- package/dist/mcp-server/tools/obsidianListNotesTool/logic.js +0 -215
- package/dist/mcp-server/tools/obsidianListNotesTool/registration.d.ts +0 -23
- package/dist/mcp-server/tools/obsidianListNotesTool/registration.js +0 -98
- package/dist/mcp-server/tools/obsidianManageFrontmatterTool/index.d.ts +0 -3
- package/dist/mcp-server/tools/obsidianManageFrontmatterTool/index.js +0 -2
- package/dist/mcp-server/tools/obsidianManageFrontmatterTool/logic.d.ts +0 -42
- package/dist/mcp-server/tools/obsidianManageFrontmatterTool/logic.js +0 -152
- package/dist/mcp-server/tools/obsidianManageFrontmatterTool/registration.d.ts +0 -3
- package/dist/mcp-server/tools/obsidianManageFrontmatterTool/registration.js +0 -52
- package/dist/mcp-server/tools/obsidianManageTagsTool/index.d.ts +0 -3
- package/dist/mcp-server/tools/obsidianManageTagsTool/index.js +0 -2
- package/dist/mcp-server/tools/obsidianManageTagsTool/logic.d.ts +0 -28
- package/dist/mcp-server/tools/obsidianManageTagsTool/logic.js +0 -161
- package/dist/mcp-server/tools/obsidianManageTagsTool/registration.d.ts +0 -3
- package/dist/mcp-server/tools/obsidianManageTagsTool/registration.js +0 -52
- package/dist/mcp-server/tools/obsidianReadNoteTool/index.d.ts +0 -12
- package/dist/mcp-server/tools/obsidianReadNoteTool/index.js +0 -12
- package/dist/mcp-server/tools/obsidianReadNoteTool/logic.d.ts +0 -87
- package/dist/mcp-server/tools/obsidianReadNoteTool/logic.js +0 -216
- package/dist/mcp-server/tools/obsidianReadNoteTool/registration.d.ts +0 -20
- package/dist/mcp-server/tools/obsidianReadNoteTool/registration.js +0 -101
- package/dist/mcp-server/tools/obsidianSearchReplaceTool/index.d.ts +0 -12
- package/dist/mcp-server/tools/obsidianSearchReplaceTool/index.js +0 -12
- package/dist/mcp-server/tools/obsidianSearchReplaceTool/logic.d.ts +0 -255
- package/dist/mcp-server/tools/obsidianSearchReplaceTool/logic.js +0 -583
- package/dist/mcp-server/tools/obsidianSearchReplaceTool/registration.d.ts +0 -22
- package/dist/mcp-server/tools/obsidianSearchReplaceTool/registration.js +0 -111
- package/dist/mcp-server/tools/obsidianUpdateNoteTool/index.d.ts +0 -12
- package/dist/mcp-server/tools/obsidianUpdateNoteTool/index.js +0 -12
- package/dist/mcp-server/tools/obsidianUpdateNoteTool/logic.d.ts +0 -183
- package/dist/mcp-server/tools/obsidianUpdateNoteTool/logic.js +0 -490
- package/dist/mcp-server/tools/obsidianUpdateNoteTool/registration.d.ts +0 -21
- package/dist/mcp-server/tools/obsidianUpdateNoteTool/registration.js +0 -108
- package/dist/mcp-server/transports/auth/core/authContext.d.ts +0 -33
- package/dist/mcp-server/transports/auth/core/authContext.js +0 -24
- package/dist/mcp-server/transports/auth/core/authTypes.d.ts +0 -17
- package/dist/mcp-server/transports/auth/core/authTypes.js +0 -5
- package/dist/mcp-server/transports/auth/core/authUtils.d.ts +0 -18
- package/dist/mcp-server/transports/auth/core/authUtils.js +0 -45
- package/dist/mcp-server/transports/auth/index.d.ts +0 -10
- package/dist/mcp-server/transports/auth/index.js +0 -9
- package/dist/mcp-server/transports/auth/strategies/jwt/jwtMiddleware.d.ts +0 -27
- package/dist/mcp-server/transports/auth/strategies/jwt/jwtMiddleware.js +0 -149
- package/dist/mcp-server/transports/auth/strategies/oauth/oauthMiddleware.d.ts +0 -20
- package/dist/mcp-server/transports/auth/strategies/oauth/oauthMiddleware.js +0 -124
- package/dist/mcp-server/transports/httpErrorHandler.d.ts +0 -26
- package/dist/mcp-server/transports/httpErrorHandler.js +0 -73
- package/dist/mcp-server/transports/httpTransport.d.ts +0 -21
- package/dist/mcp-server/transports/httpTransport.js +0 -208
- package/dist/mcp-server/transports/stdioTransport.d.ts +0 -42
- package/dist/mcp-server/transports/stdioTransport.js +0 -63
- package/dist/services/obsidianRestAPI/index.d.ts +0 -15
- package/dist/services/obsidianRestAPI/index.js +0 -17
- package/dist/services/obsidianRestAPI/methods/activeFileMethods.d.ts +0 -38
- package/dist/services/obsidianRestAPI/methods/activeFileMethods.js +0 -62
- package/dist/services/obsidianRestAPI/methods/commandMethods.d.ts +0 -22
- package/dist/services/obsidianRestAPI/methods/commandMethods.js +0 -31
- package/dist/services/obsidianRestAPI/methods/openMethods.d.ts +0 -16
- package/dist/services/obsidianRestAPI/methods/openMethods.js +0 -21
- package/dist/services/obsidianRestAPI/methods/patchMethods.d.ts +0 -37
- package/dist/services/obsidianRestAPI/methods/patchMethods.js +0 -94
- package/dist/services/obsidianRestAPI/methods/periodicNoteMethods.d.ts +0 -42
- package/dist/services/obsidianRestAPI/methods/periodicNoteMethods.js +0 -66
- package/dist/services/obsidianRestAPI/methods/searchMethods.d.ts +0 -25
- package/dist/services/obsidianRestAPI/methods/searchMethods.js +0 -36
- package/dist/services/obsidianRestAPI/methods/vaultMethods.d.ts +0 -58
- package/dist/services/obsidianRestAPI/methods/vaultMethods.js +0 -144
- package/dist/services/obsidianRestAPI/service.d.ts +0 -195
- package/dist/services/obsidianRestAPI/service.js +0 -379
- package/dist/services/obsidianRestAPI/types.d.ts +0 -127
- package/dist/services/obsidianRestAPI/types.js +0 -7
- package/dist/services/obsidianRestAPI/vaultCache/index.d.ts +0 -4
- package/dist/services/obsidianRestAPI/vaultCache/index.js +0 -4
- package/dist/services/obsidianRestAPI/vaultCache/service.d.ts +0 -88
- package/dist/services/obsidianRestAPI/vaultCache/service.js +0 -299
- package/dist/types-global/errors.d.ts +0 -73
- package/dist/types-global/errors.js +0 -71
- package/dist/utils/index.d.ts +0 -5
- package/dist/utils/index.js +0 -13
- package/dist/utils/internal/asyncUtils.d.ts +0 -54
- package/dist/utils/internal/asyncUtils.js +0 -101
- package/dist/utils/internal/errorHandler.d.ts +0 -176
- package/dist/utils/internal/errorHandler.js +0 -351
- package/dist/utils/internal/index.d.ts +0 -4
- package/dist/utils/internal/index.js +0 -4
- package/dist/utils/internal/logger.d.ts +0 -141
- package/dist/utils/internal/logger.js +0 -406
- package/dist/utils/internal/requestContext.d.ts +0 -83
- package/dist/utils/internal/requestContext.js +0 -72
- package/dist/utils/metrics/index.d.ts +0 -1
- package/dist/utils/metrics/index.js +0 -1
- package/dist/utils/metrics/tokenCounter.d.ts +0 -27
- package/dist/utils/metrics/tokenCounter.js +0 -128
- package/dist/utils/obsidian/index.d.ts +0 -5
- package/dist/utils/obsidian/index.js +0 -5
- package/dist/utils/obsidian/obsidianApiUtils.d.ts +0 -14
- package/dist/utils/obsidian/obsidianApiUtils.js +0 -29
- package/dist/utils/obsidian/obsidianStatUtils.d.ts +0 -68
- package/dist/utils/obsidian/obsidianStatUtils.js +0 -143
- package/dist/utils/parsing/dateParser.d.ts +0 -56
- package/dist/utils/parsing/dateParser.js +0 -104
- package/dist/utils/parsing/index.d.ts +0 -2
- package/dist/utils/parsing/index.js +0 -3
- package/dist/utils/parsing/jsonParser.d.ts +0 -80
- package/dist/utils/parsing/jsonParser.js +0 -133
- package/dist/utils/security/idGenerator.d.ts +0 -140
- package/dist/utils/security/idGenerator.js +0 -194
- package/dist/utils/security/index.d.ts +0 -3
- package/dist/utils/security/index.js +0 -3
- package/dist/utils/security/rateLimiter.d.ts +0 -156
- package/dist/utils/security/rateLimiter.js +0 -235
- package/dist/utils/security/sanitization.d.ts +0 -244
- package/dist/utils/security/sanitization.js +0 -599
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview obsidian_manage_frontmatter — atomic get/set/delete on a single
|
|
3
|
+
* frontmatter key. `set` PATCHes the field; `delete` reads-modifies-writes the
|
|
4
|
+
* file because PATCH has no `delete` operation.
|
|
5
|
+
* @module mcp-server/tools/definitions/obsidian-manage-frontmatter.tool
|
|
6
|
+
*/
|
|
7
|
+
import { tool, z } from '@cyanheads/mcp-ts-core';
|
|
8
|
+
import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
|
|
9
|
+
import { deleteFrontmatterKey } from '../../../services/obsidian/frontmatter-ops.js';
|
|
10
|
+
import { getObsidianService } from '../../../services/obsidian/obsidian-service.js';
|
|
11
|
+
import { TargetSchema } from './_shared/schemas.js';
|
|
12
|
+
export const obsidianManageFrontmatter = tool('obsidian_manage_frontmatter', {
|
|
13
|
+
description: 'Atomic `get` / `set` / `delete` on a single frontmatter key. `set` requires `value` (any JSON-typed value: string, number, boolean, array, or object).',
|
|
14
|
+
annotations: { destructiveHint: true },
|
|
15
|
+
input: z.object({
|
|
16
|
+
operation: z
|
|
17
|
+
.enum(['get', 'set', 'delete'])
|
|
18
|
+
.describe('Which mutation/read to perform on the key.'),
|
|
19
|
+
target: TargetSchema.describe('Where the note lives.'),
|
|
20
|
+
key: z.string().min(1).describe('Frontmatter field name.'),
|
|
21
|
+
value: z
|
|
22
|
+
.unknown()
|
|
23
|
+
.optional()
|
|
24
|
+
.describe('Required when `operation` is `"set"`. JSON-typed value to write — strings, numbers, booleans, arrays, and objects all accepted.'),
|
|
25
|
+
}),
|
|
26
|
+
output: z.object({
|
|
27
|
+
result: z
|
|
28
|
+
.discriminatedUnion('operation', [
|
|
29
|
+
z
|
|
30
|
+
.object({
|
|
31
|
+
operation: z.literal('get').describe('Echoed operation.'),
|
|
32
|
+
path: z.string().describe('Resolved vault-relative path.'),
|
|
33
|
+
key: z.string().describe('Echoed frontmatter key.'),
|
|
34
|
+
exists: z.boolean().describe('True when the key was present in the frontmatter.'),
|
|
35
|
+
value: z.unknown().describe('Current value, or `null` when the key is absent.'),
|
|
36
|
+
})
|
|
37
|
+
.describe('Result for `get`.'),
|
|
38
|
+
z
|
|
39
|
+
.object({
|
|
40
|
+
operation: z.literal('set').describe('Echoed operation.'),
|
|
41
|
+
path: z.string().describe('Resolved vault-relative path.'),
|
|
42
|
+
key: z.string().describe('Echoed frontmatter key.'),
|
|
43
|
+
frontmatter: z
|
|
44
|
+
.record(z.string(), z.unknown())
|
|
45
|
+
.describe('Full frontmatter after the change.'),
|
|
46
|
+
})
|
|
47
|
+
.describe('Result for `set`.'),
|
|
48
|
+
z
|
|
49
|
+
.object({
|
|
50
|
+
operation: z.literal('delete').describe('Echoed operation.'),
|
|
51
|
+
path: z.string().describe('Resolved vault-relative path.'),
|
|
52
|
+
key: z.string().describe('Echoed frontmatter key.'),
|
|
53
|
+
frontmatter: z
|
|
54
|
+
.record(z.string(), z.unknown())
|
|
55
|
+
.describe('Full frontmatter after the change.'),
|
|
56
|
+
})
|
|
57
|
+
.describe('Result for `delete`.'),
|
|
58
|
+
])
|
|
59
|
+
.describe('Operation-discriminated result payload.'),
|
|
60
|
+
}),
|
|
61
|
+
auth: ['tool:obsidian_manage_frontmatter:write'],
|
|
62
|
+
errors: [
|
|
63
|
+
{
|
|
64
|
+
reason: 'value_required',
|
|
65
|
+
code: JsonRpcErrorCode.ValidationError,
|
|
66
|
+
when: '`operation` is "set" but no `value` was supplied.',
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
reason: 'note_missing',
|
|
70
|
+
code: JsonRpcErrorCode.NotFound,
|
|
71
|
+
when: 'The vault path does not resolve to an existing note.',
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
reason: 'no_active_file',
|
|
75
|
+
code: JsonRpcErrorCode.NotFound,
|
|
76
|
+
when: 'Target was `active` but no file is currently open in Obsidian.',
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
reason: 'periodic_not_found',
|
|
80
|
+
code: JsonRpcErrorCode.NotFound,
|
|
81
|
+
when: 'Target was `periodic` but no matching periodic note exists.',
|
|
82
|
+
},
|
|
83
|
+
],
|
|
84
|
+
async handler(input, ctx) {
|
|
85
|
+
const svc = getObsidianService();
|
|
86
|
+
const { target } = input;
|
|
87
|
+
if (input.operation === 'get') {
|
|
88
|
+
const note = await svc.getNoteJson(ctx, target);
|
|
89
|
+
const exists = input.key in note.frontmatter;
|
|
90
|
+
return {
|
|
91
|
+
result: {
|
|
92
|
+
operation: 'get',
|
|
93
|
+
path: note.path,
|
|
94
|
+
key: input.key,
|
|
95
|
+
exists,
|
|
96
|
+
value: exists ? note.frontmatter[input.key] : null,
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
if (input.operation === 'set') {
|
|
101
|
+
if (input.value === undefined) {
|
|
102
|
+
throw ctx.fail('value_required', '`value` is required when operation is "set".', {
|
|
103
|
+
operation: input.operation,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
await svc.patchNote(ctx, target, JSON.stringify(input.value), {
|
|
107
|
+
operation: 'replace',
|
|
108
|
+
targetType: 'frontmatter',
|
|
109
|
+
target: input.key,
|
|
110
|
+
contentType: 'json',
|
|
111
|
+
createTargetIfMissing: true,
|
|
112
|
+
});
|
|
113
|
+
const note = await svc.getNoteJson(ctx, target);
|
|
114
|
+
return {
|
|
115
|
+
result: {
|
|
116
|
+
operation: 'set',
|
|
117
|
+
path: note.path,
|
|
118
|
+
key: input.key,
|
|
119
|
+
frontmatter: note.frontmatter,
|
|
120
|
+
},
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
const note = await svc.getNoteJson(ctx, target);
|
|
124
|
+
const newContent = deleteFrontmatterKey(note.content, input.key);
|
|
125
|
+
if (newContent !== note.content) {
|
|
126
|
+
await svc.writeNote(ctx, target, newContent, 'markdown');
|
|
127
|
+
}
|
|
128
|
+
const projected = { ...note.frontmatter };
|
|
129
|
+
delete projected[input.key];
|
|
130
|
+
return {
|
|
131
|
+
result: {
|
|
132
|
+
operation: 'delete',
|
|
133
|
+
path: note.path,
|
|
134
|
+
key: input.key,
|
|
135
|
+
frontmatter: projected,
|
|
136
|
+
},
|
|
137
|
+
};
|
|
138
|
+
},
|
|
139
|
+
format: ({ result }) => {
|
|
140
|
+
if (result.operation === 'get') {
|
|
141
|
+
const valueStr = result.exists ? formatValue(result.value) : '_(absent)_';
|
|
142
|
+
return [
|
|
143
|
+
{
|
|
144
|
+
type: 'text',
|
|
145
|
+
text: [
|
|
146
|
+
`**Frontmatter ${result.operation} \`${result.key}\` in ${result.path}**`,
|
|
147
|
+
`*Exists:* ${result.exists}`,
|
|
148
|
+
'*Value:*',
|
|
149
|
+
valueStr,
|
|
150
|
+
].join('\n'),
|
|
151
|
+
},
|
|
152
|
+
];
|
|
153
|
+
}
|
|
154
|
+
const fmKeys = Object.keys(result.frontmatter);
|
|
155
|
+
const lines = [
|
|
156
|
+
`**Frontmatter ${result.operation} \`${result.key}\` in ${result.path}**`,
|
|
157
|
+
'',
|
|
158
|
+
`**Frontmatter (${fmKeys.length} keys after change)**`,
|
|
159
|
+
];
|
|
160
|
+
if (fmKeys.length === 0) {
|
|
161
|
+
lines.push('_(empty)_');
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
for (const k of fmKeys) {
|
|
165
|
+
lines.push(`- \`${k}\`: ${formatValue(result.frontmatter[k])}`);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return [{ type: 'text', text: lines.join('\n') }];
|
|
169
|
+
},
|
|
170
|
+
});
|
|
171
|
+
function formatValue(v) {
|
|
172
|
+
if (v === null || v === undefined)
|
|
173
|
+
return '`null`';
|
|
174
|
+
if (typeof v === 'string')
|
|
175
|
+
return v;
|
|
176
|
+
return `\`${JSON.stringify(v)}\``;
|
|
177
|
+
}
|
|
178
|
+
//# sourceMappingURL=obsidian-manage-frontmatter.tool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"obsidian-manage-frontmatter.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/obsidian-manage-frontmatter.tool.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview obsidian_manage_tags — add/remove/list tags across both
|
|
3
|
+
* frontmatter (`tags:` array) and inline (`#tag`) syntax. The service layer
|
|
4
|
+
* reconciles both representations; inline matches inside fenced code blocks
|
|
5
|
+
* are left alone.
|
|
6
|
+
* @module mcp-server/tools/definitions/obsidian-manage-tags.tool
|
|
7
|
+
*/
|
|
8
|
+
import { z } from '@cyanheads/mcp-ts-core';
|
|
9
|
+
import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
|
|
10
|
+
export declare const obsidianManageTags: import("@cyanheads/mcp-ts-core").ToolDefinition<z.ZodObject<{
|
|
11
|
+
target: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
12
|
+
type: z.ZodLiteral<"path">;
|
|
13
|
+
path: z.ZodString;
|
|
14
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
15
|
+
type: z.ZodLiteral<"active">;
|
|
16
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
17
|
+
type: z.ZodLiteral<"periodic">;
|
|
18
|
+
period: z.ZodEnum<{
|
|
19
|
+
daily: "daily";
|
|
20
|
+
weekly: "weekly";
|
|
21
|
+
monthly: "monthly";
|
|
22
|
+
quarterly: "quarterly";
|
|
23
|
+
yearly: "yearly";
|
|
24
|
+
}>;
|
|
25
|
+
date: z.ZodOptional<z.ZodString>;
|
|
26
|
+
}, z.core.$strip>], "type">;
|
|
27
|
+
operation: z.ZodEnum<{
|
|
28
|
+
list: "list";
|
|
29
|
+
add: "add";
|
|
30
|
+
remove: "remove";
|
|
31
|
+
}>;
|
|
32
|
+
tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
33
|
+
location: z.ZodDefault<z.ZodEnum<{
|
|
34
|
+
frontmatter: "frontmatter";
|
|
35
|
+
inline: "inline";
|
|
36
|
+
both: "both";
|
|
37
|
+
}>>;
|
|
38
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
39
|
+
result: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
40
|
+
operation: z.ZodLiteral<"list">;
|
|
41
|
+
path: z.ZodString;
|
|
42
|
+
tags: z.ZodObject<{
|
|
43
|
+
frontmatter: z.ZodArray<z.ZodString>;
|
|
44
|
+
inline: z.ZodArray<z.ZodString>;
|
|
45
|
+
all: z.ZodArray<z.ZodString>;
|
|
46
|
+
}, z.core.$strip>;
|
|
47
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
48
|
+
operation: z.ZodLiteral<"add">;
|
|
49
|
+
path: z.ZodString;
|
|
50
|
+
applied: z.ZodArray<z.ZodString>;
|
|
51
|
+
skipped: z.ZodArray<z.ZodString>;
|
|
52
|
+
tags: z.ZodArray<z.ZodString>;
|
|
53
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
54
|
+
operation: z.ZodLiteral<"remove">;
|
|
55
|
+
path: z.ZodString;
|
|
56
|
+
applied: z.ZodArray<z.ZodString>;
|
|
57
|
+
skipped: z.ZodArray<z.ZodString>;
|
|
58
|
+
tags: z.ZodArray<z.ZodString>;
|
|
59
|
+
}, z.core.$strip>], "operation">;
|
|
60
|
+
}, z.core.$strip>, readonly [{
|
|
61
|
+
readonly reason: "tags_required";
|
|
62
|
+
readonly code: JsonRpcErrorCode.ValidationError;
|
|
63
|
+
readonly when: "`operation` is \"add\" or \"remove\" but `tags` was empty or omitted.";
|
|
64
|
+
}, {
|
|
65
|
+
readonly reason: "note_missing";
|
|
66
|
+
readonly code: JsonRpcErrorCode.NotFound;
|
|
67
|
+
readonly when: "The vault path does not resolve to an existing note.";
|
|
68
|
+
}, {
|
|
69
|
+
readonly reason: "no_active_file";
|
|
70
|
+
readonly code: JsonRpcErrorCode.NotFound;
|
|
71
|
+
readonly when: "Target was `active` but no file is currently open in Obsidian.";
|
|
72
|
+
}, {
|
|
73
|
+
readonly reason: "periodic_not_found";
|
|
74
|
+
readonly code: JsonRpcErrorCode.NotFound;
|
|
75
|
+
readonly when: "Target was `periodic` but no matching periodic note exists.";
|
|
76
|
+
}]>;
|
|
77
|
+
//# sourceMappingURL=obsidian-manage-tags.tool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"obsidian-manage-tags.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/obsidian-manage-tags.tool.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAUjE,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiK7B,CAAC"}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview obsidian_manage_tags — add/remove/list tags across both
|
|
3
|
+
* frontmatter (`tags:` array) and inline (`#tag`) syntax. The service layer
|
|
4
|
+
* reconciles both representations; inline matches inside fenced code blocks
|
|
5
|
+
* are left alone.
|
|
6
|
+
* @module mcp-server/tools/definitions/obsidian-manage-tags.tool
|
|
7
|
+
*/
|
|
8
|
+
import { tool, z } from '@cyanheads/mcp-ts-core';
|
|
9
|
+
import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
|
|
10
|
+
import { listTagsFromContent, reconcileTags } from '../../../services/obsidian/frontmatter-ops.js';
|
|
11
|
+
import { getObsidianService } from '../../../services/obsidian/obsidian-service.js';
|
|
12
|
+
import { TargetSchema } from './_shared/schemas.js';
|
|
13
|
+
const LocationSchema = z
|
|
14
|
+
.enum(['frontmatter', 'inline', 'both'])
|
|
15
|
+
.default('both')
|
|
16
|
+
.describe('Where to apply the change. Default `both` reconciles both representations.');
|
|
17
|
+
export const obsidianManageTags = tool('obsidian_manage_tags', {
|
|
18
|
+
description: "Add, remove, or list a note's tags. The server reconciles both representations — frontmatter `tags:` array and inline `#tag` syntax — so an `add` ensures the tag is present in the requested location(s), and a `remove` strips it. Inline `#tag` occurrences inside fenced code blocks are intentionally left alone. Inline-location additions append the new tag at the end of the file. `list` ignores the `tags` field.",
|
|
19
|
+
annotations: { destructiveHint: true },
|
|
20
|
+
input: z.object({
|
|
21
|
+
target: TargetSchema.describe('Where the note lives.'),
|
|
22
|
+
operation: z
|
|
23
|
+
.enum(['add', 'remove', 'list'])
|
|
24
|
+
.describe('`add` and `remove` mutate the note; `list` reads the current tag set.'),
|
|
25
|
+
tags: z
|
|
26
|
+
.array(z.string().min(1))
|
|
27
|
+
.optional()
|
|
28
|
+
.describe('Tags to add or remove. Omit the leading `#`. Required for add/remove.'),
|
|
29
|
+
location: LocationSchema,
|
|
30
|
+
}),
|
|
31
|
+
output: z.object({
|
|
32
|
+
result: z
|
|
33
|
+
.discriminatedUnion('operation', [
|
|
34
|
+
z
|
|
35
|
+
.object({
|
|
36
|
+
operation: z.literal('list').describe('Echoed operation.'),
|
|
37
|
+
path: z.string().describe('Resolved vault-relative path.'),
|
|
38
|
+
tags: z
|
|
39
|
+
.object({
|
|
40
|
+
frontmatter: z.array(z.string()).describe('Tags from frontmatter `tags:` array.'),
|
|
41
|
+
inline: z.array(z.string()).describe('Tags found in inline `#tag` syntax.'),
|
|
42
|
+
all: z
|
|
43
|
+
.array(z.string())
|
|
44
|
+
.describe('Deduplicated union of frontmatter and inline tags.'),
|
|
45
|
+
})
|
|
46
|
+
.describe('Tags split by location plus the deduplicated union.'),
|
|
47
|
+
})
|
|
48
|
+
.describe('Result for `list`.'),
|
|
49
|
+
z
|
|
50
|
+
.object({
|
|
51
|
+
operation: z.literal('add').describe('Echoed operation.'),
|
|
52
|
+
path: z.string().describe('Resolved vault-relative path.'),
|
|
53
|
+
applied: z.array(z.string()).describe('Tags actually changed by this call.'),
|
|
54
|
+
skipped: z
|
|
55
|
+
.array(z.string())
|
|
56
|
+
.describe('Tags already present at the targeted location(s).'),
|
|
57
|
+
tags: z.array(z.string()).describe('All tags on the note after the change.'),
|
|
58
|
+
})
|
|
59
|
+
.describe('Result for `add`.'),
|
|
60
|
+
z
|
|
61
|
+
.object({
|
|
62
|
+
operation: z.literal('remove').describe('Echoed operation.'),
|
|
63
|
+
path: z.string().describe('Resolved vault-relative path.'),
|
|
64
|
+
applied: z.array(z.string()).describe('Tags actually changed by this call.'),
|
|
65
|
+
skipped: z.array(z.string()).describe('Tags absent from the targeted location(s).'),
|
|
66
|
+
tags: z.array(z.string()).describe('All tags on the note after the change.'),
|
|
67
|
+
})
|
|
68
|
+
.describe('Result for `remove`.'),
|
|
69
|
+
])
|
|
70
|
+
.describe('Operation-discriminated result payload.'),
|
|
71
|
+
}),
|
|
72
|
+
auth: ['tool:obsidian_manage_tags:write'],
|
|
73
|
+
errors: [
|
|
74
|
+
{
|
|
75
|
+
reason: 'tags_required',
|
|
76
|
+
code: JsonRpcErrorCode.ValidationError,
|
|
77
|
+
when: '`operation` is "add" or "remove" but `tags` was empty or omitted.',
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
reason: 'note_missing',
|
|
81
|
+
code: JsonRpcErrorCode.NotFound,
|
|
82
|
+
when: 'The vault path does not resolve to an existing note.',
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
reason: 'no_active_file',
|
|
86
|
+
code: JsonRpcErrorCode.NotFound,
|
|
87
|
+
when: 'Target was `active` but no file is currently open in Obsidian.',
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
reason: 'periodic_not_found',
|
|
91
|
+
code: JsonRpcErrorCode.NotFound,
|
|
92
|
+
when: 'Target was `periodic` but no matching periodic note exists.',
|
|
93
|
+
},
|
|
94
|
+
],
|
|
95
|
+
async handler(input, ctx) {
|
|
96
|
+
const svc = getObsidianService();
|
|
97
|
+
const { target } = input;
|
|
98
|
+
const note = await svc.getNoteJson(ctx, target);
|
|
99
|
+
if (input.operation === 'list') {
|
|
100
|
+
const split = listTagsFromContent(note.content, note.frontmatter);
|
|
101
|
+
const all = Array.from(new Set([...split.frontmatter, ...split.inline]));
|
|
102
|
+
return {
|
|
103
|
+
result: {
|
|
104
|
+
operation: 'list',
|
|
105
|
+
path: note.path,
|
|
106
|
+
tags: { frontmatter: split.frontmatter, inline: split.inline, all },
|
|
107
|
+
},
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
if (!input.tags || input.tags.length === 0) {
|
|
111
|
+
throw ctx.fail('tags_required', '`tags` is required and must be non-empty for add/remove operations.', { operation: input.operation });
|
|
112
|
+
}
|
|
113
|
+
const reconciled = reconcileTags(note.content, input.tags, input.operation, input.location);
|
|
114
|
+
if (reconciled.applied.length === 0) {
|
|
115
|
+
return {
|
|
116
|
+
result: {
|
|
117
|
+
operation: input.operation,
|
|
118
|
+
path: note.path,
|
|
119
|
+
applied: reconciled.applied,
|
|
120
|
+
skipped: reconciled.skipped,
|
|
121
|
+
tags: note.tags,
|
|
122
|
+
},
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
await svc.writeNote(ctx, target, reconciled.content, 'markdown');
|
|
126
|
+
const after = await svc.getNoteJson(ctx, target);
|
|
127
|
+
if (input.operation === 'add') {
|
|
128
|
+
return {
|
|
129
|
+
result: {
|
|
130
|
+
operation: 'add',
|
|
131
|
+
path: after.path,
|
|
132
|
+
applied: reconciled.applied,
|
|
133
|
+
skipped: reconciled.skipped,
|
|
134
|
+
tags: after.tags,
|
|
135
|
+
},
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
return {
|
|
139
|
+
result: {
|
|
140
|
+
operation: 'remove',
|
|
141
|
+
path: after.path,
|
|
142
|
+
applied: reconciled.applied,
|
|
143
|
+
skipped: reconciled.skipped,
|
|
144
|
+
tags: after.tags,
|
|
145
|
+
},
|
|
146
|
+
};
|
|
147
|
+
},
|
|
148
|
+
format: ({ result }) => {
|
|
149
|
+
if (result.operation === 'list') {
|
|
150
|
+
const lines = [
|
|
151
|
+
`**Tags (operation: ${result.operation}) in ${result.path}**`,
|
|
152
|
+
`*Frontmatter (${result.tags.frontmatter.length}):* ${formatTags(result.tags.frontmatter)}`,
|
|
153
|
+
`*Inline (${result.tags.inline.length}):* ${formatTags(result.tags.inline)}`,
|
|
154
|
+
`*All (${result.tags.all.length}):* ${formatTags(result.tags.all)}`,
|
|
155
|
+
];
|
|
156
|
+
return [{ type: 'text', text: lines.join('\n') }];
|
|
157
|
+
}
|
|
158
|
+
const lines = [
|
|
159
|
+
`**${result.operation === 'add' ? 'Added tags to' : 'Removed tags from'} ${result.path}** (operation: ${result.operation})`,
|
|
160
|
+
`*Applied (${result.applied.length}):* ${formatTags(result.applied)}`,
|
|
161
|
+
`*Skipped (${result.skipped.length}):* ${formatTags(result.skipped)}`,
|
|
162
|
+
`*All tags now (${result.tags.length}):* ${formatTags(result.tags)}`,
|
|
163
|
+
];
|
|
164
|
+
return [{ type: 'text', text: lines.join('\n') }];
|
|
165
|
+
},
|
|
166
|
+
});
|
|
167
|
+
function formatTags(tags) {
|
|
168
|
+
if (tags.length === 0)
|
|
169
|
+
return '_(none)_';
|
|
170
|
+
return tags.map((t) => `\`#${t}\``).join(' ');
|
|
171
|
+
}
|
|
172
|
+
//# sourceMappingURL=obsidian-manage-tags.tool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"obsidian-manage-tags.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/obsidian-manage-tags.tool.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview obsidian_open_in_ui — open a file in the Obsidian app UI.
|
|
3
|
+
* Defaults to `failIfMissing: true` because Obsidian silently creates files on
|
|
4
|
+
* open otherwise; opt out for an "open or create" flow.
|
|
5
|
+
* @module mcp-server/tools/definitions/obsidian-open-in-ui.tool
|
|
6
|
+
*/
|
|
7
|
+
import { z } from '@cyanheads/mcp-ts-core';
|
|
8
|
+
import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
|
|
9
|
+
export declare const obsidianOpenInUi: import("@cyanheads/mcp-ts-core").ToolDefinition<z.ZodObject<{
|
|
10
|
+
path: z.ZodString;
|
|
11
|
+
failIfMissing: z.ZodDefault<z.ZodBoolean>;
|
|
12
|
+
newLeaf: z.ZodDefault<z.ZodBoolean>;
|
|
13
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
14
|
+
path: z.ZodString;
|
|
15
|
+
opened: z.ZodBoolean;
|
|
16
|
+
createdIfMissing: z.ZodBoolean;
|
|
17
|
+
}, z.core.$strip>, readonly [{
|
|
18
|
+
readonly reason: "note_missing";
|
|
19
|
+
readonly code: JsonRpcErrorCode.NotFound;
|
|
20
|
+
readonly when: "`failIfMissing: true` (default) and the path does not exist in the vault. Pass `failIfMissing: false` to allow Obsidian to create the file on open.";
|
|
21
|
+
}]>;
|
|
22
|
+
//# sourceMappingURL=obsidian-open-in-ui.tool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"obsidian-open-in-ui.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/obsidian-open-in-ui.tool.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAY,MAAM,+BAA+B,CAAC;AAK3E,eAAO,MAAM,gBAAgB;;;;;;;;;;;;GA2F3B,CAAC"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview obsidian_open_in_ui — open a file in the Obsidian app UI.
|
|
3
|
+
* Defaults to `failIfMissing: true` because Obsidian silently creates files on
|
|
4
|
+
* open otherwise; opt out for an "open or create" flow.
|
|
5
|
+
* @module mcp-server/tools/definitions/obsidian-open-in-ui.tool
|
|
6
|
+
*/
|
|
7
|
+
import { tool, z } from '@cyanheads/mcp-ts-core';
|
|
8
|
+
import { JsonRpcErrorCode, McpError } from '@cyanheads/mcp-ts-core/errors';
|
|
9
|
+
import { getObsidianService } from '../../../services/obsidian/obsidian-service.js';
|
|
10
|
+
import { withCaseFallback } from './_shared/suggest-paths.js';
|
|
11
|
+
export const obsidianOpenInUi = tool('obsidian_open_in_ui', {
|
|
12
|
+
description: 'Open a file in the Obsidian app UI. By default fails when the path does not exist; the `failIfMissing` flag controls the open-or-create behavior.',
|
|
13
|
+
annotations: { openWorldHint: true },
|
|
14
|
+
input: z.object({
|
|
15
|
+
path: z.string().min(1).describe('Vault-relative path of the file to open.'),
|
|
16
|
+
failIfMissing: z
|
|
17
|
+
.boolean()
|
|
18
|
+
.default(true)
|
|
19
|
+
.describe('When true (default), fails if the file does not exist. When false, allows Obsidian to create the file on open.'),
|
|
20
|
+
newLeaf: z
|
|
21
|
+
.boolean()
|
|
22
|
+
.default(false)
|
|
23
|
+
.describe('Open in a new leaf (split pane) instead of the active one.'),
|
|
24
|
+
}),
|
|
25
|
+
output: z.object({
|
|
26
|
+
path: z.string().describe('Resolved vault-relative path that was opened.'),
|
|
27
|
+
opened: z.boolean().describe('True when the open call succeeded.'),
|
|
28
|
+
createdIfMissing: z
|
|
29
|
+
.boolean()
|
|
30
|
+
.describe('True when the file did not exist before the call and was created by Obsidian.'),
|
|
31
|
+
}),
|
|
32
|
+
auth: ['tool:obsidian_open_in_ui:write'],
|
|
33
|
+
errors: [
|
|
34
|
+
{
|
|
35
|
+
reason: 'note_missing',
|
|
36
|
+
code: JsonRpcErrorCode.NotFound,
|
|
37
|
+
when: '`failIfMissing: true` (default) and the path does not exist in the vault. Pass `failIfMissing: false` to allow Obsidian to create the file on open.',
|
|
38
|
+
},
|
|
39
|
+
],
|
|
40
|
+
async handler(input, ctx) {
|
|
41
|
+
const svc = getObsidianService();
|
|
42
|
+
const target = { type: 'path', path: input.path };
|
|
43
|
+
if (!input.failIfMissing) {
|
|
44
|
+
// Caller opted into "open or create" — skip the existence probe and let
|
|
45
|
+
// Obsidian create the file on open.
|
|
46
|
+
await svc.openInUi(ctx, input.path, { newLeaf: input.newLeaf });
|
|
47
|
+
return { path: input.path, opened: true, createdIfMissing: true };
|
|
48
|
+
}
|
|
49
|
+
let resolvedPath = input.path;
|
|
50
|
+
try {
|
|
51
|
+
const { resolvedPath: rp } = await withCaseFallback(ctx, svc, target, (t) => svc.getNoteJson(ctx, t));
|
|
52
|
+
resolvedPath = rp ?? input.path;
|
|
53
|
+
}
|
|
54
|
+
catch (err) {
|
|
55
|
+
// Match on `data.reason` rather than the JSON-RPC code so the handler text
|
|
56
|
+
// doesn't trip `error-contract-prefer-fail` on a comparison literal. The
|
|
57
|
+
// service tags path 404s with `reason: 'note_missing'` in its error data.
|
|
58
|
+
const reason = err instanceof McpError ? err.data?.reason : undefined;
|
|
59
|
+
if (reason !== 'note_missing')
|
|
60
|
+
throw err;
|
|
61
|
+
const suggestions = (err instanceof McpError && err.data?.suggestions) || [];
|
|
62
|
+
const hint = suggestions.length > 0
|
|
63
|
+
? ` Did you mean: ${suggestions.map((s) => `"${s}"`).join(', ')}?`
|
|
64
|
+
: '';
|
|
65
|
+
throw ctx.fail('note_missing', `Cannot open '${input.path}' — file does not exist.${hint} Pass failIfMissing: false to create on open.`, {
|
|
66
|
+
path: input.path,
|
|
67
|
+
...(suggestions.length > 0 ? { suggestions } : {}),
|
|
68
|
+
}, { cause: err });
|
|
69
|
+
}
|
|
70
|
+
await svc.openInUi(ctx, resolvedPath, { newLeaf: input.newLeaf });
|
|
71
|
+
return {
|
|
72
|
+
path: resolvedPath,
|
|
73
|
+
opened: true,
|
|
74
|
+
createdIfMissing: false,
|
|
75
|
+
};
|
|
76
|
+
},
|
|
77
|
+
format: (result) => [
|
|
78
|
+
{
|
|
79
|
+
type: 'text',
|
|
80
|
+
text: [
|
|
81
|
+
`**Opened ${result.path}**`,
|
|
82
|
+
`*Opened:* ${result.opened}`,
|
|
83
|
+
`*Created if missing:* ${result.createdIfMissing}`,
|
|
84
|
+
].join('\n'),
|
|
85
|
+
},
|
|
86
|
+
],
|
|
87
|
+
});
|
|
88
|
+
//# sourceMappingURL=obsidian-open-in-ui.tool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"obsidian-open-in-ui.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/obsidian-open-in-ui.tool.ts"],"names":[],"mappings":"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"}
|