render_template
Generate Obsidian notes by applying variables to template files, creating structured content with custom frontmatter and predefined formats.
Instructions
Render a template with variables
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| frontmatter | No | Additional frontmatter | |
| targetPath | No | Target note path (for context) | |
| templatePath | Yes | Path to template file | |
| variables | No | Template variables | |
| vault | Yes | Vault name |
Implementation Reference
- src/index.ts:363-377 (registration)Registration of the 'render_template' tool in the ListTools response, defining its name, description, and input schema.{ name: 'render_template', description: 'Render a template with variables', inputSchema: { type: 'object', properties: { vault: { type: 'string', description: 'Vault name' }, templatePath: { type: 'string', description: 'Path to template file' }, variables: { type: 'object', description: 'Template variables' }, frontmatter: { type: 'object', description: 'Additional frontmatter' }, targetPath: { type: 'string', description: 'Target note path (for context)' }, }, required: ['vault', 'templatePath'], }, },
- src/index.ts:831-850 (handler)Handler for the 'render_template' tool call in the MCP server switch statement, which retrieves the vault connector and delegates rendering to TemplateService.case 'render_template': { const connector = this.connectors.get(args?.vault as string); if (!connector || !connector.vaultPath) { throw new Error(`Vault "${args?.vault}" not found or not a local vault`); } const result = await this.templateService.renderTemplate( connector.vaultPath, args?.templatePath as string, { variables: args?.variables as Record<string, any> | undefined, frontmatter: args?.frontmatter as Record<string, any> | undefined, targetPath: args?.targetPath as string | undefined, } ); return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }], }; }
- src/services/TemplateService.ts:111-155 (handler)Core handler function that implements the template rendering logic: loads template, substitutes variables (built-in and custom), handles frontmatter, and returns rendered content.async renderTemplate( vaultPath: string, templatePath: string, options?: TemplateRenderOptions ): Promise<VaultOperationResult<TemplateRenderResult>> { try { // Get template const templateResult = await this.getTemplate(vaultPath, templatePath); if (!templateResult.success || !templateResult.data) { return { success: false, error: templateResult.error }; } const template = templateResult.data; let content = template.content; // Build variables const builtInVars = this.getBuiltInVariables(options?.targetPath); const customVars = options?.variables || {}; const allVariables: Record<string, any> = { ...builtInVars, ...customVars, }; // Replace template variables content = this.substituteVariables(content, allVariables); // Add/update frontmatter if provided if (options?.frontmatter) { content = this.addFrontmatter(content, options.frontmatter); } return { success: true, data: { content, renderedVariables: allVariables, }, }; } catch (error) { return { success: false, error: `Failed to render template: ${error instanceof Error ? error.message : String(error)}` }; } }
- Helper function for substituting template variables in content, supporting formats, defaults, and date formatting.private substituteVariables(content: string, variables: Record<string, any>): string { // Replace {{variable}} or {{variable|default}} patterns return content.replace(/\{\{([^}]+)\}\}/g, (match, expression) => { expression = expression.trim(); // Handle default values: {{variable|default}} const [varName, defaultValue] = expression.split('|').map((s: string) => s.trim()); // Handle date formats: {{date:YYYY-MM-DD}} const [actualVar, format] = varName.split(':').map((s: string) => s.trim()); let value = variables[actualVar]; // Apply format if specified if (format && value instanceof Date) { value = this.formatDate(value, format); } else if (format && typeof value === 'string') { // Try to parse as date and format const date = new Date(value); if (!isNaN(date.getTime())) { value = this.formatDate(date, format); } } // Use default if value is undefined if (value === undefined || value === null) { return defaultValue !== undefined ? defaultValue : match; } return String(value); }); }