image-processor-mcp 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,30 @@
1
+ name: CI/CD Pipeline
2
+
3
+ on:
4
+ push:
5
+ branches: [ main ]
6
+ pull_request:
7
+ branches: [ main ]
8
+
9
+ jobs:
10
+ build-and-test:
11
+ runs-on: ubuntu-latest
12
+
13
+ steps:
14
+ - name: Checkout Code
15
+ uses: actions/checkout@v4
16
+
17
+ - name: Setup Node.js
18
+ uses: actions/setup-node@v4
19
+ with:
20
+ node-version: '20'
21
+ cache: 'npm'
22
+
23
+ - name: Install Dependencies
24
+ run: npm ci
25
+
26
+ - name: Lint Code
27
+ run: npm run lint
28
+
29
+ - name: Build Project
30
+ run: npm run build
@@ -0,0 +1,34 @@
1
+ name: Publish to NPM
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - 'v*'
7
+
8
+ jobs:
9
+ publish:
10
+ runs-on: ubuntu-latest
11
+ permissions:
12
+ contents: read
13
+ id-token: write
14
+
15
+ steps:
16
+ - name: Checkout Code
17
+ uses: actions/checkout@v4
18
+
19
+ - name: Setup Node.js
20
+ uses: actions/setup-node@v4
21
+ with:
22
+ node-version: '20'
23
+ registry-url: 'https://registry.npmjs.org'
24
+
25
+ - name: Install Dependencies
26
+ run: npm install
27
+
28
+ - name: Build Project
29
+ run: npm run build
30
+
31
+ - name: Publish to NPM
32
+ run: npm publish --access public
33
+ env:
34
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Dhvanil Pansuriya
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,73 @@
1
+ # Automated NPM Publishing Workflow
2
+
3
+ This guide explains how to publish new versions of this MCP server to the NPM registry using GitHub Actions.
4
+
5
+ ## Prerequisites
6
+
7
+ ### Option A: Granular Access Token (Recommended for simplicity)
8
+
9
+ 1. **Generate Token**:
10
+ - Login to [npmjs.com](https://www.npmjs.com/).
11
+ - Navigate to **Access Tokens** > **Generate New Token** > **Granular Access Token**.
12
+ - **Name**: `GitHub-Actions-Image-Processor-MCP`.
13
+ - **Expiration**: Set as needed (e.g., 365 days).
14
+ - **Permissions**:
15
+ - **Read and Write** for the specific package.
16
+ - **Bypass 2FA**: Check this if your account has 2FA enabled, otherwise the automated workflow will fail.
17
+ - Copy the generated token.
18
+
19
+ 2. **Add GitHub Secret**:
20
+ - Go to your GitHub repository.
21
+ - Navigate to **Settings** > **Secrets and variables** > **Actions**.
22
+ - Click **New repository secret**.
23
+ - **Name**: `NPM_TOKEN`
24
+ - **Value**: Paste the token from NPM.
25
+
26
+ ### Option B: Trusted Publishing (OIDC) - More Secure
27
+
28
+ 1. **Configure NPM**:
29
+ - In your NPM package settings, navigate to **Publishing** > **Trusted Publishing**.
30
+ - Add a new GitHub Actions publisher.
31
+ - Provide your repository name.
32
+
33
+ 2. **Workflow Permissions**:
34
+ The `.github/workflows/publish.yml` already has:
35
+ ```yaml
36
+ permissions:
37
+ id-token: write
38
+ contents: read
39
+ ```
40
+
41
+ ---
42
+
43
+ ## How to Release a New Version
44
+
45
+ The workflow triggers automatically when you push a new version tag (starting with `v`).
46
+
47
+ ### 1. Update Version
48
+ Update the `version` field in your `package.json`.
49
+
50
+ ### 2. Commit and Push
51
+ ```bash
52
+ git add package.json
53
+ git commit -m "chore: bump version to 0.1.1"
54
+ git push origin main
55
+ ```
56
+
57
+ ### 3. Create and Push a Version Tag
58
+ ```bash
59
+ git tag v0.1.1
60
+ git push origin v0.1.1
61
+ ```
62
+
63
+ ---
64
+
65
+ ## What Happens Behind the Scenes?
66
+
67
+ 1. GitHub Actions detects the new tag `v*`.
68
+ 2. A fresh Ubuntu runner is provisioned.
69
+ 3. The project is built using `npm run build`.
70
+ 4. The package is published to NPM using `NPM_TOKEN`.
71
+ 5. You will receive an email from NPM once the publish is successful.
72
+
73
+ You can monitor progress in the **Actions** tab of your GitHub repository.
package/README.md ADDED
@@ -0,0 +1,81 @@
1
+ # MCP Image Downloader
2
+
3
+ An MCP server that provides tools for downloading, compressing, and optimizing images. Built using the Model Context Protocol (MCP), this server enables AI assistants to download images from URLs, compress and convert images with various format options, and batch process entire directories with auto-generated reports.
4
+
5
+ ## Features
6
+
7
+ - Download images from URLs with proper error handling
8
+ - Compress and convert single images with multiple output formats (WebP, AVIF, JPEG, PNG, TIFF, GIF, HEIF, JPEG 2000, JPEG XL, PDF)
9
+ - Recursive compression to target file size
10
+ - Lossless and lossy compression with configurable quality and CPU effort
11
+ - Auto-resize oversized images
12
+ - Batch process entire directories preserving folder structure
13
+ - Filename and directory name normalization (replace chars, case conversion)
14
+ - Auto-generated markdown compression reports with file tree, per-file details, and input vs output comparison
15
+
16
+ ## Available Tools
17
+
18
+ #### download_image
19
+ Downloads an image from a URL to a specified path.
20
+
21
+ Parameters:
22
+ - `url` (required): URL of the image to download
23
+ - `outputPath` (required): Path where to save the image
24
+
25
+ #### compress_image
26
+ Compresses or converts a single image with format conversion, quality adjustment, resizing, and optional recursive compression.
27
+
28
+ Parameters:
29
+ - `inputPath` (required): Path to the input image
30
+ - `outputPath` (required): Path to save the compressed image
31
+ - `outputFormat` (optional): Output format - webp, avif, jpeg, png, tiff, gif, heif, jp2, jxl, pdf (default: webp)
32
+ - `quality` (optional): Compression quality 1-100 (default: 85)
33
+ - `lossless` (optional): Use lossless compression (default: false)
34
+ - `effort` (optional): CPU effort 0-6 (default: 6)
35
+ - `width` (optional): Exact target width
36
+ - `height` (optional): Exact target height
37
+ - `maxDimension` (optional): Auto-resize threshold in pixels (default: 2000)
38
+ - `recursiveCompress` (optional): Re-compress until under target size (default: false)
39
+ - `expectedSizeKB` (optional): Target file size in KB (default: 100)
40
+ - `qualityStepDown` (optional): Quality decrease per iteration (default: 5)
41
+ - `minimumQualityFloor` (optional): Minimum quality allowed (default: 10)
42
+
43
+ #### compress_directory
44
+ Batch compresses all images in a directory recursively, preserving folder structure, with an auto-generated report.
45
+
46
+ Parameters:
47
+ - `inputDir` (required): Input directory containing images
48
+ - `outputDir` (required): Output directory for compressed images
49
+ - `outputFormat` (optional): Output format (default: webp)
50
+ - `quality` (optional): Compression quality 1-100 (default: 85)
51
+ - `lossless` (optional): Use lossless compression (default: false)
52
+ - `effort` (optional): CPU effort 0-6 (default: 6)
53
+ - `maxDimension` (optional): Auto-resize threshold (default: 2000)
54
+ - `normalizeFilename` (optional): Enable filename normalization
55
+ - `filenameReplaceChars` (optional): Characters to replace with underscore (comma-separated)
56
+ - `filenameCase` (optional): Filename case - lowercase, uppercase, original
57
+ - `normalizeDirname` (optional): Enable directory name normalization
58
+ - `dirnameReplaceChars` (optional): Characters to replace in directory names (comma-separated)
59
+ - `dirnameCase` (optional): Directory name case
60
+ - `recursiveCompress` (optional): Re-compress oversized outputs
61
+ - `expectedSizeKB` (optional): Target file size in KB (default: 100)
62
+ - `qualityStepDown` (optional): Quality decrease per iteration (default: 5)
63
+ - `minimumQualityFloor` (optional): Minimum quality floor (default: 10)
64
+
65
+ #### get_acknowledgement
66
+ Returns all configuration defaults, supported input/output formats with descriptions, and detailed parameter explanations for every tool.
67
+
68
+ Parameters: None
69
+
70
+ ## Requirements
71
+
72
+ - Node.js 16 or higher
73
+ - NPM or compatible package manager
74
+
75
+ ## License
76
+
77
+ MIT License - see the [LICENSE](LICENSE) file for details.
78
+
79
+ ## Author
80
+
81
+ Dhvanil Pansuriya
@@ -0,0 +1,4 @@
1
+ export declare const APP_CONFIG: {
2
+ name: string;
3
+ version: string;
4
+ };
@@ -0,0 +1,4 @@
1
+ export const APP_CONFIG = {
2
+ name: 'image-processor-mcp',
3
+ version: '0.1.0',
4
+ };
@@ -0,0 +1,24 @@
1
+ export declare const DEFAULTS: {
2
+ quality: number;
3
+ lossless: boolean;
4
+ effort: number;
5
+ maxDimension: number;
6
+ expectedSizeKB: number;
7
+ qualityStepDown: number;
8
+ minimumQualityFloor: number;
9
+ outputFormat: string;
10
+ filenameCase: "lowercase";
11
+ dirnameCase: "lowercase";
12
+ filenameReplaceChars: string[];
13
+ dirnameReplaceChars: string[];
14
+ };
15
+ export declare const SUPPORTED_EXTENSIONS: string[];
16
+ export declare const SUPPORTED_OUTPUT_FORMATS: string[];
17
+ export interface ConfigDescription {
18
+ name: string;
19
+ default: string | number | boolean | string[];
20
+ description: string;
21
+ }
22
+ export declare const CONFIG_DESCRIPTIONS: ConfigDescription[];
23
+ export declare const INPUT_EXTENSION_DESCRIPTIONS: Record<string, string>;
24
+ export declare const OUTPUT_FORMAT_DESCRIPTIONS: Record<string, string>;
@@ -0,0 +1,170 @@
1
+ export const DEFAULTS = {
2
+ quality: 85,
3
+ lossless: false,
4
+ effort: 6,
5
+ maxDimension: 2000,
6
+ expectedSizeKB: 100,
7
+ qualityStepDown: 5,
8
+ minimumQualityFloor: 10,
9
+ outputFormat: 'webp',
10
+ filenameCase: 'lowercase',
11
+ dirnameCase: 'lowercase',
12
+ filenameReplaceChars: [' ', '-', '.', '&'],
13
+ dirnameReplaceChars: [' ', '-', '.', '&'],
14
+ };
15
+ export const SUPPORTED_EXTENSIONS = [
16
+ '.jpg', '.jpeg', '.png', '.gif', '.bmp', '.tiff', '.tif',
17
+ '.webp', '.avif', '.svg', '.heic', '.heif', '.ico', '.cur',
18
+ '.jp2', '.j2k', '.jpf', '.jpx', '.jpm', '.mj2',
19
+ '.jxr', '.wdp', '.hdp',
20
+ '.psd', '.psb',
21
+ '.dds',
22
+ '.tga', '.vda', '.icb', '.vst',
23
+ '.pbm', '.pgm', '.ppm', '.pnm', '.pfm',
24
+ '.exr',
25
+ '.hdr', '.hrd',
26
+ '.pic', '.pict', '.pct',
27
+ '.xbm', '.xpm',
28
+ '.wal',
29
+ '.cut',
30
+ '.ras', '.sun',
31
+ '.sgi', '.rgb', '.rgba', '.bw',
32
+ '.pcx',
33
+ '.pcd',
34
+ '.iff', '.lbm',
35
+ ];
36
+ export const SUPPORTED_OUTPUT_FORMATS = [
37
+ 'webp', 'avif', 'jpeg', 'png', 'tiff', 'gif',
38
+ 'heif', 'jp2', 'jxl', 'pdf',
39
+ ];
40
+ export const CONFIG_DESCRIPTIONS = [
41
+ {
42
+ name: 'quality',
43
+ default: DEFAULTS.quality,
44
+ description: 'Compression quality level for lossy formats (1-100). Higher values preserve more detail but produce larger files. Used for JPEG, WebP, AVIF, and HEIF output.',
45
+ },
46
+ {
47
+ name: 'lossless',
48
+ default: DEFAULTS.lossless,
49
+ description: 'When true, uses lossless compression. File sizes will be larger but pixel data is preserved exactly. Supported for WebP, PNG, GIF, and AVIF formats.',
50
+ },
51
+ {
52
+ name: 'effort',
53
+ default: DEFAULTS.effort,
54
+ description: 'CPU effort level (0-6). Higher values produce better compression ratios but take significantly longer to process. Level 6 gives the smallest file size.',
55
+ },
56
+ {
57
+ name: 'maxDimension',
58
+ default: DEFAULTS.maxDimension,
59
+ description: 'Maximum width or height in pixels. Images exceeding this threshold are automatically resized down to fit while maintaining aspect ratio. Set to a high value to effectively disable.',
60
+ },
61
+ {
62
+ name: 'expectedSizeKB',
63
+ default: DEFAULTS.expectedSizeKB,
64
+ description: 'Target file size in KB for recursive compression. If the compressed output exceeds this size, quality is reduced iteratively until the target is met or minimumQualityFloor is reached.',
65
+ },
66
+ {
67
+ name: 'qualityStepDown',
68
+ default: DEFAULTS.qualityStepDown,
69
+ description: 'Amount to reduce quality by in each recursive compression iteration. Larger values reach target size faster but risk visible quality degradation.',
70
+ },
71
+ {
72
+ name: 'minimumQualityFloor',
73
+ default: DEFAULTS.minimumQualityFloor,
74
+ description: 'Lowest quality value (1-100) allowed during recursive compression. Prevents excessive degradation even if the target file size is not reached.',
75
+ },
76
+ {
77
+ name: 'outputFormat',
78
+ default: DEFAULTS.outputFormat,
79
+ description: 'Default output image format. WebP offers excellent compression with good quality. AVIF gives better compression but slower encoding. JPEG offers universal compatibility.',
80
+ },
81
+ {
82
+ name: 'filenameCase',
83
+ default: DEFAULTS.filenameCase,
84
+ description: 'Case conversion applied to filenames when normalization is enabled. lowercase converts all to lower, uppercase converts all to UPPER, original leaves them as-is.',
85
+ },
86
+ {
87
+ name: 'dirnameCase',
88
+ default: DEFAULTS.dirnameCase,
89
+ description: 'Case conversion applied to directory names when normalization is enabled. Same options as filenameCase: lowercase, uppercase, or original.',
90
+ },
91
+ {
92
+ name: 'filenameReplaceChars',
93
+ default: DEFAULTS.filenameReplaceChars,
94
+ description: 'Array of characters replaced with underscores in filenames when normalization is enabled. Helps create web-safe filenames by removing spaces and special characters.',
95
+ },
96
+ {
97
+ name: 'dirnameReplaceChars',
98
+ default: DEFAULTS.dirnameReplaceChars,
99
+ description: 'Array of characters replaced with underscores in directory names when normalization is enabled. Helps create web-safe directory names.',
100
+ },
101
+ ];
102
+ export const INPUT_EXTENSION_DESCRIPTIONS = {
103
+ '.jpg': 'JPEG image (Joint Photographic Experts Group)',
104
+ '.jpeg': 'JPEG image (alternative extension)',
105
+ '.png': 'PNG image (Portable Network Graphics)',
106
+ '.gif': 'GIF image (Graphics Interchange Format)',
107
+ '.bmp': 'BMP image (Bitmap)',
108
+ '.tiff': 'TIFF image (Tagged Image File Format)',
109
+ '.tif': 'TIFF image (alternative extension)',
110
+ '.webp': 'WebP image (Google web format)',
111
+ '.avif': 'AVIF image (AV1 Image File Format)',
112
+ '.svg': 'SVG vector image (Scalable Vector Graphics)',
113
+ '.heic': 'HEIC image (High Efficiency Image Container)',
114
+ '.heif': 'HEIF image (High Efficiency Image File Format)',
115
+ '.ico': 'ICO icon file (Windows icon)',
116
+ '.cur': 'CUR cursor file (Windows cursor)',
117
+ '.jp2': 'JPEG 2000 image',
118
+ '.j2k': 'JPEG 2000 image (alternative extension)',
119
+ '.jpf': 'JPEG 2000 image (alternative extension)',
120
+ '.jpx': 'JPEG 2000 extended image',
121
+ '.jpm': 'JPEG 2000 compound image',
122
+ '.mj2': 'Motion JPEG 2000',
123
+ '.jxr': 'JPEG XR image (Microsoft HD Photo)',
124
+ '.wdp': 'Windows Media Photo (JPEG XR)',
125
+ '.hdp': 'HD Photo (JPEG XR)',
126
+ '.psd': 'Photoshop document',
127
+ '.psb': 'Photoshop large document',
128
+ '.dds': 'DirectDraw Surface texture',
129
+ '.tga': 'Targa image',
130
+ '.vda': 'Targa image (alternative extension)',
131
+ '.icb': 'Targa image (alternative extension)',
132
+ '.vst': 'Targa image (alternative extension)',
133
+ '.pbm': 'Portable Bitmap (black and white)',
134
+ '.pgm': 'Portable Graymap (grayscale)',
135
+ '.ppm': 'Portable Pixmap (color)',
136
+ '.pnm': 'Portable Anymap (generic PPM/PGM/PBM)',
137
+ '.pfm': 'Portable FloatMap (HDR)',
138
+ '.exr': 'OpenEXR HDR image (Industrial Light & Magic)',
139
+ '.hdr': 'Radiance HDR image',
140
+ '.hrd': 'Radiance HDR image (alternative extension)',
141
+ '.pic': 'PICT image (Apple QuickDraw)',
142
+ '.pict': 'PICT image (alternative extension)',
143
+ '.pct': 'PICT image (alternative extension)',
144
+ '.xbm': 'X BitMap (X11)',
145
+ '.xpm': 'X PixMap (X11)',
146
+ '.wal': 'Quake 2 texture (WAL format)',
147
+ '.cut': 'CUT image (Dr. Halo)',
148
+ '.ras': 'Sun Raster image',
149
+ '.sun': 'Sun Raster image (alternative extension)',
150
+ '.sgi': 'SGI image (Silicon Graphics)',
151
+ '.rgb': 'SGI RGB image',
152
+ '.rgba': 'SGI RGBA image',
153
+ '.bw': 'SGI black and white image',
154
+ '.pcx': 'PCX image (ZSoft PC Paintbrush)',
155
+ '.pcd': 'PhotoCD image (Kodak)',
156
+ '.iff': 'IFF image (Amiga Interchange File Format)',
157
+ '.lbm': 'IFF image (alternative extension)',
158
+ };
159
+ export const OUTPUT_FORMAT_DESCRIPTIONS = {
160
+ webp: 'Google WebP. Modern format with excellent lossy and lossless compression. Best all-around choice for web use. Supports transparency.',
161
+ avif: 'AVIF based on AV1 codec. Superior compression ratios (30-50% smaller than JPEG) but slower encoding. Best for modern browsers.',
162
+ jpeg: 'JPEG. Universal compatibility with all devices and software. Good for photographs. Does not support transparency.',
163
+ png: 'PNG. Lossless compression with full transparency support. Best for graphics, logos, screenshots, and images requiring sharp edges.',
164
+ tiff: 'TIFF. High-quality format commonly used in print and publishing. Supports layers and multiple pages. Largest file sizes.',
165
+ gif: 'GIF. Supports animation and transparency. Limited to 256 colors. Best for simple animations and low-color graphics.',
166
+ heif: 'HEIF (High Efficiency Image File Format). Modern format using HEVC codec. Better compression than JPEG. Apple ecosystem support.',
167
+ jp2: 'JPEG 2000. Wavelet-based compression with excellent quality. Used in medical imaging and digital cinema. Not widely supported in browsers.',
168
+ jxl: 'JPEG XL. Next-gen format designed to replace JPEG. Lossless re-encoding of existing JPEGs. Excellent compression. Growing browser support.',
169
+ pdf: 'PDF (Portable Document Format). Converts images to PDF pages. Useful for document creation and archiving.',
170
+ };
@@ -0,0 +1,48 @@
1
+ import type { DownloadImageArgs, CompressImageArgs, CompressDirectoryArgs } from '../types.js';
2
+ export declare class ToolController {
3
+ static handleDownloadImage(args: DownloadImageArgs): Promise<{
4
+ content: {
5
+ type: string;
6
+ text: string;
7
+ }[];
8
+ isError?: undefined;
9
+ } | {
10
+ content: {
11
+ type: string;
12
+ text: string;
13
+ }[];
14
+ isError: boolean;
15
+ }>;
16
+ static handleCompressImage(args: CompressImageArgs): Promise<{
17
+ content: {
18
+ type: string;
19
+ text: string;
20
+ }[];
21
+ isError: boolean;
22
+ } | {
23
+ content: {
24
+ type: string;
25
+ text: string;
26
+ }[];
27
+ isError?: undefined;
28
+ }>;
29
+ static handleCompressDirectory(args: CompressDirectoryArgs): Promise<{
30
+ content: {
31
+ type: string;
32
+ text: string;
33
+ }[];
34
+ isError: boolean;
35
+ } | {
36
+ content: {
37
+ type: string;
38
+ text: string;
39
+ }[];
40
+ isError?: undefined;
41
+ }>;
42
+ static handleGetAcknowledgement(): {
43
+ content: {
44
+ type: string;
45
+ text: string;
46
+ }[];
47
+ };
48
+ }