render_template
Render dynamic HTML or text content by processing a specified template with given variables, enabling flexible customization for dynamic AI persona management within DollhouseMCP.
Instructions
Render a template element with provided variables
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | The template name to render | |
| variables | Yes | Variables to use in the template |
Implementation Reference
- src/server/tools/ElementTools.ts:197-219 (registration)Registration of the render_template MCP tool, including name, description, input schema, and thin handler that delegates to server.renderTemplate// Element-specific tools { tool: { name: "render_template", description: "Render a template element with provided variables", inputSchema: { type: "object", properties: { name: { type: "string", description: "The template name to render", }, variables: { type: "object", description: "Variables to use in the template", additionalProperties: true, }, }, required: ["name", "variables"], }, }, handler: (args: RenderTemplateArgs) => server.renderTemplate(args.name, args.variables) },
- src/server/tools/ElementTools.ts:218-218 (handler)The MCP tool handler function that receives args and calls the internal server.renderTemplate methodhandler: (args: RenderTemplateArgs) => server.renderTemplate(args.name, args.variables)
- TypeScript interface defining the expected arguments for the render_template tool handlerinterface RenderTemplateArgs { name: string; variables: Record<string, any>; }
- src/server/types.ts:30-30 (schema)Interface definition for the internal server.renderTemplate method called by the tool handlerrenderTemplate(name: string, variables: Record<string, any>): Promise<any>;
- Core implementation of template rendering in Template class, performing safe variable substitution, validation, and include processing (likely called by server.renderTemplate)async render<T extends Record<string, unknown>>( variables: T = {} as T, includeDepth: number = 0 ): Promise<string> { // SECURITY FIX #4: Prevent infinite include loops if (includeDepth > this.MAX_INCLUDE_DEPTH) { SecurityMonitor.logSecurityEvent({ type: 'INCLUDE_DEPTH_EXCEEDED', severity: 'HIGH', source: 'Template.render', details: `Include depth ${includeDepth} exceeds maximum ${this.MAX_INCLUDE_DEPTH}` }); throw ErrorHandler.createError('Maximum template include depth exceeded', ErrorCategory.VALIDATION_ERROR, ValidationErrorCodes.MAX_INCLUDE_DEPTH); } // Compile the template const compiled = this.compile(); // Validate and sanitize all provided variables const sanitizedVariables = await this.validateAndSanitizeVariables(variables); // Start with the template content let rendered = compiled.content; // Replace tokens in reverse order to maintain positions const sortedTokens = [...compiled.tokens].sort((a, b) => b.position - a.position); for (const token of sortedTokens) { const value = this.resolveVariable(token.variable, sanitizedVariables); const stringValue = this.formatValue(value); // Replace the token with the sanitized value rendered = rendered.substring(0, token.position) + stringValue + rendered.substring(token.position + token.token.length); } // Process includes if any if (this.metadata.includes && this.metadata.includes.length > 0) { rendered = await this.processIncludes(rendered, sanitizedVariables, includeDepth); } // Update usage statistics // NOTE: These updates are not atomic and may have race conditions under concurrent access // This is acceptable for usage statistics which don't require perfect accuracy // For production systems requiring atomic counters, consider using a database or atomic operations this.metadata.usage_count = (this.metadata.usage_count || 0) + 1; this.metadata.last_used = new Date().toISOString(); // SECURITY FIX #5: Log template usage for audit trail SecurityMonitor.logSecurityEvent({ type: 'TEMPLATE_RENDERED', severity: 'LOW', source: 'Template.render', details: `Template ${this.metadata.name} rendered with ${Object.keys(sanitizedVariables).length} variables` }); return rendered; }