Icons8
Server Details
A coding agent searches the Icons8 library by keyword and style, then adds the selected icon or illustration to the project. Icons8 draws all of it: 420,000+ icons (130+ styles) and 110,000+ illustrations (340+ styles), so one project doesn't end up with mixed looks.
The server lives at https://mcp.icons8.com/mcp/ and signs people in through their Icons8 account in the browser. Downloading PNG is free as long as the project links back to Icons8. SVG is on the paid plan, and that plan makes the link optional.
- Status
- Healthy
- Uptime
- 46.8% over 41 days
- Last Tested
- Transport
- Streamable HTTP · MCP 2025-11-25
- URL
TDQS
Scored across 12 tools
Clear icon vs illustration split, and within each domain the format tools (svg, png, animation) target distinct outputs. However, get_icon_png_url vs get_icon_svg and their illustration counterparts both return image URLs and could be confused at a glance, though the descriptions push users toward the preferred format. list_platforms vs list_illustrations_styles are distinct but adjacent in purpose.
Consistent snake_case verb_noun pattern throughout (get_*, list_*, search_*). Minor asymmetry: list_categories omits 'icon' while list_illustrations_categories is explicit, so the resource isn't always named. Overall predictable.
12 tools is well-scoped for an icon/illustration search-and-fetch server. Each tool maps to a distinct format or listing operation and earns its place, with no redundant entries.
Covers search plus svg/png/animation retrieval and category/style/platform listing for both icons and illustrations, matching the domain well. No obvious dead ends, though there's no explicit quota or account-status tool, and full-size animated icon handling is deferred to search results.
Available Tools
12 toolsget_icon_animationGet icon animationARead-onlyInspect
Get an animated icon's motion, as Lottie, GIF or animated PNG.
Only an icon whose search result says isAnimated has one, and about one icon in fifty does. Find them with search_icons(animated=True). Every animated hit already carries permanent animation.gif and animation.apng links, so reach for this tool for the Lottie, or to learn what size a link actually renders at.
Pick by what you are building:
"lottie" returns the animation as compact Lottie/Bodymovin JSON text - parse it, then hand it to lottie-web, Rive, SwiftUI or Android. It is vector, so it scales to any size and
sizedoes not apply. Prefer it on the web - but it is the paid format, so it needs an Icons8 sign-in or a personal API key. "gif" and "apng" need none."gif" plays anywhere with no player.
"apng" keeps a real alpha channel, so it sits on a coloured background without a matte.
gif and apng come in one size: the one the icon's style draws at. Most styles ignore a requested size - m_outlined renders 24, ios11 30, color 48, office80 80 - and only a few scale. So ask without a size and use what comes back; the result says what it was. If you need a particular size, that is what Lottie is for.
Icons8 publishes no animated SVG for icons. An animated icon's SVG is a still frame, and so are its png, jpg and webp.
Args: icon_id: The id from a search_icons result (field icons[].id) ctx: MCP context for API access format: "lottie", "gif" or "apng" (default: "gif"). "lottie" needs a credential; the other two do not size: Pixels, for gif and apng only. Leave it out and you get whatever size this icon's style draws at, with "size" in the result saying which - that is the normal way to call this. Naming a size the icon is not drawn at is refused rather than returning a link that misstates it. A Lottie is vector, so this is not applied to it
Returns: For "lottie", a dictionary whose "lottie" is the animation as a compact JSON string - parse it before handing it to a player. For "gif" and "apng", a dictionary with a "url" that is permanent and needs no credential, and the "size" in pixels it renders at - absent only if the host answered something this server could not measure. On failure, an "error" saying what to ask for instead. A Lottie counts toward the paid-download limit: a refusal carries "retry_after_seconds" and the free "animation" links
| Name | Required | Description | Default |
|---|---|---|---|
| size | No | ||
| format | No | gif | |
| icon_id | Yes | Icon id from the results of search_icons (field icons[].id) |
Output Schema
| Name | Required | Description |
|---|---|---|
| url | No | Permanent gif or apng link. Absent for lottie and when error is set. |
| size | No | Pixel width the gif or apng renders at. Absent when the host answered something this server could not measure. |
| error | No | Set only on failure. |
| lottie | No | The animation as compact Lottie JSON text. Set only for format "lottie". |
| animation | No | Permanent gif and apng links. Set only when the download limit refused a lottie call. |
| retry_after_seconds | No | Seconds until the download limit resets. Set only when the limit refused the call. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only cover readOnly/openWorld; the description adds substantial behavioral context beyond that: 'lottie' requires an Icons8 sign-in or personal API key while gif/apng need none, Lottie counts toward a paid-download limit, refusals carry 'retry_after_seconds', and unavailable sizes are refused rather than silently misreported. Credential and rate-limit disclosure like this is exactly what annotations cannot express.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Well front-loaded and organized with a bolded sizing caveat and bulleted format selection, so it is easy to scan. It is nonetheless long for a 3-parameter tool, and the point that gif/apng links already come free is stated twice (once up top, once in the format list), which is mild redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given an output schema exists, the description still helpfully documents return shapes (parsed Lottie JSON string, permanent credential-free url plus size, error objects). Auth requirements, failure modes, and the size-omission default are all covered, leaving nothing an agent needs to call this correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is only 33% (only icon_id documented), so the description carries the burden and does it well: format values and their auth/implications, and size semantics including that Gif/APNG render at fixed per-style sizes (with concrete examples), that size is ignored for Lottie, and that mismatched sizes are refused.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Get an animated icon's motion') and immediately names the returned formats (Lottie, GIF, animated PNG). It cleanly distinguishes itself from siblings get_icon_svg and get_icon_png_url by explaining that those return still frames for animated icons.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly names the discovery path (search_icons(animated=True)), states the precondition (only isAnimated icons qualify, ~1 in 50), and tells the agent when NOT to use it (gif/apng links already come with animated hits, so use this for Lottie or sizing). It then gives per-format selection guidance for lottie vs gif vs apng with build context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_icon_png_urlGet icon PNG linkARead-onlyInspect
Get a PNG URL for an icon by its ID - use when SVG is not available. NOTE: SVG format is preferred for Icons8 icons when possible (use get_icon_svg).
An animated icon's PNG is a still frame. Use get_icon_animation for the motion.
Args: icon_id: The id from a search_icons result (field icons[].id) ctx: MCP context for API access size: The preview image size in pixels (default: 24)
Returns: Dictionary containing the PNG preview URL
| Name | Required | Description | Default |
|---|---|---|---|
| size | No | ||
| icon_id | Yes | Icon id from the results of search_icons (field icons[].id) |
Output Schema
| Name | Required | Description |
|---|---|---|
| url | Yes | Permanent PNG link of the icon at the asked size. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, so the safe-read profile is covered. The description adds one genuinely useful behavioral caveat ('An animated icon's PNG is a still frame'), but does not disclose URL permanence, auth needs, or any other runtime behavior beyond that single note.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Core guidance is front-loaded and useful, but the 'Args:' and especially 'Returns:' block duplicate information already present in the input and output schemas, and the 'ctx' arg is an internal detail that does not belong in an agent-facing description. Some trimming would sharpen it.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With annotations covering the safety profile and an output schema covering return values, the description's job is to add selection and caveat context, which it does well. It is essentially complete for a simple URL-fetch tool; only minor details like URL lifetime are absent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 50% (icon_id documented, size not), so the description must compensate. It does: it explains size as 'The preview image size in pixels (default: 24)' and restates the icon_id source. Minor noise from mentioning 'ctx' as an argument that is not in the schema keeps this below a 5.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Get a PNG URL for an icon by its ID') and immediately distinguishes itself from siblings by naming get_icon_svg as the preferred format and get_icon_animation for motion. An agent can select this tool without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states when to use ('use when SVG is not available'), when not to ('SVG format is preferred ... use get_icon_svg'), and the alternative for animated content ('Use get_icon_animation for the motion'). Nothing is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_icon_svgGet icon SVGARead-onlyInspect
Get an icon as SVG by its ID - PREFERRED FORMAT for Icons8 icons. SVG format provides scalable, crisp icons suitable for web applications. Personal API key is required for SVG access.
RECOMMENDED: Use this tool instead of PNG when possible for better quality and scalability.
An animated icon's SVG is a still frame - Icons8 publishes no animated vector. The result then carries a "note" saying so and an "animation" block with the motion, so no further call is needed.
Args: icon_id: The id from a search_icons result (field icons[].id) ctx: MCP context for API access
Returns: Dictionary containing the SVG content. For an animated icon it also carries a "note" saying the SVG is a still frame and an "animation" block of permanent gif and apng links. On failure, an "error" describing what the Icons8 API said - a rejected key is reported, not returned as an empty icon. Counts toward the paid-download limit: a refusal carries "retry_after_seconds" and a free PNG "url"
| Name | Required | Description | Default |
|---|---|---|---|
| icon_id | Yes | Icon id from the results of search_icons (field icons[].id) |
Output Schema
| Name | Required | Description |
|---|---|---|
| svg | No | SVG markup of the icon. Absent when error is set. |
| url | No | Free 24px PNG link. Set only when the download limit refused the call. |
| note | No | Set only for an animated icon: the SVG is a still frame. |
| error | No | Set only on failure. |
| animation | No | Permanent gif and apng links. Set for an animated icon, and when the download limit refused the call. |
| retry_after_seconds | No | Seconds until the download limit resets. Set only when the limit refused the call. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnlyHint=true), and the description adds substantial non-obvious behavior: API key requirement, the still-frame caveat for animated icons plus the accompanying note/animation block, error surfacing, and the paid-download limit with retry_after_seconds and free PNG fallback.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the purpose and the format preference, and the behavioral caveats earn their space. The 'PREFERRED FORMAT' and 'RECOMMENDED' lines say the same thing twice, and the Args/Returns boilerplate is partly redundant with the schema and output schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a paid, key-gated fetch tool this is complete: it covers the id source, error/limit behavior, and the animated-icon edge case. An output schema exists, yet the return-shape notes add value rather than padding.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% for the single icon_id parameter, and the description only restates its provenance (icons[].id from search_icons) with no added format or syntax detail. Baseline 3 is appropriate when the schema fully carries the parameter.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (get) and resource (icon SVG) by ID, and explicitly frames itself as the preferred SVG format versus the PNG sibling. An agent can distinguish it from get_icon_png_url without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit recommendation ('Use this tool instead of PNG when possible') with the reason (quality/scalability), and names the source of the required id (search_icons results). The alternative is named and the selecting condition is stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_illustration_animationGet illustration animation linkARead-onlyInspect
Get an animated illustration as a video, a GIF, or a Lottie animation.
ONLY for an illustration whose media_types includes "animated" - check
a search_illustrations result first. A static illustration has no
animated format, and every format here answers "not found" for it.
THIS is what you publish. The animation links in a search result are
a 368px preview with no transparency, and watermarked unless the account
is entitled to the illustration; the file this tool returns is full
size, transparent, and never watermarked. Reach for the search links
while choosing, and for this tool once the choice is made.
Formats, and where each one actually plays:
"webm" (default) - VP9 with an alpha channel. Chrome, Firefox, Edge. This is the one to reach for first
"mp4-hevc" - HEVC with an alpha channel, in an .mp4 container. Safari only: do NOT make it the single source of a , Chrome and Firefox will show nothing
"prores" - ProRes 4444 in a .mov, around 55 MB. A mastering file for a video editor, never for a web page
"gif" - full-size GIF, no transparency worth relying on
"gif-low" - a smaller GIF, and the ONLY animated format that needs no account. Roughly a third of animated illustrations have none, and nothing in a search result says which
"lottie" - a Lottie JSON to render in code. Legacy: illustrations added from 2024 onwards almost never carry it
"aep" - the After Effects project the animation was built from
TO PUT AN ANIMATION ON A PAGE, offer both web formats. One alone covers roughly half the browsers. The order is load-bearing: mp4-hevc first.
<video autoplay loop muted playsinline poster="...">
<source src="....mp4" type="video/mp4; codecs=hvc1">
<source src="....webm" type="video/webm">
</video>Safari answers canPlayType "probably" for webm as well, takes whichever source comes first, and then cannot show VP9's alpha - so a webm listed first gives Safari a black rectangle. Chrome and Firefox skip the HEVC source and fall through to the webm, so putting it first costs them nothing.
The names are this server's, not the API's, and they are deliberately not
the API's: upstream, mov-avc returns ProRes and mov-hevc returns an
.mp4, so the upstream names describe neither the container nor the codec.
WHICH FORMATS AN ILLUSTRATION HAS VARIES, and two illustrations in the same style often disagree. Do not probe them one by one: ask for the one you want, and if it is missing the answer names every format this illustration does have, so one refusal is enough to choose again.
Every format except "gif-low" needs a signed-in Icons8 account whose plan covers the illustration.
The URL is presigned and expires in one hour - download it now, do not
store it. For a link to keep, use animation.webm from the search result.
Args: illustration_id: The id from a search_illustrations result (field illustrations[].id) ctx: MCP context for API access format: One of webm, mp4-hevc, prores, gif, gif-low, lottie, aep
Returns: {"url", "width", "height", "expires_in_seconds"}, or {"error"} explaining what would unlock the format. Every format but gif-low counts toward the paid-download limit: a refusal carries "retry_after_seconds".
| Name | Required | Description | Default |
|---|---|---|---|
| format | No | webm | |
| illustration_id | Yes | Illustration id from the results of search_illustrations (field illustrations[].id) |
Output Schema
| Name | Required | Description |
|---|---|---|
| url | No | Presigned download link. Valid for expires_in_seconds. Absent when error is set. |
| error | No | Set only on failure. |
| width | No | Pixel width of the file. |
| height | No | Pixel height of the file. |
| expires_in_seconds | No | Seconds the url stays valid. One hour. |
| retry_after_seconds | No | Seconds until the download limit resets. Set only when the limit refused the call. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only cover readOnlyHint/openWorldHint; the description adds the substantive behavioral facts: presigned URL expires in one hour, every format except gif-low requires a paid account, every format but gif-low counts toward the paid-download limit, refusals carry retry_after_seconds, and per-format caveats (mp4-hevc Safari-only, prores ~55MB mastering file, gif-low has no transparency). This is far beyond what annotations provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose and the critical 'animated only' constraint, and nearly every section earns its place given seven format values. It is nonetheless long, and the digression on upstream naming (mov-avc/mov-hevc) and the extended Safari canPlayType rationale carry more detail than an agent strictly needs to select and invoke the tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, and the description still summarizes the return shape ({url, width, height, expires_in_seconds}) and the error shape including retry_after_seconds. Auth requirements, expiry, format availability variability, and browser-compatibility guidance are all covered, leaving no material gap for a two-parameter tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 50% and the schema gives no meaning for the format parameter, so the description carries it: all seven enum-like values (webm, mp4-hevc, prores, gif, gif-low, lottie, aep) are explained with container, codec, transparency, target environment, and default. The illustration_id origin (illustrations[].id) is also restated from the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb+resource ('Get an animated illustration as a video, a GIF, or a Lottie animation') and immediately scopes it to illustrations whose media_types include 'animated', which separates it from the static get_illustration_png_url/get_illustration_svg siblings. The contrast with the search_illustrations preview links further pins down what this tool uniquely produces.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit when-to-use and when-not-to-use: 'ONLY for an illustration whose media_types includes "animated" - check a search_illustrations result first', and 'Reach for the search links while choosing, and for this tool once the choice is made.' It also tells the agent not to probe formats one by one and explains that a single refusal enumerates the available formats.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_illustration_png_urlGet illustration PNG linkARead-onlyInspect
Get a PNG URL for an illustration - use when SVG is not available to you. NOTE: SVG is preferred where you can get it (use get_illustration_svg).
Sizes: "low" (a small preview), "standard" (a mid-size raster), "hd"
(the largest). "low" and "standard" work for everyone; "hd" needs an
account whose plan covers this illustration, the same as SVG. The exact
pixel dimensions depend on the illustration - read width/height from
the response rather than assuming a fixed size.
The URL is presigned and expires in one hour. For a link to keep, use the
permanent preview.url in a search result.
Args: illustration_id: The id from a search_illustrations result (field illustrations[].id) ctx: MCP context for API access size: "low", "standard" (default) or "hd"
Returns: {"url", "width", "height", "expires_in_seconds"}, or {"error"}. "hd" counts toward the paid-download limit: a refusal carries "retry_after_seconds".
| Name | Required | Description | Default |
|---|---|---|---|
| size | No | standard | |
| illustration_id | Yes | Illustration id from the results of search_illustrations (field illustrations[].id) |
Output Schema
| Name | Required | Description |
|---|---|---|
| url | No | Presigned download link. Valid for expires_in_seconds. Absent when error is set. |
| error | No | Set only on failure. |
| width | No | Pixel width of the file. |
| height | No | Pixel height of the file. |
| expires_in_seconds | No | Seconds the url stays valid. One hour. |
| retry_after_seconds | No | Seconds until the download limit resets. Set only when the limit refused the call. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only cover readOnly/openWorld; the description adds substantive behavior: the URL is presigned and expires in one hour, 'hd' requires a plan that covers the illustration, 'hd' counts against the paid-download limit, and refusals carry retry_after_seconds. It also warns that pixel dimensions vary and must be read from the response rather than assumed. This is well beyond what the annotations disclose.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the core action and the sibling preference, then layers size, lifetime, args and returns in scannable blocks. The Args/Returns sections are compact and every sentence carries operational information an agent needs.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Complete for a read-only URL-minting tool: it covers access gating, expiry, quota/retry behavior, and the return shape (url/width/height/expires_in_seconds or error). Only the 'ctx' arg is left at a general gloss, which is standard MCP plumbing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is only 50% (size has no schema description), and the description compensates fully: it enumerates the three size values, marks 'standard' as default, and explains the access tier that gates 'hd' plus its quota impact. illustration_id's provenance is restated consistently with the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Get a PNG URL for an illustration') and immediately positions it against the sibling get_illustration_svg with the qualifier 'use when SVG is not available to you'. An agent can distinguish it from get_icon_png_url and the SVG variants without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit when-to-use ('when SVG is not available to you'), names the preferred alternative ('SVG is preferred where you can get it - use get_illustration_svg'), and routes the persistence use case to 'preview.url' in a search result. Nothing is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_illustration_svgGet illustration SVG linkARead-onlyInspect
Get an illustration as SVG - PREFERRED FORMAT for Icons8 illustrations. SVG scales to any size without losing quality. A paid illustration needs a signed-in Icons8 account whose plan covers illustrations; anything with free_distribution: true needs no account at all.
RECOMMENDED: Use this tool instead of PNG when possible for better quality and scalability.
Returns a download URL rather than the file - an illustration's SVG can
be large, and the file size depends on the source, so it is not inlined.
The URL is presigned and expires in one hour - download it now, do not
store it. For a link to keep, use the permanent preview.url in a search
result.
Args: illustration_id: The id from a search_illustrations result (field illustrations[].id) ctx: MCP context for API access
Returns:
{"url", "width", "height", "expires_in_seconds"}, or {"error"}
explaining what would unlock the format. Read width/height from
the response for the actual pixel size - it varies by illustration.
Counts toward the paid-download limit: a refusal carries
"retry_after_seconds".
| Name | Required | Description | Default |
|---|---|---|---|
| illustration_id | Yes | Illustration id from the results of search_illustrations (field illustrations[].id) |
Output Schema
| Name | Required | Description |
|---|---|---|
| url | No | Presigned download link. Valid for expires_in_seconds. Absent when error is set. |
| error | No | Set only on failure. |
| width | No | Pixel width of the file. |
| height | No | Pixel height of the file. |
| expires_in_seconds | No | Seconds the url stays valid. One hour. |
| retry_after_seconds | No | Seconds until the download limit resets. Set only when the limit refused the call. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the readOnlyHint/openWorldHint annotations: returns a presigned URL that expires in one hour, must be downloaded not stored, requires an account whose plan covers illustrations, counts toward a paid-download limit, and refusals carry retry_after_seconds. Rich behavioral context an agent needs before calling.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose and recommendation, then behaviors, then args/returns. Well organized and mostly earning its place, though the Returns block partly duplicates the output schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, yet the description still frames the return shape and the refusal path usefully. Combined with the expiry and account constraints, an agent has everything needed to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Only one parameter and schema coverage is 100%, so the schema already documents illustration_id fully. The description restates the same guidance (id from search_illustrations results, illustrations[].id) without adding format or validation detail beyond the schema. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (get) and resource (illustration SVG link) and explicitly positions itself as the preferred format against the PNG sibling. An agent can distinguish it from get_illustration_png_url without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit guidance: use this instead of PNG when possible, note the account/plan requirement for paid illustrations versus free_distribution: true needing no account, and route to preview.url for a permanent link. Names the alternative and the condition that selects it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_categoriesList icon categoriesBRead-onlyInspect
List all available icon categories.
Args: ctx: MCP context for API access limit: Maximum number of results to return (default: 10) page: Page number for pagination (default: 1)
Returns: List of icon categories with subcategories
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | ||
| limit | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| docs | No | Icon categories of the requested page. Absent when error is set. |
| error | No | Set only on failure. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered. The description adds little beyond that: the 'Returns' note duplicates the existing output schema, and the defaults duplicate the schema. It does not mention ordering, item counts, or pagination edge cases.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded one-line purpose followed by short Args/Returns sections; easy to scan. The 'ctx' line is unnecessary since it is not a user-facing parameter, but overall the text is tight.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only paginated list with an output schema present, the description covers purpose and pagination semantics. Nothing critical is missing, though it could have noted sibling alternatives.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description carries the param burden and does so adequately: it explains that 'limit' caps results (default 10) and 'page' selects the page (default 1). It also mentions a 'ctx' argument that is not in the schema, which is slightly noisy but harmless.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('List all available icon categories'), which is clearly distinct from the illustration and search siblings. It does not, however, explicitly contrast itself with the other list_* tools (platforms, illustration categories/styles).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
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 list_illustrations_categories, list_platforms, or search_icons. An agent must infer the context from the name alone.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_illustrations_categoriesList illustration categoriesARead-onlyInspect
List all available illustration categories.
Categories are subjects: animal, business, education, healthcare and so
on, each with subcategories. Pass a category's pretty_id to
search_illustrations to narrow a broad search word.
Args: ctx: MCP context for API access limit: Top-level categories per page (default: 10) page: Page number, 1-based (default: 1) parent_id: Optional category pretty_id, to narrow to that category
Returns: {"total", "categories"} where each category has pretty_id, title, illustrations_count and nested children - or {"error"}. With parent_id set, the one result is that category itself, with its children nested inside rather than listed at the top level.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | ||
| limit | No | ||
| parent_id | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| error | No | Set only on failure. |
| total | No | Number of top-level categories. |
| categories | No | Categories of the requested page. Absent when error is set. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and openWorldHint=false, and the description adds useful behavior beyond that: default page size, 1-based paging, and the notable semantic shift when parent_id is set (the single result is that category with children nested rather than listed at top level). Return shape is also disclosed.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the purpose, then the category concept, then the routing hint, then Args/Returns. Efficient overall, though the Returns block is partly redundant with the existing output schema and the 'ctx: MCP context' arg line is boilerplate.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only, three-parameter, no-required-args listing tool with an output schema, the description covers purpose, argument meaning, pagination, and the parent_id nesting quirk. An agent has everything needed to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries the full burden, and it does: limit is top-level categories per page (default 10), page is 1-based (default 1), and parent_id is an optional category pretty_id that narrows the result. Every argument gains meaning the schema alone does not provide.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource (list illustration categories) and defines what a category is: a subject like animal or business with subcategories. It is clear on its own, but it does not contrast itself with the adjacent sibling list_categories, which an agent could easily confuse with this one.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives clear downstream context: pass a category's pretty_id to search_illustrations to narrow a broad search word, and explains that parent_id narrows to a category. This routes usage well, but there are no explicit exclusions or comparisons against list_categories / list_illustrations_styles.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_illustrations_stylesList illustration stylesARead-onlyInspect
List all available illustration styles.
Style is what keeps a set of illustrations looking like one family. Pick
one style and pass its pretty_id to search_illustrations for every
illustration in a project, the way you would keep to a single icon
platform.
Args:
ctx: MCP context for API access
limit: Styles per page (default: 50)
page: Page number, 1-based (default: 1)
free_only: Only styles whose illustrations a free Icons8 account can
use and redistribute. A style without this flag needs a paid
account - the ordinary case for a subscriber, not a style this
user is barred from
animated: True for animated styles only, False for static only.
THIS IS A PROPERTY OF THE STYLE, NOT A COUNT. It says the style
has video and animation formats at all - it does not say how many
of its illustrations actually move, and usually very few do:
measured on stage, 3d-business carries the flag with 19
animated illustrations out of 1497, flexy 15 out of 561, and
node carries it with none at all yet. So use it to browse
styles, and use search_illustrations(animated=True) to find
illustrations that move - that one filters on media_types,
which is the per-illustration answer
Returns: {"total", "styles"} where each style has pretty_id, title, illustrations_count, free_distribution and animated - or {"error"}
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | ||
| limit | No | ||
| animated | No | ||
| free_only | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| error | No | Set only on failure. |
| total | No | Number of styles that match, before paging. |
| styles | No | Styles of the requested page. Absent when error is set. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the read-only/non-open-world safety profile, but the description adds behavioral context the annotations cannot: free_only's licensing semantics (paid account needed, and explicitly that a lack of the flag is not a bar for a subscriber) and the counterintuitive nature of the animated flag with measured examples (3d-business 19/1497, node 0 yet flagged). This is the kind of non-obvious behavior that prevents misuse.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose before mechanics, and the Args/Returns structure is scannable. It is longer than needed in places – the animated explanation restates 'property of the style, not a count' twice and adds a folksy icon-platform analogy – but the verbosity is mostly load-bearing given 0% schema coverage.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, yet the description still sketches the return shape ({total, styles} with pretty_id, title, illustrations_count, free_distribution, animated) so the agent knows exactly which field feeds the next call. For a paged, filtered list tool with four undocumented params, nothing needed to invoke it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries the full burden and does: limit (styles per page, default 50), page (1-based, default 1), free_only (distribution licensing meaning), and animated (a property of the style, not a count, with the distinction mapped to media_types). All four undocumented parameters are given meaning beyond their names and types.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('List all available illustration styles') and immediately explains the resource's role in the workflow (family consistency, pretty_id passed to search_illustrations). An agent can distinguish it from list_illustrations_categories and list_platforms without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Names the downstream consumer explicitly ('pass its pretty_id to search_illustrations for every illustration in a project') and provides an explicit when/when-not routing rule: use this tool to browse styles, but use search_illustrations(animated=True) to find illustrations that actually move. That is a concrete alternative selection rule, not an implication.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_platformsList icon stylesBRead-onlyInspect
List all available icon platforms/styles.
Args: ctx: MCP context for API access limit: Maximum number of results to return (default: 100) page: Page number for pagination (default: 1)
Returns: List of icon platforms/styles
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | ||
| limit | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| docs | No | Icon platforms (styles) of the requested page. The apiCode of each is the value of platform in search_icons. Absent when error is set. |
| error | No | Set only on failure. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered. Beyond that the description contributes nothing behavioral — no rate limits, no note on whether the full set is always returned, no pagination semantics beyond the raw argument list. It neither contradicts nor enriches the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose is front-loaded in a single sentence, followed by a compact Args/Returns block. Minor waste exists in the 'ctx: MCP context for API access' line and in restating the return as 'List of icon platforms/styles' right after saying it lists them, but overall it is tight.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only listing tool with an output schema (so return shape need not be spelled out) and fully described parameters, the definition covers what an agent needs to invoke it correctly. The remaining gap is sibling disambiguation, which is a usage-guideline concern rather than a completeness failure.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must carry the parameters, and it does: it explains 'limit' as maximum results (default 100) and 'page' as the pagination page (default 1). This compensates for the undocumented schema fields, though it adds no edge-case meaning (e.g., max limit, behavior past the last page).
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource ('List all available icon platforms/styles'), so an agent can tell it is a listing/read tool. However, it does not differentiate itself from sibling list tools such as list_categories or list_illustrations_styles, and the name ('platforms') versus title ('icon styles') creates mild ambiguity about what is actually enumerated.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no when-to-use guidance, no prerequisites, and no mention of when a caller should prefer this over search_icons or the other list_* siblings. The only implicit signal is 'all available', which is a scope statement rather than usage direction.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_iconsSearch iconsARead-onlyInspect
Search for icons using the Icons8 API - the ONLY source for genuine Icons8 icons. Use English terms and consider Icon8's metaphors for better results.
SEARCH TIPS - Use these general approaches for better matches: • Use simple, descriptive terms (e.g., "home", "user", "settings") • Try action words for functions (e.g., "search", "download", "edit") • Use object names for items (e.g., "phone", "computer", "car") • Consider synonyms if first search doesn't work • Think about what the icon represents conceptually • Use single words or short phrases for best results
Args: query: The search term to find icons (use metaphors above for better results) ctx: MCP context for API access platform: Optional filter by platform/style (e.g., 'ios', 'fluent', 'color') category: Optional filter by category (e.g., 'transport', 'business') animated: Optional filter for icons that move. True returns only animated icons, False only static ones, and the default returns both. About one icon in fifty is animated. An animated result carries permanent animation.gif and animation.apng links that need no credential, so embedding one takes no further call. They render at the icon style's own size, whatever it is - do not upscale them, and call get_icon_animation if you need the number amount: Maximum number of results to return (default: 10) offset: Number of results to skip (for pagination)
Returns:
{"icons": [...]} or {"error"}. Each entry of icons carries id:
pass it as icon_id to get_icon_svg, get_icon_png_url or
get_icon_animation. It is the only way to get an icon's id.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | ||
| amount | No | ||
| offset | No | ||
| animated | No | ||
| category | No | ||
| platform | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| note | No | |
| error | No | Set only on failure. |
| icons | No | Matching icons. Absent when error is set. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the readOnlyHint/openWorldHint annotations: it discloses the ~1-in-50 animation rarity, that animated results carry credential-free animation.gif/apng links needing no further call, that they must not be upscaled, and that the response is either {icons:[...]} or {error}. That is exactly the operational detail annotations cannot carry.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded and readable, but the six SEARCH TIPS bullets are largely paraphrases of each other ('simple, descriptive terms', 'action words', 'object names', 'synonyms', 'conceptually', 'single words'), so several sentences don't earn their place. Claiming to be 'the ONLY source for genuine Icons8 icons' adds no decision-relevant information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a six-parameter search tool with an output schema, it covers everything an agent needs: query formulation, all filters, pagination, the interlock with the get_icon_* siblings via icon_id, and the error return. Nothing required to invoke it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries the whole burden and does: platform and category get example values ('ios', 'fluent', 'color'; 'transport', 'business'), offset is explained as pagination, amount as a maximum/cap, and animated gets non-obvious tri-state semantics (True/False/default) plus the note that about one icon in fifty is animated.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Search for icons') and scopes the source ('using the Icons8 API'), and the Returns section routes to the correct sibling tools (get_icon_svg, get_icon_png_url, get_icon_animation). It never distinguishes itself from the parallel search_illustrations sibling, so an agent choosing between icon and illustration search gets no explicit help.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives concrete usage context via the SEARCH TIPS block and names follow-up tools when more data is needed ('call get_icon_animation if you need the number'). There is no when-not-to-use guidance and no routing to search_illustrations or list_categories/list_platforms for browsing instead of searching.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_illustrationsSearch illustrationsARead-onlyInspect
Search Icons8 illustrations - the ONLY source for genuine Icons8 illustrations.
Illustrations are full scenes with people, objects and backgrounds. Reach for one when a page needs a hero image, an empty state, an onboarding step or a spot illustration. For a small symbol in a button, a menu or a table, use search_icons instead.
Every result carries preview.url: a permanent CDN link (webp) you can
embed directly. It never expires and needs no second call. Use
get_illustration_svg or get_illustration_png_url only when you need the
original asset rather than a preview.
Some illustrations are animated. A result says so in media_types, and
almost all of those carry an animation block: webm and mov play
the animation, poster is the still frame. They are previews - see
below for what that costs - and get_illustration_animation is what
returns a file to publish, along with the markup to publish it
with.
animation.lottie says whether a Lottie JSON exists for this
illustration, so you need not spend a call to find out. It is worth
checking: Lottie is missing from most work added since 2024, and two
illustrations in the same style often disagree about it. When it is
false, do not ask get_illustration_animation for "lottie".
MIND THE SIZE, AND READ IT FROM THE BLOCK. The animation links are
previews, 368x368 - fine for a spot, a card or a list row, too small for
a hero banner or a full-width section. Do not infer the size from
preview: the still preview is not square for about a third of
illustrations, while the animation always is. When the slot is large,
use poster (1200x1200, a still) or call get_illustration_animation for
the full-size video.
THE ANIMATION LINKS ARE FOR CHOOSING, NOT FOR SHIPPING. Two limits, and both are invisible until the page is built:
No transparency.
webmandmovhere are flat against an opaque #F7F7F7, and the previewmovcarries no alpha layer at all. On a coloured or dark section they render as a light-grey rectangle; on a hero they are 368px. Onlyposteris transparent.A watermark, unless the account is entitled to the illustration.
animation.watermarkedsays which you got, for these links, in this response: false means "Icons8 Ouch" is not tiled across the frame. It is false for a subscriber, and for anything withfree_distribution: truewhoever asks. It says nothing about the size or the transparency above, which apply either way.
Use them to pick an illustration, and poster where a still will do.
For anything that ships, call get_illustration_animation and host the
file: it is full size, transparent, and never watermarked.
A few animated illustrations carry no animation block at all, so read
the block, do not assume it.
SEARCH TIPS:
Describe the scene, not the symbol: "team meeting", "online payment"
One or two words work better than a sentence
Pass
styleto keep a whole project on one visual family - get the available values from list_illustrations_stylesPass
categoryto narrow a broad word - "cat" alone returns over a thousand hits; in category "animal" it returns far fewer, and in "business" fewer still. Values come from list_illustrations_categoriesPass free_only=True for illustrations a free Icons8 account can use
ABOUT free_distribution IN THE RESULTS - do not warn the user about
licensing based on it:
true means the illustration is available on a free Icons8 account and free to redistribute: the user may use and share it without a licence. Ouch skips the entitlement check for these and does not count them against a subscriber's allowance
false means it needs a paid account. For a subscriber that is the ordinary case - available, and counted against their allowance. It does NOT mean this user cannot have it, and it does NOT mean some second licence beyond their subscription is required Whether this user may download something is decided by the download call, not by this flag. Ask for the asset; if it is refused, the error says exactly what is missing. Never turn
free_distribution: falseinto a licence warning of your own.
Args:
query: What the illustration should show (max 150 characters)
ctx: MCP context for API access
style: Optional style pretty_id from list_illustrations_styles
category: Optional category pretty_id from list_illustrations_categories
free_only: Only illustrations a free Icons8 account can use and
redistribute without a licence
animated: True for animated only, False for static only. Nearly every
animated result carries an animation block - permanent WebM and
HEVC links you can embed directly, plus a poster frame - but a
few carry none, and some carry the poster without the video, so
check the block rather than assuming its keys. For the full-size
original, use get_illustration_animation.
amount: Results per page (default: 10, max: 100)
page: Page number, 1-based (this API paginates by page, not offset)
Returns:
{"total", "illustrations"}, each entry carrying id, heading, styles,
tags, media_types and a permanent preview link - plus an animation
block when media_types includes "animated" - or {"error"}. id is
what get_illustration_svg, get_illustration_png_url and
get_illustration_animation take as illustration_id; it is the only
way to get an illustration's id.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | ||
| query | Yes | ||
| style | No | ||
| amount | No | ||
| animated | No | ||
| category | No | ||
| free_only | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| error | No | Set only on failure. |
| total | No | |
| illustrations | No | Matching illustrations. Absent when error is set. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations give only readOnlyHint=true and openWorldHint=false; the description adds substantial non-structured behavior: preview URLs are permanent/no-second-call, animation previews are fixed 368x368, webm/mov are flat opaque #F7F7F7 with no alpha while poster is transparent, watermark state is exposed via animation.watermarked, and preview links are explicitly not for shipping. This is exactly the kind of behavioral disclosure the dimension rewards.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose and the sibling routing are well front-loaded, but the body is bloated and repeats the 'previews are for choosing, not shipping' theme at least twice, and restates the animation-block caveat in both the prose and the Args section. Most sentences carry real information, yet the ALL-CAPS warnings and duplicated rationale push length past what the task needs.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists so return values need not be explained, yet the description still adds the field-level contract an agent needs (id feeds get_illustration_svg/png_url/animation, animation.lottie gates whether a Lottie call is worthwhile, free_distribution is not a licence judgement). For a 7-parameter search tool with heavy downstream tool chaining, nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries the full burden and does: it documents query (max 150 chars), style/category (pretty_ids from the list tools), free_only (licensing meaning), animated (with the caveat that some animated results lack the block), amount (default 10, max 100) and page (1-based, pagination-by-page not offset). It also adds search-strategy semantics (describe scenes not symbols, category narrows broad words).
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Search Icons8 illustrations') and immediately distinguishes the resource from its closest sibling by defining illustrations as 'full scenes with people, objects and backgrounds' versus icons as 'a small symbol'. An agent can route between search_illustrations and search_icons without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit when-to-use triggers (hero image, empty state, onboarding step, spot illustration) with an explicit counter-case ('for a small symbol in a button, a menu or a table, use search_icons instead'). It further names the supporting tools for parameter values (list_illustrations_styles, list_illustrations_categories) and when to escalate to get_illustration_animation.
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.
12 tool updates
- Changed
get_icon_animation2 fields changed- added
Input schema / properties / icon_id / descriptionAdded value: +"Icon id from the results of search_icons (field icons[].id)" - changed
Output schema / (root)Previous value: -nullNew value: +{ + "additionalProperties": true, + "properties": { + "animation": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Permanent gif and apng links. Set only when the download limit refused a lottie call.", + "title": "Animation" + }, + "error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Set only on failure.", + "title": "Error" + }, + "lottie": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "The animation as compact Lottie JSON text. Set only for format \"lottie\".", + "title": "Lottie" + }, + "retry_after_seconds": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Seconds until the download limit resets. Set only when the limit refused the call.", + "title": "Retry After Seconds" + }, + "size": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Pixel width the gif or apng renders at. Absent when the host answered something this server could not measure.", + "title": "Size" + }, + "url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Permanent gif or apng link. Absent for lottie and when error is set.", + "title": "Url" + } + }, + "title": "IconAnimationResult", + "type": "object" +}
- Changed
get_icon_png_url2 fields changed- added
Input schema / properties / icon_id / descriptionAdded value: +"Icon id from the results of search_icons (field icons[].id)" - changed
Output schema / (root)Previous value: -nullNew value: +{ + "additionalProperties": true, + "properties": { + "url": { + "description": "Permanent PNG link of the icon at the asked size.", + "title": "Url", + "type": "string" + } + }, + "required": [ + "url" + ], + "title": "IconPngUrlResult", + "type": "object" +}
- Changed
get_icon_svg2 fields changed- added
Input schema / properties / icon_id / descriptionAdded value: +"Icon id from the results of search_icons (field icons[].id)" - changed
Output schema / (root)Previous value: -nullNew value: +{ + "additionalProperties": true, + "properties": { + "animation": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Permanent gif and apng links. Set for an animated icon, and when the download limit refused the call.", + "title": "Animation" + }, + "error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Set only on failure.", + "title": "Error" + }, + "note": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Set only for an animated icon: the SVG is a still frame.", + "title": "Note" + }, + "retry_after_seconds": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Seconds until the download limit resets. Set only when the limit refused the call.", + "title": "Retry After Seconds" + }, + "svg": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "SVG markup of the icon. Absent when error is set.", + "title": "Svg" + }, + "url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Free 24px PNG link. Set only when the download limit refused the call.", + "title": "Url" + } + }, + "title": "IconSvgResult", + "type": "object" +}
- Changed
get_illustration_animation2 fields changed- added
Input schema / properties / illustration_id / descriptionAdded value: +"Illustration id from the results of search_illustrations (field illustrations[].id)" - changed
Output schema / (root)Previous value: -nullNew value: +{ + "additionalProperties": true, + "properties": { + "error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Set only on failure.", + "title": "Error" + }, + "expires_in_seconds": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Seconds the url stays valid. One hour.", + "title": "Expires In Seconds" + }, + "height": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Pixel height of the file.", + "title": "Height" + }, + "retry_after_seconds": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Seconds until the download limit resets. Set only when the limit refused the call.", + "title": "Retry After Seconds" + }, + "url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Presigned download link. Valid for expires_in_seconds. Absent when error is set.", + "title": "Url" + }, + "width": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Pixel width of the file.", + "title": "Width" + } + }, + "title": "IllustrationDownloadResult", + "type": "object" +}
- Changed
get_illustration_png_url2 fields changed- added
Input schema / properties / illustration_id / descriptionAdded value: +"Illustration id from the results of search_illustrations (field illustrations[].id)" - changed
Output schema / (root)Previous value: -nullNew value: +{ + "additionalProperties": true, + "properties": { + "error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Set only on failure.", + "title": "Error" + }, + "expires_in_seconds": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Seconds the url stays valid. One hour.", + "title": "Expires In Seconds" + }, + "height": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Pixel height of the file.", + "title": "Height" + }, + "retry_after_seconds": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Seconds until the download limit resets. Set only when the limit refused the call.", + "title": "Retry After Seconds" + }, + "url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Presigned download link. Valid for expires_in_seconds. Absent when error is set.", + "title": "Url" + }, + "width": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Pixel width of the file.", + "title": "Width" + } + }, + "title": "IllustrationDownloadResult", + "type": "object" +}
- Changed
get_illustration_svg2 fields changed- added
Input schema / properties / illustration_id / descriptionAdded value: +"Illustration id from the results of search_illustrations (field illustrations[].id)" - changed
Output schema / (root)Previous value: -nullNew value: +{ + "additionalProperties": true, + "properties": { + "error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Set only on failure.", + "title": "Error" + }, + "expires_in_seconds": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Seconds the url stays valid. One hour.", + "title": "Expires In Seconds" + }, + "height": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Pixel height of the file.", + "title": "Height" + }, + "retry_after_seconds": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Seconds until the download limit resets. Set only when the limit refused the call.", + "title": "Retry After Seconds" + }, + "url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Presigned download link. Valid for expires_in_seconds. Absent when error is set.", + "title": "Url" + }, + "width": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Pixel width of the file.", + "title": "Width" + } + }, + "title": "IllustrationDownloadResult", + "type": "object" +}
- Changed
list_categories1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "additionalProperties": true, + "properties": { + "docs": { + "anyOf": [ + { + "items": { + "additionalProperties": true, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Icon categories of the requested page. Absent when error is set.", + "title": "Docs" + }, + "error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Set only on failure.", + "title": "Error" + } + }, + "title": "IconCategoriesResult", + "type": "object" +}
- Changed
list_illustrations_categories1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "$defs": { + "IllustrationCategory": { + "additionalProperties": true, + "properties": { + "children": { + "anyOf": [ + { + "items": { + "$ref": "#/$defs/IllustrationCategory" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Children" + }, + "illustrations_count": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Illustrations Count" + }, + "pretty_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Category id. Pass it as category to search_illustrations or as parent_id to list_illustrations_categories.", + "title": "Pretty Id" + }, + "title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Title" + } + }, + "title": "IllustrationCategory", + "type": "object" + } + }, + "additionalProperties": true, + "properties": { + "categories": { + "anyOf": [ + { + "items": { + "$ref": "#/$defs/IllustrationCategory" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Categories of the requested page. Absent when error is set.", + "title": "Categories" + }, + "error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Set only on failure.", + "title": "Error" + }, + "total": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Number of top-level categories.", + "title": "Total" + } + }, + "title": "IllustrationCategoriesResult", + "type": "object" +}
- Changed
list_illustrations_styles1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "$defs": { + "IllustrationStyle": { + "additionalProperties": true, + "properties": { + "animated": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "description": "True when the style has animated formats at all, whatever the count of illustrations that move.", + "title": "Animated" + }, + "free_distribution": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Free Distribution" + }, + "illustrations_count": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Illustrations Count" + }, + "pretty_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Style id. Pass it as style to search_illustrations.", + "title": "Pretty Id" + }, + "title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Title" + } + }, + "title": "IllustrationStyle", + "type": "object" + } + }, + "additionalProperties": true, + "properties": { + "error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Set only on failure.", + "title": "Error" + }, + "styles": { + "anyOf": [ + { + "items": { + "$ref": "#/$defs/IllustrationStyle" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Styles of the requested page. Absent when error is set.", + "title": "Styles" + }, + "total": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Number of styles that match, before paging.", + "title": "Total" + } + }, + "title": "IllustrationStylesResult", + "type": "object" +}
- Changed
list_platforms1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "additionalProperties": true, + "properties": { + "docs": { + "anyOf": [ + { + "items": { + "additionalProperties": true, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Icon platforms (styles) of the requested page. The apiCode of each is the value of platform in search_icons. Absent when error is set.", + "title": "Docs" + }, + "error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Set only on failure.", + "title": "Error" + } + }, + "title": "IconPlatformsResult", + "type": "object" +}
- Changed
search_icons1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "$defs": { + "IconHit": { + "additionalProperties": true, + "properties": { + "animation": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Animation" + }, + "category": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Category" + }, + "commonName": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Commonname" + }, + "id": { + "description": "Icon id. Pass it as icon_id to get_icon_svg, get_icon_png_url or get_icon_animation.", + "title": "Id", + "type": "string" + }, + "isAnimated": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Present and true only for an animated icon, which get_icon_animation accepts.", + "title": "Isanimated" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Name" + }, + "platform": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Platform" + } + }, + "required": [ + "id" + ], + "title": "IconHit", + "type": "object" + } + }, + "additionalProperties": true, + "properties": { + "error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Set only on failure.", + "title": "Error" + }, + "icons": { + "anyOf": [ + { + "items": { + "$ref": "#/$defs/IconHit" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Matching icons. Absent when error is set.", + "title": "Icons" + }, + "note": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Note" + } + }, + "title": "IconSearchResult", + "type": "object" +}
- Changed
search_illustrations1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "$defs": { + "IllustrationHit": { + "additionalProperties": true, + "properties": { + "animation": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Animation" + }, + "free_distribution": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Free Distribution" + }, + "heading": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Heading" + }, + "id": { + "description": "Illustration id. Pass it as illustration_id to get_illustration_svg, get_illustration_png_url or get_illustration_animation.", + "title": "Id", + "type": "string" + }, + "media_types": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Includes \"animated\" for an illustration get_illustration_animation accepts.", + "title": "Media Types" + }, + "pretty_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Pretty Id" + }, + "preview": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Preview" + }, + "styles": { + "anyOf": [ + { + "items": { + "additionalProperties": true, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Styles" + }, + "tags": { + "anyOf": [ + { + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Tags" + } + }, + "required": [ + "id" + ], + "title": "IllustrationHit", + "type": "object" + } + }, + "additionalProperties": true, + "properties": { + "error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Set only on failure.", + "title": "Error" + }, + "illustrations": { + "anyOf": [ + { + "items": { + "$ref": "#/$defs/IllustrationHit" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Matching illustrations. Absent when error is set.", + "title": "Illustrations" + }, + "total": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Total" + } + }, + "title": "IllustrationSearchResult", + "type": "object" +}
12 tool updates
- First observed
get_icon_animation - First observed
get_icon_png_url - First observed
get_icon_svg - First observed
get_illustration_animation - First observed
get_illustration_png_url - First observed
get_illustration_svg - First observed
list_categories - First observed
list_illustrations_categories - First observed
list_illustrations_styles - First observed
list_platforms - First observed
search_icons - First observed
search_illustrations
Publisher details
- Operator
- Icons8 · Publisher source
- Operator website
- https://icons8.com/ · Publisher source
- Vendor relationship
- First-party · Publisher source
- Documentation
- https://icons8.com/mcp · Publisher source
- Trust center
- Not available
- Restrictions
- Searching and PNG downloads work on a free Icons8 account; free use needs a link back to Icons8. SVG delivery needs a paid Icons8 plan. Hosts without OAuth connect with an API key from the MCP tab of a paid account. · Publisher source
Related MCP Connectors
Search open SVG icon packs and fetch exact SVG markup from coding agents through MCP.
Icons for agentic development: search & fetch 366,000+ open-source icons as SVG/PNG. No API key.
Generate images from Claude, ChatGPT, Cursor and Codex with 12 top AI image models and 10 tools: up to 4 images per call, SVG vectorization, editing and more. Remote MCP with OAuth, no API keys. Pay per image, no subscription.
Custom transparent PNG icons in your project's style, added by your coding agent. Free starter set.
Related MCP Servers
- AlicenseAqualityDmaintenanceAll-in-one asset search MCP server for AI coding agents, enabling search for icons, logos, stock photos, vectors, and emoji from a single tool call.485MIT
- AlicenseAqualityCmaintenanceDescription: Supericons MCP lets AI coding agents search, recommend, and retrieve SVG icons from a semantic registry of 20,000+ icons.142MIT
- AlicenseBqualityDmaintenanceMCP server that allows FE/UI/Designers to retrieve SVG icons via the Iconify API by simply asking LLMs rather than manually searching websites.332 npm4MIT
- AlicenseNot gradedqualityCmaintenanceEnables coding agents to discover and add animated SVG illustrations to websites and apps by searching a themed library, listing available themes, and retrieving individual illustration files. It runs as a no-sign-in Streamable HTTP endpoint that works with any MCP client, so agents can pick illustrations and drop them into a React project or save them as SVG files.MIT
Glama MCP Gateway
Add one secure layer between your agents and this server.