How Desktop Commander MCP Detects MIME Types and Handles Different File Formats

Desktop Commander MCP uses a lightweight extension-based MIME detection layer combined with specialized FileHandler classes that manage format-specific reading, writing, and conversion operations.

The repository implements a clean separation between MIME type identification and content processing. By centralizing MIME detection in src/tools/mime-types.ts and delegating format handling to dedicated classes in src/utils/files/, the system supports images, PDFs, and plain text with extensible precision.

Extension-Based MIME Detection Logic

The foundation of Desktop Commander MCP MIME type detection lives in a single utility function that maps file extensions to standard MIME strings. This approach prioritizes speed and predictability for the MCP server environment.

The Core MIME Lookup in mime-types.ts

In src/tools/mime-types.ts, the getMimeType() function extracts the file extension, converts it to lowercase, and matches it against hard-coded mappings for PDFs and common image formats. Any unrecognized extension defaults to text/plain.

// src/tools/mime-types.ts
export function getMimeType(filePath: string): string {
  const extension = filePath.toLowerCase().split('.').pop() || '';
  if (extension === "pdf") return "application/pdf";

  const imageTypes = {
    png:  "image/png",
    jpg:  "image/jpeg",
    jpeg: "image/jpeg",
    gif:  "image/gif",
    webp: "image/webp",
  };
  if (extension in imageTypes) return imageTypes[extension];
  return "text/plain";
}

Helper Predicates for Classification

Supporting the primary detection are two boolean utilities: isPdfFile() and isImageFile(). These functions inspect the MIME string prefix—checking for application/pdf or the image/ family—to determine file category without re-parsing the extension.

MIME Metadata Consolidation

Higher-level filesystem operations rely on getMimeTypeInfo(), defined in src/tools/filesystem.ts. This async function lazily imports the MIME utilities, runs the detection, and returns a structured object containing the MIME string plus boolean flags for images and PDFs.

// src/tools/filesystem.ts
async function getMimeTypeInfo(filePath: string) {
  const { getMimeType, isImageFile, isPdfFile } = await import('./mime-types.js');
  const mimeType = getMimeType(filePath);
  return { mimeType, isImage: isImageFile(mimeType), isPdf: isPdfFile(mimeType) };
}

This consolidation layer allows handlers in src/handlers/filesystem-handlers.ts to make routing decisions using simple property checks rather than string manipulation.

File Handler Architecture

Each supported format implements the FileHandler interface defined in src/utils/files/base.ts. The architecture treats MIME types as routing keys, dispatching to specialized handlers that understand binary encoding, document conversion, or text streaming.

ImageFileHandler for Binary Assets

Located in src/utils/files/image.ts, the ImageFileHandler manages visual assets through two key methods:

  • canHandle(): Validates the file against a whitelist of image extensions.
  • read(): Loads the file into a Buffer, converts it to Base64, and returns the data alongside the correct MIME type derived from its own getMimeType() lookup.

This handler ensures that image data travels through the MCP protocol as properly encoded strings with accurate content-type headers.

PdfFileHandler for Document Workflows

The PdfFileHandler in src/utils/files/pdf.ts handles complex document operations:

  • canHandle(): Matches strictly against .pdf extensions.
  • read(): Invokes parsePdfToMarkdown() to extract structured text, returning an object with mimeType: 'application/pdf' plus metadata (author, title, page count).
  • write(): Supports converting Markdown back to PDF via editPdf() or direct creation operations.

This bidirectional conversion capability allows the MCP server to treat PDFs as editable content rather than opaque binaries.

TextFileHandler as the Default Fallback

For any file not matching image or PDF criteria, TextFileHandler from src/utils/files/text.ts provides streaming text access. It respects offset and length arguments for partial reads and consistently returns mimeType: 'text/plain', making it the catch-all handler for code files, logs, and configuration data.

Runtime MIME-Based Dispatch

The integration point occurs in src/handlers/filesystem-handlers.ts, where the system inspects MIME metadata to delegate execution. The handler factory resolves the appropriate implementation based on the detected type.

// src/handlers/filesystem-handlers.ts (excerpt)
const { mimeType, isImage, isPdf } = await getMimeTypeInfo(validPath);
if (isImage) {
  // image preview logic …
} else if (isPdf) {
  // PDF preview / extract logic …
} else {
  // fallback to text handler
}

This routing pattern keeps the command handlers agnostic of format specifics while ensuring that binary files, documents, and text receive appropriate processing logic.

Practical Implementation Examples

Detecting MIME Types Programmatically

To determine the MIME type of an arbitrary file path, import the core utility:

import { getMimeType } from './src/tools/mime-types.js';

const path = '/home/user/photo.png';
console.log(getMimeType(path));   // → "image/png"

Reading Files with Automatic Format Handling

The getFileHandler() factory in src/utils/files/index.ts resolves the correct handler based on MIME type, enabling polymorphic file access:

import { getMimeTypeInfo } from './src/tools/filesystem.js';
import { getFileHandler } from './src/utils/files/index.js';

async function readFile(path: string) {
  const { mimeType } = await getMimeTypeInfo(path);
  const handler = await getFileHandler(mimeType);   // resolves to ImageFileHandler, PdfFileHandler, etc.
  const result = await handler.read(path);
  console.log(`MIME: ${result.mimeType}`);
  console.log(`Content (first 100 chars): ${result.content.slice(0, 100)}`);
}

Writing PDFs from Markdown

The PDF handler supports content generation through its write() method:

import { getFileHandler } from './src/utils/files/index.js';

async function writePdf(pdfPath: string, markdown: string) {
  const pdfHandler = await getFileHandler('application/pdf');
  await pdfHandler.write(pdfPath, markdown);  // converts Markdown → PDF
}

Summary

  • MIME detection relies on extension mapping in src/tools/mime-types.ts, supporting PDFs, standard images, and plain text fallbacks.
  • Consolidated metadata via getMimeTypeInfo() in src/tools/filesystem.ts provides type flags for routing decisions.
  • Handler classes in src/utils/files/ implement format-specific logic: Base64 encoding for images, Markdown conversion for PDFs, and streaming for text.
  • Runtime dispatch in src/handlers/filesystem-handlers.ts uses MIME predicates to delegate to the appropriate handler without hardcoding format logic.
  • Extensibility requires only adding extension mappings and implementing the FileHandler interface, with registration in src/utils/files/index.ts.

Frequently Asked Questions

How does Desktop Commander MCP handle unknown file extensions?

Unknown extensions default to text/plain MIME type and are processed by TextFileHandler, which streams the content as UTF-8 text. This ensures that source code files, configuration files, and logs remain accessible even without explicit format support.

Can the MIME detection system handle uppercase file extensions?

Yes. The getMimeType() function explicitly converts the extracted extension to lowercase using toLowerCase() before matching against the internal maps, ensuring case-insensitive detection for .PDF, .PNG, or .JPG files.

Where is the FileHandler routing logic implemented?

The routing occurs in src/handlers/filesystem-handlers.ts, which calls getMimeTypeInfo() to obtain boolean flags (isImage, isPdf) and then executes conditional logic to invoke the appropriate handler. The actual handler instantiation happens through getFileHandler() in src/utils/files/index.ts.

How are images transmitted through the MCP protocol?

ImageFileHandler.read() loads the binary file into a Node.js Buffer, converts it to Base64 encoding, and returns the string alongside the correct MIME type. This allows image data to pass through JSON-based MCP messages while preserving the ability to render or display the content client-side.

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 →