Generate Obsidian Property
generate_propertyReads a markdown file and returns content preview with a property schema to generate frontmatter fields such as title, tags, and summary. Does not write to disk.
Instructions
Reads a target markdown document and returns an AI-facing payload for generating frontmatter properties.
This tool does not write to disk. It returns content_preview and a target output schema so an AI can produce a valid property object.
Use Cases:
After completing a draft, when you need property suggestions from content.
When missing frontmatter fields (title, tags, summary, slug, date, category, completed) should be generated.
To apply generated properties to a file, call 'write_property' with the resulting JSON.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| filename | Yes | The name or path of the file to analyze and add properties to (e.g., "my-first-post.md") | |
| overwrite | No | If set to true, existing properties will be overwritten by the AI-generated content. Default: false. |
Implementation Reference
- The main execute function that reads a target markdown document and returns content_preview + instructions for AI to generate frontmatter properties. It validates the vault manager, reads the document via vaultManager.getDocumentInfo(), and returns a JSON payload with filename, content_preview (first 300 chars), and an output schema instructing the AI on what properties to generate.
export const execute = async ( params: ObsidianPropertyQueryParams, ): Promise<CallToolResult> => { const response: CallToolResult = { content: [], isError: false }; let vaultManager = null; try { vaultManager = getGlobalVaultManager(); } catch (e) { return createToolError((e as Error).message); } try { const document = await vaultManager.getDocumentInfo(params.filename); if (document === null) { return createToolError( `Document not found: ${params.filename}`, "Use 'list_all' action to see available documents", ); } const documentData = { filename: params.filename, content_preview: `${document.content.substring(0, 300).replace(/\s+/g, " ")}...`, instructions: { purpose: "Generate or update the document's frontmatter properties based on its content.", usage: "Analyze the provided content_preview. If more detail is needed to generate accurate properties, you MUST call the 'vault' tool with action='read' to get the full document content.", content_type: "markdown", overwrite: params.overwrite || false, output_format: "Return a JSON object with the following structure", schema: { title: "string - Title representing the core topic", tags: "string[] - Array of relevant tags from content keywords", summary: "string - 1-2 sentence summary of the document", slug: "string - URL-friendly hyphenated identifier", date: "string - ISO 8601 date format", completed: "boolean - Whether content is finalized", aliases: "string[] - (Optional) Alternative names or synonyms", category: "string - (Optional) Document category", }, }, }; response.content.push({ type: "text", text: JSON.stringify(documentData, null, 2), }); } catch (error) { return createToolError( (error as Error).message, "Ensure the VAULT_DIR_PATH environment variable is set to your Obsidian vault directory and the filename is correct.", ); } return response; }; - Input/output schemas using Zod. Input schema (obsidianPropertyQueryParamsSchema) defines 'filename' (string) and optional 'overwrite' (boolean). Output schema (obsidianPropertyOutputSchema) defines cssclasses, tags, title, date, summary, slug, category, completed as optional fields. Also defines individual property types.
import { z } from "zod"; // input properties const obsidianGenerateInputFilename = z .string() .describe( 'The name or path of the file to analyze and add properties to (e.g., "my-first-post.md")', ); const obsidianGenerateInputOverwrite = z .boolean() .default(true) .describe( "If set to true, existing properties will be overwritten by the AI-generated content. Default: false.", ); // input schema export const obsidianPropertyQueryParamsSchema = z .object({ filename: obsidianGenerateInputFilename, overwrite: obsidianGenerateInputOverwrite.optional(), }) .describe( "Parameters for generating or updating Obsidian document properties", ); export type ObsidianPropertyQueryParams = z.infer< typeof obsidianPropertyQueryParamsSchema >; // output properties export const obsidianCssClassesProperty = z .array(z.string()) .describe("List of CSS classes associated with the document"); export const obsidianTagsProperty = z .array(z.string()) .describe("List of tags associated with the document"); export const obsidianTitleProperty = z .string() .describe("Title of the document"); export const obsidianDateProperty = z .string() .describe("Creation date of the document in ISO 8601 format"); export const obsidianSummaryProperty = z .string() .describe("Brief summary or abstract of the document"); export const obsidianSlugProperty = z .string() .describe("URL-friendly identifier for the document"); export const obsidianCategoryProperty = z .string() .describe("Category or classification of the document"); export const obsidianCompletedProperty = z .boolean() .describe("Indicates whether a task or item is completed"); // output schema export const obsidianPropertyOutputSchema = z .object({ cssclasses: obsidianCssClassesProperty.optional(), tags: obsidianTagsProperty.optional(), title: obsidianTitleProperty.optional(), date: obsidianDateProperty.optional(), summary: obsidianSummaryProperty.optional(), slug: obsidianSlugProperty.optional(), category: obsidianCategoryProperty.optional(), completed: obsidianCompletedProperty.optional(), }) .describe("Extracted properties from the Obsidian document content"); - src/tools/generate_property/index.ts:32-43 (registration)The register function that registers the tool with the MCP server using mcpServer.registerTool(). It binds the tool name 'generate_property', inputSchema, description, annotations, and the execute handler.
export const register = (mcpServer: McpServer) => { mcpServer.registerTool( name, { title: annotations.title || name, description: description, inputSchema: obsidianPropertyQueryParamsSchema.shape, annotations: annotations, }, execute, ); }; - src/server.ts:40-45 (registration)Server-level registration: iterates over all tools (including generate_property) from the tools index and calls their register() method.
for (const tool of Object.values(tools)) { tool.register(mcpServer); } return mcpServer; - CLI dispatcher helper mapping the '/genprop' chat command to the 'generate_property' tool, extracting the filename argument.
"/genprop": { tool: "generate_property", requiresArgs: true, noArgsMessage: '사용법: /genprop <파일명>\n예: /genprop "my-post.md"', buildArgs: (args) => ({ filename: extractFilenameFromArgs(args), }), },