Skip to main content
Glama

TrueIcon

npm Install in VS Code Install in VS Code Insiders Install in Cursor

TrueIcon is an MCP server that gives AI coding assistants exact, version-correct icon references. Your assistant searches the icon packages your project actually uses (lucide-react, react-icons, @heroicons/react, @phosphor-icons/react, @tabler/icons-react, iconoir-react, @fluentui/react-icons, @carbon/icons-react, @ant-design/icons) and gets back real icon names, import paths and a ready-to-paste import line.

Why

AI assistants often guess icon names. The guess can be an icon that never existed, one renamed a few releases ago, or one from a different library, and you only find out when the build fails. TrueIcon closes that gap:

  • It reads which icon packages and versions your project uses.

  • It downloads those exact versions from npm and indexes every icon once.

  • The assistant calls search_icons and gets results that are guaranteed to exist in that version, for example import { Trash2 } from 'lucide-react';.

Related MCP server: Svg/icons MCP

Supported providers

Provider id

npm package

Icon naming

lucide

lucide-react

Lucide's file names, e.g. trash-2Trash2

heroicons

@heroicons/react

<icon>-<size>-<style>, e.g. trash-24-outlineTrashIcon

react-icons

react-icons

<set>-<icon>, e.g. fa6-beer-mug-emptyFaBeerMugEmpty

phosphor

@phosphor-icons/react

<icon> for the regular weight, <icon>-<weight> otherwise, e.g. trash-boldTrashIcon with weight="bold"

tabler

@tabler/icons-react

Tabler's icon names, e.g. trashIconTrash, trash-filledIconTrashFilled

iconoir

iconoir-react

<icon> for regular, <icon>-solid for solid, e.g. trash-solidTrashSolid

fluentui

@fluentui/react-icons

<icon>-<style> with style regular, filled or color, e.g. delete-regularDeleteRegular. Only the scalable (1em) icons are indexed, not the size-specific variants

carbon

@carbon/icons-react

Carbon's export names in kebab case, e.g. trash-canTrashCan. Variants add -filled, -alt or -color, e.g. accessibility-filledAccessibilityFilled

antdesign

@ant-design/icons

<icon>-<theme> with theme outlined, filled or two-tone, e.g. delete-outlinedDeleteOutlined

Tools accept either the provider id or the npm package name ("lucide" or "lucide-react"). Usage snippets are for React. Phosphor weights all share one component, so pass the record's style as the weight prop (e.g. <TrashIcon weight="bold" />); the usage snippet only shows the import.

Install

TrueIcon needs Node.js 20 or newer.

# Run without installing (this is what the MCP configs below do)
npx -y trueicon

# Or install globally and run the `trueicon` binary
npm i -g trueicon
trueicon

trueicon is a stdio MCP server. Your MCP client starts it; running it by hand only prints trueicon: v0.2.0 running on stdio to stderr and waits for JSON-RPC on stdin.

Quick start

  1. Add a .iconmcp.json to your project root that lists your icon packages:

    {
      "providers": [
        { "package": "lucide-react" },
        { "package": "@heroicons/react", "version": "2.1.5" }
      ]
    }
  2. Register TrueIcon with your MCP client (Claude Code or Claude Desktop).

  3. Ask your assistant for an icon. The first search for each package downloads and indexes it, which takes a few seconds. Later searches use the local cache.

Configuration: .iconmcp.json

TrueIcon looks for .iconmcp.json in the project directory. That is $TRUEICON_PROJECT_DIR if set, otherwise the server's working directory.

{
  "providers": [
    { "package": "lucide-react" },
    { "package": "react-icons", "version": "5.3.0" },
    { "package": "@heroicons/react", "version": "^2.1.0" }
  ]
}

Field

Type

Required

Meaning

providers

array

yes

Icon packages the project uses. search_icons searches all of them by default.

providers[].package

string

yes

npm package name: lucide-react, react-icons, @heroicons/react, @phosphor-icons/react, @tabler/icons-react, iconoir-react, @fluentui/react-icons, @carbon/icons-react or @ant-design/icons.

providers[].version

string

no

Exact version or npm range. If omitted, it is read from package.json (see below).

  • If the file is missing, no providers are configured. search_icons then only works when you pass provider explicitly, and get_icon still works.

  • Unsupported packages in the list are skipped, and search_icons reports them as a warning.

  • Invalid JSON or a malformed entry makes the tools return an error that names the file and the bad field.

