UNPKG

obsidian-mcp-server

Version:

MCP server for Obsidian vaults — read, write, search, and surgically edit notes, tags, and frontmatter via the Local REST API plugin. STDIO or Streamable HTTP.

68 lines 3.12 kB
/** * @fileoverview Reusable Zod shapes for Obsidian tool definitions. * Target/Section/PatchOptions/ContentType are referenced across multiple tools; * keeping them here prevents drift in the discriminator and field descriptions. * @module mcp-server/tools/definitions/_shared/schemas */ import { z } from '@cyanheads/mcp-ts-core'; /** Where a note lives — vault path, the active file, or a periodic note. */ export const TargetSchema = z.discriminatedUnion('type', [ z .object({ type: z.literal('path').describe('Address by vault-relative path.'), path: z .string() .min(1) .describe('Vault-relative path including extension, e.g. "Projects/foo.md".'), }) .describe('Address a note by its vault-relative path.'), z .object({ type: z.literal('active').describe('Address the file currently open in Obsidian.'), }) .describe('Address whichever file is currently active in the Obsidian UI.'), z .object({ type: z.literal('periodic').describe('Address a daily/weekly/monthly/etc. periodic note.'), period: z .enum(['daily', 'weekly', 'monthly', 'quarterly', 'yearly']) .describe('Periodic note granularity.'), date: z .string() .regex(/^\d{4}-\d{2}-\d{2}$/) .optional() .describe('ISO date YYYY-MM-DD. Omit for the current period.'), }) .describe('Address a periodic note (current or dated).'), ]); /** Sub-document target inside a note. */ export const SectionSchema = z.object({ type: z .enum(['heading', 'block', 'frontmatter']) .describe('Heading by name, block by reference, or frontmatter field by key.'), target: z .string() .min(1) .describe('Heading name (use "::" for nested headings), block reference without leading caret (e.g. "2d9b4a", not "^2d9b4a"), or frontmatter field name.'), }); export const PatchOptionsSchema = z .object({ createTargetIfMissing: z .boolean() .default(false) .describe('Create the target heading/block/frontmatter field if it does not exist.'), applyIfContentPreexists: z .boolean() .default(false) .describe('When false (default), the patch is rejected if the supplied content already appears in the target — idempotent against agent retries. Set to true to force-apply even when it would duplicate. Replace operations are unaffected (the plugin exempts them).'), trimTargetWhitespace: z .boolean() .default(false) .describe('Trim whitespace from the target section before applying the operation.'), }) .optional(); export const ContentTypeSchema = z .enum(['markdown', 'json']) .default('markdown') .describe('Content body format. Use "json" for typed frontmatter values or block-targeted table rows. JSON values must be valid JSON literals — strings need quoting (`"\\"draft\\""`, not `"draft"`), and numbers/booleans/arrays/objects pass through as-is.'); //# sourceMappingURL=schemas.js.map