Skip to main content
Glama
bazylhorsey
by bazylhorsey

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
NameRequiredDescriptionDefault
frontmatterNoAdditional frontmatter
targetPathNoTarget note path (for context)
templatePathYesPath to template file
variablesNoTemplate variables
vaultYesVault 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'],
      },
    },
  • 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) }],
      };
    }
  • 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);
      });
    }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/bazylhorsey/obsidian-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server