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

@deeploop-ai/modao-cli

v0.1.1

Published

墨刀(modao.cc)离线包 CLI 与 MCP 服务器

Readme

Modao CLI

墨刀(MockingBot)离线包 CLI 与 MCP 服务器:在终端读取、浏览、检索墨刀设计资产,也可作为 stdio MCP 服务供 Claude Code、Cursor 等客户端调用——项目 → 画布 → 页面 → 元素树,以及批注与图片资源。

墨刀官方 MCP(modao-proto-mcp)只做 AI 生成 HTML / 导入,不读取已有设计。本项目补的是「加载并理解既有设计文件」这个空位,不与官方冲突。

Modao (MockingBot) offline-package CLI and MCP server: list/search/read projects, pages, element trees, annotations and image assets from exported Modao HTML packages. Complements the official generation-oriented modao-proto-mcp.

重要前置说明

本工具的输入是墨刀的「HTML 离线演示包」,这是付费导出功能(个人版/团队版付费用户可用,免费版不支持)。获取步骤:

  1. 在墨刀网页版(modao.cc)打开目标项目;
  2. 使用「导出 → HTML 离线演示包」;
  3. 解压导出的压缩包,得到一个项目目录(内含 extra/、uploads7/、index.html);
  4. 用 --dir 指向该目录(或其父目录,可放多个项目)。

分享链接(modao.cc/app/<hash>)目前仅支持占位识别与降级指引,不做数据抓取。 原因:墨刀没有公开可用的读取型 API(历史 OAuth2 API 已被官方废弃且本就不含页面数据),分享页的设计数据由前端经未公开 XHR 接口加载,属非公开契约、随时可变更。把分享链接传给 --url(向后兼容也可传给 --dir)时,list / list_projects 中会出现一个 status: unsupported 的占位项目并附降级说明;对其做任何数据访问都会返回上述导出指引。

安装

需要 Node.js ≥ 18。

npm install -g @deeploop-ai/modao-cli

也可不安装、用 npx:

npx @deeploop-ai/modao-cli --dir <离线包目录或其父目录>

命令

全局选项:--dir <path>、--url <url>(均可重复)、--json(结构化输出)。

| 命令 | 说明 | 示例 | | --- | --- | --- | | mcp | 以 stdio 启动 MCP 服务器(可裸启,数据源由工具调用参数指定) | modao mcp / modao mcp --dir D:/design/modao-exports | | list [project] | 无参列出项目;带 project id 列出页面 | modao list --dir ./pkgs / modao list <project> --dir ./pkgs --json | | dsl <project> <page> | 输出页面裁剪 DSL(--format yaml\|json、--depth n) | modao dsl <project> <page> --dir ./pkgs --format yaml | | search <query> | 全文检索(--project、--limit) | modao search 首页 --dir ./pkgs --json | | images <project> <page> | 页面元素级图片清单(含缓存绝对路径) | modao images <project> <page> --dir ./pkgs | | menu <project> | 提取播放器菜单树:画布顺序、分组与叶子画布 id(含 flpk 解析缺失的画布) | modao menu <project> --url http://intranet/pkg/ | | snapshot <project> <page> | 整页长图 PNG(可选 --out、--zoom 1~4);远程目录源同时打印预览 URL | modao snapshot <project> <page> --dir ./pkgs | | snapshot-canvas <project> <canvas> | 画布总览长图 PNG(该画布全部页面缩略图+页名;可选 --out、--zoom 1~4 默认 2、--clip x,y,w,h 裁剪、--split 分片输出) | modao snapshot-canvas <project> <canvas> --url http://intranet/pkg/ --zoom 3 | | pull [url...] | 预拉/刷新远程包缓存 | modao pull --url http://intranet/pkg/ / modao pull http://intranet/pkg.zip --url http://intranet/pkg/ |

默认命令

不带子命令时等同 mcp,兼容旧的直挂用法:

modao --dir D:/design/modao-exports
# 等同于
modao mcp --dir D:/design/modao-exports

--dir 可重复;值为分享链接 URL 时注册为占位项目。也可用 --url 指向远程离线包(内网静态目录或 zip)或分享链接:

