sticker-sense
This server does not currently have a deployable release on Glama. Follow the repository's setup instructions to install and configure it for your MCP client, including any required credentials and local dependencies.
sticker-sense
给你的 AI 一个能"读懂"的表情包图库。
你发表情,它知道你在说什么情绪;你解释一次,它下次就记住。所有数据都在本地。

它解决什么问题
AI 看得见表情包的画面,但不懂梗。同一个"微笑",可能是礼貌敷衍,也可能是"我现在很想打人"。这种差别不在像素里,在你们共同的使用史里。
所以这个项目不训练模型,而是外挂一层语义记忆:
一张表情可以有多条读法,每条带语境提示
你解释一次,它写进库;下次同一语境再出现,直接用
读法只影响 AI 的语气,不会让它复述"我识别到这是第 3 号表情"——那样聊天感就毁了
三个入口都通了:桌面挂件(点一下粘进输入框)、MCP server(AI 自己调)、网页管理端(批量维护)。
Related MCP server: cove-sticker-mcp
快速开始
git clone <this-repo> && cd sticker-sense
python -m venv .venv
.venv/bin/pip install -r requirements.txt # Windows: .venv\Scripts\pip install -r requirements.txt
# 0. 先看看效果(生成 6 张示例小黄脸并写入读法)
python scripts/make_demo.py && python scripts/seed_demo.py
# 1. 导入自己的表情包(整个目录也行)
python -m sticker_sense.cli import ./我的表情包
# 2. 看看导入了什么
python -m sticker_sense.cli list
# 3. 给某张写读法(这才是"训练")
python -m sticker_sense.cli tag b0351e "无语到不想解释" --context "对方说了明显不合理的话时"
python -m sticker_sense.cli tag b0351e "礼貌性敷衍" --context "不想继续这个话题但不好直接拒绝"
# 4. 拿一张图问它这是什么(也可以直接喂降质后的图)
python -m sticker_sense.cli identify ./某张截图.png
# 5. 打开网页管理端(导图、看读法、改绑定)
python -m sticker_sense.cli admin
# 6. 接进 AI(二选一或都装)
python hooks/install_mcp.py # MCP server:让 AI 自己调
python hooks/install_hooks.py # 桌面挂件:点球弹面板数据默认在 ./data,用 --data 换位置,或者设 STICKER_DATA 环境变量。
三种入口
一、桌面挂件(Windows)

装一次,之后跟着 agent 自动起停。点球弹面板,点表情直接粘进输入框。
python hooks/install_hooks.py # 安装
python hooks/install_hooks.py --remove # 卸载二、MCP server
python hooks/install_mcp.py会往 ~/.workbuddy-ai/mcp.json 写一条 sticker-sense(也支持 --config 指定 Claude Desktop 的配置)。重启客户端后对这个 server 点「信任」。
之后 AI 就能自己调这 7 个工具:
工具 | 方向 | 作用 |
| 用户 → AI | 认一张图,返回 ID + 全部读法 |
| 用户 → AI | 取用户刚在挂件里点的 ID(比图像识别准,3 分钟内有效) |
| 查询 | 列出图库 |
| 查询 | 看某张的全部读法 |
| AI → 库 | 写入一条读法(唯一的"训练"入口) |
| AI → 库 | 导入图片或目录 |
| AI → 用户 | 反向:AI 从图库里挑一张发给你 |
协议是 stdio 上的 JSON-RPC 2.0,手写的,没有 MCP SDK 依赖。scripts/test_mcp.py 真起进程跑协议,18 项断言。
三、网页管理端

python -m sticker_sense.cli admin # 默认 http://127.0.0.1:8777
python -m sticker_sense.cli admin --port 9000 --no-open批量拖图导入、逐张看读法、补读法、绑定相似图、对误判的读法降权。支持 #<id> 直链。
只绑 127.0.0.1,只在本机开。

入口为什么这么难做
这是整个项目最容易做错的地方,所以单独说。
MCP 协议做不出"输入框下方的常驻按钮"。MCP Apps 的 ui:// 组件只能渲染在工具调用的结果气泡里,宿主不给你往输入框区域注入 UI 的权限。所以常驻按钮只有两条路:改客户端源码,或者写浏览器扩展(每个站点单独适配 DOM,改版就坏)。
实际可用的入口,按体验排:
入口 | 怎么做 | 代价 |
桌面挂件 | 装一次 hook,之后跟着 agent 自动起停;点球弹面板,点表情自动粘进输入框 | 需要一次安装 + 重启客户端 |
MCP 工具 | AI 自己调 | 需要客户端支持 MCP |
斜杠命令 | 输入 | 要打字,零安装 |
独立网页 |
| 要切窗口 |
挂件怎么跟着 agent 起停
用 WorkBuddy / CodeBuddy 的 SessionStart hook,不碰系统开机启动项:
python hooks/install_hooks.py # 安装
python hooks/install_hooks.py --remove # 卸载它会往 ~/.workbuddy-ai/settings.json 的 hooks.SessionStart 写一条命令,
每次会话启动时拉起挂件。
三个实现要点:
fail-open:hook 里任何异常都静默退出 0。挂件没装好、Python 没配好, agent 照常启动,绝不阻塞。
立刻返回:hook 默认 60 秒超时,所以只 fire-and-forget,不等待。
单实例:靠命名互斥量去重,重复触发无害。
还有一个不那么显然的坑:hook 的子进程会被连带杀掉。agent 通常把 hook
放在 Windows Job Object 里执行,命令一结束就回收整棵进程树。实测
CREATE_BREAKAWAY_FROM_JOB 会被拒绝(WinError 5,作业不允许 breakaway),
所以拉起挂件走的是 WMI 的 Win32_Process.Create——进程由 WmiPrvSE 服务创建,
父进程不是 hook,天然不在那个作业里,能活到用户关掉 agent。
WMI 不可用时才退回普通 detached。
装完必须完全退出客户端再启动——hook 配置在启动时缓存,热改无效; 点窗口关闭按钮不算退出,要真正结束进程。
挂件怎么约束在 agent 窗口内
不是满屏乱飘的悬浮球。三个机制:
用
EnumWindows按进程名找到 agent 主窗口,GetWindowRect拿到矩形前台跟随:宿主在前台才置顶显示,切到别的应用就收起。这样既不会被 宿主窗口盖住,也不会飘在别人的窗口上面
拖动时把坐标夹在宿主矩形内,面板弹出位置也夹在同一范围
试过用 SetWindowLongPtr(GWLP_HWNDPARENT) 把自己设成宿主的附属窗口,但
tk 的 overrideredirect 窗口上这个调用不生效(GetWindow(GW_OWNER) 恒为 0),
所以改用前台跟随。
宿主窗口消失(agent 重启换了新句柄)时,挂件不退出,而是重新找宿主接着跟—— 如果这里自杀,新会话的 hook 又会被单实例互斥量挡掉,最后两头落空。 连续五分钟找不到宿主才结束进程。
挂件怎么把表情塞进输入框
点表情时同时往剪贴板写两种格式——CF_DIB(图片)和 CF_UNICODETEXT
([sticker:id] 标记)。富文本输入框优先粘图片,纯文本框退化成粘标记,
两种都不会落空。然后恢复焦点到原窗口、模拟 Ctrl+V。
焦点恢复用 AttachThreadInput 绕过 Windows 的前台锁,否则 SetForegroundWindow 会静默失败。
这里有个容易漏掉的细节:点球这个动作本身会把前台抢到挂件身上。所以记录
"粘贴目标"时必须排掉自己的窗口,否则记下来的是挂件自己,粘回去就粘进挂件里了。
clipboard.pick_target() 负责这件事——前台不是自己就用前台,是就退回宿主窗口。
关键设计:点击回传的是 ID,不是图片。ID 精确、零误差,绕开了图像识别的所有不确定性。
挂件粘贴图片时会把 ID 写进 data/last_pick.json,AI 读它就能拿到精确身份
(MCP 的 last_pick 工具就是干这个的)。
只有用户直接粘贴别处的图片时,才退回 dHash 指纹识别。
识别是怎么做的
三级指纹,级联匹配。这里的选择都是被实测逼出来的,不是拍脑袋:
层级 | 内容 | 解决什么 |
sha256 | 文件字节 | 同一文件精确命中,零成本 |
粗筛 | 8×8 dHash × 4 个裁剪尺度 | 压缩、缩放、裁剪后仍能命中 |
细排 | 16×16 dHash + 颜色色度网格 | 区分"同模板换字/换色"的姐妹表情 |
几个踩过的坑,写下来免得再踩:
单尺度 dHash 扛不住裁剪。用户截图裁掉 15%,汉明距离从 0 跳到 25,直接认不出。所以存 100%/85%/70%/55% 四个尺度的中心裁剪指纹。
8×8 dHash 分不清同模板表情。64 位太粗,两个字形的差别在网格里都糊成"中间一坨"。所以加 16×16 做细排。
绝对 RGB 做颜色指纹会被亮度带偏。测过一次 +15% 亮度就把正确结果挤成误判。改成存色度
(r/s, g/s),亮度无关。不用 CLIP embedding。这里要解决的是"认出同一张图",不是"找到语义相似的图"。CLIP 会把所有"无语"的表情判成高度相似,正好让问题更糟。
匹配不只看分数,还看 margin(最佳与次佳的分数差)。margin 太小就标 ambiguous,宁可说"不确定"也不自信地认错。
阈值都在 sticker_sense/hashing.py 顶部,按自己的图库分布调。
数据长什么样
三张表,SQLite + WAL(管理端和 AI 服务是两个进程并发写,JSON 加锁在 Windows 上很难做对):
stickers:一张图一行,存 sha256 和多尺度指纹readings:一张表情可以挂多条读法,meaning+context_hint+confidence+usesaliases:人工绑定的相似图(同一表情的不同截图版本)
读法只降权,不硬删。管理端的"降权"把 confidence 打到 0.4 倍,删了就再也找不回来,降权还能反悔。
想拿人类可读的版本:python -m sticker_sense.cli export out.json。
自测
python scripts/make_demo.py # 生成 6 张示例小黄脸
python scripts/selftest.py # 识别:正样本 5 项 + 负样本 4 项
python scripts/test_mcp.py # MCP 协议:真起进程跑 JSON-RPC,18 项
python scripts/test_admin.py # 管理端:真起 HTTP server 打接口,15 项
python scripts/diagnose.py # 打印降质探针与全库的打分矩阵,用来调阈值当前基线:识别 9/9(压缩、放大、裁剪、调亮度、截图转发全部命中;库里没有的图全部拒绝),MCP 18/18,管理端 15/15。CI 在 Ubuntu + Windows × Python 3.10/3.12 上跑这三套。
命令一览
命令 | 作用 |
| 导入图片或目录,按 sha256 去重 |
| 识别,返回命中的表情与全部读法 |
| 写入一条读法, |
| 查看某个表情的全部读法 |
| 列出图库 |
| 记一次使用,让高频读法排到前面 |
| 人工绑定:告诉库这张图属于哪个 id |
| 导出人类可读的 JSON |
| 输出可点击面板的 HTML 片段(内联 widget 用) |
| 生成独立的可点击面板网页 |
| 启动桌面悬浮挂件(需 tkinter,Windows) |
| 以 MCP server 运行(stdio JSON-RPC) |
| 启动本地网页管理端 |
平台支持
能力 | Windows | macOS / Linux |
图库 / 识别 / 读法 | ✅ | ✅ |
MCP server | ✅ | ✅ |
网页管理端 | ✅ | ✅ |
桌面挂件 | ✅ | ❌ 未实现(依赖 Win32 剪贴板与窗口 API) |
挂件部分用了大量 Win32 调用(AttachThreadInput、PrintWindow、Job Object),
macOS 需要另写一套 NSPasteboard + Accessibility 实现,欢迎 PR。
路线图
图库 + 三级指纹 + 多义读法
负样本拒绝与歧义标记
点击回传入口(内联 widget,点击发出带 ID 的标记)
独立面板网页(不依赖客户端能力)
桌面悬浮挂件(点一下自动粘进输入框)
MCP server(AI 自己调 identify / tag / pick)
最小网页管理端(批量导图、看读法、改绑定)
反向能力:AI 也能从同一个库挑表情发给你
macOS 挂件
读法自动聚类(把语义重复的读法合并,减少手工维护)
版权
仓库不内置任何表情包。demo/ 里的占位图由 scripts/make_demo.py 生成,仅用于测试。
表情包绝大多数是影视、动漫、明星截图,二次分发有实际风险,请只导入自己有权使用的图片。
License
MIT
This server cannot be deployed
Maintenance
Related MCP Connectors
Private memory, scratchpads, context export/restore and task handoff for AI agents.
Persistent memory for AI agents. Search, store, and recall across sessions.
Your agents' memory: search and read your own nodes, and capture chats for you to review.
Universal memory for AI agents and tools. Save, organize and search context anywhere.
Related MCP Servers
- AlicenseAqualityDmaintenanceEnables AI to send expressive stickers based on conversation context, with a built-in UI for managing stickers.57MIT
- AlicenseNot gradedqualityBmaintenanceLocal-first custom sticker library for MCP agents, enabling image import, auto-tagging, search, and context-aware retrieval via standard MCP tools.39MIT
- FlicenseNot gradedqualityCmaintenanceEnables users to upload and tag stickers and GIFs through a web page, then lets Claude browse, select, add, retag, or delete them so it can send an image matching the mood of a conversation. Returns ready-to-paste markdown image links that render in markdown-capable chat interfaces.3-
- AlicenseNot gradedqualityBmaintenanceEnables users to import, tag, search, and retrieve custom stickers by context through MCP, with optional vision model tagging and backup/restore, all local-first and portable.MIT