Skip to main content
Glama
Bin-H-17

PassPaper

by Bin-H-17

递纸 PassPaper

CI OpenSSF Scorecard M8ven Score License: MIT Python 3.10+ Platform SonarCloud codecov

中文 | English


中文

在平板上手写公式/草图,AI 通过 MCP 工具实时读取。 支持 Claude CodeCodex CLI

状态:v1.0.0 早期版本。核心功能已实现并通过代码级校验(py_compile / import / 识别解析),尚未在大规模真机环境验证。欢迎在 GitHub Issues 反馈问题与使用场景。

[平板 Chrome]                    [电脑]
 手写 canvas ──WebSocket──▶ passpaper daemon (常驻)
                              │  笔画落笔即渲染到内存画布
   Claude Code / Codex ◀─MCP stdio─ mcp_shim
                              └──── localhost HTTP ────┘

功能

  1. 中文潦草 / 公式手写识别(本地、隐私) — 配置本地 VLM(PASSPAPER_RECOGNIZER_ENDPOINT,如 ollama / llama.cpp / vLLM 的 OpenAI 兼容端点)后,图片在交给 Agent 前会先转成结构化文本 / LaTeX。未配置时回退到「Agent 直接看图」。详见 docs/RECOGNITION.md

  2. 低延迟跨设备接力 — 平板落笔即增量渲染到内存画布,取图 = 读缓存(实测约 25ms)。WebSocket 断线时笔画本地缓存,重连后自动批量补发。

  3. 手写会话可随项目回溯 — 每一笔落盘为 JSONL(~/.passpaper/sessions/)。可导出 Markdown / Excalidraw,在 Excalidraw / tldraw 中回放编辑。

  4. 通用 MCP + 本地优先 — MCP shim 同时支持 Claude CodeCodex;数据只走本机和局域网,无账号、无云、无出站调用。设计受多个开源项目启发,逐条署名见 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)

  1. 双击 start.bat(自动检测 Python、装依赖、注册、启动 daemon)

  2. 打开 Claude Code 或 Codex,说 "我要用递纸"

  3. 在平板上打开它给你的链接(Chrome),存成书签

  4. 写字,然后对 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 视觉)

深入阅读

依赖

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

  1. 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.

  2. 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.

  3. 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.

  4. 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)

  1. Double-click start.bat (auto-detects Python, installs dependencies, registers, starts the daemon)

  2. Open Claude Code or Codex and say "I want to use PassPaper"

  3. Open the link it gives you on your tablet (Chrome) and save it as a bookmark

  4. 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: setup copies 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_HOME changes 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.log and ~/.passpaper/daemon.spawn.log.

  • Port 8765 taken? Run passpaper stop then passpaper start; or change PORT (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_ENDPOINT configured 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

Star History Chart

License

MIT — Copyright (c) 2026 B.Han.

Maintenance

ActivityMaintained
ResponsivenessSyncing

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Bin-H-17/passpaper'

If you have feedback or need assistance with the MCP directory API, please join our Discord server