Environment variables

Variable

Default

Purpose

TRUEICON_PROJECT_DIR

working directory

Project root holding .iconmcp.json and package.json

TRUEICON_CACHE

~/.trueicon/cache

Where downloaded packages and indexes are stored

Versions

Auto-detection

A provider's version is resolved in this order:

  1. The version argument passed to the tool call, if any.

  2. The provider's version in .iconmcp.json.

  3. The version range declared for the package in the project's package.json, checking dependencies first and then devDependencies.

If none of these is available, the tool asks you to pin the version or add the package to package.json. TrueIcon reads the declared range from package.json. It does not read node_modules or the lockfile. For a range, it indexes the range's base version: ^0.460.0 indexes lucide-react@0.460.0. For a || b ranges, only the first part counts. To match an exact installed version, pin it in .iconmcp.json.

Version policy

Indexes are keyed by major.minor:

  • Patch versions are ignored. One index serves all of 0.460.x. The index built from 0.460.0 answers requests for 0.460.3.

  • A minor change gets its own index. Bumping lucide-react from 0.460 to 0.461 builds a fresh index on the next search, with no manual step.

  • Majors are strict. A different major is always a separate index and is never served from another major's index.

  • Cached indexes rebuild automatically when the bundled synonyms.json changes (detected by hash) or the index format changes.

Using it with Claude

Claude Code

Add TrueIcon from your project directory:

claude mcp add trueicon -- npx -y trueicon

Or commit a .mcp.json at the project root to share it with your team:

{
  "mcpServers": {
    "trueicon": {
      "command": "npx",
      "args": ["-y", "trueicon"]
    }
  }
}

Claude Code starts the server in your project directory, so it finds .iconmcp.json and package.json there. If it runs from somewhere else, add "env": { "TRUEICON_PROJECT_DIR": "/absolute/path/to/project" }.

Claude Desktop

Claude Desktop doesn't start servers in your project directory, so set TRUEICON_PROJECT_DIR. Edit claude_desktop_config.json: ~/Library/Application Support/Claude/claude_desktop_config.json on macOS, %APPDATA%\Claude\claude_desktop_config.json on Windows.

{
  "mcpServers": {
    "trueicon": {
      "command": "npx",
      "args": ["-y", "trueicon"],
      "env": {
        "TRUEICON_PROJECT_DIR": "/absolute/path/to/your/project"
      }
    }
  }
}

Restart Claude Desktop after editing the file.

Using it in VS Code and Cursor

Use the install badges at the top of this README. They add TrueIcon with TRUEICON_PROJECT_DIR set to ${workspaceFolder}, so it searches the project you have open.

To add it by hand in VS Code, create .vscode/mcp.json in your project:

{
  "servers": {
    "trueicon": {
      "command": "npx",
      "args": ["-y", "trueicon"],
      "env": {
        "TRUEICON_PROJECT_DIR": "${workspaceFolder}"
      }
    }
  }
}

In Cursor, use the same entry under "mcpServers" in .cursor/mcp.json.

Tools

Every tool returns a single JSON text block. On failure, the block is {"error": "..."} and the MCP result is flagged with isError: true.

search_icons

Searches the index and returns ranked matches with import statements.

Argument

Type

Required

Description

query

string

yes

What the icon should depict, e.g. "trash"

provider

string

no

Provider id or package. Default: every provider in .iconmcp.json

version

string

no

Version or range. Default: resolved as described in Versions

style

string

no

Exact style filter, e.g. "outline", "solid", "filled" (tabler), "regular" (fluentui), "two-tone" (antdesign) or a phosphor weight such as "bold". Lucide icons are all outline; base carbon icons have no style

set

string

no

Exact set filter, e.g. "fa6" or "md" for react-icons

limit

integer

no

Maximum results, 1 to 50, default 10

Example call:

{ "query": "trash", "provider": "lucide", "limit": 3 }

Response:

{
  "results": [
    { "name": "trash", "importName": "Trash", "importPath": "lucide-react", "package": "lucide-react",
      "version": "0.460.0", "style": "outline", "set": "lucide",
      "usage": "import { Trash } from 'lucide-react';", "score": 2.0e-14 },
    { "name": "trash-2", "importName": "Trash2", "importPath": "lucide-react", "package": "lucide-react",
      "version": "0.460.0", "style": "outline", "set": "lucide",
      "usage": "import { Trash2 } from 'lucide-react';", "score": 1.6e-6 },
    { "name": "delete", "importName": "Delete", "importPath": "lucide-react", "package": "lucide-react",
      "version": "0.460.0", "style": "outline", "set": "lucide",
      "usage": "import { Delete } from 'lucide-react';", "score": 1.2e-4 }
  ]
}

How search works:

  • provider, style and set are exact, case-insensitive filters. They are applied before ranking.

  • Ranking uses Fuse.js fuzzy matching over the icon name, import name, keywords and tags. Small typos are tolerated: "detele" finds Delete.

  • score runs from 0 (perfect) to 1, so lower is better. Results from several providers are merged and sorted by score.

  • Multi-word queries are tokenized: each word is matched on its own, only icons that match every word are kept, and they are ranked by their average score. So "trash can" finds trash-can icons. Short keyword queries ("trash", "settings", "beer") still cast the widest net.

  • If one provider fails, for example because its version can't be resolved or the download fails, its results are skipped and a warnings array explains why. The other providers still return results.

list_providers

Takes no arguments. Returns the providers configured in .iconmcp.json with their resolved versions, plus every provider TrueIcon supports.

{
  "configured": [
    { "id": "lucide", "package": "lucide-react", "version": "^0.460.0", "source": "package.json" },
    { "id": "heroicons", "package": "@heroicons/react", "version": "2.1.5", "source": "iconmcp.json" }
  ],
  "registry": [
    { "id": "react-icons", "package": "react-icons", "description": "Aggregated icon sets (Font Awesome, Material, Feather, and more) as React components" },
    { "id": "lucide", "package": "lucide-react", "description": "Lucide icons as React components" },
    { "id": "heroicons", "package": "@heroicons/react", "description": "Heroicons by the Tailwind CSS team as React components" },
    { "id": "phosphor", "package": "@phosphor-icons/react", "description": "Phosphor icons in six weights (thin, light, regular, bold, fill, duotone) as React components" },
    { "id": "tabler", "package": "@tabler/icons-react", "description": "Tabler icons (outline and filled) as React components" },
    { "id": "iconoir", "package": "iconoir-react", "description": "Iconoir icons (regular and solid) as React components" },
    { "id": "fluentui", "package": "@fluentui/react-icons", "description": "Microsoft Fluent UI System icons (regular, filled and color) as React components" },
    { "id": "carbon", "package": "@carbon/icons-react", "description": "IBM Carbon Design System icons as React components" },
    { "id": "antdesign", "package": "@ant-design/icons", "description": "Ant Design icons (outlined, filled and two-tone) as React components" }
  ]
}

source is "iconmcp.json" or "package.json". version and source are null when neither file provides a version. id is null for a configured package TrueIcon doesn't support.

get_icon

Gets the full record and import statement for an icon whose name the assistant already knows.

Argument

Type

Required

Description

name

string

yes

Icon name ("trash-2") or import name ("Trash2"). Exact match first, then case-insensitive

provider

string

yes

Provider id or package

version

string

no

Version or range. Default: resolved as described in Versions

Example call:

{ "name": "Trash2", "provider": "lucide" }

Response:

{
  "id": "lucide-react@0.460:trash-2",
  "name": "trash-2",
  "importName": "Trash2",
  "importPath": "lucide-react",
  "provider": "lucide",
  "package": "lucide-react",
  "version": "0.460.0",
  "style": "outline",
  "set": "lucide",
  "categories": [],
  "tags": [],
  "keywords": ["trash", "2", "delete", "remove", "bin", "garbage", "rubbish"],
  "svg": "<path d=\"M3 6h18\"/><path d=\"M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6\"/>…",
  "usage": "import { Trash2 } from 'lucide-react';"
}

svg is the icon's inner SVG markup, meaning the children of the root <svg> element. Heroicons uses the same import name in every size and style (TrashIcon). Pass the full variant name, such as "trash-24-outline", to get a specific one.

ping

A health check that returns {"status":"ok","server":"trueicon"}.

Indexing and caching

