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

> Explore the File Preview UI architecture in DesktopCommanderMCP. Discover its secure eight-layer design enabling support for Markdown, HTML, code, images, and directories via pluggable handlers.

- Repository: [Eduard Ruzga/DesktopCommanderMCP](https://github.com/wonderwhy-er/DesktopCommanderMCP)
- Tags: architecture
- Published: 2026-08-08

---

**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`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/ui/resources.ts). The `getFilePreviewResourceText()` function reads the [`file-preview/index.html`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/file-preview/index.html), [`styles.css`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/styles.css), and [`preview-runtime.js`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/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`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/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`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/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`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/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`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/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`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/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`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/ui/file-preview/src/components/code-viewer.ts) applies language-specific syntax highlighting via [`highlight.js`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/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`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/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`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/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.

```typescript
// Client-side: Request file preview with UI origin
const result = await callTool('read_file', {
  path: './notes/project.md',
  origin: 'ui',
});
// result.structuredContent.fileType === 'markdown'

```

```typescript
// 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`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/ui/resources.ts).
- **File type inference** occurs through `resolvePreviewFileType()` in [`src/ui/file-preview/shared/preview-file-types.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/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`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/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`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/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`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/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`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/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`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/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.