Skip to main content
Glama
Eivs

MCP WebSearch

by Eivs

MCP WebSearch

基于 Model Context Protocol (MCP) 的 Web 搜索服务,使用最新的 MCP Streamable HTTP 协议。

功能特性

  • MCP Streamable HTTP 协议: 符合最新 MCP 规范

  • 单一端点设计: /mcp 支持 POST/GET/DELETE

  • Session 管理: 使用 Mcp-Session-Id header

  • 实时消息推送: 支持 streaming 响应

  • DuckDuckGo 搜索: 集成 DuckDuckGo 搜索引擎

  • 身份验证: 基于 API Token 的身份验证

  • 速率限制: 防止 API 滥用

  • 可扩展架构: 预留其他搜索引擎集成接口

  • TypeScript: 完整的类型安全

  • Fastify: 高性能 Web 框架

  • Biome: 现代化的代码格式化和 Lint 工具

技术栈

  • Web 框架: Fastify 5.x

  • MCP SDK: @modelcontextprotocol/sdk 1.21.0

  • MCP 协议: Streamable HTTP (2025-03-26 规范)

  • 搜索引擎: DuckDuckGo (HTML API)

  • 开发工具: TypeScript, Biome, tsx

  • 认证: API Token (Bearer / X-API-Key)

  • 速率限制: @fastify/rate-limit

MCP Streamable HTTP 协议说明

本服务实现了最新的 MCP Streamable HTTP transport 规范 (2025-03-26),取代了旧的 HTTP with separate endpoints transport。

关键特性

  1. 单一端点: /mcp (POST/GET/DELETE)

  2. Session 管理: 使用 Mcp-Session-Id header

  3. 初始化: POST 请求自动创建 session

  4. Streaming 连接: GET 请求建立 streaming 连接接收服务器推送

  5. Session 终止: DELETE 请求关闭 session

端点说明

方法

端点

用途

需要认证

需要 Session ID

GET

/health

健康检查

POST

/mcp

发送 JSON-RPC 消息

首次请求不需要

GET

/mcp

建立 streaming 连接

DELETE

/mcp

终止 session

快速开始

1. 安装依赖

npm install

2. 配置环境变量

复制 .env.example.env:

cp .env.example .env

编辑 .env 文件,设置你的 API Token:

PORT=3000
NODE_ENV=production

# 设置一个或多个 API Token(逗号分隔)
API_TOKENS=your-secret-token-1,your-secret-token-2

# 速率限制配置
RATE_LIMIT_WINDOW_MS=900000    # 15分钟
RATE_LIMIT_MAX_REQUESTS=100    # 每15分钟最多100个请求

# 搜索配置
SEARCH_TIMEOUT_MS=10000        # 搜索超时时间(毫秒)
MAX_SEARCH_RESULTS=10          # 默认最大搜索结果数

3. 启动服务

开发模式 (支持热重载):

npm run dev

生产模式:

npm run build
npm start

服务将在 http://localhost:3000 启动。

API 使用

健康检查

curl http://localhost:3000/health

响应:

{
  "status": "ok",
  "timestamp": "2025-01-07T10:00:00.000Z",
  "service": "mcp-websearch"
}

MCP HTTP Streamable 协议

本服务完整实现 MCP Streamable HTTP 协议:

工作流程:

  1. 初始化 (POST /mcp)

    curl -X POST http://localhost:3000/mcp \
      -H "Authorization: Bearer your-token" \
      -H "Content-Type: application/json" \
      -d '{
        "jsonrpc": "2.0",
        "id": 1,
        "method": "initialize",
        "params": {...}
      }'

    响应会包含 Mcp-Session-Id header

  2. 建立 Streaming 连接 (GET /mcp)

    curl -N -H "Authorization: Bearer your-token" \
         -H "Mcp-Session-Id: <session-id>" \
         http://localhost:3000/mcp
  3. 发送后续请求 (POST /mcp)

    curl -X POST http://localhost:3000/mcp \
      -H "Authorization: Bearer your-token" \
      -H "Mcp-Session-Id: <session-id>" \
      -H "Content-Type: application/json" \
      -d '{
        "jsonrpc": "2.0",
        "id": 2,
        "method": "tools/call",
        "params": {...}
      }'
  4. 终止 Session (DELETE /mcp)

    curl -X DELETE http://localhost:3000/mcp \
      -H "Authorization: Bearer your-token" \
      -H "Mcp-Session-Id: <session-id>"

使用示例

建立 Streaming 连接:

curl -N -H "Authorization: Bearer your-secret-token-1" \
     -H "Mcp-Session-Id: your-session-id" \
     http://localhost:3000/mcp

或使用 X-API-Key header:

curl -N -H "X-API-Key: your-secret-token-1" \
     -H "Mcp-Session-Id: your-session-id" \
     http://localhost:3000/mcp

Web 搜索工具

MCP 工具名称: web_search

参数:

  • query (必需): 搜索查询字符串

  • max_results (可选): 返回的最大结果数,默认 10

响应格式:

{
  "query": "search term",
  "results": [
    {
      "title": "Result Title",
      "url": "https://example.com",
      "snippet": "Result description...",
      "source": "duckduckgo"
    }
  ],
  "totalResults": 10,
  "engine": "duckduckgo",
  "timestamp": "2025-01-07T10:00:00.000Z"
}