The first time a tool needs package@major.minor, TrueIcon does the following:

  1. It downloads the package tarball from https://registry.npmjs.org, verifies its sha512 integrity, and extracts it into the cache.

  2. It parses the package's shipped files with the provider's adapter. Nothing is executed. Icons are read from the compiled source.

  3. It writes index.json (one record per icon) and meta.json (exact version, synonyms hash, index format, build time).

Later calls only read index.json. Package files are never touched at query time, and your node_modules is never read or modified. If several tool calls need the same index at once, they share one download.

The cache root is ~/.trueicon/cache, or $TRUEICON_CACHE if set:

~/.trueicon/cache/
├── lucide-react@0.460/          # extracted package + index.json + meta.json
├── react-icons@5.3/             # extracted package + index.json + meta.json
├── heroicons-react@2.1/         # extracted @heroicons/react package
└── @heroicons/react@2.1/        # index.json + meta.json for @heroicons/react
  • Downloads go to <package>@<major.minor>, where scoped names are flattened: @heroicons/react becomes heroicons-react. A .download-complete marker is written last, and a directory without it is treated as partial and replaced.

  • Indexes go to <package>@<major.minor>/index.json and meta.json. For unscoped packages this is the same directory as the download.

  • The cache is safe to delete. It is rebuilt on demand, which needs network access.

Each record's keywords combine the name parts, the tags, and synonym expansions from the bundled synonyms.json. The expansions are added at index time, so "bin" finds Trash2 without any extra work at query time.

Contributing

git clone https://github.com/manikumarkv/trueicon.git
cd trueicon
npm ci
npm run build      # compile to dist/
npm test           # vitest
npm run lint       # eslint
npm run typecheck  # tsc --noEmit

CI runs lint, typecheck and tests on Node 20 and 22 for every push and pull request.

Tests

Command

What it checks

Network

npm test

Adapter parsing and every tool (search_icons, get_icon, list_providers) for all 9 providers, using the small fixtures in tests/fixtures/

No

npm run smoke

Every provider against the real npm packages: several pinned releases plus the current latest, checking the icon count and a few well-known icons

Yes

The fixtures only change when someone edits them, so they can't catch a provider that changes its package format upstream. npm run smoke does. Run npm run smoke -- lucide tabler to check only some providers. CI runs it on pull requests that change src/providers/, src/indexer/ or src/cache/, and every Monday against the latest releases.

Testing and debugging locally

These scripts build the server and run it against playground/, a sample project that lists all 9 providers at their latest versions. They use a separate cache in .cache/dev/, so your real ~/.trueicon cache is untouched.

# Call one tool and print the result
npm run dev:call -- list_providers
npm run dev:call -- search_icons query="trash can" limit=5
npm run dev:call -- search_icons query=trash provider=lucide version=1.47.0
npm run dev:call -- get_icon name=Trash2 provider=lucide

# Open the MCP Inspector web UI on the local build
npm run dev:inspect

# Same, with the Node debugger on port 9229
npm run dev:debug
  • Arguments are key=value pairs. Numbers and booleans are parsed, so limit=5 is sent as a number.

  • Another project: set TRUEICON_PROJECT_DIR to test against its package.json and .iconmcp.json, e.g. TRUEICON_PROJECT_DIR=~/code/my-app npm run dev:inspect.

  • Rebuild indexes: add --fresh to delete the dev cache first, e.g. npm run dev:call -- --fresh search_icons query=trash. Use it after changing an adapter.

  • Breakpoints: run npm run dev:debug, then in VS Code use Debug: Attach to Node Process, or open chrome://inspect in Chrome. Source maps are on, so breakpoints work in the .ts files under src/. Set them, then call a tool from the Inspector.

  • Logging: stdout carries the MCP protocol, so log with console.error. It shows in the terminal for dev:call and in the Inspector's server log for dev:inspect.

Extending synonyms.json

src/synonyms/synonyms.json maps a term to extra search terms:

{
  "trash": ["delete", "remove", "bin", "garbage", "rubbish"],
  "logout": ["sign-out", "signout", "exit", "leave"]
}
  • Keys are matched against an icon's name parts (the name split on -) and its tags. trash-2 matches the key trash.

  • Values are added to that icon's keywords.

  • Expansion is one-way. If bin should also find icons named delete, add both "trash": ["bin"] and "delete": ["bin"], or add a reverse entry.

  • Write keys and values in lowercase, and give every key a non-empty array of strings. tests/synonyms.test.ts checks this.

  • Changing the file changes its hash, so cached indexes rebuild automatically on the next search.