modao list --dir D:/design/mdao-exports --url "https://modao.cc/app/<40位hash>"
modao mcp --url "http://192.168.12.67:18080/docs/6.2.6-pkg/"
modao mcp --url "http://192.168.12.67:18080/exports/pkg.zip"

modao mcp(不带 --dir/--url、也无相关环境变量)同样可以启动:此时没有默认数据源,每次工具调用需以 dir / url 入参指定(见「MCP 客户端配置」)。

MCP 客户端配置

推荐裸启:客户端配置只写 modao mcp,数据源由每次工具调用的 dir / url 入参指定(Agent 无需改配置即可切换多个项目/内网包);--dir/--url 与环境变量配置的数据源作为未传参时的默认值。

Claude Desktop(claude_desktop_config.json)/ Cursor / Kimi Code:

{
  "mcpServers": {
    "modao": {
      "command": "modao",
      "args": ["mcp"]
    }
  }
}

未全局安装时可用 npx:

{
  "mcpServers": {
    "modao": {
      "command": "npx",
      "args": ["-y", "@deeploop-ai/modao-cli", "mcp"]
    }
  }
}

Claude Code:

claude mcp add modao -- modao mcp

也可在启动参数里固定默认数据源(向后兼容,工具调用未传参时使用):

{
  "mcpServers": {
    "modao": {
      "command": "modao",
      "args": ["mcp", "--dir", "D:/design/modao-exports"]
    }
  }
}

MCP 工具数据源入参

每个工具都接受可选的 dir / url 入参(单值或数组均可,语义同 CLI 的 --dir/--url):

  • 传了 dir / url:以调用参数为准(不与默认源合并),相同组合的结果在服务内缓存复用;
  • 都不传:使用服务器启动配置(--dir/--url 或 MODO_DATA_DIR/MODO_DATA_URL)的默认数据源;
  • 两者都未配置时调用会返回指引错误,提示传 dir 或 url。

MCP 工具列表

| Tool | 说明 | | --- | --- | | list_projects | 列出所有已识别项目(id、名称、来源、更新时间;分享链接显示为占位) | | list_pages | 列出项目页面(id、名称、所属画布——区分用户画布/动态组件画布、批注数) | | get_page_dsl | 页面裁剪 DSL(元素类型/名称/位置尺寸/文本/层级),yaml/json 双格式,depth 截断 | | get_element_detail | 单个元素完整属性(含 DSL 裁掉的 zIndex、原始字段等) | | get_annotations | 页面批注(富文本说明) | | search_assets | 跨项目全文检索:项目名/页面名/元素名/文本内容,返回定位路径与片段 | | get_page_image | 页面元素级图片清单(复制到缓存目录,返回绝对路径;不做整页合成渲染) | | get_page_snapshot | 整页长图 PNG:传 page_id 截单页(原尺寸);传 canvas_id 截画布总览长图(全部页面缩略图+页名一图纵览);canvas_id + split: true 追加分片输出(总览+按空白沟切的 N 张可读宽度小图,返回 tiles 清单,每片带墙内 clip 坐标,适合逐片读小字)。返回磁盘绝对路径(及远程目录源的预览 URL),Agent 自行读取该图;需要 Playwright | | refresh_projects | 刷新数据源:远程离线包重新拉取,本地目录重新扫描(范围同上:调用参数优先,未传则默认源) |

以上所有工具均接受可选 dir / url 入参指定数据源(见「MCP 工具数据源入参」)。

典型用法流程:先检索定位,再精读——用 search_assets / list_pages 找到目标页面,再用 get_page_dsl 拉裁剪后的 DSL;超大页面先用 depth 看骨架,按截断提示用 get_element_detail 精读子树。看稿用 get_page_snapshot(读取返回的 path 直接看整页长图),读结构与文案用 get_page_dsl。

环境变量

| 环境变量 | 说明 | | --- | --- | | MODO_DATA_DIR | 数据源(等价 --dir,逗号分隔多个值;CLI 有值时不生效)。MCP 模式下作为工具未传 dir/url 入参时的默认数据源 | | MODO_DATA_URL | 远程数据源(等价 --url,逗号分隔多个值;CLI 有值时不生效)。MCP 模式下作为工具未传 dir/url 入参时的默认数据源 | | MODO_CACHE_DIR | 缓存目录(图片、远程数据),默认 Windows 为 %LOCALAPPDATA%\modao-mcp,macOS/Linux 为 ~/.cache/modao-mcp |

