发说说、改资料、管好友,一个插件全搞定
30.7/100
综合分
1
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/10/29 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
相关生态插件(非 dsh 原生,按其对应运行时安装)
git clone https://github.com/ChuYanSir/qzone-mcp.git状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:仅索引
是什么
生态应用
桌面端 / Web 外壳,不以 dsh plugin add 安装
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 5 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
⚠︎ 实装验证未通过(unknown · 2026/10/30) ——可能是验证环境差异,装前建议到 GitHub 仓库确认最近更新与 issue。
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码v2.7.0⚪ 扫描:无法判定尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0已尝试扫描但取不到可分析的源码:仓库或包不存在、已删除,或为非 JS/TS 实现、未随包发布源码。无法判定,不代表安全。
- · 包内无可扫 JS
- · TS 源码(可能为非 JS 实现或未发布源码),无法判定
扫描于 2026/11/3(0 天前) · 范围 全包扫描(包内未声明入口) · 来源 GitHub 仓库
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
QQ 空间 + 资料工具箱:MCP 插件(DSH / SnowLuma / OneBot v11),38 个工具,含发图、语音、白名单管理
README
由 DeepSeek 最新模型翻译生成qzone-mcp —— QQ 工具箱(空间 + 资料),我们的一个 MCP 插件
把上游两个 AstrBot 插件的能力合成一个插件,改成我们这套栈能直接调的形式:
| 上游 | 贡献的能力 |
| Zhalslar/astrbot_plugin_qzone(MIT) | 发/看/删/赞/评说说、好友动态、访客、可见范围、表白墙投稿审核、定时说说 |
| Zhalslar/astrbot_plugin_qqprofile(MIT) | 改头像 / 昵称 / 签名 / 在线状态、自定义状态、查资料、名片赞、好友分组 |
为什么不原样装:这两份都是 AstrBot 插件(star.Star + event.bot.),AstrBot 已经不在我们的栈里了。
所以保留它们的接口语义(端点、参数、可见范围、审核流程、状态码表),换成本机现有认证与调用方式。
从零安装(换台机器 / 换个容器)
三步:放代码 → 配环境变量 → 让 DSH 拉起 MCP。
1. 代码放到 /opt/qzone-mcp(server.py 是入口,wire.py 负责接线)。
展开完整文档(README 剩余 1 节)
qzone-mcp —— QQ 工具箱(空间 + 资料),我们的一个 MCP 插件
把上游两个 AstrBot 插件的能力合成一个插件,改成我们这套栈能直接调的形式:
| 上游 | 贡献的能力 |
| Zhalslar/astrbot_plugin_qzone(MIT) | 发/看/删/赞/评说说、好友动态、访客、可见范围、表白墙投稿审核、定时说说 |
| Zhalslar/astrbot_plugin_qqprofile(MIT) | 改头像 / 昵称 / 签名 / 在线状态、自定义状态、查资料、名片赞、好友分组 |
为什么不原样装:这两份都是 AstrBot 插件(star.Star + event.bot.),AstrBot 已经不在我们的栈里了。
所以保留它们的接口语义(端点、参数、可见范围、审核流程、状态码表),换成本机现有认证与调用方式。
从零安装(换台机器 / 换个容器)
三步:放代码 → 配环境变量 → 让 DSH 拉起 MCP。
1. 代码放到 /opt/qzone-mcp(server.py 是入口,wire.py 负责接线)。依赖:
pip3 install --break-system-packages aiohttp==3.14.5 edge-tts==7.3.1
2. 环境变量(compose 的 environment: 或 systemd Environment=):
| 变量 | 必填 | 说明 |
| QZONE_ONEBOT_URL | ✅ | OneBot HTTP,例如 http://snowluma:3000 |
| QZONE_ONEBOT_TOKEN | ✅ | SnowLuma 的 HTTP token(不是 WS token,两者不同) |
| QZONE_DATA | 建议 | 数据目录(wall.db 等),例如 /opt/qzone-data |
| QZONE_SNOWLUMA_SHARE | 发图/头像需要 | core 侧看到的共用目录,例如 /opt/snowluma-data/stickers |
| QZONE_SNOWLUMA_PREFIX | 发图/头像需要 | 同一目录在 SnowLuma 容器里的路径,例如 /app/data/stickers |
| QZONE_IMG_PORT | 可选 | 临时图 HTTP 端口,默认 8799 |
| QZONE_IMG_URL_BASE | 可选 | 临时图对外基址,默认容器 IP http://<容器IP>:8799 |
| QZONE_TTS_VOICE | 可选 | 默认音色,默认 zh-CN-XiaoyiNeural |
| QZONE_TTS_MAX_CHARS | 可选 | 一次合成最大字数,默认 400 |
config.example.json 是可选覆盖(放 QZONE_DATA 或 /opt/qzone-mcp/config.json),只管 qzone.timeout / cookieTtl / defaultUgcRight、表白墙、定时说说这些。
3. 接线(让 DSH 把它当 MCP 服务器拉起来):
python3 /opt/qzone-mcp/wire.py # 幂等;写 $DSH_HOME/profiles/<profile>/cordis.patch.yml 的 mcp-qzone 段
docker restart core # profile 层要重启才重读
wire.py 写进去的行长这样(serverName: qzone → 工具名就是 mcp__qzone__):
- insert:
- id: mcp-qzone
name: '@deepseek-ai/dsh-mcp-client'
config:
serverName: qzone
command: /usr/bin/python3
args: ['/opt/qzone-mcp/server.py']
toolCallTimeoutMs: 120000
4. QQ 会话里要能用,还得放行工具前缀:qq-tool-restrict 的 SAFE_PREFIXES 里要有 'mcp__qzone__';mcp__qzone__ 默认只给管理员(按 qq-bridge 的 owner 会话判定)。
自检:
printf '%s\n%s\n' '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}' \
'{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}' \
| python3 /opt/qzone-mcp/server.py | head -c 400
它长在哪
QQ ──► SnowLuma(注入 QQ 的 OneBot 运行时) │ HTTP 3000 │ · 空间:get_cookies → p_skey → 自算 g_tk → 空间网页版 CGI │ · 资料:set_qq_avatar / set_qq_profile / set_self_longnick / │ set_online_status / set_diy_online_status / get_stranger_info …
▼
core 容器里的 qzone-mcp(stdio MCP server,DSH 拉起) │ 工具调用 ▼ DSH agent(qq-bridge 转来的 QQ 消息 → 挑工具 → 回消息)
- 运行:/opt/qzone-mcp/server.py,MCP over stdio(JSON-RPC 2.0,按行),只依赖标准库 + aiohttp。
- 注册:/opt/qzone-mcp/wire.py 往 /opt/dsh-home/profiles/web/cordis.patch.yml 幂等追加一条 mcp-qzone,entrypoint 每次启动跑一遍。
- 文件:server.py(协议 + 工具注册)、qzone_api.py(空间 CGI)、profile_api.py(资料动作 + 状态码表)、msg_api.py(往 QQ 发图片消息)、img_bridge.py(取图 + 临时 HTTP + core↔SnowLuma 共用目录)、bridge_admin.py(改 qq-bridge 白名单)、wall.py(表白墙 sqlite)、scheduler.py(定时说说)、wire.py(profile 接线)。
工具(38 个)
空间
| 工具 | 作用 |
| qzone_publish | 发说说(ugc_right 1 公开 / 4 好友 / 64 仅自己,images 支持 URL 或本地路径) |
| qzone_list | 看说说列表,target_uin 看别人的,序号 0 = 最新 |
| qzone_detail | 单条说说完整内容(评论、图片、转发) |
| qzone_delete | 删自己的说说(走 SnowLuma 原生 delete_qzone_msg,CGI 那个端点会返回 HTML 跳转页) |
| qzone_like / qzone_unlike | 点赞 / 取消赞 |
| qzone_comment / qzone_reply | 评论 / 楼中楼回复 |
| qzone_feeds | 好友动态流 |
| qzone_visitors | 最近访客 |
| qzone_profile | 空间名 / 简介 |
| qzone_set_right | 改已发说说的可见范围 |
| wall_submit / wall_list / wall_show | 表白墙投稿、看稿、看详情 |
| wall_approve / wall_reject / wall_withdraw | 过稿(发到空间)、拒稿、撤稿 |
| qzone_schedule_get / qzone_schedule_set | 定时说说(时间点 + ±随机浮动 + 候选文案) |
资料
| 工具 | 作用 |
| profile_get | 机器人自己的资料:QQ、昵称、连接状态、性别、年龄、等级 |
| profile_set_nickname | 改昵称(可选 personal_note) |
| profile_set_signature | 改个性签名(set_self_longnick) |
| profile_set_avatar | 改头像(图片 URL 或容器内文件路径) |
| profile_set_status | 改在线状态,认官方名也认白话(见下) |
| profile_set_diy_status | 自定义状态(face_id + 文字) |
| profile_list_statuses | 列出全部支持的官方状态名 |
| profile_stranger | 查任意 QQ 的资料(昵称/性别/年龄/等级/签名) |
| profile_likes | 名片赞:谁赞过、总次数、今日新增 |
| profile_friends | 好友分组列表(含备注) |
状态白话归一:profile_set_status 先精确匹配 status.py 的官方名(43 个),再走别名表,最后做包含匹配。举例:忙→忙碌、挂机→离开、睡了→睡觉中、在摸鱼→摸鱼中、 coding→搬砖中、好累→被掏空、开心→元气满满、emo→emo中、没电→我的电量。
也接受纯数字(1300 → 摸鱼中)。
没搬的东西:上游的「切换人格 / 人格列表」依赖 AstrBot 的 conversation_manager + persona_manager,我们这套栈里没有对应概念(人设由 DSH 的 agent preset + feeling 插件承担),所以不做。
发图
| 工具 | 作用 |
| qq_send_image | 把一张图当图片消息发到 QQ(私聊或群)。image 支持公网 URL、base64://、data:image/…、本容器内文件路径;target 填 QQ 号或群号;kind 默认 private |
这条是 v1.5.0 加的,解决的是「本地生成的图发不进 QQ」:收藏表情只能走 qq_send_sticker (发的是表情包收藏里的东西),而 meme_render / 自己用 PIL 画的图原先只落在容器里、控制台能看、QQ 发不出去。
// 发 meme_render 刚搓出来的图 {"name": "qq_send_image", "arguments": { "image": "/opt/dsh-home/nekowhale-stickers/renders/a0985f7f45247229.gif", "target": "123456789", "kind": "private", "text": "喏,本鱼自己搓的" }} // → 已把图片发到私聊 123456789:发送成功(797.1 KB image/gif,走共用目录,message_id=2105297674,前面带了文字,回读确认有图片段)
实现要点:
1. img_bridge.load(image) 统一把 URL / base64 / data URL / 容器内路径读成字节;
2. 优先 img_bridge.to_snowluma() 写到 core↔SnowLuma 共用目录(宿主 /opt/snowluma/data/stickers, core 里 /opt/snowluma-data/stickers,snowluma 里 /app/data/stickers),把 snowluma 侧路径 交给 send_private_msg / send_group_msg 的 image 段;失败退 base64://;
3. 发完用 get_msg 回读确认图片段真的在(返回里那句「回读确认有图片段」就是它)。
4. v1.5.1 加入的重试自愈:call_action 遇到 unauthorized / retcode 1401,会从 /opt/snowluma-data/config/onebot_.json 重新挑一个 HTTP token 再试一次;send_image 每条通道各试 2 次(鉴权失败就换 token,0.6s 后重试;其它失败退避 0.8s)。失败信息会把三次尝试的原话拼出来,不再是光秃秃一句 unauthorized。
入参可以是 dsh web 的路由地址:meme_render / sticker_send 返回的是… 这种 markdown(web 配置档下
origin() 有值,插件就不给文件路径了)。这种地址可以原样填进 image —— img_bridge.load
会自己去 127.0.0.1:8080 把图取下来(实测 /r/ 814 KB、/s/ 1.90 MB 都能发)。
为什么不用别的路子:set_qq_avatar 对 base64:// 直接报 avatar file is empty;QQ 消息里自带的图片地址带 rkey,SnowLuma 自己去拉会 401。发消息这条对三种写法都放行(实测 A 容器内路径、B base64://、 C file:///… 全部 retcode 0,回读都能看到 multimedia.nt.qq.com.cn 的下载地址)。
meme_render 的产物落在 /opt/dsh-home/nekowhale-stickers/renders/<hash>.gif,它返回的 Markdown 行里就带这个路径——直接把同一个路径喂给 qq_send_image 即可。
语音(让机器人开口说话,v1.6.0 起)
| 工具 | 作用 |
| qq_speak | 把文字念成 QQ 语音条发出去。text 要念的话(≤400 字)、target QQ 号/群号、kind private/group、voice 音色名、rate/volume 形如 +10% |
| qq_voice_list | 列出常用中文音色名,不发消息 |
{"name": "qq_speak", "arguments": {
"text": "我是大肥鱼,这条语音是本鱼自己说的,听到没。", "target": "123456789", "kind": "private" }} // → 已经用语音说了(28.3 KB,音色 zh-CN-XiaoyiNeural,message_id=1771999584,回读确认是语音条)
链路(和发图完全同构):
text → edge-tts(微软 Edge 朗读接口,免密钥,装 pip 包即可)合成 mp3 → 写进 core↔SnowLuma 共用目录(img_bridge.to_snowluma(..., "audio/mpeg", ext=".mp3")) → OneBot send_private_msg / send_group_msg 的 {"type":"record","data":{"file":"/app/data/stickers/xxx.mp3"}} → SnowLuma 自己把 mp3 转 SILK 发出去 → get_msg 回读确认 record 段
为什么不直接用 qq-bridge 的 qq_send_voice:它只认 /opt/qq-bridge/audio/ 语音库里的现成文件(allowAbsolutePath:false),而且 cfg.socialV2.tools.sendVoice 默认 false → 工具根本不注册,还要 core 里有 ffmpeg/ffprobe 才能过音量归一化。我们要的是「现说现发」,所以绕开它。
snowluma 容器里有 ffmpeg 5.1.9,转码那一步由它做,core 不必装 ffmpeg(省 ~250 MB)。
音色默认 zh-CN-XiaoyiNeural(少女感女声,最像「大肥鱼」);东北话 zh-CN-liaoning-XiaobeiNeural、陕西话 zh-CN-shaanxi-XiaoniNeural、粤语 zh-HK-HiuMaanNeural、台腔 zh-TW-HsiaoChenNeural 都有。
换默认音色:compose 里给 core 加 QZONE_TTS_VOICE=zh-CN-XiaoxiaoNeural。
已知边界:edge-tts 要出网访问 speech.platform.bing.com(本机已验证通,4.8 秒 mp3 用了约 1 秒);合成失败会明确区分「出网不通/音色名不对」;单条上限 400 字(QZONE_TTS_MAX_CHARS 可调)。
配置
/opt/qzone-data/config.json(容器内),宿主上是 /opt/core/qzone-data/config.json:
{
"onebot": { "httpUrl": "http://snowluma:3000", "accessToken": "<SnowLuma HTTP token>" },
"qzone": { "timeout": 30, "cookieTtl": 1800, "defaultUgcRight": 1 },
"wall": { "enabled": true, "name": "表白墙", "template": "【表白墙】\n{text}",
"anonymousSuffix": "\n—— 匿名", "maxLength": 800 },
"schedule": { "enabled": false, "times": ["09:30","14:30","21:00"],
"offsetMinutes": 20, "ugcRight": 1, "texts": [] }
}
- QZONE_ONEBOT_URL / QZONE_ONEBOT_TOKEN 覆盖 onebot 段。不要用 ONEBOT_TOKEN(那是 qqd 的 WS token)。
- SnowLuma 的 HTTP(3000) 与 WS(3001) token 是两个不同的值,这里要 HTTP 那个。
- 表白墙数据:/opt/qzone-data/wall.db(sqlite)。
- 定时说说只在 MCP 进程活着时生效;qzone_schedule_set 会即时重载,不用重启。
运维
改了插件代码必须重建(COPY 进镜像的,compose up -d 不重建)
cd /opt/core && docker compose up -d --build
看 MCP 是否被 DSH 拉起来
docker logs core 2>&1 | grep -i qzone
协议自检
printf '%s\n' \
'{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18"}}' \
'{"jsonrpc":"2.0","id":2,"method":"tools/list"}' \
| docker exec -i core python3 /opt/qzone-mcp/server.py
直接调一个工具
printf '%s\n' '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}' \
'{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"profile_get","arguments":{}}}' \
| docker exec -i core python3 /opt/qzone-mcp/server.py
已知边界
- get_status 只回 {online, good, time},拿不到当前 status/ext_status,所以 profile_get 只报「在线/离线」。
改完状态要确认效果,看 QQ 客户端上的机器人名片。
- get_unidirectional_friend_list 在 SnowLuma 这版会抛 protobuf invalid wire type 6(SnowLuma 侧 bug),所以这个工具没做,别去加。
- profile_likes 里 QQ 常常不下发昵称(nick 为空),只能显示 QQ 号与次数。
- profile_set_avatar 已实现但未实机验证(换头像对用户可见,等你自己点头再动)。
- 点赞接口上游注明「接口显示成功但实测点赞无效」;这里沿用同一端点(http:// 的 unikey 才记赞)。
- 图片上传(up.qzone.qq.com)上游标为「较脆弱」,失败会报错而不是静默。
- 访客接口只返回 items,字段随 QQ 版本变化时可能少名字;动态流深翻页需时间游标,这里只取首页。
白名单管理(admin_* 五个工具,v1.2.0 起)
为什么要这组工具:qq-bridge 的白名单闸门在「消息进 agent 之前」,所以以前想加人只能登录服务器改 config.json 再重启容器 —— 你在 QQ 里跟机器人说「把谁加白」是没人接的。
现在怎么做:直接说人话,agent 会调工具。
| 你说 | agent 调 | 效果 |
| 「看下白名单」 | admin_whitelist_show | 列出模式 / 管理员 / 私聊白名单 / 群白名单 |
| 「把 123456 加进白名单」 | admin_whitelist_add {kind:private, ids:["123456"]} | 那个人能私聊机器人 |
| 「把群 987654321 加白」 | admin_whitelist_add {kind:group, ids:["987654321"]} | 那个群能 @ 机器人 |
| 「把 123456 删掉」 | admin_whitelist_remove | 立即不再响应 |
| 「白名单只留 123456789」 | admin_whitelist_set | 整份替换 |
| 「管理员改成 xxx」 | admin_set_owner | 换 ownerQQ |
实现路径(为什么不用重启):
qzone-mcp (MCP server)
└─ POST http://127.0.0.1:3100/api/whitelist ← qq-bridge 自带控制台 API header: x-console-token: $(cat /opt/qq-bridge/state/console-token) └─ qq-bridge: atomicWriteJson(config.json) + cfg.allow 热更新 + reconcileSessionPolicies()
踩过的坑(重要):/opt/qq-bridge/config.json 是单文件 bind mount(./qbridge/config.json:/opt/qq-bridge/config.json),容器内对它 rename(2) 恒返回 EBUSY → qq-bridge 的 atomicWriteJson 抛错 → 控制台所有「改配置」接口 500,工具报 OSError(16, 'Device or resource busy')。修法:构建期用 core/patch-qqbridge.js 给 renameWithRetry 打一条退化路径(rename 反复 EBUSY 就原地覆盖写),core/Dockerfile 里 RUN node /tmp/patch-qqbridge.js。
本插件自己的 patch_file() 也有同样的 EBUSY 退化,作为控制台彻底不通时的保底(那种情况要 docker restart core 才生效,返回值里会写明)。
验证过:加群 → config.json 里 groups: [987654321] 落盘 → qq-bridge 日志 控制台:白名单已更新(群: 987654321,私聊: 123456789,管理员: 123456789) → 移除后回到 groups: [],全程没重启容器。预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
ChuYanSir/qzone-mcp
发说说、改资料、管好友,一个插件全搞定
相关插件 · 平台集成
智能体工程课walkinglabs/learn-harness-engineering
一门项目制课程,教你搭建环境、管理状态、做验证、加控制机制,让 AI 编程智能体稳定干活。
★ 21,155已汉化DSH
71.7
视频翻译配音liuzhao1225/YouDub-webui
开源视频本地化工作台:导入视频,识别、翻译并逐句克隆原声,生成字幕和配音成片。
★ 5,778已汉化Cordis
71.4
失败经验库Ikalus1988/MisakaNet
📚 零依赖、由 git 支撑的微课程库,让 AI 智能体异步分享并检索经过验证的调试经验。| https://misakanet.org
★ 550已汉化DSH
71.2
桌面智能体工作区freestylefly/wesight
WeSight 是开源桌面控制台,面向本地 AI 智能体。它帮你安装或复用 Claude…
★ 933已汉化MCP
71
IM 机器人接入xmanrui/dsh-im
让 DeepSeek Harness 触手可及 Connecting DeepSeek Harness
★ 3,110已汉化DeepSeek 客户端
70.9
中国平台研究引擎Jesseovo/last30days-skill-cn
给 AI Agent 的中文互联网研究 Skill:检索 8 大平台最近 30…
★ 2,031已汉化DSH
70.7