Write Obsidian Property
write_propertyAdds or updates properties in an Obsidian markdown file's frontmatter to apply generated metadata such as title, date, tags, and summary.
Instructions
Description: Adds or updates properties within the frontmatter section at the top of a specified Obsidian markdown file. This tool is primarily used to apply metadata generated by the 'generate_property' tool to an actual file.
Parameters:
filePath (string, required): The path to the target markdown file to which properties will be added or updated. Example: "my-first-post.md"
properties (object, required): A JSON object containing the key-value pairs to be written to the file's frontmatter. If a property with the same key already exists in the file, it will be overwritten with the new value.
Example:
JSON { "title": "Optimizing I/O Handling in a Serverless Environment", "date": "2025-04-03", "tags": ["serverless", "optimization"], "summary": "A case study on optimizing I/O in a serverless environment by benchmarking Promise.all and Workers.", "completed": true }
Return Value:
Upon successful execution, it returns a JSON object containing the status, a confirmation message, and the property object that was applied to the file.
Example:
JSON { "status": "success", "message": "Successfully updated properties for my-first-post.md", "properties": { "title": "Optimizing I/O Handling in a Serverless Environment", "date": "2025-04-03", "tags": ["serverless", "optimization"], "summary": "A case study on optimizing I/O in a serverless environment by benchmarking Promise.all and Workers.", "completed": true } }
Dependencies & Requirements:
Input Data: The properties parameter should typically be the JSON object output from the 'generate_property' tool.
Environment Setup: The absolute path to the user's Obsidian Vault must be correctly set as an environment variable.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| filePath | Yes | Path to the target markdown file within the Obsidian vault | |
| properties | Yes | Key-value pairs to be written to the file's frontmatter | |
| quiet | No | If true, suppresses non-error output messages. Default is false. |
Implementation Reference
- src/tools/write_property/index.ts:81-140 (handler)The main execute function for the write_property tool. It gets the vault manager, calls writeDocument with the file path and properties, and returns success/failure results.
export const execute = async ( params: ObsidianPropertyParams, ): Promise<CallToolResult> => { const vaultDirPath = state.vaultPath; if (!vaultDirPath) { return createToolError( "VAULT_DIR_PATH is not set. Cannot write properties to file.", "Set the VAULT_DIR_PATH environment variable to your Obsidian vault path.", ); } let vaultManager = null; try { vaultManager = getGlobalVaultManager(); } catch (e) { return createToolError((e as Error).message); } try { await vaultManager.writeDocument(params.filePath, params.properties); if (params.quiet) { return { isError: false, content: [ { type: "text", text: JSON.stringify({ status: "success" }) }, ], }; } return { isError: false, content: [ { type: "text", text: JSON.stringify( { status: "success", message: `Successfully updated properties for ${params.filePath}`, properties: params.properties, }, null, 2, ), }, ], }; } catch (error) { if (error instanceof VaultPathError) { return createToolError( "filePath is outside VAULT_DIR_PATH. Writing outside the vault is blocked.", `Use a filePath inside VAULT_DIR_PATH ("${error.vaultPath}"). Received filePath: "${error.inputPath}"`, ); } return createToolError( (error as Error).message || "An unknown error occurred.", ); } }; - The writeDocument method on VaultManager that resolves the path, reads existing content, merges frontmatter via gray-matter's stringify, writes the file, and re-indexes it.
public async writeDocument( fullPath: string, frontmatter: Record<string, unknown>, ): Promise<void> { const resolvedPath = this.resolvePathForWrite(fullPath); await this.ioSemaphore.acquire(); try { const content = (await this.readDocumentContent(resolvedPath)) || ""; const newDocument = matter.stringify(content, frontmatter); await writeFile(resolvedPath, newDocument, "utf8"); } finally { this.ioSemaphore.release(); } await this.upsertDocument(resolvedPath); } - Zod schema defining the input validation for write_property: filePath (required), properties (object with optional fields like title, tags, date, etc.), and quiet mode flag.
import { z } from "zod"; // input properties const obsidianCssClassesProperty = z .array(z.string()) .describe("List of CSS classes associated with the document"); const obsidianTagsProperty = z .array(z.string()) .describe("List of tags associated with the document"); const obsidianTitleProperty = z.string().describe("Title of the document"); const obsidianDateProperty = z .string() .describe("Creation date of the document in ISO 8601 format"); const obsidianSummaryProperty = z .string() .describe("Brief summary or abstract of the document"); const obsidianSlugProperty = z .string() .describe("URL-friendly identifier for the document"); const obsidianCategoryProperty = z .string() .describe("Category or classification of the document"); const obsidianCompletedProperty = z .boolean() .describe("Indicates whether a task or item is completed"); const quiteMode = z .boolean() .default(true) .describe("If true, suppresses non-error output messages. Default is false."); const obsidianPropertySchema = 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("Schema for Obsidian frontmatter properties"); // input schema export const obsidianPropertyParamsSchema = z .object({ filePath: z .string() .min(1) .describe("Path to the target markdown file within the Obsidian vault"), properties: obsidianPropertySchema.describe( "Key-value pairs to be written to the file's frontmatter", ), quiet: quiteMode.optional(), }) .describe("Parameters for writing properties to an Obsidian markdown file"); - src/tools/write_property/index.ts:68-79 (registration)The register function that binds the tool name, schema, annotations, and execute handler to the MCP server.
export const register = (mcpServer: McpServer) => { mcpServer.registerTool( name, { title: annotations.title || name, description: description, inputSchema: obsidianPropertyParamsSchema.shape, annotations: annotations, }, execute, ); }; - src/tools/index.ts:5-13 (registration)Import and export of WriteObsidianPropertyTool from the centralized tools barrel file.
import WriteObsidianPropertyTool from "./write_property/index.js"; export default { ObsidianVaultTool, GenerateObsidianVaultPropertiesTool, WriteObsidianPropertyTool, CreateDocumentWithPropertyTool, OrganizeAttachmentsTool, };