Skip to main content
Glama
HJLiyu
by HJLiyu
README.md
# QQ File MCP

**在 Codex 中查找 QQ 群资料、读取原生群作业和聊天补充要求,并预览自己的提交。**

无需让 Agent 逐步识图、点击 QQ 窗口。工具通过本机 OneBot 接口实时查询资料,再通过 MCP 返回候选文件和搜索范围。Windows 可使用 SnowLuma 加载到正在运行的桌面 QQ,在同一账号下聊天、查群文件和下载。

```text
你:找「示例学习群」里文件名包含「课件」的文件。
Codex → qq_search_files → 群文件目录 + 可获取的聊天附件
你:下载第二个。
Codex → qq_download_file → 本机路径、文件大小、SHA-256
你:总结刚下载的课件。
Codex → qq_read_downloaded_file → 分页正文 → 总结并标明页码
```

这是单用户、自行部署的项目。QQ、桥接工具、MCP 工具和 Codex 运行在同一台电脑;电脑关闭时服务离线。无需租服务器,也不调用额外的模型 API。Codex 自身的账号与使用额度照常适用。

**需要同时聊天和查文件时,使用桌面会话接入方式。** 原有 NapCat Shell 安装仍可使用,但它独立登录 QQ,同账号与桌面 QQ 可能发生登录冲突;两种方式不要一起启动。

## 能做什么

- 用群名、群名关键词或群号定位已加入的群;同名群先供选择。
- 实时查询根目录及接口返回的一级文件夹,不预同步。
- 文件名支持完整名称、部分名称、大小写与全半角归一化;明确要求全部文件时可传 `*`。
- 不知道文件名时,可按群名和发布人查找;支持 QQ 号、昵称/群名片及发布时间范围,同名成员先供选择。
- 聊天附件默认扫描最近 **1,000 条可获取消息**,可分段继续向前查询。
- 返回实际扫描条数、时间范围、截断或错误原因,避免将“未扫描到”当成“不存在”。
- 下载前重新确认文件,保留同名文件,返回 SHA-256;不会执行下载内容。
- 离线查找已下载的文件,直接读取 PDF、DOCX 正文和表格、TXT、Markdown、CSV 等文本;无需重新下载。
- 下载时保存群、上传者/发送者、发布时间和来源记录;之后可离线按这些信息筛选。
- 按页或行返回文字及续读位置,长页截断后仍可接着读。
- 检索聊天正文及作业补充说明,返回发送者、时间和原文依据;长消息可以续读。
- 准备自己的文字或文件提交预览;发送默认关闭,启用后仍需明确授权准确目标和内容。
- 不提供删除或群管理工具;QQ 原生“群作业”页面暂未支持。

## 快速开始:Windows 桌面 QQ 共享会话

需要 Python 3.11+、官方 QQNT、Codex。保留电脑 QQ 的正常登录。

```powershell
git clone https://github.com/HJLiyu/qq-file-mcp.git
cd qq-file-mcp
./scripts/setup.ps1
Copy-Item .env.example .env
```

按 [桌面 QQ 接入说明](docs/desktop-qq.md) 手动准备官方 SnowLuma 发行包,启动控制台并加载已有 QQ 进程。核对 OneBot HTTP 服务绑定 `127.0.0.1`、令牌非空、消息格式 `array`,关闭桥接的自动状态回复命令。在 `.env` 中填写:

```dotenv
QQ_FILE_BACKEND=snowluma
ONEBOT_URL=http://127.0.0.1:3000
ONEBOT_TOKEN=你的本地OneBot访问令牌
```

检查连接并注册工具:

```powershell
./.venv/Scripts/python.exe -m qq_file_mcp --env-file .env doctor
./scripts/register-codex.ps1
```

重新加载 Codex 的 MCP 连接或开启新对话,让 Codex 调用 `qq_status`、`qq_search_files`。电脑 QQ 继续聊天,工具复用这个登录会话。退出 QQ 或桥接工具后,实时检索暂不可用。

**聊天历史限制:** SnowLuma v1.14.20 的原版接口需要已观察到该群的消息,才能从这个起点向前取历史;首次加载后安静的群可能返回空。打开群窗口不保证能补齐起点。本工具返回 `HISTORY_ANCHOR_UNAVAILABLE` 和实际覆盖范围;群文件目录不受此限制。本仓库没有提供修改版桥接程序,详见接入说明。

## 原有方式:Windows NapCat Shell

需要 Python 3.11+、已安装的官方 QQNT、Codex,以及可以访问目标群的 QQ 账号。

