Skip to main content
Glama
donghch
by donghch

EPUB 阅读器 MCP 服务器

License MCP Version Node.js Version

一个模型上下文协议 (MCP) 服务器,充当“AI 智能体的 Kindle”,通过 MCP 的工具 API 公开 EPUB 文件内容。

概述

EPUB 阅读器 MCP 服务器为 AI 智能体提供了阅读和浏览 EPUB 文件的能力。它实现了模型上下文协议 (MCP),公开了 13 种工具,支持打开 EPUB 文件、浏览目录和页面、搜索内容、查看脚注以及管理阅读会话。

功能特性

  • 打开 EPUB 文件:验证并解析 EPUB 文件,创建阅读会话

  • 浏览内容:在页面间向前/向后移动,跳转到特定页面或章节

  • 发现内容:查看目录、元数据和章节摘要

  • 搜索功能:跨章节进行带上下文的全文搜索

  • 参考工具:解析脚注引用,获取阅读进度

  • 会话管理:列出已打开的书籍,关闭会话,管理资源

Related MCP server: Readbook MCP Server

前置要求

  • Node.js 20+

  • npm 或兼容的包管理器

  • 待阅读的 EPUB 文件 (.epub 格式)

安装

从源码安装

git clone https://github.com/your-username/mcp-epub-reader.git
cd mcp-epub-reader
npm install
npm run build

使用方法

运行服务器

该服务器使用 stdio 传输,非常适合与 Claude Desktop 等 MCP 客户端集成。

stdio (本地集成)

用于与 Claude Desktop 或其他 MCP 客户端集成:

node build/index.js

服务器通过 stdin/stdout 使用 MCP JSON-RPC 协议进行通信。

配置

Claude Desktop 配置

将服务器添加到您的 Claude Desktop 配置中(macOS 上位于 ~/Library/Application Support/Claude/claude_desktop_config.json):

{
  "mcpServers": {
    "epub-reader": {
      "command": "node",
      "args": ["/absolute/path/to/mcp-epub-reader/build/index.js"],
      "env": {
        "LOG_LEVEL": "info"
      }
    }
  }
}

环境变量

变量

描述

必需

默认值

LOG_LEVEL

日志级别 (error, warn, info, debug)

info

工具参考

服务器提供了 13 种用于 EPUB 文件交互的工具:

工具

描述

输入参数

ebook/open

打开 EPUB 文件并创建阅读会话

filePath: string, autoNavigate?: boolean

ebook/close

关闭阅读会话并释放资源

sessionId: string

ebook/list_open_books

列出当前所有打开的 EPUB 会话

(无)

ebook/navigate_next

移动到当前会话的下一页

sessionId: string

ebook/navigate_previous

移动到当前会话的上一页

sessionId: string

ebook/jump_to_page

跳转到特定页码

sessionId: string, pageNumber: number

ebook/jump_to_chapter

跳转到特定章节(按标题或索引)

sessionId: string, chapter: string | number

ebook/get_position

获取当前阅读位置和进度

sessionId: string

ebook/search

跨所有章节搜索文本

sessionId: string, query: string, contextWords?: number

ebook/get_toc

获取分层目录

sessionId: string

ebook/get_metadata

获取 EPUB 元数据(标题、作者、出版商等)

sessionId: string

ebook/get_footnote

通过 ID 解析脚注引用

sessionId: string, footnoteId: string

ebook/get_chapter_summary

获取当前章节的摘要

sessionId: string, maxSentences?: number

工具详情

ebook/open

打开 EPUB 文件,解析其内容,创建阅读会话,并返回元数据。

输入模式

{
  filePath: string;      // Absolute or relative path to EPUB file
  autoNavigate?: boolean; // Whether to auto-navigate to first page (default: false)
}

请求示例

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ebook/open",
    "arguments": {
      "filePath": "/path/to/book.epub",
      "autoNavigate": true
    }
  }
}

响应示例

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{\"sessionId\":\"sess_123\",\"metadata\":{\"title\":\"Sample Book\",\"author\":\"Author Name\",\"totalPages\":250,\"totalChapters\":12}}"
      }
    ]
  }
}

ebook/close

