reader
MCP server that lets Claude send documents, drills, and choices to an e-reader (Kindle, Kobo, etc.) in real time via a Cloudflare Worker, supporting anonymous and OAuth-authenticated access.
README
reader
Read Claude on your e-reader — and tap back.
Ask Claude for something long and it appears on your Kindle, Kobo, reMarkable, PocketBook or Boox in about three seconds — through the browser the device already has. No jailbreak, no email, no EPUB, no account, no app.
And it reads back: Claude can put tappable buttons under what it wrote, so you answer from the device and the conversation carries on.
Start
1. Add the connector https://reader.neves.cloud/mcp
2. On the e-reader, open reader.neves.cloud → shows a 5-char code
3. Tell Claude "send that to my reader, code 8427X"
The e-reader types nothing. It shows a code; you read it off the screen and say it out loud. That constraint drives most of the design below.
The tools
| Tool | What it does |
|---|---|
send_to_reader |
Puts markdown on the screen. Optionally with tappable choices. |
await_reader_choice |
Blocks until they tap — a choice, a quick action, or text they marked. |
check_reader |
Is a device polling, what is it showing, what page are they on. |
send_drill |
Hands a whole multiple-choice deck to the server, which runs the loop. |
await_drill_report |
Per-item results once the deck clears. |
resume_drill |
Puts the drill question back after an interruption. |
Markdown, GFM tables and SVG (fenced ```svg or raw <svg>) render crisply in
grayscale. mode: "append" streams a long piece in chunks without losing the
reader's place.
Beyond the buttons Claude sends, the device always offers three of its own: ↻ simpler, → more, and ✎ explain — mark a word, sentence or block and Claude explains it in place.
How it works
"send that to my reader, code 8427X"
│
Claude
│
┌─────────────────────┴──────────────────────┐
▼ ▼
reader.neves.cloud/mcp mcp.neves.cloud/mcp
anonymous · no sign-in GitHub OAuth · remembers
calls the DO in-process your reader
│ │
│ Bearer READER_TOKEN
│ → /_api/send
└─────────────────────┬──────────────────────┘
▼
┌───────────────────────────────┐
│ Durable Object "<code>" │
│ { v, html, title } · 6h TTL │
└───────────────────────────────┘
│ ▲
polls /s/<code> │ │ taps /c/<code>
2.5s → 30s ▼ │ (also ws /w/<code>,
e-reader — stock browser, e-ink one frame per tap)
Polling rather than WebSocket or SSE is deliberate: e-ink repaints in about a second and these devices' WS/SSE are unreliable, so a 2.5s short-poll with full-document replace is both the right granularity and the robust one.
Two front doors, same tools, same core operations (src/ops.ts) — so their
append, render and delivery behaviour cannot drift apart:
reader.neves.cloud/mcp— anonymous, served by this Worker (src/mcp.ts), calling the Session Durable Objects in-process. No OAuth anywhere on this origin. The 5-character code is required on every call: with no accounts, there is nothing to hang a saved pairing on.mcp.neves.cloud/mcp— GitHub sign-in buys a saved pairing (codebecomes optional after the first send) and apair_readertool. It reaches this Worker's write API over a service binding.
Deck mode: a drill runs on the device, not through the model
A multiple-choice drill with an answer key is a deterministic loop, but run screen-by-screen through an agent it costs two round-trips per item — an 18-item deck is 36 — for work a state machine does.
send_drill hands the whole deck over: question, choices, answer index,
optional feedback, plus a policy (requeue_until_correct, shuffle). From there
the Durable Object scores each tap, renders the feedback screen and turns the
page itself. Pages advance at device speed, with no model in the loop.
await_drill_report returns per-item results at the end: what they tapped,
first-try correctness, retries, seconds.
Its edges stay open. A quick action is the one tap that genuinely needs a model —
it parks the drill and surfaces as an ordinary pending tap. Reply with
mode: "append" and the next answer-tap resumes it on its own; resume_drill
re-renders the question when you want a clean screen. A mode: "replace" send
ends the drill, which is also how you cancel one.
The boundary is deliberate: deck mode is only for a deck authored up front with
closed-form answers. Teaching, discussion, partial credit and adaptive
re-explaining stay on send_to_reader / await_reader_choice. The calling agent
picks the mode.
Security
The code is the whole capability, so the keyspace is the security parameter:
30<sup>5</sup> = 24,300,000 (base32 minus every character you could misread off
e-ink — no I/L/O/U, no 0/1). Unthrottled, that is a search space
rather than a secret, so two per-IP budgets sit in front of it:
- a loose ceiling on every code-bearing device route, sized well above a real reader's 2.5s poll — it caps how fast one address can mint Durable Objects;
- a tight budget spent only on first contact with a code. A device pays it once and is never fresh again; a guesser pays it on every guess. At 30/min, one address needs on the order of a year and a half to walk the keyspace.
The MCP endpoint gets only the loose ceiling on purpose: those requests arrive from the client's shared egress, so a tight per-IP budget there would make users throttle each other.
The write API (/_api/*) is a separate matter — shared-secret bearer,
fail-closed: an unset secret rejects every write.
Treat the code like a password. Anyone holding it can see that screen and
send to it. Open reader.neves.cloud/new for a fresh one.
Privacy
No accounts, no email, no analytics, no third-party sharing, nothing used for training. A session holds the document, your taps and your place in it, and deletes itself after 6 hours in which neither side touches it. One first-party cookie remembers your code for 48 hours.
Full policy: https://reader.neves.cloud/privacy — and privacyPage in
src/pages.ts, so every claim in it is checkable against the code here.
Support
Open an issue: https://github.com/nevescloud/reader/issues
Develop
npm install
npm run dev # wrangler dev — local Durable Objects, no Cloudflare auth needed
npm run typecheck
npm test # markdown renderer, code-alphabet invariants, the drill machine
# write API — set READER_TOKEN in .dev.vars (e.g. "dev"); always required, fail-closed
curl -H "Authorization: Bearer dev" -X POST localhost:8787/_api/send \
-d '{"code":"ABCDE","content":"# hi"}'
Deploy
wrangler secret put READER_TOKEN # one-time: the shared secret the write API expects
npm run deploy # binds reader.neves.cloud (DNS auto-provisioned)
Layout
One Worker, served at the origin root.
| File | What lives there |
|---|---|
src/index.ts |
Router: /mcp · /_api/* (write, token) · /s poll · /c tap · /w feed · /<code> reader · /privacy · / entry |
src/ops.ts |
sendDoc / awaitChoice / readStatus / startDrill / awaitDrillReport / resumeDrill — the single source both front doors call |
src/mcp.ts |
ReaderMcp — the anonymous Streamable-HTTP server and its six tools |
src/session.ts |
One Durable Object per code: document + version, pending tap, parked waiters, drill state, hibernating feed sockets, 6h expiry |
src/drill.ts |
Deck mode's rules, pure — validation, tap→next-state, the three screens, the report. No storage, no rendering, so it tests without a DO harness |
src/limit.ts |
The two anti-enumeration budgets (see Security) |
src/md.ts |
Markdown → clean reading HTML |
src/pages.ts |
landingPage · privacyPage · readerPage (e-ink serif, paginated, ES5-only inline script for ~2012 WebKit) |
src/util.ts |
Host, code alphabet, public-URL constants — single source |
License
MIT — see LICENSE.
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
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 模型以安全和受控的方式获取实时的网络信息。