Skip to main content
Glama
diagrammo
by diagrammo

preview_diagram

Render one or more DGMO diagrams into an HTML preview in your browser, with optional theme and source display.

Instructions

Render one or more DGMO diagrams and open an HTML preview in the browser. Supports theme toggle and optional source display. IMPORTANT: Parentheses in DGMO labels = color notation (stripped from name). All labels must be unique. Use dashes for qualifiers, e.g. "App - TS" not "App (TS)".

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
diagramsYesOne or more diagrams to preview
themeNoColor themedark
paletteNoColor palettenord
include_sourceNoShow DGMO source in collapsible blocks

Implementation Reference

  • The main handler function for the preview_diagram tool. It accepts an array of diagrams (each with a title and DGMO markup), a theme, palette, and include_source flag. It renders each diagram via tryRender, builds either a single preview HTML (using buildPreviewHtml) or a multi-diagram report (using buildReportHtml), writes the HTML to a temp file, opens it in the browser, and returns a status message with any errors.
    // --- Tool 6: preview_diagram ---
    
    server.tool(
      'preview_diagram',
      'Render one or more DGMO diagrams and open an HTML preview in the browser. Supports theme toggle and optional source display. IMPORTANT: Parentheses in DGMO labels = color notation (stripped from name). All labels must be unique. Use dashes for qualifiers, e.g. "App - TS" not "App (TS)".',
      {
        diagrams: z
          .array(
            z.object({
              title: z.string().optional().describe('Optional title for this diagram'),
              dgmo: z.string().describe('DGMO diagram markup. Parentheses in labels = color notation. All labels must be unique.'),
            }),
          )
          .min(1)
          .describe('One or more diagrams to preview'),
        theme: z.enum(['light', 'dark']).default('dark').describe('Color theme'),
        palette: z.string().default('nord').describe('Color palette'),
        include_source: z.boolean().default(true).describe('Show DGMO source in collapsible blocks'),
      },
      {
        title: 'Preview Diagram',
        readOnlyHint: false,
        destructiveHint: false,
        openWorldHint: true,
      },
      async ({ diagrams, theme, palette, include_source }) => {
        const paletteConfig = getPalette(palette);
        const results = await Promise.all(
          diagrams.map(async (d) => {
            const { svg, error } = await tryRender(d.dgmo, theme, palette);
            return { title: d.title, dgmo: d.dgmo, svg, error };
          }),
        );
    
        const successes = results.filter((r) => r.svg);
        const failures = results.filter((r) => !r.svg);
    
        if (successes.length === 0) {
          return {
            content: [
              {
                type: 'text' as const,
                text:
                  'All diagrams failed to render:\n' +
                  failures.map((f) => `- ${f.title || 'untitled'}: ${f.error}`).join('\n'),
              },
            ],
            isError: true,
          };
        }
    
        let html: string;
        if (diagrams.length === 1 && successes.length === 1) {
          // Single diagram → simple preview
          const r = results[0];
          const shareResult = encodeDiagramUrl(r.dgmo);
          const shareUrl = shareResult.error ? undefined : shareResult.url;
          html = buildPreviewHtml({
            svg: r.svg!,
            title: r.title,
            dgmoSource: include_source ? r.dgmo : undefined,
            palette: paletteConfig,
            shareUrl,
          });
        } else {
          // Multiple diagrams → report layout
          const sections: ReportSection[] = results.map((r) => ({
            title: r.title || 'Untitled',
            svg: r.svg,
            dgmoSource: r.dgmo,
            error: r.error ?? undefined,
          }));
          html = buildReportHtml({
            title: 'Diagram Preview',
            sections,
            palette: paletteConfig,
            includeSource: include_source,
          });
        }
    
        const filePath = writeTempHtml(html, 'dgmo-preview');
        await openInBrowser(filePath);
    
        let message = `Opened preview in browser: ${filePath}`;
        if (failures.length > 0) {
          message +=
            '\n\nWarning — some diagrams failed to render:\n' +
            failures.map((f) => `- ${f.title || 'untitled'}: ${f.error}`).join('\n');
        }
    
        return {
          content: [{ type: 'text' as const, text: message }],
        };
      },
    );
  • Zod schema definitions for the preview_diagram tool's parameters: diagrams (array of {title?, dgmo}), theme (light/dark, default dark), palette (string, default 'nord'), include_source (boolean, default true).
    {
      diagrams: z
        .array(
          z.object({
            title: z.string().optional().describe('Optional title for this diagram'),
            dgmo: z.string().describe('DGMO diagram markup. Parentheses in labels = color notation. All labels must be unique.'),
          }),
        )
        .min(1)
        .describe('One or more diagrams to preview'),
      theme: z.enum(['light', 'dark']).default('dark').describe('Color theme'),
      palette: z.string().default('nord').describe('Color palette'),
      include_source: z.boolean().default(true).describe('Show DGMO source in collapsible blocks'),
    },
  • src/index.ts:436-528 (registration)
    Registration of the 'preview_diagram' tool via server.tool() with metadata including title 'Preview Diagram', readOnlyHint: false, destructiveHint: false, openWorldHint: true.
    server.tool(
      'preview_diagram',
      'Render one or more DGMO diagrams and open an HTML preview in the browser. Supports theme toggle and optional source display. IMPORTANT: Parentheses in DGMO labels = color notation (stripped from name). All labels must be unique. Use dashes for qualifiers, e.g. "App - TS" not "App (TS)".',
      {
        diagrams: z
          .array(
            z.object({
              title: z.string().optional().describe('Optional title for this diagram'),
              dgmo: z.string().describe('DGMO diagram markup. Parentheses in labels = color notation. All labels must be unique.'),
            }),
          )
          .min(1)
          .describe('One or more diagrams to preview'),
        theme: z.enum(['light', 'dark']).default('dark').describe('Color theme'),
        palette: z.string().default('nord').describe('Color palette'),
        include_source: z.boolean().default(true).describe('Show DGMO source in collapsible blocks'),
      },
      {
        title: 'Preview Diagram',
        readOnlyHint: false,
        destructiveHint: false,
        openWorldHint: true,
      },
      async ({ diagrams, theme, palette, include_source }) => {
        const paletteConfig = getPalette(palette);
        const results = await Promise.all(
          diagrams.map(async (d) => {
            const { svg, error } = await tryRender(d.dgmo, theme, palette);
            return { title: d.title, dgmo: d.dgmo, svg, error };
          }),
        );
    
        const successes = results.filter((r) => r.svg);
        const failures = results.filter((r) => !r.svg);
    
        if (successes.length === 0) {
          return {
            content: [
              {
                type: 'text' as const,
                text:
                  'All diagrams failed to render:\n' +
                  failures.map((f) => `- ${f.title || 'untitled'}: ${f.error}`).join('\n'),
              },
            ],
            isError: true,
          };
        }
    
        let html: string;
        if (diagrams.length === 1 && successes.length === 1) {
          // Single diagram → simple preview
          const r = results[0];
          const shareResult = encodeDiagramUrl(r.dgmo);
          const shareUrl = shareResult.error ? undefined : shareResult.url;
          html = buildPreviewHtml({
            svg: r.svg!,
            title: r.title,
            dgmoSource: include_source ? r.dgmo : undefined,
            palette: paletteConfig,
            shareUrl,
          });
        } else {
          // Multiple diagrams → report layout
          const sections: ReportSection[] = results.map((r) => ({
            title: r.title || 'Untitled',
            svg: r.svg,
            dgmoSource: r.dgmo,
            error: r.error ?? undefined,
          }));
          html = buildReportHtml({
            title: 'Diagram Preview',
            sections,
            palette: paletteConfig,
            includeSource: include_source,
          });
        }
    
        const filePath = writeTempHtml(html, 'dgmo-preview');
        await openInBrowser(filePath);
    
        let message = `Opened preview in browser: ${filePath}`;
        if (failures.length > 0) {
          message +=
            '\n\nWarning — some diagrams failed to render:\n' +
            failures.map((f) => `- ${f.title || 'untitled'}: ${f.error}`).join('\n');
        }
    
        return {
          content: [{ type: 'text' as const, text: message }],
        };
      },
    );
  • The tryRender helper function that parses DGMO markup, checks for errors, and calls the render function to produce SVG output. Used by the preview_diagram handler to render each diagram.
    async function tryRender(
      dgmo: string,
      theme: 'light' | 'dark',
      palette: string,
    ): Promise<{ svg: string | null; error: string | null }> {
      const { diagnostics } = parseDgmo(dgmo);
      const errors = diagnostics.filter((d) => d.severity === 'error');
      if (errors.length > 0) {
        return { svg: null, error: errors.map(formatDgmoError).join('\n') };
      }
      try {
        const { svg } = await render(dgmo, { theme, palette });
        if (!svg) return { svg: null, error: 'Render returned empty SVG.' };
        return { svg, error: null };
      } catch (err) {
        return { svg: null, error: err instanceof Error ? err.message : String(err) };
      }
    }
  • The buildPreviewHtml helper function that generates a complete HTML page for a single diagram preview. Includes the SVG, title, optional DGMO source block, palette-based CSS theme, and an open-in-diagrammo.app link.
    export function buildPreviewHtml(options: PreviewHtmlOptions): string {
      const { svg, title, dgmoSource, palette, shareUrl } = options;
      const pageTitle = title || 'Diagram Preview';
      const openLink = shareUrl
        ? `<a class="open-link" href="${escapeHtml(shareUrl)}" target="_blank" rel="noopener">Open at diagrammo.app ↗</a>`
        : '';
    
      return `<!DOCTYPE html>
    <html lang="en" data-theme="dark">
    <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>${escapeHtml(pageTitle)}</title>
    <style>${buildCss(palette)}
    .preview-root { display: flex; flex-direction: column; min-height: 100vh; padding: 1rem; }
    .preview-diagram { flex: 1; overflow: auto; display: flex; align-items: flex-start; justify-content: flex-start; }
    .preview-diagram svg { max-width: none; height: auto; display: block; }
    .preview-source { flex-shrink: 0; }
    </style>
    </head>
    <body>
    ${openLink}
    <div class="preview-root">
    <div class="preview-diagram">${svg}</div>
    ${dgmoSource ? `<div class="preview-source">${sourceBlock(dgmoSource)}</div>` : ''}
    </div>
    ${COPY_SCRIPT}
    </body>
    </html>`;
    }
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations indicate readOnlyHint=false and openWorldHint=true, but the description does not explain behavioral traits beyond opening a browser preview. It fails to disclose whether the tool modifies state or has side effects, and does not mention rate limits or permissions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise (4 sentences) and front-loads the core purpose. Every sentence provides necessary information without fluff. The important note is placed for emphasis.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, and the description does not explain what the tool returns (it implies opening a browser window). It covers key usage notes but lacks details on error handling or edge cases, making it adequate but with gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 100% schema coverage, the baseline is 3. The description adds value by explaining that parentheses in labels denote color notation and that labels must be unique, which is not fully captured in the schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool 'Renders one or more DGMO diagrams and opens an HTML preview in the browser' and includes specific features like theme toggle and source display. It distinguishes from sibling tools like render_diagram by focusing on browser preview.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides important constraints (parentheses notation, unique labels) but does not explicitly state when to use this tool versus alternatives like render_diagram or validate_diagram. The guidance is implied through feature description.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

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/diagrammo/dgmo-mcp'

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