Skip to main content
Glama

squoosh-mcp

An MCP server that lets AI agents optimise images the way an expert would. It handles a whole folder at once, deciding format, size and quality separately for each image.

It uses the codecs and settings from Squoosh: WebP by default, plus AVIF, MozJPEG, OxiPNG and libimagequant on request. Each image gets the smallest file that still meets a visual-quality score, SSIMULACRA 2, so you aren't guessing a quality number.

Unofficial. Not affiliated with or endorsed by Google or the Squoosh team.

Why

squoosh.app gives great results, but you do one image at a time, by hand, in a browser. Squoosh's batch tools apply one setting to every image, which doesn't suit a mix of photos, screenshots, logos and odd aspect ratios. squoosh-mcp lets your agent do what you would do by hand, for every image:

For each image it…

How

Works out what it is

Photo, screenshot, graphic, icon or animation, from colour count, flat areas and edges

Tries the encodings that suit it

Photos: lossy WebP. Screenshots and graphics: lossless, palette or lossy WebP, whichever is smallest. Add AVIF with policy: "avif"

Finds the lowest quality that still looks right

Searches quality until the SSIMULACRA 2 score meets the target, usually in 3–6 encodes

Sizes it for the web

Fits a box, crops to a shape, or makes srcset widths, keeping each image's own aspect ratio and never upscaling

Never makes things worse

Keeps the original when nothing beats it; never touches your source files

Gives you the HTML

<picture>/<img> markup with srcset, width/height and lazy loading

Measured on 12 phone photos (1792×2400 PNG, 81 MB in total), Apple Silicon Mac. Every image scored 75–77 against a target of 75, and at 100% zoom they're hard to tell apart from the originals.

Policy

Output

Smaller by

Time

Works in

auto (default): WebP

5.0 MB

93.8%

14 s

Every current browser (Safari 14+, iOS 14+)

avif: AVIF or WebP

3.4 MB

95.8%

27 s

Safari 16.4+ and other current browsers

Related MCP server: obrobka-mcp

Install

You need Node.js 22.17 or newer. Give the server the folders it may read and write. It refuses everything else.

Claude Code

claude mcp add squoosh -- npx -y squoosh-mcp /absolute/path/to/images

Inside a project, you can leave the path out. The server then uses the project folder (CLAUDE_PROJECT_DIR), but never your home folder or a filesystem root.

Claude Desktop

Settings → Developer → Edit Config (claude_desktop_config.json):

{
  "mcpServers": {
    "squoosh": {
      "command": "npx",
      "args": ["-y", "squoosh-mcp", "/Users/you/Pictures/site-images"]
    }
  }
}

Cursor

.cursor/mcp.json in the project, or ~/.cursor/mcp.json:

{
  "mcpServers": {
    "squoosh": {
      "command": "npx",
      "args": ["-y", "squoosh-mcp", "${workspaceFolder}"]
    }
  }
}

VS Code

.vscode/mcp.json (note the servers key):

{
  "servers": {
    "squoosh": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "squoosh-mcp", "."]
    }
  }
}

Codex CLI

codex mcp add squoosh -- npx -y squoosh-mcp /absolute/path/to/images

The first npx download can take longer than Codex's default 10 s start-up limit. Raise it in ~/.codex/config.toml:

[mcp_servers.squoosh]
command = "npx"
args = ["-y", "squoosh-mcp", "/absolute/path/to/images"]
startup_timeout_sec = 30

Windsurf / Devin Desktop

Same shape as Claude Desktop, in ~/.codeium/windsurf/mcp_config.json (Windsurf) or ~/.config/devin/mcp_config.json (Devin Desktop).

Use

Ask your agent in plain words:

  • "Optimise every image in public/images for the web."

  • "Make the hero image responsive with srcset, and load it first."

  • "Turn these product photos into 400×400 thumbnails."

  • "Compress the screenshots in docs/ losslessly."

  • "What would you do with assets/? Don't write anything yet."

The agent calls these tools:

Tool

What it does

analyze_images

Lists images with size, dimensions, transparency and animation. With deep, it also classifies each one and shows the plan

optimize_images

Optimises files, folders or globs. Top-level settings apply to all; files[] overrides them per image. dryRun shows the plan without writing

get_job

Waits on and pages through a long batch. Calls return after 45 s with a jobId and keep working

cancel_job

Stops a batch. Finished images stay and are skipped on the next run

compare_images

Scores an output against its original, with optional thumbnails

Settings, at the top level or per file:

Setting

Values

Default

policy

auto (WebP: lossy, lossless or palette, whichever is smallest) · avif (AVIF or WebP, whichever is smaller) · keep (same format as the source) · picture (AVIF/WebP plus a JPEG/PNG fallback for <picture>)

auto

target

small · balanced · high · lossless-look · a number 30–100 (100 = lossless)

balanced

resize

{ maxWidth, maxHeight }: fit inside, never upscale

none

crop

{ width, height, strategy: attention | entropy | center }

none

widths

