{"id":"be0fe0d0-d2af-4bbf-a7e2-ff8d5719e0fb","slug":"sohampatwardhan-iconify-mcp","kind":"mcp","name":"iconify-mcp","summary":"MCP server for Iconify icons (as browsed on Icônes): search icons and view them as images","owner":"sohampatwardhan","repoUrl":"https://github.com/sohampatwardhan/iconify-mcp","license":"MIT","licenseTier":"permissive","trust":"community","stars":0,"match":null,"fewStars":true,"format":"mcp","createdAt":"2026-10-31T21:00:13.000Z","addedAt":"2026-11-01T02:17:13.871Z","logoUrl":"https://avatars.githubusercontent.com/u/39222082?u=0fc65bb752569a88229087e96e28b51d5a940b91&v=4","linkOnly":false,"collection":null,"skillPath":null,"categories":["search","cloud-infra"],"tags":[],"runtime":"node","local":true,"cloudCapable":false,"cloudCapability":"unknown","cloudReadyOnPlatform":false,"needsApiKey":false,"reviewed":false,"syncedAt":"2026-11-01T02:47:33.316Z","sample":false,"url":"https://conduits.dev/tools/sohampatwardhan-iconify-mcp","language":"TypeScript","transports":["stdio"],"install":{"npm":"@sohampatwardhan/iconify-mcp"},"requirements":{"env":[],"upstreamMayCharge":false},"tools":null,"readme":"# @sohampatwardhan/iconify-mcp\n\n[![npm version](https://img.shields.io/npm/v/@sohampatwardhan/iconify-mcp)](https://www.npmjs.com/package/@sohampatwardhan/iconify-mcp)\n\nUnofficial community MCP server for [Iconify](https://iconify.design). It searches the public Iconify catalog, returns each collection's license, and sends PNG previews back as MCP image content so a model can see the icons.\n\nIcon pages link to [Icônes](https://icones.js.org), Anthony Fu's icon browser, which is a front end over the same catalog.\n\n![Contact sheet of twelve Lucide icons rendered by iconify-mcp](docs/contact-sheet.png)\n\n## Tools\n\n| Tool | What you get |\n| --- | --- |\n| `list_collections` | Filter the catalog by name, prefix, or category. Each hit includes author, license, icon count, and sample ids. |\n| `get_collection` | One collection: license, categories, a page of icon names, and a PNG of its sample icons. |\n| `search_icons` | Keyword search (`query`, optional `prefix` / `prefixes` / `category`, `limit`, `start`). Results include Iconify ids, licenses, and Icônes links, plus a contact-sheet PNG. |\n| `get_icon` | One icon (`prefix:name`): SVG, dimensions, collection, license, alias parent, Icônes URL, and a PNG. Snippets cover SVG, data URL, Vue, React, Svelte, UnoCSS, Tailwind, and the Iconify name. |\n| `preview_icons` | One labeled contact sheet for a list of ids, or for the top search matches. `size`, `color`, `background`, and `columns` are configurable. |\n\n`search_icons` and `get_collection` include a preview image by default. Pass `preview: false` when you only want the JSON.\n\nIconify search matches names and keywords. It does not search by visual similarity. Use the contact sheet to compare candidates.\n\n### Code snippets\n\n`get_icon` returns the formats Icônes offers:\n\n- **Iconify name:** `lucide:house`\n- **SVG** and a **data URL**\n- **Iconify SVG URL:** `https://api.iconify.design/lucide/house.svg`\n- **Vue, React, and Svelte** components\n- **UnoCSS:** `<div class=\"i-lucide-house\"></div>`\n- **Tailwind** (Iconify plugin): `<span class=\"icon-[lucide--house]\"></span>`\n\nSnippet SVGs keep `currentColor` so they inherit text color. Pass `color` (for example `#b45309`) when the SVG and the PNG should use a fixed color. PNGs default to `#1c1917` on white. Palette icons that do not use `currentColor` keep their original colors.\n\n### Resources\n\n| URI | Body |\n| --- | --- |\n| `iconify://collections` | Collection list with licenses |\n| `iconify://collection/{prefix}` | One collection, including up to 200 icon names |\n| `iconify://icon/{prefix}/{name}.svg` | SVG |\n| `iconify://icon/{prefix}/{name}.png` | 128px PNG on white |\n| `iconify://icon/{prefix}/{name}.json` | Metadata and snippets |\n\n`iconify://` is the scheme to use. The same resources are also registered on `icones://` so older URIs keep working.\n\nIcônes links look like `https://icones.js.org/collection/lucide?icon=lucide:house`.\n\n## Setup\n\nRequires Node.js 20 or newer.\n\n```bash\nnpx -y @sohampatwardhan/iconify-mcp@latest\n```\n\nThe published bin is `iconify-mcp`. `icones-mcp` is a compatibility alias for the same program. Stdio is the default. Logs go to stderr so they stay off the JSON-RPC stream. The MCP server name is `iconify-mcp`.\n\n### Cursor\n\nAdd this to `~/.cursor/mcp.json` or the project's `.cursor/mcp.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"iconify\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@sohampatwardhan/iconify-mcp@latest\"]\n    }\n  }\n}\n```\n\n### Claude Desktop\n\nThe same `mcpServers` block goes in the desktop config:\n\n- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`\n- Windows: `%APPDATA%\\Claude\\claude_desktop_config.json`\n- Linux: `~/.config/Claude/claude_desktop_config.json`\n\nRestart Claude Desktop after saving.\n\n### Claude Code\n\n```bash\nclaude mcp add iconify -- npx -y @sohampatwardhan/iconify-mcp@latest\n```\n\n### VS Code\n\nCreate `.vscode/mcp.json`:\n\n```json\n{\n  \"servers\": {\n    \"iconify\": {\n      \"type\": \"stdio\",\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@sohampatwardhan/iconify-mcp@latest\"]\n    }\n  }\n}\n```\n\n### Streamable HTTP\n\nHTTP mode is stateless and has no authentication. Bind it to localhost.\n\n```bash\nnpx -y @sohampatwardhan/iconify-mcp@latest --http --port 3333\n```\n\nThe MCP endpoint is `http://127.0.0.1:3333/mcp`. A client config looks like:\n\n```json\n{\n  \"mcpServers\": {\n    \"iconify\": {\n      \"url\": \"http://127.0.0.1:3333/mcp\"\n    }\n  }\n}\n```\n\n`GET /health` returns `ok`.\n\n### MCP Inspector\n\nThe web UI:\n\n```bash\nnpm install\nnpm run build\nnpx @modelcontextprotocol/inspector node dist/cli.js\n```\n\nA non-interactive check of the stdio server:\n\n```bash\nnpx @modelcontextprotocol/inspector --cli --method tools/list node dist/cli.js\nnpx @modelcontextprotocol/inspector --cli --method tools/call \\\n  --tool-name get_icon \\\n  --tool-args-json '{\"icon\":\"lucide:house\",\"size\":64}' \\\n  node dist/cli.js\n```\n\n## Examples\n\nSearch and look at the sheet:\n\n```json\n{\n  \"name\": \"search_icons\",\n  \"arguments\": { \"query\": \"arrow\", \"prefix\": \"lucide\", \"limit\": 8 }\n}\n```\n\nFetch one icon as a React component and a 128px PNG:\n\n```json\n{\n  \"name\": \"get_icon\",\n  \"arguments\": { \"icon\": \"lucide:house\", \"formats\": [\"react\", \"svg\", \"iconify\"] }\n}\n```\n\nCompare a hand-picked set. This is the call that produced the image at the top of the README:\n\n```json\n{\n  \"name\": \"preview_icons\",\n  \"arguments\": {\n    \"title\": \"Lucide\",\n    \"columns\": 4,\n    \"size\": 72,\n    \"icons\": [\n      \"lucide:house\", \"lucide:search\", \"lucide:heart\", \"lucide:star\",\n      \"lucide:sun\", \"lucide:moon\", \"lucide:cloud\", \"lucide:camera\",\n      \"lucide:bell\", \"lucide:settings\", \"lucide:user\", \"lucide:mail\"\n    ]\n  }\n}\n```\n\nPrompts that work well once the server is connected:\n\n- \"Search Lucide for a house icon and show me the candidates.\"\n- \"Get the SVG and a Svelte component for `tabler:brand-github`.\"\n- \"Make a contact sheet of weather icons from Phosphor.\"\n\n## Licenses\n\nThis server is MIT. See [LICENSE](LICENSE).\n\nIcon artwork is not relicensed. Every collection on Iconify has its own license (MIT, Apache-2.0, ISC, CC BY 4.0, and others). `list_collections`, `get_collection`, `search_icons`, `get_icon`, and `preview_icons` return that license's title, SPDX id, and URL. SVG snippets include a comment with the collection, author, and license. Read that license before shipping an icon.\n\nContact-sheet labels are set in [Inter](https://github.com/rsms/inter), which is bundled under the SIL Open Font License. The license text is in [assets/fonts/OFL.txt](assets/fonts/OFL.txt). Rasterized labels in a PNG are pixels. The font file itself stays under the OFL.\n\n## Data source\n\nThis server calls the public Iconify API at `https://api.iconify.design`. Icônes (icones.js.org) is the browsing UI those icon links open. The client uses:\n\n- `GET /collections` and `GET /collection`\n- `GET /search`\n- `GET /{prefix}.json?icons=...`\n\nSVGs are built locally with `@iconify/utils` and rasterized with `@resvg/resvg-js`. The client keeps at least 100ms between requests, caches collection metadata, search results, and icon bodies in memory, and retries 429 and 5xx responses.\n\nThe public API is a shared service. Point `ICONIFY_API_URL` at your own [Iconify API](https://iconify.design/docs/api/) instance if you need higher volume.\n\n| Variable | Default | Purpose |\n| --- | --- | --- |\n| `ICONIFY_API_URL` | `https://api.iconify.design` | API origin |\n| `ICONES_MIN_INTERVAL_MS` | `100` | Minimum gap between API calls |\n| `ICONES_CACHE` | enabled | Set to `0` to disable the memory cache |\n\n## Development\n\n```bash\nnpm install\nnpm run lint\nnpm test\nnpm run typecheck\nnpm run build\nnode dist/cli.js --help\nnpm run smoke\n```\n\n`npm run lint` checks TSDoc comments with `eslint-plugin-tsdoc` (`tsdoc/syntax`). `npm test` includes rendering tests and a live call against the public API. `npm run smoke` starts the built stdio server, calls `preview_icons`, and writes `docs/contact-sheet.png` unless `CONTACT_SHEET_OUT` is set. It also copies the PNG to `contact-sheet.png` inside `SMOKE_OUT`, or the system temp directory when `SMOKE_OUT` is unset. CI runs `npm ci`, then lint, typecheck, test, build, and smoke.\n\n`prepublishOnly` compiles TypeScript into `dist/` before the package is packed.\n\n## Releasing\n\n`@sohampatwardhan/iconify-mcp` is published only by `.github/workflows/release.yml`, using GitHub OIDC trusted publishing. `0.2.1` was published that way. Do not run `npm publish` from a laptop or an agent session, and do not create an npm token.\n\nBump the version on `main` after the release commit is there. `npm version` updates `package.json` and `package-lock.json` and creates the matching tag. `src/version.ts` reads the version from `package.json`, so leave that file's version line alone.\n\n```bash\nnpm version patch   # or minor, or major\ngit push --follow-tags\n```\n\nRun those commands from `main`. A tag pushed from a feature branch does not release. Do not move a tag or publish the same version again.\n\nThe workflow rejects a tag that is not `v` plus the `package.json` version, then runs `npm ci`, lint, typecheck, test, build, and smoke, publishes with `npm publish --provenance --access public`, and opens a GitHub Release with generated notes.\n"}