关闭阅读会话并释放相关资源。

输入模式

{
  sessionId: string;  // Session ID returned by ebook/open
}

ebook/list_open_books

列出当前所有活动的阅读会话。

输入模式:(无)

响应示例

{
  "sessions": [
    {
      "sessionId": "sess_123",
      "filePath": "/path/to/book.epub",
      "metadata": {
        "title": "Sample Book",
        "author": "Author Name",
        "currentPage": 42,
        "totalPages": 250
      }
    }
  ]
}

ebook/navigate_nextebook/navigate_previous

在页面间向前或向后浏览。

输入模式

{
  sessionId: string;
}

响应示例

{
  "sessionId": "sess_123",
  "currentPage": 43,
  "content": "Page content here...",
  "chapterTitle": "Chapter 3: The Adventure Begins"
}

ebook/jump_to_page

跳转到特定页码。

输入模式

{
  sessionId: string;
  pageNumber: number;  // 1-based page number
}

ebook/jump_to_chapter

按标题(不区分大小写的模糊匹配)或章节索引(从 1 开始)跳转到特定章节。

输入模式

{
  sessionId: string;
  chapter: string | number;  // Chapter title or index
}

ebook/get_position

获取当前阅读位置和进度统计信息。

响应示例

{
  "sessionId": "sess_123",
  "currentPage": 42,
  "totalPages": 250,
  "progress": 0.168,
  "chapterTitle": "Chapter 3: The Adventure Begins",
  "chapterIndex": 3
}

ebook/search

跨所有章节搜索文本,并可选择上下文词数。

输入模式

{
  sessionId: string;
  query: string;
  contextWords?: number;  // Number of context words around matches (default: 50)
}

响应示例

{
  "sessionId": "sess_123",
  "query": "adventure",
  "matches": [
    {
      "chapterIndex": 3,
      "chapterTitle": "Chapter 3: The Adventure Begins",
      "pageNumber": 42,
      "context": "...the great adventure began when...",
      "position": 1250
    }
  ],
  "totalMatches": 1
}

ebook/get_toc

获取分层目录。

响应示例

{
  "sessionId": "sess_123",
  "toc": [
    {
      "title": "Chapter 1: Introduction",
      "level": 1,
      "pageNumber": 1,
      "children": []
    },
    {
      "title": "Part I: The Beginning",
      "level": 1,
      "pageNumber": 10,
      "children": [
        {
          "title": "Chapter 2: First Steps",
          "level": 2,
          "pageNumber": 12,
          "children": []
        }
      ]
    }
  ]
}

ebook/get_metadata

获取完整的 EPUB 元数据。

响应示例

{
  "sessionId": "sess_123",
  "metadata": {
    "title": "Sample Book",
    "author": "Author Name",
    "publisher": "Publisher Name",
    "description": "Book description...",
    "language": "en",
    "publishedDate": "2023-01-01",
    "totalPages": 250,
    "totalChapters": 12
  }
}

ebook/get_footnote

通过 ID 解析脚注引用。

输入模式

{
  sessionId: string;
  footnoteId: string;  // Footnote reference ID (e.g., "fn1")
}

响应示例

{
  "sessionId": "sess_123",
  "footnoteId": "fn1",
  "content": "Footnote content here...",
  "referencingPage": 42
}

ebook/get_chapter_summary

通过提取关键句获取当前章节的摘要。

输入模式

{
  sessionId: string;
  maxSentences?: number;  // Maximum sentences in summary (default: 3)
}

响应示例

{
  "sessionId": "sess_123",
  "chapterTitle": "Chapter 3: The Adventure Begins",
  "summary": [
    "The protagonist begins their journey.",
    "They encounter their first challenge.",
    "A mysterious figure offers guidance."
  ]
}

开发

项目结构