```powershell
git clone https://github.com/HJLiyu/qq-file-mcp.git
cd qq-file-mcp
./scripts/setup.ps1 -WithNapCat
./scripts/start-napcat.ps1 -OpenWebUI
```

先关闭桌面 QQ,再在本地 NapCat 页面完成 QQ 登录。安装脚本将:

1. 创建 `.venv`,安装本项目依赖。
2. 从 NapCat 项目发布页下载固定版本 **v4.18.28**,核对 SHA-256 后解压到 `.local/`。
3. 从已安装 QQ 的运行目录复制该发布包缺少的 `crypto.dll`、`ssl.dll`。不修改 QQ 安装文件。
4. 生成本地令牌、`.env` 和仅绑定 `127.0.0.1` 的配置。

QQ 安装在其他位置时:

```powershell
./scripts/setup.ps1 -WithNapCat -QQInstallDirectory 'D:\Apps\QQNT'
```

检查连接、接入 Codex:

```powershell
./.venv/Scripts/python.exe -m qq_file_mcp --env-file .env doctor
./scripts/register-codex.ps1
```

重新加载 Codex 的 MCP 连接或开启新对话。让 Codex 调用 `qq_status`,再要求它搜索群文件。注册命令中只有配置文件路径,访问令牌保留在本机 `.env` 中。

查完后返回日常电脑 QQ:

```powershell
./scripts/stop-napcat.ps1
# 然后自行打开桌面 QQ 并登录。
```

停止脚本只终止本项目 `.local/napcat-node/node.exe` 对应的进程,保留 QQ 登录数据和已下载的文件。停止期间 MCP 的实时检索与下载不可用,下次需要时再次关闭桌面 QQ、运行 `start-napcat.ps1 -OpenWebUI` 并登录。