"auto" (640/960/1280/1920/2560 up to the image's width) or a list

none

priority

true for above-the-fold images (eager loading, fetchpriority="high")

false

metadata

strip (removes EXIF/GPS after auto-rotating) · all

strip

The balanced preset targets 75 for photos and 85 for screenshots, graphics and icons. The metric is tuned on photos and doesn't weigh faint 1-pixel UI lines heavily enough, so flat content gets a higher target.

Output

New files go to an optimized/ folder inside each input folder, mirroring its subfolders; you can set outputDir instead. Originals are never modified.

images/
  hero.jpg
  logo.png
  optimized/
    hero-1920w.webp  hero-1280w.webp  hero-640w.webp
    logo.webp
    squoosh-manifest.json   ← every output, its score, and ready-to-paste markup

Re-running skips images whose source and settings haven't changed. If a run is interrupted, the next run picks up where it stopped.

Supported formats

Input

Output

JPEG, PNG, WebP, AVIF, GIF (incl. animated), TIFF

WebP (lossy, lossless, palette) by default; AVIF, JPEG (MozJPEG) and PNG (OxiPNG, palette) by policy

Not supported yet: HEIC, SVG, BMP and ICO are skipped with a reason. Animated PNG is left as it is.

Configuration

Environment variable

Default

Meaning

SQUOOSH_MCP_CONCURRENCY

min(4, cores ÷ 2)

Images processed in parallel (about 450 MB each for 4 MP images)

SQUOOSH_MCP_INLINE_SECONDS

45

How long optimize_images works before handing back a jobId

How it differs from Squoosh

squoosh-mcp runs Squoosh's codecs through sharp (libvips) with Squoosh's settings, plus OxiPNG. That makes it fast and native rather than browser WASM. Libraries can differ in version from squoosh.app's frozen 2024 build, so outputs are close to squoosh.app's but not byte-identical. The quality score is fast-ssim2, compiled to WebAssembly.

Development

npm install
npm run build        # TypeScript → dist/, plus the prebuilt SSIMULACRA 2 WASM
npm test             # unit and end-to-end tests (in-memory MCP client)
npm run fixtures     # edge-case test images → test/fixtures/generated/
npm run inspector    # try the tools in the MCP Inspector

See CONTRIBUTING.md.

License

Apache-2.0. Third-party components: THIRD_PARTY_NOTICES.md.

Available Tools

5 tools
analyze_imagesAnalyse imagesA
Read-only

Scan files, folders or globs and report what is there: format, size, dimensions, transparency, animation. With deep: true, also classify each image (photo, screenshot, graphic, icon, animated) and show the plan optimize_images would follow (candidate formats, sizes, quality target, output path). Read-only. Paged: use offset/nextOffset. Allowed directories: (none configured).

Inputs: paths (required), crop, deep, limit, +8 more.

cancel_jobCancel jobA
Idempotent

Stop an optimize_images job. Images already written stay, and are recorded in the manifest so a re-run skips them.

Inputs: jobId (required).

compare_imagesCompare imagesA
Read-only

Visual similarity of an optimised image to its original, as a SSIMULACRA 2 score (100 = identical; 90+ visually lossless; 80+ very high; 70+ high; below 50 visibly degraded), plus both sizes. Use it to check results. Read-only.

Inputs: original (required), candidate (required), preview.

get_jobGet job statusA
Read-only

Progress and results of an optimize_images job. Waits up to waitSeconds for it to finish. Results are paged (offset/nextOffset). Jobs are kept in memory for an hour after they finish, until the server stops.

Inputs: jobId (required), limit, offset, waitSeconds, +1 more.

optimize_imagesOptimise imagesA
Idempotent

Optimise images like an expert, deciding per image. Default policy "auto" writes WebP, which every current browser supports: lossy for photos, lossless or palette for screenshots and graphics, whichever is smallest at the visual target. policy "avif" also tries AVIF (smaller, needs Safari 16.4+); "picture" adds a JPEG/PNG fallback; "keep" keeps the source format. Resizing fits each image's own aspect ratio and never upscales; widths makes srcset sizes; crop makes exact shapes. Writes NEW files to "/optimized/" (or outputDir), never touching originals; re-runs skip unchanged files. Works up to 45s, then returns status "running" with a jobId: call get_job to wait for the rest. Use dryRun: true to preview decisions without encoding. Allowed directories: (none configured).

Inputs: crop, files, limit, paths, +11 more.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A4.2/5.0

    Scored across 5 tools

    Disambiguation5/5

    Each tool has a clearly distinct role: read-only inspection (analyze_images), mutation (optimize_images), async job control (get_job, cancel_job), and quality verification (compare_images). The get_job/cancel_job pair targets the same job resource but differs cleanly by action (wait/read vs stop). No plausible misselection risk.

    Naming Consistency5/5

    All five tools follow a consistent snake_case verb_noun pattern: analyze_images, optimize_images, get_job, cancel_job, compare_images. Even the resource-oriented job tools fit the same verb-first convention, with no style mixing.

    Tool Count5/5

    Five tools is well-scoped for an image optimization server: inspection, encoding, and verification are all explicit, and get_job/cancel_job exist because optimize_images can return a long-running jobId. Nothing feels padded or missing.

    Completeness4/5

    The analyze → optimize → verify → manage-job lifecycle is covered, including dryRun preview, per-policy formats, resize/srcset/crop, and SSIMULACRA 2 checking. Minor gaps: no tool to list/discover outstanding jobs (a jobId is only obtainable from a running optimize call) and no way to clean up or roll back written outputs.

    Maintenance

    ActivityMaintained
    ResponsivenessOutdated data

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      B
      maintenance
      Enables AI agents to process images locally via file paths—converting, resizing, removing backgrounds, smart cropping, upscaling, reading or stripping metadata, and batch processing—without files ever leaving the device.
      MIT
    • A
      license
      Not graded
      quality
      B
      maintenance
      Enables AI agents to run real image and PDF processing remotely — compressing, converting, resizing, cropping, watermarking, and chaining multiple operations in a single call — with no local install and zero-retention handling.
      9
      MIT
    • A
      license
      B
      quality
      C
      maintenance
      Enables AI agents to drive a full photo-editing engine through validated, non-destructive operations — exposure and colour grading, effects, geometry, text/watermarks, style matching from a reference image, natural-language looks, and batch processing over folders. Originals stay untouched, edits live in an open JSON project format, and everything runs locally without network access unless opted in.
      27
      Apache 2.0