数据源形态

支持三种输入(CLI 用 --dir/--url,MCP 工具调用用 dir/url 入参,形态一致):

  • 本地目录(一等):dir 指向已解压的离线包根目录,或其父目录(扫描含 extra/data.0.js 的子目录)。
  • 远程离线包:url 指向内网静态服务器上的解压目录,或 zip 下载地址;会下载到本地缓存后再解析。
  • 分享链接:url(或向后兼容写在 dir/--dir)识别为占位项目,不抓取数据,仅返回导出离线包的降级指引。

远程数据缓存于 MODO_CACHE_DIR(或系统默认缓存目录)下的 remote/。MCP 启动时会自动检查默认远程源的更新,工具调用首次使用某个 url 数据源时同样做一次检查(目录形态对比 updated_at,zip 对比 ETag/Last-Modified);运行期间可调用 refresh_projects 工具重新拉取,或在 CLI 使用 modao pull 检查并在有更新时拉取。

图片缓存

images 命令与 MCP 工具 get_page_image 不做整页合成渲染,只收集页面元素级图片:从包内 uploads7/images/ 按需复制到缓存目录,返回绝对路径。远程目录形态若本地未带图片,会按 uploads7/images/<file> 回源拉取并落盘;失败则跳过该图片。缓存根目录由 MODO_CACHE_DIR 控制。

整页截图(snapshot)