mcp-epub-reader/
├── src/
│   ├── epub/                    # EPUB domain logic
│   │   ├── parser.ts           # EPUB parsing and metadata extraction
│   │   ├── paginator.ts        # Page splitting and content retrieval
│   │   └── types.ts            # EPUB domain types
│   ├── server/                 # MCP server implementation
│   │   ├── index.ts           # Server entry point (stdio transport)
│   │   ├── book-manager.ts    # Session lifecycle management
│   │   ├── tool-registration.ts # Tool registration and routing
│   │   └── types.ts           # Server-side types
│   ├── tools/                  # All 13 tool implementations
│   │   ├── open.ts            # ebook/open tool
│   │   ├── close.ts           # ebook/close tool
│   │   ├── list-books.ts      # ebook/list_open_books tool
│   │   ├── navigate.ts        # Navigation tools (next/previous)
│   │   ├── jump.ts            # Jump tools (page/chapter)
│   │   ├── position.ts        # ebook/get_position tool
│   │   ├── search.ts          # ebook/search tool
│   │   ├── toc.ts             # ebook/get_toc tool
│   │   ├── metadata.ts        # ebook/get_metadata tool
│   │   ├── footnote.ts        # ebook/get_footnote tool
│   │   └── summary.ts         # ebook/get_chapter_summary tool
│   └── utils/                  # Shared utilities
│       └── validation.ts      # Zod schemas and input validation
├── tests/                      # Test suites
│   ├── unit/                  # Unit tests
│   └── integration/           # Integration tests
├── package.json
├── tsconfig.json
└── jest.config.js

从源码构建

# Install dependencies
npm install

# Build the project (TypeScript → JavaScript)
npm run build

# Output goes to `build/` directory

测试

# Run all tests
npm test

# Run tests with coverage
npm test -- --coverage

# Run specific test file
npm test -- tests/unit/epub/parser.test.ts

添加新工具

  1. src/tools/ 中创建一个包含工具实现的新文件:

// src/tools/example.ts
import { BookManager } from '../server/book-manager';
import { ExampleToolInput, ExampleToolOutput } from '../server/types';

export async function handleExampleTool(
  input: ExampleToolInput,
  bookManager: BookManager
): Promise<ExampleToolOutput> {
  // Tool implementation
  return { result: 'success' };
}

export function createExampleTool(bookManager: BookManager) {
  return {
    name: 'ebook/example' as const,
    handler: (input: ExampleToolInput) => handleExampleTool(input, bookManager),
  };
}
  1. src/utils/validation.ts 中添加 Zod 模式:

export const ExampleToolSchema = z.object({
  sessionId: z.string(),
  // ... other parameters
});
  1. src/server/tool-registration.ts 中导入并注册:

import { createExampleTool } from '../tools/example';

const toolFactories = {
  // ... existing tools
  'ebook/example': createExampleTool,
};

贡献

欢迎贡献!请遵循以下步骤:

  1. Fork 本仓库

  2. 创建功能分支 (git checkout -b feature/amazing-feature)

  3. 提交更改 (git commit -m 'Add amazing feature')

  4. 推送到分支 (git push origin feature/amazing-feature)

  5. 发起 Pull Request

开发设置

# Clone the repository
git clone https://github.com/your-username/mcp-epub-reader.git
cd mcp-epub-reader

# Install dependencies
npm install

# Set up environment
cp .env.example .env  # if applicable

# Run development server with watch mode
npm run dev

代码标准

  • 遵循 TypeScript 最佳实践,使用严格类型

  • 尽可能编写纯函数,保持不可变性

  • 使用依赖注入以提高可测试性

  • 包含全面的单元测试 (AAA 模式)

  • 为公共 API 和复杂逻辑编写文档

许可证

本项目采用 MIT 许可证 开源。

致谢

参考资料

更新日志

查看 CHANGELOG.md 获取版本历史。


注意:此服务器专为与 Claude Desktop 等 MCP 客户端配合使用而设计。它在为 AI 智能体提供 EPUB 阅读能力的同时,保持了会话隔离和资源管理。

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    Provides AI agents with research capabilities for local Calibre e-book libraries, including fulltext search across titles, ISBNs, and comments, plus structured excerpt retrieval from books.
    2
    GPL 3.0
  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables AI assistants to help users manage their reading experience by searching books, tracking reading progress, managing bookmarks, and generating personalized recommendations and summaries.
    -
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables searching, reading, and managing a Calibre ebook library through natural language, with features like metadata search, full-text search, content extraction, and library management.
    40 npm
    Apache 2.0