在 Claude Desktop 中使用

在 Claude Desktop 的 MCP 配置中添加:

{
  "mcpServers": {
    "websearch": {
      "url": "http://your-server:3000/mcp",
      "headers": {
        "Authorization": "Bearer your-secret-token-1"
      }
    }
  }
}

或使用 X-API-Key:

{
  "mcpServers": {
    "websearch": {
      "url": "http://your-server:3000/mcp",
      "headers": {
        "X-API-Key": "your-secret-token-1"
      }
    }
  }
}

注意: 使用的是单一的 /mcp 端点,支持 POST/GET/DELETE 方法。

开发

开发服务器

npm run dev

代码格式化和 Lint

# 格式化代码
npm run format

# 检查代码质量
npm run lint

# 自动修复问题
npm run lint:fix

构建

npm run build

Nginx 反向代理配置

创建 Nginx 配置文件:

server {
    listen 80;
    server_name your-domain.com;

    location / {
        proxy_pass http://localhost:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;

        # Streamable HTTP 支持
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_buffering off;
        proxy_cache off;
        proxy_read_timeout 86400s;
    }
}

使用 Docker 部署

构建和运行:

docker build -t mcp-websearch .
docker run -d \
  -p 3000:3000 \
  -e API_TOKENS=your-token \
  --name mcp-websearch \
  mcp-websearch

或使用 docker-compose.yml:

version: '3.8'

services:
  websearch:
    build: .
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=production
      - API_TOKENS=${API_TOKENS}
      - PORT=3000
    restart: unless-stopped

启动:

docker-compose up -d

扩展其他搜索引擎

项目架构已预留扩展接口,添加新搜索引擎步骤:

  1. src/search/providers/ 创建新的提供商文件

  2. 继承 SearchProvider 基类

  3. 实现 search() 方法

  4. 在 MCP 服务器中注册新工具

示例:

// src/search/providers/bing.ts
import { SearchProvider } from './base';
import type { SearchResult, SearchOptions } from '../types';

export class BingProvider extends SearchProvider {
  readonly name = 'bing';

  async search(query: string, options?: SearchOptions): Promise<SearchResult[]> {
    // 实现 Bing 搜索逻辑
    // ...
  }
}

项目结构

websearch/
├── src/
│   ├── server.ts              # Fastify 服务器入口
│   ├── config/
│   │   └── index.ts          # 配置管理
│   ├── mcp/
│   │   └── server.ts         # MCP 服务器实现
│   ├── search/
│   │   ├── types.ts          # 类型定义
│   │   └── providers/
│   │       ├── base.ts       # 搜索引擎基类
│   │       └── duckduckgo.ts # DuckDuckGo 实现
│   ├── auth/
│   │   ├── middleware.ts     # Fastify 认证钩子
│   │   └── rateLimiter.ts    # 速率限制配置
│   └── utils/
│       ├── logger.ts         # 日志工具
│       └── errors.ts         # 错误处理
├── dist/                      # 编译输出
├── biome.json                 # Biome 配置
├── .env                       # 环境变量(不提交)
├── .env.example              # 环境变量模板
├── package.json
├── tsconfig.json
└── README.md

故障排查

问题: 搜索结果为空

  • 检查网络连接

  • 检查 DuckDuckGo 是否可访问

  • 增加 SEARCH_TIMEOUT_MS

问题: 认证失败

  • 确认 .env 文件中 API_TOKENS 配置正确

  • 确认请求 header 格式正确

  • 检查 token 中是否有多余的空格

问题: 速率限制触发

  • 调整 RATE_LIMIT_MAX_REQUESTSRATE_LIMIT_WINDOW_MS

  • 检查是否有异常请求

MCP 协议说明

本服务实现了 MCP Streamable HTTP transport 规范 (2025-03-26):

  1. 初始化连接: 客户端向 POST /mcp 发送 initialize 请求

  2. Session 创建: 服务器返回 Mcp-Session-Id header

  3. 建立 Streaming: 客户端用 session ID 向 GET /mcp 建立 streaming 连接

  4. 消息交换: 客户端用 session ID 向 POST /mcp 发送请求,通过 streaming 连接接收响应

  5. 连接保持: Streaming 连接保持打开状态,支持双向通信

  6. Session 终止: 客户端向 DELETE /mcp 发送请求关闭 session

端点说明

  • GET /health - 健康检查(无需认证)

  • POST /mcp - 发送 MCP 请求(首次不需要 session ID)

  • GET /mcp - 建立 streaming 连接(需要 session ID)

  • DELETE /mcp - 终止 session(需要 session ID)

Session 管理

  • Stateful 模式: 服务器自动生成并管理 session ID

  • Session Header: 使用 Mcp-Session-Id header

  • Session 验证: 非初始化请求必须提供有效的 session ID

  • Session 清理: DELETE 请求或连接关闭时自动清理

License

MIT

贡献

欢迎提交 Issue 和 Pull Request!

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Eivs/mcp-websearch'

If you have feedback or need assistance with the MCP directory API, please join our Discord server