Skip to main content
Glama

reader

Read Claude on your e-reader — and tap back.

Add to Claude

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.

Related MCP server: Remote MCP Server

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 (code becomes optional after the first send) and a pair_reader tool. 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: 305 = 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.

A
license - permissive license
-
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

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

Related MCP Servers

  • F
    license
    -
    quality
    D
    maintenance
    A Cloudflare Workers-based implementation of Model Context Protocol (MCP) server with OAuth login that allows tools like Claude to access external capabilities.
    Last updated
  • -
    license
    -
    quality
    -
    maintenance
    A Model Context Protocol server implementation that runs on Cloudflare Workers with OAuth authentication support, allowing users to connect MCP clients like Claude Desktop or the MCP Inspector to utilize remote AI tools.
    Last updated
  • F
    license
    -
    quality
    C
    maintenance
    A Model Context Protocol server implementation designed to run on Cloudflare Workers with integrated OAuth authentication. It enables hosting and securely accessing MCP tools remotely via SSE transport from clients like Claude Desktop.
    Last updated

View all related MCP servers

Related MCP Connectors

  • MCP server for AI agents to plan, verify, and deploy Cloudflare-native apps.

  • MCP server for Argo RPG Platform — connects AI assistants to campaign data via OAuth2

  • Hosted MCP server connecting claude.ai, ChatGPT and other AI apps to your own computer

View all 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/nevescloud/reader'

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