Skip to content

cq-viewer 1.1.0: MCP tools to add model folders and files, bundled CadQuery skill - #19

Merged
HanZijie merged 1 commit into
mainfrom
feat/cq-viewer-templates-mcp
Oct 15, 2026
Merged

HanZijie merged 1 commit into
mainfrom
feat/cq-viewer-templates-mcp

Conversation

@HanZijie

@HanZijie HanZijie commented Oct 15, 2026 •

Copy link
Copy Markdown
Collaborator

What

Update of plugins/hanzijie/cq-viewer (CadQuery Viewer) to 1.1.0.

MCP tools for the AI

The Mini App now serves an MCP server cq-viewer itself (servers.mcp.json + mcpEndpoints, Streamable HTTP on POST /mcp/cq-viewer):

Tool Behaviour
add_model_folder {path, select?} Registers a folder with the same rules as the page's + (inside $HOME, not $HOME/~/Library/hidden top-level). Returns folder ID + up to 200 model paths; select (default true) switches the viewer to it.
add_model_file {path} Opens an .stl/.step/.stp in place via the closest registered folder that lists it (or registers the file's own folder). The viewer ticks it, fits, and live-reloads on re-export.
add_model_file {path, copy_to_scene: true, name?, color?, opacity?} Copies the file into ~/.cqview/scene/ (like cqview.show_file) for files outside $HOME, e.g. /tmp.
list_model_folders {folder?} Read-only: registered folders + pushed scene, or one folder's models.

Requests are persisted in dataDir/open-requests.json (24 h, last 20) and applied once per browser, so a model the AI opens while the viewer is closed shows up on the next visit. Results carry viewer_connected; the page closes its SSE connection on pagehide so that flag is accurate.

Bundled skill

skills/parametric-3d-printing/ = the skill from flowful-ai/cad-skill @ fe42159. Runtime files are byte-identical; README.md, docs/, tests/ are left out; one clearly marked section is appended to SKILL.md telling the agent to open exported models with add_model_file. See skills/parametric-3d-printing/UPSTREAM.md.

License note: that directory is PolyForm Noncommercial 1.0.0, not MIT. Its LICENSE and Required Notice (Copyright Nicolas Chourrout) are kept, and the plugin LICENSE/READMEs state the exception. Per CONTRIBUTING ("preserve required attribution for third-party code").

Other

  • author: HanZijie, flowful-ai; root README rows list both.
  • Writes to roots.json / scene files are serialized; writeJsonAtomic creates the target's own directory.

Checks

  • npm run check: plugins/hanzijie/cq-viewer: OK — 0 errors, 0 warnings; 55/55 repo tests. (The 4 warnings shown belong to two other packages.)
  • node --test plugins/hanzijie/cq-viewer/tests/*.test.mjs: 10/10 (real Node entry, temporary $HOME): the three tools, folder rules, copy with colour, request log across a restart, 403 on non-loopback Host/Origin, 405 on GET, 415 on non-JSON.

Data & access (delta — full detail in the README)

  • New read: with copy_to_scene, the one model file the AI names (regular .stl/.step/.stp ≤ 512 MB, any location).
  • New writes: ~/.cqview/scene/<name>.<ext> + scene.json (only for copy_to_scene); dataDir/open-requests.json (folder ID / relative path / scene name — no absolute paths).
  • New endpoint: POST /mcp/cq-viewer, loopback Host/Origin only, JSON only. No network, no new processes. The bundled skill's scripts are run by the agent, never by the Mini App.

Tested environment

  • MiniMax Code 3.1.1-preview.4597 (Electron 42), macOS 26 (Apple Silicon); Python 3.9, CadQuery 2.5.2 / OCP 7.7.2, trimesh 4.12, pyrender 0.1.45.
  • In MiniMax Code: local install of this exact tree; a new conversation lists mcp__cq-viewer__add_model_folder / add_model_file / list_model_folders and the skill cq-viewer:parametric-3d-printing; list_model_folders and add_model_folder (select:false) called through the Host return ok: true.
  • Headless Chrome E2E against the same Node entry (13/13): page switches folder on add_model_folder; add_model_file ticks + renders the file and toasts; copy_to_scene shows the part in the requested colour; a file requested while the page is closed opens on the next visit, is not replayed afterwards, and stays closed after the user unticks it; viewer_connected goes false when the page leaves. No console errors.
  • Bundled skill: run_cadquery_model.py --preview --strict from the installed plugin directory → STL, watertight, preview PNG.

Not verified

  • Windows.
  • add_model_file through the Host with the viewer panel open (page side verified in headless Chrome only).
  • Unchanged from 1.0.0: whether the Send fallback (mcode.miniapp.message.append) actually fills the conversation input in this build; STEP face colours from other CAD tools.
  • The skill's Gridfinity generator on CadQuery 2.5 (skill asks for ≥ 2.6.1).

View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.

…dQuery skill

- MCP server "cq-viewer" served by the Mini App itself (POST /mcp/cq-viewer,
  loopback Host/Origin only, JSON only):
  - add_model_folder: register a folder (same rules as the page), list its models,
    optionally switch the viewer to it.
  - add_model_file: open an .stl/.step/.stp in place through the closest registered
    folder (or register its own folder); copy_to_scene copies it into
    ~/.cqview/scene for files outside the home directory.
  - list_model_folders: registered folders, pushed scene, or one folder's models.
- Requests persist in dataDir/open-requests.json (24 h, last 20); the page applies
  each once, so models the AI opens while the viewer is closed show up on the next
  visit. The page closes its live connection on pagehide so viewer_connected is accurate.
- Bundle skills/parametric-3d-printing from flowful-ai/cad-skill (fe42159),
  PolyForm Noncommercial 1.0.0 with its Required Notice; one section appended to
  SKILL.md pointing the agent at add_model_file. Author: HanZijie, flowful-ai.
- tests/mcp.test.mjs: 10 tests against the real Node entry with a temporary home.

npm run check: plugins/hanzijie/cq-viewer OK (0 errors, 0 warnings).
@HanZijie
HanZijie merged commit 4578aa6 into main Oct 15, 2026
1 check passed

@MyPrototypeWhat MyPrototypeWhat left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

感谢更新,MCP 工具这部分做得很扎实!看到 PR 已经合并了,我补充一些合并后的复查结果,想请你再开一个后续 PR,修一下下面两处需要修改的问题。

另外想顺便提一下:这个仓库一般使用 squash merge,并且希望 PR 在合并前至少经过一次 review,后续的 PR 麻烦等 review 后再合并,谢谢理解~

我在本地实测了新的 MCP 端点:非回环的 Host / Origin 会被拒绝(403),参数校验严格,add_model_folder 和原地打开的 add_model_file 沿用了原来的路径规则(home 外、隐藏目录、指向外部的软链都会被拒绝);tests/mcp.test.mjs 和 npm run check 都通过。内置 skill 与上游 fe42159 对比,除了 SKILL.md 末尾追加的一节,其余文件都一致。

需要修改(#18 中的两处,请在后续 PR 中修复)

  1. 并发写入:addRoot、pushRequest、copyToScene 已经进入 serial() 队列,8 个并发登记现在都成功了 👍。但 writeSelection 还没有进队列,writeJsonAtomic 的 tmp 名也还是 pid + 毫秒(见行内评论),实测 40 个并发保存标注仍有 21 个返回 500。
  2. dispose 之后仍会启动 Python:这部分还没有改动。我在 f0c477d 上重测,转换过程中 abort 后,同一秒又启动了 fallback 的 python -c 转换,并写入了缓存。建议 dispose 后 runChild 直接拒绝,被信号结束(包括超时)时不再进入 fallback。

提醒(非必改)

  • 内置 skill skills/parametric-3d-printing/ 使用的是 PolyForm Noncommercial 1.0.0(仅限非商业用途)。你已经在 LICENSE、README 和 UPSTREAM.md 里标注得很清楚了,谢谢。这里只是提出来,请维护者留意一下这个仓库收录非商业许可内容是否合适。

建议(可选)

  1. /viewer/api/* 页面路由仍然没有 Host 校验,可以直接复用 MCP 端点里的 isLoopbackRequest。
  2. host-bridge.js 里的 APP_INFO.version 还是 1.3.0,建议与 plugin.json 的 1.1.0 统一。

后续 PR 提上来后我会尽快复查,谢谢!

async function writeJsonAtomic(file, data) {
await mkdir(EXCHANGE_DIR, { recursive: true });
await mkdir(dirname(file), { recursive: true });
const tmp = `${file}.${process.pid}.${Date.now()}.tmp`;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里的 tmp 名还是 pid + 毫秒,而 writeSelection 没有进 serial(),同一毫秒内的两次保存仍会撞名:实测 40 个并发 POST /api/selection 有 21 个 500(ENOENT)。建议 tmp 名加随机后缀(例如 randomBytes(6).toString('hex'),上面已经 import 了),并让 writeSelection 也走 serial()。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants