mcpField
I
Image Processor Mcp

Image Processor Mcp

Local
github.com/pansuriyadhvanilMedia & Design2Updated 22w ago

About Image Processor Mcp

Image Processor MCP is an image-processing server for AI assistants, covering downloads, compression, batch directory processing, filename synchronization, and local OCR.

Key features

  1. 01Download images by URL or Pexels search
  2. 02Compress and convert image formats
  3. 03Batch-process directories with reports
  4. 04Normalize filenames and sync references
  5. 05Extract text with local OCR

Use cases

  1. 01Download and optimize images for a project
  2. 02Convert and resize individual images
  3. 03Compress image folders while preserving structure
  4. 04Extract text from images locally

MCP support

It exposes image download, compression, batch processing, filename synchronization, and OCR tools to MCP clients.

Configuration

Local server config is the same for every client. Copy it into your client’s MCP config file.

mcp.json · Universal config
{
"mcpServers": {
"Image-Processor-MCP": {
"command": "npx",
"args": [
"-y",
"image-processor-mcp"
],
"env": {
"IMAGE_SEARCH_API_KEY": "<IMAGE_SEARCH_API_KEY>"
}
}
}
}
Run commandnpx -y image-processor-mcp
Environment variables to set
IMAGE_SEARCH_API_KEYSecret

Local servers need a runtime on your machine (e.g. Node.js 18+). Config file locations differ by client; see your client’s docs.

Packages
npmimage-processor-mcp

Tools

6

Saved tool list · updated 3w ago

ParameterTypeRequiredDescription
urlstringNoURL of the image to download (required if query not provided)
querystringNoSearch keyword to find an image (required if url not provided)
outputPathstringNoPath where to save the downloaded image
outputFormatstringNoOutput format: webp, avif, jpeg, png, tiff, gif (default: keep original format)
qualitynumberNoCompression quality 1-100 (default: 85)
losslessbooleanNoUse lossless compression (default: false)
effortnumberNoCPU effort 0-6, 6 is slowest with best compression (default: 6)
widthnumberNoExact target width (maintains aspect ratio if only width is specified)
heightnumberNoExact target height (maintains aspect ratio if only height is specified)
maxDimensionnumberNoAuto-resize if width or height exceeds this threshold (default: 2000)
recursiveCompressbooleanNoRe-compress until file is under target size (default: false)
expectedSizeKBnumberNoTarget file size in KB for recursive compression (default: 100)
qualityStepDownnumberNoQuality decrease per recursive iteration (default: 10)
minimumQualityFloornumberNoMinimum quality allowed during recursive compression (default: 10)

Details

From the project README

Image Processor MCP — Complete Documentation

Version: 0.2.3
Package: image-processor-mcp
Author: Dhvanil Pansuriya


Table of Contents

  1. Overview
  2. Installation & Configuration
  3. Tool: download_image
  4. Tool: compress_image
  5. Tool: compress_directory
  6. Tool: sync_filenames
  7. Tool: extract_text
  8. Tool: get_acknowledgement
  9. Configuration Defaults
  10. Supported Formats
  11. Credits & License

Overview

An MCP (Model Context Protocol) server that provides 6 tools for image downloading, compression, batch processing, filename synchronization, OCR text extraction, and configuration discovery.

Quick Start
npx -y image-processor-mcp
Key Features
  • Download images from URLs or search by keyword (Pexels integration)
  • Compress and convert single images with 10 output formats
  • Recursive compression to target file size
  • Lossless and lossy compression with configurable quality and CPU effort
  • Auto-resize oversized images
  • Batch process entire directories preserving folder structure
  • Filename and directory name normalization
  • Auto-generated markdown compression reports
  • Auto-generated filename mappings paired with reports
  • Scan project files and replace old filenames with new ones
  • OCR text extraction (100+ languages, runs 100% locally)

Installation & Configuration

Install from npm
npm install image-processor-mcp
Requirements
  • Node.js 18 or higher
MCP Configuration
Claude Desktop
{
  "mcpServers": {
    "image-processor-mcp": {
      "command": "npx",
      "args": ["-y", "image-processor-mcp"],
      "env": {
        "IMAGE_SEARCH_API_KEY": "your_pexels_api_key_here"
      }
    }
  }
}
VS Code (Cline / MCP extensions)
{
  "mcpServers": {
    "image-processor-mcp": {
      "command": "npx",
      "args": ["-y", "image-processor-mcp"],
      "env": {
        "IMAGE_SEARCH_API_KEY": "your_pexels_api_key_here"
      }
    }
  }
}

IMAGE_SEARCH_API_KEY is optional — only needed for keyword search in download_image. Get a free key at https://www.pexels.com/api/key/.


1. download_image

Downloads an image from a URL or searches by keyword. Optionally compress/convert the image.

Modes
ModeParameterDescription
URL modeurlDirect download from an image URL
Search modequeryKeyword search via Pexels

If both provided, search mode takes priority.

Parameters
ParameterTypeRequiredDefaultDescription
urlstringno*—Direct image URL
querystringno*—Search keyword
outputPathstringyes—Save path
outputFormatstringnooriginalwebp, avif, jpeg, png, tiff, gif
qualitynumberno851–100
losslessbooleannofalseLossless mode
effortnumberno6CPU effort 0–6
widthnumberno—Target width
heightnumberno—Target height
maxDimensionnumberno2000Auto-resize threshold
recursiveCompressbooleannofalseIterative size targeting
expectedSizeKBnumberno100Target KB
qualityStepDownnumberno10Per-iteration decrease
minimumQualityFloornumberno10Minimum quality

* One of url or query is required.

Data Flow
Request → type guard → Controller
  ├─ Search mode? → Pexels API → first hit URL
  └─ URL mode?    → use directly
  ↓
axios.get(url, arraybuffer, 30s timeout)
  ↓
Write to temp file → check compression params
  ├─ YES → ImageService.compressImage → clean temp → return result
  └─ NO  → move to final path → return success
Response Example (search + compression)
{
  "query": "mountain sunset",
  "imageId": 12345,
  "width": 1920,
  "height": 1080,
  "imageSize": 0,
  "user": "John Doe",
  "tags": "mountain sunset",
  "inputPath": "...",
  "outputPath": "./images/mountain.webp",
  "originalSize": 500000,
  "compressedSize": 80000,
  "compressionRatio": 84.00,
  "success": true,
  "iterations": 1,
  "qualitySteps": [85],
  "finalQuality": 85,
  "exceededTarget": false
}
Edge Cases
  • No url or query: Error — must provide one
  • Empty search results: Error — no images found
  • Missing API key: Error — IMAGE_SEARCH_API_KEY not set
  • Download timeout (30s): Error — timeout exceeded
  • Compression fails: Temp file cleaned up, error returned

2. compress_image

Compress or convert a single image with full control over quality, dimensions, format, and recursive compression.

Parameters
ParameterTypeRequiredDefaultDescription
inputPathstringyes—Source image path
outputPathstringyes—Destination path
outputFormatstringnowebpOutput format
qualitynumberno851–100
losslessbooleannofalseLossless mode
effortnumberno6CPU effort 0–6
widthnumberno—Target width
heightnumberno—Target height
maxDimensionnumberno2000Auto-resize threshold
recursiveCompressbooleannofalseIterative targeting
expectedSizeKBnumberno100Target KB
qualityStepDownnumberno10Per-iteration decrease
minimumQualityFloornumberno10Minimum quality
Core Compression Algorithm
1. Read original size + image metadata (sharp)
2. Compute resize:
   - Explicit w/h? → use those
   - Exceeds maxDimension? → scale proportionally
   - Otherwise → no resize
3. Loop:
   - sharp pipeline → apply format with quality
   - If input === output → buffer (safe in-place)
   - Else → write to file
   - If recursive + over target + above floor → reduce quality, loop
   - Else → break
