qq-bridge
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@qq-bridgecheck my QQ for new messages"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
OneBot Agent Bridge
把 QQ 的 OneBot v11 收发能力封装成 CLI、JSON HTTP 接口和 stdio MCP 工具。面向需要自己决定如何处理消息的 AI Agent,适配 NapCat / SnowLuma 的标准 OneBot 接口。
本项目参考 wechat-ilink-bridge 的 CLI + 本地状态 + MCP 设计,独立实现 QQ 传输层。微信版通过 iLink 长轮询收消息;QQ 版需要一个常驻进程接收 OneBot 事件,并把事件保存到 SQLite,再交给 Agent 拉取。
QQ ↔ NapCat / SnowLuma ↔ OneBot v11 ↔ qbridge 常驻进程
↕ SQLite 消息队列
CLI / HTTP / MCP
↕
你的 AI Agent 或应用部署后可以收发 QQ 消息。自动生成回复需要另一个 Agent 或应用调用这些工具;此桥接器不内置模型或模型 API Key。MCP 工具提供调用能力,本身不会唤醒关闭的客户端,也不会把 QQ 消息自动注入当前聊天。持续自动回复需要一个持续运行的消费循环,见 Agent 接入说明。
如果使用有独立 Computer 和定时任务的 Muse,见 Muse 拉取与定时查询说明。真实连接凭证需单独提供,不包含在这个仓库里。
首版范围
能力 | 状态 |
OneBot v11 正向通用 WebSocket | 已实现,断线自动重连 |
OneBot v11 反向通用 WebSocket | 已实现,支持 Bearer / query token |
HTTP API + HTTP POST 事件 | 已实现,支持 HMAC-SHA1 签名验证 |
QQ 私聊 / 群聊收发文本 | 已实现 |
CQ 字符串 / 数组格式入站消息 | 已实现 |
@ / 引用回复 / 群聊只处理 @bot | 已实现;默认只 @ 触发,普通消息仅作上下文 |
被 @ 时附带最近群聊上下文 | 已实现;默认此前 20 条,可配置 0–100 |
标准 OneBot 图片发送 | 已实现,本地图片转 base64 |
文件发送 | 扩展接口;要求后端支持和共享路径 |
入站图片 | 已实现按引用读取;MCP 原生图片 / CLI 保存图片 / HTTP base64 |
入站语音、视频、文件 | 仅返回类型和元数据,不下载 / 转写 |
本地消息历史、去重、处理确认 | 已实现,SQLite 持久化 |
发送 requestId 去重 | 已实现;无法确认的发送不会自动补发 |
CLI / stdio MCP / JSON HTTP | 已实现 |
Docker / Compose 配置 | 已提供 |
多 QQ 账号 | 每个账号单独运行一个桥接进程和状态目录 |
QQ 扫码登录 | 由 NapCat / SnowLuma 完成 |
标准文本、图片不依赖 NapCat 专属接口。文件使用 upload_private_file / upload_group_file,不属于 OneBot v11 的标准 API,实际可用性由你部署的后端版本决定。
Related MCP server: SnowLuma Remote MCP Server
从源码运行
需要 Node.js 24+,使用内置 SQLite。
git clone https://github.com/Reshwell/onebot-agent-bridge.git
cd onebot-agent-bridge
npm ci
cp .env.example .env
mkdir -p shared编辑 .env,至少设置这三项:
QBRIDGE_TOKEN=填入你自己的随机桥接密钥至少16字符
ONEBOT_WS_URL=ws://127.0.0.1:3001/
ONEBOT_ACCESS_TOKEN=填入NapCat或SnowLuma的OneBot密钥QBRIDGE_TOKEN 用来保护本工具的 CLI / HTTP / MCP 接口;ONEBOT_ACCESS_TOKEN 是 QQ 协议端的密钥,两者用途不同。桥接器不会接受示例占位密钥。
然后启动常驻接收进程:
npm start保持这个进程运行。在另一终端进入同一个目录:
node src/cli.js status
node src/cli.js fetch --wait 10000
node src/cli.js send --user 123456789 --text "收到" --request-id reply-001
node src/cli.js send --group 987654321 --text "群内回复" --request-id reply-002
node src/cli.js ack --ids 1,2示例 QQ 号、群号和序号需要换成你自己的。status.data.accountReady: true 表示已经通过 get_login_info 校验当前 QQ 账号。没有连接成功时,检查 OneBot 服务是否开启、地址、端口和密钥是否一致。
可选安装本地全局命令:
npm install -g .
qbridge status
qbridge-mcp这只是从本地源码安装;本项目尚未发布到 npm,不能直接使用 npx onebot-agent-bridge 从 registry 安装。
NapCat / SnowLuma 配置
首选正向 WebSocket。后端打开一个同时提供 API 和事件的通用 WebSocket 服务,把地址和 token 填入 .env。标准 OneBot 路径通常是 /,仅 /event 的连接无法调用 API;仅 /api 的连接无法收新消息。如果使用事件专用 WS,则还须配置 ONEBOT_HTTP_URL 作为 API 出口。
SnowLuma 文档默认 OneBot WS 端口为 3001;NapCat 使用你在管理界面里配置的 WS 端口,不必设成相同的数字。
使用反向 WebSocket 时设置:
ONEBOT_MODE=reverse
ONEBOT_ACCESS_TOKEN=与QQ协议端一致的密钥然后在 NapCat / SnowLuma 填通用反向 WS 地址:
ws://桥接器地址:8787/onebot/v11/ws首版只接受通用连接(X-Client-Role: Universal),不接受分开的 API / Event 双连接。反向连接由 OneBot 端负责重连。需要从另一台机器接入时,设置监听地址为 QBRIDGE_HOST=0.0.0.0,并让该机器能够访问配置的端口。
HTTP 方式设置:
ONEBOT_MODE=http
ONEBOT_HTTP_URL=http://QQ协议端地址:3000/
ONEBOT_ACCESS_TOKEN=QQ协议端密钥
ONEBOT_HTTP_SECRET=事件上报签名密钥OneBot 事件上报地址设置为 http://桥接器地址:8787/events,使用相同签名 secret。若后端仅支持带 Bearer token 的 HTTP 事件,则留空 ONEBOT_HTTP_SECRET,用 ONEBOT_ACCESS_TOKEN 鉴权。HTTP API token 与 WS / 事件 token 不同时,通过 ONEBOT_HTTP_ACCESS_TOKEN 单独配置。
Docker 部署
先编辑 .env,准备 shared/。如果 QQ 协议端运行在宿主机,Docker 内的 127.0.0.1 指向容器,应改成:
ONEBOT_WS_URL=ws://host.docker.internal:3001/QQ 协议端须监听容器能访问的地址。Docker Desktop 通常支持 host.docker.internal;在 Linux 上只监听 127.0.0.1 的后端通常不能通过 host-gateway 访问,需要改为可访问的监听地址。
docker compose up -d --build
docker compose logs -f qbridge
docker compose exec qbridge node src/cli.js status
docker compose exec qbridge node src/cli.js fetch --wait 10000Compose 把本地 8787 映射到容器并用命名卷保存 SQLite,重建容器保留消息。QBRIDGE_URL 默认 http://127.0.0.1:8787,适用于容器内 CLI 和宿主机客户端。
如果 NapCat / SnowLuma 也在 Docker 中,把它和 qbridge 加入同一个 Docker network,并设置 ONEBOT_WS_URL=ws://napcat:端口/ 或 ws://snowluma:3001/。不同 Compose 项目之间需要显式共享 network;服务名不能自动跨 network 解析。
Compose 默认只把端口映射到宿主机回环地址。来自其他容器的反向 WS 可走共享 network 到 qbridge:8787;来自其他机器的反向 WS 需要按你的网络环境调整端口绑定。
接入 MCP
把 examples/mcp-config.json 中的绝对路径和桥接器 token 改成你的值。MCP 进程只充当工具客户端,常驻接收进程需要另行启动。
{
"mcpServers": {
"qq-bridge": {
"command": "node",
"args": ["/absolute/path/to/onebot-agent-bridge/src/mcp.js"],
"env": {
"QBRIDGE_URL": "http://127.0.0.1:8787",
"QBRIDGE_TOKEN": "与常驻进程一致的桥接密钥"
}
}
}
}具体导入方式由你的 MCP 客户端决定。这里只提供通用 stdio 配置,不保证每个 AI 产品都允许本地 stdio MCP 或后台自动轮询。
工具包括 fetchMessages、getImage、ackMessages、sendText、sendImage、sendFile、listUsers、listGroups、listConversations、history、status、getDelivery。
消息处理与防重复
fetchMessages / qbridge fetch 读取待处理消息,不自动消费。回复完成后调用 ackMessages / qbridge ack。只取走消息就自动确认,可能在 Agent 中断时遗漏未处理内容。
{
"ok": true,
"data": {
"messages": [
{
"seq": 1,
"conversationId": "group:987654321",
"messageId": "456",
"userId": "123456789",
"groupId": "987654321",
"text": "你好",
"pending": true
}
],
"ackIds": [1]
}
}群消息应回到 conversationId / groupId,而不是把发言者 userId 当成私聊目的地。每条回复使用稳定 requestId,例如 reply-10001-1:重试同一 ID 和内容不会发送第二遍。相同 ID 配不同内容会被拒绝。
如果返回 SEND_UNCERTAIN,表示断线、超时或响应异常导致无法确定消息是否已经发送。先在 QQ 检查,不要直接换一个 ID 重发。getDelivery 可查看本地记录,但不能证明远端最终是否收到。程序崩溃留下的 sending 记录同样需要人工核实。
同一消息队列默认面向一个消费循环;多个 Agent 同时读取会得到相同未确认消息,首版没有消费者租约。已确认及发送历史最多保留 QBRIDGE_MAX_HISTORY 条;未确认消息不会被这个上限清理。去重键和发送记录持续保留,需要为长期运行的状态目录预留磁盘空间。
群聊:只 @ 触发,同时保留上下文
默认配置:
QBRIDGE_GROUP_MENTION_ONLY=true
QBRIDGE_GROUP_CONTEXT_LIMIT=20普通群消息保存在有界历史中,contextOnly: true、pending: false,不进入待处理队列,也不会结束 fetch --wait 的等待。明确 @ 当前 QQ 机器人的消息才会进入群聊待处理队列;@all 不算 @bot。私聊不受这个开关影响。
查询到群聊任务时,messages[i].context 会自动附带该条 @ 消息之前、同一群聊的最近 20 条消息(含本桥接器的已发送回复),按接收顺序排列。后续群聊不会混入这条任务的上下文,其他群也不会串入。QBRIDGE_GROUP_CONTEXT_LIMIT 可设 0–100,0 表示不附带上下文。正文和图片都可作为背景,但上下文不是新的回复任务,也不在本轮 ackIds 中。
QBRIDGE_ALLOWED_GROUPS 限定保存哪些群的消息;为完整上下文,这些群内其他发言者的消息也会保存为背景。QBRIDGE_ALLOWED_USERS 限定允许触发处理的发言者和私聊对象,不再阻止保留允许群内的其他发言者背景。建议部署时填写群白名单,避免收集无关群聊。
从 0.1.0 升级时,若旧 .env 写了 QBRIDGE_GROUP_MENTION_ONLY=false,必须改为 true;环境变量也可覆盖 .env。启动后,旧队列中不符合当前触发规则的普通群消息会降为上下文,保留历史而不继续作为任务。
桥接器只区分“待处理消息”和“背景”,不控制 Muse 的调度器。两分钟定时任务仍会按时运行;这一轮没有私聊或 @ 消息时,应安静结束,不因普通群聊发通知或自动回复。
OneBot v11 的事件没有可靠历史回放协议。桥接器离线期间的 QQ 消息、已经发出但未写入 SQLite 就断电的事件,不保证补齐。这个桥接器提供收到并落盘后的本地持久化,不承诺端到端恰好一次投递。
图片和文件
接收图片并让 AI 看图
fetchMessages、history 和群聊 context 中的图片附件会提供 imageRef,例如:
{"kind":"image","segmentIndex":1,"imageRef":{"seq":17,"attachmentIndex":0}}MCP:调用
getImage({ seq: 17, attachmentIndex: 0 }),返回文字元数据 + 原生 MCPimage内容。客户端必须支持把图片交给有视觉能力的模型。CLI / Muse Computer:执行下面的命令,把图片保存在消费端,再使用 Computer 的图片查看能力打开;不是让 AI 阅读一大段 base64。
HTTP:
POST /rpc,请求{"method":"getImage","params":{"seq":17,"attachmentIndex":0}},返回mimeType、bytes、sha256和base64;应用需要将实际图片作为视觉输入交给模型。
mkdir -p work
node src/cli.js image --seq 17 --attachment 0 --output work/incoming-17.pngseq 和 attachmentIndex 应使用 imageRef 的实际值。CLI 输出保存后的绝对路径,已有文件不会被覆盖。读取图片不会自动确认消息;看图和回复完成后再 ack。桥接器不会自己生成图片描述或 OCR,也不能让纯文本模型拥有视觉能力。
读取时优先用 get_image 刷新后端图片信息,再使用 base64、QQ CDN 下载链接或明确配置的共享图片缓存。临时签名链接、后端文件路径不会在查询结果中返回。默认接受 PNG/JPEG/GIF/WebP,单张上限由 QBRIDGE_MAX_MEDIA_BYTES 控制(默认 10 MiB);网页、JSON、SVG 和超大内容会被拒绝。
下载只允许 QBRIDGE_IMAGE_ALLOWED_HOSTS 指定的域名及其子域(默认 QQ 图片 CDN);每次重定向和实际 DNS 地址均校验,默认拒绝回环、内网和保留地址,不携带 OneBot token、桥接 token 或 Cookie。仅对明确可信的 LAN 图片服务同时配置允许域名及 QBRIDGE_IMAGE_ALLOW_PRIVATE_NETWORK=true;不要为普通 QQ 图片关闭内网保护。
若后端仅返回本地文件路径(OneBot 标准允许这种情况),需要共享图片缓存目录并设置:
QBRIDGE_IMAGE_LOCAL_ROOT=/read-only-qq-images
ONEBOT_IMAGE_LOCAL_ROOT=/backend/cache/images这是目录映射:后端 /backend/cache/images/a.png 对应桥接器 /read-only-qq-images/a.png。应只读挂载具体的图片缓存,不要配置成 / 或包含凭证的目录;越界路径和跳出目录的符号链接会被拒绝。SnowLuma 提供可用 URL 时通常不需要目录共享。
发送图片和文件
图片放进 shared/ 后发送,协议端无需访问桥接器本地路径,因为桥接器会转成 base64:
node src/cli.js send --user 123456789 --image photo.png --request-id image-001普通文件上传使用后端扩展接口,后端读取 file 对应的文件路径。需要把同一个文件夹挂到两个容器,并用 ONEBOT_FILE_ROOT 配置后端看到的目录。例如两边都挂到 /shared:
docker compose exec qbridge node src/cli.js send --group 987654321 --file report.pdf --request-id file-001仅桥接器能访问该文件、而 QQ 协议端看不到对应路径时,文件上传无法成功。sendImage / sendFile 的 filePath 都是桥接器服务端的路径,不是远程 MCP 客户端的路径。
HTTP JSON 接口
所有 Agent 操作统一为 POST /rpc,Bearer token 为 QBRIDGE_TOKEN:
POST /rpc
Authorization: Bearer YOUR_BRIDGE_TOKEN
Content-Type: application/json
{"method":"fetchMessages","params":{"limit":20,"waitMs":10000}}方法名与 MCP 工具一致。GET /healthz 仅检查进程能否应答,不等同于 QQ 账号在线;连接状态应查询 status。如通过跨机器网络使用 HTTP,请按你的部署环境配置 TLS 或私有网络。
验证
npm test
npm run check
npm run pack:dry-run测试使用模拟 OneBot 服务,覆盖三种传输、重连、签名、持久化、路由、发送去重、媒体发送和官方 MCP 客户端 stdio 调用。已通过真实 SnowLuma 正向 WS 的私聊收发联调,见 验证记录。其他后端、群聊、媒体和具体部署环境仍需按 真实环境验收清单 验证。
This server cannot be deployed
Maintenance
Related MCP Connectors
AI agent messaging with durable inboxes, contacts and tasks. Connect through MCP with OAuth.
1Async message queue for AI agents. Self-provision queues, push/poll messages, no signup.
Human-input bridge for AI agents with voice-first answer links, MCP tools, and HTTP APIs.
Command your AI agents by voice: PTT rooms, channels, direct messages, agent email, memory (mRAG).
Related MCP Servers
- FlicenseAqualityBmaintenanceEnables MCP hosts to bridge with QQ via NapCat/OneBot 11, allowing whitelisted private messages to reach an agent with full tool access while group mentions are answered by a sandboxed pure LLM without system access.8-
- AlicenseNot gradedqualityBmaintenanceEnables mobile AI agents and remote clients to connect to SnowLuma OneBot v11 over Streamable HTTP/SSE, providing messaging, group management, reaction emojis, and full OneBot v11 action pass-through.1MIT
- AlicenseAqualityCmaintenanceEnables interaction with QQ through official bot APIs or personal accounts bridged via NapCat/OneBot v11, including status checks, target listing, bounded context retrieval, and plain-text sending to allowlisted conversations.5MIT
- AlicenseAqualityCmaintenanceExposes NapCat/OneBot v11 QQ-bot APIs as MCP tools for any MCP client, and includes an LLM-driven QQ bot with memory, knowledge base, tool calling, web search, multimodal recognition, and permission controls.45MIT