npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

search2chart-mcp

v0.5.0

Published

跨客户端 ECharts 图表 MCP server:数据 → 自包含可交互 HTML + 对话框内联图片(data URI / localhost http / GitHub+jsDelivr CDN 公网 https)

Readme

MCP

echarts-chart-mcp

A cross-agent ECharts chart MCP server. Feed it data (from web search or a CSV/XLSX file), get back an interactive chart as a self-contained HTML file. Works with DeepSeek Harness (DSH), Codex, WorkBuddy, and Trae.

把「数据 → 图表」做成一次开发、多端通用的 MCP server。agent 用自带搜索 / 本地文件取数后调用本服务,即可在对话里出图。零运行时依赖(纯 Node 手写 MCP stdio 协议)。

特性

  • 零运行时依赖:纯 Node 实现 MCP stdio 协议,不需要 Python 或其他运行时。
  • 自包含、可交互图表:生成内嵌 ECharts 的 HTML 文件,支持类型切换 / 配色 / 宽高调整。
  • 离线可用:npm run fetch-echarts 把 echarts 落到 vendor/,沙箱禁外网也能渲染。
  • 跨端通用:搜索流(chart_from_data)+ 文件流(chart_from_file)。
  • Excel 可选:npm i xlsx 后支持 .xlsx/.xls;不装也能跑 CSV。

工具

| 工具 | 作用 | |------|------| | chart_from_data | 结构化数据 → 写入图表 HTML 文件,返回绝对路径 + 数据概要(完整 ECharts option 默认省略,includeOption: true 恢复) | | chart_from_file | CSV/XLSX 路径 → 解析后写入图表 HTML,返回路径 + 概要(首列类别轴,其余列数值序列) | | list_chart_types | 列出支持的类型 / 配色与字段约定 |

字段约定:第一列 = 类别轴;其余列 = 数值序列(多列即多序列);chartType: auto 按数据自动选 饼/柱。

为什么输出「文件 + 路径」而不是 HTML 文本

MCP 工具结果在多数宿主里走文本通道:宿主(如 DSH 的 mcp-client)会把非文本块折叠成纯文本,直接把 HTML 吐回去只会在工具结果里显示成一长段 / 调试视图,不会被当成网页内联渲染。

因此本 server 统一把图表写成 .html 文件并返回绝对路径,各宿主用自己擅长的方式呈现:

  • DSH / Web:模型在终回复用反引号写出路径 → 自动变可点击链接 → 浏览器打开即交互式图表(无需改宿主本体/UI)。
  • WorkBuddy:助手读文件后用 Visualizer 内联渲染。
  • Codex / Trae:打开该 HTML 文件即可。

想让宿主直接拿到 HTML(而不是走文件链接),把工具参数 returnHtml: true 即可额外返回 HTML 原文——前提是宿主能渲染 HTML(如 Trae 的预览、装了 genui 的 DSH)。

图表文件默认写入 os.tmpdir()/echarts-charts/,可用环境变量 ECHARTS_CHARTS_DIR 覆盖(例如设成你的工作区 charts/ 目录,产物就落在该目录)。产物自动清理:超过 3 天或目录内超过 500 个文件时删除最旧者,无需手动维护。

对话框直接内联出图

不同客户端对「工具结果里的图片」处理方式不一致:有的把 image content block 当多模态输入(纯文本模型会过滤掉),有的不渲染 file:// 图片。为此采用模型回写策略:

  1. 工具结果落盘一份 .svg,并在返回的文本里给出 ![标题](url) 这一行 + 一句「请在最终回复中原样写回该行」的指示。
  2. 模型按指示在最终回复里写出该 markdown 图片 → 走客户端的 markdown 渲染通路(展示给人看),避开 MCP 多模态输入过滤。
  3. 同时仍附带 MCP image content block(base64 SVG),供 Claude Desktop / Cursor 等支持 image block 的客户端直接渲染。
  4. 都不支持时回退到 .html 路径文本(可点击打开交互式图表)。

内联模式速查

通过环境变量 ECHARTS_INLINE_MODE 控制内联行为:

