Image Search MCP Server
一个基于 PicImageSearch 的 MCP 服务器,支持多引擎以图搜图。
支持通过 uvx (uv) 或 pipx 一键运行,无需手动克隆代码。
✨ 特性
- 多引擎支持:集成 11 种主流搜图引擎 (Yandex, SauceNAO, Google, TraceMoe, ASCII2D, EHentai, Iqdb, BaiDu, Bing, GoogleLens, Tineye)。
- 结果精简:自动移除原始冗余数据,仅返回最关键的标题、链接、缩略图等信息。
- 空结果提示:没匹配到结果时给出排查顺序(图本身、覆盖范围、限流、是否需要凭据),不替上游断定"是机器人验证"。
- 零配置部署:通过
uvx直接运行。 - 安全配置:API Key 和代理设置通过环境变量管理。
- 灵活输入:支持图片 URL 和 Base64 编码。
🚀 快速开始
方式 1: 直接运行 (Stdio 模式)
适用于 Claude Desktop 或其他支持 MCP Stdio 的客户端。
Command:
uvx image-search-mcp
方式 2: SSE 模式 (HTTP Server)
适用于远程部署或 Web 客户端。
uvx image-search-mcp --sse --port 8000
🔒 安全认证
SSE/HTTP 模式下 MCP_AUTH_TOKEN 是必需的 —— 缺失或只有空白时服务拒绝启动并
以非零码退出(旧版本会照常起一个任何人都能调的服务,那是认证绕过的前提)。
环境变量示例:
Linux/macOS:
export MCP_AUTH_TOKEN="$(openssl rand -hex 32)" # 必需
export IMAGE_SEARCH_API_KEY="your_saucenao_key" # 可选(SauceNAO)
export IMAGE_SEARCH_COOKIES_YANDEX="your_cookies" # 可选,按引擎命名
export IMAGE_SEARCH_PROXY="http://127.0.0.1:7890" # 可选
uvx image-search-mcp --sse --host 0.0.0.0 --port 8000
Windows (PowerShell):
$env:MCP_AUTH_TOKEN="my-secret-token-123"
$env:IMAGE_SEARCH_API_KEY="your_saucenao_key"
$env:IMAGE_SEARCH_COOKIES_YANDEX="your_cookies"
$env:IMAGE_SEARCH_PROXY="http://127.0.0.1:7890"
uvx image-search-mcp --sse --host 0.0.0.0 --port 8000
认证面(收窄后的)
/healthz的GET/HEAD免认证。它不访问任何引擎 —— 真实搜图会烧配额,还会让上游抽风传导成本机重启- 其余所有路径(含
/)都需要Authorization: Bearer <token> - 带
Origin头的请求默认被拒(防 DNS rebinding)。浏览器类客户端需要把来源 写进IMAGE_SEARCH_ALLOWED_ORIGINS(逗号分隔);原生 MCP 客户端不发这个头,不受影响 - WebSocket 一律拒绝(握手阶段回 1008)
- 仅本机调试可开匿名:
IMAGE_SEARCH_ALLOW_ANONYMOUS=1且--host 127.0.0.1
这一批修复改变了运行期行为。升级前请读
docs/配置变更说明.md。
客户端连接示例 (SSE)
JSON 配置示例 (例如用于 Claude Desktop 或其他支持远程 MCP 的客户端):
{
"mcpServers": {
"image-search-remote": {
"type": "sse",
"url": "http://your-server-ip:8000/sse",
"headers": {
"Authorization": "Bearer my-secret-token-123"
}
}
}
}
⚙️ 环境配置说明
以下是所有支持的环境变量:
| 环境变量 | 说明 | 示例 |
|---|---|---|
MCP_AUTH_TOKEN |
HTTP 模式必需。缺失或空白则拒绝启动 | $(openssl rand -hex 32) |
IMAGE_SEARCH_API_KEY |
SauceNAO API Key。只从环境读,不接受调用方传入 | your_api_key |
IMAGE_SEARCH_COOKIES_<引擎> |
按引擎命名的 Cookies,例如 IMAGE_SEARCH_COOKIES_YANDEX、IMAGE_SEARCH_COOKIES_EHENTAI、IMAGE_SEARCH_COOKIES_GOOGLE |
igneous=...; ipb_member_id=... |
IMAGE_SEARCH_PROXY |
HTTP 代理地址 | http://127.0.0.1:7890 |
IMAGE_SEARCH_ALLOWED_ORIGINS |
允许的浏览器 Origin(逗号分隔)。不设置时任何带 Origin 的请求都被拒 |
https://a.example,https://b.example |
IMAGE_SEARCH_ALLOW_ANONYMOUS |
仅本机调试:1 且绑定回环地址时可不认证 |
1 |
HTTP_PROXY / HTTPS_PROXY |
系统代理。引擎自身的请求遵循 httpx 默认(会读);取图下载器刻意不读(trust_env=False) |
http://127.0.0.1:7890 |
IMAGE_SEARCH_COOKIES(无后缀的全局变量)不再被接受。 一个不带域名的 cookie 会跟着请求发给任何域名 —— 实测把sid=...发到了untrusted.invalid。检测到全局变量时服务会拒绝这次调用,并指出该用哪个变量名。 归属不明时宁可拒绝,也不猜一个引擎发出去(猜错就是把 A 站凭据发给 B 站)。
关于 Cookies 的重要提示
有些引擎(Yandex、Google、Bing、GoogleLens、Tineye 等)确实可能要求凭据,但 "No results found." 不等于机器人验证 —— 服务也不会这样断言(旧文案这么写过,是猜的)。 没结果时按这个顺序排查:
- 先看有没有明确失败信息。上游明确报错时会返回
Error: …(isError=true), 那是可判定的事实,照它修;只有 "No results found." 才是"搜索成功、上游没报错、就是没匹配"。 - 图本身:太小、太模糊、被裁过,任何引擎都匹配不到。
- 覆盖范围:收录这张图的站点不在该引擎的索引里。
- 限流 / 需要凭据:到这一步再考虑配 cookies —— 在浏览器里登录对应搜索引擎,
拿到 cookies 后设到对应引擎的
IMAGE_SEARCH_COOKIES_<引擎>(例如IMAGE_SEARCH_COOKIES_YANDEX)。
配 cookie 不保证能绕过风控。Bing 尤其要注意:它在本项目里标为 experimental,
原因是上游 PyPI 3.12.11 缺少签名解密修复(该修复尚未发版),空结果可能与之有关 ——
这种情况配 cookie 也不会改善。
每个引擎的 cookie 只会发给它自己真正访问的域名(Yandex → yandex.com,EHentai → e-hentai.org / exhentai.org,依此类推)。这张域名表对着上游源码核验过,并有测试盯着。
💻 客户端部署指南 (本地 Stdio)
Claude Desktop 配置 (Stdio)
编辑 claude_desktop_config.json,在 env 字段中配置本地运行所需的变量:
{
"mcpServers": {
"image-search-local": {
"command": "uvx",
"args": ["image-search-mcp"],
"env": {
"IMAGE_SEARCH_API_KEY": "your_saucenao_key",
"IMAGE_SEARCH_COOKIES_YANDEX": "your_cookies",
"IMAGE_SEARCH_PROXY": "http://127.0.0.1:7890"
}
}
}
}
🛠 工具使用指南
search_image
参数列表:
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
source |
string | 是 | - | 图片 URL (http://...) 或 Base64 字符串。URL 必须以 http:// / https:// 开头;Base64 输入上限 16 MiB。 |
engine |
string | 否 | "Yandex" | 搜索引擎名称。支持: Yandex, SauceNAO, Google, TraceMoe, Ascii2D, EHentai, Iqdb, BaiDu, Bing, GoogleLens, Tineye。 |
extra_params_json |
string | 否 | - | JSON 对象字符串,用于传递该引擎真实支持的参数。见下方说明。 |
limit |
int | 否 | 5 | 返回结果的最大数量,必须在 1–50 之间。越界或非整数会在发出任何请求之前被拒。 |
关于 extra_params_json:只接受该引擎真实支持的参数。
白名单来自对已安装 PicImageSearch 真实函数签名的检查(不是从文档或旧配置手抄),
由 tests/test_param_contract.py 逐项核验。三类输入会被拒绝:
- 未知参数 —— 报错并列出允许的名字。例如 SauceNAO 的
output_type虽然存在于上游 签名里,但本库的解析固定走 JSON,设成别的值会让解析失败,因此刻意不开 - 保留键 ——
url/file/client/api_key/cookies/proxies/request_kwargs/base_url一律拒绝。早期版本允许覆盖它们, 于是{"file": "/etc/passwd"}能把输入换成本地路径,读出来的内容会被上传到搜索引擎站点 - 顶层不是对象 —— 数组、标量都拒绝
用 get_engine_info 查看某个引擎的完整参数列表。
调用示例(有效参数):
{
"engine": "TraceMoe",
"source": "https://example.com/image.jpg",
"extra_params_json": "{\"cut_borders\": false}",
"limit": 3
}
{
"engine": "Ascii2D",
"source": "https://example.com/image.jpg",
"extra_params_json": "{\"bovw\": true}"
}
(bovw 是 Ascii2D 的初始化参数:true = 特征搜索,对裁剪/改图更有效)
参数名用上游的真实拼写。旧文档里那个
cutBorders(驼峰)从来没生效过 —— 它会落进上游的**kwargs被静静吞掉。现在这类拼错会被明确拒绝并指出正确写法。
get_engine_info
获取支持的搜索引擎列表或特定引擎的详细参数信息。
调用示例:
{
"engine_name": "all"
}
或
{
"engine_name": "SauceNAO"
}
📦 开发与发布
测试与验收
python -m venv .venv && .venv/bin/pip install -e ".[dev]"
./check.sh # 一键验收:单元测试 + 门禁自检 + 反向测试
./check.sh --fast # 跳过反向测试
./check.sh --reverse-only # 只跑反向测试
测试的默认姿态是禁网:tests/conftest.py 会给 httpx 注入"拒绝一切"的 transport,
并拦掉真实 DNS 解析。任何未被显式 mock 的出站请求都会立刻失败,而不是真的打出去。
tools/reverse_tests/ 是反向测试:把已经修好的缺陷重新注入到代码副本里,
要求指定测试因此变红。没有它,一片绿的测试无法区分"代码是对的"和"测试没在看"。
每条注入都写明对应哪个原始缺陷,执行器还会先确认导入到的是副本里的模块 ——
否则跑的仍是干净代码,反向测试是假的。
| 工具 | 用途 |
|---|---|
tools/reverse_tests/run.py |
反向测试(--list 看注入清单) |
tools/gate_tests_not_ignored.py |
门禁:测试源码没被 .gitignore 吞掉(--self-test 自检) |
tools/status.py --update docs/实施进度.md |
重新生成状态段,避免手抄数字 |
构建与上传
-
安装构建工具:
pip install build twine
-
构建:
python -m build
-
上传到 PyPI:
twine upload dist/*
环境要求
- Python >= 3.10(CI 矩阵覆盖 3.10 / 3.11 / 3.12)
- 注意:依赖库
lxml建议使用 Python 3.12。
依赖策略
不跟 PicImageSearch 的 main 分支。 PyPI 上的 3.12.11 就是本项目使用的版本,
而 main 领先 78 个提交且尚未发布,其中包含 httpx→httpx2 这种破坏性迁移。
上游 yandex.py 在这期间只改了类型标注 —— 我们最依赖的那个引擎没有行为变化。
"上游改了签名没人知道"这件事由三个机制兜住,而不是靠给依赖加上界:
tests/test_param_contract.py对着inspect.signature逐项比对参数契约- CI 里跑一遍完整测试
- 低频的在线抽验
pyproject.toml 里刻意不给依赖上界:上界解决不了"上游改了行为",
只会让人以为锁住了。
Metadata
Release files for image-search-mcp 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| image_search_mcp-0.3.0.tar.gz | 92.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| image_search_mcp-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 143.0 kB
Release files / image_search_mcp-0.3.0.tar.gz
| Download URL | image_search_mcp-0.3.0.tar.gz |
|---|---|
| Size | 92.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
955632a9b670c88f0c6692651107587ff8f4d5aec25ac6faf82a468ca36257a2
|
|
BLAKE2b-256 checksum How to use checksums |
62803ce74817837eab8b1a8768763b3a6a8f8436b1970a095ce482c4625e91fe
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / image_search_mcp-0.3.0-py3-none-any.whl
| Download URL | image_search_mcp-0.3.0-py3-none-any.whl |
|---|---|
| Size | 50.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
23d8a083107f3230b19844dfa1b59b1f13d767e42eef104cdf8710595ebc92dd
|
|
BLAKE2b-256 checksum How to use checksums |
b622ebbc258fd6dd42eea36202fabffa45e000a392d0086ffa9e64c6ea962096
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|