4. Return CompressionResult
Format Conversion
FormatSharp Options
webp{quality, lossless, effort, smartSubsample, alphaQuality:90}
avif{quality, lossless, effort}
jpeg{quality, mozjpeg:true}
png{compressionLevel:9}
tiff{quality, compression:'lzw'}
gifgif() (no options)
otherFalls back to WebP
Response Example
{
  "inputPath": "./input/photo.jpg",
  "outputPath": "./output/photo.webp",
  "originalSize": 500000,
  "compressedSize": 80000,
  "compressionRatio": 84.00,
  "success": true,
  "iterations": 1,
  "qualitySteps": [85],
  "finalQuality": 85,
  "exceededTarget": false
}
Edge Cases
  • In-place compression (same path): Buffer-based to avoid corruption
  • Missing input file: success: false with error
  • Unknown format: Falls back to WebP
  • Recursion floor: Stops when quality can't decrease further
  • Abort: Returns partial result with success: false

3. compress_directory

Batch compress all images in a directory recursively, preserving folder structure. Generates report + mappings.

Parameters
ParameterTypeRequiredDefaultDescription
inputDirstringyes—Source directory
outputDirstringyes—Output directory
outputFormatstringnowebpOutput format
qualitynumberno851–100
losslessbooleannofalseLossless mode
effortnumberno6CPU effort 0–6
maxDimensionnumberno2000Auto-resize threshold
normalizeFilenamebooleannofalseClean filenames
filenameReplaceCharsstringno , -, ., &Replace chars
filenameCasestringnolowercaseCase conversion
normalizeDirnamebooleannofalseClean dir names
dirnameReplaceCharsstringno , -, ., &Dir replace chars
dirnameCasestringnolowercaseDir case
recursiveCompressbooleannofalseIterative targeting
expectedSizeKBnumberno100Target KB
qualityStepDownnumberno5 (schema) / 10 (code)Per-iteration decrease
minimumQualityFloornumberno10Minimum quality
Data Flow
Request → type guard → Controller
  ├─ Validate input directory exists
  ├─ Apply defaults, build FileNamingOptions
  ├─ Scan all image files (recursive)
  ├─ Filter out SVG (restricted)
  ├─ For each file:
  │   ├─ Compute output path (preserves structure, normalizes, changes ext)
  │   └─ Run ImageService.compressImage
  ├─ Generate report (.image-processor-mcp/reports/)
  └─ Generate mappings JSON (.image-processor-mcp/mappings/)
Output Path Algorithm
relativePath = inputDir → inputFile difference

1. Dir naming enabled → normalize each directory component
2. File naming enabled → normalize basename
3. Replace extension with .{outputFormat}
4. Prepend outputDir
normalizeName
Replace each char → '_', collapse multiple '_', trim edges, apply case
Generated Files
.image-processor-mcp/
├── reports/scan-report-{timestamp}.md
└── mappings/mappings-{timestamp}.json
Response Example
{
  "success": true,
  "totalFiles": 10,
  "successful": 9,
  "failed": 1,
  "totalOriginalSize": 5000000,
  "totalCompressedSize": 1200000,
  "overallReduction": 76.00,
  "durationMs": 5432,
  "reportPath": ".image-processor-mcp/reports/scan-report-2026-05-29-15-30-00.md",
  "mappingsPath": ".image-processor-mcp/mappings/mappings-2026-05-29-15-30-00.json"
}
Edge Cases
  • Input dir not found: Early error, no files written
  • SVG files: Silently excluded
  • Abort mid-batch: Partial results processed
  • All files fail: No mappings file generated
  • No images found: Empty report

4. sync_filenames

Scan project files and replace all references to old filenames with new filenames after compression.

Parameters
ParameterTypeRequiredDefaultDescription
scanDirstringyes—Directory to scan
mappingFilePathstringno—Path to mappings JSON file
mappingsarrayno—Inline {oldFileName, newFileName}[]
includeExtensionsarraynohtml,js,ts,css,md,json...Extensions to scan
excludeDirectoriesarraynonode_modules,.git,build,dist...Dirs to skip
dryRunbooleannotruePreview only
Validation

When using mappingFilePath:

  1. File exists + valid JSON
  2. Mappings array present and non-empty
  3. Each entry has oldFileName and newFileName (strings)
  4. Timestamp extracted from filename mappings-(.+).json
  5. Matching report must exist: reports/scan-report-{timestamp}.md

If the matching report is missing → operation rejected (prevents stale mappings).