> NapCat 是第三方接入,非腾讯官方开放 API,可能出现掉线、登录验证和账号风控。请阅读 [NapCat 安全说明](https://napneko.github.io/other/security),再决定使用哪个账号。发送自己的作业需要单独启用,删除和群管理不开放;桥接本身有更广的能力,因此其接口必须保持本机绑定与令牌鉴权。

## 已有 OneBot 服务 / 其他系统

本项目支持同一台机器上的 NapCat 或 SnowLuma HTTP 服务。Windows 安装脚本只提供 Python 工具和可选 NapCat Shell 环境;其他系统的 QQ 运行环境需自行准备。

```bash
python -m venv .venv
# 激活对应系统的虚拟环境后:
python -m pip install -e .
cp .env.example .env
```

启用 HTTP 服务:`127.0.0.1:3000`、设置非空 token、消息格式 `array`(NapCat 名称为 `messagePostFormat`,SnowLuma 为 `messageFormat`)。把相同 token 写入 `.env` 的 `ONEBOT_TOKEN`,并设置 `QQ_FILE_BACKEND=napcat` 或 `snowluma`。连接地址只允许本机回环。

旧配置中的 `NAPCAT_URL` / `NAPCAT_TOKEN` 仍有效;没有设置后端时默认 `napcat`。新的 `ONEBOT_*` 配置优先。文件和分页引用绑定接入方式,切换后会拒绝旧引用并要求重新搜索;推荐使用独立 `QQ_FILE_STATE_DIR`。

优先使用 QQ HTTPS 文件链接下载。如果当前 NapCat 不支持链接接口,将尝试 QQ 本地缓存;此时需要通过 `QQ_FILE_ALLOWED_ROOTS` 指定允许读取的 QQ 缓存目录。不要将整个磁盘或个人主目录加入允许列表。SnowLuma 的 `get_file` 只适用于图片/语音缓存,群文件下载链接不可用时会报错,不会尝试该后备路径。

## 命令行

```powershell
# 搜群
./.venv/Scripts/python.exe -m qq_file_mcp --env-file .env groups '示例学习群'

# 搜群文件与最近可获取的聊天附件
./.venv/Scripts/python.exe -m qq_file_mcp --env-file .env search '示例学习群' '课件'

# 列出群文件(此命令不自动批量下载)
./.venv/Scripts/python.exe -m qq_file_mcp --env-file .env search '示例学习群' '*' --source group_files

# 继续向前搜索聊天附件,保持同一群和关键词
./.venv/Scripts/python.exe -m qq_file_mcp --env-file .env search '示例学习群' '课件' --history-cursor '上次返回的标识'

# 下载选定文件;使用搜索返回的 result_id
./.venv/Scripts/python.exe -m qq_file_mcp --env-file .env download '选定结果的标识'

# 不知道文件名,只知道群名和发布人
./.venv/Scripts/python.exe -m qq_file_mcp --env-file .env search '示例学习群' --publisher '张老师' --source group_files

# 离线从已下载文件中按群和发布人找资料
./.venv/Scripts/python.exe -m qq_file_mcp --env-file .env downloads --group '示例学习群' --publisher '张老师'
```

默认下载目录:`~/Downloads/QQ-File-MCP`。可用 `.env` 中的 `QQ_FILE_DOWNLOAD_DIR` 修改。

## 让 Agent 使用已下载文件

更新代码和依赖后,重新加载 Codex 的 MCP 连接;若当前对话仍显示旧工具列表,开启新对话或重启 Codex。QQ 和桥接工具无需为离线读取重新登录。

直接说“总结已经下载的课件”或“在已下载的笔记里找数值积分的说明”。Agent 先用 `qq_list_downloaded_files` 定位文件,再用 `qq_read_downloaded_file` 获取正文。下载工具新增 `local_file_id`,可以立即传给读取工具。旧版下载的文件也可直接列出,包括专用下载目录内的普通子目录。

读取结果带页号、行号或 DOCX 正文块编号、SHA-256 和 `next_read`。只返回指定范围,不会把整个长文档一次塞进上下文。DOCX 不提供页码,图片、公式、页眉页脚等未解析;扫描 PDF 暂无 OCR,公式和表格的提取可能不完整。详见 [离线读取说明](docs/downloads.md)。

v0.8.0 增加 DOCX 离线读取,修复状态数据库连接未及时关闭、Windows 文件被占用的问题;提交文件读取或暂存失败时返回 `SUBMISSION_IO`,便于 Agent 提示检查文件占用、权限或磁盘空间。已有工具名称和参数兼容,升级后重新加载 Codex 的 MCP 连接即可。

例如“找示例学习群里张老师9月份发的资料”:Agent 可以组合 `group`、`publisher`、`published_after`、`published_before` 和可选的文件名。新下载会持久保存实际观察到的群、发布人和发布时间;旧文件缺少这些记录时标为未知,有来源筛选时不会猜测匹配。群文件的发布人是上传者,聊天附件是发送者,不代表文档作者。

## MCP 工具

| 工具 | 用途 |
| --- | --- |
| `qq_status` | 检查连接和登录 |
| `qq_find_groups` | 按群名或群号定位群 |
| `qq_search_files` | 按群、可选文件名、发布人和时间查询;`source=both/group_files/history` |
| `qq_more_results` | 读取同一轮搜索的其余候选,每页 50 条 |
| `qq_download_file` | 下载选定 `result_id`,返回可直接读取的 `local_file_id` |
| `qq_list_downloaded_files` | 离线按文件名、群、发布人、来源和时间查找,返回 `file_id` |
| `qq_read_downloaded_file` | 用上述引用读取 PDF 页、DOCX 正文块或文本行,支持续读 |
| `qq_search_messages` | 按群、关键词、发布人和时间检索聊天正文与附件,带范围和继续查询 |
| `qq_read_message` | 续读选定消息正文,核对群、发送者、时间及内容哈希 |
| `qq_prepare_submission` | 生成自己的文字或文件提交预览,不发送 |
| `qq_submit_submission` | 启用发送并批准具体预览后执行一次;不能替换内容或目标 |
| `qq_submission_receipt` | 离线查看状态和回执,不重发 |
| `qq_search_homework` | 实时查询原生群作业,按群、关键词、发布人筛选并翻页 |
| `qq_read_homework` | 读取原生要求、自己的答案、提交状态和老师评语,支持长正文续读 |
| `qq_download_homework_attachment` | 下载上述详情返回的附件,供查看图片或读取 PDF/DOCX/文本 |
| `qq_prepare_homework_submission` | 准备原生文字或 PDF/Word 预览,绑定文件哈希,默认禁止覆盖 |
| `qq_submit_homework` | 一次尝试提交准确预览,并读回原生记录核对答案 |

例如“结合老师发的文件和之后的聊天补充,整理作业要求”。Agent 使用文件工具和聊天工具取证,并注明发送者、时间和实际查到的范围。提交先展示群名/群号及准确文字或文件;默认 `QQ_FILE_ENABLE_SUBMISSIONS=false`,文件只可来自独立的 `submission_dir`。启用发送、生成预览均不代表批准提交。配置、用法与回执含义见 [作业与提交说明](docs/homework.md)。

v0.7.0 可直接说“读取这个群的原生群作业,查看我是否提交过”,或“把提交目录里的答案 PDF 准备成这份原生作业的预览”。原生工具复用 SnowLuma 桌面会话,支持文字和一个 PDF/DOC/DOCX 文件,可附文字;文件上传使用原生作业专用接口。已有答案默认禁止覆盖。真实原生读取、图片/历史PDF下载和本机预览已验证;**原生文件提交为试验功能,真实上传与提交尚未验收**,不能将模拟测试当成真实成功。详见 [原生群作业说明](docs/native-homework.md)。更新后重载 Codex 的 MCP 连接,加载新增的 `file_path` 参数;仍是17个工具,无需重登QQ。

## 范围与限制

- 同账号聊天与群文件工具已在 Windows QQNT + SnowLuma v1.14.20 中验证。上游版本、QQ 版本和登录状态改变后仍需重新验证;独立 NapCat Shell 不属于共享会话方式。
- 作业汇总可以结合原生要求、文件及可获取聊天正文。关键词查询可能漏掉不含该词的补充说明;图片/语音/转发不自动提取正文。群消息/文件回执不代表原生作业提交;原生答案只有准确读回后才报告已验证,均不代表老师认可。
- 聊天历史仅覆盖当前 QQ 会话实际能取回的内容,无法保证任意年份的消息都可用。
- 合并转发中的文件、在线文件和多层嵌套目录尚未支持;普通聊天 `file` 附件已实现。
- 群文件默认每个目录最多处理 10,000 项、最多查 100 个一级目录;聊天每轮最多 5,000 条。即使上游忽略请求数量,也在客户端限制目录处理。达到上限会在 coverage/warnings 中说明。
- 两种来源独立限时,默认每种最多 40 秒;一个来源失败不会丢弃另一来源的结果。
- 超时或到达范围上限后,以返回的范围为准。空结果不等于完整历史中不存在。
- 文件结果及继续查询标识默认保留一小时。QQ 会话重启后,聊天消息标识可能失效,需要重新搜索。
- 已下载文件的来源记录持久保存在本机状态库;不受结果引用的一小时有效期影响。昵称/群名片是查询或下载时观察到的名字,离线时不自动跟随改名;QQ 号可精确定位。
- 同一文件可能分别出现在群目录和聊天附件中,本版保留来源,不通过名称猜测它们是同一文件。
- 默认单文件大小上限 512 MiB;过期文件、权限不足或内容大小变化会明确报错。
- 离线读取默认单文件最多 50 MiB、单次解析 20 秒,最多10页或500行/正文块、20,000字符。DOCX 正文 XML 展开后最多8 MiB;暂不支持加密文档、旧版 DOC、Excel、通用压缩包和图片 OCR。
- 提交文字或单文件的预览有效15分钟,默认文件上限50 MiB。超时或发送中断可能已经发送,同一预览不能自动重试,需先在QQ核对。
- 原生 QQ 下载在某些运行环境中可能超时;本版优先使用受限 QQ HTTPS 下载,NapCat 的原生缓存作为后备路径。

## 开发与验证

```powershell
./.venv/Scripts/python.exe -m pip install -e '.[dev]'
./.venv/Scripts/python.exe -m pytest -q
./.venv/Scripts/python.exe -m ruff check src tests scripts
./.venv/Scripts/python.exe -m build
```

测试覆盖两种后端的历史参数差异、同秒消息排序、目录检索、群名歧义、历史翻页、账号切换、同名文件、下载路径、链接重定向、令牌隔离,以及真实 stdio MCP 握手。离线读取另覆盖中文编码、PDF 页码、DOCX 段落/表格顺序与修订警告、长正文续读、压缩/XML 解析上限、文件变化与过期、Windows junction/符号链接边界和解析子进程超时终止。状态库测试核对事务提交、回滚和连接释放;提交文件测试覆盖读取失败及部分暂存清理。

测试和示例不包含真实 QQ 消息。`.env`、`.local/`、会话配置、检索结果与下载文件均不应提交到 Git。

架构与验证边界见 [docs/architecture.md](docs/architecture.md),本轮改进与后续验收目标见 [扩展方向](docs/roadmap.md)。

## 上游与许可

本项目独立编写的客户端代码使用 MIT 许可。QQ、NapCat、SnowLuma 是独立运行依赖,遵循各自的许可和使用规则;仓库不包含其源代码、修改版或二进制文件。SnowLuma 使用[源码可见非商业许可](https://github.com/SnowLuma/SnowLuma/blob/v1.14.20/LICENSE),还需阅读其 [EULA](https://github.com/SnowLuma/SnowLuma/blob/v1.14.20/EULA.md)。MCP 使用 [官方 Python SDK](https://github.com/modelcontextprotocol/python-sdk)。