Content
# imagebank-mcp
MCP server that lets AI coding agents (Claude Code, Codex, Cursor, Antigravity, Cline, Windsurf and any MCP-compatible client) search free stock photos on **Pexels**, **Unsplash** and **Pixabay**, download them, and convert them to **WebP** directly into your project — no placeholders, no hotlinking, no manual image hunting.
Built for web developers: the agent asks for "a hero photo of artisan bread", gets real results, saves an optimized `public/images/hero-artisan-bread.webp`, and writes the `<Image>` tag pointing to it. Done.
## Tools
| Tool | What it does |
|---|---|
| `search_images` | Searches one or all configured providers in parallel. Returns preview URL, download URL, dimensions, author and attribution link. Supports orientation and dominant-color filters. |
| `download_image` | Downloads a result, converts to WebP (quality and max-width configurable), saves inside the project, returns the path ready for `<Image src>`. Automatically fires the Unsplash download-tracking endpoint when required. |
| `optimize_local_image` | Same pipeline for local files. Use it when the client replaces stock photos with their own, so performance stays consistent. |
## Requirements
- Node.js >= 18.17
- At least one API key (all free):
- Pexels: https://www.pexels.com/api/
- Unsplash: https://unsplash.com/developers (use the **Access Key**)
- Pixabay: https://pixabay.com/api/docs/
> First install may take a bit longer: `sharp` (image processing) downloads a prebuilt native binary for your platform. This is normal.
## Installation
The recommended way is `npx` — nothing to install manually, each client just points at the package:
```jsonc
"command": "npx",
"args": ["-y", "imagebank-mcp"]
```
API keys go in the `env` block of each client config. **Never commit keys to a repository.** Only the keys you set are used; missing providers are simply skipped.
### Claude Code
Per project (`.mcp.json` at the project root) or global (`~/.claude.json`):
```json
{
"mcpServers": {
"image-banks": {
"command": "npx",
"args": ["-y", "imagebank-mcp"],
"env": {
"PEXELS_API_KEY": "your_key",
"UNSPLASH_ACCESS_KEY": "your_key",
"PIXABAY_API_KEY": "your_key"
}
}
}
}
```
Or via CLI:
```bash
claude mcp add image-banks -e PEXELS_API_KEY=your_key -e UNSPLASH_ACCESS_KEY=your_key -e PIXABAY_API_KEY=your_key -- npx -y imagebank-mcp
```
### Cursor
`.cursor/mcp.json` in the project (or `~/.cursor/mcp.json` global). Same JSON shape as Claude Code above.
### OpenAI Codex CLI
`~/.codex/config.toml`:
```toml
[mcp_servers.image-banks]
command = "npx"
args = ["-y", "imagebank-mcp"]
[mcp_servers.image-banks.env]
PEXELS_API_KEY = "your_key"
UNSPLASH_ACCESS_KEY = "your_key"
PIXABAY_API_KEY = "your_key"
```
### Antigravity
Agent settings → MCP servers → add server. Uses the same JSON structure as Claude Code (`mcpServers` block with `command`, `args`, `env`).
### Cline / Roo Code (VSCode)
MCP settings file (`cline_mcp_settings.json`): same JSON shape as Claude Code.
### Windsurf
`~/.codeium/windsurf/mcp_config.json`: same JSON shape as Claude Code.
### Gemini CLI
`~/.gemini/settings.json`, inside `mcpServers`: same JSON shape as Claude Code.
> Config file locations change between client versions. If a path above doesn't match your install, check the client's MCP docs — the server block itself (`command`/`args`/`env`) is identical everywhere.
## Usage
You rarely call the tools explicitly. In normal use the agent decides on its own:
> "Build the hero section for the bakery with a photo of fresh sourdough coming out of the oven."
The agent will call `search_images` (query in English, `orientation: landscape`), pick a result, call `download_image`, and write the component using the returned local path.
Explicit prompts also work:
```
Search 6 landscape photos of "modern dental clinic reception" on unsplash,
download the best one as hero-clinic-reception at quality 85.
```
### Recommended agent guidance
Add to your `CLAUDE.md` / rules file for best behavior:
```
Images: when the design needs photos and the client has not provided any,
use the image-banks MCP (search_images then download_image). Search in
English. Never hotlink stock URLs; always download to public/images.
Prefer client-provided photos when they exist (optimize them with
optimize_local_image). Avoid stock photos with prominent faces for paid ads.
```
## Image licensing (read this once)
All three providers allow **free commercial use without attribution on the final website**. Still:
- **Unsplash API rule**: when a photo is actually used, the download endpoint must be pinged. `download_image` does this automatically when you pass `trackDownloadUrl`.
- **Pixabay**: permanent hotlinking is prohibited — you must self-host. This server downloads by design, so you're compliant by default.
- **Model releases**: none of the platforms verify consent of people appearing in photos. Avoid images with recognizable faces in paid advertising; fine for regular site sections.
- Attribution is not required but is appreciated — the `attributionUrl` and `author` fields are always returned if you want to credit.
This is not legal advice; check each provider's license for your specific case.
## Security
- **SSRF protection**: `download_image` only accepts `https` URLs on `pexels.com`, `unsplash.com`, `pixabay.com` and subdomains. Internal IPs, cloud metadata endpoints and arbitrary hosts are rejected.
- **Path traversal protection**: filenames are sanitized to kebab-case; output and input paths must resolve inside the working directory.
- **Size and type limits**: downloads capped at 25 MB; content-type validated; sharp pixel-bomb limit set.
- **Keys**: read from env only, never logged, never echoed in tool output.
- Runs locally over stdio. Nothing is hosted; no data leaves your machine except the API calls to the providers you configured.
## Local development
```bash
git clone https://github.com/romuloquintanilha/imagebank-mcp
cd imagebank-mcp
npm install
npm run build
npm test # unit + real MCP protocol + sharp pipeline tests
npm run inspector # interactive UI to call tools manually
```
For the inspector, export your keys first (`export PEXELS_API_KEY=...`).
## License
MIT — see [LICENSE](./LICENSE). The code is MIT; the images you download are governed by each provider's own license.