搜索工具服务器

基于FastMCP的服务器,提供带有可选Keycloak认证的搜索工具,适用于需要安全访问的AI代理集成场景。

  • by anggaadypratama
  • Python
  • 本地部署
  • 更新于
在 GitHub 查看 anggaadypratama/mcp-search

使用说明

带Keycloak身份验证的MCP服务器

基于FastMCP的服务器,提供具有可选Keycloak身份验证的搜索工具。

特性

  • 搜索工具:由Tavily API提供支持,用于网络搜索、提取和爬网
  • 密钥斗篷身份验证:可选的基于JWT的身份验证,用于安全访问
  • MCP协议:用于AI代理集成的模型上下文协议

安装

先决条件

  • Python 3.14+
  • Keycloak服务器(可选,仅在使用身份验证时)

设置

  1. 克隆或导航到项目目录:

    cd /Users/anggaadypratama/Development/MCP
    
  2. 安装依赖项:

    uv sync
    

    或者使用pip:

    pip install -e .
    
  3. 配置环境变量:

    cp .env.example .env
    

    编辑 .env 根据您的配置:

    # Required: Tavily API Key
    TAVILY_API_KEY=your_tavily_api_key
    
    # Optional: Enable Keycloak Authentication
    AUTH_ENABLED=true
    KEYCLOAK_SERVER_URL=http://localhost:8080
    KEYCLOAK_REALM=your_realm
    KEYCLOAK_CLIENT_ID=your_client_id
    KEYCLOAK_CLIENT_SECRET=your_client_secret
    

钥匙斗篷设置

选项1:使用现有的Keycloak服务器

如果您已经拥有Keycloak服务器:

  1. 创建新领域 (或使用现有)

  2. 创建客户端:

    • 客户端ID:选择一个名称(例如。, mcp-server)
    • 客户端协议: openid-connect
    • 访问类型: confidential (如果使用客户端机密)或 public
    • 有效的重定向URI:根据需要配置
    • 保存并记录客户机密(如果是机密)
  3. 更新 .env 带有Keycloak细节

选项2:使用Docker在本地运行Keycloak

# Run Keycloak in development mode
docker run -d \
  --name keycloak \
  -p 8080:8080 \
  -e KEYCLOAK_ADMIN=admin \
  -e KEYCLOAK_ADMIN_PASSWORD=admin \
  quay.io/keycloak/keycloak:latest \
  start-dev

# Access Keycloak admin console at http://localhost:8080
# Login: admin / admin

然后按照选项1中的步骤创建领域和客户端。

运行服务器

无身份验证(开发)

# Make sure AUTH_ENABLED=false in .env
python main.py

服务器将于启动 http://localhost:8000 所有端点均可公开访问。

带身份验证(生产)

# Make sure AUTH_ENABLED=true in .env
python main.py

服务器将在启用身份验证的情况下启动。所有请求都必须包含有效的Keycloak JWT令牌。

用法

获取访问令牌

要使用经过身份验证的API,首先从Keycapture获取令牌:

# For client credentials flow (machine-to-machine)
curl -X POST "http://localhost:8080/realms/YOUR_REALM/protocol/openid-connect/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "client_id=YOUR_CLIENT_ID" \
  -d "client_secret=YOUR_CLIENT_SECRET" \
  -d "grant_type=client_credentials"

这将返回一个JSON响应,其中包含 access_token:

{
  "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
  "expires_in": 300,
  "token_type": "Bearer"
}

发出经过身份验证的请求

使用搜索工具

无身份验证:

curl -X POST http://localhost:8000/tools/call \
  -H "Content-Type: application/json" \
  -d '{
    "name": "search__search",
    "arguments": {
      "query": "FastMCP documentation"
    }
  }'

使用身份验证:

curl -X POST http://localhost:8000/tools/call \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -d '{
    "name": "search__search",
    "arguments": {
      "query": "FastMCP documentation"
    }
  }'

使用提取工具

curl -X POST http://localhost:8000/tools/call \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -d '{
    "name": "search__extract",
    "arguments": {
      "urls": ["https://example.com", "https://example.org"]
    }
  }'

使用爬行工具

curl -X POST http://localhost:8000/tools/call \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -d '{
    "name": "search__crawl",
    "arguments": {
      "url": "https://example.com",
      "instructions": "Extract all article titles"
    }
  }'

可用工具

搜索

使用Tavily API进行网络搜索。

论据:

  • query (string):搜索查询

搜索_提取

从多个URL中提取内容。

论据:

  • urls (字符串数组):从中提取内容的URL列表

搜索_抓取

使用可选说明抓取网站。

论据:

  • url (string):要抓取的URL
  • instructions (字符串,可选):爬行说明

身份验证详细信息

启用身份验证时(AUTH_ENABLED=true):

  • 所有MCP工具端点都需要有效的JWT令牌
  • 令牌必须包含在 Authorization 标题为 Bearer TOKEN
  • 令牌根据Keycloak的公钥进行验证
  • 令牌过期已强制执行
  • 提取并记录用户信息

令牌验证

中间件执行以下验证:

  • ✓ 使用Keycloak的RSA公钥进行签名验证
  • ✓ 令牌过期检查
  • ✓ 令牌未经过时间验证
  • ✓ 受众验证(可选)

访问用户信息

在您的工具实现中,您可以访问经过身份验证的用户信息:

from fastmcp import FastMCP

@search_mcp.tool()
def my_tool(request) -> dict:
    # Access user info if authentication is enabled
    if hasattr(request, 'state') and hasattr(request.state, 'user'):
        user_info = request.state.user
        username = user_info['username']
        roles = user_info['roles']

    return {"result": "success"}

故障排除

常见问题

问题:“缺少必需的Keycloak配置”

  • 解决方案:确保在以下情况下设置了所有Keycloak环境变量 AUTH_ENABLED=true

问题:“令牌已过期”

  • 解决方案:从Keycloak请求新的访问令牌

问题:“无效令牌”

  • 解决方案:验证令牌是否正确复制,Keycloak配置是否匹配

问题:“Keycloak连接被拒绝”

  • 解决方案:确保Keycloak服务器正在运行,并且可以在配置的URL上访问

问题:身份验证有效,但工具失败

  • 解决方案:检查Tavily API密钥是否正确配置

调试日志记录

服务器记录身份验证事件:

  • 令牌验证尝试
  • 身份验证失败
  • 用户信息提取
  • 公钥刷新事件

检查控制台输出以了解详细的错误消息。

发展

项目结构

.
├── main.py                 # Application entry point
├── config/
│   └── __init__.py        # Configuration management
├── middleware/
│   ├── __init__.py
│   └── keycloak_auth.py   # Authentication middleware
├── tools/
│   ├── search_tool.py     # Tavily search tools
│   └── telegram_tool.py   # Telegram tools (commented)
├── .env                   # Environment variables (not in git)
├── .env.example          # Environment template
└── pyproject.toml        # Python dependencies

添加新工具

当向MCP服务器注册时,工具会自动继承身份验证中间件。

安全考虑

  • 永不承诺 .env 到版本控制
  • 使用 强大的客户秘密 生产中
  • 启用 超文本传输安全协议 用于生产部署
  • 定期 轮换客户端机密
  • 配置适当 令牌过期时间 在Keycloak
  • 实施 基于角色的访问控制 如有需要

许可证

[您的许可证在这里]

支持

对于问题或疑问:

  • 检查上面的故障排除部分
  • 查看Keycloak文档:https://www.keycloak.org/docs/latest/
  • 查阅FastMCP文档:https://github.com/jlowin/fastmcp