CNCDraw MCP Server
Enables AI agents to control pen plotters via MCP tools for text layout, SVG/DXF import, G-code generation, device control, and vision calibration.
README
CNCDraw — 写字机 Python 工具集
基于奎享写字机(KenjoyDraw)软件逆向工程的 Python3 实现:把文字、图片、SVG/DXF 转成笔式绘图机(pen plotter)的 G-code,并驱动机器绘制。含 Web UI、MCP agent 接口 与摄像头闭环校准。
本次重构:修复了核心管线/设备层/图像处理的一批 bug,Flask → FastAPI,新增视觉与 MCP 支持,全部功能在无硬件时可用内置 mock 控制器运行与测试。
.tfont 轨迹字体格式
.tfont 是本项目自研的轨迹(笔画)字体格式。与 .gfont(TEA 加密元数据 +
一个 ZIP 打包的逐字形 blob)不同,.tfont 是单个明文二进制,带一个按码点排序
的索引,可随机访问、按需只加载单个字形(不必解压/扫描整包)。每个字形就是若干
条笔画折线(正是笔式绘图机要画的东西)——没有轮廓要填充、没有加密要解。
设计目标:省空间、加载快、坐标精确、支持 >U+FFFF 码点(gfont 的 2 字节码点做不到)。 实测把 74 个 gfont 转成 tfont:208 MB → 106 MB(约一半),字形坐标往返无损。
字节布局(整数均为大端):
magic 6 bytes b"TFONT\x01" (5 字符 + 版本字节)
units_per_em uint16 坐标空间(如 1000)
flags uint8 bit0: y_down (1=y 向下, 绘图机坐标)
name_len uint16
name name_len 字节 (utf-8 字体名)
glyph_count uint32
index glyph_count × (uint32 码点, uint32 偏移, uint32 长度) # 按码点排序, 偏移为文件绝对偏移
glyph 数据块(位于各自偏移处):
advance int16 # 字宽(font units)
stroke_count uint16
每条笔画: point_count uint16, 然后 point_count × (int16 x, int16 y)
坐标为整数 font units,紧凑且精确;索引让读取器可直接 seek 到目标字形。
字体转换
from cncdraw.tfont import gfont_to_tfont, tfont_to_gfont, ttf_to_tfont
# gfont <-> tfont(坐标往返无损)
gfont_to_tfont("in.gfont", "out.tfont")
tfont_to_gfont("out.tfont", "back.gfont")
# TTF/OTF -> tfont,两种轨迹策略(都是真轨迹,不是栅格填充):
# outline : 轮廓自适应贝塞尔展平——直线段2点、曲线按需加点,精确且省点
# centerline : 骨架中轴单线(写字感),非描双边("画画")
ttf_to_tfont("font.ttf", "ascii.tfont", chars="ABCabc012", mode="outline")
ttf_to_tfont("font.ttf", "mono.tfont", chars="好书写字", mode="centerline")
# 批量把一个目录里的 gfont 全部转成 tfont
from cncdraw.tfont.convert import convert_gfont_dir
convert_gfont_dir("cncdraw/fonts", "cncdraw/fonts_tfont")
.tfont 是排版引擎的一等字体源——直接把 .tfont 路径填进 PageInfo.font_paths
即可(TextLayout 会按扩展名自动选择读取器)。
字体说明
cncdraw/fonts/ 下为 .gfont 字体,cncdraw/fonts_tfont/ 为对应的
.tfont 转换结果。也可用上面的 ttf_to_tfont 从任意 TTF 生成轨迹字体。
安装
python3 -m venv .venv
. .venv/bin/activate
pip install -e . # 核心 + Web UI + 视觉
pip install -e ".[mcp]" # 需要 MCP agent 接口时
依赖:numpy, Pillow, matplotlib, pyserial, fonttools, ezdxf,
opencv-python-headless, fastapi, uvicorn(mcp 为可选)。
快速开始
Web UI(FastAPI)
python run_server.py # 监听 0.0.0.0:5000
# 或 KENJOY_PORT=8080 python run_server.py
浏览器打开 http://<本机IP>:5000/,可从局域网其它设备访问。
自带 OpenAPI 文档:/docs。
MCP agent 接口
把写字机能力封装成一组 MCP 工具(provider 无关,任何支持 MCP 的模型都能驱动):
python -m cncdraw.mcp_server # stdio transport
工具:list_fonts / layout_text / layout_note / import_svg|dxf|image / generate_gcode / save_preview / device_connect|status|command|draw|disconnect / vision_calibrate|verify。工具在服务端维护"当前文档",agent 用极小的调用即可完成
「排版→生成 G-code→驱动机器绘制→拍照核对」。
命令行 / 库
from cncdraw.service import KenjoyService
svc = KenjoyService()
r = svc.layout_text("你好世界", handwriting=True, align="center")
gcode = svc.generate_gcode(r["paths"], firmware="grbl")
svc.connect("mock:grbl") # 无硬件时用 mock 控制器
svc.send_gcode(gcode) # 带 ok 握手的流控发送
无硬件运行(mock 控制器)
所有设备操作都支持 mock 端口(如 mock:grbl / mock:ebb / mock:marlin),
模拟控制器的 ok 握手、状态回报与掉线,用于开发、测试与 Web/MCP 演示。
功能
- 字体:解析
.gfont(TEA 元数据 + ZIP 字形),TTF→GFont,字体预览/合并/子集化。 - 排版:自动换行、对齐、中文标点 kerning、手写扰动、笔记/多页/网格/表格模式。
- 图像→线稿:边缘检测、单线字(骨架化)、实心填充(扫描线)、抖动点阵、波浪图 (numpy 向量化,OpenCV 轮廓/骨架追踪)。
- 导入:SVG(path/几何图形/viewBox 缩放/贝塞尔展平) 与 DXF(基于 ezdxf)。
- G-code:Grbl / EBB / Marlin,最近邻路径优化,页面中心旋转。
- 设备:串口线程化读写,
ok流控发送 + 进度/取消,掉线通知,四种固件。 - 视觉闭环:USB 摄像头(或图片文件)采集,纸张矩形/ArUco 标记检测 → 相机像素↔机器 毫米的单应矩阵;绘制后拍照与规划路径对比核对(IoU/覆盖率 + 叠加图)。
- Web UI:FastAPI + 原生前端,实时预览、设备面板、WebSocket 绘制进度。
架构
cncdraw/
├── service.py # 高层门面:Web 与 MCP 共用的唯一业务逻辑
├── mcp_server.py # MCP 工具层(agent 接口)
├── gfont/ # .gfont 读写 / TEA / 生命周期
├── layout/ # 文字/高级排版、SVG/DXF 导入、路径数据
├── gcode/generator.py # G-code 生成 + 路径优化
├── image/ # 图像处理(边缘/骨架/填充/抖动/波浪)
├── device/ # 串口(+mock) 与四种固件控制器
├── vision/ # 摄像头采集 + 标定/核对
├── preview/renderer.py # matplotlib 预览
└── web/ # FastAPI 后端 + static/ 前端
测试
.venv/bin/python -m pytest tests/ -q # 全套
.venv/bin/python -m pytest tests/test_pipeline.py -q # 重构后的端到端用例
.venv/bin/python scripts/smoke_pipeline.py # 冒烟:字体→排版→gcode→预览
逆向分析摘要
.gfont 文件格式:
int version (5)
int body_length
byte[body_length] TEA 加密元数据 (key=[1,9,8,9,0,8,2,6,1,9,9,2,0,8,2,8])
ZIP archive 全部字形(entry 名为十进制 Unicode 码点)
字形:char(2B) + int(坐标数) + float[坐标数] BE + byte[点数] + int(优先级)
| 固件 | 抬笔 | 落笔 | 移动 |
|---|---|---|---|
| Grbl | M5 | M3S<power> | G0/G1 X.. Y.. F.. |
| EBB | SP,1,<delay> | SP,0,<delay> | XM,<ms>,<stepsX>,<stepsY> |
| Marlin | M280 P0 S<up> | M280 P0 S<down> | G0/G1 X.. Y.. F.. |
tools/ 为逆向工程用的原始 Windows 软件产物(CFR 反编译器、TEA 密钥来源等),非运行时依赖。
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。