1 comment

[ 7.4 ms ] story [ 13.9 ms ] thread
I’ve been maintaining react-image-editor (530 stars) and noticed a pattern: every time an AI agent needs to do anything with images — crop, resize, add text, apply a gradient — it either tries to write raw Sharp boilerplate from scratch or calls a generative model that rewrites the whole image nondeterministically.

Neither is good in an agentic pipeline. So I built image-edit-tools.

*What it is*

A TypeScript-first image editing SDK with 18+ pure functions, designed from the ground up for AI agents rather than human UIs. The key constraints that shaped the design:

- Every function is `(input, options) => Promise<Result<Buffer>>`. No classes, no global state, no side effects. - Never throws. Returns `{ ok: true, data }` or `{ ok: false, error, code }`. Agents need structured feedback, not stack traces. - Deterministic. Same input always produces the same output. Generative models can’t guarantee this. - Ships with a bundled MCP server. Add it to `claude_desktop_config.json` and Claude can call all 18 tools directly without writing any code.

*Core operations*

crop (absolute px / ratio / aspect ratio / subject-detect), resize, pad, adjust (brightness/contrast/saturation/hue/temperature), filter presets, blurRegion, addText (with inline spans for mixed bold/italic), composite, watermark, gradientOverlay, dropShadow, clipToShape, drawShape, removeBg, convert, optimize, getMetadata, pipeline, batch.

*The MCP angle*

This is the part I haven’t seen done elsewhere: the package ships with a ready-to-use MCP server. No Python, no model downloads, no venv. `npm install image-edit-tools`, add the server path to your MCP client config, and Claude/Cursor/Windsurf can immediately call `image_crop`, `image_add_text`, `image_pipeline` etc. as native tools.

In contrast, the closest existing tool (ImageSorcery) requires Python, a virtual environment, downloading YOLO models (1GB+), and only runs locally.

*What I learned building it*

librsvg (Sharp’s SVG renderer) silently ignores several CSS properties: `dominant-baseline: text-before-edge` falls back to `alphabetic`, `@import url()` for external fonts doesn’t work, and color emoji don’t render. All three hit us in production and required workarounds. Happy to discuss the details if anyone is building on Sharp + SVG compositing.

*Stack*: TypeScript, Sharp (libvips), @xenova/transformers (ONNX, for removeBg/detectFaces without Python), tesseract.js, MCP SDK.

npm: https://www.npmjs.com/package/image-edit-tools GitHub: https://github.com/swimmingkiim/image-edit-tools