import type { CallToolResult, ToolAnnotations } from '@modelcontextprotocol/sdk/types.js';
import { type McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { obsidianPropertyParamsSchema, ObsidianPropertyParams } from './params.js';
import { getParsedVaultPath } from '@/utils/parseVaultPath.js';
import { VaultManager } from '@/utils/VaultManager.js';
export const name = 'write_property';
export const annotations: ToolAnnotations = {
title: 'Write Obsidian Property',
openWorldHint: true,
};
export const description = `
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_obsidian_properties 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_obsidian_properties tool.
- Environment Setup: The absolute path to the user's Obsidian Vault must be correctly set as an environment variable.
`;
export const register = (mcpServer: McpServer) => {
mcpServer.registerTool(
name,
{
title: annotations.title || name,
description: description,
inputSchema: obsidianPropertyParamsSchema.shape,
annotations: annotations,
},
execute
);
};
export const execute = async (params: ObsidianPropertyParams): Promise<CallToolResult> => {
const response: CallToolResult = { content: [], isError: false };
const vaultDirPath = getParsedVaultPath();
if (!vaultDirPath) {
response.content.push({
type: 'text',
text: JSON.stringify(
{
error: 'VAULT_DIR_PATH is not set. Cannot write properties to file.',
suggestion:
'Please set the VAULT_DIR_PATH environment variable to your Obsidian vault path.',
},
null,
2
),
});
response.isError = true;
return response;
}
try {
const vaultManager = new VaultManager(vaultDirPath);
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) {
response.content.push({
type: 'text',
text: JSON.stringify(
{
error: (error as Error).message || 'An unknown error occurred.',
},
null,
2
),
});
response.isError = true;
return response;
}
};
export default {
name,
description,
annotations,
inputSchema: obsidianPropertyParamsSchema.shape,
execute,
register,
};