关于 TrueIcon
TrueIcon 是面向 AI 编码助手的 MCP 服务,可按项目实际使用的图标包和版本搜索图标,并返回名称、导入路径及导入语句。它覆盖 React、Vue 和 Svelte 的多种图标包,结果对应所选版本中真实存在的图标。
主要功能
- 01按项目依赖和版本索引图标
- 02搜索图标并返回导入语句
- 03支持 React、Vue 和 Svelte 图标包
- 04可选语义搜索与本地缓存
适用场景
- 01为项目界面查找可用图标
- 02核对图标名称及对应导入路径
- 03按指定图标包版本生成导入代码
MCP 相关
TrueIcon 作为 MCP 服务向客户端提供 search_icons、get_icon 和 list_providers 等图标查询工具。客户端启动该服务后,它会读取项目配置并搜索对应图标包。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
npx -y trueiconTRUEICON_PROJECT_DIRAbsolute path to the project whose icon packages to search. Defaults to the working directory.TRUEICON_CACHEDirectory for the downloaded icon package cache. Defaults to ~/.trueicon/cache.本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。
工具
4收录的工具列表 · 更新于 3 周前
此工具无需参数。
详细介绍
TrueIcon
TrueIcon 是一个 MCP 服务,可为 AI 编码助手提供准确且与版本匹配的图标引用。助手会搜索项目实际使用的图标包(lucide-react、react-icons、@heroicons/react、@phosphor-icons/react、@tabler/icons-react、iconoir-react、@fluentui/react-icons、@carbon/icons-react、@ant-design/icons、@mui/icons-material、@radix-ui/react-icons、@remixicon/react、Font Awesome Free 包,以及 Lucide、Heroicons、Tabler 和 Phosphor 的 Vue 与 Svelte 包),并返回真实的图标名称、导入路径和可直接粘贴的 import 语句。
为什么选择 TrueIcon
AI 助手经常会猜测图标名称。它们猜到的图标可能根本不存在,可能在几个版本之前就已更名,也可能属于其他图标库;只有在构建失败时,你才会发现问题。TrueIcon 可以弥补这一缺口:
- 它会读取项目使用的图标包及其版本。
- 它会从 npm 下载这些确切版本,并为其中的每个图标建立索引。
- 助手会调用
search_icons,并获得保证存在于该版本中的搜索结果,例如import { Trash2 } from 'lucide-react';。
支持的提供方
| 提供方 ID | npm 包 | 图标命名 |
|---|---|---|
lucide | lucide-react | Lucide 的文件名,例如 trash-2 → Trash2 |
heroicons | @heroicons/react | <icon>-<size>-<style>,例如 trash-24-outline → TrashIcon |
react-icons | react-icons | <set>-<icon>,例如 fa6-beer-mug-empty → FaBeerMugEmpty |
phosphor | @phosphor-icons/react | 常规粗细使用 <icon>,其他情况使用 <icon>-<weight>,例如 trash-bold → TrashIcon,并设置 weight="bold" |
tabler | @tabler/icons-react | Tabler 的图标名称,例如 trash → IconTrash,trash-filled → IconTrashFilled |
iconoir | iconoir-react | 常规样式使用 <icon>,实心样式使用 <icon>-solid,例如 trash-solid → TrashSolid |
fluentui | @fluentui/react-icons | <icon>-<style>,其中 style 为 regular、filled 或 color,例如 delete-regular → DeleteRegular。仅索引可缩放(1em)的图标,不索引特定尺寸的变体 |
carbon | @carbon/icons-react | Carbon 的导出名称,采用 kebab case,例如 trash-can → TrashCan。变体会添加 -filled、-alt 或 -color,例如 accessibility-filled → AccessibilityFilled |
antdesign | @ant-design/icons | <icon>-<theme>,其中 theme 为 outlined、filled 或 two-tone,例如 delete-outlined → DeleteOutlined |
mui | @mui/icons-material | MUI 的导出名称,采用 kebab case,例如 delete → Delete。主题会添加 -outlined、-rounded、-sharp 或 -two-tone,例如 delete-outlined → DeleteOutlined;基础图标的样式为 filled |
radix | @radix-ui/react-icons | Radix 的图标名称,例如 trash → TrashIcon,github-logo → GitHubLogoIcon |
remix | @remixicon/react | Remix 的图标名称,使用 -line 或 -fill 样式,例如 delete-bin-line → RiDeleteBinLine |
fontawesome-solid | @fortawesome/free-solid-svg-icons | Font Awesome 的图标名称,例如 trash-can → faTrashCan。旧名称仍可解析:get_icon 会将 trash-alt 或 faTrashAlt 解析为 faTrashCan,并将 faSearch 解析为 faMagnifyingGlass |
fontawesome-regular | @fortawesome/free-regular-svg-icons | 与 fontawesome-solid 相同,例如 star → faStar |
fontawesome-brands | @fortawesome/free-brands-svg-icons | 与 fontawesome-solid 相同,例如 github → faGithub |
Vue 和 Svelte
这些包索引的插画与上面的 React 包相同,但使用各自的组件名称和导入路径。
| 提供方 ID | npm 包 | 图标命名 |
|---|---|---|
lucide-vue | @lucide/vue | 与 lucide 相同,例如 trash → Trash |
lucide-vue-next | lucide-vue-next | 与 lucide 相同。上游已弃用,推荐使用 @lucide/vue,但目前仍广泛使用 |
lucide-svelte5 | @lucide/svelte | 与 lucide 相同(Svelte 5) |
lucide-svelte | lucide-svelte | 与 lucide 相同。上游已弃用,推荐使用 @lucide/svelte |
heroicons-vue | @heroicons/vue | 与 heroicons 相同,例如 trash-24-outline → 来自 @heroicons/vue/24/outline 的 TrashIcon |
tabler-vue | @tabler/icons-vue | 与 tabler 相同,例如 trash → IconTrash |
tabler-svelte | @tabler/icons-svelte | 与 tabler 相同 |
phosphor-vue | @phosphor-icons/vue | 与 phosphor 相同,例如 trash-bold → PhTrash,并设置 weight="bold" |
phosphor-svelte | phosphor-svelte | 与 phosphor 相同,例如 trash-bold → TrashIcon,并设置 weight="bold" |
Heroicons 没有官方的 Svelte 包。Angular 包暂不支持。
工具接受提供方 ID 或 npm 包名称("lucide" 或 "lucide-react")。用法示例是导入语句,在 React、Vue 和 Svelte 中的写法相同。Phosphor 的所有字重共用一个组件,因此请将记录的 style 作为 weight 属性传入(例如,<TrashIcon weight="bold" />);用法示例仅显示导入语句。Font Awesome 的导入项是图标定义,而不是组件:请使用 @fortawesome/react-fontawesome 渲染,例如 <FontAwesomeIcon icon={faTrashCan} />。
安装
TrueIcon 需要 Node.js 20 或更高版本。
# 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 是一个 stdio MCP 服务。MCP 客户端会启动它;手动运行时,它只会向 stderr 输出 trueicon: v<version> running on stdio,然后等待从 stdin 接收 JSON-RPC。
快速开始
- 在 MCP 客户端中注册 TrueIcon(Claude Code、Claude Desktop 或 VS Code 和 Cursor)。
- 请助手提供一个图标。
大多数项目到这里就完成了。TrueIcon 会查找 package.json 中列出的图标包,以及安装在 node_modules 中的版本。首次搜索每个包时,TrueIcon 会下载并为其建立索引,这需要几秒钟。之后的搜索会使用本地缓存。
配置
搜索哪些图标包
- 默认情况下,会搜索
package.json的dependencies或devDependencies中列出的所有受支持的软件包。 - 如果项目中有
.iconmcp.json,则只搜索其中列出的软件包。可用它仅搜索部分图标包、添加package.json未列出的图标包(例如通过 UI 套件引入的图标包),或锁定版本。
{
"providers": [
{ "package": "lucide-react" },
{ "package": "react-icons", "version": "5.3.0" },
{ "package": "@heroicons/react", "version": "^2.1.0" }
]
}
| 字段 | 类型 | 必填 | 含义 |
|---|---|---|---|
providers | 数组 | 是 | 要搜索的图标包。如果其中列出了任何图标包,就不会使用 package.json 来选择软件包。 |
providers[].package | 字符串 | 是 | 受支持提供程序的 npm 软件包名称,例如 lucide-react、@lucide/vue 或 @tabler/icons-svelte(参见受支持的提供程序)。 |
providers[].version | 字符串 | 否 | 精确版本或 npm 版本范围。会覆盖已安装的版本(参见版本)。 |
semantic | 布尔值 | 否 | 启用语义搜索(默认值为 false)。参见下文。 |
.iconmcp.json中不受支持的软件包会被跳过,search_icons会将其报告为警告。- 无效的 JSON 或格式错误的条目会导致工具返回错误,并指出文件名和错误字段。
- 如果两个文件都未列出受支持的软件包,
search_icons会返回错误,说明它检查了哪个目录。你仍可以在工具调用中传入provider。
语义搜索(可选启用)
在 .iconmcp.json 中设置 "semantic": true,即可为 search_icons 添加基于含义的排序。每个查询都会通过一个小型本地模型(all-MiniLM-L6-v2,约 90 MB,只会下载一次到 transformers.js 缓存)生成嵌入,并与索引构建时生成的每个图标向量进行匹配;随后通过倒数排名融合将语义候选结果与关键词结果合并,因此精确名称匹配仍会优先,而“移除背景”这类概念性查询也能找到 eraser。
{
"providers": [{ "package": "lucide-react" }],
"semantic": true
}
语义搜索基于 @huggingface/transformers 运行。它是可选的同级依赖,默认不会安装,因此从不启用该标志的安装会保持轻量。要启用语义搜索,请将其与 trueicon 一起安装一次(约 400 MB):
npm install @huggingface/transformers
如果启用了该标志,但缺少此软件包,search_icons 和 get_icon 会回退到仅使用关键词的索引,并返回一行警告及安装命令。
切换此标志会重建一次索引(向量会与每条记录一同存储在 index.json 中,meta.json 则会记录嵌入模型)。整个过程完全在本地运行:数据不会离开你的设备。TRUEICON_SEMANTIC=1(或 0)可在单次运行中覆盖此标志。
项目目录指什么
TrueIcon 会从项目目录读取 package.json、.iconmcp.json 和 node_modules。它会按以下顺序选择目录:
- 设置了
$TRUEICON_PROJECT_DIR时,使用其指定的目录。 - MCP 客户端与服务共享的文件夹(MCP 根目录),其中包含
package.json或.iconmcp.json。支持根目录的客户端(如 VS Code)会告知 TrueIcon 你正在使用哪些文件夹,因此无需任何设置,它就能跟随你打开的项目。 - 服务的工作目录(其中包含上述文件之一)。Claude Code 会在你的项目中启动服务,因此 TrueIcon 通过此方式找到项目。
- 首个共享文件夹;如果没有,则使用工作目录。
list_providers 会显示当前使用的目录以及选用该目录的规则,方便你检查客户端的行为。
环境变量
| 变量 | 默认值 | 用途 |
|---|---|---|
TRUEICON_PROJECT_DIR | 共享文件夹,否则为工作目录 | 存放 package.json 和 .iconmcp.json 的项目根目录 |
TRUEICON_CACHE | ~/.trueicon/cache | 存储下载的软件包和索引的位置 |
TRUEICON_SEMANTIC | .iconmcp.json 标志 | 1/0,强制本次运行启用/关闭语义搜索 |
版本
自动检测
提供方的版本按以下顺序确定:
- 如果有,使用传递给工具调用的
version参数。 - 使用
.iconmcp.json中提供方的version。 - 使用
node_modules中安装的版本;先检查项目目录,再逐级检查父目录,以便找到提升到 monorepo 根目录的软件包。 - 使用项目
package.json中为该软件包声明的版本范围;先检查dependencies,再检查devDependencies。
如果以上都不可用,工具会要求你固定版本或将软件包添加到 package.json。TrueIcon 不会读取你的锁文件,而是从 npm 下载自己的软件包副本,不会使用 node_modules 中的文件。对于版本范围,它会为范围的基础版本建立索引:^0.460.0 会为 [email protected] 建立索引。对于 a || b 范围,只会采用第一部分。在运行 npm install 之前,该基础版本可能比你最终获得的版本更旧;如果确切版本很重要,请在 .iconmcp.json 中固定版本。
版本策略
索引按 major.minor 编号:
- 忽略补丁版本。 一个索引适用于所有
0.460.x。基于0.460.0构建的索引会响应针对0.460.3的请求。 - 次版本变更会建立独立索引。 将
lucide-react从0.460升级到0.461后,下次搜索时会建立新索引,无需手动操作。 - 主版本严格区分。 不同的主版本始终使用独立索引,绝不会使用其他主版本的索引。
- 缓存的索引会在捆绑的
synonyms.json变更(通过哈希检测)或索引格式变更时自动重建。
在 Claude 中使用
Claude Code
在项目目录中添加 TrueIcon:
claude mcp add trueicon -- npx -y trueicon
或者在项目根目录提交 .mcp.json,与团队共享:
{
"mcpServers": {
"trueicon": {
"command": "npx",
"args": ["-y", "trueicon"]
}
}
}
Claude Code 会在项目目录中启动服务,因此无需设置就能在那里找到 package.json。如果它从其他位置运行,请添加 "env": { "TRUEICON_PROJECT_DIR": "/absolute/path/to/project" }。
Claude Desktop
Claude Desktop 不会在项目目录中启动服务,因此请设置 TRUEICON_PROJECT_DIR。如果你的 Claude Desktop 版本会与服务共享文件夹,TrueIcon 会改用这些文件夹;list_providers 会显示它选择的目录。编辑 claude_desktop_config.json:macOS 上的路径为 ~/Library/Application Support/Claude/claude_desktop_config.json,Windows 上的路径为 %APPDATA%\Claude\claude_desktop_config.json。
{
"mcpServers": {
"trueicon": {
"command": "npx",
"args": ["-y", "trueicon"],
"env": {
"TRUEICON_PROJECT_DIR": "/absolute/path/to/your/project"
}
}
}
}
编辑文件后重启 Claude Desktop。
在 VS Code 和 Cursor 中使用
使用本 README 顶部的安装徽章。它们会添加 TrueIcon,并将 TRUEICON_PROJECT_DIR 设置为 ${workspaceFolder},以便搜索你当前打开的项目。
要在 VS Code 中手动添加,请在项目中创建 .vscode/mcp.json:
{
"servers": {
"trueicon": {
"command": "npx",
"args": ["-y", "trueicon"],
"env": {
"TRUEICON_PROJECT_DIR": "${workspaceFolder}"
}
}
}
}
在 Cursor 中,请在 .cursor/mcp.json 的 "mcpServers" 下使用相同的条目。
工具
每个工具都会返回一个 JSON 文本块。发生失败时,该文本块为 {"error": "..."},且 MCP 结果会标记为 isError: true。
search_icons
搜索索引并返回按相关性排序的匹配项及导入语句。
| Argument | Type | Required | Description |
|---|---|---|---|
query | string | yes | 图标应描绘的内容,例如 "trash" |
provider | string | no | 提供方 ID 或包。默认值:项目使用的所有提供方(参见配置) |
version | string | no | 版本或范围。默认值:按版本中所述解析 |
style | string | no | 精确的样式筛选条件,例如 "outline"、"solid"、"filled"(tabler)、"regular"(fluentui)、"two-tone"(antdesign、mui)、"line"(remix)、"brands"(Font Awesome),或 phosphor 的某种粗细,如 "bold"。Lucide 图标全部为 outline;基础 carbon 图标和 radix 图标没有样式 |
set | string | no | 精确的图标集筛选条件,例如 react-icons 的 "fa6" 或 "md" |
limit | integer | no | 最大结果数,范围为 1 到 50,默认值为 10 |
调用示例:
{ "query": "trash", "provider": "lucide", "limit": 3 }
响应:
{
"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": 0 },
{ "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": 0.02 },
{ "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": 0.6 }
]
}
搜索工作原理:
-
provider、style和set是精确且不区分大小写的筛选条件。它们会在排序前应用。 -
候选项来自 Fuse.js 对图标名称、导入名称、关键词和标签进行的模糊匹配。允许少量拼写错误:
"detele"可以找到Delete。 -
名称与查询相符的图标会优先排序,比较时会去掉名称中的样式后缀(
delete-bin-line→delete-bin):- 名称与查询相同:
delete可以找到delete、delete-outlined、DeleteRegular - 名称以查询开头:
delete-bin-line - 名称中包含查询短语:
"arrow right"可以找到circle-arrow-right - 查询中的每个词都出现在名称、同义词或标签中:
trash可以找到restore-from-trash,而delete可以通过 trash → delete 这一同义词找到相关图标
同一层级内,名称较短的排在前面,因此普通图标优先于组合图标(
delete在restore-from-trash之前),且每个图标的各个样式会排在一起,默认样式优先。除非查询中包含变体编号,否则会忽略编号,因此trash的排序是trash,然后是trash-2。其余结果(如拼写错误匹配)按模糊匹配分数排序。 - 名称与查询相同:
-
score的取值范围为0(完全匹配)到1,因此越低越好。它体现了上述排序规则,因此来自多个提供方的结果可以合并并按分数排序,同时保留分数。 -
多词查询会进行分词:每个词单独匹配,只保留匹配所有词的图标,并按平均分数排序。因此,
"trash can"可以找到trash-can图标。较短的关键词查询("trash"、"settings"、"beer")仍会尽可能广泛地搜索。 -
如果某个提供方失败,例如无法解析其版本或下载失败,则会跳过该提供方的结果,并通过
warnings数组说明原因。其他提供方仍会返回结果。
list_providers
不接受任何参数。返回 TrueIcon 读取的项目目录及其查找方式、项目使用的提供方及其解析后的版本,以及 TrueIcon 支持的所有提供方。
{
"project": { "dir": "/Users/you/code/my-app", "source": "roots" },
"providersFrom": "package.json",
"configured": [
{ "id": "lucide", "package": "lucide-react", "version": "1.47.0", "source": "node_modules" },
{ "id": "heroicons", "package": "@heroicons/react", "version": "^2.1.0", "source": "package.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" },
{ "id": "mui", "package": "@mui/icons-material", "description": "Material UI icons (filled, outlined, rounded, sharp and two-tone) as React components" },
{ "id": "radix", "package": "@radix-ui/react-icons", "description": "Radix UI icons (15x15) as React components" },
{ "id": "remix", "package": "@remixicon/react", "description": "Remix Icon (line and fill) as React components" },
{ "id": "fontawesome-solid", "package": "@fortawesome/free-solid-svg-icons", "description": "Font Awesome Free solid icons, rendered with @fortawesome/react-fontawesome" },
{ "id": "fontawesome-regular", "package": "@fortawesome/free-regular-svg-icons", "description": "Font Awesome Free regular icons, rendered with @fortawesome/react-fontawesome" },
{ "id": "fontawesome-brands", "package": "@fortawesome/free-brands-svg-icons", "description": "Font Awesome Free brand logos, rendered with @fortawesome/react-fontawesome" },
{ "id": "lucide-vue", "package": "@lucide/vue", "description": "Lucide icons as Vue components" },
{ "id": "lucide-vue-next", "package": "lucide-vue-next", "description": "Lucide icons as Vue components (deprecated package, replaced by @lucide/vue)" },
{ "id": "lucide-svelte5", "package": "@lucide/svelte", "description": "Lucide icons as Svelte 5 components" },
{ "id": "lucide-svelte", "package": "lucide-svelte", "description": "Lucide icons as Svelte components (deprecated package, replaced by @lucide/svelte)" },
{ "id": "heroicons-vue", "package": "@heroicons/vue", "description": "Heroicons by the Tailwind CSS team as Vue components" },
{ "id": "tabler-vue", "package": "@tabler/icons-vue", "description": "Tabler icons (outline and filled) as Vue components" },
{ "id": "tabler-svelte", "package": "@tabler/icons-svelte", "description": "Tabler icons (outline and filled) as Svelte components" },
{ "id": "phosphor-vue", "package": "@phosphor-icons/vue", "description": "Phosphor icons in six weights as Vue components" },
{ "id": "phosphor-svelte", "package": "phosphor-svelte", "description": "Phosphor icons in six weights as Svelte components" }
]
}
project.source为"TRUEICON_PROJECT_DIR"、"roots"(MCP 客户端共享的文件夹)或"cwd"(服务的工作目录)。参见项目目录是什么。providersFrom为"iconmcp.json"、"package.json";如果两者均未指定受支持的包,则为null。- 每个提供方的
source表示其版本来源:"iconmcp.json"、"node_modules"或"package.json"。如果没有任何来源提供版本,version和source将为null。对于 TrueIcon 不支持的.iconmcp.json中的包,id为null。
get_icon
获取助手已知名称的图标的完整记录和导入语句。
| 参数 | 类型 | 必填 | 描述 |
|---|---|---|---|
name | string | 是 | 图标名称("trash-2")或导入名称("Trash2")。先进行精确匹配,再进行不区分大小写的匹配 |
provider | string | 是 | Provider ID 或包名 |
version | string | 否 | 版本或范围。默认值:按 Versions 中的说明解析 |
调用示例:
{ "name": "Trash2", "provider": "lucide" }
响应:
{
"id": "[email protected]: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 是图标内部的 SVG 标记,也就是根 <svg> 元素的子元素。Heroicons 在所有尺寸和样式中使用相同的导入名称(TrashIcon)。传入完整的变体名称,例如 "trash-24-outline",即可获取指定变体。
ping
健康检查,返回 {"status":"ok","server":"trueicon"}。
索引与缓存
工具首次需要 [email protected] 时,TrueIcon 会执行以下操作:
- 从
https://registry.npmjs.org下载包 tarball,验证其 sha512 完整性,并将其解压到缓存中。 - 使用 Provider 的适配器解析包中随附的文件。不会执行任何内容。图标从编译后的源文件中读取。
- 写入
index.json(每个图标一条记录)和meta.json(确切版本、同义词哈希、索引格式、构建时间)。
之后的调用只读取 index.json。查询时不会访问包文件。对于你的 node_modules,TrueIcon 只读取每个图标包的 package.json 以获取已安装版本,并且绝不会修改其中的任何内容。如果多个工具调用同时需要同一个索引,它们会共用一次下载。
缓存根目录为 ~/.trueicon/cache,如果设置了 $TRUEICON_CACHE,则使用该变量指定的目录:
~/.trueicon/cache/
├── [email protected]/ # extracted package + index.json + meta.json
├── [email protected]/ # extracted package + index.json + meta.json
├── [email protected]/ # extracted @heroicons/react package
└── @heroicons/[email protected]/ # index.json + meta.json for @heroicons/react
- 下载内容存放在
<package>@<major.minor>中,带作用域的名称会扁平化处理:@heroicons/react会变为heroicons-react。最后会写入.download-complete标记,没有该标记的目录会被视为不完整并替换。 - 索引存放在
<package>@<major.minor>/index.json和meta.json中。对于不带作用域的包,这与下载目录相同。 - 删除缓存是安全的。需要时会重新构建,但这需要网络访问。
每条记录的 keywords 会合并名称部分、标签以及随附的 synonyms.json 中的同义词扩展。这些扩展会在索引时添加,因此搜索 "bin" 就能找到 Trash2,查询时无需额外处理。
贡献
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 会在每次推送和拉取请求中,使用 Node 20 和 22 运行 lint、类型检查和测试。
在 Web 版 Claude Code 中,SessionStart 钩子(.claude/hooks/session-start.sh)会在会话开始时安装依赖,因此这些命令可以立即运行。安装时会使用 --ignore-scripts,因为沙盒会阻止可选语义搜索依赖项下载原生模块;因此,依赖该模块的语义测试会在沙盒中跳过。
测试
| 命令 | 检查内容 | 网络 |
|---|---|---|
npm test | 使用 tests/fixtures/ 中的小型固定样例,测试全部 24 个 Provider 的适配器解析和每个工具(search_icons、get_icon、list_providers) | 否 |
npm run smoke | 针对真实 npm 包测试每个 Provider:使用多个固定版本及当前最新版本,检查图标数量和几个知名图标 | 是 |
固定样例只有在有人编辑时才会变化,因此无法检测上游 Provider 是否更改了包格式。npm run smoke 可以做到这一点。运行 npm run smoke -- lucide tabler 可仅检查部分 Provider。CI 会在更改 src/providers/、src/indexer/ 或 src/cache/ 的拉取请求中运行该命令,并在每周一针对最新版本运行。
在本地测试和调试
这些脚本会构建服务,并针对 playground/ 运行。这是一个示例项目,列出了最新版本的全部 24 个提供商。脚本使用 .cache/dev/ 中的独立缓存,因此不会影响你实际使用的 ~/.trueicon 缓存。
# 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
- 参数是
key=value键值对。数字和布尔值会被解析,因此limit=5会以数字形式传入。 - **其他项目:**将
TRUEICON_PROJECT_DIR设置为目标项目,以使用该项目的package.json和.iconmcp.json进行测试,例如:TRUEICON_PROJECT_DIR=~/code/my-app npm run dev:inspect。 - **重建索引:**添加
--fresh,先删除开发缓存,例如:npm run dev:call -- --fresh search_icons query=trash。修改适配器后使用此选项。 - **断点:**运行
npm run dev:debug,然后在 VS Code 中使用 Debug: Attach to Node Process,或在 Chrome 中打开chrome://inspect。已启用源映射,因此可以在src/下的.ts文件中设置断点。设置断点后,从 Inspector 调用工具。 - **日志记录:**stdout 承载 MCP 协议,因此请使用
console.error记录日志。运行dev:call时,日志会显示在终端中;运行dev:inspect时,则会显示在 Inspector 的服务日志中。 - 手动测试提示词:
playground/TEST-PROMPTS.md是一份提示词检查清单,可在 MCP 客户端中针对 playground 运行,并查看预期的工具调用和结果。它涵盖所有工具、全部 15 个提供商、排序、配置错误和语义搜索。发布前请先运行此清单。
扩展 synonyms.json
src/synonyms/synonyms.json 将一个词映射到额外的搜索词:
{
"trash": ["delete", "remove", "bin", "garbage", "rubbish"],
"logout": ["sign-out", "signout", "exit", "leave"]
}
- 键会与图标的名称部分(按
-拆分的名称)及标签进行匹配。trash-2会匹配键trash。 - 值会添加到该图标的
keywords中。 - 扩展是单向的。如果希望搜索
bin也能找到名称为delete的图标,请同时添加"trash": ["bin"]和"delete": ["bin"],或添加反向条目。 - 键和值均使用小写,并确保每个键对应一个非空字符串数组。
tests/synonyms.test.ts会检查这一点。 - 修改该文件会改变其哈希值,因此下次搜索时会自动重建缓存索引。
添加提供商
- 注册提供商:在
src/providers/registry.ts中添加提供商,并设置稳定的id、npmpackage和简短的description。 - 编写适配器:在
src/providers/adapters/<provider>.ts中实现适配器,导出parseIcons(packageDir: string): RawIcon[](参见src/providers/adapter.ts)。它接收解压后的包目录,并为每个图标返回一个RawIcon:name:使用 kebab-case,且在包内唯一,因为它会成为记录 ID 的一部分。使用adapter.ts中的toKebabCase。如果包中有组件名称冲突的变体,请将变体添加到名称中,heroicons、react-icons、phosphor 和 iconoir 适配器就是这样做的。importName和importPath:用户导入时所用的准确导出名称和模块说明符。svg:内部 SVG 标记。LiteralCursor(src/providers/jsLiteral.ts)可以解析 JS 对象和数组字面量,而无需执行代码。toSvgAttrs和renderSvg(src/providers/svg.ts)可将 React props 转换为 SVG 标记,parseCreateElement则读取编译后的createElement(...)树。- 可选字段:
style、set、categories和tags。 - 在适配器顶部添加注释,描述包的文件布局,与现有适配器保持一致。
- 接入适配器:在
src/providers/adapters/index.ts的ADAPTERS中,使用提供商 ID 添加该适配器。 - 编写测试:在
tests/fixtures/<provider>/下添加一个小型固定版本夹具,模拟包的布局,其中包含几个真实图标文件以及适配器必须跳过的文件。然后添加tests/adapters/<provider>.test.ts,参照现有适配器测试,覆盖名称映射、导入路径、SVG 输出和buildIndex记录 ID。若已注册的提供商没有适配器,tests/adapters/common.test.ts会报错。 - 将其添加到工具测试:在
tests/providers-tools.test.ts的CASES中添加一个用例:包含夹具、搜索查询、一个带准确导入语句的图标,以及包中存在的弃用别名。若已注册的提供商没有对应的用例,测试会报错。 - 添加冒烟测试目标:在
scripts/smoke.mjs的TARGETS中添加几个知名导入名称和一个远低于实际数量的最低图标数。然后运行npm run smoke -- <provider>,检查真实发布的包。
许可证
MIT © 2026 manikumarkv
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。