Data Flow
Request → type guard → Controller
  ├─ mappingFilePath?
  │   YES → ReferenceService.readMappingFile → validate against report
  │   NO  → use inline mappings
  ├─ dryRun = args.dryRun !== false
  ├─ ReferenceService.scanReferences:
  │   ├─ Collect files recursively (filtered by extension, excluding dirs)
  │   ├─ For each file:
  │   │   ├─ For each mapping:
  │   │   │   ├─ Regex-escape oldFileName, count occurrences
  │   │   │   ├─ Build line-by-line details
  │   │   │   ├─ Build preview (3 lines context)
  │   │   │   └─ If !dryRun: replace in content
  │   │   └─ If modified: write file
  │   └─ Return UpdateRefResult
  └─ ReportService.generateSyncReport → .image-processor-mcp/syncs/
Generated Files
.image-processor-mcp/syncs/sync-report-{timestamp}.md           (live)
.image-processor-mcp/syncs/dry-run/sync-report-{timestamp}.md   (dry-run)
Response Example
Dry run — no files were modified.

Mapping source: .image-processor-mcp/mappings/mappings-2026-05-29-15-30-00.json
Files scanned: 42
Files with matches: 3
Total replacements: 12

--- Matches ---

[src/components/Header.tsx]
  "logo.png" → "logo.webp" (5x)
  Preview: ... context lines ...
  Line 15:23  "logo.png" → "logo.webp"
  ... and 3 more (see report)

Report saved to: .image-processor-mcp/syncs/dry-run/sync-report-2026-05-29-15-31-00.md
Edge Cases
  • Mapping file not found: Error with path
  • Invalid JSON: Parse error
  • No matching report: Detailed rejection message
  • Neither source provided: Error explaining options
  • No matches found: Informational message
  • Regex special chars: Properly escaped
  • Binary files: Filtered by extension list

5. extract_text

Extract visible printed text from images using OCR (tesseract.js). Runs entirely locally.

Parameters
ParameterTypeRequiredDefaultDescription
imagePathstringyes—Path to image file
languagestringnoengLanguage code (use + for multiple)
rectangleobjectno—Region {top, left, width, height}
outputFormatenumnotexttext, blocks, hocr, tsv
preprocessbooleannotrueGrayscale + auto-rotate
Data Flow
Request → type guard → OcrController → OcrService.recognize
  ├─ Validate path (exists, not dir, not empty, not SVG)
  ├─ Validate rectangle (positive dimensions)
  ├─ Build sharp pipeline:
  │   ├─ Convert unsupported formats to PNG
  │   └─ Preprocess: grayscale + rotate
  ├─ runOcr:
  │   ├─ Serialized via jobQueue (one at a time)
  │   ├─ getWorker: reuse / reinitialize / create
  │   ├─ worker.recognize()
  │   └─ Recycle worker every 500 jobs
  └─ Return ExtractTextResult
Worker Lifecycle
StateAction
Worker exists, same languageReuse directly
Worker exists, different languageworker.reinitialize(language)
No workercreateWorker(language, 1, ...)
After 500 jobssetImmediate(recycleWorker)
Worker errorerrorHandler nulls out reference
SIGINT / transport closeshutdown() → terminate
Supported Input Formats
Natively supportedAuto-converted to PNG
bmp, jpg, jpeg, pngtiff, heic, heif, webp*, gif*
pbm, pgm, ppmand all others

* webp and gif ARE natively supported by tesseract.js, despite the conversion check. The code converts any extension NOT in OCR_SUPPORTED_EXTENSIONS. Since webp and gif are in that list, they are NOT converted.

Limitations
  • Handwritten text: NOT supported
  • SVG files: Rejected (vector format)
  • Empty images: Return empty string (not an error)
  • First run: Downloads language data (~2MB) from CDN
Response Example (text format)
{
  "success": true,
  "text": "Extracted text content",
  "confidence": 92.5,
  "words": 42,
  "language": "eng",
  "durationMs": 1234,
  "preprocessed": true
}
Edge Cases
  • SVG: Explicit rejection
  • Unsupported format: Auto-converted to PNG
  • Worker crash: Auto-recovery (errorHandler nulls out)
  • Abort: DOMException caught → cancelled result
  • Empty file (0 bytes): Explicit rejection
  • Path is directory: Explicit rejection

