Co-Reading MCP

Co-Reading MCP

A local MCP server that gives Claude a durable reading room for EPUB and plain text books, enabling chunk-by-chunk navigation, annotations, progress tracking, and shared margin cards.

Category
访问服务器

README

Co-Reading MCP

A local MCP server that gives Claude a durable reading room:

  • import EPUB or plain text into stable chunks while preserving EPUB spine/chapter boundaries
  • list books and chunks
  • read chunk-by-chunk with prevId / nextId
  • continue directly from the next unread chunk
  • search across a book with cached chunk text
  • write margin annotations
  • stage user notes, submit them to Claude once, and attach Claude replies under them
  • track reading progress
  • surface small shared-margin cards when human and Claude stop at the same passage
  • return a small finish ritual when a book is completed

The goal is not one-shot summarization. The goal is a shared reading surface where a human and Claude can both read, leave anchored notes, and resume smoothly. Human notes can also stay private until the reader chooses to share them with Claude.

For a step-by-step setup and usage flow, see docs/user-guide.md.

Quick Start

Requirements:

  • Node.js 18+
  • Python 3.10+ for the import scripts
cd co-reading-mcp
cp -R data.example data
node src/server.js

If you also want a human-friendly reading surface, start the bundled reader:

npm run reader

Open http://127.0.0.1:8787. This serves a small reference reader and local HTTP API while also keeping the MCP stdio server active in the same process. In Claude Desktop / Claude Code you can point the MCP command at src/http.js instead of src/server.js when you want one process to handle both:

{
  "mcpServers": {
    "co-reading": {
      "command": "node",
      "args": ["/absolute/path/to/co-reading-mcp/src/http.js"],
      "env": {
        "READING_MCP_DATA_DIR": "/absolute/path/to/co-reading-mcp/data",
        "READING_HTTP_PORT": "8787"
      }
    }
  }
}

The reader's Library header includes an import button for EPUB, TXT, or Markdown files. Browser imports upload the file directly to the co-reading server, so they also work with remote claude.ai setups where chat attachments are isolated from the MCP server filesystem.

For Claude Desktop / Claude Code, configure the MCP server as a stdio command:

{
  "mcpServers": {
    "co-reading": {
      "command": "node",
      "args": ["/absolute/path/to/co-reading-mcp/src/server.js"],
      "env": {
        "READING_MCP_DATA_DIR": "/absolute/path/to/co-reading-mcp/data"
      }
    }
  }
}

Remote Server

For VPS, reverse-proxy, tunnel, or remote MCP clients, run one process:

READING_MCP_DATA_DIR=./data MCP_AUTH_TOKEN="change-me" npm run start:sse

The same port serves the human reader, REST API, and remote MCP transports:

  • https://your-domain.example/: reference reader UI
  • https://your-domain.example/?token=change-me: reader UI with auth saved in a cookie (convenience shortcut — the token appears in the first request URL; avoid on shared devices or high-security setups)
  • https://your-domain.example/api/*: reader REST API
  • https://your-domain.example/mcp: remote MCP JSON-RPC endpoint for custom connectors
  • https://your-domain.example/sse: legacy MCP SSE transport
  • https://your-domain.example/.well-known/oauth-protected-resource/mcp: MCP resource metadata for connector discovery

Environment variables:

  • MCP_SSE_PORT or PORT: listen port, default 3100
  • MCP_SSE_HOST: listen host, default 0.0.0.0
  • MCP_AUTH_TOKEN: bearer token required by remote clients
  • MCP_CORS_ORIGIN: CORS origin. When MCP_AUTH_TOKEN is set, defaults to *; when unset, defaults to no CORS headers (blocks cross-origin requests)
  • MCP_MAX_BODY_BYTES: max JSON-RPC POST body size, default 25000000
  • READING_IMPORT_MAX_BYTES: max EPUB/TXT upload size, default 25000000

For Claude custom connectors, prefer the /mcp URL. /sse remains available for older MCP clients that still expect the SSE + /messages flow.

