Content
# Icons8 — Agent Skills
Nine [Agent Skills](https://agentskills.io) that give coding agents taste, first when picking
Icons8 artwork and then when looking at what they built with it. `icons8` and `ouch` keep a project
on **one consistent set** instead of a pile of mismatched pieces; the seven that follow check the
finished screen and fix what they find from the same catalogue.
Ships as a Claude Code plugin that bundles the [Icons8 MCP server](https://github.com/icons8/icons8-mcp)
(420,000+ icons across 132 styles). Installing it is the whole setup: sign in through the browser
once on first use, and search and high-res PNG are free from there. No API key to paste.
## Why
The MCP server is a thin wrapper over the Icons8 search API. It gives an agent a handful of tools and no
judgement, and the default behaviour fails in three specific ways:
1. **Unfiltered search returns one metaphor in ten styles.** Asking for `delete` twelve times
returns the same trash can in twelve different packs — one idea, no alternatives, and whatever
gets picked won't match the icon picked five minutes earlier.
2. **Ranking is not taste-ranking.** `settings` puts four Apple logos above the plain gear;
`dashboard` puts a car dashboard gauge first. The API matches names and tags — it doesn't know
you're building a settings screen.
3. **SVG is the slow, paid path.** One call per icon, and payloads run from 600 characters to
46,000. PNG previews are free, instant, and need no MCP call at all.
The skill fixes all three: it lists every concept a screen needs *before* searching, picks one pack
for the whole project and locks it in `icons8.json`, filters every search by that pack so results are
ten different metaphors instead of ten styles of one, rejects the brand logos and machine parts that
search ranks first, previews on a free PNG contact sheet, and fetches SVG only for the approved
final set.
## Examples
Ask in plain words. The skills trigger by intent, so you do not have to name them.
- "Add icons to this dashboard, one consistent Icons8 set, 24px."
- "Illustrate the empty states with one Ouch! style."
- "Put an animated illustration in the hero of this landing page."
- "Check this screen: emoji icons, missing images, contrast."
- "Review the button labels and error messages on this signup form."
## Install
### Claude Code
```
/plugin marketplace add icons8/agent-skills
/plugin install icons8@icons8
```
That registers both the skill and the Icons8 MCP server. Approve the server on first use, sign in
when the browser opens, and start asking for icons. `/mcp` signs in again later if you need it.
### OpenAI Codex
```
codex plugin marketplace add icons8/agent-skills
```
Then install **icons8** from the plugin browser (`/plugins`, or the Plugins section in the Codex app).
The skill triggers by intent — just ask for icons; slash commands are Claude Code-only.
The plugin **bundles the MCP server here too**, so installing it registers `icons8mcp` — check with
`codex mcp list`, and sign in with `codex mcp login icons8mcp`. `.codex-plugin/plugin.json` points
`mcpServers` at the root `./mcp.json`, the file every Agent Plugins v1 client reads. Claude reads its
own `.mcp.json` instead. Both files declare the same server, and CI fails if their URLs differ.
On an older Codex that doesn't read `mcpServers` from a plugin manifest, add it yourself:
```
codex mcp add icons8mcp --url https://mcp.icons8.com/mcp/
```
or in `~/.codex/config.toml`:
```toml
[mcp_servers.icons8mcp]
url = "https://mcp.icons8.com/mcp/"
```
Either way the server has to be there: icon ids come from `search_icons` and nowhere else, so without
it the skill reports that it isn't connected rather than guessing an id.
### Any Agent Plugins v1 client
The repository root is a conforming [Agent Plugins v1](https://agent-plugins.org/specification)
package: `plugin.json` is the portable manifest, `mcp.json` declares the Icons8 server, and `skills/`
is the location the spec fixes for skill discovery. Clients on the
[compatible clients](https://agent-plugins.org/compatible-clients) list pick up both the skill and
the server from those files.
In **VS Code**, no marketplace is needed — run `Chat: Install Plugin From Source` from the Command
Palette and paste the repository URL. In **GitHub Copilot CLI**, `copilot plugin install`; what it
installs also shows up in VS Code. **Cursor** installs from marketplaces only, so it needs the plugin
listed in one — either Cursor's registry or a team marketplace imported from a repo.
`.claude-plugin/` and `.codex-plugin/` keep their manifests, because Claude Code isn't on the
compatible-clients list yet and Codex still reads its own. Codex points `mcpServers` at the root
`mcp.json`. Claude reads `.mcp.json`, which declares the same server as `http`: the Claude directory,
chat and Cowork accept `http` and reject the `streamable-http` name that Agent Plugins v1 requires.
### Any agent via npx
Using the community [`skills`](https://www.npmjs.com/package/skills) installer (installs the bare
skill, not the plugin/marketplace):
```
npx skills add icons8/agent-skills --skill icons8 -a claude-code
# -a codex to target Codex instead, or '*' for every detected agent; add -g for a global install
```
This route installs the skill alone, so no MCP server is registered — add it for your client following
the [icons8-mcp README](https://github.com/icons8/icons8-mcp#pick-your-plan). Until you do, the skill
has nothing to search and will say so.
## Pick your plan
**Free high-res PNG** — what the plugin bundles, once you sign in. The server exposes
`search_icons`, `list_categories`, `list_platforms`, `get_icon_png_url` and `get_icon_animation`, which is everything the
skill needs to choose a pack, build the contact sheet, and prototype straight from
`https://img.icons8.com/?id=…&format=png&size=24`. Free icon usage requires attribution — see the
[Icons8 license](https://icons8.com/license).
**Animated icons** come through `get_icon_animation`: gif and apng are free, Lottie counts as a paid
download. The skill keeps icons static by default and lets one play once on a click or a hover, half a
cycle each way on a toggle such as like, or while something loads; never on a loop, and with motion
that matches the action.
**Full SVG access** — [subscribe for $15](https://icons8.com/icons/pricing). There is no second
setup: the account you already signed in with carries the plan, and `get_icon_svg` appears alongside
the others. The skill's final step then inlines real SVG for the approved set.
If the agent still hands back PNG, sign in again so it picks up the new plan — `/mcp` in Claude Code,
`codex mcp login icons8mcp` in Codex, **Connect** in Cursor.
**A client without OAuth** — send an API key instead. The MCP tab of your Icons8 account has the
snippet with your key already in it, or write the header by hand:
```json
{
"mcpServers": {
"icons8mcp": {
"type": "http",
"url": "https://mcp.icons8.com/mcp/",
"headers": {
"Authorization": "Bearer YOUR_API_KEY"
}
}
}
}
```
In Claude Code the same thing is one command:
```bash
claude mcp add --transport http icons8mcp https://mcp.icons8.com/mcp/ \
--header "Authorization: Bearer YOUR_API_KEY"
```
A key skips the browser entirely, which is what you want on a build server or in CI where nobody is
around to sign in. If you set this up with a key before, leave it alone — it still works.
Without a paid plan the skill stays on the PNG path, which is its recommended path for prototyping
regardless of plan.
## What's inside
```
plugin.json # Agent Plugins v1 manifest — the portable one
mcp.json # the server in Agent Plugins v1 format (streamable-http): Codex, v1 clients
.mcp.json # the same server in Claude's format (http): Claude Code, chat, Cowork
.claude-plugin/ # Claude manifest, marketplace, and the directory listing icon
.codex-plugin/ # Codex manifest
.agents/plugins/ # Agent Plugins marketplace entry
skills/icons8/
├── SKILL.md # the loop, the rejection rules, criteria by context, gotchas
└── references/
├── PACKS.md # which pack for which job, outline+filled pairs, coverage numbers
├── VOCABULARY.md # concept → commonName map, verified visually, plus the traps
├── KITS.md # ready concept lists: SaaS UI, landing, ecommerce, dev docs, analytics
└── ANIMATION.md # when an icon may move, motion that matches the action, play-once Lottie
skills/ouch/
├── SKILL.md # the sequence, hard rules, the priority ladder, gotchas
├── references/
│ ├── STYLES.md # the 43-style first tier, the free tier in full, styles by surface
│ ├── SLOTS.md # slot kits per project type, thin subjects
│ ├── VOCABULARY.md # state → search query map, measured against the live server
│ ├── LAYOUT.md # the browser measurements behind the layout rules
│ └── ANIMATION.md # when a slot earns motion, formats, the source order that plays
└── scripts/measure.py # ground line, mass offset, saturation: one source of the formulas
skills/icons8-design/ # front door: routes a design request to the skill that owns it
skills/asset-check/ # four mechanical checks on what is on the page
skills/ux-check/ # behaviour, the six states, flows, the accessibility floor
skills/ux-writing/ # every string a user reads, with before/after patterns
skills/ui-polish/ # visual finish: radii, icons, contrast, focus, state styling
skills/motion/ # whether it should animate at all, then every timing value
skills/design-tokens/ # bootstrap a token system, then catch drift in counts
```
Reference files load on demand, so the cost of having them is close to zero until they're needed.
The three manifests describe the same plugin for three packaging formats, so `version` and
`description` have to move together. The server is declared in `mcp.json` and in `.mcp.json`, one
file per format, and the two URLs have to match.
## Checking what the agent built
Fetching the right icon is half the job. The other half is what happens to it on the page, and
that is what the rest of the skills do.
`asset-check` is the cheap one and runs on its own once a UI is built or changed: emoji standing in
for icons, sections that should carry a picture and carry none, dead placeholder images, and icon
imports whose names no longer exist in the library (that last one works on projects that use no
Icons8 asset at all). Five more go deeper, one territory each, and `icons8-design` is the front door
that picks between them so a narrow question does not load all of them.
Two properties make them usable rather than noisy. Every rule two skills could raise has exactly one
named owner, so one defect produces one finding. And when several run together the reports merge
into a single table with one verdict instead of five stacked lists.
They fix as well as report: where a finding is about an icon or an illustration, the replacement
comes from the catalogue through the MCP, already in place.
`icons8` and `ouch` do not reference any of this. Asking for an icon stays a one-skill job.
## The lock file
One pack per project is the whole point, and it has to survive across sessions and across agents.
The skill writes `icons8.json` next to the project and treats it as binding — no second pack, not
even for one extra icon:
```json
{
"version": 2,
"icons": {
"pack": "m_outlined",
"sizes": [16, 20, 24],
"color": "currentColor",
"items": { "settings": { "id": "82535", "commonName": "settings" } }
},
"illustrations": {
"style": "notion-line-art",
"slots": { "hero": { "id": "6a3d01f2fae3aa473512807f", "file": "assets/hero.svg" } }
},
"tokens": { "iconColor": "--foreground", "accent": "--primary", "radius": "--radius" }
}
```
One file for the whole project: the icon pack, the sizes in use, the illustration style with its
slots, and the names of the CSS variables assets are wired to. A lock written in the older shape
(`pack` at the top level) is still read as it was, and a separate `ouch.json` from earlier releases
is folded in on the next write rather than deleted.
Commit it. The next session picks up where this one left off.
## Illustrations: the `ouch` skill
The same discipline for [Ouch! illustrations](https://icons8.com/illustrations): hero images,
empty states, onboarding, 404s and docs spots, from a catalog of 348 styles. What it enforces,
each rule earned in test runs rather than declared:
- **The picture is about the product, not about the interface.** Every slot query carries the
product's own noun. Empty states show the missing container (an empty pot for a plant app),
never a happy owner of the thing the heading says is absent.
- **One style per project**, locked in `icons8.json` under `illustrations`, with named escapes: an existing page's style
always wins, and a public repo filters to `free_distribution: true`.
- **A first-tier shortlist of 43 styles** picked by the Icons8 side: a preference with named
exits, not a fence. Subject coverage outranks tone, and the skill's priority ladder says in
which order the rules give way.
- **Contrast gate** for non-white backgrounds, and layout rules measured in real browsers:
absolute box heights, `max-height` never upscales a small SVG, ground-line alignment for 3D
artwork. `scripts/measure.py` ships with the skill and does the measuring: Python 3 with
Pillow (`python3 -m pip install pillow`, `py -3 -m pip install pillow` on Windows, where
python.org's installer creates no `python3`, or `uv run` the script), plus Chrome or Edge to
rasterize SVG. PNG needs no browser.
- **Watermarked previews are for choosing; originals are fetched once, for the approved set.**
Presigned URLs live an hour and never go into a page.
- **Motion when the slot earns it.** Many styles also ship animated. The skill picks those, fetches
the real files through `get_illustration_animation`, and writes the sources in the order that
plays: `mp4-hevc` first, because Safari answers "probably" for webm too, takes whichever it sees
first and then cannot show the transparency. Lottie where the artwork has it.
**Server note:** the illustration tools (`search_illustrations`, `get_illustration_svg`,
`get_illustration_png_url`, `get_illustration_animation`, `list_illustrations_styles`,
`list_illustrations_categories`) are live on `mcp.icons8.com`, the still ones since 2026-09-07 and
`get_illustration_animation` with them. On a connection that does not expose them, the skill says so
and stops, per its own rules.
## What the plugin connects to
The plugin has no hooks and starts no background process. Everything below happens when a skill runs.
| Host | What goes there | What comes back |
|---|---|---|
| `mcp.icons8.com` | MCP tool calls: search words that describe the screen (for example "empty pot"), style and category filters, asset ids. Your Icons8 sign-in, through OAuth in the browser, or an API key if you set one. | Search results, icon SVG, links to files |
| `img.icons8.com` | An icon id, a format and a size, in the URL of a PNG, gif or apng file | The file |
| `ouch-prod-var-cdn.icons8.com`, `ouch-prod-src-cdn.icons8.com` | The address of an illustration preview or animation preview | The preview file |
| `*.r2.cloudflarestorage.com` | A presigned link that the MCP server issued, valid for one hour | The original illustration file |
The skills do not send your source code, your files or your conversation to any of these hosts.
Icons8 operates all of them; the last one is the Cloudflare R2 storage that holds Icons8 originals.
The [Icons8 privacy policy](https://intercom.help/icons8-7fb7577e8170/en/articles/7228039-privacy-policy) covers what the server keeps.
In your project, the skills write `icons8.json` (the lock file), the asset files you approve, and a
`sheet.html` contact sheet to choose from. They edit your UI code where you ask them to. When a
screen gets an animated icon, the page loads the lottie-web player from `cdn.jsdelivr.net` in the
visitor's browser; the plugin itself sends nothing there.
On your machine, the `ouch` skill can run `scripts/measure.py`. It reads image files, rasterizes SVG
with headless Chrome or Edge, writes rasters to a temporary directory and deletes them on exit. It
makes no network request. If you start it with `uv run`, uv downloads Pillow from PyPI first.
## Requirements
- A client that supports the Agent Skills standard (Claude Code, Codex, VS Code + Copilot, Cursor, …)
- Network access to `https://mcp.icons8.com/mcp/`
- An Icons8 account, signed in through the browser on first use
- An Icons8 API key **only** where the client cannot do OAuth, or on CI
## Support
Report a bug or a wrong icon choice in
[GitHub Issues](https://github.com/icons8/agent-skills/issues). Report a security issue privately
through the [Icons8 contact page](https://icons8.com/contact), not in a public issue. For your Icons8 account, plan or
billing, use the [Icons8 Help Center](https://intercom.help/icons8-7fb7577e8170). The Help Center
also explains [what the Icons8 MCP server is](https://intercom.help/icons8-7fb7577e8170/en/articles/13569445-what-s-the-icons8-mcp-server).
## License
Apache-2.0 — see [LICENSE](LICENSE) and [NOTICE](NOTICE).
The license covers this repository, not the icon artwork. Icons are licensed separately under the
[Icons8 license](https://icons8.com/license): free icons require attribution, SVG delivery requires
a paid plan. If the assets ship in a product, confirm the license before handing over paid icons.
Connection Info
You Might Also Like
No recommendations available