Files
2026-08-21 16:00:13 +08:00
..
2026-08-21 16:00:13 +08:00
2026-08-21 16:00:13 +08:00
2026-08-21 16:00:13 +08:00
2026-08-21 16:00:13 +08:00
2026-08-21 16:00:13 +08:00
2026-08-21 16:00:13 +08:00

博闻 Bowen · MCP Web Search

博闻是魂镜的 MCP 联网搜索服务,支持多搜索引擎、多 API 密钥智能轮询、两级缓存和双传输模式。

文化命名出自《礼记·中庸》「博闻强识而让」,与辰正、一炁等同属魂镜文化命名体系。工程路径保留 mcp/web-search。


架构概览

flowchart TD
    subgraph L1["① 传输层"]
        ST["stdio<br/>stdin/stdout JSON-RPC"]
        SSE["HTTP SSE<br/>/sse + /messages"]
        HTTP["简化 HTTP<br/>/tools/list + /tools/call"]
    end

    subgraph L2["② 核心处理器"]
        H["Handler<br/>传输层共享"]
        C["Cache Manager<br/>L1 LRU → L2 Redis"]
    end

    subgraph L3["③ 负载均衡"]
        LB["Load Balancer"]
        KP["KeyPool<br/>EWMA 动态权重"]
        CB["Circuit Breaker<br/>closed / open / half-open"]
    end

    subgraph L4["④ 搜索提供商"]
        T[Tavily]
        B[Bing]
        V[Brave]
    end

    subgraph L5["⑤ 可观测性"]
        M["Prometheus Metrics<br/>7 指标"]
        S["/status + /health"]
        A["管理 API<br/>enable / disable / clear"]
    end

    ST --> H
    SSE --> H
    HTTP --> H
    H --> C
    H --> LB
    LB --> KP
    KP --> CB
    LB --> T
    LB --> B
    LB --> V
    H --> M
    H --> S
    H --> A

核心特性

特性 说明
多 Provider Tavily、Bing、Brave 三家搜索,统一响应格式
多 Key 轮询 每 Provider 可配多个 API Key,按 EWMA 动态权重(延迟×成功率)自动排序
熔断器 每个 Key 独立熔断(closed → open → half-open),失败 key 自动隔离并恢复探测
故障转移 一个 Key 失败自动换 Key,一个 Provider 耗尽自动切其他 Provider
双传输 HTTP SSE(远程 Client 直连)+ stdio(子进程集成),由 --port / --stdio CLI 标志决定
两级缓存 L1 内存 LRU(毫秒级)+ L2 Redis(可选,跨实例共享),L2 命中自动升温到 L1
配置热重载 fsnotify 监听 YAML 变更,动态调整 provider 启用/禁用、缓存 TTL、重试次数,无需重启
管理 API 运行时启用/禁用 provider、清空缓存、查询密钥状态
SearchMode first(首个成功返回,默认低延迟)+ merge(并发搜所有引擎,URL 去重排序)
可观测性 暗色风格 HTML 监控面板(:9090)、Prometheus 指标(:9090/metrics)、结构化彩色日志

快速开始

前置条件

  • Go 1.22+
  • 至少一个搜索 API Key(Tavily / Bing / Brave)
  • (可选)Redis 用于二级缓存

环境变量快速配置

# 必填——搜索 API Key(逗号分隔支持多 key 轮询)
export TAVILY_API_KEYS="tvly-key1,tvly-key2"
export BRAVE_API_KEYS="brave-key1"

完整环境变量见项目根目录 .env.example 中的「博闻」段。

启动

# HTTP SSE 模式(供 MCP Client 远程连接,或供灵台注册为工具)
go run ./cmd/server --port 8080

# stdio 模式(供 Claude Desktop / Cursor 等 MCP Client 子进程集成)
go run ./cmd/server --stdio

# 指定 YAML 配置文件(可选,不传则自动探测 config/mcp/web-search.yaml)
go run ./cmd/server --config ../../config/mcp/web-search.yaml

验证

# 存活探针
curl http://localhost:8080/health
# → {"status":"ok"}

# 系统状态
curl http://localhost:8080/status
# → {"version":"2.0.0","uptime":"...","providers":[...],"cache":{...}}

# 工具列表(MCP tools/list)
curl -X POST http://localhost:8080/tools/list
# → {"tools":[{"name":"web_search",...}]}

# 搜索调用
curl -X POST http://localhost:8080/tools/call \
  -H "Content-Type: application/json" \
  -d '{"tool":"web_search","input":{"query":"hello world"}}'

# 监控面板(浏览器打开)
open http://localhost:9090

端口规划