| 模式 | 行为 | 适用客户端 | |---|---|---| | inline(默认) | data URI → localhost http → file:// 自动 fallback | OpenCode / DSH / 通用 | | file | 只输出 file:// 本地路径 | ZCode | | cdn | 上传 GitHub+jsDelivr,输出公网 https(见下方隐私说明) | WorkBuddy | | all | 测试模式:一次返回所有格式,让用户判断哪个能显示 | 首次接入时测试 | | none | 纯文本(.html 路径 + 数据),无内联 | 纯文本模型 / 终端 |

隐私说明(cdn 模式):图表含你的数据,上传到公网 GitHub 仓库后经 jsDelivr 可被任何人访问。因此 CDN 仅在显式设置 ECHARTS_INLINE_MODE=cdn 时启用,不会自动兜底上传;敏感数据请勿使用 cdn 模式。

环境变量

| 变量 | 默认值 | 说明 | |---|---|---| | ECHARTS_INLINE_MODE | inline | 内联模式(inline / file / cdn / all / none) | | ECHARTS_RETURN_IMAGE | true | 是否返回 MCP image content block | | ECHARTS_RETURN_DATA | true | 是否附带清洗后完整数据 | | ECHARTS_RETURN_OPTION | false | 是否附带完整 ECharts option JSON(体积较大,默认省略;工具参数 includeOption 可单次覆盖) | | ECHARTS_DATA_MAX_ROWS | 60 | 返回数据的最大行数 | | ECHARTS_DATA_URI_MAX | 49152 | data URI 最大字节数 | | SEARCH2CHART_PORT | 18765 | 本地 HTTP 服务端口 | | ECHARTS_CHARTS_DIR | os.tmpdir()/echarts-charts | 图表输出目录 | | ECHARTS_CDN_TOKEN | — | GitHub PAT(cdn 模式必填) | | ECHARTS_CDN_REPO | iqingyoung/search2chart-cdn | GitHub 仓库(cdn 模式) | | ECHARTS_CDN_RETENTION_DAYS | 3 | CDN 图片保留天数(自动清理) | | ECHARTS_CDN_BRANCH | main | GitHub 分支 |

首次接入测试

先用 all 模式一次性测试所有格式:

临时配置:

{ "env": { "ECHARTS_INLINE_MODE": "all" } }

发给 Agent:

用 chart_from_data 生成一个简单柱状图。
数据:[["城市","销量"],["北京",120],["上海",200],["广州",150]]
标题:城市销量对比
chartType:bar

Agent 返回 3-4 行图片,分别标记为 【1·data URI】【2·localhost http】【3·file://】【4·CDN 公网 https】。哪个在对话框里真正渲染成了图片,你的客户端就支持哪种。然后把 ECHARTS_INLINE_MODE 固定为对应值。

工具结果里已内置 Agent 自动检测指令,告诉模型如何根据用户反馈自动设置模式:

| 用户反馈 | Agent 动作 | |---|---| | "1正常" | 提示设置 ECHARTS_INLINE_MODE=inline | | "2正常" | 提示设置 ECHARTS_INLINE_MODE=inline | | "3正常" | 提示设置 ECHARTS_INLINE_MODE=file | | "4正常" | 提示设置 ECHARTS_INLINE_MODE=cdn | | "都行" | 提示设置 ECHARTS_INLINE_MODE=inline(data URI 优先) | | "都不行" | 提示设置 ECHARTS_INLINE_MODE=none |

已知实测:ZCode → file,OpenCode → inline(data URI),WorkBuddy → cdn,DSH → inline(localhost http),Claude/Cursor → inline + returnImage:true。

视觉与数据:

  • 统一米白底色 #fafaf7:SVG 与 HTML 都用米白底,避免透明背景在深色/灰白客户端不可见。
  • 清洗数据留存:默认在结果里附带清洗后的完整数据(JSON 数组数组,代码块包裹),让纯文本模型(GLM-5.2 / DeepSeek 等)在上下文里继续做占比/趋势/对比分析,无需看图。returnData: false 或环境变量 ECHARTS_RETURN_DATA=false 可关;超 60 行(ECHARTS_DATA_MAX_ROWS 可调)自动截断。
  • 图表类型双语:summary 同时给出中文名与英文键(如「柱状图(bar)」)。

ZCode 实测:MCP 客户端把工具结果的 image block 当模型输入过滤掉,但模型回复里的 file:// markdown 图片能被渲染器直接显示——因此走「模型回写」通路。

各客户端表现:

| 客户端 | image block 内联 | 模型回写 file:// 图片 | 路径文本兜底 | |---|---|---|---| | ZCode | ❌(过滤) | ✅(实测) | ✅ | | Claude Desktop / Cursor | ✅ | 取决于客户端 | ✅ | | Codex CLI / Claude Code(终端) | ❌(终端不渲染像素) | ❌ | ✅ 落盘 .html | | DSH(MCP 通道) | ❌ | ❌(sanitizeUrl 拦截 file:) | ✅ 路径变可点击链接;或改用 dsh/ 原生插件 |

运行

node server.js            # 由 MCP 客户端以 stdio 拉起,无需手动运行
npm run fetch-echarts     # 可选:下载 echarts 到 vendor/,支持离线/沙箱渲染
npm test                  # 可选:端到端自检(initialize / tools/list / 两路出图)

接入各客户端

所有客户端统一用 stdio 拉起。推荐用 npx(无需 clone):npx search2chart-mcp。或手动指定路径 node <绝对路径>/mcp/server.js(注意 mcp/ 子目录,server.js 在 mcp/ 下,不在仓库根)。

路径坑:本仓库根有 mcp/ 和 dsh/ 两个子目录。MCP server 入口是 mcp/server.js,不是根目录的 server.js。所有接入配置里的 args 都要写完整路径 .../search2chart-mcp/mcp/server.js。

ZCode

ZCode 的 MCP 配置在 .zcode 体系下,分 workspace 和 user 两个 scope。

在 <repo>/.zcode/config.json(workspace scope,仅当前项目生效)或 ~/.zcode/cli/config.json(user scope,全局生效)的 mcp.servers 下新增:

{
  "mcp": {
    "servers": {
      "echarts-chart-mcp": {
        "type": "stdio",
        "command": "node",
        "args": ["/abs/path/to/search2chart-mcp/mcp/server.js"],
        "enabled": true
      }
    }
  }
}