6. get_acknowledgement

Returns comprehensive documentation of all tools, defaults, formats, and environment variables.

Parameters

None — empty input schema.

Response

A full markdown document built dynamically from all configuration constants:

SectionSource
All 6 toolsHardcoded descriptions
Configuration defaultsDEFAULTS + CONFIG_DESCRIPTIONS
Supported input formatsSUPPORTED_EXTENSIONS + INPUT_EXTENSION_DESCRIPTIONS
Supported output formatsSUPPORTED_OUTPUT_FORMATS + OUTPUT_FORMAT_DESCRIPTIONS
Sync scan defaultsDEFAULT_EXTENSIONS + DEFAULT_EXCLUDE_DIRS
Restricted extensionsRESTRICTED_EXTENSIONS
Environment variablesHardcoded
CreditsHardcoded
Implementation
ToolController.handleGetAcknowledgement()
  // Synchronous — no abort signal, no async
  // Returns { content: [{ type: 'text', text: markdown }] }
Edge Cases

None — always succeeds, no parameters, no I/O.


Configuration Defaults

ParameterDefaultDescription
quality85Compression quality for lossy formats (1–100)
losslessfalseLossless compression (WebP, PNG, GIF, AVIF)
effort6CPU effort (0–6). Higher = smaller files
maxDimension2000Auto-resize threshold in pixels
expectedSizeKB100Target file size for recursive compression
qualityStepDown10Quality decrease per recursive iteration
minimumQualityFloor10Minimum quality (1–100) during recursion
outputFormatwebpDefault output format
filenameCaselowercaseFilename case conversion
dirnameCaselowercaseDirectory name case conversion
filenameReplaceChars[' ', '-', '.', '&']Characters replaced with _ in filenames
dirnameReplaceChars[' ', '-', '.', '&']Characters replaced with _ in dir names

Supported Formats

Input Formats (35+)

.jpg, .jpeg, .png, .gif, .bmp, .tiff, .tif, .webp, .avif, .svg, .heic, .heif, .ico, .cur, .jp2, .j2k, .jpf, .jpx, .jpm, .mj2, .jxr, .wdp, .hdp, .psd, .psb, .dds, .tga, .vda, .icb, .vst, .pbm, .pgm, .ppm, .pnm, .pfm, .exr, .hdr, .hrd, .pic, .pict, .pct, .xbm, .xpm, .wal, .cut, .ras, .sun, .sgi, .rgb, .rgba, .bw, .pcx, .pcd, .iff, .lbm

Output Formats (10)
FormatDescription
webpGoogle WebP. Excellent lossy/lossless. Supports transparency.
avifAV1-based. 30–50% smaller than JPEG. Slower encoding.
jpegUniversal compatibility. No transparency.
pngLossless with transparency. Best for graphics/logos.
tiffHigh-quality. Print/publishing. Largest sizes.
gifAnimation + transparency. 256 colors.
heifHEVC-based. Apple ecosystem.
jp2JPEG 2000. Wavelet-based. Medical/ cinema.
jxlJPEG XL. Next-gen. Lossless JPEG re-encoding.
pdfConvert images to PDF pages.
Restricted Extensions

.svg — SVG files are skipped during batch compression (vector format — sharp cannot safely compress without breaking rendering).


Credits & License

Author

Dhvanil Pansuriya

GitHubhttps://github.com/pansuriyadhvanil/
LinkedInhttps://linkedin.com/in/dhvanil-pansuriya/
Packageimage-processor-mcp on npm
Technology Credits
TechnologyRole
Model Context Protocol SDKMCP server framework
sharpHigh-performance image processing
tesseract.jsOCR text extraction — 100% local, no API key
PexelsFree stock photo API for image search
axiosHTTP client
fs-extraExtended file system
License

MIT License — See LICENSE for details.

Image-Processor-MCP

Comments

Markdown supported

New to MCP?

From what the protocol is to installing your first server, these answers cover most first questions.

An open protocol that defines how AI applications connect to external tools and data in a uniform way. Clients talk to the model; MCP servers provide tools, resources and prompt templates. They exchange standard messages, so one server can be reused by many clients.