How the DesktopCommanderMCP File Preview UI Renders Markdown, Images, and HTML

The DesktopCommanderMCP file preview UI processes Markdown through a custom markdown-it pipeline that emits standard HTML <img> tags, renders raw HTML inside sandboxed iframes with strict security policies, and displays binary images as base64 data URIs.

The DesktopCommanderMCP repository provides a sophisticated file preview system capable of handling diverse content types safely. Understanding how this file preview UI transforms raw file contents into rendered output requires examining the modular File-Type Handler architecture and the specific rendering pipelines for Markdown, HTML, and image formats.

Markdown Rendering Pipeline

The Markdown rendering flow follows a strict pipeline from type detection to final HTML injection.

File-Type Detection and Routing

The process begins in src/ui/file-preview/src/file-type-handlers.ts, where the File-Type Handler detects Markdown files and delegates to the Markdown controller. The handler registers a markdown entry that implements renderBody to trigger the rendering chain.

// src/ui/file-preview/src/file-type-handlers.ts
markdown: {
  getCapabilities: (payload) => buildPreviewCapabilities(payload, false),
  renderBody: ({ payload, markdownController }) => {
    try {
      return markdownController.buildBody(payload);
    } catch {
      return {
        notice: 'Markdown renderer failed. Showing raw source instead.',
        html: `<div class="panel-content source-content">${renderRawFallback(stripReadStatusLine(payload.content))}</div>`,
      };
    }
  },
},

Markdown Controller and Workspace

Once routed, src/ui/file-preview/src/markdown/controller.ts instantiates a Markdown Editor Handle and Markdown Workspace containing the raw source and rendered view. The controller calls markdownController.buildBody(payload) to initiate processing.

The Markdown-it Renderer

The actual transformation occurs in src/ui/file-preview/src/components/markdown-renderer.ts. This component wraps a configured markdown-it instance defined in src/ui/file-preview/src/markdown/parser.ts.

The renderer applies three key customizations:

  • Syntax highlighting via a custom highlight function for code blocks
  • Slug generation by overriding the heading_open rule to inject ID attributes
  • Link tracking by overriding the link_open rule to add data-markdown-link="true" and data-wiki-link attributes for wiki-style links
// src/ui/file-preview/src/components/markdown-renderer.ts
export function renderMarkdown(content: string): string {
  return markdown.render(prepareMarkdownSource(content), {
    nextSlug: createSlugTracker(),
  });
}

Image Token Processing

When the markdown-it parser encounters Markdown image syntax ![alt](url), it automatically converts these tokens into standard HTML <img> tags. The overridden link rules add metadata attributes, but no additional post-processing is required for images. The resulting HTML string is injected into the preview pane via src/ui/file-preview/src/document-layout.ts inside a <div class="markdown-doc"> container.

HTML Rendering and Sandboxing

Raw HTML files receive different treatment focused on security isolation.

HTML Handler Logic

In src/ui/file-preview/src/file-type-handlers.ts, the HTML handler calls renderHtmlPreview from src/ui/file-preview/src/components/html-renderer.ts. This function supports two modes:

  • Source mode: Displays raw HTML with syntax highlighting via renderCodeViewer
  • Rendered mode: Generates a sandboxed iframe via renderSandboxedHtmlFrame
// src/ui/file-preview/src/components/html-renderer.ts
export function renderHtmlPreview(content: string, mode: HtmlPreviewMode): { html: string; notice?: string } {
  if (mode === 'source') {
    return { html: `<div class="panel-content source-content">${renderCodeViewer(content, 'html')}</div>` };
  }
  return {
    html: `<div class="panel-content html-content">${renderSandboxedHtmlFrame(content)}</div>`,
  };
}

Sandboxed Iframe Implementation

The rendered mode creates an isolated execution environment using an <iframe> with sandbox="allow-scripts allow-forms allow-popups". The iframe's srcdoc contains a minimal HTML document that applies the application's theme variables (--panel, --text, --font-sans) and responsive image styling:

img { max-width: 100%; height: auto; }

This isolation prevents scripts in the previewed HTML from accessing the parent page while still allowing the content to display images and execute its own logic. The iframe is wrapped in <div class="panel-content html-content"> and injected into the preview pane.

Raw Image File Handling

For binary image files (PNG, JPEG, GIF), src/ui/file-preview/src/file-type-handlers.ts constructs a base64 data URI after validating the MIME type via helpers in src/ui/file-preview/src/image-preview.ts (which provides normalizeImageMimeType). The handler then renders the image directly:

// src/ui/file-preview/src/file-type-handlers.ts
const src = `data:${mimeType};base64,${payload.content}`;
return {
  html: `<div class="panel-content image-content"><div class="image-preview"><img src="${escapeHtml(src)}" alt="${escapeHtml(payload.fileName)}" loading="eager" decoding="async"></div></div>`,
};

This path bypasses the Markdown pipeline but shares the same final visual output—an <img> element displayed within the preview panel.

Summary

  • DesktopCommanderMCP routes all preview requests through a central File-Type Handler system in file-type-handlers.ts that delegates to specialized renderers based on MIME type detection.
  • Markdown processing uses a customized markdown-it instance with overridden token rules for headings and links, automatically converting image references to standard HTML <img> tags without additional post-processing.
  • HTML security relies on sandboxed iframes with restricted permissions (allow-scripts allow-forms allow-popups) to isolate potentially malicious scripts while preserving visual fidelity and image rendering.
  • Binary images convert directly to base64 data URIs using MIME type validation from image-preview.ts, displaying in dedicated image containers with eager loading and async decoding for performance.

Frequently Asked Questions

How does the DesktopCommanderMCP preview UI prevent XSS attacks when rendering HTML files?

The UI renders all HTML content inside a sandboxed <iframe> element configured with the sandbox="allow-scripts allow-forms allow-popups" attribute. This isolation prevents scripts within the previewed HTML from accessing the parent window's DOM, cookies, or localStorage, effectively containing any XSS vectors while still allowing the content to execute its own scripts and display images.

What markdown-it plugins does the Markdown renderer use for image handling?

The renderer does not use specialized image plugins. Instead, it relies on markdown-it's built-in tokenization to convert standard Markdown image syntax ![alt](url) into HTML <img> tags. The pipeline focuses customization on code block highlighting (via the highlight function), slug generation for headings, and link metadata injection rather than image-specific processing.

Can the DesktopCommanderMCP preview UI display images referenced by relative paths in Markdown files?

The analysis indicates that image references are converted to HTML <img> tags with the original URLs preserved. For relative paths to resolve correctly, the underlying content loader must resolve these references before they reach the renderer, as the markdown-it instance processes the already-resolved URLs. The rendering pipeline itself does not perform path resolution or validation.

Where does the final rendered output get injected into the UI?

All rendered content—whether Markdown HTML, sandboxed iframes, or raw image elements—passes through src/ui/file-preview/src/document-layout.ts, which injects the generated HTML into the preview pane. Markdown content targets <div class="markdown-doc">, HTML content uses <div class="panel-content html-content">, and images render within <div class="panel-content image-content">.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →