{
  "markdown": "# ShortPixel MCP Server\n\nPublic HTTP MCP server that exposes ShortPixel SPIO image optimization to AI agents (Cursor, Claude Desktop, VS Code, etc.).\n\n## Architecture\n\n```text\nAI client (Cursor, Claude, …)\n    │\n    │  MCP over HTTPS (Streamable HTTP)\n    ▼\nhttps://mcp.shortpixel.com/mcp\n    │\n    │  user's API key in Authorization header\n    ▼\nShortPixel SPIO API (api.shortpixel.com)\n```\n\nEach request carries the **user's own ShortPixel API key**. The MCP server does not store user keys — it forwards them to the public SPIO API.\n\n## Requirements\n\n- Node.js 20+\n- npm\n\n## Install (server)\n\n```bash\nnpm ci\nnpm run build\ncp .env.example .env\n```\n\nEdit `.env` for server settings (port, allowed hosts, upstream API URL). **Do not** put user API keys in server `.env`.\n\n## Run\n\n```bash\nnpm start\n```\n\nEndpoints:\n\n| Path | Method | Description |\n|------|--------|-------------|\n| `/health` | GET | Health check (no API key) |\n| `/ping` | GET | Auth check — returns ok if API key header is present |\n| `/mcp` | POST | MCP Streamable HTTP endpoint |\n\n### Quick test (curl)\n\nServer up, no API key:\n\n```bash\ncurl http://mcp.shortpixel.com:3000/health\n```\n\nAPI key present (simple check):\n\n```bash\ncurl -i -H \"Authorization: Bearer YOUR_API_KEY\" http://mcp.shortpixel.com:3000/ping\n```\n\nUse `http://` (not `https://`) on port 3000 unless TLS is configured on nginx.\n\nMCP request (important: Streamable HTTP clients must accept both JSON and SSE):\n\n```bash\ncurl -s -N -X POST http://mcp.shortpixel.com:3000/mcp \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Accept: application/json, text/event-stream\" \\\n  -H \"Authorization: Bearer YOUR_API_KEY\" \\\n  -d '{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"tools/list\",\"params\":{}}'\n```\n\n## Authentication\n\nSend the user's ShortPixel API key on every MCP request:\n\n```http\nAuthorization: Bearer <shortpixel_api_key>\n```\n\nAlternative header:\n\n```http\nX-ShortPixel-Api-Key: <shortpixel_api_key>\n```\n\nUsers without a key can get one at [shortpixel.com](https://shortpixel.com).\n\n## Cursor setup (end user)\n\n```json\n{\n  \"mcpServers\": {\n    \"shortpixel\": {\n      \"url\": \"https://mcp.shortpixel.com/mcp\",\n      \"headers\": {\n        \"Authorization\": \"Bearer YOUR_SHORTPIXEL_API_KEY\"\n      }\n    }\n  }\n}\n```\n\nReplace the URL with your deployed host during development (e.g. `http://localhost:3000/mcp`).\n\n## Server environment variables\n\n| Variable | Required | Default | Description |\n|----------|----------|---------|-------------|\n| `PORT` | no | `3000` | HTTP listen port |\n| `ALLOWED_HOSTS` | no | — | Comma-separated Host header allowlist (recommended in production) |\n| `SHORTPIXEL_API_URL` | no | `https://api.shortpixel.com/v2` | Upstream SPIO API base URL |\n| `SHORTPIXEL_PLUGIN_VERSION` | no | `MCP01` | Plugin version sent to SPIO |\n| `LOG_LEVEL` | no | `info` | Log verbosity: `debug`, `info`, `warn`, `error` |\n| `LOG_FORMAT` | no | `text` | `text` = human-readable lines; `json` = structured JSON |\n| `LOG_MCP_PROTOCOL` | no | `true` | Log inbound/outbound MCP JSON-RPC payloads |\n\nFor internal ShortPixel development, set `SHORTPIXEL_API_URL=https://devapi2.shortpixel.com/v2`.\n\n## Request logging\n\nLogs go to stdout (`pm2 logs` / `npm start`).\n\n**Default (`LOG_FORMAT=text`)** — narrative flow you can follow:\n\n```\n[2026-06-30 15:01:53] [1/5] → CLIENT | HTTP POST /mcp | JSON-RPC request: \"initialize\" (client connects) | id: 0\n           {\n             \"jsonrpc\": \"2.0\",\n             \"method\": \"initialize\",\n             \"id\": 0,\n             \"params\": { ... }\n           }\n[2026-06-30 15:01:53] [1/5] ← SERVER | HTTP POST /mcp 200 | JSON-RPC response: \"initialize\" (client connects)\n[2026-06-30 15:01:53] [2/5] → CLIENT | HTTP POST /mcp | JSON-RPC request: \"notifications/initialized\" (session ready, no response body expected) | id: null\n[2026-06-30 15:01:53] [2.5/5] → CLIENT | HTTP POST /mcp | JSON-RPC request: \"tools/list\" (client asks which tools exist) | id: 1\n[2026-06-30 15:01:53] [2.5/5] ← SERVER | HTTP POST /mcp 200 | JSON-RPC response: \"tools/list\" (client asks which tools exist) | tools discovered: optimize_image_urls\n[2026-06-30 15:02:18] [3/5] → CLIENT | HTTP POST /mcp | JSON-RPC request: \"tools/call\" (client runs a tool) | id: 2 | tool: \"optimize_image_urls\"\n[2026-06-30 15:02:18] [4/5] MCP → SPIO API: POST reducer.php (args mapped to SPIO payload) | ...\n[2026-06-30 15:02:35] [5/5] MCP ← SPIO API: Success | reduction: 27.41% | optimized: http://api.shortpixel.com/f/...-lossy.jpg | original: ...\n[2026-06-30 15:02:35] [3/5] ← SERVER | HTTP POST /mcp 200 | JSON-RPC response: \"tools/call\" (client runs a tool) | tool: optimize_image_urls\n           { \"jsonrpc\": \"2.0\", \"id\": 2, \"result\": { ... } }\n[2026-06-30 15:02:35]     ✓ round-trip done (16.3s)\n```\n\n`LOG_MCP_PROTOCOL=false` keeps only high-level app logs and hides MCP payload dumps.\n\n**Structured (`LOG_FORMAT=json`)** — one JSON object per line:\n\n| Event | When |\n|-------|------|\n| `http_request` | Every request (method, path, status, duration, MCP method/tool) |\n| `spio_request` | Outgoing call to SPIO `reducer.php` |\n| `spio_response` | SPIO result summary (status, % improvement) |\n| `mcp_auth_missing` | Request without API key |\n\nAPI keys are masked (`****abcd`). Full keys are never logged.\n\n**Note:** The chat prompt never reaches this server. The LLM (inside the MCP client) turns user text into a structured `tools/call`; the server only sees JSON-RPC arguments and maps them to the SPIO API.\n\n```bash\npm2 logs shortpixel-mcp\n# or\nnpm start\n```\n\nSet `LOG_LEVEL=debug` for `tools/list` and extra HTTP lines.\n\n## Deploy on dev server\n\n```bash\ncd /xxx/mcp.shortpixel.com\nnpm ci\nnpm run build\ncp .env.example .env\n# set ALLOWED_HOSTS and PORT, then run behind nginx with TLS\nnpm start\n```\n\nRe-upload `package.json` and `package-lock.json` after each dependency change. If build still fails, run `npm ci --include=dev` (some servers set `NODE_ENV=production` which skips devDependencies).\n\n## Available MCP tools\n\n| Tool | Description |\n|------|-------------|\n| `optimize_image_urls` | Optimize one or more public image URLs via SPIO reducer API |\n\n`optimize_image_urls` arguments:\n\n- `urls` (required): Public image URLs to optimize (max 100)\n- `lossy`: Compression level (`0` lossless, `1` lossy, `2` glossy)\n- `wait`: Max wait seconds (`0` to return immediately, `1-30` to wait)\n- `upscale`: Upscale factor (`0`, `2`, `3`, `4`)\n- `resize`: Resize mode (`0` none, `1` outer, `3` inner, `4` smart crop)\n- `resize_width`, `resize_height`: Resize target dimensions in pixels\n- `cmyk2rgb`: Convert CMYK to RGB (`1` yes, `0` no)\n- `keep_exif`: Keep EXIF metadata (`1` keep, `0` remove)\n- `convertto`: Conversion value (`+webp`, `+avif`, `+webp|+avif`, `webp|avif`, `jpg`, `png`, `gif`)\n- `bg_remove`: Background removal (`1`, image URL, or `#rrggbbxx`)\n- `refresh`: Force source refetch (`1`) or use cached optimized data (`0`)\n- `paramlist`: Per-URL overrides array (must match `urls` length)\n- `returndatalist`: Any array echoed back unchanged in response\n\n## Project layout\n\n```text\nsrc/index.ts                    HTTP server entry point\nsrc/http/auth.ts                API key extraction from requests\nsrc/mcp/create-mcp-server.ts    Per-request MCP server factory\nsrc/clients/spio-api-client.ts  ShortPixel SPIO HTTP client\nsrc/tools/spio-tools.ts         MCP tools\nsrc/http/request-log-middleware.ts HTTP request logging\nsrc/logging/request-logger.ts    Structured JSON logger\nsrc/logging/mcp-protocol-log.ts  MCP protocol payload capture/normalize\n```\n\n## Naming conventions\n\n| Kind | Style | Example |\n|------|-------|---------|\n| Files | kebab-case | `spio-api-client.ts` |\n| Classes | PascalCase | `SpioApiClient` |\n| Methods | camelCase | `optimizeUrls` |\n\n## Scripts\n\n| Command | Description |\n|---------|-------------|\n| `npm run build` | Compile TypeScript to `dist/` |\n| `npm start` | Run HTTP MCP server |\n| `npm run dev` | Run with tsx (no build step) |\n",
  "bytes": 7897,
  "sha": "04371525d51ae1e7988fcebe1f199ada98908f95b2d7e16f4cf1e964396ba62f",
  "repo_slug": "short-pixel-optimizer/com.shortpixel.mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_com_shortpixel_mcp_optimize_dc178f10/readme"
}