内容
# 阅读书源 MCP
本机 **Legado 运行时 + MCP Server**(原「书源工坊」)。App 内不调用任何模型、不保存任何模型密钥。书源的制作、修复和调试全部由外部 MCP 客户端完成。
- 包名:`com.mina.legadostudio`
- 当前版本:`1.1.003`(versionCode 182)
- 许可证:GPL-3.0
- 上游致谢:DandanLLab/legadoSkill、LegadoTeam/legado
- 下载:[Releases](https://github.com/Mina-kk/yuedu-MCP/releases)(每个版本附带已签名 APK)
## 界面
iOS 简约白风格:液态玻璃顶栏/底栏(高斯模糊)、大圆角卡片、底部悬浮标签栏。底栏为 **MCP / 书源 / 技能 / 验证中心 / 日志**。
验证中心运行时提供圆形 **M** 字悬浮球:可自由拖动到任意位置,松手时若靠近屏幕左右边缘会自动吸附并半隐一半(点按展开);人工验证 alert 气泡弹出时自动贴边完整显示,不打断当前 App 操作。
## 连接 MCP
MCP 页分三个页签:**连接**(服务开关 / 接入信息 / 健康检查)、**设置**(端口、令牌、书源类型、外观)、**前置条件**(通知、电池策略、端口占用等)。
1. 底栏 **MCP** →「连接」页签开启服务(默认端口 **58823**)
2. 「接入信息」卡按你的客户端界面形态给出对应填法,每一项都可一键复制:
- **服务器链接(所有客户端)**:`http://127.0.0.1:58823/mcp`;客户端不在同一台设备时切「局域网」,使用 `http://<局域网IP>:58823/mcp`
- 客户端有 **Token / Bearer Token 输入框** → 只粘贴令牌本身,不要加 `Bearer` 前缀
- 客户端只有 **自定义请求头(名称 + 值)两个框** → 名称填 `Authorization`,值填 `Bearer <令牌>`(名称填成 `Bearer` 是常见错误,会 401)
- 客户端没有任何鉴权输入 → 在「设置」页关闭访问令牌校验,或换用支持鉴权的客户端
- **「配置文件客户端(高级)」折叠卡**:标准 `mcpServers` JSON(Claude Code / Cline / Cherry Studio 等)整段复制
3. 鉴权统一使用 MCP 规范的标准头:**`Authorization: Bearer <令牌>`**
4. 调用 `get_app_info`,应返回 `"ai": false`、`"role": "mcp-runtime"` 与语料库信息
### 书源类型开关
MCP 页可选择目标书源类型:**自动 / 文本 / 音频 / 图片 / 文件 / 视频**(对应 Legado `bookSourceType` -1、0–4)。
- `save_source` 保存书源时自动写入所选类型;选「自动」时不写入,保留 JSON 原样;
- `fetch_page` 按类型过滤二进制内容:文本类型跳过图片/音视频/压缩包等二进制响应(返回 `bodyNote`/`binaryBytes` 说明),非文本类型保留对应媒体内容;「自动」不干预抓取,适合图文漫画混合等类型不确定的站点。
## MCP 工具一览
| 分组 | 工具 |
|---|---|
| 语料 / 知识 / 技能 | `match_sources` `get_corpus_source` `get_corpus_shard` `search_knowledge` `read_knowledge` `list_skills` `get_skill` `get_skill_reference` |
| 任务上下文 | `create_context` `get_context` `list_contexts` `update_context` `clear_context` `read_page` `read_result` |
| 抓取与解析 | `fetch_page` `analyze_html` `inspect_rule` `eval_js` |
| 书源 | `validate_source` `list_sources` `get_source` `save_source` `export_source` `debug_source` `check_source` `list_projects` `get_project` `delete_projects` |
| 验证与 Cookie | `browser_verify` `get_verification_status` `get_domain_modes` `set_domain_mode` `get_cookies` `set_cookie` `clear_cookies` |
| 状态与日志 | `get_app_info` `app_status` `set_http_log_recording` `get_http_logs` `get_http_log` `get_logs` `get_log` `get_crash_logs` `get_crash_log` `get_diagnostic_snapshots` `get_diagnostic_snapshot` `capture_once` `webview_capture` `list_captures` `get_capture` `poll_capture` `get_capture_resource` |
## 制作流程
```
match_sources 语料命中(同域/同模板族现成书源)
→ create_context 建任务,全程显式传 contextId
→ fetch_page 抓页存快照;read_page / inspect_rule / analyze_html / eval_js 在快照上作业
→ 编写 BookSource JSON → debug_source 逐阶段调试(正文→目录→详情→搜索→发现)
→ check_source(refresh=true) 全程实时验收
→ save_source 保存,get_source 回读确认
```
`save_source` 默认按书源 URL 覆盖更新同站记录;需要保留历史版本时传 `newVersion=true` 追加。技能包 `legado-book-source` 内置完整工作流与参考文档:`get_skill` 读主文件,`get_skill_reference` 分页读参考(语料 / 验证 / 基础 / 排障 / JS API 等),`search_knowledge` → `read_knowledge` 查验证码、编码、Web JS 逆向(方法论 / 入门 SOP / 进阶对抗 / 书源迁移四篇专题)等知识库;另附《书源 JS 入门教程》知识包(零基础语法到书源 `<js>` 实战),技能参考文档同步收录。
### eval_js 与书源 JS 环境
`eval_js` 与书源 `<js>` / `{{}}` 段运行在 vendored 官方 Rhino + analyzeRule 引擎上,除 `java`(ajax/connect/加解密)外还注入官方同名对象:`cookie`(`getCookie`/`getKey`/`setCookie`/`replaceCookie`/`removeCookie`)、`cache`(`put`/`get`/`delete`/`putMemory`/`getFromMemory`,进程内有效)、`source`(`put`/`get`/`getVariable`/`setVariable`,`debug_source` 时与书源变量互通)。`java.getStringList(...)` 返回真正的 JS `Array`(可 `.length` / `.map` / 下标访问),与官方阅读一致。规则链路全程保留元素对象:CSS/XPath 子规则在列表元素自身上求值,裸 `@attr`(如 `chapterUrl: "@href"`)取当前节点属性;多段落 `@text` 按官方语义 join 全部段落。
`set_cookie` 默认 `merge=true` 按 Cookie 名合并(不会冲掉该域其他 Cookie,如登录态),`merge=false` 为整串替换。
### 验收闭环
`validate_source` 检查联动完整性:`searchUrl` 必须配 `ruleSearch.bookList`、`exploreUrl` 必须配 `ruleExplore.bookList`,缺一直接判非法。`check_source` 在书源含 `searchUrl` 而未传 `searchKey` 时,自动用关键词「我」探测搜索链路并在 `warnings` 标注——搜索结果页结构与列表页常常是两套 DOM,漏验会导致真机搜索零结果;正式验收请显式传 `searchKey` 并配 `refresh=true`。
### 语料命中(省 token 第一步)
内置 **26861 个现成书源**,按内容规则签名聚成 **1838 个模板族**(同族 = 同 CMS / 同模板结构):
- `match_sources(域名或站名)`:返回 `i`(序号)、`d`(域名)、`f`(族 ID)、`t`(类型)、`g`(特征位掩码:CookieJar / 登录 / 验证码 / Cloudflare / 禁用等);
- 命中同域 → `get_corpus_source(i)` 取完整书源做底本最小修改;
- 未命中同域 → `get_corpus_shard(f)` 读同族 ≤6 个最完整代表样例,参考结构改写;
- 都未命中才走 `fetch_page` 探索。语料样例改写通常比抓页探索省一个数量级调用。
### 验证中心(验证码 / CF / WAF)
遇到站点验证时,MCP 工具返回结构化 JSON 而不是裸错误,按 `status` 行动:
| status | 含义与行动 |
|---|---|
| `verification_required` | 需要人工验证:`browser_verify(url, waitSec=90)` 阻塞等待用户在验证中心完成,完成后自动取证并返回 `evidence`;随后重试原工具 |
| `webview_mode_enabled` | 该域已自动切换 WebView 抓取(`fetch_page` 已原地重试一次,`autoRetried=true` 时本次即成功结果) |
- 每域验证模式:`get_domain_modes` / `set_domain_mode(domain, auto|always|webview)`。**`always` 适合「一搜一验、URL 次次不同」的站点**——这类站点缓存 Cookie 无效,每次都走人工验证;验证完成但 `evidence.marker` 仍非空说明每次访问都要验,同样设 `always`。
- 同一域的等待中验证会话自动复用,不会重复创建。
- WebView 通道的 Cookie 与 OkHttp 通道 TLS 指纹不一致(如 `cf_clearance`):系统对被 JS 盾拦截的站点自动改用 WebView 通道抓取,而不是把无效 Cookie 灌进规则。
- 成品源在官方阅读 App 内过盾靠书源 `loginCheckJs` + `java.startBrowserAwait`,与调试期验证中心互补。
#### 图文验证码(image_code)
部分站点在搜索/详情页弹出**纯图片验证码**(输字符进框,非滑块/点选)。这一链路已闭环:
- 书源 JS 内 `java.getVerificationCode(imageUrl)` 会挂起当前调用:App 把图片下载回本地,在验证中心弹出「看图输字符」会话,用户输入答案后自动把答案写回、原 JS 继续跑;
- MCP 侧 `browser_verify(url, imageUrl=...)` 同样可发起 image_code 会话(直接传验证码图 URL,不必先走网页);`get_verification_status` 轮询到 `answered` 后取 `answer` 字段;
- image_code 会话**不采 Cookie**(图片验证不建立登录态),验证中心按 `kind` 区分 image_code / challenge 两类入口,UI 分别渲染「图片+输入框」与「WebView 内嵌页」。
### 并行多书源
同时制作多个书源时:
- 每个任务各自 `create_context` 并全程显式传 `contextId`,任务间缓存、引用、笔记完全隔离;
- 未传 `contextId` 时使用**每条 MCP 连接各自的默认上下文**,多客户端同时连接不会串数据;
- 调试缓存按调用传入(无全局锁),多个书源可同时 `debug_source` 而不互相等待;
- 书源页「导入至阅读」支持最多 **4 个书源同时排队待导入**,新导入不会顶掉尚未被阅读拉取的端点。
## 书源与技能
书源页按站点域名分组,组内按保存时间倒序展开。每个书源版本支持点击查看格式化 JSON 详情(全屏独立滚动、支持文本自由选中复制),并在版本操作栏提供「复制源」一键写入剪贴板及「导入至阅读」。技能页可查看内置 Skill 并控制启用/停用(停用后对 MCP 不可见);自定义 Skill 支持新增、导入、导出和删除。`save_skill` / `delete_skill` 不能改写内置 Skill。
## 日志与诊断
底栏 **日志** 分五段:操作日志 / HTTP / 抓包 / 崩溃 / 诊断快照。可多选删除。
- 操作日志与 HTTP 日志均采用吸顶日期切换栏(一天一页),支持左右按天翻看与弹窗跳选日期;
- HTTP 记录含时间、状态码与耗时;自动过滤本地回环与私网探测流量,点击进入全屏详情页(请求/响应头、正文、重定向链),详情页内滚动与列表互不影响,系统返回键只关闭详情、回到列表;打开详情时隐藏底部标签栏;
- HTTP 列表停留在顶部时自动跟随最新记录,翻历史时不被打断;
- **「抓包」页签是三个独立页的入口**:「逐次抓包」表单发一次请求并看逐跳结果;「浏览器抓包」是可见可交互的 WebView;「抓包会话历史」按 `cap:contextId` 分组持久化(逐次/可见浏览器/无头 webview 三类,重启可回看),分页加载 + 按抓包 ID 全库精确查找;该页并可开关 HTTP 事务记录;抓包事务不进入 HTTP 标签、不参与锚点分桶与按天导出;
- 抓包引擎对 `application/octet-stream` 等无明确 MIME 的响应用**魔数嗅探**(PNG/JPEG/GIF/WebP/WOFF/WOFF2/zip 等)自动归类,字体/封面图落盘为二进制资源而不是文本乱码;
- 操作日志与 HTTP 日志支持**按天导出为文本**(经系统分享发给电脑/AI 排查),导出含请求/响应头与正文;
- 诊断快照只含版本、MCP 状态和前置条件,不含 HTTP 或崩溃正文。
排查请用 MCP:`get_logs` / `get_log` / `get_http_logs` / `get_http_log` / `get_crash_logs` / `get_crash_log` / `get_diagnostic_snapshots` / `get_diagnostic_snapshot`。
抓包取证链路(`cap:` 会话,与上述普通 HTTP 日志隔离):`capture_once` 发单次请求并逐跳记录重定向(中间跳为 `originKind=capture_hop`);`webview_capture` 一次性无头 WebView 抓包(OkHttp 供给/观察证据,非 WebView 原生网络栈抓包;跑完即销毁、不可交互);用户在「浏览器抓包」页的可见交互会话同样以 `cap:contextId` 入库。AI 侧读取:`list_captures` 找会话(`kind` 如实区分逐次/可见浏览器/无头/未知)→ `get_capture(contextId)` 分页回看,活会话 `poll_capture(contextId, afterLogId)` 增量拉新 → `get_http_log(id)` 看单条详情 → 字体/图片等落盘二进制用 `get_capture_resource(logId)` 分片读取。日志与摘要含完整 URL/query,可能带令牌等敏感参数,分享前请自行检查。
构建说明见 `BUILDING.md`。
## 任务上下文
使用 `create_context` 创建任务,后续调用传入 `contextId`。`fetch_page` 保存网页并返回 `pageId`;相同 method+URL+body(**含 POST 搜索**)在 5 分钟内复用快照,只返回引用。正文通过 `read_page` 分段或搜索,也可直接交给 `inspect_rule`、`analyze_html`、`eval_js`(传 `pageId` 即可,免传 HTML)。工具结果超过 12000 字符自动转 `resultId` + 预览,用 `read_result` 分段取回,不重复执行原工具;`list_contexts` 可列出当前任务与占用,不返回正文。
`update_context` 保存阶段笔记,重连后使用 `get_context` 恢复目录与进度,完成后 `clear_context`。上限 **16 个任务**(LRU 兜底:满员时自动回收最久未用的空闲任务,不顶掉正在被引用的)、每任务 32 项 / 200 万字符 / 单项 100 万字符;快照 5 分钟内新鲜、闲置 30 分钟过期。上下文持久化到应用私有目录(memory + snapshot):进程重启后自动恢复,但恢复条目标记 `stale`,先 `refresh=true` 刷新再依赖其内容。MCP 令牌、User-Agent 或书源类型变化会使旧引用失效;它不自动读取、总结或裁剪客户端的聊天历史。
`fetch_page` 支持 `responseMode=reference`(不回传正文,仅存快照)与 `maxChars`(预览大小)进一步省流量;`debug_source` / `check_source` 默认复用本任务快照,**最终验收传 `refresh=true` 全程实时**;调试输出有意截断(正文 4000 字符、目录 20 章、搜索 10 条等),均带全量计数字段。
MCP 会话按 `Mcp-Session-Id` 统计:`clientCount` 只计最近 60 秒内发生过**真实工具调用**的活跃会话(客户端保活/心跳流量不计入),任务停止后自动掉出计数。会话活跃度只由真实工具调用刷新:闲置超过 `reapIdleSeconds`(默认 1800 秒)即由 `McpSessions` 主动关闭释放(客户端再请求会收到 404 并重新握手),不再长期占用。`app_status` 同时返回 `sessionTotal`(累计建立)、`sessionClosed`、`sessionReaped`(已回收)、`reapIdleSeconds`。
连接信息
猜你喜欢
暂无推荐服务器