mcp-apisix
# mcp-apisix
Apache APISIX Admin API MCP Server —— 让 AI 助手查询与管理 APISIX 网关配置。
兼容 APISIX 2.x/3.x,响应格式(v2/v3)自动探测(优先依据 `X-API-VERSION` 响应头,头缺失时按响应体结构推断)。
## 特性
- **多协议传输**:`stdio`(默认)、`sse`、`streamable-http`
- **HTTP 接口认证**:Bearer Token 保护,未授权请求返回 `401`
- **写前确认**:创建 / 更新 / 切换状态等写操作强制二次确认,客户端需支持 Elicitation 能力
- **MCP Resources**:`apisix://` URI 暴露服务器环境等只读元数据
- **Stateless HTTP**:无会话状态,适配 Serverless / 多副本部署
- **凭据脱敏**:强制启用(不可关闭),消费者凭据、插件密钥等响应时自动遮盖
- **默认只读**:写工具默认不注册,需显式 `APISIX_READ_ONLY=false` 开启
- **灵活部署**:`uvx` 免安装、Docker 公开镜像、或本地构建
## 快速开始
### MCP 客户端(stdio,本地)
Claude Code 示例,写入项目 `.mcp.json` 或全局 `~/.claude.json`:
```json
{
"mcpServers": {
"apisix": {
"type": "stdio",
"command": "uvx",
"args": ["mcp-apisix"],
"env": {
"APISIX_BASE_URL": "http://localhost:9180",
"APISIX_ADMIN_KEY": "your-admin-key",
"APISIX_READ_ONLY": "false"
}
}
}
}
```
Cursor / OpenCode / Claude Desktop 等客户端格式相同:`command: uvx` + `args: ["mcp-apisix"]` + `APISIX_*` 环境变量。
**`APISIX_BASE_URL` 格式**:`scheme://host[:port]`。Admin API 默认独立监听 `9180`,Data Plane 监听 `9080`,二者分离。典型取值:
| 部署形态 | `APISIX_BASE_URL` 示例 |
|---|---|
| 默认 | `http://<host>:9180` |
| 经反向代理转发 | 填代理对外完整地址 |
| 自签名 TLS | `https://<host>:9180` + `APISIX_INSECURE=true` |
### Docker(公开镜像,免构建)
公开镜像:`ghcr.io/zhouweico/mcp-apisix:latest`。
**方式一:stdio(客户端拉起容器)**
```json
{
"mcpServers": {
"apisix": {
"type": "stdio",
"command": "docker",
"args": ["run", "-i", "--rm", "ghcr.io/zhouweico/mcp-apisix:latest"],
"env": {
"APISIX_BASE_URL": "http://your-apisix-host:9180",
"APISIX_ADMIN_KEY": "your-admin-key",
"APISIX_READ_ONLY": "false"
}
}
}
}
```
> 必须带 `-i`(保持 stdin 管道)。
**方式二:HTTP + 认证(容器独立运行)**
> 容器启动时会校验 `APISIX_ADMIN_KEY`(缺失则 `${VAR:?...}` 报错退出),必须显式传入。
启动容器:
```bash
docker run -d -p 8000:8000 \
-e MCP_TRANSPORT=streamable-http \
-e MCP_AUTH_TOKEN=your-strong-token \
-e APISIX_BASE_URL=http://your-apisix-host:9180 \
-e APISIX_ADMIN_KEY=your-admin-key \
-e APISIX_READ_ONLY=false \
ghcr.io/zhouweico/mcp-apisix:latest
```
客户端 `.mcp.json`:
```json
{
"mcpServers": {
"apisix": {
"type": "streamable-http",
"url": "http://localhost:8000/mcp",
"headers": {
"Authorization": "Bearer your-strong-token"
}
}
}
}
```
## 可用工具
共 22 个原子工具 + 1 个 MCP Resource。
### 资源读取(11 个,只读)
所有 `list_*` 工具共享通用参数:`page` / `page_size`(有效区间 [10, 500])/ `detail`(返回完整配置)/ `fields`(JSON 数组,覆盖默认投影;`detail=true` 时忽略)。所有资源响应统一经过脱敏层。
| 工具 | 对应端点 | 资源特有过滤参数 | 只读模式 |
|------|----------|------------------|----------|
| `apisix_list_routes` | `GET /routes` | `name` / `uri` / `label`(v3)/ `service_id` / `upstream_id`(引用过滤,≥3.13) | ✅ |
| `apisix_get_route` | `GET /routes/{id}` | — | ✅ |
| `apisix_list_services` | `GET /services` | 无 | ✅ |
| `apisix_get_service` | `GET /services/{id}` | — | ✅ |
| `apisix_list_upstreams` | `GET /upstreams` | 无 | ✅ |
| `apisix_get_upstream` | `GET /upstreams/{id}` | — | ✅ |
| `apisix_list_consumers` | `GET /consumers` | 无(凭据字段已脱敏) | ✅ |
| `apisix_get_consumer` | `GET /consumers/{username}` | —(凭据字段已脱敏) | ✅ |
| `apisix_list_global_rules` | `GET /global_rules` | 无 | ✅ |
| `apisix_list_stream_routes` | `GET /stream_routes` | 无 | ✅ |
| `apisix_list_plugin_configs` | `GET /plugin_configs` | 无 | ✅ |
> `global_rules` / `stream_routes` / `plugin_configs` 有意只提供 list,不提供 get:资源数量通常很少,一次 list 即可获取全部。需完整配置时传 `detail=true`。
### 语义支撑(3 个,只读)
| 工具 | 对应端点 | 说明 | 只读模式 |
|------|----------|------|----------|
| `apisix_list_plugins` | `GET /plugins/list` | 插件名数组(按 priority 降序,不含 schema);`subsystem` 取 `http`(默认)或 `stream` | ✅ |
| `apisix_get_plugin_schema` | `GET /schema/plugins/{name}` | 单个插件字段定义、类型、必填项、默认值(含 `metadata_schema` 与 `consumer_schema`) | ✅ |
| `apisix_get_server_info` | 探测层数据 | 客户端探测层状态(响应格式 v2/v3、可用能力清单),非 APISIX 节点运行时信息 | ✅ |
### 资源配置校验(1 个,只读)
| 工具 | 对应端点 | 说明 | 只读模式 |
|------|----------|------|----------|
| `apisix_validate_resource_config` | `POST /schema/validate/{resource}`(≥3.5) | 校验配置是否符合 JSON schema;仅校验 schema,不校验引用存在性与插件合法性;通过不代表写入必定成功 | ✅ |
### 写操作(7 个,`APISIX_READ_ONLY=true` 时不注册)
| 工具 | 语义 | 只读模式 |
|------|------|----------|
| `apisix_create_route` | POST 创建(服务端生成 id) | ❌ |
| `apisix_update_route` | PATCH 增量(带乐观锁) | ❌ |
| `apisix_toggle_route` | PATCH `status` 0/1(仅 route 有此字段) | ❌ |
| `apisix_create_upstream` | POST 创建(服务端生成 id) | ❌ |
| `apisix_update_upstream` | PATCH 增量 | ❌ |
| `apisix_create_service` | POST 创建(服务端生成 id) | ❌ |
| `apisix_update_service` | PATCH 增量 | ❌ |
**写操作约定**:
- **create 严格用 POST**,服务端生成 id,不接受 `id` 参数;禁止 PUT(会静默全量覆盖且无乐观锁)
- **update 用 PATCH**,仅传需修改字段,未提及字段保持不变;自带乐观锁,配置在读取后被其他来源修改会返回冲突提示
- **toggle 仅限 route**:upstream 和 service 的 schema 无 `status` 字段,不提供 toggle
- **不提供 DELETE**:破坏性过大,需删除时通过 APISIX Dashboard 或 Admin API 手动处理
- **不提供 consumer 写操作**:consumer 涉及凭据写入,风险过高
**写前确认**:所有写工具执行前强制向用户确认,确认由 MCP SDK 在参数解析阶段发起(`Resolve` + `Elicit`),并按协议版本自动选择传输方式(2025-06-18 同步 Elicitation / 2026-07-28 MRTR)。
> ⚠️ **客户端能力要求**:客户端必须声明 `elicitation` 能力,否则 SDK 直接返回 `-32021` 拒绝,写工具不会执行。自 v0.3.0 起不再提供"放行并标注未经人工确认"的降级路径——确认机制失效时一律拒绝,而非视为无需确认。非交互环境(如自动化脚本)如需写入,请直接调用 APISIX Admin API。
**多来源共管风险**:APISIX 配置可能同时被 Dashboard、Ingress Controller(源自 ApisixRoute 等 CRD)等多方管理。若目标资源由声明式控制器管理,此处修改可能在数秒后被控制器按 CRD 覆盖回原状。写工具的描述中会显式声明此风险。
### APISIX 概念
- **route**:核心路由配置,匹配请求并指向 upstream 或 service
- **service**:可复用的服务配置(upstream + plugins),被 route 引用
- **upstream**:后端节点集合(含负载均衡策略、健康检查等)
- **consumer**:消费者身份,承载认证凭据(如 key-auth 的 key)与限流配额
- **global_rules**:全局生效的插件配置,作用于所有路由
- **plugin_configs**:可复用的插件配置组,被 route 引用
- **stream_routes**:四层(TCP/UDP)流路由
> **响应格式 v2/v3**:APISIX 3.x 可通过 `deployment.admin.admin_api_version` 配置返回 v2 格式,APISIX 2.x 原生返回 v2 格式。本 Server 自动探测响应格式(优先依据 `X-API-VERSION` 响应头,头缺失时按响应体结构推断),无需手动配置。v2 格式下分页与过滤参数被服务端静默忽略,返回结果中会显式告知。
## 配置
### 环境变量
**MCP 传输与认证**
| 变量 | 说明 | 默认值 |
|------|------|--------|
| `MCP_TRANSPORT` | 传输协议:`stdio` / `sse` / `streamable-http` | `stdio` |
| `MCP_HOST` | HTTP 监听地址(stdio 忽略),默认仅本地回环;对外暴露需显式设置并务必配置 `MCP_AUTH_TOKEN` | `127.0.0.1` |
| `MCP_PORT` | HTTP 监听端口(stdio 忽略) | `8000` |
| `MCP_AUTH_TOKEN` | 非空时启用 Bearer Token 认证 | -(不鉴权) |
| `MCP_STATELESS_HTTP` | 启用无状态 HTTP(适配 Serverless) | `false` |
| `MCP_LOG_LEVEL` | 日志级别:`debug` / `info` / `warning` / `error` | `info` |
**APISIX 连接**
| 变量 | 说明 | 默认值 |
|------|------|--------|
| `APISIX_BASE_URL` | Admin API 地址,格式 `scheme://host[:port]` | `http://localhost:9180` |
| `APISIX_ADMIN_KEY` | **必填**。映射到 `X-API-KEY` 请求头 | - |
| `APISIX_API_VERSION` | 响应格式:`auto`(自动探测)/ `v2` / `v3` | `auto` |
| `APISIX_READ_ONLY` | 只读模式(禁用写工具) | `true` |
| `APISIX_TIMEOUT` | 请求超时秒数 | `30` |
| `APISIX_INSECURE` | 跳过 TLS 证书验证(自签名 / 内部 CA 场景) | `false` |
### 只读模式
默认开启,写工具(create / update / toggle)不注册,Agent 看不到也调不到。开启写操作:
```json
{ "env": { "APISIX_READ_ONLY": "false" } }
```
### 响应格式探测
`APISIX_API_VERSION=auto`(默认)时,从成功响应(2xx)中自动探测:优先读取 `X-API-VERSION` 响应头,头缺失时按响应体结构推断(`node`+`action` → v2,`list`+`total` → v3)。探测未完成前按 v3 处理。可强制指定 `v2` 或 `v3` 跳过探测。
> 探测结果在进程生命周期内缓存,不主动失效。若 APISIX 实例重启并切换了配置,需重启 MCP 进程。
### TLS 证书验证
默认验证 TLS 证书(行为与 httpx 一致)。自签名或内部 CA 环境:
```json
{ "env": { "APISIX_INSECURE": "true" } }
```
> 禁用证书验证不安全,生产环境应使用受信任 CA 签发的有效证书。
## 多协议传输
| 协议 | 端点 | 适用 |
|---|---|---|
| `stdio`(默认) | - | 本地客户端集成(Claude Code、Cursor 等) |
| `sse` | `http://<host>:<port>/sse` | SSE 传输(已废弃) |
| `streamable-http` | `http://<host>:<port>/mcp` | 远程部署 / 多客户端共享 |
启动示例:
```bash
MCP_TRANSPORT=streamable-http \
MCP_HOST=0.0.0.0 MCP_PORT=8000 \
MCP_AUTH_TOKEN=your-strong-token \
APISIX_BASE_URL=http://localhost:9180 \
APISIX_ADMIN_KEY=your-admin-key \
mcp-apisix
```
## 接口认证
`MCP_AUTH_TOKEN` 非空时,HTTP 请求需携带:
```
Authorization: Bearer <MCP_AUTH_TOKEN>
```
兼容 `X-Auth-Token` / `X-MCP-Token` 请求头。`GET /health` 免鉴权(容器探活)。
> `stdio` 不经过网络,不做 Token 认证。未设 `MCP_AUTH_TOKEN` 时 HTTP 接口不鉴权,生产环境务必配置。
## MCP Resources
| URI | 说明 |
|---|---|
| `apisix://server-info` | 客户端探测层状态(响应格式 v2/v3、可用能力清单),非 APISIX 节点运行时信息 |
会话建立时探测层尚无数据,Resource 返回配置值 + 探测状态"未知";首次调用 Admin API 后探测完成,后续读取返回准确格式。每次读取动态返回,非静态快照。
## Stateless HTTP 模式
`MCP_STATELESS_HTTP=true`:每次请求独立处理,不保留会话状态。适配 Serverless(AWS Lambda、阿里云函数计算)或多副本部署。
```bash
MCP_TRANSPORT=streamable-http \
MCP_STATELESS_HTTP=true \
MCP_PORT=8000 \
mcp-apisix
```
> Stateless 模式不支持 SSE 流式响应,每个 HTTP 请求独立完成后返回。
## 容器化部署
### 本地构建(Docker)
```bash
docker build -t mcp-apisix:latest .
docker run -d --name mcp-apisix -p 8000:8000 \
-e MCP_TRANSPORT=streamable-http \
-e MCP_AUTH_TOKEN=your-strong-token \
-e APISIX_BASE_URL=http://your-apisix-host:9180 \
-e APISIX_ADMIN_KEY=your-admin-key \
-e APISIX_READ_ONLY=false \
mcp-apisix:latest
```
### Docker Compose
```bash
cp .env.example .env # 按需修改
docker compose up -d
```
`docker-compose.yml` 已内置:基于 Dockerfile 构建(标记为 `mcp-apisix:latest`)、`/health` 健康检查、非 root 用户运行。
> 跳过本地构建、直接拉取公开镜像:删除 `build:` 段,只保留 `image: ghcr.io/zhouweico/mcp-apisix:latest`。
## 使用示例
下面示例均为自然语言提示,AI 助手会自动映射到对应 MCP 工具。
### 资源查询
```
列出 APISIX 里所有的路由(只看 id、name、uri)
```
```
查看路由 r1 的完整配置
```
```
列出所有上游,按名称过滤包含 "user-service" 的
```
```
查看消费者 alice 的配置
```
```
列出所有全局规则,返回完整配置
```
### 语义查询
```
APISIX 支持哪些插件?按优先级列出来
```
```
查看 key-auth 插件的 schema,需要哪些字段
```
```
当前 APISIX 实例返回的是 v2 还是 v3 格式?支持引用过滤吗?
```
### 配置校验
```
帮我校验这份路由配置是否符合 schema:
{"uri": "/api/v1/*", "upstream": {"type": "roundrobin", "nodes": {"127.0.0.1:8080": 1}}}
```
### 写操作(需 `APISIX_READ_ONLY=false`)
```
创建一个路由,uri 是 /api/v1/users,转发到 upstream u1
```
```
更新路由 r1,把 priority 改成 100
```
```
禁用路由 r1
```
```
创建一个上游,类型 roundrobin,节点 127.0.0.1:8080 权重 1
```
```
更新上游 u1,把超时改成 10 秒
```
```
创建一个服务,绑定 upstream u1,开启 key-auth 插件
```
> 写操作属破坏性操作,执行前会弹出二次确认。客户端未声明 `elicitation` 能力时,请求被 SDK 以 `-32021` 拒绝,工具不会执行。
### 字段投影
```
列出所有路由,只返回 id、name、uri、upstream_id 这几个字段
```
```
列出路由的完整配置(不要裁剪字段)
```
> `labels` 为强制保留字段,任何投影都会包含(用于识别资源归属)。
### 只读模式(`APISIX_READ_ONLY=true`)
写工具在只读模式下不注册,AI 只能执行查询类操作:
```
只读模式下:帮我禁用路由 r1
```
AI 会回复该操作不可用,引导用户关闭只读模式或手动处理。
## License
MIT
TDQS
Scored across 15 tools
Each tool targets a distinct resource type (route, service, upstream, consumer, etc.) and a distinct action (get, list, validate). Even similar list tools like apisix_list_routes and apisix_list_stream_routes are clearly differentiated by resource type and descriptions.
All tools follow the consistent pattern apisix_<verb>_<resource>, with verbs limited to get, list, and validate. Naming is uniform snake_case with no mixed conventions, making the toolset highly predictable.
With 15 tools, the server sits at the top of the ideal 3-15 range. Each tool corresponds to a meaningful APISIX resource or capability, and none feel redundant or out of scope, so the count is well-calibrated.
The toolset offers comprehensive read coverage for all major APISIX resources plus schema validation, and intentional omissions are documented. However, there are no create, update, or delete operations, which is a notable gap if full lifecycle management is expected, though consistent with the apparent read-only intent.