Skip to main content
Glama

Stock Images MCP

CI npm license

An MCP (Model Context Protocol) server for searching and downloading stock images from Pexels, Unsplash, and Pixabay.

Features

  • search_images: search one or all configured providers; partial failures are reported per provider

  • download_image: download an image safely into a local folder

Related MCP server: Pexels MCP Server

Setup

Get API keys (at least one required)

Provider

Env var

Get a key

Pexels

PEXELS_API_KEY

https://www.pexels.com/api/

Unsplash

UNSPLASH_API_KEY

https://unsplash.com/developers

Pixabay

PIXABAY_API_KEY

https://pixabay.com/api/docs/

Optional: STOCK_IMAGES_DOWNLOAD_DIR — where download_image writes files (default ./downloads).

Claude Code / Cursor / Claude Desktop

Add to your MCP config (~/.claude/mcp.json, ~/.cursor/mcp.json, or claude_desktop_config.json):

{
  "mcpServers": {
    "stock-images": {
      "command": "npx",
      "args": ["-y", "stock-images-mcp"],
      "env": {
        "PEXELS_API_KEY": "your-key-here",
        "UNSPLASH_API_KEY": "your-key-here",
        "PIXABAY_API_KEY": "your-key-here"
      }
    }
  }
}

Requires Node.js 22+.

Docker

docker build -t stock-images-mcp .
docker run -i --rm -e PEXELS_API_KEY=xxx -v "$PWD/downloads:/downloads" stock-images-mcp

From source

git clone https://github.com/jeanpfs/stock-images-mcp.git
cd stock-images-mcp
npm ci && npm run build
PEXELS_API_KEY=xxx node dist/index.js

Tools

search_images

Search for stock images across configured providers.

Parameters:

  • query (required): search term

  • provider: "pexels", "unsplash", "pixabay", or "all" (default: "all")

  • count: results per provider (default 5, max 20)

  • orientation: "landscape", "portrait", or "square"

Each result has id, provider, url, thumbnail, description, author, authorUrl, downloadUrl, width, height. Pass downloadUrl to download_image.

download_image

Download an image into the download directory.

Parameters:

  • url (required): https image URL on pexels.com, unsplash.com or pixabay.com (use downloadUrl from search_images)

  • filename: output name — letters, digits, _, -, . only; the extension is added from the content-type if missing (auto-generated if omitted)

  • folder: subfolder inside the download directory

Behavior and limits:

  • Download directory is ./downloads, or STOCK_IMAGES_DOWNLOAD_DIR if set. Paths that escape it (including via symlinks) are rejected.

  • Only image/* responses are saved; max 50 MiB; 30 s timeout; redirects are followed only to allowed hosts.

  • Existing files are never overwritten.

  • Unsplash downloads require UNSPLASH_API_KEY: the tool calls Unsplash's download endpoint, as their API guidelines require.

Errors

Failures return isError: true. search_images also returns a per-provider errors list when some providers fail but others succeed. Provider requests time out after 10 s and are retried on network errors, 429 and 502/503/504.

Attribution and licensing

Images stay under each provider's license. Credit the photographer where the provider requires it (author and authorUrl are returned for that purpose) and review the terms: Pexels, Unsplash, Pixabay.

Development

npm ci
npm run lint && npm run format:check && npm run typecheck && npm test

See CONTRIBUTING.md, CODE_OF_CONDUCT.md and SECURITY.md (report vulnerabilities privately, not in public issues).

License

MIT

Available Tools

2 tools
download_imageA

Download a stock image (https URL on pexels.com, unsplash.com or pixabay.com) into the download directory. Refuses to overwrite existing files.

NameRequiredDescriptionDefault
urlYesURL of the image to download
folderNoSubfolder inside the download directory
filenameNoOutput filename (auto-generated if omitted)

TDQS

A3.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does disclose real behavior: files land in the download directory, only specific stock domains are accepted, and existing files are never overwritten (a refusal outcome). It omits auth requirements, failure modes for disallowed URLs, and rate limits, but the overwrite rule is genuinely useful beyond structured data.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight sentences with the resource, domain scope, destination, and overwrite rule front-loaded; every clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 3-param download tool with no annotations and no output schema, the description covers destination and the non-overwrite guarantee, which is what an agent needs to avoid surprising behavior. Return-value and error semantics are left implicit, a minor gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and all three parameters are documented in the schema, so the baseline is 3. The description confirms the download directory as the destination, contextualizing folder/filename, but adds no syntax or format detail beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Download a stock image') and constrains the accepted sources (pexels.com, unsplash.com, pixabay.com), which cleanly separates it from the search_images sibling. It stops short of explicitly naming or contrasting against that sibling, but the action is unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No statement of when to use this tool versus search_images or any alternative, and no prerequisites. The accepted-domain list is a constraint rather than usage guidance, so the agent must infer the search-then-download workflow.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_imagesC

Search stock images across providers. Available providers: pexels

NameRequiredDescriptionDefault
countNoNumber of images per provider (default: 5, max: 20)
queryYesSearch term for images
providerNoWhich provider to search (default: all configured)all
orientationNoImage orientation filter

TDQS

C2.9/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full behavioral burden but discloses little: it does not mention provider API key/credential requirements, rate limits, or that results are metadata rather than image bytes. The only real disclosure is which providers exist.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences, zero filler, with the core action front-loaded and the provider availability noted immediately after. Nothing could be cut without losing information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 4-parameter search tool with no annotations and no output schema, the description is thin — it omits return shape, whether results are paginated or deduplicated across providers, and what happens when a provider is unconfigured. An agent would need to trial-and-error these.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description adds one piece of runtime context — "Available providers: pexels" — which is slightly helpful given the schema's "default: all configured" wording, but it does not explain count, orientation, or query semantics beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource ("Search stock images") and adds scope ("across providers"), which is enough to distinguish it from the sibling download_image. It stops short of explicitly contrasting the two, but the read-vs-fetch distinction is inferable.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No when-to-use guidance is given: nothing about when to choose this over download_image, whether a prior search is required before downloading, or how the provider parameter interacts with the task. Usage is only implied by the verb.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 2 tool updatesv2.0.1
    • Changeddownload_image4 fields changed
      • addedInput schema / $schema
        Added value: +"http://json-schema.org/draft-07/schema#"
      • removedInput schema / properties / folder / default
        Removed value: -"./downloads"
      • changedInput schema / properties / folder / description
        Previous value: -"Destination folder (default: ./downloads)"New value: +"Subfolder inside the download directory"
      • addedInput schema / properties / url / format
        Added value: +"uri"
    • Changedsearch_images1 field changed
      • addedInput schema / $schema
        Added value: +"http://json-schema.org/draft-07/schema#"
  2. 2 tool updatesv1.0.0
    • First observeddownload_image
    • First observedsearch_images

TDQS

B3.4/5.0

Scored across 2 tools

Disambiguation5/5

The two tools have clearly distinct purposes: search_images finds images and download_image retrieves a specific one to disk. There is no plausible way to confuse them, and their boundaries are crisp.

Naming Consistency5/5

Both follow the same verb_noun snake_case pattern (search_images, download_image). Fully predictable and consistent.

Tool Count3/5

Only 2 tools is thin for a stock-image server; a search-plus-download pair is a reasonable minimal core, but it feels under-scoped for a domain that typically needs provider listing, metadata, and pagination.

Completeness3/5

The search-to-download workflow is covered, but there is no way to list providers or fetch image metadata/details, and search only exposes pexels while download accepts pexels/unsplash/pixabay, an inconsistency that hints at a partial surface.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers