关于 OwnSearch
OwnSearch 是自托管的 MCP 和 HTTP 搜索服务,通过评分后的公共 SearXNG 实例组成搜索集群,适合需要自管搜索流程的用户。它在本地 SQLite 保存集群状态,并支持实例轮换、故障切换和结果合并。
主要功能
- 01发现并探测公共 SearXNG 实例
- 02评分并维护本地实例集群
- 03轮换实例并在故障时切换
- 04合并结果并保留来源信息
- 05抓取网页并提取正文
适用场景
- 01通过多个 SearXNG 实例执行网页搜索
- 02实例故障时继续获取搜索结果
- 03抓取网页并提取 Markdown 或文本
- 04检查实例健康状态与搜索能力
MCP 相关
作为 MCP 服务,OwnSearch 可通过 stdio 或 Streamable HTTP 连接客户端,提供搜索、网页抓取、实例管理与状态查询工具。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
我们还没有获取到这个服务的安装包或远程地址,请按项目 README 中的说明安装。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
OwnSearch
通过一组按评分筛选的公共 SearXNG 实例,提供可自托管的 MCP 和 HTTP 搜索服务。
mcp-name: io.github.devops-infinity/ownsearch
状态:预发布版本,工作区版本为 0.2.0。
OwnSearch 会从 searx.space 发现公共 SearXNG 实例,以较低频率探测并评分,将实例列表保存在本地 SQLite 数据库中;它会轮换起始实例,在实例故障时重试,并从下一个健康实例返回结果。每条结果都会附带提供该结果的来源,包括实例,以及在已知时提供结果的引擎。它通过标准输入/输出或 Streamable HTTP 作为模型上下文协议(MCP)服务运行,HTTP 端口还提供两个 REST 调用。
所有者:Md. Sazzad Hossain Sharkar。
参考资料:实例策略见 docs/scanner-policy.md,运行手册见 docs/operations.md,发布流程见 RELEASING.md,报告政策见 SECURITY.md。
目录
- 功能
- 默认启用的功能
- 不提供的功能
- 要求
- 构建和安装
- 快速开始
- 连接 MCP 客户端
- 工具
- 搜索行为
- 扫描器策略
- 质量模型
- 配置
- HTTP 模式
- 容器
- 本地文件与保留窗口
- 数据库
- 数据库命令
- AI 辅助数据库变更
- 开发
- 故障排除
- 隐私
- 安全
- 支持
- 贡献
- 分发
- 许可证
功能
- 从
https://searx.space/data/instances.json发现公共 HTTPS SearXNG 实例;首次运行时,在进行任何网络调用前导入包含 67 个实例的内嵌快照。 - 每次扫描对每个候选实例探测一次:解析主机并验证 TLS 证书链和证书日期,读取
/config,并进行一次 JSON 搜索。只有在 JSON 搜索被拒绝时才会进行 HTML 搜索;只有在实例声明支持 exact-Google 引擎且 JSON 搜索成功时,才会进行 exact-Google 搜索。 - 评分前先应用硬性门槛,因此证书即将过期、存在分析跟踪器或无法读取
/config的实例不会进入活跃实例列表。 - 通过实例数量上限、每个网络的实例数量上限和滞后机制选择活跃实例列表,避免一次不良扫描就移除正常运行的实例。
- 每次搜索都会轮换起始实例;遇到网络错误或
5xx时,每个实例最多尝试三次;反复失败的实例会进入冷却状态;随后切换到下一个实例,直到搜索成功或超过截止时间。 - 合并多个实例的结果,保留每条来源观测记录,并标记覆盖不完整的情况。
- 绝不重试
429,绝不执行工作量证明,也绝不伪装成人类浏览器。如果操作员设置了OWNSEARCH_CAPSOLVER_KEY,对于只出现在渲染页面中的验证挑战,可以使用 CapSolver 服务解决该页面的挑战。
默认启用的功能
这些功能默认启用。每项功能都由配置中对应的设置控制。
- HTML 搜索回退:开启。当某个实例以
403、其他4xx或5xx响应拒绝 JSON,或返回非 JSON 响应体时,OwnSearch 会改为读取普通 HTML 结果页。对于401、429和挑战页面,不会重试 HTML;这些情况将按隔离和冷却规则处理。 - 轮询选择:开启。每次搜索都会从不同的健康实例开始。
- 故障转移:开启。发生故障的实例会按配置进行重试,随后进入冷却,搜索会切换到下一个实例。
- 所选实例启用的所有搜索引擎:开启。默认情况下,OwnSearch 不发送引擎筛选条件,因此 Google、Bing、DuckDuckGo、Brave 以及该实例运行的所有其他引擎均可用。可在调用时设置
engines以缩小范围。 - 所有 SearXNG 类别:开启。默认情况下,OwnSearch 不发送类别筛选条件。
- 精确 Google 探测:开启;只要实例声明支持
google引擎,就会启用。 - 页面提取:开启。
ownsearch_fetch会抓取公开页面,并以 Markdown、纯文本或清理后的 HTML 格式返回内容,同时包含标题并限制内容大小。 - JavaScript 渲染:开启。当页面是空壳页面或调用设置了
render: "always"时,会使用无头 Chrome 渲染;浏览器会在使用期间保持打开,并在空闲、连续两次未收到健康检查响应或达到最长运行时间时关闭。 - 同主机爬取:开启。
ownsearch_fetch会从你指定的页面跟进最多max_pages - 1个链接,最多七个,并将每个页面放在pages下返回。same_host_only默认为 true,因此除非你允许,否则调用不会跳转到其他网站。 - 结果归属信息、字段预设、响应缓存、会话统计和类型化数据库更改(带预览和一次性令牌)均可直接使用,无需额外标志。
它不会做什么
- 它不会托管或运营 SearXNG 实例。
- 它不会调用付费搜索 API。
- 它不会让你的查询匿名。每个公共实例的运营者都能看到这些查询。
- 它不会在普通搜索结果上运行 JavaScript。无头浏览器仅供提取工具用于你指定的页面;作为最后手段,也会用于拒绝所有 HTTP 格式的实例所返回的搜索页面或探测页面。
- 它不会绕过机器人检查。许多公共实例会向自动化客户端返回
429、挑战页面或 CAPTCHA。OwnSearch 会记录这些情况并继续尝试其他实例;但如果设置了OWNSEARCH_CAPSOLVER_KEY,则可通过 CapSolver 服务解决仅在渲染页面中出现的挑战。
要求
- 构建需要 Rust 1.94.1 或更高版本。固定工具链版本见
rust-toolchain.toml(1.99.1)。 - Linux 或 macOS 机器。Windows 构建也在发布目标列表中。
- 用于发现、探测和搜索的出站 HTTPS 连接。
- 用于构建捆绑的 SQLite 的 C 编译器:Debian 和 Ubuntu 上的
build-essential,或 macOS 上的 Command Line Tools。 - 用于 JavaScript 渲染的 Chrome 或 Chromium 可执行文件。如果自动检测未能找到,请设置
OWNSEARCH_BROWSER_PATH。
构建和安装
git clone https://github.com/devops-infinity/ownsearch
cd ownsearch
cargo build --release --locked
二进制文件会生成在 target/release/ownsearch。通过完整检查后,可将其安装到 ~/.local/bin:
tools/reinstall.sh
快速开始
ownsearch doctor
ownsearch scan # refresh discovery and probe the fleet
ownsearch scan # once OWNSEARCH_SCAN_MIN_INTERVAL_SECS (30 by default) has passed, a second pass promotes repeat successes to active
ownsearch serve # MCP over stdio
试运行不会更改任何服务集数据,只会打印将要执行的操作。首次运行时可能会创建空的状态架构:
ownsearch scan --dry-run --limit 12
搜索使用当前活动服务集。如果没有活动实例,OwnSearch 会回退到通过所有硬性门槛的已扫描候选实例,并在 warnings 中说明这一点。
连接 MCP 客户端
{
"mcpServers": {
"ownsearch": {
"command": "/home/you/.local/bin/ownsearch",
"args": ["serve"],
"env": {
"OWNSEARCH_STATE_DIR": "/home/you/.local/state/ownsearch"
}
}
}
}
无需 API 密钥。OwnSearch 唯一可能持有的机密是 HTTP Bearer 令牌,仅在通过 Streamable HTTP 提供服务时使用。
使用 Streamable HTTP 时,将客户端指向 http://127.0.0.1:8774/mcp,或指向同一主机且不带路径的地址。这两个地址都会提供 MCP 端点,其他路径均会返回带有问题详情的 404 响应。该端口还响应 /healthz、/startupz、/readyz 和 /metrics。设置 OWNSEARCH_BEARER_TOKENS 后,请发送 Authorization: Bearer <token>。REST 调用 POST /v1/search 和 POST /v1/fetch 将工具参数作为 JSON 请求体。
工具
ownsearch_search:联邦式网络搜索。参数:query(必填)、categories、engines、language、page、time_range(day、week、month、year)、safesearch(off、moderate、strict)、limit、fields(minimal、standard、full)、mode(fast、balanced、exhaustive)、timeout_secs和result_text(summary、full)。回答前可能会刷新本地服务集状态。ownsearch_fetch:以markdown(默认)、text或html格式获取公开页面;url为必填项,max_chars范围为 1000 到 200000。max_pages范围为 1 到 8,默认值为 3;设为大于 1 时,会跟随第一页中的链接,并将结果放在pages下;除非same_host_only为 false,否则仅访问同一主机。HTTP 重定向最多跟随三跳,每一跳都会像首次请求一样通过公开地址检查;回答会报告finalUrl和redirects链,调用方无需猜测链接最终指向何处。application/pdf响应会在解压文本上限为 8 MiB 的条件下进行解析,并整理成 Markdown 段落。render用于选择浏览器:auto(默认)仅渲染看起来像空 JavaScript 框架的页面,always渲染每次调用,never则仅使用 HTTP。Markdown 从主要内容中提取:导航、侧边栏、Cookie 横幅、分享区块、评论区和页脚会被清除;内容最密集的根节点优先于链接列表;代码围栏会标注语言。私有地址和环回地址会被拒绝,且每个页面都会受到大小限制并经过清理。ownsearch_instance_info:提供单个实例或实例列表的生命周期和能力信息,包括其slug、状态、评分、排名、版本、JSON 和 HTML 访问方式、引擎、类别以及精确 Google 结果的证据。每个结果来源和每次扫描状态变更都会携带 slug;失败的来源会标明其实例 ID 和 URL。/config中的实例名称来自ownsearch_db_query,其entity为"capabilities"。ownsearch_instance_health:提供硬性门槛结果、证书剩余天数、TLS 协议和等级、搜索中位耗时、冷却状态、连续失败次数以及最近的生命周期事件。ownsearch_scan:刷新发现结果、探测实例、重新评分并重新选择服务集。默认值为dry_run: true。在同一进程内,每个状态数据库一次只能运行一个写入扫描;两次运行之间会等待OWNSEARCH_SCAN_MIN_INTERVAL_SECS,并且如果指定实例尚未到期,会拒绝执行,除非调用设置了force。ownsearch_session:提供本地调用次数、缓存状态、账本长度和头部信息,以及服务集大小。不进行网络调用。ownsearch_db_query:对实例、质量、策略覆盖项、能力快照、事件、快照和发现运行进行有界只读查询。每个实体都有自己的筛选条件;如果所选实体无法应用某个筛选条件,则会拒绝该条件,而非忽略。事件通过 SQL 分页,因此可以访问任意偏移量。它不接受 SQL。ownsearch_db_crud:执行一项有类型约束的生命周期或策略变更。需要写入模式、变更原因,以及来自试运行预览的一次性确认令牌。无法删除实例行。
每个工具都会返回 structuredContent 和一行文本摘要。每个输入架构都将 additionalProperties 设为 false。预设可能会省略的所有字段,在已发布的输出架构中均为可选项。
搜索行为
模式用于控制有多少个实例响应一次查询。
fast目标为一个实例。balanced(默认模式)目标为三个实例。exhaustive目标为OWNSEARCH_EXHAUSTIVE_MAX。
所有模式的故障转移方式相同。选中的实例会并行响应。对于每个实例,网络错误、超时或 5xx 最多重试 OWNSEARCH_SEARCH_ATTEMPTS 次。除 408 和 429 之外的 4xx、403 或质询页面都不会重试。如果实例仍然失败,OwnSearch 会设置其 cooldown_until,记录一个 search_failed 事件,并按评分顺序尝试下一个实例,直到达到目标数量或搜索截止时间(OWNSEARCH_SEARCH_DEADLINE_SECS)。搜索失败不会改变状态,也不会更改探测计数器。扫描探测或操作员命令会将实例切换到活跃、观察或隔离状态,且只有探测才会重置成功和失败计数。故障转移会按顺序继续遍历评分后的实例,直到达到目标数量或截止时间,因此仍能找到列表靠后的答案。前面设有一个有界队列:OWNSEARCH_SEARCH_MAX_CONCURRENT 个搜索会同时运行,最多有 OWNSEARCH_SEARCH_QUEUE_LIMIT 个搜索等待空位,等待时间为 OWNSEARCH_SEARCH_QUEUE_WAIT_SECS;其余搜索会返回 ownsearch.rate_limited,不会继续堆积任务,从而在小型机器上限制内存和 CPU 的使用。零结果答案也算成功,而非失败;只有结果中不含可用标题和 URL 的页面才算解析器失败。
轮询会在排名靠前的健康实例范围内轮换起始位置,因此连续两次搜索不会总是从同一个实例开始。如果你希望严格按评分顺序处理,可通过 OWNSEARCH_ROUND_ROBIN=false 关闭此功能。
在任何扫描为实例群评分之前,或所有已评分实例都处于冷却状态时,搜索会回退到排名最高、且未通过硬性检查失败的已发现实例,而不是以 ownsearch.no_fleet 失败,并会在响应的 warnings 中说明这一点。响应绝不会编造结果:当所有尝试都遭到拒绝或受到速率限制时,sources.failed 会列出每个实例、其代码以及响应内容。sources.fallbacks 会列出每个使用 HTML 解析器而非 JSON 返回答案的实例。
字段预设用于控制负载大小。minimal 保留标题、URL、排名、评分和来源 ID。standard 会额外包含摘要、引擎、发布日期和完整来源列表。full 保留所有内容。
扫描器策略
- 内置调度器会在启动时以及每个发现时间窗口(
OWNSEARCH_DISCOVERY_REFRESH_SECS)刷新发现结果,文档上限为 500 条记录。随后,它会在扫描间隔到期时探测符合条件的实例;每次只扫描一个实例,并在扫描前等待一段随机抖动时间。 - 即使实例的得分会使其落选,固定的实例仍会保留在选择结果中。固定实例会优先于得分排序、滞后机制、每个网络的数量上限以及 Google 要求,并允许候选记录或缺失记录加入实例集群。硬性门槛检查失败的实例仍会被排除。
- 如果发现记录中的主机解析到环回、私有、链路本地、文档专用或保留地址,则会跳过该记录;明确扫描被拒绝、已禁用、已退役或处于冷却状态的实例时会遭到拒绝。
- 每次运行中,每个实例的每种类型只探测一次。
- 默认情况下,探测任务并发数为 4,并带有随机抖动。
OWNSEARCH_SCAN_CONCURRENCY可更改任何运行(定时或按需)的并发数。 429会启动冷却,但保留实例状态。401或挑战页面会立即将实例隔离。403会计为扫描失败:重新安排扫描,并在失败次数超过阈值后将实例转入观察期或隔离状态。重复失败也会降低实例得分。- 用户代理会标明产品名称:
OwnSearch (MCP fleet scanner; +https://github.com/devops-infinity/ownsearch) v<version>。 - 不轮换代理,也不伪造请求头。只有在所有 HTTP 格式都被拒绝后,浏览器才会作为最后手段访问实例页面以检查其功能;绝不会用浏览器绕过已检测到的挑战。
完整策略见 docs/scanner-policy.md。
质量模型
硬性门槛,按以下顺序检查。任一项失败,实例都会被排除在活跃实例集群之外。
- 仅限 HTTPS。
- 证书链有效,且主机名匹配。
- 证书剩余有效天数不少于
OWNSEARCH_CERT_MIN_DAYS。 - 不含分析跟踪器。
/config可解析。- 必须包含精确的 Google,但仅在
OWNSEARCH_GOOGLE_REQUIRED=true时要求。
总分为 100 分:
- 月度正常运行时间,20 分。
- 年度正常运行时间,10 分。
- 搜索成功率,20 分。
- 搜索中位耗时,15 分。
- 初始响应成功率和耗时,10 分。
- 精确 Google 的成功率和耗时,10 分。
- TLS 等级、协议和证书有效期,10 分。
- SearXNG 版本新近程度,5 分。
- 有上限的修正项,最多 5 分,依据包括引擎覆盖率、类别覆盖率、连续成功、连续失败和解析器偏差。
实例集群选择按得分排序,最多选取 OWNSEARCH_FLEET_MAX 个实例;同一公告网络前缀下最多选取 OWNSEARCH_MAX_PER_NETWORK 个实例;排除 Tor 记录;如果设置了 OWNSEARCH_GOOGLE_REQUIRED,则排除不支持精确 Google 的实例,但固定的实例除外。滞后机制要求连续 OWNSEARCH_PROMOTE_SUCCESSES 次扫描成功才会晋升,连续 OWNSEARCH_PROBATION_FAILURES 次扫描失败才会降级,连续 OWNSEARCH_QUARANTINE_FAILURES 次扫描失败才会隔离。恢复的缺失实例会先进入观察期。
配置
设置的优先级依次为:CLI 标志、OWNSEARCH_* 环境变量、${XDG_CONFIG_HOME}/ownsearch/profile.toml 中的 TOML 配置档案,然后是内置默认值。
大多数环境变量都有对应的配置档案键:去掉 OWNSEARCH_ 前缀,并将其余部分转换为小写。例如,OWNSEARCH_FLEET_MAX 对应 fleet_max,OWNSEARCH_STATE_DIR 对应 state_dir。有三个键不遵循此规则:OWNSEARCH_BROWSER_PATH 对应 browser_executable,而 OWNSEARCH_BEARER_TOKENS 和 OWNSEARCH_PROFILE 没有对应的配置档案键。只有配置档案中存在的键有两个:cache_max_bytes 和 preset。
路径和传输方式
OWNSEARCH_PROFILE:TOML 配置文件的路径。OWNSEARCH_STATE_DIR:存放instances.db、快照、事件和备份的目录。默认值为${XDG_STATE_HOME}/ownsearch。OWNSEARCH_LEDGER_DIR:存放calls.jsonl、其归档文件和args.key的目录。默认值为${XDG_DATA_HOME}/ownsearch/ledger。OWNSEARCH_HTTP:使用 Streamable HTTP 而非 stdio 提供服务。默认值为 false。OWNSEARCH_BIND:HTTP 绑定地址。默认值为127.0.0.1:8774。OWNSEARCH_BEARER_TOKENS:以逗号分隔的 bearer 令牌,每个至少 32 个字符。OWNSEARCH_ALLOWED_HOSTS:HTTP 模式下以逗号分隔的Host值。OWNSEARCH_ALLOWED_ORIGINS:HTTP 模式下以逗号分隔的Origin值。OWNSEARCH_LOG_FORMAT:text或json。日志仅写入 stderr。OWNSEARCH_ALLOW_PRIVATE_INSTANCES:接受发现记录、探测、搜索和抓取中的回环地址及专用地址。默认值为 false,此选项仅用于本地测试。在任何可访问互联网的部署中都应保持关闭,因为启用后,恶意发现文档可能会将扫描器指向本地服务。
发现和扫描
OWNSEARCH_DISCOVERY_URL:发现源。默认值为https://searx.space/data/instances.json。OWNSEARCH_DISCOVERY_REFRESH_SECS:刷新间隔。默认值为 21600。OWNSEARCH_OFFLINE:跳过发现,仅使用本地状态。默认值为 false。OWNSEARCH_SCAN_CONCURRENCY:并行探测数,范围为 1 到 8。默认值为 4。OWNSEARCH_SCAN_JITTER_MS:探测之间的随机延迟,上限为此毫秒数。默认值为 250。OWNSEARCH_PROBE_TIMEOUT_SECS:每个探测步骤中单个请求的超时时间。默认值为 15;单次探测在达到此值的 5 倍时停止。OWNSEARCH_SCAN_DEADLINE_SECS:整个扫描的时限。默认值为 600,范围为 30 到 7200。超过时限后,扫描会发出警告并停止。OWNSEARCH_SCAN_MIN_INTERVAL_SECS:同一状态数据库上两次写入扫描之间的最短间隔。默认值为 30,范围为 0 到 3600;设为 0 可关闭间隔限制。无论如何,同一进程内始终一次只运行一个扫描。OWNSEARCH_FETCH_DEADLINE_SECS:整个抓取的时限,包括跟踪链接和浏览器渲染。默认值为 60,范围为 5 到 600。OWNSEARCH_BROWSER:在无头 Chrome 中渲染 JavaScript 页面。默认值为 true。OWNSEARCH_BROWSER_PATH:Chrome 或 Chromium 可执行文件。留空时自动检测。OWNSEARCH_BROWSER_IDLE_SECS:浏览器空闲时保持打开的时间。默认值为 120,范围为 30 到 3600。OWNSEARCH_BROWSER_NO_SANDBOX:传入--no-sandbox;对于无法设置沙箱的容器,此选项为必需。默认值为 false。OWNSEARCH_BROWSER_WATCHDOG_SECS:检查此进程启动的浏览器是否响应的频率。默认值为 30,范围为 5 到 600。连续两次未收到响应时会关闭浏览器。OWNSEARCH_BROWSER_MAX_LIFETIME_SECS:浏览器会话被替换前可持续的最长时间。默认值为 1800,范围为 60 到 86400。OWNSEARCH_REQUEST_TIMEOUT_SECS:HTTP 客户端超时时间。默认值为 30。OWNSEARCH_CONNECT_TIMEOUT_SECS:连接超时时间。默认值为 5。OWNSEARCH_MAX_UPSTREAM_BYTES:响应正文大小上限。默认值为 4194304。OWNSEARCH_COOLDOWN_SECS:触发速率限制、遇到验证挑战或搜索失败后的冷却时间。默认值为 3600。OWNSEARCH_PROMOTE_SUCCESSES、OWNSEARCH_PROBATION_FAILURES、OWNSEARCH_QUARANTINE_FAILURES:滞后阈值。默认值分别为 2、2、4。OWNSEARCH_FLEET_MIN、OWNSEARCH_FLEET_MAX:实例集群大小。默认值分别为 6 和 12。OWNSEARCH_MAX_PER_NETWORK:每个公告网络前缀允许的实例数。默认值为 2。OWNSEARCH_CERT_MIN_DAYS:证书有效期门槛。默认值为 14。OWNSEARCH_HTML_FALLBACK:启用 HTML 探测和回退。默认值为 true。OWNSEARCH_GOOGLE_REQUIRED:将精确匹配 Google 设为硬性门槛。默认值为 false。
搜索
OWNSEARCH_SEARCH_DEADLINE_SECS:整个搜索的截止时间,默认 30。OWNSEARCH_EXHAUSTIVE_MAX:exhaustive模式下的实例数,默认 16。OWNSEARCH_SEARCH_ATTEMPTS:每个实例的尝试次数,范围为 1 至 5。默认 3。OWNSEARCH_SEARCH_FAILOVER:故障时切换到下一个实例。默认 true。OWNSEARCH_ROUND_ROBIN:轮换起始实例。默认 true。OWNSEARCH_RESULT_CAP:默认结果上限,也是一次调用的limit上限。默认 25,范围为 1 至 100。OWNSEARCH_SEARCH_MAX_CONCURRENT:同时运行的搜索数,默认 8。OWNSEARCH_SEARCH_QUEUE_LIMIT:允许等待空位的搜索数,默认 64。OWNSEARCH_SEARCH_QUEUE_WAIT_SECS:排队中的搜索等待多久后返回ownsearch.rate_limited,默认 30。OWNSEARCH_CACHE_TTL_SECS:缓存的答案保持新鲜的时长。默认 300,设为 0 可关闭缓存。- 配置文件键
cache_max_bytes:缓存字节上限。默认 16 MiB。 - 配置文件键
preset:默认字段预设,可选minimal、standard或full。默认standard。
保留窗口与维护
OWNSEARCH_KEEP_WINDOW:账本归档、事件行和迁移前备份的保留时长。接受90s、15m、2h、3d或纯秒数。默认3d。最短 1 小时,最长 90 天;负值或格式错误的值会在启动时被拒绝。OWNSEARCH_MAINTENANCE_INTERVAL_SECS:运行中的服务执行清理程序的频率。默认 3600,最小 60,最大 86400。OWNSEARCH_WATCHDOG_SECS:进程在退出前允许无进展的时长;超时后进程以代码 75 退出,以便监管程序重新启动。默认 120,范围为 0 至 3600;设为 0 可关闭此功能。
清理程序会在启动时、每次扫描应用后、服务运行期间按该间隔执行,也会在 ownsearch db maintenance 中执行。如果实时账本中最早的行超过保留时长,就会轮换账本;还会删除超过保留窗口的账本归档和 pre-migration-*.db 文件,并从 instances.events.jsonl 中清除旧行。清理期间会锁定文件,因此不会丢失恰好在同一时刻写入的事件。相同的间隔也会清理 SQLite 中的旧行:探测、TLS 观察、能力快照、指标、快照、事件和发现运行各自有独立的保留窗口;ownsearch db maintenance 会报告清理内容。同一状态数据库上的两个进程会通过锁文件轮流执行,因此清理不会重复运行。如果文件无法删除,本次运行会记录一条警告,指出可通过 ownsearch db maintenance 手动修复;如果清理报告了问题,还会在 maintenance_runs 中写入一条 attention 记录。
AI 数据库更改
OWNSEARCH_AI_DB_MODE:read-only或read-write。默认read-write,因为每项更改仍需预览和一次性令牌;设置为read-only可拒绝所有通过输入执行的数据库更改。OWNSEARCH_AI_DB_MAX_CHANGES_PER_CALL:每次调用的字段更改数,默认 5。OWNSEARCH_AI_DB_CONFIRM_TTL_SECS:确认有效期,默认 120。OWNSEARCH_AI_DB_MIN_INTERVAL_SECS:应用更改的最小间隔,默认 2。
配置文件示例
version = 1
fleet_min = 6
fleet_max = 12
html_fallback = true
google_required = false
result_cap = 10
search_attempts = 3
round_robin = true
keep_window = "3d"
ai_db_mode = "read-only"
HTTP 模式
OWNSEARCH_BEARER_TOKENS="$(openssl rand -hex 24)" ownsearch serve --http
任何长度至少为 32 个字符的随机值都可用;openssl rand -hex 24 是一种生成方式。
- 默认绑定地址为
127.0.0.1:8774。 - 不带 bearer token 的非环回绑定会在启动时被拒绝。
- token 至少需要 32 个字符,并采用恒定时间比较。
Host会根据环回地址列表或OWNSEARCH_ALLOWED_HOSTS进行检查。- 除非
Origin标头与OWNSEARCH_ALLOWED_ORIGINS匹配,否则请求会被拒绝。 - 请求正文上限为 1 MiB,标头必须在 10 秒内到达,并发请求数量也设有上限。
GET /healthz用于存活检查。GET /startupz会在每次请求时执行快速数据库检查,检查失败时返回 503。GET /readyz会在每次请求时执行开销较低的存活读取,并在关闭期间失败,因此监控程序无需等待全数据库扫描。GET /metrics会报告调用计数、各工具计数,以及带有延迟总和与最大值的各路由 HTTP 计数。- 中间件按最外层优先的顺序运行:正文截止时间、请求 ID、Origin 检查、Host 检查、bearer 检查、并发限制、正文大小限制、跟踪层、指标、路由。安全标头会包裹整个路由器。跟踪层会记录方法、路径、状态和延迟。
- 关闭时会先将就绪状态设为不可用,然后在截止时间内排空正在处理的调用。
- 在 supervisor 下,卡死的进程会被替换。
OWNSEARCH_WATCHDOG_SECS限制进程卡顿后以代码 75 退出前的最长时间;docker-compose.yml设置了restart: unless-stopped,并将停止宽限期设为 30 秒。
REST 端点
同一引擎会在 HTTP 端口上提供两个 JSON 端点,并与 MCP 流使用相同的 bearer 检查、Origin 检查、Host 检查和正文大小限制。
POST /v1/search接受ownsearch_search的字段,其中query为必填项。POST /v1/fetch接受ownsearch_fetch的字段,其中url为必填项。
curl -s http://127.0.0.1:8774/v1/search \
-H 'content-type: application/json' \
-d '{"query":"rust programming language","limit":5}'
调用成功时返回 200,并包含 MCP 工具返回的结构化内容。调用被拒绝时,若参数无效则返回 400,若 token 缺失或错误则返回 401,若策略拒绝则返回 403,若路由或资源不存在则返回 404,若方法错误则返回 405,若确认已过期则返回 409,若触发速率限制则返回 429,若上游失败则返回 502,若没有可用服务实例或正在关闭则返回 503,若发生超时则返回 504。响应正文采用 RFC 9457 application/problem+json 格式,包含 type、title、status、detail、instance 以及作为扩展成员的稳定字段 code 和 remedy,不包含任何内部细节。每次 REST 调用都会记录在账本中,并像 MCP 调用一样计入 /metrics。
任何远程使用场景都应在前面部署 Caddy。切勿暴露未进行身份验证的扫描器。
将 token 列表存储在操作系统的密钥链中,而非环境变量中:
printf '%s' "$TOKEN" | ownsearch config set-bearer-token
容器
docker build -t ownsearch .
docker run --rm -p 127.0.0.1:8774:8774 \
-e OWNSEARCH_BEARER_TOKENS="$(openssl rand -hex 24)" \
-v ownsearch-state:/home/ownsearch/.local/state/ownsearch \
ownsearch
docker-compose.yml 保存了相同的配置,并包含 restart: unless-stopped、两个状态卷和健康检查。镜像设置了 OWNSEARCH_BIND=0.0.0.0:8774、位于 /home/ownsearch/.local/share/ownsearch/ledger 下的账本目录,以及 OWNSEARCH_BROWSER=false,因此容器不会渲染任何页面。运行时必须设置 OWNSEARCH_BEARER_TOKENS,否则服务会拒绝启动。添加 OWNSEARCH_ALLOWED_HOSTS 并填写客户端使用的名称,否则 Host 检查会拒绝所有 Host 不是 localhost 或绑定地址的请求。状态卷会在重启后保留数据库和快照;如果需要在重启后保留账本和 args.key,也请挂载账本目录。
本地文件与保留窗口
- 数据库:
${XDG_STATE_HOME}/ownsearch/instances.db,或OWNSEARCH_STATE_DIR/instances.db。 - 快照:同目录下的
instances.snapshot.json,每次发现运行、扫描、AI 更改以及引导导入后都会重新生成。 - 发现历史:
instances.events.jsonl,会按保留窗口裁剪。 - 你创建的备份:
backups/instances-<stamp>.db,使用VACUUM INTO写入,通过快速检查和外键检查验证,并像其他临时文件一样在保留窗口结束后删除。 - 迁移前备份:
pre-migration-<stamp>.db,会在保留窗口结束后删除。 - 浏览器配置文件:状态目录下的
browser/profile-<pid>,仅所有者可访问,会在会话关闭时删除,并在启动时清理其所属进程已退出的配置文件。 - 账本:
calls.jsonl,在保留期限边界归档为calls-<stamp>.jsonl,并删除超过保留窗口的归档。 - 参数密钥:账本旁的
args.key。它用于参数哈希和账本链,因此会保留。
状态目录以模式 0700 创建,文件以模式 0600 创建。WAL 模式会生成 instances.db-wal 和 instances.db-shm。数据库行各自有保留窗口,由 ownsearch db maintenance 执行清理:探测记录保留 90 天,TLS 观测记录保留 90 天,能力快照保留 90 天,小时指标保留 180 天,集群快照保留 30 天,发现运行记录保留 180 天,生命周期事件保留 365 天。扫描器永远不会删除实例行。
数据库
数据库采用 WAL 模式的 SQLite,启用外键,使用 STRICT 表,并设有带校验和的迁移账本。一个迁移文件包含完整架构:表、外键、检查约束、索引和视图,因此开发构建始终可一步创建当前架构。列级架构位于 crates/ownsearch-core/src/db/migrations/0001_initial.sql;本页不再重复说明。
数据表包括:schema_migrations、application_metadata、discovery_sources、discovery_runs、instances、capability_snapshots、engines、categories、capability_engines、capability_categories、probes、tls_observations、hourly_probe_metrics、instance_quality、instance_events、fleet_snapshots、instance_policy_overrides 和 maintenance_runs。两个视图用于高频路径:active_fleet 和 scan_due。
ownsearch db verify 会检查文件完整性和外键,并显示架构版本。存储层在打开数据库时也会检查每个迁移的校验和。备份使用 VACUUM INTO 写入,并在使用前进行验证。
数据库命令
ownsearch db pathownsearch db verifyownsearch db backup [--out PATH]ownsearch db export [--out PATH]ownsearch db maintenance(WAL 检查点、压缩、数据过期处理和清理)ownsearch db counts [--json]ownsearch instances list [--status S] [--limit N] [--json]ownsearch instances show [ID] [--url URL] [--json]ownsearch instances add URL [--pin] [--json]ownsearch instances pin ID、unpin ID、deny ID [--reason TEXT]、reset-status IDownsearch instances retire ID [--reason TEXT]、restore ID
你自己的实例
ownsearch instances add http://localhost:8888/ --pin 会存储你自行运行的 SearXNG 实例,无论它监听的是 localhost 端口、Docker 网络地址,还是任何其他私有地址。该实例初始状态为候选。扫描会像探测其他实例一样探测它,两次探测通过后便会将其提升为活动状态,之后搜索就会使用它。回环地址或私有主机不会进行 TLS 和证书检查,因为这些检查是针对公共主机的。地址规则仍然适用:设置 OWNSEARCH_ALLOW_PRIVATE_INSTANCES=true,并确保实例位于你控制的网络中,因为相同设置也会允许恶意发现文档将扫描器指向本地服务。
实例 CRUD 示例
创建实例:
ownsearch instances add http://127.0.0.1:8080/ --pin
读取实例:
ownsearch instances list --limit 10
ownsearch instances show 1
ownsearch instances show --url http://127.0.0.1:8080/
更新其策略:
ownsearch instances pin 1
ownsearch instances unpin 1
ownsearch instances deny 1 --reason "host is gone"
ownsearch instances reset-status 1
将其从实例集群中删除;这会将其退役,而不是删除该行:
ownsearch instances retire 1 --reason "replaced by another host"
恢复实例:
ownsearch instances restore 1
通过扫描将变更应用到实例集群:
ownsearch scan --instance 1 --force
实例永远不会被删除,因此其探测历史和事件始终可读。retire 是生命周期中的删除步骤,restore 会将已退役或缺失的实例恢复为候选状态。通过 MCP 使用 ownsearch_db_crud 也能执行相同操作,并采用预览和一次性令牌流程。
AI 辅助数据库变更
默认启用写入模式。每项变更仍需先预览,再单独调用应用操作并携带一次性令牌;OWNSEARCH_AI_DB_MODE=read-only 会拒绝所有变更。
- 客户端使用
dry_run: true调用ownsearch_db_crud。OwnSearch 会验证实体、字段允许列表、值类型和生命周期转换,然后返回变更前后的预览,以及一个带有有效期的一次性令牌。使用令牌时会强制执行应用操作之间的最短间隔。 - 客户端再次调用,设置
dry_run: false并提供令牌。OwnSearch 会在一个事务中精确应用预览过的变更、追加一条生命周期事件、重新生成快照,并返回已提交的记录。 - 要添加实例,请使用相同工具,设置
operation: create、entity: instance,并将url设置为实例地址。预览和令牌流程相同,实例的存储方式与ownsearch instances add完全一致。 - 令牌过期、预览内容发生变化、令牌被重放、使用原始 SQL 字段、字段未知或处于只读模式时,都会返回带有解决方法的稳定错误;每次拒绝操作都会写入事件历史。
该工具可以创建或移除策略覆盖项、更新生命周期和策略字段、退役实例,或恢复已退役或缺失的实例。它无法删除实例行、改写探测记录或伪造事件。将 status 设为 active 需要通过硬性门槛检查。
开发
cargo fmt --all -- --check
cargo check --workspace --all-targets --all-features --locked
cargo clippy --workspace --all-targets --all-features --locked -- -D warnings
cargo test --workspace --all-features --locked
cargo test --workspace --all-features --locked --doc
RUSTDOCFLAGS="-D warnings" cargo doc --workspace --all-features --no-deps --locked
cargo llvm-cov --workspace --all-features --locked --fail-under-lines 80
cargo run -p ownsearch -- sbom
tools/verify.sh
tools/smoke.sh http://127.0.0.1:8774
默认情况下,实时测试会被忽略,因为它需要访问公共网络:
cargo test -p ownsearch-core --test live -- --ignored --nocapture
故障排除
ownsearch.no_fleet:运行ownsearch scan,然后检查ownsearch instances list。- 所有搜索都没有结果,且
sources.failed显示ownsearch.policy_refused:所选实例拒绝 JSON 和 HTML。请从实例接受的网络运行,或检查ownsearch instances list中是否有已隔离的记录。 ownsearch.state_corrupted:运行ownsearch db verify并恢复最新备份。ownsearch.write_disabled:设置ai_db_mode = "read-write"。ownsearch.confirmation_expired:再次调用该工具,并设置dry_run: true。- 磁盘空间不足:降低用于账本归档、事件行和迁移前备份的
OWNSEARCH_KEEP_WINDOW,然后运行ownsearch db maintenance并查看其输出的警告。SQLite 行遵循“本地文件和保留窗口”部分所列的各表固定窗口。 - 启动错误会指出设置名称及其取值范围。请修正该值,或移除该设置以使用默认值。
- 进程以代码 75 退出:在
OWNSEARCH_WATCHDOG_SECS时间内未取得进展,因此进程已停止。请检查日志中的最后一个请求,并让监管程序重新启动该进程。
隐私
查询会发送到你选择的公共实例以及这些实例背后的引擎。OwnSearch 不存储原始查询文本。账本会记录参数的带密钥哈希、工具名称、状态、上游 HTTP 状态类别、耗时、字节数、解析器和实例 ID。系统不会收集遥测数据。
安全
- 整个工作区中没有任何
unsafe代码。 - 发现记录仅限公共地址,因此恶意文档无法将扫描器指向本地或内部服务。
- 所有出站连接均使用 rustls,并严格验证证书。
- 限制响应读取量和连接数,并设置请求截止时间。
- 搜索结果是数据。每个字符串都会经过净化处理,移除不可见字符和控制字符;URL 必须使用 HTTP 或 HTTPS;过长的值会被截断,并附带可见标记。
- 不会通过命令行接收、写入配置文件或由任何命令打印任何机密。
- 浏览器在每个进程独立的配置文件下运行,仅所有者可访问;若浏览器挂起、进入空闲状态或超过最大运行时长,则会将其关闭。只会关闭由 OwnSearch 启动的浏览器。
请私下报告漏洞;SECURITY.md 说明了具体方式。
支持
如有疑问、报告错误或遇到安装问题,请写信至 [email protected]。请附上版本、运行的命令和输出。安全问题请按 SECURITY.md 中的说明处理,不要发送到此地址的常规支持队列。
运行手册位于 docs/operations.md:服务级别、检测、分诊、自愈行为和基线。
贡献
此代码库由一位维护者负责。开始大型工作前,请将补丁或提案发送至 [email protected],并在提交更改前运行 tools/verify.sh。完整门禁通过后,更改即可合并;RELEASING.md 列出了门禁运行的检查项。
分发
每个版本都包含 sha256.sum,涵盖所有归档、安装程序、formula 和 MCPB 包,并使用 minisign 签名。ownsearch sbom 可根据 Cargo.lock 按需生成 CycloneDX 1.7 软件物料清单。
发布渠道:
- GitHub 发布归档和校验和,使用 minisign 签名。
- Shell 和 PowerShell 安装程序。
- 根据发布归档构建的 Homebrew formula。
- npm 加载器
@devops-infinity/ownsearch。 - crates.io 包
ownsearch-core和ownsearch。 - MCP Registry 条目
io.github.devops-infinity/ownsearch。 - 面向桌面客户端的 MCP 包(MCPB)。
ghcr.io/devops-infinity/ownsearch镜像。
v* 标签会启动发布工作流,构建七个目标,然后创建并发布 GitHub 发布版本。标签生成前,门禁会通过 tools/verify.sh 在机器上运行,因此工作流不会重复运行这些检查。该工作流中的每个 action 都固定到某个提交,因此移动标签不会改变实际运行的内容。RELEASING.md 列出了按顺序执行的发布步骤及各步骤所需的凭据。
许可证
可自行选择 MIT 或 Apache-2.0。完整文本见 LICENSE-MIT 和 LICENSE-APACHE。HTML 解析器(scraper)引入了 MPL-2.0 组件(cssparser、selectors、dtoa-short),这些组件作为未经修改的依赖项使用;MPL-2.0 允许在采用其他许可证的更大作品中这样使用。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。