Paperboy

Paperboy

Enables sending Markdown or EPUB content to a Kindle device via MCP. Users can send documents to their Kindle directly from Claude or any MCP client.

Category
访问服务器

README

Paperboy - Send to Kindle in one step

<div align="center"> <img src="docs/assets/icons/main-icon.png" alt="Paperboy icon" width="400" /> </div>

<div align="center">

Quality Gate Status Bugs Code Smells Lines of Code Security Rating Vulnerabilities

</div>

Send Markdown (or pre-built EPUB) content to your Kindle — from the terminal, from Claude Code, or from any MCP client.

How It Works

  1. You provide Markdown content (a file, stdin, or via Claude) or an existing .epub file
  2. Paperboy converts Markdown to EPUB (downloading and embedding remote images along the way); .epub files pass through untouched
  3. The EPUB is emailed to your Kindle address
  4. The document appears in your Kindle library

Three Ways to Use It

CLI

# From a Markdown file
paperboy --title "My Article" --file article.md

# From an existing EPUB (sent as-is, no conversion)
paperboy --file book.epub

# From stdin
cat article.md | paperboy --title "My Article"

# With options
paperboy --title "Notes" --file notes.md --author "Alice" --device "Alice's Kindle"

Folder Watcher

Drop .md or .epub files into a watched folder — Paperboy converts (Markdown) or forwards (EPUB) and sends them automatically.

paperboy watch

MCP Server

Connect Claude Desktop or any MCP client to the server. Claude can then send content to your Kindle in a single tool call during conversation.

Prerequisites

  • Node.js 22 or later
  • An SMTP account — any provider works; Gmail is the easiest option, see Gmail setup below
  • Your Kindle email address (found in Amazon account settings under "Send to Kindle")
  • The SMTP sender address must be in your Amazon approved senders list

Setup

git clone <repo-url>
cd send-to-kindle
npm install
npm run build

Copy .env.example to .env and fill in your values:

cp .env.example .env

The .env file loads automatically when running locally. In Docker, set environment variables directly — they take precedence over .env.

Required Environment Variables

Variable Description Example
KINDLE_DEVICES Named device(s) in name:email format personal:your-kindle@kindle.com
SENDER_EMAIL Email that sends the EPUB you@gmail.com
SMTP_HOST SMTP server hostname smtp.gmail.com
SMTP_PORT SMTP server port 587
SMTP_USER SMTP login username you@gmail.com
SMTP_PASS SMTP app password abcd-efgh-ijkl-mnop

Multiple devices: KINDLE_DEVICES=personal:you@kindle.com,partner:them@kindle.com

Optional Environment Variables

Variable Default Description
DEFAULT_AUTHOR Claude Author name when none is specified
WATCH_FOLDER Path to folder for the paperboy watch command (auto-sends files)
MCP_HTTP_PORT Enables HTTP/SSE transport on this port
MCP_AUTH_TOKEN Required when MCP_HTTP_PORT is set
LOG_LEVEL info Pino log level (debug, info, warn, error)

CLI Usage

Flags

Flag Required Description
--title <title> No Title of the document sent to Kindle. If omitted, resolved from EPUB metadata (for .epub), Markdown frontmatter, or the filename stem
--file <path> No Path to a .md or .epub file; reads Markdown from stdin if omitted
--author <name> No Author name embedded in the EPUB (default: configured value)
--device <name> No Target Kindle device name (default: first configured device)
--help No Show usage text and exit
--version No Show version number and exit

Exit Codes

Code Meaning
0 Document sent successfully
1 Validation error (unresolvable title, empty content, malformed frontmatter, size limit)
2 EPUB conversion error
3 Email delivery error (SMTP auth, connection, rejection)
4 Configuration error (missing or invalid environment variables)

Configuration Resolution

The CLI loads configuration in this order (first match wins):

  1. Shell environment variables
  2. .env file in the current working directory
  3. ~/.paperboy/.env fallback for global user configuration

--help and --version work without any configuration.

MCP Server Usage

Local (stdio transport)

npm run dev

Add to your Claude Desktop config (claude_desktop_config.json):

{
  "mcpServers": {
    "paperboy": {
      "command": "node",
      "args": ["dist/index.js"],
      "cwd": "/path/to/send-to-kindle",
      "env": {
        "KINDLE_DEVICES": "personal:your-kindle@kindle.com",
        "SENDER_EMAIL": "you@gmail.com",
        "SMTP_HOST": "smtp.gmail.com",
        "SMTP_PORT": "587",
        "SMTP_USER": "you@gmail.com",
        "SMTP_PASS": "your-app-password"
      }
    }
  }
}

Remote (HTTP/SSE transport)

Set MCP_HTTP_PORT and MCP_AUTH_TOKEN, then start the server:

MCP_HTTP_PORT=3000 MCP_AUTH_TOKEN=your-secret npm run dev

The server accepts MCP requests at POST /mcp with Bearer token authentication.

MCP Tool: send_to_kindle

Parameter Type Required Description
title string yes Document title (appears in Kindle library)
content string yes Document body in Markdown format
author string no Author name (defaults to DEFAULT_AUTHOR)
device string no Target Kindle device name