snapshot 命令与 MCP 工具 get_page_snapshot 用 Playwright 打开官方离线 HTML 播放器,按页面画板实际宽度截取整页长图 PNG:

  • 默认落盘 <缓存目录>/snapshots/<project>/<画布序>-<页序>-<页面名>.png(画布总览为 overview-<画布序>-<画布名>.png),序号 1 起零填充两位,目录按名排序即设计稿顺序;页面不在模型中(远程源宽容放行)时回退用页面 id。CLI 可用 --out 覆盖;返回值含 path、width、height。
  • 数据源为远程目录形态(--url http://...)时一并返回 previewUrl(包根地址,可直接打开播放器);zip 与本地 --dir 源只返回 path(本地源截图期间会临时起一个仅绑定 127.0.0.1 的静态服务,进程退出即关闭)。
  • Playwright 为可选依赖:未安装时报错并提示安装,不做静默降级;托管 chromium 未下载时会自动回退本机 Chrome/Edge(channel 方式),无需 150MB 浏览器下载:
npm install playwright          # 未安装时
npx playwright install chromium # 可选:下载托管浏览器(无系统 Chrome/Edge 时)
  • 跳页采用官方播放器深链 ?view_mode=device&canvasId=<页面id> 直达目标页,并按画板自然尺寸(非模拟器缩放尺寸)输出 PNG。
  • 画布总览:snapshot-canvas 命令(或 get_page_snapshot 传 canvas_id,来自 list_pages 的 canvasId,或 menu 命令输出的叶子画布 id)切换到播放器总览模式,一面长图截下该画布全部页面缩略图与页名——适合一图纵览多页结构。默认 2 倍像素输出,--zoom 1~4 调节;--clip x,y,w,h(相对墙左上 CSS 像素)可只截批注/文档区域。页面级 snapshot --zoom 同理。
  • 分片输出(读小字推荐):整墙长图送入读图模型会被降采样,批注小字必然不可读。--split 在同一次渲染内追加输出:总览 1 张(看结构)+ 按内容空白沟切的 N 张可读宽度分片(逐片读文字,无需手工估算 clip 坐标),并写 tiles.json 清单——每片带墙内 CSS 像素 clip 坐标与切法(gutter=刀口在空白沟,uniform=等宽退化切),可溯源、可定点复查。--split auto 按空白沟自适应片数(默认片宽 520 CSS px,--band 调节);--split <n> 强制片数;墙内容过密无沟可切时退化为等宽切并留 --overlap(默认 60 CSS px);沟内有内容贯穿(表格行线、白卡连续区——切开会把一张表/一张卡劈到两片)时不下刀,整块内容并入同一条分片(最宽 band+200 CSS px,超宽才等宽切);墙缘滚动条等过窄伪内容不参与切线。--out 此时为输出目录(默认 snapshots/<project>/split-<画布序>-<画布名>/);--skip-existing 在清单与文件齐全时直接复用不重截。与 --clip 互斥。
  • 画布 id 校验规则:id 在解析结果中时直接使用;不在时,远程目录源会放行并由播放器侧选中态校验(覆盖菜单中存在但解析缺失的画布),本地源则严格报错并列出可用画布。

典型工作流:从设计稿到需求文档(Agent 自主完成)

modao list --url http://intranet/pkg/                    # 1. 找到项目 id
modao menu <project> --url http://intranet/pkg/          # 2. 菜单顺序 + 全部画布 id(含解析缺失的)
modao snapshot-canvas <project> <canvasId> \
  --url http://intranet/pkg/ --zoom 3 \
  --split auto --out shots/<canvasId>/                   # 3. 总览 + 按空白沟分片 + tiles.json
# Agent 识读:先读总览看结构,再按 tiles.json 顺序逐片读文字;
# 个别没读清的行用 tiles.json 的 clip 坐标 --clip 定点复查

全程只需要 CLI 返回的信息:菜单给出顺序与 id,snapshot 返回 PNG 绝对路径与尺寸(分片模式附每片墙内坐标),无需了解墨刀文件结构,也无需人工估算裁剪坐标。

数据格式说明

离线包内 extra/data.0.js 为项目元信息,extra/data.1.js 为设计数据,核心是 window.hzv5.flpk 操作码序列:

  • v1(旧版):明文操作码数组;
  • v2(新版):gzip+base64 压缩块 + 明文增量更新。

解析器做操作码回放(I 定义元素 / A 更新属性 / B@ref-danli 动态组件画布 / @@T 外部引用跳过),用 rRBPK 索引区分用户画布与动态组件画布。flpk 是墨刀内部格式、非公开契约,解析器采用防御式解析:无法识别的操作码跳过并计数,不会崩溃。

本项目的 flpk 解析逻辑移植自 modao-exporter(MIT 许可证)的 src/parser/,特此致谢。本项目同样以 MIT 许可证发布。

开发

npm install
npm run build   # tsc → dist/
npm test        # vitest
npm run dev     # tsx 直接跑 src/index.ts(需 -- --dir <path> 或子命令)

项目结构:

modao-cli/
├── src/
│   ├── index.ts              # 入口:分发到 cli
│   ├── cli.ts                # cac 命令定义与分发
│   ├── config.ts             # configFromOptions(CLI 选项 + 环境变量)
│   ├── bootstrap.ts          # createSource / checkRemoteUpdates
│   ├── cli-output.ts         # 人类可读格式化
│   ├── mcp-command.ts        # mcp 子命令:stdio 启动│   ├── commands/             # list / dsl / search / images / pull
│   ├── model/                # Project/Canvas/Page/Element/Annotation/Asset 统一模型
│   ├── flpk/
│   │   ├── decode.ts         # flpk v1/v2 解包(gzip+base64 → 操作码行)
│   │   └── replay.ts         # 操作码回放 → 统一文档模型
│   ├── sources/
│   │   ├── source.ts         # Source 接口
│   │   ├── offline-package.ts# 本地离线包目录(惰性解析)
│   │   ├── remote-package.ts # 远程离线包目录 / zip 拉取与缓存
│   │   ├── share-link.ts     # 分享链接占位(降级指引,不抓取)
│   │   └── combined.ts       # 多数据源组合
│   ├── services/
│   │   ├── dsl.ts            # 文档模型 → 裁剪 DSL(json/yaml、depth 截断)
│   │   ├── index.ts          # 内存检索索引与打分
│   │   ├── assets.ts         # uploads7/images 资源读取与缓存目录落盘
│   │   └── pages.ts          # 页面查找辅助
│   └── mcp/
│       ├── server.ts         # McpServer 装配
│       ├── source-manager.ts # 工具调用 dir/url 入参 → 数据源解析与缓存
│       └── tools.ts          # tool 注册
└── test/                     # vitest + 手工构造的微型离线包 fixtures

License

MIT © deeploop-ai