Skip to main content
Glama

expand-code

Expands TypeScript macros and @derive decorators to show generated code with diagnostics for debugging and understanding transformations.

Instructions

Expands Macroforge macros in TypeScript code and returns the transformed result.

Shows:

  • The fully expanded TypeScript code with all generated methods

  • Any diagnostics (errors, warnings, info) with line/column locations

  • Help text for fixing issues (when available)

Useful for:

  • Seeing what code the macros generate

  • Understanding how @derive decorators transform your classes

  • Debugging macro expansion issues

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
codeYesTypeScript code with @derive decorators to expand
filenameNoFilename for the code (default: input.ts)

Implementation Reference

  • The main handler function that implements the 'expand-code' tool. It dynamically imports @macroforge/core, calls expandSync to expand macros in the provided TypeScript code, processes any diagnostics, and returns formatted markdown output containing the expanded code and diagnostic information.
    async function handleExpandCode(args: { code: string; filename?: string }) { const filename = args.filename || 'input.ts'; try { const macroforge = await importMacroforge(); if (!macroforge) { return { content: [ { type: 'text' as const, text: 'Native Macroforge bindings not available. Install @macroforge/core to enable code expansion.', }, ], }; } const result = macroforge.expandSync(args.code, filename, {}); const diagnostics = result.diagnostics || []; // Build structured output const output: ExpandResult = { expandedCode: result.code, diagnostics: diagnostics.map((d) => ({ level: normalizeLevel(d.level), message: d.message, location: d.span?.start, help: d.help || undefined, })), hasErrors: diagnostics.some((d) => d.level === 'Error'), }; // Format human-readable text let text = `## Expanded Code\n\n\`\`\`typescript\n${result.code}\n\`\`\``; if (diagnostics.length > 0) { text += '\n\n## Diagnostics\n\n'; for (const d of diagnostics) { const loc = d.span ? ` (line ${d.span.start.line}, col ${d.span.start.column})` : ''; text += `- **[${normalizeLevel(d.level)}]**${loc} ${d.message}\n`; if (d.help) { text += ` - Help: ${d.help}\n`; } if (d.notes && d.notes.length > 0) { for (const note of d.notes) { text += ` - Note: ${note}\n`; } } } } return { content: [{ type: 'text' as const, text }], }; } catch (error) { const message = error instanceof Error ? error.message : String(error); return { content: [ { type: 'text' as const, text: `Error expanding code: ${message}`, }, ], }; }
  • The tool registration definition in the ListToolsRequestSchema handler, including the tool name, description, and input schema.
    { name: 'expand-code', description: `Expands Macroforge macros in TypeScript code and returns the transformed result. Shows: - The fully expanded TypeScript code with all generated methods - Any diagnostics (errors, warnings, info) with line/column locations - Help text for fixing issues (when available) Useful for: - Seeing what code the macros generate - Understanding how @derive decorators transform your classes - Debugging macro expansion issues`, inputSchema: { type: 'object', properties: { code: { type: 'string', description: 'TypeScript code with @derive decorators to expand', }, filename: { type: 'string', description: 'Filename for the code (default: input.ts)', }, }, required: ['code'], }, },
  • TypeScript interface defining the structured output format used internally by the expand-code handler.
    interface ExpandResult { expandedCode: string; diagnostics: Array<{ /** Severity level: "error", "warning", or "info" */ level: string; /** Human-readable description of the issue */ message: string; /** Source location (line and column) if available */ location?: { line: number; column: number }; /** Suggested fix for the issue */ help?: string; }>; hasErrors: boolean; }
  • Dispatch case in the CallToolRequestSchema handler that routes 'expand-code' calls to the handleExpandCode function.
    case 'expand-code': return handleExpandCode(args as { code: string; filename?: string });
  • Helper functions used by the handler: importMacroforge dynamically loads the optional @macroforge/core dependency, and normalizeLevel converts diagnostic levels to lowercase.
    } } /** * Handles the `get-macro-info` tool call. * * Retrieves documentation for Macroforge macros and field decorators from the * native manifest. Can return info for a specific macro/decorator or the full * manifest of all available macros and decorators. * * ## Usage Modes * * - **Without name**: Returns full manifest with all macros and decorators * - **With name**: Returns detailed info for the specific macro or decorator * * ## Manifest Contents * * - **Macros**: @derive decorators like Debug, Serialize, Clone * - **Decorators**: Field decorators like @serde.skip, @serde.rename * * @param args - Tool arguments * @param args.name - Optional macro or decorator name to look up * @returns MCP response with formatted macro/decorator documentation */ async function handleGetMacroInfo(args: { name?: string }) { try { const macroforge = await importMacroforge(); if (!macroforge || !macroforge.__macroforgeGetManifest) { return { content: [ { type: 'text' as const, text: 'Native Macroforge bindings not available. Install @macroforge/core to access macro documentation.', }, ], }; } const manifest = macroforge.__macroforgeGetManifest(); if (args.name) { // Look up specific macro or decorator const nameLower = args.name.toLowerCase(); const macro = manifest.macros.find(m => m.name.toLowerCase() === nameLower); const decorator = manifest.decorators.find(d => d.export.toLowerCase() === nameLower); if (!macro && !decorator) { return { content: [ { type: 'text' as const, text: `No macro or decorator found with name "${args.name}". Available macros: ${manifest.macros.map(m => m.name).join(', ')} Available decorators: ${manifest.decorators.map(d => d.export).join(', ')}`, }, ], }; } let result = ''; if (macro) { result += `## Macro: @derive(${macro.name})\n\n`; result += `**Description:** ${macro.description || 'No description available'}\n`; result += `**Kind:** ${macro.kind}\n`; result += `**Package:** ${macro.package}\n`; } if (decorator) { if (result) result += '\n---\n\n'; result += `## Decorator: @${decorator.export}\n\n`; result += `**Documentation:** ${decorator.docs || 'No documentation available'}\n`; result += `**Kind:** ${decorator.kind}\n`; result += `**Module:** ${decorator.module}\n`; } return { content: [{ type: 'text' as const, text: result }], }; } // Return full manifest let result = '# Macroforge Macro Manifest\n\n'; result += '## Available Macros\n\n'; for (const macro of manifest.macros) { result += `### @derive(${macro.name})\n`; result += `${macro.description || 'No description'}\n\n`; } if (manifest.decorators.length > 0) { result += '## Available Field Decorators\n\n'; for (const decorator of manifest.decorators) { result += `### @${decorator.export}\n`; result += `${decorator.docs || 'No documentation'}\n\n`; } } return { content: [{ type: 'text' as const, text: result }], }; } catch (error) { const message = error instanceof Error ? error.message : String(error); return { content: [ { type: 'text' as const, text: `Error getting macro info: ${message}`, }, ], }; } } // ============================================================================ // Types - Match Rust's Diagnostic structure from macroforge_ts_syn/src/abi/patch.rs // ============================================================================ /** * Represents a location span in source code. * * Used by diagnostics to indicate where an error or warning occurred. * Matches the Rust `Span` type from the macroforge_ts_syn crate. * * @property start - Starting position (line and column, 1-indexed) * @property end - Ending position (line and column, 1-indexed) */ interface DiagnosticSpan { start: { line: number; column: number }; end: { line: number; column: number }; } /** * Represents a diagnostic message from the Macroforge analyzer. * * Diagnostics are produced during code validation and expansion to report * errors, warnings, and informational messages. Matches the Rust `Diagnostic` * type from macroforge_ts_syn/src/abi/patch.rs. * * @property level - Severity level: 'Error', 'Warning', or 'Info' * @property message - Human-readable description of the issue * @property span - Optional source location where the issue occurred * @property notes - Additional context or explanatory notes * @property help - Optional suggestion for how to fix the issue */ interface Diagnostic { level: 'Error' | 'Warning' | 'Info'; message: string; span?: DiagnosticSpan; notes: string[]; help?: string; } /** * Metadata for a Macroforge macro in the manifest. * * Describes a @derive macro that can be applied to classes. * * @property name - Macro name as used in @derive (e.g., "Debug", "Serialize") * @property kind - Type of macro (e.g., "derive") * @property description - Human-readable description of what the macro does * @property package - Package that provides this macro */ interface MacroManifestEntry { name: string; kind: string; description: string; package: string; } /** * Metadata for a field decorator in the manifest. * * Describes a decorator that can be applied to class fields to customize * macro behavior (e.g., @serde.skip, @debug.format). * * @property module - Module path where the decorator is defined * @property export - Export name of the decorator * @property kind - Type of decorator (e.g., "field") * @property docs - Documentation string for the decorator */ interface DecoratorManifestEntry { module: string; export: string; kind: string; docs: string; } /** * Complete manifest of available Macroforge macros and decorators. * * Returned by the native bindings to provide documentation and metadata * for all available macros and field decorators. * * @property version - Manifest format version * @property macros - Array of available @derive macros * @property decorators - Array of available field decorators */ interface MacroManifest { version: number; macros: MacroManifestEntry[]; decorators: DecoratorManifestEntry[]; } /** * Interface for the native Macroforge module (@macroforge/core). * * Defines the expected API surface of the optional native bindings that * provide code validation, expansion, and manifest access. * * @property expandSync - Synchronously expands macros in TypeScript code * @property __macroforgeGetManifest - Optional function to retrieve the macro manifest */ interface MacroforgeModule { /** * Synchronously expands Macroforge macros in TypeScript code. * * @param code - TypeScript source code with @derive decorators * @param filename - Filename for error reporting * @param options - Expansion options (currently unused) * @returns Object with expanded code and any diagnostics */ expandSync: (code: string, filename: string, options: object) => { code: string; diagnostics?: Diagnostic[]; }; /** * Retrieves the macro manifest with all available macros and decorators. * Optional - may not be available in all versions. */ __macroforgeGetManifest?: () => MacroManifest; } // ============================================================================ // Output types for structured responses // ============================================================================ /** * Structured output format for the `macroforge-autofixer` tool. * * Provides a JSON response that clients can parse to display errors, * navigate to problem locations, and determine if re-validation is needed. * * @property diagnostics - Array of diagnostic messages with locations * @property summary - Counts of errors, warnings, and info messages * @property require_another_tool_call_after_fixing - True if errors exist and client should revalidate after fixing */ interface AutofixerResult { diagnostics: Array<{ /** Severity level: "error", "warning", or "info" */ level: string; /** Human-readable description of the issue */ message: string; /** Source location (line and column) if available */ location?: { line: number; column: number }; /** Suggested fix for the issue */ help?: string; /** Additional context or explanatory notes */ notes?: string[]; }>; /** Summary counts for quick overview */ summary: { errors: number; warnings: number; info: number; }; /** If true, client should fix issues and call autofixer again */ require_another_tool_call_after_fixing: boolean; } /** * Structured output format for the `expand-code` tool. * * Contains the fully expanded code along with any diagnostics produced * during expansion. * * @property expandedCode - The TypeScript code after macro expansion * @property diagnostics - Array of diagnostic messages from expansion * @property hasErrors - True if any error-level diagnostics were produced */ interface ExpandResult { expandedCode: string; diagnostics: Array<{ /** Severity level: "error", "warning", or "info" */ level: string; /** Human-readable description of the issue */ message: string; /** Source location (line and column) if available */ location?: { line: number; column: number }; /** Suggested fix for the issue */ help?: string; }>; hasErrors: boolean; } // ============================================================================ // Helper functions // ============================================================================ /** * Dynamically imports the native Macroforge bindings. * * The @macroforge/core package is an optional peer dependency that provides * native Rust-based code analysis and expansion. This function attempts to * load it at runtime and gracefully returns null if unavailable. * * Using dynamic import allows the MCP server to run and serve documentation * even when the native bindings are not installed. * * @returns The Macroforge module if available, or null if not installed * * @example * ```typescript * const macroforge = await importMacroforge(); * if (macroforge) { * const result = macroforge.expandSync(code, 'input.ts', {}); * } * ``` */ async function importMacroforge(): Promise<MacroforgeModule | null> {

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/macroforge-ts/mcp-server'

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