screenshot-feedback-hook-mcp
by lkh081231
README.md
# screenshot-feedback-hook-mcp 👁
**中文** | [English](README.en.md)
### dsh 用户请跳转到[dsh-plugin/README.zh.md——中文](dsh-plugin/README.zh.md)|[dsh-plugin/README.md——English](dsh-plugin/README.md)
**让 coding agent 看到自己产出的真实画面** —— 跨平台截图反馈工具(MCP server + Claude Code hook 双层)。
Let your coding agent **see what it builds**: a cross-platform (Windows / Linux / macOS) screenshot-feedback tool for AI agents, shipped as an MCP server plus a Claude Code hook helper.
## 为什么需要它 / Why
Agent 写前端、画 EasyEDA/CAD 工程图时,没有视觉反馈就只能猜。给它一个「截图 → 看图 → 自我纠正」的回路,产出质量立刻不一样。
技术现实:Claude Code 的 **hook 只能回传文本**,而 **MCP 工具可以回传原生图片**。所以本工具做成双层:
| 层 | 触发方式 | 图片如何进入 agent 视野 |
|---|---|---|
| **MCP server** | agent 主动调用 `take_screenshot` | 工具直接返回原生图片块(跨 MCP 客户端通用) |
| **Claude Code hook** | 某操作后自动触发 | hook 回传截图的绝对路径,agent 用 Read 工具读图 |
| **DeepSeek Harness 插件** | agent 主动调用,或操作后 / 轮次结束时自动触发 | 截图存进 dsh 的持久附件库,作为图片块直接进上下文,**agent 什么都不用做** |
图片默认降采样(最长边 1568px)并按**字节预算**(~80KB)迭代压缩 JPEG,避开 Claude Code 对 MCP 输出 ~25k token 的限制。
> [!TIP]
> **推荐工程师 / 非程序员用户:直接让 AI agent 替你安装配置,没必要手动编辑 JSON。**
> 在 Claude Code 里说一句「帮我安装并配置 screenshot-feedback-hook-mcp」,agent 会按下文 [hook 配置](#接入-claude-code-hook操作后自动截图) 的提示先问清你的使用场景(看什么画面、渲染多久、何时截图),再替你写好 MCP + hook 配置。想自己动手的见下面的手动步骤。
## 安装 / Install
零安装运行(需要 [uv](https://docs.astral.sh/uv/)):
```bash
# MCP server(无参数 = MCP server)
uvx screenshot-feedback-hook-mcp
# CLI 截图(带子命令 = CLI)
uvx screenshot-feedback-hook-mcp capture --monitor 0 --out shot.jpg
uvx screenshot-feedback-hook-mcp monitors
```
或常驻安装:`pipx install screenshot-feedback-hook-mcp` / `uv tool install screenshot-feedback-hook-mcp`。
## 接入 MCP(推荐起点)
Claude Code 一行:
```bash
claude mcp add screenshot-feedback -- uvx screenshot-feedback-hook-mcp
```
或任意 MCP 客户端(Cursor / Cline / Windsurf...)的 mcp.json:
```json
{
"mcpServers": {
"screenshot-feedback": {
"command": "uvx",
"args": ["screenshot-feedback-hook-mcp"]
}
}
}
```
工具:
- `take_screenshot(monitor=0)` —— 截屏,直接返回图片。0=全部显示器拼接,1..N=单屏。
- `list_monitors()` —— 列出显示器编号/分辨率。
## 接入 DeepSeek Harness(dsh 原生插件)
[DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) 用户请走原生插件,别走上面的 MCP:dsh 有持久图片附件服务,插件可以把截图直接变成图片块推进上下文,**agent 不需要主动调任何工具**。
```sh
dsh plugin --profile web add dsh-screenshot-feedback-hook-mcp
dsh web
```
本包是一个 dsh **组合包(bundle)**:`package.json` 里的 `dsh.bundle.patch` 指向包内自带的 [cordis.patch.yml](dsh-plugin/cordis.patch.yml)。`dsh plugin add` 认出这个 manifest 后,会把包名追加进 profile 的 `dsh.profile.bundles`,那一层 patch 随即组合进配置树 —— **你不需要手写任何 patch**。装完用 `dsh --profile web --dump-config` 能看到多出来的 `# == dsh-screenshot-feedback-hook-mcp` 层和 `id: screenshot-feedback` 那一行。
要求 dsh ≥ `v0.1.0-rc.8`、PATH 上有 pnpm、Python 包 ≥ 0.3.0、插件 ≥ **0.2.0**,以及**一个支持图片输入的模型**。
> [!CAUTION]
> **插件 0.1.0 有严重缺陷,装了会让该 profile 里的所有工具调用崩掉**(不只是截图)。请升级到 ≥ 0.2.0,升级步骤见 [dsh-plugin/README.zh.md](dsh-plugin/README.zh.md#从-010-升级必看)。
> [!IMPORTANT]
> **DeepSeek 的 `deepseek-v4-flash` 和 `deepseek-v4-pro` 都是纯文本模型**,rc.8 的内置 `deepseek-official` 路由也没有自带任何视觉模型。用它们的话截图根本进不了上下文(dsh 会在发请求前拒掉),所以插件会跳过截图并告诉你怎么换:在「设置 → 模型」加一个 Anthropic / OpenAI 等 catalog provider 选视觉模型,或给自定义 provider 的模型声明 `input: [text, image]`。注意**设置页填不了模态** —— 加完模型要点「打开配置文件」,在 `settings.yaml` 里手工补这个字段(`llm-deepseek` 下叫 `inputModalities`)。
装好后可以在 **设置 → 插件 → 插件配置 → 截图反馈** 那张卡片上直接调参(显示器、各种等待时间、两个默认关闭的自动截图时机等),存完免重启即生效。完整字段表与工作原理见 [dsh-plugin/README.zh.md](dsh-plugin/README.zh.md)。
## 接入 Claude Code hook(操作后自动截图)
> [!IMPORTANT]
> **如果你是替用户配置本工具的 AI agent:在写入任何 hook 配置之前,请先询问用户的使用场景。** hook 的正确配置高度依赖场景,盲配多半会截到无关画面或时机不对。至少要问清:
> 1. **要看什么画面?** 前端页面(浏览器)、工程图(EasyEDA/CAD 等桌面应用)、还是别的?决定 `--monitor`(视觉输出在哪个屏幕)。
> 2. **画面渲染/刷新需要多久?** 浏览器热重载约 1–2s,EDA/CAD 重绘可能更久 → 决定 `--delay`。
> 3. **什么时候截?** 每次 Claude 停下来时(`Stop`,最省心)还是每次改完文件后(`PostToolUse` + matcher,更密集)?
> 4. **配在哪一层?** 仅当前项目(项目 `.claude/settings.json`)还是所有项目(用户级 `~/.claude/settings.json`)?
>
> 问清后再从下面的模板里挑一个、填好参数写入。不要默认照抄。
### 手动配置步骤
**第 1 步 · 选触发时机**
| 触发 | 何时截图 | 适合 |
|---|---|---|
| `Stop` | Claude 每次回答结束时截一张 | 大多数场景,频率适中、省心 |
| `PostToolUse` | 每次匹配到的工具(如 `Edit`/`Write`)执行后截 | 想在每次改动后立刻看到效果 |
**第 2 步 · 按场景填参数**
- `--monitor N`:视觉输出所在的显示器。`0`=全部拼接,`1..N`=单屏。先跑 `uvx screenshot-feedback-hook-mcp monitors` 看编号。
- `--delay 秒`:截图前等待,确保画面渲染完成(前端 `1`、EDA/CAD 视渲染速度可设 `2`~`5`)。
- `--max-edge 像素` / `--target-kb 体积`:一般用默认即可(最长边 1568px、~80KB)。
**第 3 步 · 写入 `.claude/settings.json`**
项目级配置放项目根目录的 `.claude/settings.json`;想全局生效放用户级 `~/.claude/settings.json`。模板见下方与 [examples/](examples/)。
**第 4 步 · 验证**
重启 Claude Code 会话,触发一次对应事件,确认 Claude 收到「截图已保存到 …」并主动用 Read 读了图。
### 模板 A:每次 Claude 停下来时截图(`Stop`,推荐起点)
```json
{
"hooks": {
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "uvx screenshot-feedback-hook-mcp capture --delay 1 --hook-output stop"
}
]
}
]
}
}
```
### 模板 B:每次改完文件后截图(`PostToolUse`)
```json
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "uvx screenshot-feedback-hook-mcp capture --delay 2 --hook-output post-tool-use"
}
]
}
]
}
}
```
### 原理
CLI 会输出正确的 hook JSON(`Stop` 用 `decision:block` 回传文字并自动处理 `stop_hook_active` 防死循环;`PostToolUse` 用 `hookSpecificOutput.additionalContext`),agent 看到「截图已保存到 …,请用 Read 工具读取」后会读图。因为 **hook 只能回传文本**,所以走「回传路径 + agent 用 Read 读图」这条路;想让 agent 直接拿到图片块请用上面的 MCP 方式。
## 平台注意事项 / Platform notes
- **Windows**:开箱即用。
- **macOS**:首次使用需在「系统设置 → 隐私与安全性 → 屏幕录制」勾选运行 agent 的终端/IDE 并重启该应用。未授权时截到的**不是黑屏,而是壁纸 + 菜单栏** —— 其他应用的窗口一个都不在图里。
> ⚠️ **未授权不一定会被检测出来,请先手动验证一次。** 现在的检测是事后启发式(`core/platform_check.py` 的 `capture_warning`):把画面缩到 16×16 看灰度极差,只有**接近纯色**(纯黑、纯色壁纸)才会给出提示。**照片壁纸下不会触发**,而那正是 macOS 的默认样子。也就是说你可能拿到一张「看起来完全正常的桌面截图」、一句警告都没有,而你要看的窗口根本不在图里 —— 比黑屏更难察觉,agent 会以为是自己的页面没渲染出来,跑去 debug 一份没问题的代码。
>
> 在授权确定之前,先手动跑一次 `uvx screenshot-feedback-hook-mcp capture --out shot.jpg` 并亲眼看一下图里有没有你的窗口,再交给 agent。
>
> 确定性的检测(`CGPreflightScreenCaptureAccess()`,与画面内容无关)在 roadmap 上,缺一台 macOS 机器验证。
- **Linux**:X11 开箱即用;**纯 Wayland 下 mss 受限**,工具启动时会探测并提示(grim/portal 后端在 roadmap)。
## Roadmap
- [ ] 区域截图(`--region x,y,w,h`)
- [ ] 按窗口标题截图(Win EnumWindows / mac CGWindowList / Linux wmctrl)
- [ ] URL / 无头浏览器模式(前端确定性截图)
- [ ] Wayland 后端(grim / xdg-desktop-portal)
- [ ] macOS 屏幕录制授权的确定性检测(`CGPreflightScreenCaptureAccess`),替掉现在会漏检照片壁纸的纯色启发式
## 开发 / Development
```bash
uv sync # 安装依赖
uv run pytest # 测试
uv run screenshot-feedback-hook-mcp capture --out shot.jpg # CLI
uv run screenshot-feedback-hook-mcp # MCP server
```
MIT License.
TDQS
A4.4/5.0
Scored across 2 tools
Disambiguation5/5
The two tools have clearly distinct purposes: one lists available monitors, the other takes screenshots. There is no overlap or ambiguity.
Naming Consistency5/5
Both tools use consistent snake_case naming (list_monitors, take_screenshot), following a clear verb_noun pattern.
Tool Count4/5
With only 2 tools, the server is minimal but well-scoped for its specific purpose of screenshot feedback. It is on the lower end of the ideal range but not inappropriate.
Completeness5/5
The tool set covers the essential workflow: checking available monitors and taking screenshots. No obvious gaps for the stated use case.