Adding a provider

  1. Register it in src/providers/registry.ts with a stable id, the npm package and a short description.

  2. Write an adapter in src/providers/adapters/<provider>.ts that exports parseIcons(packageDir: string): RawIcon[] (see src/providers/adapter.ts). It gets the extracted package directory and returns one RawIcon per icon:

    • name: kebab-case and unique within the package, because it becomes part of the record id. Use toKebabCase from adapter.ts. If the package has variants with clashing component names, add the variant to the name, as the heroicons, react-icons, phosphor and iconoir adapters do.

    • importName and importPath: the exact export and module specifier a user would import.

    • svg: the inner SVG markup. LiteralCursor (src/providers/jsLiteral.ts) parses JS object and array literals without executing code. toSvgAttrs and renderSvg (src/providers/svg.ts) turn React props into SVG markup, and parseCreateElement reads compiled createElement(...) trees.

    • Optional style, set, categories and tags.

    • Put a comment at the top of the adapter describing the package's file layout, as the existing adapters do.

  3. Wire it up in src/providers/adapters/index.ts by adding it to ADAPTERS under the provider id.

  4. Test it. Add a small pinned fixture under tests/fixtures/<provider>/ that mirrors the package layout, with a few real icon files plus any files the adapter must skip. Then add tests/adapters/<provider>.test.ts, covering name mapping, import paths, SVG output and buildIndex record ids like the existing adapter tests. tests/adapters/common.test.ts fails if a registered provider has no adapter.

  5. Add it to the tool tests by adding a case to CASES in tests/providers-tools.test.ts: the fixture, a search query, one icon with its exact import line, and a deprecated alias if the package has them. The test fails if a registered provider has no case.

  6. Add smoke targets to TARGETS in scripts/smoke.mjs: a few well-known import names and a minimum icon count well below the real one. Then run npm run smoke -- <provider> to check it against the real published package.

License

MIT © 2026 manikumarkv

Available Tools

4 tools
get_iconA

Get the full record and exact import statement for an icon whose name is already known, e.g. Trash2 from lucide.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesIcon name or import name, e.g. "trash-2" or "Trash2"
versionNoPackage version or range; defaults to the project's version
providerYesProvider id or npm package, e.g. "lucide" or "lucide-react"

TDQS

A4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden. It does disclose the output behavior ('full record and exact import statement'), which is the core behavioral trait for a getter. However, it does not mention failure behavior for unknown icons, provider-specific formatting, or any other side effects, leaving a moderate gap.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single sentence that front-loads the verb and resource, conveys the scoping constraint, and includes a clarifying example. Every word earns its place with zero redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple getter with 3 parameters, 100% schema coverage, and no output schema, the description adequately covers the return value and the tool's niche relative to siblings. The only minor gap is the lack of error/failure semantics for unknown icon names, which is low-stakes for a read-only lookup.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents name, version, and provider including examples and defaults. The description adds only an example mapping ('Trash2 from lucide') but no additional meaning beyond what the schema provides, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('Get') with a specific resource ('full record and exact import statement') and adds a scoping constraint ('whose name is already known') that clearly differentiates it from the sibling search_icons. The concrete example 'Trash2 from lucide' makes the purpose unmistakable.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

'Whose name is already known' gives clear context for when to use this tool versus searching, implicitly routing the agent away from search_icons and toward this tool when the name is known. However, it does not explicitly name the alternative or state when-not-to-use, so it falls short of the explicit-alternative bar.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_providersA

List the icon providers configured for this project and all providers trueicon supports.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A3.9/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden of behavioral disclosure. The verb 'List' implies a read-only operation and the scope is explicit, but the description does not mention return format, side effects, authorization, or any other behavioral context. It is adequate but not rich.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single, front-loaded sentence that states the action and scope with no filler. Every word earns its place, and the structure is immediately scannable.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter list tool with no output schema, the description is complete: it identifies exactly what is listed and the scope. An agent can invoke it without needing additional context, and the sibling set does not introduce ambiguity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters, so the schema description coverage is effectively 100% and there is nothing for the description to explain. The 0-parameter baseline of 4 applies; no parameter information is missing.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('List') and a clear resource ('icon providers'), and it specifies the scope: providers configured for the project plus all providers trueicon supports. This makes it easy to distinguish from siblings like search_icons or get_icon 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.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no guidance on when to use this tool versus alternatives. The sibling tool names are provided, but the description never mentions them or gives conditions for selecting this tool over search_icons or get_icon.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

