blur-studio
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@blur-studioBlur all faces in sample-photos with ellipse regions and export config"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Blur Studio
Coordinate-based selective photo blurring — precisely blur faces, plates, screens, or any region while keeping VIP subjects sharp, from a glass-UI web app, a CLI, or an MCP server that AI agents can drive directly.

What it is
Blur Studio applies Gaussian blur with soft feathered edges to exact regions of an image — ellipses, rectangles, or hand-painted grid tiles — and can carve out rectangular "VIP" exclusion boxes that stay 100% sharp even when they overlap a blurred region. The same processing engine (blurService.js → blur_processor.py) is exposed three ways:
Web UI — a glass-materials dark studio for humans to click, drag, and paint regions on real photos.
CLI (
blur-studio) — scriptable access to every operation for shell pipelines and automation.MCP server — the same tools exposed over stdio so an AI agent (with its own vision) can decide what to blur and call it directly.
Related MCP server: Image Processor MCP Server
Features
Four contextual tools — grid paint, ellipse, VIP box, and pan — switchable by click or keys
1–4Ellipse targets — draggable, resizable center+radius regions with optional per-target blur/feather override
VIP exclusion boxes — rectangular "stay sharp" zones that punch through any overlapping blur
Grid painting — paint a density-adjustable grid of tiles over an image, then convert painted tiles into ellipse targets in one click
Per-target blur override — one region can use a heavier or lighter blur/feather radius than the image-wide default
Undo/redo — full document history (targets, exclusions, grid paint) across all loaded images, via buttons or
Ctrl+Z/Ctrl+Shift+ZFour view modes — Blurred, Original, Split (side-by-side), and Mask (see exactly what the blur mask covers), plus a hold-
Spacepeek-originalBatch processing — apply saved regions across an entire folder in one pass, with a live per-image progress list
Single & bulk download — download the just-processed photo, or zip every batch output for one-click download
Destination modes — write to a separate output folder (default, non-destructive) or replace files in place with an automatic
.bakbackupPython export — turn the current saved config into a standalone Python snippet (
EXCLUSION_BOXES/EXPLICIT_BLUR_TARGETS) for another pipelineCLI + MCP parity — every capability of the web UI is also a CLI command and an MCP tool, backed by the same
blurService.js
Quick Start
Requires Node.js >=20 and Python 3.10+ with Pillow.
git clone https://github.com/fauzulkc/blur-studio.git
cd blur-studio
npm install
pip install -r requirements.txt
./start.shstart.sh installs npm dependencies on first run, starts the backend, then the frontend dev server. Or run the two halves yourself:
npm run server # backend API — http://localhost:3333
npm run dev # frontend — http://localhost:5173Open http://localhost:5173. The app loads the bundled sample-photos/ folder by default, so there's something to click on immediately.
How it works
Blur Studio does not do automatic face, license-plate, or subject detection. It has no model for "what a face looks like." Every blur region is a set of exact normalized 0–1 coordinates that the caller supplies:
an ellipse —
{ cx, cy, rx, ry }, a center point + radiia rectangle / grid tile —
{ x1, y1, x2, y2 }, top-left and bottom-right cornersan exclusion box —
{ x1, y1, x2, y2 }, same shape, but it keeps that region sharp instead
(0, 0) is the top-left corner of the image, (1, 1) is the bottom-right — so coordinates stay correct regardless of the image's actual pixel dimensions.
This is a deliberate design constraint, not a missing feature:
A human using the web UI supplies coordinates by clicking, dragging, and painting.
An agent using the CLI or MCP server supplies coordinates by looking at the image with its own vision and deciding what needs to be blurred.
blurService.js is the single source of truth for this contract — it validates and forwards the same shapes to blur_processor.py (Pillow) regardless of which of the three front ends called it.
Web UI
npm run server # terminal 1 — backend, port 3333 (override with PORT env var)
npm run dev # terminal 2 — frontend, port 5173Point the source-folder field at a directory of images (or pick a Quick Preset).
Select a tool (
1grid,2ellipse,3VIP box,4pan) and mark regions on the active photo.Adjust blur/feather radius, and per-target overrides if needed.
Choose a destination mode — Export Folder (safe default) or Replace In-Place.
Apply Active to process the current photo, or Batch All to process every photo in the folder — then Download.
CLI
The blur-studio command wraps blurService.js for humans and scripts (node cli.js <command> also works without installing globally).
node cli.js --helpCommands:
presets List quick-access image folder presets
scan [options] Scan a folder for images along with their configured targets/exclusions
config Print the full persisted app configuration
save-config [options] Save per-image targets/exclusions and/or global blur settings
apply [options] Apply blur processing to a single image, or a batch of items
export-python [options] Export the current config as a Python snippetEvery flag that takes JSON (--targets, --exclusions, --items) also accepts an @file.json path, so large coordinate arrays never have to survive shell quoting.
Scan a folder for images and their currently saved regions:
node cli.js scan --folder ./sample-photosBlur one image — an ellipse over one region, a rectangle kept sharp:
node cli.js apply \
--input ./sample-photos/sample-1.jpg \
--output ./sample-photos-blurred/sample-1.jpg \
--targets '[{"cx":0.15,"cy":0.2,"rx":0.055,"ry":0.075,"label":"Person 1"}]' \
--exclusions '[{"x1":0.43,"y1":0.16,"x2":0.56,"y2":0.33,"label":"VIP - keep sharp"}]' \
--blur-radius 13 --feather-radius 14 \
--destination-mode separate_folderBatch-process several images from a JSON file of {inputPath, outputPath, targets, exclusions} items:
node cli.js apply --items @batch.json --destination-mode separate_folderRun node cli.js <command> --help for the full flag list of any subcommand.
MCP server
mcp-server.js exposes the same operations as MCP tools over stdio (StdioServerTransport), so an agent can drive the app directly — deciding what to blur with its own vision, then calling the tool with exact coordinates.
Tool | Description |
| List the quick-access image folder presets |
| Scan a folder for images plus each one's saved targets/exclusions and global defaults |
| Return the full persisted config (targets, exclusions, folders, blur defaults) |
| Persist targets/exclusions for a filename and/or update global blur defaults — writes config only, no pixels |
| Actually blur pixels for one or more images and write output — the tool that does the work |
| Render the persisted config as a standalone Python snippet |
apply_blur's tool description spells out the same no-auto-detection contract as above — the agent must supply exact {cx,cy,rx,ry} or {x1,y1,x2,y2} coordinates itself.
Registering it (add to your MCP client)
Every MCP client wants the same basic shape — a command to spawn plus its args — just in a different config location. Point it at this repo's mcp-server.js directly, or at the mcp Docker image (see Docker) if you'd rather not install Node/Python locally.
Claude Code — if you clone this repo and open Claude Code inside it, the checked-in .mcp.json is auto-detected and Claude Code will prompt to enable it — nothing else to do. To make it available from any directory instead:
claude mcp add --scope user blur-studio -- node /absolute/path/to/blur-studio/mcp-server.js
# or, via Docker, no local Node/Python required:
claude mcp add --scope user blur-studio -- docker run -i --rm -v ~/Photos:/photos blur-studio-mcpClaude Desktop — add an entry to its config file (create the file if it doesn't exist yet):
OS | Path |
macOS |
|
Windows |
|
Linux |
|
{
"mcpServers": {
"blur-studio": {
"command": "node",
"args": ["/absolute/path/to/blur-studio/mcp-server.js"]
}
}
}Cursor — same JSON shape, in .cursor/mcp.json (project-scoped) or ~/.cursor/mcp.json (every project).
Any other MCP-capable tool — register the same command/args pair however that tool takes MCP server configuration; this repo's own .mcp.json is a working reference for the exact shape.
Using the skill (Claude Code) / AGENTS.md (everyone else)
This repo ships two parallel sets of agent-facing instructions — install neither, both travel with the repo automatically:
.claude/skills/blur-studio/— a Claude Code Skill. It's project-scoped: clone this repo, open Claude Code with it as your working directory, and Claude Code auto-discovers and can invoke it — no separate install step. To make it available in every project instead of just this one, copy or symlink it into your personal skills folder:ln -s "$(pwd)/.claude/skills/blur-studio" ~/.claude/skills/blur-studioAGENTS.md(repo root) — the same operating instructions in a plain, tool-agnostic file for any other agent that reads repo context automatically (Cursor, OpenAI Codex CLI, Gemini CLI/Antigravity, etc.). Nothing to install — it's just read from the working directory like this README.
Docker
One multi-target Dockerfile builds two independent images, sharing a common Node + Python/Pillow/numpy base:
Target | Build | What it runs | Port |
|
|
|
|
|
|
| — |
docker build . with no --target builds web.
Deploy the full app:
docker build --target web -t blur-studio-web .
docker run -d -p 3333:3333 -v ~/Photos:/photos blur-studio-webOpen http://localhost:3333 — the API and UI are served from the same container. A HEALTHCHECK hits /health every 30s so orchestrators (Docker, Kubernetes, most hosting platforms) can tell it's actually serving requests, not just running.
Run the MCP server in a container:
docker build --target mcp -t blur-studio-mcp .
docker run -i --rm -v ~/Photos:/photos blur-studio-mcpOnly the folders you explicitly mount (-v host:container) are visible inside either container. The rest of your filesystem is not reachable — pass whichever photo directories you need as bind mounts, and reference the container-side path (e.g. /photos) in the UI's source-folder field or when calling scan_folder/apply_blur.
docker-compose.yml runs both as named services (web and mcp), each with its own persistent volume for blur_studio_config.json so saved regions survive container restarts:
docker compose up -d web # full app at http://localhost:3333
docker compose run --rm -i mcp # MCP server, stdio-attachedEdit the commented-out volume line under whichever service you use to point at your own photo folder before running it — see the file's own comments for the full picture, including the destinationMode: 'replace' in-place-overwrite caveat.
This image has no authentication of its own — see SECURITY.md before exposing the web container to anything beyond your own machine/network.
Safety & privacy
destinationModecontrols whether your original files are touched.
separate_folder(default, safe) — originals are never modified; blurred output is written to a separate destination folder.
replace— overwrites the source file in place. The original is backed up first to<file>.bakunless backups are explicitly disabled (--no-backupon the CLI, ormakeBackup: falsevia the API/MCP). Use this mode deliberately, and be especially careful when mounting a real photo folder into the Docker container withreplacemode — you are giving the container permission to overwrite files in that mount.
Testing
npm run test:e2eThis drives the real running app in headless Chromium (Playwright) — not mocked. It requires both servers running first:
node server.js & # backend, port 3333
npx vite --port 5173 & # frontend
npm run test:e2e # defaults to http://localhost:5178; override with BLUR_STUDIO_URL
BLUR_STUDIO_URL=http://localhost:5173 npm run test:e2eIt covers every interactive function — image browsing/search/filter, all four tools, ellipse and VIP-box create/select/edit/delete, grid density/paint/convert/clear, blur/feather sliders, all four view modes, peek-original, zoom/pan, undo/redo, destination-mode toggle, the Python/Batch modals — and, for real rather than as a presence check, Apply Active, Start Batch Processing, and both Download buttons.
These real Apply/Batch runs are safe because the app's default folder is the bundled sample-photos/ — two CC0 (public-domain) photos checked into the repo (see sample-photos/CREDITS.md). Output only ever lands in the gitignored sample-photos-blurred/ folder; the tracked source images are never mutated in place. See tests/e2e/README.md for the full testing conventions.
Architecture
Three front ends — the Web UI (via server.js's Express API), the CLI (cli.js), and the MCP server (mcp-server.js) — all call into the same blurService.js, which shells out to blur_processor.py (Pillow) to actually touch pixels. No front end talks to Python directly.
Web UI (React) CLI (blur-studio) MCP server (agents)
│ │ │
▼ ▼ ▼
server.js ─────────────────────────────────────────────
(Express API) blurService.js
│
▼
blur_processor.py
(Pillow, subprocess)
│
▼
image filesContributing
See CONTRIBUTING.md for how to get set up and submit changes.
License
MIT © Fauzul Chowdhury
Security
See SECURITY.md for how to report a vulnerability.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- Alicense-qualityAmaintenanceMCP server for generating, editing, and processing images via multiple providers including Kilo, OpenRouter, OpenAI, and Gemini, with local tools for background removal, resizing, and cropping.372MIT
- Flicense-qualityDmaintenanceA powerful Model Context Protocol (MCP) server for image processing, designed to empower AI models with advanced image manipulation capabilities.
- AlicenseAqualityDmaintenanceMCP server that provides image generation, captioning, and tagging via ComfyUI API, configurable for agent tools.43MIT
- Alicense-qualityAmaintenanceA local, read-only MCP server that lets AI agents inspect and analyze photo libraries by scanning files, aggregating EXIF stats, finding duplicates, scoring blur, and generating cull reports without uploading any data.MIT
Related MCP Connectors
MCP server for NanoBanana AI image generation and editing
MCP server for Flux AI image generation
MCP server for Wan AI video generation
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/fauzulkc/blur-studio'
If you have feedback or need assistance with the MCP directory API, please join our Discord server