关于 MCP Retrieval
mcp-retrieval 是以 Go 编写的 MCP 服务,为 MCP 客户端提供只读网页搜索、图片搜索和页面抓取。它无需 API 密钥,并以结构化数据和 Markdown 返回搜索结果及提取的页面文本。
主要功能
- 01通过 DuckDuckGo Lite 搜索网页
- 02通过 Bing Images 搜索图片
- 03抓取页面文本并转换为 Markdown
- 04并行执行查询和 URL 抓取
- 05支持 stdio 或可流式 HTTP 传输
适用场景
- 01为大模型回答查找网页来源
- 02查找与查询相关的图片
- 03提取网页中的文章文本
- 04为本地或远程 MCP 客户端提供检索工具
MCP 相关
向 MCP 客户端提供网页搜索、图片搜索和页面抓取三种只读工具。三种工具均支持 stdio 和可流式 HTTP 传输。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
我们还没有获取到这个服务的安装包或远程地址,请按项目 README 中的说明安装。
ghcr.io/role1776/mcp-retrieval:0.1.10stdio工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
mcp-retrieval
一个 MCP 服务,为大模型提供三种 Web 工具:搜索、图片搜索和网页抓取——无需 API 密钥。
工具 · 快速开始 · 配置 · 检索引擎 · 架构 · 参与贡献
项目简介
mcp-retrieval 是一个用 Go 编写的 Model Context Protocol 服务。它将 Web 检索功能作为三种只读工具提供给任何兼容 MCP 的客户端(Claude Desktop、IDE Agent、自定义大模型应用)。在底层,它使用 retrieval-go 库搜索 Web 并抓取网页,以简洁的 Markdown 格式返回结果,可直接交给模型处理。
该库无需 API 密钥:Web 搜索通过 DuckDuckGo Lite 完成,图片搜索通过 Bing Images 完成,抓取网页时会先使用可读性提取器处理 HTML,再转换为 Markdown。为避免受到机器人防护机制影响,它会在 TLS 层模拟真实浏览器,并可轮换浏览器指纹和代理——详见检索引擎。
MCP SDK 支持的两种传输方式均可使用,且提供完全相同的工具集:
- stdio — 客户端启动二进制文件,并通过 stdin/stdout 通信(默认方式,非常适合桌面客户端)。
- http — 长时间运行的流式 HTTP 服务(适用于远程或共享部署)。
工具
| 工具 | 描述 |
|---|---|
web_search | 并行执行一个或多个查询,并返回每个查询去重、重新排序后的摘要及链接。 |
web_search_images | 并行执行一个或多个图片查询,并返回每个查询去重后的图片结果。 |
web_scrape | 并行下载一个或多个网页,并以 Markdown 格式返回正文内容。 |
这三种工具均标记为只读。每种工具都会返回符合其输出架构的结构化 JSON 负载;对于不读取 structuredContent 的客户端,SDK 也会将相同的 JSON 写入文本内容块。
web_search
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
queries | []string | — | 必填。 并行执行。 |
max_results | int | 5 | 每个查询返回的摘要数量,上限由配置项 max_results(20)决定。 |
timeout_ms | int64 | 5000 | 整个调用的超时时间;限制在配置中的 [min, max] 范围内。 |
date | string | — | 新鲜度筛选条件:d(天)、w(周)、m(月)、y(年)。 |
web_search_images
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
queries | []string | — | 必填。 并行执行。 |
max_images | int | 5 | 每个查询返回的图片数量,上限由配置项 max_images(10)决定。 |
timeout_ms | int64 | 5000 | 整个调用的超时时间;限制在配置中的 [min, max] 范围内。 |
date | string | — | 新鲜度筛选条件:d / w / m / y。 |
web_scrape
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
urls | []string | — | 必填。 并行下载。 |
robots_txt | bool | false | 遵循页面的 robots.txt。 |
timeout_ms | int64 | 5000 | 整个调用的超时时间;会限制在配置中的 [min, max] 范围内。 |
remove_links | bool | false | 从文本中移除 Markdown 链接。 |
max_chars | int | 20000 | 将页面文本截断至 N 个字符,上限为配置中的 max_document_chars(20000)。 |
每次调用的
queries/urls列表都最多包含max_queries(10)项。查询不得超过 512 个字符;URL 不得超过 2048 个字符,且只能使用http/https。
结果与计数
每次调用都会对输入列表中的各项分别执行操作,并为每个查询/URL 返回一个条目,每个条目都有自己的 status——success、failed 或 timeout——因此即使部分失败,也仍会返回已成功处理的条目。
count 是实际返回的条目数,可能小于请求的 max_results / max_images:应用限制前,会先移除单个查询结果中的重复项;上游也可能没有足够的条目可返回。count 较小是正常情况,并非错误。
去重是按查询进行,而不是跨查询进行。每个条目会单独去重,因此同一次调用中的两个查询若都找到同一个链接,该链接会同时出现在两个条目中——如果需要对合并后的结果去重,请自行处理。
错误
请求级失败会作为带有 isError: true 的工具结果返回,并附带纯文本消息,而不是 JSON-RPC 错误——模型会读取消息并自行修正调用。单项失败不会以这种方式返回;它们会保留在负载中,状态为 status: "failed" / "timeout"。
仅当输入在任何操作开始前被拒绝,或其中所有条目都失败时,调用才会彻底失败:
| 消息 | 含义 |
|---|---|
invalid request | 参数未通过验证。 |
too many queries / too many urls | 列表超出 MAX_QUERIES。这么长的列表通常会在更早阶段被输入架构验证拒绝(架构包含 maxItems),因此客户端会看到 validating "arguments": maxItems: ...;此消息是备用处理。 |
query must not be empty | 查询为空,或 queries 列表为空。 |
query is too long | 查询超过 512 个字符。 |
invalid url | URL 格式错误、超过 2048 个字符,或协议不是 http/https。 |
robots.txt denied | robots_txt: true,且页面禁止抓取。 |
every url failed to be scraped; the pages may be unreachable or hold no extractable text | 所有 URL 均因超时以外的错误而失败。各项具体原因会记录到 stderr,不会返回。 |
every query failed; the search upstream may be unreachable | 所有查询均因超时以外的错误而失败,包括上游拒绝请求的情况(任何非 200 响应,例如 DuckDuckGo 在短时间内收到大量请求时返回的 HTTP 202 机器人验证)。每个查询的具体原因会记录到 stderr。 |
request canceled | 客户端在调用完成前取消了调用;这不代表上游出现任何问题。 |
internal server error | 未分类的错误。 |
超时永远不会导致调用级错误:超时的条目会获得 status: "timeout";即使所有条目都超时,调用仍会返回所有条目及其状态。只有在没有任何条目成功或超时时,才会触发“全部失败”消息。
已知限制
web_scrape仅处理 HTML。 页面会经过可读性提取器处理,该提取器需要文章标记,因此text/plain响应不会产生任何内容,并会返回status: "failed"。原始文件托管站点是最常见的情况:raw.githubusercontent.com、github.com/.../raw/...、cdn.jsdelivr.net。请抓取渲染后的页面,而不是原始文件。web_search_images无法保证相关性。 对于某些查询,Bing Images 会提供一个并非结果集的页面,而工具会将其当作结果集解析——随后以status: "success"返回无关图片。请将图片结果视为尽力而为的结果,并在展示给用户前进行核实。- 不支持 JavaScript。 页面会按原样抓取;客户端渲染的内容对提取器不可见。
- 突发的并行搜索可能触发 DuckDuckGo 的机器人验证。 验证会返回 HTTP 202,这会被视为查询失败,因此在请求速率降低之前,查询会持续失败。轮换代理(参见 HTTP 客户端和代理)会将负载分散到不同的出口 IP。
快速开始
安装
任选一种方式——它们提供的服务完全相同。
容器(无需 Go 工具链):
docker pull ghcr.io/role1776/mcp-retrieval:latest
预构建二进制文件——从最新版本下载适用于你平台的压缩包,解压后将 mcp-retrieval 放入 PATH。
MCP Bundle——对于安装 .mcpb 文件的客户端,从最新版本下载 mcp-retrieval_<version>_<os>_<arch>.mcpb,然后用客户端打开。该 Bundle 包含编译好的二进制文件,因此既不需要 Docker,也不需要 Go。请选择与你的操作系统和 CPU 架构匹配的文件:每个 Bundle 只包含一个原生二进制文件。
从源代码构建:
go install github.com/Role1776/mcp-retrieval/app/cmd/mcp-retrieval@latest # needs Go 1.25.5+
或者在当前目录构建二进制文件(Go 模块位于 app/ 中):
make build # -> bin/mcp-retrieval
运行
# defaults: stdio transport, no configuration needed
./bin/mcp-retrieval
# with an explicit env file
./bin/mcp-retrieval -env /absolute/path/to/.env
唯一的标志是可选的:
| 标志 | 含义 |
|---|---|
-env | .env 文件的路径。如果省略该参数,或文件不存在,服务会使用默认值和环境中已有的变量启动。不会隐式查找文件:在 stdio 模式下,工作目录由 MCP 客户端决定,因此相对路径的默认值会难以预测。 |
连接 MCP 客户端(stdio)
将客户端指向构建好的二进制文件。Claude Desktop 配置示例:
{
"mcpServers": {
"retrieval": {
"command": "/absolute/path/to/mcp-retrieval",
"env": {
"MAX_RESULTS": "20"
}
}
}
}
env 块是可选的——仅使用 "command" 就足够了。
连接 MCP 客户端(容器)
通过 stdio 运行镜像。配置仍通过 env 块传递,但要让变量传递到进程,Docker 需要在命令行中用 -e 指定每个变量:
{
"mcpServers": {
"retrieval": {
"command": "docker",
"args": [
"run", "-i", "--rm",
"-e", "MAX_RESULTS",
"-e", "DEFAULT_TIMEOUT_MS",
"ghcr.io/role1776/mcp-retrieval:latest"
],
"env": {
"MAX_RESULTS": "20",
"DEFAULT_TIMEOUT_MS": "5000"
}
}
}
}
必须使用 -i——否则容器不会收到 stdin,客户端会立即看到服务退出。通过 MCP Registry 安装的客户端会自行构建此调用,并提示输入 server.json 中声明的变量。
通过 HTTP 运行
设置 MCP_TRANSPORT=http 后,服务会在 SERVER_PORT 上的 MCP_PATH 处监听(默认值为 http://localhost:8080/mcp)。
配置
所有配置均通过环境变量完成,每个值都会在启动前进行验证:非数字或非正数的值会导致启动错误(*_IN_FLIGHT 上限也接受 0)。启动时不会检查各项限制之间的关系——请参见限制。环境中已有的变量优先于 .env 文件,因此 MCP 客户端的 env 块始终生效。每个字段都有合理的默认值,因此无需任何配置,服务也能以 stdio 传输模式运行。
完整变量列表及其默认值请见 .env.example,可直接复制到 .env。
MCP 服务
| 环境变量 | 默认值 | 说明 |
|---|---|---|
MCP_TRANSPORT | stdio | stdio 或 http。 |
MCP_NAME | mcp-retrieval | 向客户端公布的服务名称。 |
MCP_PATH | /mcp | HTTP 路由(仅限 http 传输)。 |
向客户端公布的版本不可配置:它会在构建时根据 git 标签写入二进制文件。
HTTP 服务(仅限 http 传输)
| 环境变量 | 默认值 |
|---|---|
SERVER_PORT | 8080 |
SERVER_READ_TIMEOUT | 60s |
SERVER_WRITE_TIMEOUT | 60s |
HTTP 客户端和代理
| 环境变量 | 默认值 | 说明 |
|---|---|---|
MAX_IDLE_CONNS_PER_HOST | 100 | HTTP 连接池。 |
PROXY_HOST | — | 可选。设置后,请求会通过轮换会话代理路由。 |
PROXY_PORT | — | 设置 PROXY_HOST 时必填。 |
PROXY_SCHEME | — | 设置 PROXY_HOST 时必填。 |
PROXY_LOGIN | — | 设置 PROXY_HOST 时必填。 |
PROXY_PASSWORD | — | 设置 PROXY_HOST 时必填。 |
配置代理后,每个出站请求都会在登录名后附加唯一的会话 ID,因此上游提供商会针对每个请求轮换出口 IP。
限制
| 环境变量 | 默认值 |
|---|---|
MAX_QUERIES | 10 |
DEFAULT_RESULTS | 5 |
MAX_RESULTS | 20 |
DEFAULT_TIMEOUT_MS | 5000 |
MAX_TIMEOUT_MS | 10000 |
MIN_TIMEOUT_MS | 1000 |
DEFAULT_IMAGES | 5 |
MAX_IMAGES | 10 |
DEFAULT_DOCUMENT_CHARS | 20000 |
MAX_DOCUMENT_CHARS | 20000 |
MAX_SEARCH_IN_FLIGHT | 2 |
MAX_IMAGES_IN_FLIGHT | 2 |
MAX_SEARCH_IN_FLIGHT 和 MAX_IMAGES_IN_FLIGHT 用于限制每个服务进程中并发的上游网页搜索和图片搜索请求数;设为 0 则禁用限制。
每个值都会单独检查——除 *_IN_FLIGHT 限制项外,值必须大于零;对于这些限制项,设为 0 则禁用限制。但启动时不会交叉检查 DEFAULT_*、MIN_* 和 MAX_* 三元组之间的关系。配置不一致不会阻止服务启动,而是在每次请求时进行协调:
- 调用方省略的值,或传入的值为零或负数时,会回退到对应的
DEFAULT_*; - 随后将结果限制在
[MIN_*, MAX_*]范围内,因此,如果DEFAULT_*大于其MAX_*,结果就是MAX_*; - 如果
MIN_*大于MAX_*,则以最大值为准。
因此,有效限制始终不超过配置的最大值;即使配置错误,服务也会降级运行,而不是启动失败。代价是这种降级不会发出提示:例如,将 MAX_RESULTS=20 误写为 MAX_RESULTS=2 不会产生警告,只会悄然缩小响应内容。如果结果看起来被截断,值得再次检查这些值。
日志记录
| 环境变量 | 默认值 | 说明 |
|---|---|---|
LOG_MODE | local | local → debug 级别的文本处理器;prod → info 级别的 JSON 处理器。日志输出到 stderr。 |
架构
该项目采用清晰的分层结构。依赖关系向内指向领域层,每一层通过接口与下一层交互。
app/ the Go module: sources plus its build files
(Dockerfile, .dockerignore, .goreleaser.yaml)
cmd/mcp-retrieval/main.go entry point: parse flags, load config, run app
internal/
app/ wiring + lifecycle (build server, run, graceful shutdown)
config/ config loading (.env → env vars → validate)
domain/ core types (Query, Link, Document, Snippet, Image) and errors
dto/web/ request/response shapes for the MCP tools
transport/mcp/ MCP layer
router/ registers every tool group on the MCP server
web/ tool handlers
utils/ schema helpers and error → tool-result mapping
usecase/web/ business logic: validation, parallelism, timeouts, dedupe/limit/rerank
adapter/web/ retrieval-go client wiring (search, images, scrape, proxy)
pkg/ reusable building blocks (mcpserver, server, logger, validator)
工具调用的请求流程:
MCP client → transport/mcp/web (handler) → usecase/web → adapter/web → retrieval-go → the web
↑ maps errors ↑ validates, fans out, limits results
搜索和抓取都会并发处理输入列表中的各项,并汇总每项结果;每项都有自己的状态(success、failed、timeout)。只有当某次调用中的所有项目都因超时以外的错误而失败时,该调用才会彻底失败。
检索引擎
所有网络操作均交由 retrieval-go 处理,并在 app/internal/adapter/web 中进行配置。值得了解的内容:
- 来源。 网页搜索使用 DuckDuckGo Lite;图片搜索使用 Bing Images;网页抓取会将原始 HTML 交由 readability 提取器处理,并将主要文章转换为 Markdown(包括表格)。无需搜索引擎 API 密钥。
- 浏览器模拟。 适配器启用了
WithBrowserRotation(),因此每个请求都会随机使用约 11 种真实浏览器配置之一发送。每种配置都将真实的 TLS/JA3 指纹(通过 uTLS)与相匹配的User-Agent和客户端提示标头配对:Chrome 133/131/120(Windows/macOS/Linux)、Edge 131、Firefox 120(Windows/macOS)、Safari 18.4(macOS)以及 iOS 18.4 Safari。这样,流量看起来就像普通浏览器发出的,而不是 Go HTTP 客户端,这也是免费来源能够持续访问的关键。 - 代理轮换。 配置
PROXY_HOST后,适配器会安装一个代理工厂,在每个请求的代理用户名后追加唯一的session-<id>。使用基于会话的住宅/轮换代理提供商时,这样每个请求都会获得一个全新的出口 IP,从而分散负载并避免触发速率限制。不使用代理时,请求会直接发出。 - 响应处理。 响应会透明解压(
gzip、br、zstd、deflate),并禁用 keep-alive(WithDisableKeepAlive()),以免连接池中的连接让多个请求固定使用同一个指纹/IP。
以上功能均无需配置即可运行——系统会自动应用上述默认设置。只有代理凭据是可选的附加项。
开发
所有 Go 相关内容都位于 app/ 中,因此可以从仓库根目录使用 makefile,也可以向工具链传入 -C app:
make build # compile the binary
make test # run tests
go -C app build ./... # compile everything
go -C app test ./... # run tests
go -C app vet ./... # static checks
请参阅 CONTRIBUTING.md 了解拉取请求指南。
许可证
根据 MIT License 发布。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。