Docker

# Build
docker build -t paperboy .

# Run with stdio
docker run -i --env-file .env paperboy

# Run with HTTP/SSE
docker run -p 3000:3000 --env-file .env paperboy

Or with Docker Compose:

docker compose up

Folder Watcher

The folder watcher monitors a directory for Markdown and EPUB files and automatically sends each one to your Kindle. Drop a .md or .epub file in — .md files are converted to EPUB and .epub files are sent as-is; in both cases the file moves to sent/ when done (or error/ if something goes wrong).

Setup

Add WATCH_FOLDER to your .env:

WATCH_FOLDER=/path/to/your/kindle-inbox

The folder must exist before starting the watcher. The sent/ and error/ subdirectories are created automatically.

Run

paperboy watch

Files already in the folder when the watcher starts are processed immediately. New files are picked up as they arrive.

Run as a background service

Service templates are provided in scripts/service-templates/.

Linux (systemd):

# Edit the file and replace /path/to/npx with the output of: which npx
cp scripts/service-templates/paperboy-watcher.service ~/.config/systemd/user/
systemctl --user enable --now paperboy-watcher
systemctl --user status paperboy-watcher
journalctl --user -u paperboy-watcher   # view logs

macOS (launchd):

# Edit the file and replace /path/to/npx with the output of: which npx
cp scripts/service-templates/com.paperboy.watcher.plist ~/Library/LaunchAgents/
launchctl load ~/Library/LaunchAgents/com.paperboy.watcher.plist
# Logs: ~/Library/Logs/paperboy-watcher.log

Windows (Task Scheduler):

# Edit the file and replace C:\path\to\npx.cmd with the output of: where npx
schtasks /create /tn "PaperboyWatcher" /xml "scripts\service-templates\windows-task.xml"

# Or as a one-liner (no XML edit needed):
schtasks /create /tn "PaperboyWatcher" /tr "\"C:\path\to\npx.cmd\" paperboy watch" /sc onlogon /rl limited

The task starts at login and restarts automatically on failure.

How it works

  • Watches only the root of WATCH_FOLDER (not subdirectories)
  • Waits 2 seconds after a file stops changing before processing (safe for slow copies)
  • Processes files one at a time
  • Retries transient SMTP failures up to 3 times with exponential backoff
  • Permanent errors (auth failure, rejection) are not retried
  • Shuts down gracefully on SIGINT/SIGTERM, draining any in-progress file

Security

Dependency Scanning: npm audit is enforced at two points:

  1. Pre-commit hook — blocks commits if high/critical vulnerabilities are found
  2. CI/CD workflow — blocks merges if high/critical vulnerabilities are found

Run locally: npm run audit:ci (exits non-zero if vulnerabilities present)

Development

npm run dev            # Run MCP server with tsx (no build step)
npm run cli -- --help  # Run CLI with tsx
npm run build          # Compile TypeScript to dist/
npm test               # Run automated tests (335 tests across 31 files)
npm run test:watch     # Run tests in watch mode
npm run test:coverage  # Run tests with coverage report (lcov)
npm run sonar:local    # Run coverage + SonarCloud scan locally
npm run test:email     # Send a real test email to verify SMTP config
npm run audit:ci       # Check for high/critical npm vulnerabilities
npm run lint           # Lint sources with ESLint

Gmail Setup

Any SMTP provider works. Gmail is recommended for personal use — it's free, requires no domain, and has no sending restrictions for individual use.

Gmail requires an App Password — your regular password will not work for SMTP.

  1. Enable 2-Step Verification: Google Account > Security > 2-Step Verification
  2. Create an App Password: Google Account > Security > App Passwords
  3. Use the generated 16-character password as SMTP_PASS in .env

Then add your sender address to Amazon's approved list: Amazon Account > Manage Your Content and Devices > Preferences > Personal Document Settings > Approved Personal Document E-mail List.

Architecture

Three-layer design with strict dependency inversion:

Application (MCP + CLI adapters) --> Domain (service, values, ports) <-- Infrastructure (EPUB, SMTP)
  • Domain: Value objects (Title, Author, MarkdownContent, EpubDocument, ImageStats), service orchestration (Markdown convert-then-deliver and EPUB passthrough), port interfaces, typed errors with Result<T, E>
  • Infrastructure: Markdown-to-EPUB conversion (marked + sanitize-html + epub-gen-memory), image processor (downloads remote images with SSRF-safe redirect handling, converts AVIF/WebP/HEIC to JPEG via sharp), cover generator (SVG → JPEG via sharp), YAML frontmatter parser (gray-matter), EPUB reader (title from <dc:title> via jszip), SMTP delivery (nodemailer) with retry/backoff, Pino logging, CLI content reader
  • Application: MCP tool handler, CLI adapter (arg parsing, exit codes, orchestration), folder watcher (chokidar), two composition roots (index.ts for MCP, cli-entry.ts for CLI)

License

MIT

推荐服务器

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 模型以安全和受控的方式获取实时的网络信息。

官方
精选