Do not expose the remote server on the public internet without HTTPS and MCP_AUTH_TOKEN. When MCP_AUTH_TOKEN is set, the reader, static assets, /api/*, /sse, /messages, /mcp, and /health require the token. Open the reader once with /?token=...; the server sets a same-site cookie and the reader stores the token for API calls. If you use nginx, Caddy, or cloudflared, proxy /, /api/*, /sse, /messages, /mcp, and /.well-known/* to the same local process and make sure streaming responses are not buffered.

Import Books

Plain text:

python3 scripts/import_text.py ./book.txt --title "Book Title" --author "Author" --out ./data/books

Plain text can also preserve section headings with a multiline regex:

python3 scripts/import_text.py ./book.txt \
  --title "Book Title" \
  --heading-regex "^第[一二三四五六七八九十百零〇0-9]+[章节回].*$"

If a loose heading regex catches navigation labels or other tiny sections, add --min-section-chars 100 or a similar threshold.

EPUB:

python3 scripts/import_epub.py ./book.epub --out ./data/books

Claude can also import books through MCP, which is useful on claude.ai or mobile devices where the user cannot SSH into the server:

  • reading_import_book: one EPUB/TXT as a base64 payload
  • reading_import_begin / reading_import_part / reading_import_finish: chunked upload for larger files

For example, after a user drops book.epub into a Claude chat, Claude can read the file, base64-encode it, and call reading_import_book:

{
  "filename": "book.epub",
  "dataBase64": "...",
  "bookId": "optional-stable-id"
}

TXT imports can pass the same heading options as the command-line script:

{
  "filename": "book.txt",
  "dataBase64": "...",
  "title": "Book Title",
  "headingRegex": "^Chapter\\s+\\w+"
}

The import tools write into data/books immediately; no server restart is needed.

Both importers create:

data/books/<book-id>/
  manifest.json
  chunks/
    ch00.txt
    ch01.txt

EPUB imports keep each spine item as a section boundary. If an EPUB stores the whole book in a single spine item, the importer falls back to internal h1/h2/h3 headings. If a chapter is longer than --max-chars, only that chapter is split into Chapter Title Part 1/N, Part 2/N, and so on.

Runtime state is stored outside book content:

data/
  annotations.jsonl
  progress.json
  reading_sessions.json

reading_submit_user_notes includes full chunk text once per sessionId by default, then sends only new notes for the same chunk in that session. Use a new sessionId when Claude starts a new conversation/session so the relevant chunk context is sent again.

Tools

  • reading_list_books
  • reading_list_chunks
  • reading_read_chunk
  • reading_continue
  • reading_search_chunks
  • reading_import_book
  • reading_import_begin
  • reading_import_part
  • reading_import_finish
  • reading_import_cancel
  • reading_delete_book
  • reading_annotate_passage
  • reading_list_annotations
  • reading_submit_user_notes
  • reading_list_submissions
  • reading_read_submission
  • reading_reply_to_annotation
  • reading_mark_read
  • reading_card_inbox
  • reading_open_card
  • reading_save_card
  • reading_dismiss_card
  • reading_list_cards
  • reading_collect_card
  • reading_get_progress

See docs/mcp-tools.md and docs/data-format.md. For the intended Claude workflow, see docs/claude-workflow.md.

Frontend Integration

The bundled reader is intentionally small: it is a reference UI, not a required frontend. Existing apps can talk to the same local HTTP API:

  • GET /api/books
  • DELETE /api/books/:bookId
  • GET /api/books/:bookId/chunks
  • GET /api/books/:bookId/chunks/:chunkId
  • GET /api/continue?bookId=...
  • GET /api/annotations?bookId=...&chunkId=...
  • POST /api/annotations
  • POST /api/replies
  • POST /api/submit-notes
  • POST /api/mark-read
  • GET /api/search?q=...&bookId=...
  • POST /api/import

Human notes are saved as open local notes first. Pressing "Send to Claude" calls reading_submit_user_notes, includes chunk context according to the session policy, marks those notes submitted, and avoids resending the same open notes.

Deleting a book removes it from the active library and archives the book folder plus related progress, annotations, submissions, and cards under data/trash/books/.... Trash is pruned after 30 days by default; set READING_TRASH_RETENTION_DAYS=0 to keep trash forever.

Small ritual cards/bookmarks can be collected with reading_collect_card. Claude can then use reading_card_inbox like a quiet bookmark inbox, open a visual card with reading_open_card, save it as a local image with reading_save_card, or clear it with reading_dismiss_card. They are meant for completed sections, shared-margin moments, quiet passages worth carrying forward, and a separate Last Fold card when the final chunk of a book is marked read.

By default the card renderer stays zero-dependency and falls back to SVG. For the polished PNG cards, install Playwright's Chromium renderer once:

npm i -D playwright
npm run install:card-renderer

Privacy

This repo is designed so private content stays in data/, which is ignored by git. data.example/ contains only toy text.

Contributors

  • GPT
  • Claude
  • Koshi

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选