接入踩坑(实测):

  1. 必须完全退出 ZCode 再重开:不是新建会话,是退出整个应用/进程再打开。MCP server 在会话启动时连接,当前会话无法热加载新配置。
  2. command 用 node 依赖 PATH:若启动失败(设置 → MCP 显示 failed / spawn node ENOENT),用 which node 查绝对路径(如 /usr/local/bin/node、~/.nvm/versions/node/v20.x.x/bin/node),填进 command 字段。
  3. schema 严格:配置里多余的未知字段会导致整个 server 被静默丢弃(不报错但不加载)。只保留 type / command / args / enabled / cwd / env / timeoutMs。
  4. 图片不走 MCP image block:ZCode 的 MCP 客户端会把工具结果的 image content block 当作多模态模型输入处理,纯文本模型(如 GLM-5.2)会过滤掉。本 server 采用「模型回写」策略——工具结果里给出 ![标题](file://...svg) 字面量并指示模型在最终回复中原样写回,走 ZCode 的 markdown 渲染通路(展示给人看),绕开 MCP 输入过滤。重启后调用工具,模型回复里会直接显示图表。
  5. 验证连接:重启后进入 设置 → MCP,应看到 echarts-chart-mcp 显示为「已连接」。工具名形如 mcp__echarts-chart-mcp__chart_from_data。

DeepSeek Harness (DSH)

DSH 用 Cordis 加载插件(不是 harness.yaml)。在 profile 的 patch 层新增一个 mcp-client 实例即可(每个实例只连一个 server)。

编辑 ~/.dsh/profiles/<profile>/cordis.patch.yml(如 web profile):

- insert:
    - id: mcp-client-echarts-chart
      name: '@deepseek-ai/dsh-mcp-client'   # 随 dsh 包预装
      config:
        transport: stdio
        serverName: echarts-chart
        command: 'C:/abs/path/to/node.exe'
        args:
          - 'C:/abs/path/to/search2chart-mcp/mcp/server.js'
        cwd: 'C:/abs/path/to/search2chart-mcp'
        failOnStartupError: false   # 务必 false,否则 server 启动失败会让 DSH 整体启动失败
        reconnect: { enabled: true, initialDelayMs: 500, maxDelayMs: 30000, maxAttempts: 10 }
  • 务必用 - insert: 包裹:写成顶层 - id: 会被 DSH 当成「覆盖已有插件」,因 id 在 bundle 层不存在而静默 skip,表现就是重启后找不到、且不报错。
  • id 全局唯一;serverName 须匹配 [A-Za-z0-9_-]{1,32},决定工具前缀 mcp__echarts-chart__*。
  • 路径用 C:/... 正斜杠(Windows 下 Node 接受),避免重启后相对/PATH 丢失。
  • DSH 的 MCP 通道不渲染图片:DSH 的 MCP 客户端会把非文本 content block 折叠成纯文本(extractText 丢弃),且 markdown 渲染器只放行 http(s) 协议(sanitizeUrl 拦截 file:/data:)。因此在 DSH 里只能走 .html 路径文本通路——终回复里用反引号包路径成可点击链接,浏览器打开即交互式图表。若要真正内联出图,改用本仓库 dsh/ 目录下的原生 DSH 插件(走 localhost HTTP 服务 + http URL markdown 图片),见仓库根 README。
  • 重启 DSH 后,会话里即可看到 mcp__echarts-chart__chart_from_data 等工具。

完整示例见 examples/dsh-cordis.patch.yml。

WorkBuddy

写入 ~/.workbuddy/mcp.json 的 mcpServers:

{ "mcpServers": { "echarts-chart-mcp": { "command": "node", "args": ["/abs/path/to/search2chart-mcp/mcp/server.js"] } } }

工具返回 HTML 文件路径后,助手用 HTML 预览 / Visualizer 内联展示。

Trae

在 Trae 的 MCP 设置中加入同上的 stdio 配置(命令 node,参数指向 mcp/server.js 的绝对路径),Web IDE 直接预览返回的 HTML(亦可设 returnHtml: true 直接拿到 HTML)。

Codex / Claude Code

claude mcp add echarts -- node /abs/path/to/search2chart-mcp/mcp/server.js

终端无内联渲染:工具会落盘 .html,用浏览器打开即可。Codex 会把 image block 透传给支持图像的模型(模型不支持则降级为占位文本)。

示例

搜索流(agent 搜完把数据喂入):

{ "data": [["品牌","市占率"],["A",32.5],["B",27.8],["C",18.2]], "chartType": "pie", "title": "品牌市占率" }

文件流:

{ "filePath": "/data/sales.csv", "chartType": "bar", "title": "月度销量" }

目录结构

echarts-chart-mcp/
├── server.js                 # MCP stdio 协议 + 工具入口
├── lib/
│   ├── chart.js              # 数据归一化 + 选图推断 + ECharts option
│   ├── html.js               # 自包含可交互 HTML(类型/配色/宽高控件)
│   ├── svg.js                # 零依赖 SVG 渲染器(bar/line/pie)→ image content block
│   └── parse.js              # CSV 零依赖解析;XLSX 走可选 xlsx
├── scripts/
│   ├── fetch-echarts.js      # 下载 echarts 到 vendor/(离线用)
│   └── selftest.js           # 端到端自检
├── examples/
│   └── dsh-cordis.patch.yml  # DSH 接入示例
├── sample.csv                # 自测用样例
├── package.json
├── README.md
├── LICENSE
└── .gitignore

可选:在 DSH 对话流里真正内联渲染

「写文件 + 可点击链接」是零 UI 改动的通用方案,四端都能用。若要在 DSH 对话流里直接内联(不点链接),可按 DSH「一切皆插件」的官方扩展路径,加一对「原生 dsh 插件 + 配对 UI 插件」:生成逻辑复用 lib/chart.js / lib/html.js,只是出口从 MCP 文本换成 Cordis 结构化事件 + ECharts UI 组件(参照 dsh-client-ui-tool 的 searchBody/card 渲染分支)。此方式不碰 DSH 本体。

License

MIT