passpaper v1.0.0 发布:平板手写经 MCP 实时接入 Claude Code 与 Codex
Bin-H-17/passpaper
passpaper 发布 v1.0.0 早期版本,让 AI 通过 MCP 工具实时读取平板上手写的中文与公式,支持 Claude Code 和 Codex CLI。
中文
在平板上手写公式/草图,AI 通过 MCP 工具实时读取。 支持 Claude Code 和 Codex CLI。
状态:v1.0.0 早期版本。核心功能已实现并通过代码级校验(
py_compile/ import / 识别解析),尚未在大规模真机环境验证。欢迎在 GitHub Issues 反馈问题与使用场景。
[平板 Chrome] [电脑]
手写 canvas ──WebSocket──▶ passpaper daemon (常驻)
│ 笔画落笔即渲染到内存画布
Claude Code / Codex ◀─MCP stdio─ mcp_shim
└──── localhost HTTP ────┘
功能
- 中文潦草 / 公式手写识别(本地、隐私) — 配置本地 VLM(
PASSPAPER_RECOGNIZER_ENDPOINT,如 ollama / llama.cpp / vLLM 的 OpenAI 兼容端点)后,图片在交给 Agent 前会先转成结构化文本 / LaTeX。未配置时回退到「Agent 直接看图」。详见 docs/RECOGNITION.md。 - 低延迟跨设备接力 — 平板落笔即增量渲染到内存画布,取图 = 读缓存(实测约 25ms)。WebSocket 断线时笔画本地缓存,重连后自动批量补发。
- 手写会话可随项目回溯 — 每一笔落盘为 JSONL(
~/.passpaper/sessions/)。可导出 Markdown / Excalidraw,在 Excalidraw / tldraw 中回放编辑。 - 通用 MCP + 本地优先 — MCP shim 同时支持 Claude Code 和 Codex;数据只走本机和局域网,无账号、无云、无出站调用。设计受多个开源项目启发,逐条署名见 REFERENCES.md。
设计架构:daemon + shim 双层
| 问题 | 解法 |
|---|---|
| AI 客户端里 MCP 加载慢/超时 | shim 纯标准库,握手 <100ms;重活全在 daemon |
| 连接不稳定 | daemon 常驻,独立于客户端生命周期;日志写文件不写管道;平板断线笔画本地缓存、重连自动补发 |
| 传输慢 | 笔画到达即增量渲染,取图 = 读缓存(实测约 25ms);图片自动裁切、限制 1568px、调色板 PNG |
| 每次用每次扫码 | 持久配对码:平板上存书签,点开就写,passpaper rotate-token 可轮换 |
| 客户端重启后僵尸进程占端口 | shim 在 stdin 关闭时立即退出;daemon 用 PID 文件管理,优雅关机先存盘 |
| 想用 Codex | 同一 shim,passpaper setup 同时注册 Claude Code + Codex;save_snapshot 提供文件兜底 |
快速开始(Windows)
- 双击
start.bat(自动检测 Python、装依赖、注册、启动 daemon) - 打开 Claude Code 或 Codex,说 "我要用递纸"
- 在平板上打开它给你的链接(Chrome),存成书签
- 写字,然后对 AI 说 "看看我写的"
以后每次用:打开书签直接写。daemon 没跑的话 shim 会自动拉起。
手动命令
python src/passpaper/cli.py setup # 一次性:依赖 + 运行时包 + 注册 CC/Codex python src/passpaper/cli.py start # 启动 daemon(后台常驻) python src/passpaper/cli.py status # 健康状态 / 笔画数 / 平板数 / 链接 python src/passpaper/cli.py stop # 优雅停止(先存盘) python src/passpaper/cli.py doctor # 环境诊断 python src/passpaper/cli.py rotate-token # 配对码泄露时轮换
可选开机自启:python src/passpaper/cli.py setup --autostart
MCP 工具
| 工具 | 用途 |
|---|---|
get_connection_info |
平板链接 + 二维码(AI 首次必调) |
get_handwriting |
当前手写内容(PNG,自动裁切/缩放) |
get_handwriting_status |
笔画数/修订号/有无新内容(轻量) |
clear_canvas |
清空画布 |
save_snapshot |
存 PNG 到磁盘返回路径(无法接收 MCP 图片的客户端走这里) |
list_sessions |
列出已录制手写会话(笔画数/时间) |
start_session |
开新会话,旧会话保留可回溯 |
export_session |
导出会话为 md / jsonl / json / excalidraw,可随项目 Git 提交 |
recognize_handwriting |
调用本地 VLM 识别中文/公式(未配置则回退到 Agent 视觉) |
深入阅读
- docs/ARCHITECTURE.md — daemon + shim 双层架构、数据流、延迟与鉴权细节
- docs/RECOGNITION.md — 本地中文/公式识别端点配置 + 推荐模型组合
- docs/ACCEPTANCE_TEST_PLAN.md — 真机验收清单
- PRIVACY.md — 隐私政策:本地优先,无云、无遥测、无出站调用
- SECURITY.md — 安全模型:配对令牌、识别端点风险说明、漏洞报告
依赖
Python ≥ 3.10,websockets Pillow qrcode(shim 本身零依赖,纯标准库)。
测试
python scripts/e2e_test.py # 26 项检查:shim 冷握手速度、daemon 自动拉起、平板 WS、取图延迟、 # 6 万点渲染性能、离线批量补发、优雅关机等
设计要点
- 坐标系:平板端把可视区域等比映射到 2048×1536 规范坐标(letterbox),所见即所得,与设备方向/缩放无关
- 橡皮擦:白墨覆盖渲染(视觉等同真擦除),擦除笔迹不参与自动裁切
- 安全:128-bit 持久配对码,WS/HTTP 全部校验;仅局域网监听
- 运行时包:
setup把 daemon/shim 复制到~/.passpaper/(纯 ASCII 路径),客户端配置指向那里——项目在中文路径下也不会踩 spawn 编码坑 - 环境变量:
PASSPAPER_HOME可改数据目录(测试/便携安装用)
路线图
已发布(v1.0.0)
- 常驻 daemon + MCP shim
- 持久配对 / 离线补发 / 增量渲染(~25ms 取图、MCP 握手 <100ms)
- 手写会话录制 + 多格式导出(md / jsonl / json / excalidraw)
- 可插拔中文 / 公式识别管线(本地 VLM,无模型时回退)
进行中 / 下一步
- 真机验收(平板 + Claude Code / Codex 实跑)
- PyPI 发布 + MCP 市场提交(
pip install passpaper-mcp) - Cloudflare Tunnel 模式(户外 / 跨网络)
- 笔画级语义擦除
- 系统托盘 App 形态
- 更多本地识别后端(PaddleOCR-VL / GLM-OCR 开箱集成)
故障排除
passpaper doctor— 诊断 Python / 依赖 / 运行时包 / MCP 注册 / 配对令牌。- daemon 没起来?看
~/.passpaper/daemon.log与~/.passpaper/daemon.spawn.log。 - 端口 8765 被占?
passpaper stop后再passpaper start;或改PORT(需同步改 canvas)。 - 平板连不上:确认与电脑同一 WiFi;用
passpaper url重新获取链接;公司/校园网可能隔离设备——换手机热点测试。 - 识别没反应:未配置
PASSPAPER_RECOGNIZER_ENDPOINT时走「Agent 直接看图」回退,属正常;配置方法见 docs/RECOGNITION.md。
贡献
欢迎 Issue / PR。开发环境、测试与规则见 CONTRIBUTING.md。安全漏洞请私下报告,见 SECURITY.md。
参考与灵感来源
递纸的设计受到多个开源项目的启发,逐条署名见 REFERENCES.md。
License
MIT — Copyright (c) 2026 B.Han.
English
Write formulas/sketches on your tablet — the AI reads them in real time through MCP tools. Supports Claude Code and Codex CLI.
Status: v1.0.0 early release. Core features are implemented and verified at the code level (
py_compile/ import / recognition parsing), but not yet validated in large-scale real-device environments. Please report issues and use cases via GitHub Issues.
[Tablet Chrome] [Computer]
handwriting canvas ──WebSocket──▶ passpaper daemon (resident)
│ strokes rendered to in-memory canvas on arrival
Claude Code / Codex ◀─MCP stdio─ mcp_shim
└──── localhost HTTP ────┘
Features
- Messy-Chinese / formula handwriting recognition (local & private) — After you configure a local VLM (
PASSPAPER_RECOGNIZER_ENDPOINT, e.g. an OpenAI-compatible endpoint from ollama / llama.cpp / vLLM), the image is converted into structured text / LaTeX before being handed to the agent. Without a configured endpoint it falls back to letting the agent look at the image directly. See docs/RECOGNITION.md. - Low-latency cross-device relay — Strokes are incrementally rendered to an in-memory canvas as they land on the tablet; capturing an image reads a cache (~25ms measured). On WebSocket disconnect, strokes are cached locally and bulk re-sent on reconnect.
- Handwriting sessions traceable per project — Every stroke is persisted to JSONL (
~/.passpaper/sessions/). Sessions can be exported as Markdown / Excalidraw and replayed or edited in Excalidraw / tldraw. - Generic MCP + local-first — The MCP shim supports both Claude Code and Codex; data travels only over your own machine and LAN — no account, no cloud, no outbound calls. The design draws inspiration from several open-source projects, credited one by one in REFERENCES.md.
Architecture: daemon + shim
| Problem | Solution |
|---|---|
| MCP loads slowly / times out inside AI clients | shim is pure stdlib, handshake <100ms; all heavy work lives in the daemon |
| Unstable connections | daemon is resident and independent of the client lifecycle; logs go to files, not pipes; tablet strokes cached locally on disconnect, bulk re-sent on reconnect |
| Slow transfer | strokes are incrementally rendered on arrival; capture reads a cache (~25ms measured); images auto-cropped, capped at 1568px, palette PNG |
| Re-scanning a QR code every time | persistent pairing code: save a bookmark on the tablet, tap to write, valid until rotated (passpaper rotate-token) |
| Zombie processes holding the port after client restart | shim exits immediately when stdin closes; daemon is managed via a PID file; graceful shutdown persists data first |
| Want to use Codex | same shim — passpaper setup registers both Claude Code and Codex; save_snapshot provides a file-based fallback |
Quick start (Windows)
- Double-click
start.bat(auto-detects Python, installs dependencies, registers, starts the daemon) - Open Claude Code or Codex and say "I want to use PassPaper"
- Open the link it gives you on your tablet (Chrome) and save it as a bookmark
- Write, then tell the AI "look at what I wrote"
From then on: open the bookmark and just write. If the daemon isn't running, the shim starts it automatically.
Manual commands
python src/passpaper/cli.py setup # one-time: dependencies + runtime package + register CC/Codex python src/passpaper/cli.py start # start the daemon (resident in background) python src/passpaper/cli.py status # health / stroke count / tablet count / links python src/passpaper/cli.py stop # graceful stop (persists data first) python src/passpaper/cli.py doctor # environment diagnostics python src/passpaper/cli.py rotate-token # rotate when the pairing code leaks
Optional autostart at boot: python src/passpaper/cli.py setup --autostart
MCP tools
| Tool | Purpose |
|---|---|
get_connection_info |
Tablet link + QR code (the AI must call this first) |
get_handwriting |
Current handwriting content (PNG, auto-cropped / scaled) |
get_handwriting_status |
Stroke count / revision / whether new content exists (lightweight) |
clear_canvas |
Clear the canvas |
save_snapshot |
Save PNG to disk and return the path (for clients that cannot receive MCP images) |
list_sessions |
List recorded handwriting sessions (stroke count / time) |
start_session |
Start a new session; old sessions are kept for traceability |
export_session |
Export a session as md / jsonl / json / excalidraw, committable with the project's Git |
recognize_handwriting |
Call the local VLM to recognize Chinese / formulas (falls back to agent vision if unconfigured) |
Further reading
- docs/ARCHITECTURE.md — daemon + shim architecture, data flow, latency and auth details
- docs/RECOGNITION.md — local Chinese / formula recognition endpoint configuration + recommended model combinations
- docs/ACCEPTANCE_TEST_PLAN.md — real-device acceptance checklist
- PRIVACY.md — privacy policy: local-first, no cloud, no telemetry, no outbound calls
- SECURITY.md — security model: pairing token, recognition endpoint risk, vulnerability reporting
Dependencies
Python ≥ 3.10, websockets Pillow qrcode (the shim itself has zero dependencies — pure stdlib).
Testing
python scripts/e2e_test.py # 26 checks: shim cold-handshake speed, daemon auto-spawn, tablet WS, capture latency, # 60k-point rendering performance, offline bulk re-send, graceful shutdown, etc.
Design notes
- Coordinate system: the tablet maps the visible area proportionally onto 2048×1536 canonical coordinates (letterbox) — WYSIWYG, independent of device orientation / zoom
- Eraser: white-ink overlay rendering (visually equivalent to a real erase); erased strokes don't participate in auto-cropping
- Security: 128-bit persistent pairing code, verified on WS/HTTP; listens on LAN only
- Runtime package:
setupcopies daemon/shim to~/.passpaper/(pure ASCII path); client config points there — no spawn encoding issues even when the project lives under a non-ASCII path - Environment variable:
PASSPAPER_HOMEchanges the data directory (for testing / portable installs)
Roadmap
Shipped (v1.0.0)
- Resident daemon + MCP shim
- Persistent pairing / offline re-send / incremental rendering (~25ms capture, MCP handshake <100ms)
- Handwriting session recording + multi-format export (md / jsonl / json / excalidraw)
- Pluggable Chinese / formula recognition pipeline (local VLM, falls back when no model)
In progress / next
- Real-device acceptance (tablet + Claude Code / Codex in actual use)
- PyPI release + MCP marketplace submission (
pip install passpaper-mcp) - Cloudflare Tunnel mode (outdoor / cross-network)
- Stroke-level semantic erasing
- System tray app
- More local recognition backends (PaddleOCR-VL / GLM-OCR out-of-the-box integration)
Troubleshooting
passpaper doctor— diagnostics for Python / dependencies / runtime package / MCP registration / pairing token.- Daemon not starting? Check
~/.passpaper/daemon.logand~/.passpaper/daemon.spawn.log. - Port 8765 taken? Run
passpaper stopthenpasspaper start; or changePORT(must also update the canvas). - Tablet can't connect: make sure it's on the same WiFi as the computer; re-fetch the link with
passpaper url; corporate / campus networks may isolate devices — try a phone hotspot. - Recognition not responding: without
PASSPAPER_RECOGNIZER_ENDPOINTconfigured it falls back to "agent looks at the image directly", which is expected; configuration see docs/RECOGNITION.md.
Contributing
Issues and PRs welcome. Dev environment, tests and rules: see CONTRIBUTING.md. Report security vulnerabilities privately, see SECURITY.md.
References & inspiration
PassPaper's design is inspired by several open-source projects, credited one by one in REFERENCES.md.
Star History
License
MIT — Copyright (c) 2026 B.Han.
来源:GitHub · github.com