captcha
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.
captcha-solver — 给 agent 用的本地验证码插件
把验证码识别做成 agent 可以直接调用的工具:文字、算术、滑块、点选、旋转五类, 本地推理,不外传图片;识别不了的再按需上报远端服务。
插件以 MCP server 的形态提供能力,所以同一个后端可以挂到任何支持 MCP 的 agent(DSH、Claude Desktop、Cursor、自研框架),也可以当普通 HTTP 服务用。
工具面
在 DSH 里工具名会带命名空间前缀:mcp__captcha__captcha_solve、
mcp__captcha__captcha_slider、mcp__captcha__captcha_click、
mcp__captcha__captcha_status、mcp__captcha__captcha_bench。
工具 | 作用 | 关键参数 |
| 一次识别,返回要提交的 |
|
| 定位滑块缺口,返回 |
|
| 点选验证码,返回有序点击坐标 |
|
| 生成人性化拖拽/点击轨迹(缓动 + 变速 + 抖动 + 回弹) |
|
| 报告当前可用的识别引擎 | — |
| 跑合成语料基准,输出各类准确率与耗时 |
|
统一返回结构(captcha_solve):
{
"kind": "text",
"answer": "G9DPM",
"confidence": 96.7,
"candidates": [{"text": "G9DPM", "score": 96.7, "support": 3, "variants": ["ddddocr@1x", "otsu", "raw_l"]}],
"elapsed_ms": 812,
"recommendation": "submit the answer"
}confidence < 55 就别硬提交,刷新验证码重来或补 charset/length 提示——这比
在错误答案上重试更省时间。
Related MCP server: atlas-browser-mcp
引擎
三级流水线,按需叠加,每一级都产出候选、最后做加权投票:
神经分类器(ddddocr + onnxruntime)—— 文字/点选的主力,对常见验证码字体最稳。
Tesseract 5 多配置集成 —— 12 组预处理变体(Otsu、自适应二值化、去干扰线、 中值去噪、3 倍放大、锐化、反色、去斜)+ psm 7/8/13 组合,按置信度投票。
字体模板匹配 + 字形分割 —— 用系统字体合成字形库做归一化互相关, 对标准字体渲染的验证码是"作弊级"准确,也是
charset很窄时的兜底。
滑块不看 OCR:用 2-D 边缘归一化互相关(FFT 实现,纯 numpy) 在背景上做多尺度 模板匹配,带尺度先验(piece 通常与背景 1:1)与左侧伪峰抑制;只有合成截图时改走 局部方差平坦块检测(二值连通域 + 形状过滤),找被挖走的那块矩形。
算术走结构化解析,不再依赖整串 OCR:笔画几何识别 + - =(实心细条 vs 两段
细条 vs 十字交叉),字形模板读数字,= 位置把尾巴的 ? 直接切掉;再和"算子切分
(几何定算子、OCR 读两侧数字)"、"= 左侧裁剪整串 OCR"两条路线互相印证取最
可信的结果——=? 被读成数字这类错误就是靠这个消掉的。
算术的求值拆到 expression.py:真正的递归下降解析器,+ - 与 * / 分级、
支持括号与一元负号、内部用 Fraction 保证精确(7/2 输出 7/2 而不是 3.5)。
单运算符仍走原来的严格整串匹配(a op b 才认),因为 solve_arithmetic 的
跨路线投票正是靠这种严格性起作用的;只有当一次读数里真的出现 ≥2 个运算符时,
才由 ocr.eval_chain 接管,按运算优先级求值。这样"支持 10+3*3+8"不会把
单运算符的仲裁逻辑放松掉:
>>> ocr.eval_arithmetic("10+3*3+8答案是?")
{'expr': '10+3*3+8', 'answer': '27', 'operator': '+', 'operators': ['+', '*', '+'], 'operands': [10, 3, 3, 8]}
>>> ocr.eval_arithmetic("5+3=?") # 单运算符:严格语义不变
{'expr': '5+3', 'answer': '8', 'operator': '+'}arith.py + symbols.py 是实验性的结构化算术引擎(kind=arith_multi):多阈值
扫描、斜线抑制 + 形态学重建、按字高分块、几何判 + - = *、真图/合成图的真实成绩见
下面"多运算符算术"一节——它目前没有接入 auto 路由。
旋转用全局角度扫描 + 逐位置投票:投影方差给出的角度只有量级可信、符号不可信,
所以按 ±est±10° 铺 6 个角度各做一次快速 OCR(只跑神经引擎 + 3 个 tesseract 变体),
长度按置信度加权投票选定,再逐字符加权投票出结果,最后在胜出角度上跑一次完整
流水线做收尾。
安装
cd .dsh-bundles/captcha-solver
./scripts/setup.sh # 建 .venv 并装 ddddocr/numpy/pillowscripts/setup.sh 默认使用清华镜像;换源:
./scripts/setup.sh https://pypi.org/simpleTesseract 是可选但强烈建议的兜底引擎:
brew install tesseract tesseract-lang为什么单独建 venv:DSH 自带的 Python 带 hardened runtime(library validation), 加载不了 onnxruntime 的
.so。venv 用非 hardened 的解释器,这才有神经引擎; 没有 venv 时插件仍能跑,只是退化为 tesseract + 模板两级。
接入 DSH
已注册到当前 profile(~/.dsh/profiles/desktop/cordis.patch.yml 里的 mcp-captcha
条目),重启 DSH 后生效,之后 agent 会多出 5 个 captcha_* 工具。
工具 schema 只用 DSH 支持的子集(type/properties/enum/items + 注解),
已用 assertSupportedJsonSchema 校验通过;协议用换行分隔的 JSON-RPC 2.0,
与 @modelcontextprotocol/client 的 stdio 传输一致,已用该 SDK 实测握手 + 调用。
首次在别的机器/别的 profile 里安装:
# 1) 装依赖
cd <repo>/.dsh-bundles/captcha-solver && ./scripts/setup.sh
# 2) 把 bundle 加进 profile 的 package.json(dependencies + dsh.profile.bundles),
# 或者直接把 cordis.patch.yml 里的 insert 段合并到 profile 的 patch 文件
# 3) 重启 DSH自检(不依赖 DSH):
printf '%s\n' \
'{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{}}}' \
'{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"captcha_status","arguments":{}}}' \
| ./run.shHTTP 用法(非 MCP 框架)
.venv/bin/python -m captcha_solver.service --port 8790
curl -s localhost:8790/health
curl -s localhost:8790/solve -d '{"image_path":"/abs/login.png","charset":"0123456789"}'
curl -s localhost:8790/slider -d '{"background_path":"/abs/bg.png","piece_path":"/abs/piece.png","handle_x":0}'
curl -s localhost:8790/click -d '{"image_path":"/abs/click.png","prompt":"请依次点击:明 天 快 乐"}'
curl -s localhost:8790/track -d '{"distance":185,"seed":7}' # 人性化拖拽轨迹 + 自检
curl -s localhost:8790/track -d '{"points":[[120,44],[300,88]]}' # 点选轨迹(时序 + 落点偏移)需要的话用 CAPTCHA_API_TOKEN 加 X-Api-Token 头做鉴权。
命令行
cd server
../.venv/bin/python -m captcha_solver.cli solve --image out/corpus/text_000.png \
--charset 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ --json
../.venv/bin/python -m captcha_solver.cli solve --image cap.png --kind slider \
--background bg.png --piece piece.png --overlay out/slider_debug.png
../.venv/bin/python -m captcha_solver.cli solve --image cap.png --kind arith_multi --json
../.venv/bin/python -m captcha_solver.cli bench --count 8准确率基准
合成语料(bench/gen_corpus.py,刻意加了字符旋转、干扰线、噪点、模糊)。
每类 12 张(60 张,调参用的主力集合,数字最保守):
kind acc n ms
arithmetic 83.3% 12 1310
click 100.0% 12 1090
rotate 100.0% 12 2489
slider 100.0% 12 13
text 91.7% 12 1325
OVERALL 95.0% 60 1245换到 Python 3.14 + onnxruntime 1.31 后重跑过一遍,overall 仍是 95.0%;算术类那两张 错的是
arith_007/arith_009——OCR 把干扰笔画读成第二位数字(41-18而非13-18),属于引擎版本的读法差异,不是求值逻辑的问题(求值见tests/test_expression.py)。
每类 6 张(30 张,最初那版语料,用来对比提升):
kind acc n ms (before)
arithmetic 100.0% 6 1523 66.7%
click 100.0% 6 1222 83.3%
rotate 66.7% 6 2854 66.7%
slider 100.0% 6 13 100.0%
text 83.3% 6 822 83.3%
OVERALL 90.0% 30 1287 80.0%复现:../.venv/bin/python -m bench.run_bench --dir out/corpus12
(报告写到 server/out/bench_report.json;bench.gen_corpus --count 12 重新生成语料)。
真实站点验证码多为标准字体、轻噪点,文字类通常明显高于这个数字;点选/旋转类受
艺术字影响更大。剩下的失败几乎都是"同形字":U/F、V/I、Z/2、J/1、0/O
——这类只看一帧像素本身就有歧义,工程的正确做法是低置信度时刷新换一张,而不是
硬猜(返回里的 confidence 就是给这个决策用的)。
参数提示能明显救回准确率:charset 收窄到真实字符集(如
0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ)后,文字类从 66.7% 升到 75%,点选从
75% 升到 100%。不传 charset 时默认按"数字+大写"处理;小写验证码请显式传
charset=0123456789abcdefghijklmnopqrstuvwxyz。
真实站点实测
合成基准再高也只说明管线没写错,能不能打要看真图。抓了 44 张真实验证码(每个接口各一次、 低频率、不登录不提交):
来源 | 类型 | 尺寸 | 数量 | 结果 |
| 5 位字母数字 + 波浪干扰 | 100×40 | 18 | 12/18 |
| 4 位字母数字 + 3D 描边 | 130×53 | 18 | 10/18 |
| 中文算术「a+b*c 答案是?」 | 200×100 | 8 | 0/8 |
去掉 5 张人眼也无法确定的(real_labels.json 里标 ?),字母数字类 22/31 = 71%,
中文算术 0/8。
复现:
# 图片放在任意目录,labels 是人工目视核对过的答案
../.venv/bin/python -m bench.real_eval --dir out/real --labels bench/real_labels.json真实数据打出的三个问题(已修)
单次推理不可信。 同一张图,ddddocr 在 raw / 反色 / 2 倍锐化 / Otsu 下的读法会不一样, 一张图只跑一次就下结论等于抽签。现在跑 8 个变体 + beta 模型(第二套网络),共 9 个读数进池子。
置信度是假的。 之前 ddddocr 每次都报 82%,错的也报 82%。现在置信度由证据强度算: 变体一致率 × 长度一致性 × 是否有第二个引擎印证,
variant_agreement/length_consensus/corroborated三个字段都返回,agent 可以据此决定提交还是换图。少读一个字符比读错更常见。 加了一条规则:若某读法只是"比最优读法多插了一个字符"、 且有 ≥3 次独立支持、置信度不低 20% 以上,则优先采用——
CDG/CDGE这种就是靠它纠正的 (QQ 那批里改对 1 张,且不再误改其他)。
剩下 9 张全是同形字:A/4、n/H、7/Z、d/C、E/3、K/X、N/M、c/S。
这类在人眼放大 6 倍后也要反复看,属于模型能力边界,不是管线 bug。
多运算符算术(新增)
kind=arith_multi 是结构化引擎(arith.py),为"一串数字 + 图形运算符"的题准备的。
管线:多阈值扫描(otsu / +35 / +70,选解析成功且置信度最高的那轮)→ 多角度
游程滤波删斜线(imageops.slant_mask)→ 腐蚀 + 形态学重建(reconstruct:粗核长回
细笔画,1px 线和椒盐点没有粗核所以永远不出现)→ 小连通域过滤 → 用连通域自身高度估
字高与行带 → 分块(列零点优先,粘连块再按字高切)→ 逐块分类(- = + 用几何、
* 用星形填充率/长直游程/中心密度、其余交模板+OCR 投票、都不像就判 CJK 并截断)。
每块都带证据,最终返回:
{"kind": "arith_multi", "text": "742+26727", "expr": "742+26727", "answer": "27469",
"confidence": 82.6, "threshold": 172.0,
"routes": [{"route": "columns", "chars": "71+419821162", "conf": 71.8, "parsed": true}, ...]}读不出时 answer 是 null 并附 variants(每个阈值的读法),不会编一个答案出来。
合成语料 arith_multi(Verdana/Trebuchet/Baskerville/Tahoma 渲染——刻意选
模板库没有的字体、画六角星当 *、加中文后缀和椒盐/斜线干扰)目前 0/12;
真图学信网 0/7。原因见下一节,这是诚实的现状,不是没跑。
中文算术(学信网):求值已解决,读图仍未解决
那 8 张是「10+3*3+8 答案是?」这种阿拉伯数字 + 图形运算符 + 中文后缀,带密集椒盐
噪点、斜向/竖向干扰线和紧贴的字距。真值已人工 6x 放大核对,写进
bench/real_labels_arith.json(chsi_7 不是算术题,是「2Rqv」这类字母验证码,排除)。
今天把能确定解决的部分解决了,剩下的如实记在这里:
环节 | 状态 | 证据 |
表达式求值(含 | ✅ 已解决 |
|
中文后缀识别(用「答案是?」定位切分) | ⚠️ 部分 |
|
数字识别(衬线体、未知字体) | ❌ 未解决 | 模板库与站点字体不匹配,NCC 上界只有 ~0.5,判别力不足以定位 |
| ⚠️ 部分 |
|
字符分割 | ❌ 未解决 | 字距 1~2px 且噪点填缝,列投影没有干净谷,等宽切分又会切进字内 |
真图实测(python -m bench.real_eval --dir out/real --kind arithmetic):
accuracy: 0/7 = 0.0%
chsi_1.jpg got 63 truth 27 read='111-48'
chsi_2.jpg got 172 truth 50 read='171+1'
chsi_5.jpg got 14 truth 18 read='2+12'
chsi_8.jpg got -144081 truth 5 read='80-144161'读错的是字符级的(10+3*3+8 被读成 111-48),不是求值错的。诚实的结论:
这类图靠"换预处理参数"不行。斜线抑制 + 形态学重建(
imageops.reconstruct)能把 噪点和 1px 线清掉,但字形先验(字体)和分割先验(字距)都没有,纯启发式到头了。正确做法是拿标注数据训一个识别模型:学信网每次刷新都给一张新题,抓几百张 + 用"提交答案对错"当弱标签就能自举,或人工标 200~300 张微调一个小 CRNN。 这一步需要站点侧采样和标注预算,属于下一个迭代,不是本地调参能补的。
在那之前:
kind=arith_multi会返回answer: null+ 每路读法(routes), 让 agent 知道"这题读不出、该换一张",而不是拿一个假置信度去提交。providers.py的远端逃生通道对这类图是更现实的兜底(支持中文的远端求解器)。
浏览器实测(bench/lab/)
bench/lab/index.html 是一个本地验证码测试台:五种验证码都由页面自己画出来,
真值留在 window.LAB.truth,提交后页面自己判定对错。任何浏览器 agent 都能拿它
做闭环验证。
cd server/bench/lab
python3 -m http.server 8811 --bind 127.0.0.1 & # 测试台页面
python3 sink.py & # 可选:接收 canvas 原始像素
# 打开 http://127.0.0.1:8811/index.htmlagent 侧一轮闭环(已实测 4 轮 × 5 类 = 20/20 通过):
取图:
canvas.toBlob()→ POST 到本地 sink 落盘,或toDataURL()取 base64; 非 canvas 的<img>验证码直接取src/fetch成 base64。识别:
captcha_solve/captcha_click/captcha_slider拿答案。回填:文字/算术/旋转填输入框;点选按返回坐标
dispatchEvent(new MouseEvent('click', ...)); 滑块按drag_distance分 20~30 步发pointerdown/move/up(别瞬移)。判定:页面读
#v-*或window.LAB.results。
// 第 4 轮实测(真值 → 识别)
{"text":"BCEJX","arith":"25×2=50","rotate":"DW38(-12°)","click":"天云日星","slider":"gapX=185"}
{"text":"BCEJX","arith":"50","rotate":"DW38","click":[[201,107],[58,39],[46,108],[190,46]],"slider":185}
→ 5/5 通过(滑块偏差 0px)
两条踩过的坑,接其他站点时同样适用:
别用无障碍节点的 box 截图当验证码。MCP 的
take_screenshot(uid=...)拿到的 区域比 canvas 实际尺寸大且偏移(实测 442×158 vs 画布 220×78),裁出来会带进 相邻卡片的内容,识别直接崩。canvas 用toBlob/toDataURL拿原始像素,<img>用src,两者都精确。滑块距离是 CSS 像素。截图若带
devicePixelRatio(这里是 2.0),从图里算出的 offset 要先除以 DPR 再拖动;否则会多拖一倍。
行为轨迹(新增:captcha_trajectory)
上一节结尾那条教训——"位置对了不代表过,脚本化拖动会按轨迹打分被判失败"——现在落成了
代码。behavior.py 只做一件事:把"像人"变成可复现的参数。
from captcha_solver import behavior
track = behavior.drag_track(185, seed=7)
track["points"][:3] # [{'x': 0.0, 'y': 0.0, 't': 0}, {'x': 38.06, 'y': -0.01, 't': 12}, ...]
track["durations_ms"][:8] # [12, 11, 10, 11, 10, 9, 11, 13]
track["profile"] # easing / steps / speed_range_ms / overshoot_px
behavior.humanize_check(track)
# {'ok': True, 'metrics': {'x_monotonic': True, 'duration_cv': 0.271,
# 'uniform_risk': False, 'mean_ms': 14.9, ...}}参数 | 默认 | 作用 |
| — | 目标位移(CSS px) |
| 自适应 | 分几步走 |
|
|
|
| 0.6 | 亚像素抖动幅度(x 严格非减,末点精确等于 |
| True | 末端多拖 0.5 |
| 随机 | 给定 seed 完全可复现 |
时间步长在 826ms 内变速(前快后慢),y 用两条低频正弦整条一次生成(回弹段不跳变,
幅度 ≤0.8px)。点选验证码用 click_track(points):按压 60140ms、点间移动 150~400ms、
落点前 2 步 micro-move、落点偏移 ±1.2px。
humanize_check 会把 README 里那条"等间距 12ms、零抖动"的机器轨迹判成
uniform_risk: True / ok: False,可以直接当回归基准。MCP 侧是 captcha_trajectory,
HTTP 侧是 POST /track(body 同上,返回里带自检字段)。
自测
cd server
../.venv/bin/python -m unittest discover -s tests -t . -v # 46 条:表达式/形态学/符号/轨迹
../.venv/bin/python -m bench.run_bench --dir out/corpus12 # 合成基准
../.venv/bin/python -m bench.real_eval --dir out/real # 真图·字母数字
../.venv/bin/python -m bench.real_eval --dir out/real --kind arithmetic # 真图·算术实战:阿里云滑块(business.uniagency.net 登录页)
https://business.uniagency.net/login 的验证码是阿里云验证码 PUZZLE 版(AliyunCaptcha.js),
DOM 非常好认:
节点 | 含义 |
| 背景图(data URL,296×200,缺口已画在图上) |
| 拼图块(data URL,52×200,内容在 alpha 通道里,位于条带 y=41~118) |
| 滑块把手,拖动距离 = 把手 |
| 状态文案("Verification failed. Try again." 等) |
拿图 → 解偏移 → 拖拽,全程不需要账号:
// 页面里:把两张 data URL 落到本地再解
const bg = document.getElementById('aliyunCaptcha-img');
const piece = document.getElementById('aliyunCaptcha-puzzle');
await fetch('http://127.0.0.1:8815/bg.png', { method: 'POST', body: await (await fetch(bg.src)).blob() });
await fetch('http://127.0.0.1:8815/piece.png', { method: 'POST', body: await (await fetch(piece.src)).blob() });../.venv/bin/python -m captcha_solver.cli solve --image bg.png --kind slider --background bg.png --piece piece.png --overlay dbg.png
# 拖动距离(CSS) = offset × 显示宽度/图片宽度 − 拼图块在条带里的左偏移实测两张挑战:
挑战 | 我们的 offset | 置信度 | 拖拽 | 站点结果 |
#1 山涧 | 233(真值≈235) | 100 | 236 CSS,等间距 12ms、无抖动 | Verification failed |
#2 雪林 | 176 | 94 | 176.4 CSS,缓动 + 抖动 + 变速 | 通过(弹窗关闭、站点继续走登录流程) |
为这张图踩的两个坑,已经修进代码:
拼图块必须保留 alpha。
load_image默认会把透明 PNG 压到白底,拼图块一旦压平就只剩 一块含噪内容,shape 匹配无从谈起。现在 CLI / HTTP / MCP 取piece一律keep_alpha=True。内容 NCC 会被纹理骗。雪山那张背景里全是树干,内容相关性把缺口对到了树上(score 0.21, 置信度 20.8——低置信度如实报出来了)。新增
shape_offset():拿拼图块的 alpha 轮廓去匹配 背景里"比周围更亮且低饱和"的缺口剪影,两张图分别给出 233 / 176,置信度 100 / 94.4。
行为侧结论:位置对了不代表过。第一次拖拽是等间距 12ms、零抖动的机器轨迹,被判定失败; 第二次换成缓动曲线 + 亚像素抖动 + 8~26ms 变速后通过。阿里云会按轨迹打分,脚本化拖动必须 把"像人"这件事做出来(或者用 CDP 的真实输入事件)。
实战:TikTok Ads 点选 + GeeTest v4 滑块(2026-11-01 真站实测)
两个目标都真跑了,结论不同,细节和现场图片在
server/out/live/REPORT.md。
TikTok Ads 点选(Select 2 objects that are the same shape):通过 2/2。
流程是 读 img.src 的 webp → 用 imageops.components 按饱和度分割物体(粘连块再按行
剖成"文字/几何体"两半)→ 视觉判断同形状的一对 → 按
pointerover → move(3 段) → down → hold 80ms → up → click 点选 → Confirm。
通过证据是弹窗关闭、登录请求打到服务端并返回
We couldn't find an account with that email. 第一次失败是因为坐标靠目视估计偏了 60px,
改用像素分割出的中心点后一次过——点选类不要相信目测坐标。
GeeTest v4 滑块:用 CDP 真实输入后 4/4 通过。(第一轮用 JS 合成事件是 0/1,见下) gt4 的背景图和拼图块是两张独立
PNG(300×200 / 80×80 RGBA),直接 curl 下来喂 captcha_slider 即可,没有 DPR 问题;
三张挑战分别给出 149 / 201 / 137,人眼复核缺口在 150 / 200 / 133,shape_ncc 可用。
第一轮用页面 JS 派发 PointerEvent,坐标对、轨迹对,仍然 Please try again——gt4 检查
事件的 isTrusted,合成事件过不去。
第二轮换成 Input.dispatchMouseEvent(captcha_solver/cdp.py +
tools/live_slider.py),连续 6 次全部通过,面板显示
0.6 s. You beat 99% of users:
run 1 gap 137 margin 10 drag 123.3px → Verification Success
run 2 gap 116 margin 15 drag 97.4px → Verification Success
run 3 gap 184 margin 10 drag 168.5px → Verification Success同时修掉一个系统性偏差:gt4 的拼图块是 80×80 RGBA,轮廓只占中间 56×61(左边距 11~15px),
匹配得到的是"轮廓该在的位置",而滑块移动的是图片左上角,所以 drag = gap_x − margin。
上一轮直接拖 gap_x,正好差那 11px。
cd server
PYTHONPATH=. ../.venv/bin/python -m tools.live_slider --json # 拉起带调试端口的 Chrome 并跑一遍注意 headless 会被 gt4 直接拒绝,脚本默认带窗口;Chrome 用独立 profile,不影响日常浏览器。
逃生通道:远端求解器
本地置信度低时才上报,默认关闭:
export CAPTCHA_PROVIDER=http
export CAPTCHA_PROVIDER_URL=https://solver.internal/api/solve
export CAPTCHA_PROVIDER_KEY=YOUR_KEY
# 或打码平台
export CAPTCHA_PROVIDER=twocaptcha CAPTCHA_PROVIDER_KEY=YOUR_KEY调用时带 escalate: true,返回里会出现 escalated: true 和 local 对照。
协议实现见 server/captcha_solver/providers.py。
目录
.dsh-bundles/captcha-solver/
├── cordis.patch.yml # DSH bundle:把 MCP server 注册成 agent 工具
├── package.json # bundle 元数据(dsh.bundle.patch)
├── run.sh # 选解释器启动 MCP server
├── scripts/setup.sh # 建 venv、装神经引擎
└── server/
├── captcha_solver/
│ ├── imageops.py # 纯 numpy 图像原语:二值化/去线/去噪/去斜/连通域/2-D NCC
│ │ # + reconstruct/erode3/drop_small_components/slant_mask/column_runs
│ ├── ocr.py # tesseract 驱动、字符混淆修复、多引擎投票、算术求值
│ ├── expression.py # 递归下降表达式解析(优先级/括号/Fraction 精确值)
│ ├── arith.py # 实验性:多阈值 + 形态学清洗 + 分块 + 符号分类(kind=arith_multi)
│ ├── symbols.py # 图形运算符定位:+ * - = 的合成模板 NCC + 几何复核
│ ├── behavior.py # 人性化轨迹:缓动/变速/抖动/回弹 + humanize_check 自检
│ ├── cdp.py # 最小 CDP 客户端:真实(isTrusted)鼠标输入、launch/connect/drag
│ ├── text_solver.py # 文字/算术:预处理集成 + 投票
│ ├── template.py # 字体模板库与逐字形识别
│ ├── slider.py # 滑块:2-D 边缘匹配 + 平坦块缺口检测
│ ├── click.py # 点选:检测框 + 逐字识别 + 全局指派排序
│ ├── rotate.py # 旋转:投影角度 + OCR 置信度二次搜索
│ ├── engine.py # 神经引擎适配(ddddocr,可选)
│ ├── providers.py # 远端兜底
│ ├── pipeline.py # 路由、升级轮次、统一返回
│ ├── service.py # HTTP API
│ └── mcp_server.py # MCP stdio JSON-RPC
├── bench/
│ ├── gen_corpus.py # 合成六类验证码(含 arith_multi)+ labels.json
│ ├── real_eval.py # 真图评估(--kind arithmetic 支持表达式+答案标签)
│ ├── real_labels.json # 字母数字真值(人工核对)
│ ├── real_labels_arith.json # 学信网算术真值(人工核对)
│ └── run_bench.py # 准确率/耗时基准
├── tools/
│ └── live_slider.py # 真站滑块闭环:读图 → slider → behavior → CDP 真实拖动
└── tests/ # unittest:expression / 形态学 / 符号 / 轨迹 / 滑块透明边距接进浏览器流程
agent 侧的典型闭环(配合浏览器 MCP 或 Playwright):
截图验证码元素 →
captcha_solve(或captcha_click拿坐标)→ 填/点。滑块:截背景图 + 缺口图 →
captcha_slider→ 按drag_distance做人性化拖动 (分 20~40 步、先快后慢、末端 3px 回弹),不要瞬移。失败就换一张:
confidence < 55或服务端拒绝时点刷新,不要连续重试同一张图。
License
MIT —— 见 LICENSE。copyright (c) 2026 clawpaw-beep。
仓库里 server/out/live/ 下的验证码样本是各站点公开发给匿名会话的挑战图(不含个人数据),
仅作回归 fixture 保留;bench/lab/real_samples/ 同理。第三方字体、tesseract、ddddocr
分别遵循它们自己的许可,本项目只在使用层面依赖它们。
This server cannot be deployed
Maintenance
Related MCP Connectors
Solve reCAPTCHA image grids, text captchas, GeeTest and FunCAPTCHA for AI agents. Free tier.
Solve reCAPTCHA v2/v3, hCaptcha, Cloudflare Turnstile and image captchas. Platform-hosted, no creden
Human-in-the-loop API for AI agents. CAPTCHA, OTP, KYC, and approvals by real humans.
Web search, browser automation, scraping, crawling and CAPTCHA solving for AI agents.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to solve CAPTCHAs using OCR text recognition, object detection, and slider position matching through the ddddocr library.4MIT
- AlicenseAqualityDmaintenanceEnables AI agents to navigate the web visually using screenshot-based interaction and Set-of-Mark labeling for interactive elements. It supports humanized browsing behaviors, anti-detection measures, and complex tasks like multi-click CAPTCHA solving.6MIT
- FlicenseNot gradedqualityCmaintenanceEnables PraisonAI agents to solve authorized CAPTCHA challenges with a bounded one-attempt budget, structured result validation, and a human-review stop for denied, unsupported, exhausted, or malformed requests.-
- AlicenseAqualityCmaintenanceEnables AI agents to solve reCAPTCHA v2/v3/Enterprise, Cloudflare Turnstile, DataDome and image captchas during browser or HTTP automation, returning the token, cookie or text the page needs. Failed solves are never billed, and a configurable per-process spend cap limits autonomous spending.464 npmMIT