File Preview UI in DesktopCommanderMCP: Architecture and Multi-Type Support

The File Preview UI in DesktopCommanderMCP uses an eight-layer architecture combining a resource loader, payload normalizer, extension-based type inference, and pluggable handler registry to securely render Markdown, HTML, code, images, and directories inside a sandboxed widget.

The DesktopCommanderMCP server provides a sophisticated File Preview UI that allows AI assistants to display file contents directly within the chat interface. This system handles diverse file formats through a modular pipeline that converts raw file data into secure, interactive HTML widgets served under the ui://desktop-commander/file-preview resource URI.

Architecture of the File Preview UI

The preview system follows a layered architecture that separates resource delivery from rendering logic, ensuring each file type receives appropriate handling while maintaining security boundaries.

UI Resource Loading and Widget Initialization

The entry point is the UI Resource Loader defined in src/ui/resources.ts. The getFilePreviewResourceText() function reads the file-preview/index.html, styles.css, and preview-runtime.js assets, inlining them into a single HTML payload. This bundled resource initializes the FilePreviewWidget runtime, which registers the RPC hook used by the host to fetch file data with origin: 'ui'.

Payload Normalization and Type Inference

When a file read originates from the UI, the handleReadFile function in src/handlers/filesystem-handlers.ts constructs a structuredContent object. This payload includes the critical fileType field determined by resolvePreviewFileType() in src/ui/file-preview/shared/preview-file-types.ts. The resolver maps file extensions and special basenames to preview modes: markdown, html, text, image, directory, or unsupported.

Handler Registry and Capability Exposure

The Handler Registry in src/ui/file-preview/src/file-type-handlers.ts maintains a mapping of file types to FileTypeHandler implementations. Each handler defines how to generate HTML bodies via renderPayloadBody() and exposes UI capabilities through getFileTypeCapabilities(), enabling actions like "Copy" or "Open in folder" based on the specific file type.

How the File Preview UI Handles Different File Types

The DesktopCommanderMCP File Preview UI supports six distinct rendering modes, each implemented through specialized handlers and components.

Markdown Files

Markdown documents (.md, .markdown, .mdx) render in a full-featured editor workspace controlled by src/ui/file-preview/src/markdown/controller.ts. The MarkdownController builds the workspace via buildBody() and provides live preview panes, outline navigation, fullscreen mode, and auto-save functionality. Methods like loadFullDocument, navigateLink, and requestEditMode orchestrate complex interactions while routing actions back through the RPC channel.

HTML Files

HTML content (.html, .htm) is sanitized and embedded inside a sandboxed <iframe> with allow-scripts, allow-forms, and allow-popups permissions. The HtmlRenderer component in src/ui/file-preview/src/components/html-renderer.ts ensures the host environment remains isolated from potentially malicious scripts while allowing the page to function normally.

Text and Code Files

Plain text and code files pass through formatJsonIfPossible and inferLanguageFromPath utilities in the handler pipeline. The CodeViewer component in src/ui/file-preview/src/components/code-viewer.ts applies language-specific syntax highlighting via highlight.js based on the inferred file extension.

Image Files

Images (.png, .jpeg, .svg) undergo MIME type normalization via normalizeImageMimeType() and validation through isAllowedImageMimeType(). Valid images are Base64-encoded and rendered with optimized <img loading="eager" decoding="async"> tags as implemented in src/ui/file-preview/src/image-preview.ts.

Directory Listings

Directories trigger the renderDirectoryBody function in the handler registry, displaying a simple list of entries. The widget preserves the "Open in folder" capability for quick navigation to the system file explorer.

Unsupported File Types

For unrecognized extensions, the system falls back to the default handler in src/ui/file-preview/src/file-type-handlers.ts, displaying the raw source inside a <pre> block while maintaining copy-to-clipboard functionality.

Implementation Example

The following TypeScript snippets demonstrate how clients trigger previews and how the server selects the appropriate renderer.

// Client-side: Request file preview with UI origin
const result = await callTool('read_file', {
  path: './notes/project.md',
  origin: 'ui',
});
// result.structuredContent.fileType === 'markdown'
// Server-side: Resolve preview type and render HTML body
import { resolvePreviewFileType } from './ui/file-preview/shared/preview-file-types.js';
import { renderPayloadBody } from './ui/file-preview/src/file-type-handlers.js';

const fileType = resolvePreviewFileType(resolvedFilePath);

const htmlBody = renderPayloadBody({
  payload: {
    filePath: resolvedFilePath,
    fileName: 'project.md',
    fileType,
    content: rawText,
    mimeType: 'text/markdown',
  },
  htmlMode: 'default',
  startLine: 1,
  markdownController,
});
// htmlBody.html is injected into the UI widget

Summary

  • The File Preview UI loads as a single inlined HTML resource via getFilePreviewResourceText() in src/ui/resources.ts.
  • File type inference occurs through resolvePreviewFileType() in src/ui/file-preview/shared/preview-file-types.ts, mapping extensions to preview modes.
  • Markdown renders in an editable workspace with navigation, fullscreen, and auto-save capabilities via MarkdownController.
  • HTML displays inside sandboxed iframes with controlled permissions to protect the host environment.
  • Code files receive automatic syntax highlighting based on file extension analysis.
  • Images are validated, Base64-encoded, and displayed with performance-optimized loading attributes.
  • Directories and unsupported files receive appropriate fallback renderers with consistent capability exposure through getFileTypeCapabilities().

Frequently Asked Questions

How does DesktopCommanderMCP determine which preview handler to use?

The system examines the file extension and basename through resolvePreviewFileType() in src/ui/file-preview/shared/preview-file-types.ts. This function returns a type identifier that the handler registry in src/ui/file-preview/src/file-type-handlers.ts uses to select the appropriate FileTypeHandler implementation for rendering.

Is the HTML preview secure against malicious scripts?

Yes. HTML files render inside sandboxed iframes implemented in src/ui/file-preview/src/components/html-renderer.ts. The sandbox configuration allows necessary functionality like scripts and forms while isolating the content from the host environment, preventing access to sensitive APIs or data.

Can the File Preview UI handle large Markdown files efficiently?

Yes. The MarkdownController in src/ui/file-preview/src/markdown/controller.ts implements loadFullDocument methods and optimized rendering pipelines specifically designed for large documents. The controller also provides outline navigation that helps users manage and navigate substantial content without performance degradation.

What happens when a file type is not recognized?

Unsupported files trigger the default handler in src/ui/file-preview/src/file-type-handlers.ts, which displays the raw content within a <pre> block. This fallback maintains essential capabilities like copy-to-clipboard through getFileTypeCapabilities(), ensuring users can access file contents even without specialized rendering logic.

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 →