{
  "markdown": "# mcp-icon-visual\n\n[![MCP Registry](https://img.shields.io/badge/MCP_Registry-published-6f42c1)](https://registry.modelcontextprotocol.io/?q=io.github.n0isy/mcp-icon-visual)\n[![npm](https://img.shields.io/npm/v/@br-ai-n/mcp-icon-visual)](https://www.npmjs.com/package/@br-ai-n/mcp-icon-visual)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nMCP server that gives AI agents the ability to **search**, **retrieve**, **compare**, and **render** SVG icons. Built with Rust and the [rmcp](https://github.com/modelcontextprotocol/rust-sdk) SDK.\n\nCombines local filesystem access with a remote rendering API to resolve SVGs from any source — inline strings, URLs, local files, or [Iconify](https://iconify.design/) IDs — and render them onto visual comparison grids.\n\nThe key insight: every tool returns **images**. A vision-capable LLM doesn't just get metadata — it *sees* the icons. This turns icon selection from guesswork into a visual conversation.\n\n<p align=\"center\">\n  <img src=\"docs/search-grid-example.png\" alt=\"search_icons result for 'machine learning' — 4x4 grid with 16 icons\" width=\"512\" />\n  <br/>\n  <em><code>search_icons(\"machine learning\")</code> — 4x4 grid, cells 0–15, returned as PNG</em>\n</p>\n\n## Agent Pipelines\n\nThese tools are designed to be composed by AI agents with vision. Below are three proven patterns.\n\n### 1. Visual Search & Selection\n\nAn agent searches for icons and **visually picks** the best match — no blind URL selection.\n\n```\n                          ┌─────────────────────────────┐\n                          │        Agent + Vision        │\n                          └──────────────┬──────────────┘\n                                         │\n                        ┌────────────────┼────────────────┐\n                        v                v                v\n                  search_icons     search_icons     search_icons\n                  \"cloud\"          \"upload\"          \"storage\"\n                        │                │                │\n                        v                v                v\n                  ┌──────────┐    ┌──────────┐    ┌──────────┐\n                  │ 4x4 grid │    │ 4x4 grid │    │ 4x4 grid │\n                  │  (sees)  │    │  (sees)  │    │  (sees)  │\n                  └────┬─────┘    └────┬─────┘    └────┬─────┘\n                       │               │               │\n                       └───────────────┼───────────────┘\n                                       v\n                              \"cells 3, 7, 12 match\n                               the project style\"\n                                       │\n                                       v\n                               render_grid [3 winners]\n                                       │\n                                       v\n                              ┌──────────────────┐\n                              │  final comparison │\n                              │   grid (sees)     │──> pick best\n                              └──────────────────┘\n```\n\nThe agent runs multiple searches, **looks** at each grid, picks candidates by cell number, then renders a final side-by-side comparison to make the choice. Works especially well when the agent has context about the project's visual style.\n\n### 2. Iterative Icon Editing\n\nAn agent modifies SVG code and uses `render_grid` as a **visual diff** to track progress across iterations.\n\n```\n         get_svg \"mdi/cloud\"\n                │\n                v\n          ┌───────────┐\n          │ raw SVG    │\n          │ markup     │\n          └─────┬─────┘\n                │\n       ┌────────┴─────────────────────────────────────┐\n       │              Edit Loop                        │\n       │                                               │\n       │   Agent modifies SVG code                     │\n       │        │                                      │\n       │        v                                      │\n       │   render_grid [original, v1, v2, v3]          │\n       │        │                                      │\n       │        v                                      │\n       │   ┌──────────────────────────────┐            │\n       │   │ cell 0: original             │            │\n       │   │ cell 1: thicker strokes      │            │\n       │   │ cell 2: rounded corners      │            │\n       │   │ cell 3: filled variant       │            │\n       │   └──────────────┬───────────────┘            │\n       │                  │                            │\n       │        agent sees all versions                │\n       │        decides next edit                      │\n       │                  │                            │\n       │                  └──── loop ──────────────────┘\n       │\n       v\n  save final SVG to disk\n```\n\nEach iteration, the agent passes **all versions** (original + edits) as inline SVGs to `render_grid`. It sees them side-by-side in one image and decides whether to keep iterating or stop. The original always stays in cell 0 as a reference.\n\n### 3. Style Matching & Consistency\n\nAn agent ensures new icons match the visual style of existing project icons.\n\n```\n  Project icons on disk             Candidate sources\n  ─────────────────────             ─────────────────\n  /app/icons/nav-home.svg           search_icons \"settings\"\n  /app/icons/nav-search.svg              │\n  /app/icons/nav-profile.svg             v\n          │                        picks cells 2, 5, 9\n          │                              │\n          └──────────┬───────────────────┘\n                     v\n              render_grid [\n                /app/icons/nav-home.svg,      ← cell 0: existing\n                /app/icons/nav-search.svg,    ← cell 1: existing\n                /app/icons/nav-profile.svg,   ← cell 2: existing\n                candidate_url_1,              ← cell 3: candidate\n                candidate_url_2,              ← cell 4: candidate\n                candidate_url_3,              ← cell 5: candidate\n                \"<svg>...custom edit...</svg>\" ← cell 6: agent's edit\n              ]\n                     │\n                     v\n              ┌────────────────────────────────┐\n              │ grid image:                     │\n              │  existing icons  vs  candidates │\n              │  (agent sees style match/clash) │\n              └────────────────┬───────────────┘\n                               │\n                      agent judges:\n                  \"cell 4 matches stroke weight\n                   and corner radius of cells 0-2,\n                   cell 3 is too thin,\n                   cell 5 wrong fill style\"\n                               │\n                               v\n                       get_svg cell_4_url\n                               │\n                               v\n                    save to /app/icons/nav-settings.svg\n```\n\nBy mixing local file paths and remote sources in a single grid, the agent can visually compare existing project icons against candidates in one shot. The grid becomes a style audit tool.\n\n### Combining Pipelines\n\nThese patterns compose naturally. A real-world workflow might:\n\n1. **Search** across multiple keywords (pipeline 1)\n2. **Compare** top candidates against existing project icons (pipeline 3)\n3. **Edit** the closest match to fix style inconsistencies (pipeline 2)\n4. **Verify** the final icon one more time against the full icon set (pipeline 3)\n\nAll driven by a single agent with vision, using three tools.\n\n## Tools\n\n### `search_icons`\n\nSemantic icon search. Returns a 4x4 PNG grid (512x512, cells 0-15) and a mapping of cell numbers to SVG URLs.\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `keyword` | string | *required* | Semantic search query (e.g. `\"cloud computing\"`, `\"arrows\"`) |\n| `background` | string | `\"#FFFFFF\"` | Grid background color, CSS hex |\n| `color` | string \\| null | `null` | Recolor all icons to this CSS hex color |\n\n### `get_svg`\n\nRetrieve raw SVG markup from any source. Returns the complete SVG string for inspection or modification.\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `source` | string | URL, Iconify ID (`mdi/cloud`), absolute file path, or inline `<svg>` |\n\n### `render_grid`\n\nRender 1-16 SVGs onto a 4x4 comparison grid (512x512, cells 0-15). Useful for comparing icon variants side-by-side or previewing local icons alongside search results.\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `sources` | string[] | *required* | 1-16 SVG sources (URLs, Iconify IDs, file paths, or inline SVGs) |\n| `background` | string | `\"#FFFFFF\"` | Grid background color, CSS hex |\n\n## Source Resolution\n\nAll tools share a unified resolution pipeline that classifies sources automatically:\n\n| Source type | Example | Resolution |\n|-------------|---------|------------|\n| Inline SVG | `<svg xmlns=\"...\">...</svg>` | Returned as-is |\n| URL | `https://mdn.alipayobjects.com/.../original` | Resolved via API |\n| File path | `/home/user/icons/logo.svg` | Read from local disk |\n| Iconify ID | `mdi/cloud`, `lucide/home` | Resolved via API |\n\nFile paths are detected by prefix (`/`, `./`, `~/`) or `.svg` extension. Everything else without `http://`/`https://` is treated as an Iconify ID.\n\n## Grid Format\n\nAll grid outputs are **512x512 PNG** images with a **4x4 layout** (128x128 cells), numbered 0-15 left-to-right, top-to-bottom:\n\n```\n┌────┬────┬────┬────┐\n│  0 │  1 │  2 │  3 │\n├────┼────┼────┼────┤\n│  4 │  5 │  6 │  7 │\n├────┼────┼────┼────┤\n│  8 │  9 │ 10 │ 11 │\n├────┼────┼────┼────┤\n│ 12 │ 13 │ 14 │ 15 │\n└────┴────┴────┴────┘\n```\n\nCell numbers appear at the bottom-left of each cell. Unused cells show the number only.\n\n## Installation\n\n### npx (recommended)\n\nNo build needed. Works on Linux (x64/arm64), macOS (Intel/Apple Silicon), and Windows (x64).\n\n```json\n{\n  \"mcpServers\": {\n    \"icon-visual\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@br-ai-n/mcp-icon-visual\"]\n    }\n  }\n}\n```\n\n### From source\n\nRequires Rust (edition 2024):\n\n```bash\ncargo build --release --target x86_64-unknown-linux-musl\n```\n\nThe release profile produces a fully static binary (musl libc, `rustls-tls`, LTO, stripped).\n\n## Usage\n\n```bash\n# Default upstream API\n./mcp-icon-visual\n\n# Custom API endpoint\n./mcp-icon-visual --api-base http://localhost:3000\n```\n\nThe server communicates over **stdio** using the MCP protocol.\n\n## MCP Client Configuration\n\n### Claude Desktop / Cursor\n\n```json\n{\n  \"mcpServers\": {\n    \"icon-visual\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@br-ai-n/mcp-icon-visual\"]\n    }\n  }\n}\n```\n\n### Custom API endpoint\n\n```json\n{\n  \"mcpServers\": {\n    \"icon-visual\": {\n      \"command\": \"/path/to/mcp-icon-visual\",\n      \"args\": [\"--api-base\", \"http://localhost:3000\"]\n    }\n  }\n}\n```\n\n## Project Structure\n\n```\nsrc/\n├── main.rs           # Entrypoint, CLI args, stdio transport\n├── server.rs         # IconServer + MCP tool routing + response builders\n├── api_client.rs     # HTTP client for upstream rendering API\n├── resolve.rs        # Source classification and SVG resolution\n├── error.rs          # Error types\n└── tools/\n    ├── mod.rs\n    ├── search_icons.rs   # SearchIconsParams\n    ├── get_svg.rs        # GetSvgParams\n    └── render_grid.rs    # RenderGridParams\n```\n\n## Testing\n\n```bash\n# Unit tests (source classification)\ncargo test\n\n# Integration tests (requires network access to icons.buan.me)\ncargo test -- --ignored\n```\n\n## Dependencies\n\n| Crate | Purpose |\n|-------|---------|\n| `rmcp` | MCP server SDK (tool routing, stdio transport) |\n| `tokio` | Async runtime |\n| `reqwest` | HTTP client (`rustls-tls`, no OpenSSL) |\n| `serde` / `serde_json` | Serialization |\n| `schemars` | JSON Schema generation for tool parameters |\n| `clap` | CLI argument parsing |\n| `base64` | Base64 encoding |\n| `tracing` | Logging |\n| `thiserror` | Error derive macros |\n\n## License\n\nMIT License\n\nCopyright (c) 2025\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n",
  "bytes": 12993,
  "sha": "192225285d242728805415b46826c8047e7b3afc31e4bf3b9a3556cd14dcea50",
  "repo_slug": "n0isy/brain-mcp-icon-visual",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_n0isy_mcp_icon_visual_16a0e56d/readme"
}