内容
# grok-mcp
[简体中文](./README_CN.md)
`grok-mcp` 是一个仅支持 HTTP 的 [模型上下文协议(MCP)](https://modelcontextprotocol.io/) 服务器,提供由 Grok 驱动的实时网络搜索、X/Twitter 搜索和模型发现功能,供 MCP 客户端使用。
它**不**直接调用官方的 xAI API,而是连接到现有的 [CLIProxyAPI(CPA)](https://github.com/router-for-me/CLIProxyAPI) 部署。CPA 拥有上游 xAI 身份验证,而 `grok-mcp` 提供 MCP 传输、客户端 API 密钥、配额、使用情况跟踪和管理面板。
> [!IMPORTANT]
> 该项目仅支持 **可流式传输的 HTTP**。它不提供_stdio_传输或内置的 TLS 终止。
- `grok-mcp` 必须作为独立的 HTTP 服务运行,MCP 客户端连接到 `http://<host>:<port>/mcp`。
- 它不能配置为_stdio_服务器,MCP 客户端通过标准输入和输出启动和通信。
- 服务监听纯 HTTP,不加载 HTTPS 证书或私钥,也不执行 TLS 握手。
- 对于面向互联网的部署,请在 `grok-mcp` 前面放置一个受信任的反向代理,如 Nginx、Caddy、Traefik、Kubernetes Ingress 或云负载均衡器。代理应公开 HTTPS 并将请求转发到 `grok-mcp`,使用内部 HTTP。
典型的生产请求路径如下:
```text
MCP 客户端 -- HTTPS --> 反向代理 / 负载均衡器 -- HTTP --> grok-mcp /mcp
(TLS 在此处终止)
```
## 功能
- `/mcp` 处的可流式传输 HTTP MCP 端点
- 三个只读 MCP 工具:
- `grok_web_search`
- `grok_x_search`
- `grok_list_models`
- 可选的 CPA 上游协议:OpenAI 响应、OpenAI 聊天补全或Anthropic 消息
- 上游搜索轮次的 MCP 进度通知
- 每个用户的客户端 API 密钥,带有启用/禁用控件
- 基于层级的 RPM 和每月成功调用配额
- `/mcp` 和面板身份验证的 `valid-forwarded-IP-triggered` 保护
- 用于用户、密钥、层级、使用情况、邀请代码和服务器设置的 SQLite 持久性
- 带有无单独前端构建步骤的嵌入式管理面板
- 上游设置、代理设置、注册模式和调试模式的运行时更新
- 带有非根运行时镜像的 Docker Compose 部署
## 架构
```text
可流式传输的 HTTP MCP 客户端
|
| POST /mcp
| Authorization: Bearer <MCP 客户端 API 密钥>
v
grok-mcp
| |
| +---- /panel/ 和 /panel/v1/* ---- 管理员和用户
|
+---------- SQLite -------------------- 用户、密钥、层级、使用情况、设置
|
| POST /v1/responses、/v1/chat/completions 或 /v1/messages
| GET /v1/models
| Authorization: Bearer <CPA API 密钥>
v
CLIProxyAPI
|
v
xAI / Grok
```
### 凭证不可互换
| 凭证 | 使用于 | 目的 |
|---|---|---|
| CPA API 密钥 | `grok-mcp` -> CPA | 验证所选的上游搜索端点和 `/v1/models` 请求。 |
| MCP 客户端 API 密钥 | MCP 客户端 -> `/mcp` | 在面板中创建和复制按需。数据库存储身份验证哈希和可恢复的密文,加密后使用从 `GROK_JWT_SECRET` 派生的密钥。 |
| 面板 JWT | 浏览器/API 客户端 -> `/panel/v1` | 由面板登录返回。不能验证 `/mcp`。 |
## 要求
- Linux 是目前记录的本地运行时目标
- 本地构建需要 Go 1.25.0 或更高版本
- 需要一个可访问的 CPA 部署,包含 `/v1/models` 和至少一个兼容的搜索端点:`/v1/responses`、`/v1/chat/completions` 或 `/v1/messages`
- Docker 和 Docker Compose 用于容器工作流(如果需要)
- 支持可流式传输的 HTTP 和自定义 Bearer 头部的 MCP 客户端
应用程序使用纯 Go SQLite (`modernc.org/sqlite`),不需要 CGO。
## 快速开始
### 1. 构建
```bash
go build -o grok-mcp ./cmd/grok-mcp
```
可选地在构建时注入版本号:
```bash
go build \
-ldflags "-X github.com/grok-mcp/internal/version.Version=1.2.3" \
-o grok-mcp ./cmd/grok-mcp
./grok-mcp -version
```
### 2. 配置
```bash
cp .env.example .env
mkdir -p data
${EDITOR:-vi} .env
```
至少需要一个新的安装:
```dotenv
CPA_API_KEY=用您的 CPA API 密钥替换
GROK_JWT_SECRET=用至少 32 个字节的强随机密钥替换
```
加载环境并启动服务器:
```bash
set -a
source .env
set +a
./grok-mcp
```
默认端点:
| 服务 | URL |
|---|---|
| MCP | `http://127.0.0.1:8080/mcp` |
| 管理面板 | `http://127.0.0.1:8080/panel/` |
| 面板 REST API | `http://127.0.0.1:8080/panel/v1/` |
### 3. 登录并创建 MCP 客户端密钥
当没有启用的管理员时,服务器会引导一个 `admin` 账户,并将其一次性随机密码写入启动日志。登录,尽快轮换凭证,并创建 MCP 客户端 API 密钥。
```bash
login_token="$(curl -sS -X POST "http://127.0.0.1:8080/panel/v1/auth/login" \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"password-from-startup-log"}' | jq -r '.token')"
curl -sS -X POST "http://127.0.0.1:8080/panel/v1/keys" \
-H "Authorization: Bearer ${login_token}" \
-H "Content-Type: application/json" \
-d '{"name":"local-client"}'
```
响应中的 `api_key` 仅返回一次。请安全存储。
### 4. 连接 Claude Code
Claude Code 是一个带有存储库记录的设置示例的客户端:
```bash
export GROK_MCP_API_KEY="grok_xxx"
claude mcp add --transport http grok-mcp http://127.0.0.1:8080/mcp \
--header "Authorization: Bearer ${GROK_MCP_API_KEY}"
```
项目级 `.mcp.json` 可以使用环境扩展:
```json
{
"mcpServers": {
"grok-mcp": {
"type": "http",
"url": "http://127.0.0.1:8080/mcp",
"headers": {
"Authorization": "Bearer ${GROK_MCP_API_KEY}"
}
}
}
}
```
请勿提交实际的 API 密钥。其他 MCP 客户端可以连接,如果它们支持带有自定义 `Authorization: Bearer ...` 头的可流式传输 HTTP,但此存储库中未记录的客户端特定配置应被视为未经验证。
## MCP 工具
所有工具都是只读的。搜索失败作为 MCP 工具结果返回,带有 `isError=true`,因此正常的工具错误不会终止 MCP 会话。
### `grok_web_search`
通过 Grok 执行实时公共网络搜索。
| 参数 | 类型 | 必需 | 描述 |
|---|---|:---:|---|
| `query` | 字符串 | 是 | 非空搜索请求。 |
| `model` | 字符串 | 否 | 覆盖配置的默认值;值必须包含 `grok`。 |
| `allowed_domains` | 字符串[] | 否 | 仅搜索这些域名;最多 5 个。 |
| `excluded_domains` | 字符串[] | 否 | 排除这些域名;最多 5 个。 |
| `enable_image_understanding` | 布尔值 | 否 | 为网络搜索启用图像理解。 |
| `enable_image_search` | 布尔值 | 否 | 启用图像搜索结果。 |
`allowed_domains` 和 `excluded_domains` 互相排斥。条目必须是纯域名,而不是 URL。通配符、IP 字面量、端口、路径、`localhost` 和 `.local` 域名被拒绝。
### `grok_x_search`
通过 Grok 搜索 X/Twitter 上的实时帖子。
| 参数 | 类型 | 必需 | 描述 |
|---|---|:---:|---|
| `query` | 字符串 | 是 | 非空搜索请求。 |
| `model` | 字符串 | 否 | 覆盖配置的默认值;值必须包含 `grok`。 |
域名过滤器和图像相关参数仅适用于 `grok_web_search`。
线路级映射取决于所选的上游协议。响应使用 CPA 的原生 `x_search` 工具,聊天补全使用 `x` 搜索源,Anthropic 消息使用支持的服务器端网络搜索工具,限制在 `x.com` 上。Anthropic 映射是必要的,因为自定义 Anthropic `x_search` 声明被 CPA 视为客户端执行的工具调用,它本身不产生最终的搜索答案。
### `grok_list_models`
不接受参数。它读取 CPA 的 `GET /v1/models`,修剪并 deduplicate ID,保留包含 `grok` 的 ID,并排除包含 `imagine` 或 `video` 的 ID。
### 搜索结果形状
```json
{
"answer": "Grok 合成的答案",
"citations": [
"https://example.com/source"
],
"sources": [
{
"url": "https://example.com/source",
"title": "示例来源"
}
],
"usage": {
"input_tokens": 120,
"output_tokens": 340,
"total_tokens": 460,
"reasoning_tokens": 0
}
}
```
当上游响应不提供时,`citations`、`sources` 和 `usage` 可能会被省略。JSON-RPC 批处理请求被故意拒绝,因为批处理可能会绕过每次调用的配额预留和使用情况核算。
## 配置
### 启动环境
| 变量 | 默认值 | 描述 |
|---|---|---|
| `GROK_JWT_SECRET` | 无 | 必需的 HS256 面板签名密钥;必须至少 32 个字节。始终通过环境提供。 |
| `CPA_API_KEY` | 无 | 新数据库所需。现有的持久化服务器设置可能在后续启动时提供它。 |
| `CPA_BASE_URL` | `http://127.0.0.1:8317` | CPA 根 URL。 |
| `GROK_UPSTREAM_PROTOCOL` | `responses` | 搜索协议:`responses`、`chat_completions` 或 `anthropic_messages`。 |
| `GROK_MODEL` | `grok-4.3` | 默认 Grok 模型。 |
| `GROK_HTTP_TIMEOUT` | `120` | 上游超时(秒)。 |
| `GROK_HTTP_ADDR` | `:8080` | HTTP 监听地址。需要重启才能更改。 |
| `GROK_DB_PATH` | `./grok-mcp.db` | SQLite 数据库路径。需要重启才能更改。 |
| `GROK_MCP_IP_RPM` | `300` | 源 IP RPM 在 MCP API 密钥身份验证之前应用,仅当 `X-Real-IP` 或 `X-Forwarded-For` 包含有效 IP 时。 |
| `GROK_MCP_DEBUG` | `false` | 接受 `1`、`true` 或 `yes`。可能在用法记录中捕获调试请求/响应上下文。 |
| `GROK_PROXY_URL` | 空 | 显式上游 HTTP(S) 代理 URL。 |
| `GROK_PROXY_ENABLED` | 推断 | 显式代理开关。当未设置时,非空的 `GROK_PROXY_URL` 启用它。 |
| `HTTP_PROXY`、`HTTPS_PROXY`、`NO_PROXY` | Go 默认值 | 标准传输在未启用显式代理时使用。 |
### 转发客户端 IP 保护
仅当可以从 `X-Real-IP` 或 `X-Forwarded-For` 解析出有效 IP 时,应用程序级 IP 保护才启用。相同的策略用于:
- `/mcp` 的令牌桶在 API 密钥身份验证之前运行;
- 面板登录和注册端点令牌桶;
- 面板用户名/IP 登录失败锁定。
请求行为:
| 请求状态 | IP 保护行为 |
|---|---|
| 两个头部都不存在、为空或不包含有效 IP | 应用程序级 IP 速率限制和登录 IP 锁定将被跳过。用户层级的 RPM 和配额检查在成功的 MCP 身份验证后仍将应用。 |
| 存在有效的转发客户端 IP 头部 | 如果有效,则使用 `X-Real-IP`;否则,使用 `X-Forwarded-For` 中的第一个有效 IP。不需要受信任的代理允许列表。 |
> [!IMPORTANT]
> 应用程序直接信任 `X-Real-IP` 和 `X-Forwarded-For`。它必须仅可通过受信任的反向代理访问,该代理始终注入有效的客户端 IP 并首先删除客户端提供的数值。如果客户端可以直接访问 `grok-mcp`,它们可以省略或使头部无效以跳过 IP 保护,或者伪造它们以选择任意速率限制桶。请为 `/mcp`、`/panel/v1/auth/login` 和 `/panel/v1/auth/register` 启用代理层速率限制。
代理必须覆盖 `X-Real-IP` 并从连接源重建 `X-Forwarded-For`。由于应用程序选择 `X-Forwarded-For` 的第一个有效条目,因此请勿保留不受信任的客户端提供的链。
Nginx 转发配置示例:
```nginx
location / {
proxy_pass http://grok-mcp:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
}
```
### 持久性和实时更新
启动时,首先加载环境变量。如果 SQLite 已经包含服务器设置,则持久化的上游设置将优先。管理员可以从 **服务器设置** 更新以下值而无需重启:
- CPA 基本 URL 和 API 密钥
- 上游搜索协议
- 默认模型和超时
- 显式代理 URL 和启用状态
- 注册模式
- 调试模式
监听地址、数据库路径、JWT 密钥和源 IP RPM 仍是仅限启动的设置。
> [!WARNING]
> CPA API 密钥保存在 SQLite 中。保护并备份数据库作为敏感数据。面板仅返回此密钥的掩码预览。
### 上游协议映射
| 设置 | 端点 | 搜索映射 |
|---|---|---|
| `responses` | `POST /v1/responses` | CPA 响应内置项 (`web_search` / `x_search`);这保持向后兼容,默认提供搜索轮次进度事件。 |
| `chat_completions` | `POST /v1/chat/completions` | xAI 兼容的 `search_parameters`,带有 `web` 或 `x` 源以及 Chat Completions 块。短状态响应(例如“searching...”)将继续有限的后续请求,以便 MCP 调用者接收最终答案或显式错误。 |
| `anthropic_messages` | `POST /v1/messages` | Anthropic 服务器端 `web_search_20250305`,带有 Messages SSE 事件。网络搜索保留配置的域名过滤器;X 搜索使用相同服务器工具,限制在 `x.com` 上,并添加指令返回直接 X 帖子 URL。 |
协议支持最终取决于所选的 CPA 版本、提供者和模型功能。响应是最安全的兼容性选择,用于现有的 Grok/CPA 部署。图像搜索选项是响应特定;其他协议忽略它们,因为没有等效的线路选项存在。
协议可以公开不同的元数据,即使它们的答案文本是等效的:- 响应通常提供最丰富的搜索轮次进度和结构化引用数据。
- Chat Completions 仅在 CPA 包括兼容的非标准搜索事件时发出进度。标准聊天块可能仅包含最终文本和使用情况。
- Anthropic 消息可能在 CPA 提供商翻译的答案文本中包含源 URL,而不发出结构化引用块。
- `usage` 在上游响应包含令牌计数时会在所有协议中规范化。
## 用户、注册、层级和配额
注册可以更改为运行时:
| 模式 | 行为 |
|---|---|
| `free` | 允许公共自注册。 |
| `invite` | 需要有效的启用、非耗尽的邀请代码。 |
| `disabled` | 禁止公共注册。 |
管理员可以创建、禁用和删除邀请代码并设置他们的注册限制。
每个用户都属于一个层级。用户的所有 API 密钥共享该层级的 RPM 和每月成功调用额度。只有实际的 `tools/call` 请求会被计量;初始化、ping 和工具列表请求不会被计量;初始化、ping 和工具列表请求不会被计量。
默认层级为新数据库:
| 层级 | RPM | 每月成功调用次数 |
|---|---:|---:|
| `tier0` | 10 | 800 |
| `tier1` | 20 | 4,000 |
| `tier2` | 40 | 16,000 |
| `tier3` | 60 | 40,000 |
| `tier4` | 120 | 160,000 |
| `tier5` | 300 | 800,000 |
| `tier6` | 无限制 | 无限制 |
成功的调用周期使用 UTC 日历月份。调用会在执行工具之前预留配额;失败的调用会回滚预留。层级值可以在面板中自定义。
`/mcp` 的中间件顺序如下所示。`IP RPM` 步骤在没有 IP 头的情况下直接跳过:
```text
最大请求体 -> IP RPM -> API 密钥 -> 提取工具名称 -> 用户 RPM -> 配额 -> 用量 -> MCP 处理器
```
## 管理 API 概述
嵌入式面板位于 `/panel/`。其 API 在 `/panel/v1` 下。
公共身份验证路由:
```text
GET /panel/v1/auth/registration-settings
POST /panel/v1/auth/register
POST /panel/v1/auth/login
```
身份验证用户路由涵盖个人资料信息、API 密钥管理和用量:
```text
GET /panel/v1/me
GET /panel/v1/keys
POST /panel/v1/keys
POST /panel/v1/keys/{id}/reveal
PATCH /panel/v1/keys/{id}
DELETE /panel/v1/keys/{id}
GET /panel/v1/keys/{id}/usage
GET /panel/v1/usage
```
管理员路由在 `/panel/v1/admin/` 下管理用户、层级、服务器设置、邀请代码、模型和用量。所有非公共面板请求需要:
```text
Authorization: Bearer <面板 JWT>
```
## Docker Compose
```bash
cp .env.example .env
${EDITOR:-vi} .env
docker compose up -d --build
```
如果 CPA 直接在 Docker 主机上运行,请使用:
```dotenv
CPA_BASE_URL=http://host.docker.internal:8317
```
提供的容器:
- 使用 `CGO_ENABLED=0` 构建
- 作为非 root `app` 用户运行
- 监听端口 8080
- 将 SQLite 数据存储在 `/app/data`
- 在 Docker Compose 中使用 `grok-mcp-data` 命名卷
- 健康检查 `/panel/`
Docker Compose 文件不会转发每个可选的外部代理变量。如果容器需要 `GROK_PROXY_URL`、`GROK_PROXY_ENABLED` 或标准代理变量,请扩展 `environment`。
## 生产和安全说明
- 在公开服务之前,请将其置于 HTTPS 反向代理后面。服务器不提供 TLS。
- 永远不要公开面板 JWT、MCP 客户端 API 密钥、CPA 密钥、邀请码或实际的 `.env` 文件。
- 立即轮换引导管理员凭证。
- 限制对 SQLite 文件的访问,并将其包含在安全备份中。
- 确保反向代理覆盖 `X-Real-IP`、重建 `X-Forwarded-For`,并且始终添加其中一个;否则,可以绕过应用级 IP 保护。
- 阻止所有客户端直接访问应用程序端口,因为转发客户端 IP 头部在没有应用级代理允许列表的情况下是受信任的。
- 为 `/mcp`、面板登录和面板注册添加反向代理速率限制。
- 除非在故障排除时,否则保持调试模式禁用。调试上下文可能会保留请求或响应内容,即使身份验证头部被删除。
- MCP 客户端 API 密钥仅显示一次,并存储为哈希;丢失明文密钥需要创建替换密钥。
## 开发和测试
运行默认测试套件:
```bash
go test ./...
```
验证可执行文件构建:
```bash
go build ./cmd/grok-mcp
```
实时 CPA/xAI 集成测试是可选的:
```bash
export GROK_INTEGRATION_TEST="1"
export CPA_API_KEY="用您的 CPA API 密钥替换"
export CPA_BASE_URL="http://127.0.0.1:8317"
go test ./test/grok -run TestIntegrationSearchLiveCPA -v
```
面板前端是嵌入的静态 HTML、CSS 和 JavaScript;不需要 Node.js 构建。存储库目前没有 Makefile、任务运行器或已发布的 CI/发布管道。在贡献时,请使用标准 Go 工具,如 `gofmt` 和 `go vet`。
### 项目布局
```text
cmd/grok-mcp/ 进程入口点和版本标志
internal/app/ 应用程序组成、引导、HTTP 服务器、关闭
internal/auth/ MCP API 密钥身份验证和面板 JWT
internal/config/ 环境加载和持久设置映射
internal/grok/ CPA 请求、SSE 解析、模型列表
internal/mcp/ MCP 服务器指令和工具注册
internal/panel/ 面板 REST API
internal/panelui/ 嵌入式管理前端
internal/quota/ 每月成功调用预留
internal/ratelimit/ 源 IP 和每用户速率限制
internal/store/ SQLite 架构和持久性
internal/usage/ 工具调用使用情况和可选调试捕获
test/http/ HTTP 集成和保护测试
test/grok/ 可选的实时上游集成测试
```
## 故障排除
| 症状 | 检查 |
|---|---|
| `GROK_JWT_SECRET is required` | 在服务环境中设置至少 32 字节的密钥。 |
| 新数据库启动失败 | 设置有效的 `CPA_API_KEY` 并验证数据库目录可写。 |
| MCP 返回 `401` 或 `403` | 使用 MCP 客户端 API 密钥,而不是面板 JWT;验证密钥和用户是否启用。 |
| MCP 返回 `429` | 检查源 IP RPM、用户层 RPM 和每月成功调用额度。 |
| 上游超时或 HTTP 错误 | 验证 CPA URL、CPA 密钥、代理设置和 CPA 健康状态。 |
| Docker 无法访问主机 CPA | 在提供的 Compose 配置中使用 `http://host.docker.internal:<port>`。 |
| 模型列表为空 | 确认 CPA 返回 Grok 模型 ID;`imagine` 和 `video` ID 会被故意过滤。 |
| 客户端无法连接 | 确认它支持 Streamable HTTP 并向确切的 `/mcp` URL 发送 Bearer 头部。 |
## 许可证
该项目根据 [CC BY-NC 4.0](./LICENSE) 许可。复制、分发和修改用于非商业目的时,允许注明出处并遵守许可条款。商业使用需要版权持有人的事先书面许可。
MCP 配置
以下是此 MCP Server 的配置信息,可直接复制到 Cursor 或其他 MCP 客户端中使用。
mcp.json
连接信息
猜你喜欢
暂无推荐服务器