🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

番茄小说阅读 fysh1010/mcp-server-fanqie

MCPv0.1.2
fysh10104 天前有提交已提供中文文档扫描:含敏感能力兼容 / 相关生态

搜书读章节,登录后看书架与收藏划线

51.7/100
综合分
54
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/11/4 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

相关生态插件(非 dsh 原生,按其对应运行时安装)
git clone https://github.com/fysh1010/mcp-server-fanqie.git

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:仅索引
是什么
生态插件
可安装,未声明 dsh 能力
装得上吗
静态安装检查通过
未做真实安装
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 4 天前
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查✓ 自动检查通过
展开查看检查明细 ↓

以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。

✓npm 包@fysh925/mcp-server-fanqie @ 0.1.2
✓Node 引擎要求 >=22 · 基线 Node 22.19 满足
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/11/4 03:20:22

安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

读写/删除本地文件读取剪贴板或密钥环境变量发起外部网络请求
查看扫描证据(共 68 处,展示前 64 条)
  • 读取密钥环境变量
    server/mcp-local.mjs:9
    process.env.FANQIE_API_TOKEN = process.env.FANQIE_LOCAL_TOKEN || '';
  • 发起网络请求
    server/core.mjs:158
    const page = initialState(await this.request(`/page/${id(bookId, 'book_id')}`)).page;
  • 发起网络请求
    server/core.mjs:167
    const data = await this.request(`/api/reader/directory/detail?bookId=${id(bookId, 'book_id')}`, true);
  • 发起网络请求
    server/core.mjs:176
    const html = await this.request(`/reader/${id(itemId, 'item_id')}`);
  • 请求外部主机novel.snssdk.com
    server/core.mjs:200
    const data = await this.request(`/api/novel/channel/homepage/search/search/v1/?${params}`, true, 'https://novel.snssdk.com');
  • 发起网络请求
    server/core.mjs:200
    const data = await this.request(`/api/novel/channel/homepage/search/search/v1/?${params}`, true, 'https://novel.snssdk.com');
  • 发起网络请求
    server/core.mjs:211
    const data = await this.request(`/api/author/search/search_book/v1?${params}`, true);
  • 请求外部主机reading.snssdk.com
    server/core.mjs:222
    const response = await this.request(`/reading/bookapi/search/tab/v?${params}`, true, 'https://reading.snssdk.com', { signed: true, whole: true });
  • 发起网络请求
    server/core.mjs:222
    const response = await this.request(`/reading/bookapi/search/tab/v?${params}`, true, 'https://reading.snssdk.com', { signed: true, whole: true });
  • 读取密钥环境变量
    server/http.mjs:6
    export function createApiServer(client, { token = process.env.FANQIE_LOCAL_TOKEN, index, accounts } = {}) {
  • 读取本地文件
    server/accounts.mjs:33
    try { return JSON.parse(await readFile(path, 'utf8')); }
  • 写入本地文件
    server/accounts.mjs:38
    await mkdir(this.root, { recursive: true, mode: 0o700 });
  • 读取本地文件
    server/accounts.mjs:40
    this.root = await realpath(this.root);
  • 写入本地文件
    server/accounts.mjs:44
    await writeFile(temp, JSON.stringify(value), { mode: 0o600, flag: 'wx' });
  • 写入本地文件
    server/accounts.mjs:45
    await rename(temp, target);
  • 删除本地文件
    server/accounts.mjs:46
    } finally { await unlink(temp).catch(error => { if (error.code !== 'ENOENT') throw error; }); }
  • 写入本地文件
    server/accounts.mjs:50
    await mkdir(this.root, { recursive: true, mode: 0o700 });
  • 读取本地文件
    server/accounts.mjs:51
    this.root = await realpath(this.root);
  • 读取本地文件
    server/accounts.mjs:58
    let owner; try { owner = Number(await readFile(path, 'utf8')); } catch {}
  • 删除本地文件
    server/accounts.mjs:63
    if (attempt === 0 && dead) { await unlink(path); continue; }
  • 删除本地文件
    server/accounts.mjs:68
    return async () => { await handle.close(); await unlink(path); };
  • 发起网络请求
    server/accounts.mjs:137
    const { json } = await this.request(path, cookies, body);
  • 发起网络请求
    server/accounts.mjs:148
    await this.request(loginPage, cookies);
  • 发起网络请求
    server/accounts.mjs:150
    const { json } = await this.request('/passport/web/get_qrcode/?' + params, cookies);
  • 写入本地文件
    server/accounts.mjs:160
    await writeFile(qrPath, Buffer.from(data.qrcode, 'base64'), { mode: 0o600, flag: 'wx' });
  • 发起网络请求
    server/accounts.mjs:178
    let response = await this.request('/passport/web/check_qrconnect/?' + params, pending.cookies);
  • 发起网络请求
    server/accounts.mjs:182
    response = await this.request(redirect, pending.cookies);
  • 读取本地文件
    server/local-index.mjs:13
    const data = JSON.parse(await readFile(this.path, 'utf8'));
  • 写入本地文件
    server/local-index.mjs:25
    await mkdir(dirname(this.path), { recursive: true });
  • 写入本地文件
    server/local-index.mjs:26
    await writeFile(this.path + '.tmp', content, 'utf8');
  • 写入本地文件
    server/local-index.mjs:27
    await rename(this.path + '.tmp', this.path);
  • 发起网络请求
    server/local-index.mjs:33
    const state = initialState(await client.request('/'));
  • 发起网络请求
    build/FanQieApi.js:18
    this.axiosInstance = axios.create({
  • 读取密钥环境变量
    build/FanQieApi.js:24
    ...(process.env.FANQIE_API_TOKEN ? { Authorization: `Bearer ${process.env.FANQIE_API_TOKEN}` } : {})
  • 发起网络请求
    build/FanQieApi.js:268
    const response = await this.axiosInstance.request({ method, url: `/api/account/${action}`, params });
  • 读取本地文件
    server/accounts.test.mjs:42
    assert.ok((await readFile(login.qrcode_path)).length > 0);
  • 发起网络请求
    server/accounts.test.mjs:95
    await assert.rejects(client.request('https://example.com/steal', { sessionid: 'secret' }), e => e.kind === 'ACCOUNT_REDIRECT_DENIED');
  • 请求外部主机fanqienovel.com
    server/accounts.test.mjs:96
    await assert.rejects(client.request('https://user:secret@fanqienovel.com/', {}), e => e.kind === 'ACCOUNT_REDIRECT_DENIED');
  • 发起网络请求
    server/accounts.test.mjs:96
    await assert.rejects(client.request('https://user:secret@fanqienovel.com/', {}), e => e.kind === 'ACCOUNT_REDIRECT_DENIED');
  • 发起网络请求
    server/accounts.test.mjs:154
    assert.equal((await fetch(url)).status, 405);
  • 发起网络请求
    server/accounts.test.mjs:155
    assert.equal((await fetch(url, { method: 'POST', headers: { Origin: 'https://example.com' } })).status, 403);
  • 发起网络请求
    server/accounts.test.mjs:157
    assert.equal((await (await fetch(url, { method: 'POST' })).json()).data.account, 'alice');
  • 读取本地文件
    server/cli.test.mjs:36
    assert.ok((await readFile(join(installed, 'SKILL.md'), 'utf8')).includes('fanqie-novel'));
  • 发起网络请求
    server/core.test.mjs:36
    assert.equal((await fetch(url + '/health')).status, 401);
  • 发起网络请求
    server/core.test.mjs:37
    assert.equal((await fetch(url + '/health', { headers: { Authorization: 'Bearer test-secret', Origin: 'https://example.com' } })).status, 403);
  • 发起网络请求
    server/core.test.mjs:38
    const response = await fetch(url + '/health', { headers: { Authorization: 'Bearer test-secret' } });
  • 发起网络请求
    server/core.test.mjs:40
    const unsupported = await fetch(url + '/api/ios/register', { headers: { Authorization: 'Bearer test-secret' } });
  • 发起网络请求
    server/core.test.mjs:46
    assert.deepEqual(await Promise.all([client.request('/'), client.request('/')]), ['ok', 'ok']);
  • 发起网络请求
    server/core.test.mjs:62
    await assert.rejects(client.request('/', false, 'https://example.com'), e => e.kind === 'INVALID_ORIGIN');
  • 发起网络请求
    server/mcp.test.mjs:25
    const list = await mcp.request({ method: 'tools/list' }, ListToolsResultSchema);
  • 发起网络请求
    server/mcp.test.mjs:28
    const result = await mcp.request({ method: 'tools/call', params: { name, arguments: args } }, CallToolResultSchema);
  • 发起网络请求
    server/mcp.test.mjs:43
    const qr = await mcp.request({ method: 'tools/call', params: { name: 'start_account_login', arguments: { account: 'alice' } } }, CallToolResultSchema)
  • 读取密钥环境变量
    server/smoke.mjs:16
    const headers = process.env.FANQIE_LOCAL_TOKEN ? { Authorization: `Bearer ${process.env.FANQIE_LOCAL_TOKEN}` } : {};
  • 发起网络请求
    server/smoke.mjs:19
    const response = await fetch(base + path, { method, headers }); const data = await response.json();
  • 发起网络请求
    server/smoke.mjs:81
    const result = await mcp.request({ method: 'tools/call', params: { name: 'get_book_detail', arguments: { book_id: book } } }, CallToolResultSchema);
  • 发起网络请求
    server/smoke.mjs:84
    const pageResult = await mcp.request({ method: 'tools/call', params: { name: 'get_book_directory', arguments: { book_id: book, offset: 10, limit: 5 }
  • 发起网络请求
    server/smoke.mjs:88
    const reviewResult = await mcp.request({ method: 'tools/call', params: { name: 'get_comments', arguments: { book_id: book, count: 3 } } }, CallToolRes
  • 发起网络请求
    server/smoke.mjs:93
    const categoryResult = await mcp.request({ method: 'tools/call', params: { name: 'search_books', arguments: { key: tab_type === 8 ? '绝世武神' : '重生', tab
  • 发起网络请求
    server/transport.test.mjs:10
    assert.deepEqual(await Promise.all([client.request('/'), client.request('/')]), ['ok', 'ok']);
  • 发起网络请求
    server/transport.test.mjs:11
    assert.equal(await client.request('/'), 'ok');
  • 发起网络请求
    server/transport.test.mjs:22
    await assert.rejects(client.request('/'), e => e.code === 502 && e.kind === 'UPSTREAM_UNAVAILABLE');
  • 发起网络请求
    server/transport.test.mjs:36
    const response = await fetch(base + '/api/search?key=test');
  • 发起网络请求
    server/transport.test.mjs:54
    await assert.rejects(client.request('/', true), e => e.kind === expected);
  • 发起网络请求
    server/transport.test.mjs:69
    await assert.rejects(client.request('/'), e => e.kind === 'UPSTREAM_FORMAT');
扫描于 2026/11/4(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库
涉及外部主机:novel.snssdk.com、reading.snssdk.com、fanqienovel.com

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

番茄小说 MCP、独立 Skill 与 DeepSeek Harness 阅读插件,支持搜书、阅读官网可见章节,以及查看本人书架和收藏划线。

README

由 DeepSeek 最新模型翻译生成
番茄小说:MCP、独立技能与 DeepSeek Harness 阅读插件 搜索番茄作品、查看小说目录和网站可见正文、读取书评;本人扫码登录后,还可以读取自己的书架、阅读进度和收藏划线原文。 项目提供三种入口:MCP 服务、独立技能、DeepSeek Harness 图形插件,另有命令行和本地 HTTP API。各入口复用本机数据核心,直接访问番茄官方站点。 版本说明:MCP / 技能历史 Release 为 0.2.0-dev.6;DeepSeek Harness 插件为源码中的 0.4.0。旧 Release 不含该插件,应从当前仓库获取插件。 安装与使用 · Harness 插件 · 功能清单 · HTTP API · 历史 Release 当前插件尚未发布到 npm;旧 npm 包 @fysh925/mcp-server-fanqie 也不包含此开发预览版。请使用仓库源码或对应的历史 Release,不要用旧 npm 包判断当前功能。 三种使用方式 - MCP:为支持 MCP 的 AI 客户端提供番茄搜索、阅读和本人账号数据查询。当前开发预览版请按使用指南从源码或 Release 安装。 - 独立技能:在支持技能和 Node.js 22+ 的客户端中使用,技能目录包含独立运行文件。安装方法见使用指南。
展开完整文档(README 剩余 1 节)
番茄小说:MCP、独立技能与 DeepSeek Harness 阅读插件

搜索番茄作品、查看小说目录和网站可见正文、读取书评;本人扫码登录后,还可以读取自己的书架、阅读进度和收藏划线原文。

项目提供三种入口:MCP 服务、独立技能、DeepSeek Harness 图形插件,另有命令行和本地 HTTP API。各入口复用本机数据核心,直接访问番茄官方站点。

版本说明:MCP / 技能历史 Release 为 0.2.0-dev.6;DeepSeek Harness 插件为源码中的 0.4.0。旧 Release 不含该插件,应从当前仓库获取插件。

安装与使用 · Harness 插件 · 功能清单 · HTTP API · 历史 Release

当前插件尚未发布到 npm;旧 npm 包 @fysh925/mcp-server-fanqie 也不包含此开发预览版。请使用仓库源码或对应的历史 Release,不要用旧 npm 包判断当前功能。

三种使用方式

- MCP:为支持 MCP 的 AI 客户端提供番茄搜索、阅读和本人账号数据查询。当前开发预览版请按使用指南从源码或 Release 安装。
- 独立技能:在支持技能和 Node.js 22+ 的客户端中使用,技能目录包含独立运行文件。安装方法见使用指南。
- DeepSeek Harness 插件:在右侧栏搜索、查看封面和目录、阅读网站可见章节;本人扫码后查看书架和收藏划线,并提供对话工具。详见插件文档。

DeepSeek Harness 插件是独立包 dsh-fanqie-reader;它与上文提到的 MCP 包 @fysh925/mcp-server-fanqie 是不同的 npm 包。插件当前支持的媒体范围和账号使用方式见插件文档。

为什么重做:从第三方服务迁移到本地实现

旧版 0.1.x 的主要职责是把第三方服务封装成 14 个 MCP 工具,默认请求 http://101.35.133.34:5000。搜索、目录、正文和设备管理等能力由该第三方服务器提供。第三方地址不可用后,MCP 工具虽然仍能列出,实际查询也会随之失效。

本次把数据获取实现放进项目本身:

- 本地实现公开查询:搜索、书籍详情、目录、网站可见章节、书评正文,直接访问官方入口。
- 提供 MCP、独立技能和 Harness 插件:三种入口复用核心;技能可以独立运行,Harness 插件提供图形界面和对话工具。
- 新增本人账号能力:扫码登录、当前书架、云端阅读位置、收藏划线原文及翻页。
- 补齐使用与错误处理:目录分页、分类搜索游标、完整书评文本、故障重试、限流提示及本地索引后备。
- 明确能力边界:保留旧路径方便迁移,未实现的功能返回 501;不把工具名称还存在当作功能已经完成。

本版解决的是旧第三方 API 这一中间依赖,仍需要联网访问番茄官方站点。官方接口、网页结构、字体或匿名设备规则变化后,仍可能需要维护。

对比旧第三方服务:本次实现了什么

「旧版范围」以仓库 0.1.x 的 README 和 API 封装为依据,只说明当时声明或转发了什么,不代表现在还可验证旧服务,也不保证新旧返回字段逐项相同。

| 能力 | 旧版第三方依赖范围 | 当前 MCP | 当前技能 | 本版实际行为与边界 |
| 小说关键词搜索 | 转发第三方搜索 | 支持 | 支持 | 官方免签名搜索,支持 offset 翻页 |
| 听书搜索 | 转发第三方分类搜索 | 支持 | 支持 | 官方 App 只读搜索,本地生成签名 |
| 漫画搜索 | 转发第三方分类搜索 | 支持 | 支持 | 仅搜索与基本元数据;可能混入推荐 |
| 短剧搜索 | 转发第三方分类搜索 | 支持 | 支持 | 仅搜索与基本元数据;支持 cursor 翻页 |
| 小说详情 | 转发第三方详情 | 支持 | 支持 | 从官网页面数据提取规范化字段 |
| 分卷目录 | 转发第三方完整目录 | 支持 | 支持 | 默认每页 50 章,上限 200 章 |
| 简化目录 | 转发第三方简化目录 | 支持 | 使用 directory | MCP/API 可只返回标题与 ID |
| 单章小说正文 | 转发第三方内容 | 部分支持 | 部分支持 | 网站可见正文;不保证与 App 全文一致 |
| 批量小说正文 | 转发第三方批量接口 | 支持 | 支持 | 每批最多 20 章,逐章校验书籍归属 |
| 原始章节数据 | 转发第三方原始内容 | 支持 | 支持 | 官网章节字段及解析正文 |
| 书评正文与翻页 | 旧文档声明评论列表 | 支持 | 支持 | 保留正文、评分、点赞、回复数及 cursor;这里只读取整本书的书评 |
| 章评、段评、楼中楼正文 | 旧文档对评论范围有宽泛描述 | 未实现 | 未实现 | 不把书评当作其他评论类型 |
| 听书音频播放 | 旧统一内容接口声明支持 | 未实现 | 未实现 | 搜索可用,音频内容未接入 |
| 短剧视频播放 | 旧统一内容接口声明支持 | 未实现 | 未实现 | 搜索可用,视频内容未接入 |
| 漫画图片、下载任务与进度 | 旧统一内容与任务接口声明支持 | 未实现 | 未实现 | 任务进度兼容入口返回 501 |
| 整本下载 | 旧统一内容接口声明支持 | 未实现 | 未实现 | 可按目录批量查询,未提供整本任务或导出 |
| Android 设备注册、设备池 | 旧版依赖服务端设备管理 | 未实现真实管理 | 无命令 | 两个状态工具只返回网页模式说明;注册返回 501 |
| iOS 注册及专用正文 | 旧版依赖 iOS 服务 | 未实现 | 无命令 | 保留接口,返回 501 |
| 本人扫码登录与本地退出 | 原 14 个工具未提供 | 新增 | 新增 | 手机本人确认,凭据只保存在本机 |
| 本人书架及阅读位置 | 原 14 个工具未提供 | 新增 | 新增 | 当前书架、云端可用阅读记录及当前章节 |
| 有收藏的书及数量 | 原 14 个工具未提供 | 新增 | 新增 | 划线数、书签数、笔记数 |
| 本人收藏划线原文 | 原 14 个工具未提供 | 新增 | 新增 | 原文、章节、位置、修改时间与 cursor 翻页 |
| 独立撰写的笔记/想法正文 | 原 14 个工具未提供 | 未实现 | 未实现 | 可读笔记数量,尚不读取笔记正文 |
| 本地元数据索引 | 原 14 个工具未提供 | 无专用工具 | 新增 | 通过命令行/API 导入和刷新,小说搜索故障时明确标记降级 |

结论:本版覆盖了公开搜索、书评、小说网站阅读和个人阅读数据的当前需求,并未完整复刻旧服务的音视频、漫画内容、设备池、iOS 或整本下载能力。

当前 MCP 与 Skill 能调用哪些方法

以下 Skill 命令均由技能目录内的 scripts/fanqie.mjs 执行。源码用户可使用 node "server/cli.mjs" <命令>。

公开查询,无需账号登录

| MCP 工具 | Skill/命令行命令 | 用户可以做什么 |
| search_books | search | 搜索小说、听书、漫画、短剧;关键词与分类保持不变继续翻页 |
| get_book_detail | detail | 查看书名、作者、简介、字数及最新章节等 |
| get_book_directory | directory | 分页查看含分卷信息的章节目录 |
| get_simple_directory | 无独立命令,可使用 directory | 获取简化的章节标题、ID 列表 |
| get_chapter_content | chapter | 读取一个网站可见章节 |
| get_content | chapter / batch | 统一单章与批量正文入口,每批最多 20 章 |
| get_raw_content | raw | 查看原始章节数据及解析后的正文 |
| get_comments | comments | 获取整本书的书评正文、评分、点赞数和回复数 |

本人账号,需要扫码授权

| MCP 工具 | Skill/命令行命令 | 用户可以做什么 |
| start_account_login | login-start | 获取本人登录二维码 |
| poll_account_login | login-poll | 检查扫码、确认和登录完成状态 |
| get_account_status | account-status | 检查本地账号登录是否有效 |
| get_my_bookshelf | bookshelf | 查看当前官方书架及已同步的阅读位置 |
| get_my_reading_progress | reading-progress | 查看云端阅读记录、书名、当前章节,可筛选一本书 |
| get_my_highlight_books | highlight-books | 查找有收藏记录的书及划线、书签、笔记数量 |
| get_my_highlights | highlights | 分页读取自己收藏的划线原文及位置 |
| logout_account | logout | 清除本机该配置的凭据,不更改官方书架、进度或收藏 |

辅助与兼容方法

| MCP 工具 | Skill/命令行命令 | 实际作用 |
| 无 | index-import | 从官网录入指定书籍的元数据 |
| 无 | index-refresh | 刷新官网首页可发现的书籍索引 |
| 无 | capabilities | 查看当前能力清单 |
| 无 | help | 显示命令和参数帮助 |
| get_device_pool_status | 无 | 返回网页模式说明,不管理真实设备池 |
| get_device_status | 无 | 返回网页模式说明,不验证真实 App 设备 |
| register_device | 无 | 尚未实现,返回 501 |
| get_ios_content | 无 | 尚未实现,返回 501 |
| register_ios_device | 无 | 尚未实现,返回 501 |
| get_manga_progress | 无 | 尚未实现,返回 501 |

MCP 共注册 22 个工具,其中 16 个公开查询/本人账号工具、2 个状态兼容工具、4 个未实现工具。Skill/命令行有 19 个命令,含 help 和 capabilities。Harness 插件另注册 7 个 fanqie_ 对话工具,并提供图形界面;它们与 MCP 的 22 个工具不是一一对应。参数、HTTP 路径及边界见 完整清单。

我们如何实现

旧版调用链是「AI 客户端 → MCP 封装 → 第三方开放 API → 数据」。本版默认调用链如下:

flowchart TD
A[支持MCP的AI客户端] --> B[MCP工具层]
B --> C[自动启动的本机HTTP API]
D[Skill或终端CLI] --> E[共享数据核心]
P[Harness右侧栏与对话工具] --> Q[插件Host]
Q --> E
F[其他本机程序] --> C
C --> E
E --> G[公开查询客户端]
E --> H[本人账号客户端]
G --> I[番茄官网网页与目录接口]
G --> J[官方小说搜索接口]
G --> K[官方App搜索与书评接口]
G --> L[本地元数据索引后备]
H --> M[官方扫码登录与账号接口]
H --> N[本机用户目录中的账号凭据]

数据来源与处理方式

| 模块 | 实现方式 | 主要代码 |
| 小说搜索 | 请求官方 novel.snssdk.com 轻量搜索;失败时尝试官网后备和有限本地索引;降级结果明确标记范围 | server/core.mjs、server/local-index.mjs |
| 听书/漫画/短剧搜索 | 请求 reading.snssdk.com/reading/bookapi/search/tab/v,按book_data/video_data解析类别;保留官方推荐标记与翻页游标 | server/app.mjs、server/core.mjs |
| 书评正文 | 请求官方commentapi只读列表,保留完整文本和分页会话;不在客户端截断正文 | server/core.mjs、server/app.mjs |
| 本地请求签名 | 使用Node原生加密实现签名,无需公共签名服务;MIT来源及许可随包附带 | server/sign.mjs、第三方说明 |
| 小说详情 | 读取官网页面的JSON初始数据,直接解析,不执行页面脚本 | server/core.mjs |
| 目录和网站正文 | 目录走官网接口;章节提取可见数据,使用已知字体映射转换字符;锁定、未知字体或残余乱码明确报错 | server/core.mjs、src/fontDecrypt.ts |
| 扫码与会话 | 官方二维码、本人手机确认、手动保留跳转中的Cookie;成功后验证阅读进度接口,凭据持久化到本机 | server/accounts.mjs |
| 书架与进度 | 读取官方书架和进度,再按book_id关联书籍详情、章节标题;保留上游进度值,不猜测百分比 | server/accounts.mjs |
| 收藏划线 | 先列出有收藏的书,再读取官方bookmark列表;初次带next_id=0,后续cursor同时携带两项上游分页标记;区分划线和普通书签 | server/accounts.mjs |
| 三种入口复用 | MCP通过本地API调用核心;Skill和Harness插件分别使用同步的核心运行文件,可独立安装 | src/、scripts/build-skill.mjs、plugins/deepseek-harness/ |

小说公开搜索不需要签名或本人登录。书评与App分类搜索使用匿名设备参数和本地签名,内置公共示例设备可能失效,可配置配套的 FANQIE_DEVICE_ID、FANQIE_INSTALL_ID;不会自动注册设备或激活会员。个人书架和划线使用本人扫码的会话,与匿名设备配置是两条独立链路。

稳定性和数据边界

- 公开上游请求串行处理,最小间隔500毫秒,同一请求合并;缓存最多100项、有效期5分钟。网络中断或502/503/504最多重试一次,限流时返回等待时间。
- 个人响应不进入公开查询缓存,按本地账号配置分别存储;同一账号跨进程使用文件锁。账号请求不自动重试。
- 账号凭据默认在系统用户数据目录,可用 FANQIE_ACCOUNT_DIR 指定;不写入技能目录、源码仓库或发布包。不同系统不保证文件加密,请使用自己的受保护用户目录。
- 书架是当前书架,阅读进度是官方当前返回的云端记录;缺少进度不能推断从未读过。read_progress不直接当作百分比。
- 只有 has_more=false 才结束划线翻页。上游分页同时计算书签等记录,某页没有划线也可能还有下一页。
- HTTP API仅监听本机,拒绝浏览器Origin及非本机Host,可选Bearer Token;账号接口不面向公开部署或多租户服务。

安装:选择适合的入口

| 入口 | 前置要求 | 是否手动启动API |
| MCP | Node.js 22+、项目npm依赖、支持MCP的客户端 | 不需要,自动启动随机本地端口API |
| 独立Skill | Node.js 22+、支持Skills且能执行本地脚本的客户端 | 不需要,直接运行核心代码 |
| DeepSeek Harness 插件 | 支持插件的 Harness 桌面端;已记录 0.2.1-rc.5 的桌面验证 | 不需要,插件 Host 调用内置核心 |
| CLI | Node.js 22+和完整代码 | 不需要 |
| HTTP API | Node.js 22+和项目依赖 | 单独启动,默认127.0.0.1:5000 |

DeepSeek Harness:图形界面与对话工具

1. 克隆或下载当前仓库,保留完整的 plugins/deepseek-harness/ 目录,包括 vendor/。
2. 在 Harness 的插件管理页选择该目录安装,或在会话中让智能体通过 plugin_manager install_bundle 安装该目录的绝对路径。
3. 按需刷新或重启 Harness,打开右侧栏的「+」开始页,选择「番茄阅读」。
4. 在界面搜索、浏览目录和阅读;查看本人书架与划线时,在「我的」页面按官方提示扫码。

插件还提供7个 fanqie_ 对话工具。它与 MCP/Skill 可分别使用,账号凭据默认沿用核心的本机存储方式;具体路径可能因打包环境而不同。安装与卸载详见 插件文档。插件目前未发布到 npm,历史 0.2.0-dev.6 Release 也不含它。

独立Skill:无需npm依赖

1. 下载 fanqie-novel-skill-0.2.0-dev.6.zip。
2. 将整个 fanqie-novel 文件夹放入客户端的技能父目录。Codex示例为Windows的 $HOME/.agents/skills/,macOS/Linux的 ~/.agents/skills/;其他客户端使用其支持的目录。
3. 确认 fanqie-novel/SKILL.md 和 fanqie-novel/scripts/runtime/ 都存在,不能只复制说明文件,也不要多套一层同名目录。
4. 重新加载技能或重启客户端,输入:$fanqie-novel 搜索《三体》,核对作者并查看前20章目录。

Skill ZIP包含全部必需运行代码;不需要另外安装Python、浏览器、npm包或启动MCP服务。仍需联网访问官方站点。

从克隆仓库安装Skill也可以,无需先安装npm依赖:

sh
node "scripts/install-skill.mjs" --target "$HOME/.agents/skills"

支持 GitHub 路径的技能安装器可安装 fysh1010/mcp-server-fanqie 仓库的 skills/fanqie-novel 目录。更新时先备份或重命名原技能文件夹,安装脚本不会覆盖已有目录。

MCP:从源码或源码 ZIP 安装 sh
git clone https://github.com/fysh1010/mcp-server-fanqie.git
cd mcp-server-fanqie
npm ci
npm run build

也可从 Release 下载源码 ZIP,解压后在仓库根目录执行 npm ci 和 npm run build。

支持 mcpServers 格式的客户端可使用以下 JSON 配置;其他客户端按其 MCP 配置格式填写相同 command 和 args: json {
"mcpServers": {
"fanqie": {
"command": "node",
"args": ["D:/你的路径/mcp-server-fanqie/server/mcp-local.mjs"]
}
}
}

将 args 改为本机真实绝对路径。macOS/Linux 填写对应的 /Users/... 或 /home/... 路径。若客户端找不到 node,将 command 改为 Node 可执行文件的绝对路径。重新加载 MCP 连接后即可搜书,无需先运行 start:api。

Release 也提供本地 npm 安装用的 .tgz;安装步骤见 使用指南。不要把旧 npm 包名的 npx 配置当作本版安装方法,也不要将本机路径填写到无法访问本机文件的云端托管环境。

使用:可以直接告诉 AI 什么

无需登录

- “搜索《三体》,核对作者,查看前 20 章目录。”
- “读取这本书第三章,概括情节。”
- “获取这本书 20 条书评,整理读者评价。”
- “搜索带‘重生’的短剧,再看下一页。”

CLI 也可以直接运行: sh
node "server/cli.mjs" search "三体"
node "server/cli.mjs" search "绝世武神" --type manga
node "server/cli.mjs" search "重生" --type drama
node "server/cli.mjs" comments "7143038691944959011" --count 20
node "server/cli.mjs" directory "7143038691944959011" --offset 0 --limit 20

本人书架、阅读进度与收藏划线

1. 告诉 AI:“连接我的番茄账号,让我扫码。”AI 调用 start_account_login 或 Skill 的 login-start 并展示二维码。
2. 按二维码返回的官方提示,用本人已登录的手机 App 扫码并确认;当前官方可能提示使用抖音 App,以实际说明为准。
3. AI 每隔至少 3 秒检查登录结果,status=connected 才算完成。二维码约 5 分钟有效,过期重新生成。
4. 先说“查看我的书架”,核对是否对应自己的番茄账号。
5. 再说“列出我有划线的书,读取其中一本的全部收藏划线,按章节整理”。AI 会使用 cursor 翻页。
6. 要清除本机登录时,说“断开我的番茄账号”。

MCP 和 Skill 在相同系统用户、相同账号目录配置下可共用登录状态。多账号使用不同 account 本地配置名,并分别扫码。账号名不是平台用户 ID,不能凭别人的 ID 读取私人数据。不要把密码或 Cookie 发送到聊天里。

终端用户使用 login-start → login-poll → bookshelf / reading-progress / highlight-books / highlights;可运行示例、分页字段和退出说明见 详细使用指南。

独立 HTTP API sh
npm run start:api

默认地址为 http://127.0.0.1:5000。示例: powershell Invoke-RestMethod "http://127.0.0.1:5000/health" Invoke-RestMethod "http://127.0.0.1:5000/api/search?key=三体" Invoke-RestMethod "http://127.0.0.1:5000/api/account/status?account=default"

成功返回 { "code": 200, "message": "success", "data": ... },失败同时使用真实 HTTP 状态码及业务码。接口清单、参数、Token 和端口配置见 HTTP 文档。

更新、排错与验证

- 更新源码 MCP:确认自己已保存本地修改,再执行 git pull --ff-only、npm ci、npm run build,重新加载 MCP 连接。
- 更新 Skill:先备份或重命名旧技能目录,再解压新 ZIP 或运行安装脚本;重新发现技能。不要只更新 SKILL.md。
- 401 或账号过期:重新扫码,不把失败结果当成空书架。
- 403 章节权限错误:官网未提供可读权限,当前实现无法读取。
- 429 限流:按响应的 retry_after 提示等待;账号接口未返回等待秒数时稍后重试,勿循环请求。
- 409 ACCOUNT_BUSY:同一账号正在处理另一请求,完成后再试。
- 503 LOCAL_BUSY:公开请求队列繁忙,减少并发后重试。
- 评论/分类搜索匿名设备失效:配置配套的 FANQIE_DEVICE_ID、FANQIE_INSTALL_ID;本人扫码登录与该匿名设备配置无关。
- 搜索结果 source=local_index:只表示有限本地索引,不能推断全站没有该书。

构建与离线测试: sh
npm run build
npm test

当前 34 项离线测试覆盖解析、权限、字体、分页、签名、限流、账号隔离、登录跳转、划线游标、MCP 调用与独立 Skill 安装。node "server/smoke.mjs" 额外执行少量公开样本在线验证;个人账号功能另经本人扫码实测,公开测试和仓库示例不包含真实账号凭据或私人划线。
历史协议实验单独记录在 EXPERIMENTS.md。实验成功不代表对应能力已经集成本版。依赖审计与发布验证信息见本版 Release 说明。

项目结构与许可 text src/ MCP工具定义、客户端封装、字体映射 build/ 已编译MCP代码 server/ 公开数据核心、账号核心、HTTP与CLI、测试 skills/fanqie-novel/ 可独立安装的完整Skill scripts/build-skill.mjs 从共享核心生成Skill运行文件 scripts/install-skill.mjs 安装完整技能目录,不覆盖已有安装 docs/USAGE.md 详细安装、登录、分页和排错 docs/FUNCTIONS.md 全部能力、MCP/Skill/HTTP方法对照

修改核心后执行 npm run build 同步 Skill 运行文件;无需维护第二套爬虫。运行使用 Node.js 22+,Python 仅用于开发者打包 ZIP,不是用户运行依赖。

MIT。本项目为非官方工具,内容版权归原平台及权利人所有。本地签名代码的 MIT 参考来源与许可见 第三方说明,相关许可证随独立 Skill 分发。

Star History

下图展示本仓库 GitHub Star 数量随时间的变化,点击可打开交互页面。图表由 Star History 生成。
预览分享卡片长什么样 ↓fysh1010/mcp-server-fanqie
分享 · DeepSeek Harness Hub
fysh1010/mcp-server-fanqie

搜书读章节,登录后看书架与收藏划线

这是你的仓库?认领条目

回到顶部