pingB

Health check

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

B3.1/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden. 'Health check' implies a read-only status verification but does not disclose any return format, potential delay, or what exactly is being checked. An agent gets minimal behavioral insight beyond the tool name.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is extremely short—two words with no filler. For a tool with zero parameters and a clear single purpose, this is appropriately sized. It is not verbose or structured, but that is acceptable here.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the trivial nature of a health check with no parameters, the description is nearly sufficient. However, with no output schema or described return behavior, an agent does not know what the response will look like or how to interpret success vs. failure. Sibling separation is clear, but the missing response detail is a gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters approximating the schema, so 100% of parameters are documented. The description adds no parameter detail, but none is needed. Baseline for 0-param tools is 4.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description 'Health check' directly names the tool's function as a status probe, which is a specific enough resource scope. It distinguishes itself from the icon/provider siblings, which clearly serve different purposes.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no explicit guidance on when to use this tool versus alternatives. While the sibling names make the distinction apparent, the description does not state any context, prerequisites, or conditions that would help an agent decide to call ping.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_iconsA

Search icons in the icon packages installed in the project. Returns ranked matches with ready-to-paste import statements.

ParametersJSON Schema
NameRequiredDescriptionDefault
setNoIcon set filter (react-icons), e.g. "fa6"
limitNoMaximum results (1-50, default 10)
queryYesWhat the icon should depict, e.g. "trash can"
styleNoStyle filter, e.g. "outline" or "solid"
versionNoPackage version or range; defaults to the project's version
providerNoProvider id or npm package, e.g. "lucide" or "lucide-react"

TDQS

A3.5/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full disclosure burden. It usefully discloses that results are ranked and include ready-to-paste import statements, but it does not clarify read-only status, matching semantics, or what 'installed packages' means in practical terms.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences with no filler. The main verb and scope are front-loaded, and the second sentence adds the key output detail without redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 6-parameter tool with no annotations and no output schema, the description gives the essential purpose and output but leaves usage guidance and behavioral details to inference. The high schema coverage compensates for parameter semantics, so it is adequate but not fully complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the input schema already documents all six parameters, including query, set, style, version, and provider. The description adds no parameter-specific meaning beyond the overall search scope, so the baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific action ('search icons') and a clear scope ('icon packages installed in the project'), and signals the output ('ranked matches with ready-to-paste import statements'). It is distinguishable from siblings like get_icon and list_providers, though it does not explicitly name them.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies use when an agent needs to locate an icon by concept, but it gives no explicit when-to-use or when-not-to-use guidance and does not mention alternatives such as get_icon for retrieving a specific icon. The sibling names help, but the description itself leaves the choice to inference.

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.

  1. 4 tool updatesv0.1.1
    • First observedget_icon
    • First observedlist_providers
    • First observedping
    • First observedsearch_icons

TDQS

A3.7/5.0

Scored across 4 tools

Disambiguation5/5

Each tool serves a clearly distinct purpose: ping for health, search_icons for discovery, get_icon for exact retrieval, and list_providers for configuration. There is no ambiguity between searching and fetching a known icon, as the descriptions explicitly state when to use each.

Naming Consistency4/5

Three of four tools follow a consistent verb_noun pattern (search_icons, list_providers, get_icon). The exception is 'ping', which is a standard health-check verb and not confusing, but it does deviate from the naming convention.

Tool Count5/5

With only 4 tools, the server is tightly scoped to its purpose of searching and retrieving icons. Each tool is essential and there is no bloat or redundancy, making the count ideal for this domain.

Completeness4/5

The tool surface covers the core read operations: searching, retrieving exact icons, and listing providers. A minor gap is the lack of a way to browse all icons in a provider without a search query, but this is a workable limitation given the search functionality.

Maintenance

ActivityNo data
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers