MCP Server

iconlab

io.github.op0ai/iconlab
Design & Creative Developer Tools Public & reachable MCP 2026-07-28

What this MCP does

Searches a Lucide icon corpus and generates or retrieves icons as SVG, JSX, or animated React components.

generate_icon
Generate a NEW icon in the Lucide grammar for a concept that doesn't exist yet. Grab-first: returns mode='grab' with matches when a strong existing icon covers the prompt. Otherwise runs the lint + critique + repair loop and returns lint-scored candidates. Subject to quota (errors carry error.code='quota_exceeded').
Input schema
{'type': 'object', 'required': ['prompt'], 'properties': {'prompt': {'type': 'string', 'description': "the concept, e.g. 'portafilter'"}}}
Output schema
{'oneOf': [{'type': 'object', 'required': ['mode', 'matches'], 'properties': {'id': {'type': 'string', 'description': 'generation record id (mode=generated); bench at /gen/{id}, record kept 90 days'}, 'ms': {'type': 'number'}, 'mode': {'enum': ['grab', 'generated'], 'type': 'string', 'description': 'grab = strong existing matches, no generation ran'}, 'quota': {'type': 'object', 'description': '{ used, limit } after this call'}, 'prompt': {'type': 'string'}, 'reason': {'type': 'string'}, 'matches': {'type': 'array', 'items': {'type': 'object', 'required': ['slug', 'score', 'source', 'license'], 'properties': {'slug': {'type': 'string'}, 'score': {'type': 'number'}, 'source': {'type': 'string'}, 'license': {'type': 'string'}}}}, 'createdAt': {'type': 'string'}, 'candidates': {'type': 'array', 'items': {'type': 'object', 'required': ['name', 'body', 'score', 'pass', 'rounds'], 'properties': {'body': {'type': 'string', 'description': 'inner SVG body in the 24x24 Lucide grammar (stroke-2, no fills)'}, 'name': {'type': 'string'}, 'pass': {'type': 'boolean'}, 'score': {'type': 'number', 'description': 'grammar lint score, 0-100'}, 'rounds': {'type': 'number', 'description': 'repair rounds used'}, 'violations': {'type': 'array', 'items': {'type': 'object'}}, 'visionNote': {'type': 'string'}, 'visionVerdict': {'type': 'string'}}}}, 'modelCalls': {'type': 'number'}, 'provenance': {'type': 'object', 'description': "{ attribution, license: 'yours', source: 'generated' }"}}}, {'type': 'object', 'required': ['error'], 'properties': {'error': {'type': 'object', 'required': ['code', 'message'], 'properties': {'code': {'enum': ['prompt_too_short', 'quota_exceeded', 'internal'], 'type': 'string'}, 'quota': {'type': 'object', 'description': 'present on quota_exceeded: { used, limit, tier }'}, 'message': {'type': 'string'}}}}}]}
get_icon
Fetch one icon by slug. format='svg' (default) returns the SVG document; 'jsx' returns a lucide-react-compatible TSX component; 'motion' returns a TSX component with a stroke-draw entrance.
Input schema
{'type': 'object', 'required': ['slug'], 'properties': {'slug': {'type': 'string'}, 'format': {'enum': ['svg', 'jsx', 'motion'], 'type': 'string'}}}
Output schema
{'oneOf': [{'type': 'object', 'required': ['slug', 'format', 'source', 'license', 'content'], 'properties': {'slug': {'type': 'string'}, 'format': {'enum': ['svg', 'jsx', 'motion'], 'type': 'string'}, 'source': {'type': 'string'}, 'content': {'type': 'string', 'description': 'SVG document (format=svg) or TSX component source (jsx/motion)'}, 'license': {'type': 'string'}}}, {'type': 'object', 'required': ['error'], 'properties': {'error': {'type': 'object', 'required': ['code', 'message'], 'properties': {'code': {'enum': ['unknown_icon'], 'type': 'string'}, 'quota': {'type': 'object', 'description': 'present on quota_exceeded: { used, limit, tier }'}, 'message': {'type': 'string'}}}}}]}
search_icons
Search the iconlab corpus (Lucide static + lucide-animated variants) by concept. Returns scored matches with slugs, sources and licenses.
Input schema
{'type': 'object', 'required': ['query'], 'properties': {'limit': {'type': 'number', 'description': 'max results, 1-50 (default 12)'}, 'query': {'type': 'string', 'description': "concept, e.g. 'drum' or 'vector database'"}}}
Output schema
{'type': 'object', 'required': ['query', 'total', 'truncated', 'results'], 'properties': {'query': {'type': 'string'}, 'total': {'type': 'number', 'description': 'matches found (counting stops at limit+1, so total may read limit+1 when truncated)'}, 'results': {'type': 'array', 'items': {'type': 'object', 'required': ['slug', 'score', 'source', 'license', 'animatedVariant'], 'properties': {'slug': {'type': 'string'}, 'score': {'type': 'number', 'description': 'relevance, 0-1'}, 'source': {'type': 'string', 'description': 'lucide | lucide-animated'}, 'license': {'type': 'string', 'description': 'SPDX id of the source set'}, 'animatedVariant': {'type': 'boolean', 'description': 'an animated variant exists for this slug'}}}}, 'truncated': {'type': 'boolean', 'description': 'true when more matches exist beyond `results`'}}}
Added
generate_icon
Sept. 17, 2026, 12:45 p.m.
Added
get_icon
Sept. 17, 2026, 12:45 p.m.
Added
search_icons
Sept. 17, 2026, 12:45 p.m.