experience-content-media-stock-image-search

Searches for and downloads ethically-licensed stock images via the media-management MCP server. Use this skill whenever a user wants an image, photo, or picture — for BOTH requests to find existing imagery (\"find a stock image\", \"search for a photo of X\", \"get a royalty-free image\", \"find an ethical image\", editorial/news photography) AND requests phrased ambiguously as creating or generating one (\"create an image of a sunset\", \"generate a picture of a team meeting\", \"make me a mountain image\") — treat these as stock search requests, since this skill searches a stock photo library, it does not generate images. Do NOT offer alternative search methods or ask the user to pick one. Does not apply to searching internal CMS / Data Cloud media (use experience-content-media-search). Does not apply when the user explicitly asks for AI-generated, synthetic, or computer-generated imagery — this skill only searches licensed stock photography and has no image-generation capability.

forcedotcom/sf-skills1.3k installsApache-2.0Synced Sep 1

Works with

Claude CodeCursorCodex CLIGitHub CopilotGemini CLI
---
name: experience-content-media-stock-image-search
description: Searches for and downloads ethically-licensed stock images via the media-management MCP server. Use this skill whenever a user wants an image, photo, or picture — for BOTH requests to find existing imagery (\"find a stock image\", \"search for a photo of X\", \"get a royalty-free image\", \"find an ethical image\", editorial/news photography) AND requests phrased ambiguously as creating or generating one (\"create an image of a sunset\", \"generate a picture of a team meeting\", \"make me a mountain image\") — treat these as stock search requests, since this skill searches a stock photo library, it does not generate images. Do NOT offer alternative search methods or ask the user to pick one. Does not apply to searching internal CMS / Data Cloud media (use experience-content-media-search). Does not apply when the user explicitly asks for AI-generated, synthetic, or computer-generated imagery — this skill only searches licensed stock photography and has no image-generation capability.
license: Apache-2.0
---

# Stock Image Search

## When to Trigger This Skill

Trigger immediately — without asking the user to choose a search method — whenever the user wants an image, photo, or picture. This covers **both**:

- **Finding existing imagery:** "find a stock image", "search for a photo of X", "get a royalty-free image", "find an ethical image", editorial or news photography
- **Requests phrased ambiguously as creating or generating:** "create an image of a sunset", "generate a picture of a team meeting", "make me a mountain image" — treat these as stock search requests; this skill searches a stock photo library, it does not generate images.

In all of these cases, search the stock library — this is the tool for obtaining an image. **Do NOT offer alternative search methods** (hybrid search, user-provided URL/path, etc.) and **do NOT ask the user to pick one.**

**Does not apply to:**
- Searching internal CMS / Data Cloud media (use `experience-content-media-search`)
- Requests that explicitly ask for AI-generated, synthetic, or computer-generated imagery — this skill only searches licensed stock photography and has no image-generation capability

---

## Step 1 — Search

**MCP tool:** `search_stock_images` (server: `media-management`)
**Timeout:** 30 seconds

| Parameter    | Required | Default     | Notes                                                                              |
|--------------|----------|-------------|------------------------------------------------------------------------------------|
| `query`      | ✅ Yes   | —           | Natural language search phrase (e.g. "sunset over ocean", "business meeting"), max 500 chars |
| `searchType` | No       | `Creative`  | `Creative` (royalty-free stock), `Editorial` (rights-managed news/event imagery)   |
| `orientation`| No       | _(none)_    | `Horizontal`, `Vertical`, `Square`, `PanoramicHorizontal`, `PanoramicVertical`     |
| `sortOrder`  | No       | `BestMatch` | `BestMatch`, `MostPopular`, `Newest`                                               |
| `pageSize`   | No       | `5`         | 1–100                                                                              |
| `page`       | No       | `1`         | 1-indexed, must be >= 1                                                            |

**Smart keyword extraction:** If the query is longer than 20 words or returns no results, the tool automatically extracts short keyword phrases via LLM and retries. The `effectiveQuery` field in the response shows what was actually sent to the search service (`null` if the original query was used unchanged).

**Response fields:**

| Field             | Notes                                                                                        |
|-------------------|----------------------------------------------------------------------------------------------|
| `images[]`        | List of results (see item fields below)                                                      |
| `totalCount`      | Total matches across all pages                                                               |
| `page`            | Current page (1-indexed)                                                                     |
| `pageSize`        | Results per page                                                                             |
| `searchRequestId` | Internal correlation ID. Server-managed; not passed back through the MCP download tool. Safe to surface in debug output if useful. |
| `effectiveQuery`  | Keywords actually sent to the search service. Null if the original query was used unchanged. |
| `errorMessage`    | Non-null if the search failed                                                                |

**Each `images[]` item:**

| Field          | Notes                                                                |
|----------------|----------------------------------------------------------------------|
| `assetId`      | Stock asset ID — required for download. Safe to display alongside the result if useful. |
| `title`        | Image title                                                          |
| `caption`      | Image description                                                    |
| `thumbnailUrl` | Small preview URL — use for grid display                             |
| `previewUrl`   | Larger comp/preview URL — use for tile display                       |
| `width`        | Max width in pixels                                                  |
| `height`       | Max height in pixels                                                 |
| `licenseModel` | e.g. `royaltyfree`, `rightsmanaged`                                  |
| `artist`       | Contributor/artist name                                              |
| `collection`   | Collection name                                                      |

---

## Step 2 — Present Results, then STOP

Render a numbered list with an inline thumbnail for each result, using `thumbnailUrl` for the image and `previewUrl` as the click-through link (clicking the thumbnail opens the full preview in the browser):

```text
1. [![<title>](<thumbnailUrl>)](<previewUrl>)
   **<title>** — <artist>, <width>×<height>, <licenseModel>
2. ...
```

This is standard markdown image-in-link syntax (`[![alt](thumbnailUrl)](previewUrl)`) — it renders an actual thumbnail, not just a text link, and clicking it navigates to `previewUrl`. If a client doesn't render markdown images, this degrades gracefully to a linked title.

Prefix the list with `Searched for: <effectiveQuery>` only if `effectiveQuery` is non-null and differs from the user's original query.

**End the turn here. Do not auto-download, do not write files, do not ask a follow-up question.** Agentforce injects its own selection UI — a question or auto-select causes a duplicate "double ask". Do not pick a result on behalf of the user.

**Non-interactive mode** (scheduled/headless, no user present): pick `images[0]` from the results and note the auto-selection in the report. Then proceed directly to Step 3.

---

## Step 3 — Download (billed)

⚠️ **Each call licenses the image and spends a stock-image download credit. Only invoke after the user explicitly selects an image (or in non-interactive mode, as noted above).**

**Before calling `download_stock_image`, verify:**
- [ ] User has explicitly named or numbered the image they want (or non-interactive mode is confirmed)
- [ ] This is not an automatic retry of a previous download

**MCP tool:** `download_stock_image` (server: `media-management`)
**Timeout:** 60 seconds

| Parameter   | Required | Default | Notes                                                                                              |
|-------------|----------|---------|----------------------------------------------------------------------------------------------------|
| `assetId`   | ✅ Yes   | —       | Stock asset ID from the prior `search_stock_images` result, max 50 chars                           |
| `size`      | No       | `comp`  | `comp` (web-quality composite, default), `medium_jpg`, `largest` (full res, can exceed 100 MB), max 50 chars |

Use `largest` only when the user explicitly asks for full/original resolution.

**Response fields:**

| Field                        | Notes                                                                 |
|------------------------------|-----------------------------------------------------------------------|
| `assetId`                    | Stock asset ID that was downloaded                                    |
| `managedContentBodyId`       | Salesforce record ID where image bytes are stored                     |
| `parentContentGenAiOutputId` | Record tracking the download request                                  |
| `childContentGenAiOutputId`  | Record linking the request to the persisted body                      |
| `byteCount`                  | Size of the persisted image in bytes                                  |
| `format`                     | Resolved image format (e.g. `jpg`, `png`, `eps`, `tiff`, `svg`)       |
| `url`                        | **URL to the persisted image** — use this to download or preview it   |

---

## Step 4 — Download to Client and Preview

After a successful `download_stock_image` call, download the image locally and open it in VS Code.

**You MUST use `download-stock-image.py` for this. Do not use `curl`, `wget`, or any other tool.**

```bash
python3 scripts/download-stock-image.py \
  --url "<url from download response>" \
  --id "<assetId>" \
  --format "<format from download response>" \
  --preview
```

The script retrieves org credentials via the `sf` CLI (`sf config get target-org` and `sf org auth show-access-token`), downloads the image with `Authorization: Bearer <accessToken>` to `stockimages/<assetId>.<format>`, and opens it in VS Code if `--preview` is passed.

Pass `--output-dir <path>` to override the default `stockimages/` directory.

**Never resize or post-process the image.** Use CSS (`width`, `height`, `object-fit`) to control display dimensions.

**Vector/binary formats (`eps`, `tiff`):** always pass the exact `format` returned by the download response — never substitute a format like `jpg` to work around a validation error; the file bytes won't match the extension and the file will appear corrupted. VS Code cannot render `eps`/`tiff` previews, so the script skips `--preview` for those formats automatically and still reports the saved path.

---

## Step 5 — Report Back

After a successful download, tell the user:
- Image title and artist
- Local path to the saved image (printed by the script)
- `managedContentBodyId`
- Attribution: `{artist} · {collection}` (use the attribution string returned by the download response when present)

---

## Fallbacks & Errors

| Situation                          | Action                                                                       |
|------------------------------------|------------------------------------------------------------------------------|
| `errorMessage` non-null in search  | Show it; suggest a simpler query or different `searchType`/`orientation`     |
| `images` empty                     | Suggest broader keywords; try switching `Editorial` vs `Creative`            |
| `effectiveQuery` differs           | Inform user what the search service actually received                        |
| MCP tools unavailable              | Use the placeholder URL below — do not download or save                      |
| Download fails                     | Show error; do NOT retry automatically — confirm with user first (each retry is billed) |

---

## Placeholder

If `search_stock_images` and `download_stock_image` are both unavailable, use this URL directly as `src` or CSS `url()`:

```text
https://cdn.scs.static.lightning.force.com/content/assets/d5222d4a11e6c2b735152d7eea824ce4/placeholder.svg
```

**Placeholder policy:** There is only one placeholder URL. Do not download it, modify it, or generate alternative placeholders using Python, ImageMagick, or any other tool. If the user asks for a placeholder of a specific size or format, tell them only this URL is available and direct them to use CSS to scale it at the point of use.

More General & Other skills

← All General & Other skills

Check your AI visibility

One URL in, a 0–100 score and the exact fixes out.

RUN THE CHECK

Browse all the tools

15 tools across six categories
13 of them never send your data anywhere

Free · No signup · No trial clock

SEE THE DIRECTORY