端口 用途 说明
8080 MCP 服务端口 tools/list、tools/call、SSE、管理 API、/health、/status
9090 监控端口 HTML 仪表盘(/)、Prometheus 指标(/metrics)、存活探针(/health)

MCP 服务端点(端口 8080)

MCP 协议端点

路径 方法 说明
POST /tools/list POST 列出可用工具(web_search),含 inputSchema
POST /tools/call POST 调用 web_search 工具执行搜索
GET /sse GET SSE 事件流(MCP 标准握手)
POST /messages POST MCP JSON-RPC 消息(与 /sse 配对使用)
GET / GET 端点指引(纯文本)

web_search 工具

inputSchema:

参数 类型 默认 说明
query string (必填) 搜索关键词
max_results integer 5 最大返回结果数(1–20)
mode string "first" 搜索模式:first(首个成功返回) / merge(并发搜所有引擎后合并去重)
providers string[] 全部 优先使用的搜索引擎

响应(CallToolResult):

{
  "content": [{
    "type": "json",
    "text": "{\"provider\":\"tavily\",\"query\":\"...\",\"results\":[...],\"total_count\":5,\"cached\":false}"
  }]
}

管理端点

路径 方法 说明
GET /health GET 存活探针 → {"status":"ok"}
GET /status GET 系统状态:provider 列表、活跃密钥数、缓存命中率、uptime
GET /admin/keys GET 各 provider 启用状态
PUT /admin/provider/{name}/enable PUT 启用指定 provider
PUT /admin/provider/{name}/disable PUT 禁用指定 provider
POST /admin/cache/clear POST 清空缓存

监控面板(端口 9090)

HTML 仪表盘 GET /

暗色风格的可视化面板,展示:

  • 四张概览卡片:Provider 数、活跃密钥数、缓存命中率(绿/黄/红三档)、缓存条目总数
  • Provider 状态表格:🟢/🔴 状态指示灯、名称、启用/禁用开关、活跃密钥计数
  • 缓存统计表格:L1(内存 LRU)命中、L2(Redis)命中、未命中、综合命中率
  • 自动刷新:每 30 秒自动刷新
  • 导航链接:一键跳转 /status、/admin/keys、/health

Prometheus 原始指标 GET /metrics

指标名 类型 标签 说明
bowen_search_total Counter provider 搜索请求总数
bowen_search_duration_seconds Histogram — 搜索耗时分布
bowen_search_errors_total Counter reason 搜索错误数
bowen_cache_hits_total Counter — 缓存命中总数
bowen_cache_hits_l2_total Counter — Redis 二级缓存命中数
bowen_cache_misses_total Counter — 缓存未命中数
bowen_active_keys Gauge provider 各 provider 活跃密钥数

所有监控端点也可在端口 9090 访问,与 MCP 服务端口独立。


配置文件

非敏感配置放在项目根目录 config/mcp/web-search.yaml(从 config/mcp/web-search.example.yaml 复制)。 不传 --config 时自动按项目惯例探测:开发模式探测 ../../config/mcp/web-search.yaml,容器内探测 /etc/bowen/config.yaml。

server:
  port: 8080                # SSE 模式监听端口
  read_timeout: 30s         # HTTP 读取超时
  write_timeout: 30s        # HTTP 写入超时

providers:
  tavily:
    enabled: true           # 是否启用(热重载:支持动态变更)
    timeout: 10s
    max_results: 10
    health_check:
      interval: 60s
      failure_threshold: 3
  bing:
    enabled: true
    timeout: 10s
    max_results: 20
  brave:
    enabled: true
    timeout: 10s
    max_results: 10

balancer:
  strategy: weighted_round_robin
  retry_count: 2            # 热重载:支持动态变更
  circuit_breaker:
    enabled: true
    failure_threshold: 5
    cooldown: 30s

cache:
  enabled: true
  ttl: 5m                   # 热重载:支持动态变更
  max_items: 1000
  redis:
    enabled: false           # 需要自行部署 Redis
    addr: 127.0.0.1:6379
    password: ""
    db: 0

metrics:
  enabled: true
  port: 9090
  path: /metrics

配置优先级:环境变量 > YAML 文件 > 内置默认值

热重载:指定 --config 后,修改 YAML 文件自动生效(500ms 防抖),支持动态变更:

配置项 变更后自动生效
providers.{name}.enabled 运行时启用/禁用搜索源
cache.ttl 更新新缓存条目的过期时间
balancer.retry_count 更新重试次数

传输模式

博闻支持两种 MCP 传输模式,不在配置中写死,由启动 CLI 参数决定:

模式 启动方式 适用场景
SSE --port 8080 灵台后端注册(简化 HTTP 端点 /tools/list + /tools/call)、远程 MCP Client 直连(/sse + /messages)
Stdio --stdio Claude Desktop / Cursor 等 MCP Client 以子进程方式启动,通过 stdin/stdout 走 JSON-RPC 通信

两种模式下核心业务逻辑完全共享(internal/mcp/handler.go),只有传输层不同。


环境变量

所有敏感信息通过环境变量注入(参见 .env.example 博闻段):

变量 必填 说明
TAVILY_API_KEYS 是 Tavily 搜索 Key,多 key 逗号分隔
BRAVE_API_KEYS 是 Brave Search Key
MCP_WEB_SEARCH_REDIS_ENABLED 否 Redis 二级缓存开关
MCP_WEB_SEARCH_REDIS_ADDR 否 Redis 地址(默认 127.0.0.1:6379)
MCP_WEB_SEARCH_REDIS_PASSWORD 否 Redis 密码
MCP_WEB_SEARCH_REDIS_DB 否 Redis 数据库编号(默认 0)

开发

# 运行所有测试
make test

# 编译
make build           # → bin/bowen-server

# 本地 SSE 模式
make run-sse

# 本地 stdio 模式
make run-stdio

# 代码检查
make lint

开发环境日志自动使用彩色输出(ANSI 颜色代码):

  • INFO → 绿色
  • WARN → 黄色
  • ERROR → 红色
  • DEBUG → 灰色

生产环境(ENV=production)自动切换为 JSON 格式,便于日志采集系统采集。

项目结构

mcp/web-search/
├── cmd/server/main.go              # 入口(--port / --stdio)
├── internal/
│   ├── config/
│   │   ├── config.go               # YAML + 环境变量配置加载
│   │   ├── yaml.go                 # YAML 解析
│   │   └── reloader.go            # 配置热重载(fsnotify)
│   ├── logger/logger.go            # slog 双模式(dev 彩色 / prod JSON)
│   ├── models/types.go             # 核心数据类型
│   ├── providers/                  # 搜索提供商适配
│   │   ├── provider.go             # SearchProvider 接口
│   │   ├── tavily.go / bing.go / brave.go
│   │   └── registry.go            # 注册中心
│   ├── balancer/                   # 负载均衡
│   │   ├── keypool.go              # 密钥池(EWMA)
│   │   ├── circuitbreaker.go       # 熔断器
│   │   └── balancer.go            # LoadBalancer
│   ├── cache/cache.go              # 两级缓存
│   ├── mcp/                        # MCP 协议实现
│   │   ├── handler.go              # 核心处理逻辑
│   │   ├── stdio.go                # stdin/stdout JSON-RPC
│   │   ├── sse.go                  # HTTP SSE 传输
│   │   ├── http.go                 # 简化 HTTP 端点
│   │   ├── status.go               # /health + /status
│   │   ├── admin.go                # 管理 API
│   │   └── monitor.go              # HTML 监控面板
│   └── metrics/metrics.go          # Prometheus 指标
├── Makefile
├── go.mod / go.sum

Docker

# 构建镜像
docker build -t bowen-web-search -f ../../docker/Dockerfile.web-search .

# 运行
docker run \
  -e TAVILY_API_KEYS=tvly-xxx \
  -e BRAVE_API_KEYS=brave-xxx \
  -p 8080:8080 -p 9090:9090 \
  bowen-web-search

Docker 镜像可通过魂镜的 docker/docker-compose.app.yml 编排启动。


集成到灵台

后端通过 MCP 注册 API 自动接入博闻:

# 注册博闻为 MCP Server
curl -X POST http://localhost:8000/api/v1/tools/mcp-servers \
  -H "Content-Type: application/json" \
  -d '{
    "name": "bowen-web-search",
    "endpoint_url": "http://localhost:8080",
    "status": "enabled"
  }'

注册后灵台会拉取工具清单,Agent 即可在对话中直接调用 web_search 工具。


搜索模式对比

模式 延迟 召回 使用场景
first(默认) 低(首个成功即返回) 单 provider 快速查天气、新闻、百科等简单查询
merge 中(等最慢 provider) 高(多源合并去重) 研究、对比多个来源、需要全面 coverage

技术栈

类别 选型
语言 Go 1.22+
Web 标准库 net/http
日志 标准库 log/slog + 自定义彩色 Handler
配置 gopkg.in/yaml.v3 + 环境变量
内存缓存 hashicorp/golang-lru/v2
Redis redis/go-redis/v9(可选)
监控 prometheus/client_golang
热重载 fsnotify
测试 标准库 testing
容器化 Docker 多阶段构建