{
  "markdown": "# @tinify-dev/mcp\n\nMCP (Model Context Protocol) server for the [Tinify.dev](https://tinify.dev/developers) image API. Lets ChatGPT, Claude, Cursor, and other MCP clients compress, resize, crop, and convert images — with honest results.\n\n```text\nYou: compress the screenshots in ~/Desktop/launch/\nClaude: 312.4 KB → 97.1 KB (-68.9%), wrote /Users/you/Desktop/launch/hero.min.png\n        84.2 KB → 84.2 KB — logo.png is already as small as Tinify.dev can make it\n        (optimized: false), so no file was written.\n```\n\n- **Never lies about savings** — when the API cannot shrink a file it says so (`optimized: false`) instead of writing a byte-identical \"optimized\" copy.\n- **Never overwrites your originals silently** — results go to `<name>.min.<ext>` beside the input, or to an explicit `output_path`. Replacing a file requires `overwrite: true`.\n- **Raw numbers in `structuredContent`** on every call, so agents can do math instead of parsing prose.\n\n> Not affiliated with TinyPNG. This server talks to the Tinify.dev API.\n\n## Requirements\n\n- Node.js >= 20\n- A Tinify.dev API key from [tinify.dev/developers](https://tinify.dev/developers) — free tier is 500 operations/month, no card required.\n\n## Setup\n\n### Claude Desktop\n\nAdd to `claude_desktop_config.json` (Settings → Developer → Edit Config):\n\n```json\n{\n  \"mcpServers\": {\n    \"tinify\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@tinify-dev/mcp\"],\n      \"env\": { \"TINIFY_API_KEY\": \"tnf_live_...\" }\n    }\n  }\n}\n```\n\n### Claude Code\n\n```sh\nclaude mcp add tinify -e TINIFY_API_KEY=tnf_live_... -- npx -y @tinify-dev/mcp\n```\n\n### Cursor\n\nCreate `.cursor/mcp.json` in your project (or `~/.cursor/mcp.json` globally):\n\n```json\n{\n  \"mcpServers\": {\n    \"tinify\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@tinify-dev/mcp\"],\n      \"env\": { \"TINIFY_API_KEY\": \"tnf_live_...\" }\n    }\n  }\n}\n```\n\n## Remote server (hosted)\n\nThe same five tools are available as a hosted streamable-HTTP MCP server - no install, works from ChatGPT connectors, the claude.ai directory, and any registry that expects a URL:\n\n```text\nEndpoint:  https://api.tinify.dev/mcp\nAuth:      OAuth 2.1 (PKCE + dynamic client registration), or\n           Authorization: Bearer tnf_live_...   (or tnf_test_...)\n```\n\nTwo ways to authenticate:\n\n- **OAuth (for connectors)** - ChatGPT connectors and the claude.ai directory only speak \"OAuth\" or \"no auth\". Add the server by its URL (`https://api.tinify.dev/mcp`) and pick **OAuth**; the client discovers the authorization and token endpoints automatically from the server's `.well-known` metadata, registers itself, and opens a **Connect Tinify** page where you paste your Tinify API key. Your key stays the credential - the client only ever holds an opaque token that maps back to it server-side.\n- **Direct bearer (for scripts/CLIs)** - send `Authorization: Bearer tnf_live_...` (or `tnf_test_...`) and skip OAuth entirely. Unchanged.\n\n### ChatGPT developer-mode connection\n\n1. In ChatGPT, open **Settings → Security and login** and enable **Developer mode**.\n2. Open [ChatGPT Plugins](https://chatgpt.com/plugins), select the plus button, and add `https://api.tinify.dev/mcp`.\n3. Complete **Connect Tinify** with a Tinify API key.\n4. Add the connection from the conversation's tools menu, attach a PNG/JPEG/WebP/AVIF, and ask:\n\n   ```text\n   Use Tinify to compress this image for the web. Show the original size,\n   result size, and percentage saved.\n   ```\n\nThe hosted server cannot access local paths, so each image tool accepts exactly one of:\n\n- `image` — the ChatGPT attachment object. ChatGPT fills this automatically because the descriptor advertises `openai/fileParams`.\n- `image_base64` — a portable fallback for other MCP clients, capped at ~28 MB decoded.\n\nChatGPT attachment downloads are HTTPS-only, reject private/reserved network targets and redirects, time out after 30 seconds, and are capped at the Tinify API's 40 MB limit. Successful operations return exact byte metrics and a temporary MCP result link. Existing base64 callers also receive `structuredContent.image_base64` for backwards compatibility. `get_usage` is identical to the local version. Nothing is written to the user's filesystem.\n\nTry it with curl:\n\n```sh\ncurl -s https://api.tinify.dev/mcp \\\n  -H \"Authorization: Bearer tnf_live_...\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Accept: application/json, text/event-stream\" \\\n  -d '{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"initialize\",\"params\":{\"protocolVersion\":\"2025-03-26\",\"capabilities\":{},\"clientInfo\":{\"name\":\"curl\",\"version\":\"0\"}}}'\n```\n\nFor local files, prefer the stdio server above - it reads and writes them directly with no base64 round-trip and no 28 MB cap.\n\n### One server, two transport adapters\n\nThis repository intentionally supports both OpenAI and Claude:\n\n- The shared tool names, Tinify client, result metrics, errors, and annotations are platform-neutral.\n- The stdio adapter uses absolute local paths and writes files for desktop/CLI clients such as Claude, Cursor, and Codex.\n- The hosted adapter uses ChatGPT file attachments or base64 and returns temporary result links because hosted servers cannot read a user's filesystem.\n\nAn OpenAI-only repository would duplicate the Tinify logic and make behavior drift more likely. OpenAI-specific descriptor metadata stays as a small additive layer in the hosted adapter; a separate repository is not needed.\n\nFor public OpenAI submission, set the portal-provided domain token as\n`OPENAI_APPS_CHALLENGE_TOKEN` in `/etc/tinify/mcp-http.env` and deploy the\nmatching nginx location from `deploy/nginx-location.conf`. The endpoint returns\nonly that token at `/.well-known/openai-apps-challenge`; do not commit the real\nportal token.\n\n## Tools\n\n| Tool | Arguments | Does |\n| --- | --- | --- |\n| `compress_image` | `path` (absolute), `output_path?`, `quality_mode?` (`balanced`/`best_quality`/`lossless`), `target_size_kb?` (beta), `overwrite?` | Compresses PNG/JPEG/WebP/AVIF. Writes `<name>.min.<ext>` beside the input. When the API returns `optimized: false`, nothing is written (unless you asked for an explicit `output_path`). |\n| `resize_image` | `path`, `width?`/`height?`/`scale?` (at least one), `keep_aspect_ratio?`, `output_path?`, `overwrite?` | Resizes and writes the result. |\n| `crop_image` | `path`, `x`, `y`, `width`, `height`, `output_path?`, `overwrite?` | Crops to a rectangle and writes the result. |\n| `convert_image` | `path`, `format` (`avif`/`webp`/`jpeg`/`png`), `quality_mode?`, `output_path?`, `overwrite?` | Converts formats (**beta** — the endpoint is rolling out server-side). Default output: `<name>.min.<new-ext>`. |\n| `get_usage` | — | Plan, billing period, operations used and remaining. |\n\nAll image tools require **absolute paths** (MCP servers run with an unpredictable working directory) and pre-check the **40 MB** API limit locally. API errors come back as readable tool errors with the error `code` and `request_id` to quote to support.\n\n## Example prompts\n\n- \"Compress every PNG in /Users/me/site/static/img\"\n- \"Resize /Users/me/photo.jpg to 1200px wide and tell me how many bytes it saved\"\n- \"Convert /Users/me/hero.png to webp with best quality\"\n- \"How many Tinify operations do I have left this month?\"\n\n## Limits and privacy\n\n- Max **40 MB / 50 MP** per image; PNG, JPEG, WebP, AVIF.\n- Uploaded images and results are deleted from Tinify.dev servers after **2 hours**.\n- The server only reads the files you point it at and only writes where it tells you it wrote.\n\n## Troubleshooting\n\n- **\"TINIFY_API_KEY is not set\"** — the server exits at startup with the exact config snippet to fix it. Add the key to the `env` block of your MCP config.\n- **`invalid_api_key`** — the key is wrong or revoked; create a new one at [tinify.dev/developers](https://tinify.dev/developers).\n- **`quota_exhausted` (429)** — the monthly quota is used up; run `get_usage` to see the period end.\n- **\"path must be absolute\"** — pass full paths like `/Users/you/img.png`, not `./img.png`.\n- Logs go to stderr; in Claude Desktop see `~/Library/Logs/Claude/mcp-server-tinify.log`.\n\n## Roadmap\n\n- Batch tools (create/commit/wait/download) on top of the durable batch API — not in v1.\n\n## License\n\nMIT © Stian Larsen\n\n## One-click / one-line installs\n\n**Cursor**: [Add to Cursor](cursor://anysphere.cursor-deeplink/mcp/install?name=tinify&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkB0aW5pZnktZGV2L21jcCJdLCJlbnYiOnsiVElOSUZZX0FQSV9LRVkiOiJZT1VSX0FQSV9LRVkifX0=) - then set your real key in Cursor's MCP settings.\n\n**VS Code**:\n\n```sh\ncode --add-mcp '{\"name\":\"tinify\",\"command\":\"npx\",\"args\":[\"-y\",\"@tinify-dev/mcp\"],\"env\":{\"TINIFY_API_KEY\":\"tnf_live_...\"}}'\n```\n\n**Codex CLI**:\n\n```sh\ncodex mcp add tinify --env TINIFY_API_KEY=tnf_live_... -- npx -y @tinify-dev/mcp\n```\n\nor in `~/.codex/config.toml`:\n\n```toml\n[mcp_servers.tinify]\ncommand = \"npx\"\nargs = [\"-y\", \"@tinify-dev/mcp\"]\n\n[mcp_servers.tinify.env]\nTINIFY_API_KEY = \"tnf_live_...\"\n```\n\n**Claude Code plugin** (MCP + image-optimization skill):\n\n```\n/plugin marketplace add Stianlars1/tinify-claude-plugin\n/plugin install tinify@tinify\n```\n\nMore: https://tinify.dev/mcp\n",
  "bytes": 9120,
  "sha": "747548e96e68be69927d5665913e1df6fab3c6c255054aa7e8afb2a6c5cb76a7",
  "repo_slug": "stianlars1/tinify-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_dev_tinify_mcp_15a8ec7c/readme"
}