mcp-apisix 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mcp_apisix-0.1.0/.dockerignore +45 -0
- mcp_apisix-0.1.0/.env.example +15 -0
- mcp_apisix-0.1.0/.gitignore +41 -0
- mcp_apisix-0.1.0/Dockerfile +54 -0
- mcp_apisix-0.1.0/LICENSE +21 -0
- mcp_apisix-0.1.0/PKG-INFO +441 -0
- mcp_apisix-0.1.0/README.md +410 -0
- mcp_apisix-0.1.0/docker-compose.yml +35 -0
- mcp_apisix-0.1.0/pyproject.toml +65 -0
- mcp_apisix-0.1.0/scripts/e2e_run.py +510 -0
- mcp_apisix-0.1.0/src/mcp_apisix/__init__.py +6 -0
- mcp_apisix-0.1.0/src/mcp_apisix/__main__.py +6 -0
- mcp_apisix-0.1.0/src/mcp_apisix/auth.py +107 -0
- mcp_apisix-0.1.0/src/mcp_apisix/clients/__init__.py +6 -0
- mcp_apisix-0.1.0/src/mcp_apisix/clients/admin.py +353 -0
- mcp_apisix-0.1.0/src/mcp_apisix/clients/base.py +139 -0
- mcp_apisix-0.1.0/src/mcp_apisix/clients/detector.py +144 -0
- mcp_apisix-0.1.0/src/mcp_apisix/clients/factory.py +25 -0
- mcp_apisix-0.1.0/src/mcp_apisix/clients/normalizer.py +72 -0
- mcp_apisix-0.1.0/src/mcp_apisix/projection.py +104 -0
- mcp_apisix-0.1.0/src/mcp_apisix/sanitizer.py +80 -0
- mcp_apisix-0.1.0/src/mcp_apisix/server.py +936 -0
- mcp_apisix-0.1.0/tests/__init__.py +0 -0
- mcp_apisix-0.1.0/tests/conftest.py +33 -0
- mcp_apisix-0.1.0/tests/test_client.py +183 -0
- mcp_apisix-0.1.0/tests/test_detector.py +289 -0
- mcp_apisix-0.1.0/tests/test_e2e_mcp.py +305 -0
- mcp_apisix-0.1.0/tests/test_normalizer.py +154 -0
- mcp_apisix-0.1.0/tests/test_projection.py +263 -0
- mcp_apisix-0.1.0/tests/test_sanitizer.py +294 -0
- mcp_apisix-0.1.0/tests/test_server.py +407 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# 版本控制与 CI
|
|
2
|
+
.git
|
|
3
|
+
.gitignore
|
|
4
|
+
|
|
5
|
+
# Python 缓存与构建产物
|
|
6
|
+
__pycache__/
|
|
7
|
+
*.py[cod]
|
|
8
|
+
*$py.class
|
|
9
|
+
*.so
|
|
10
|
+
build/
|
|
11
|
+
dist/
|
|
12
|
+
*.egg-info/
|
|
13
|
+
.eggs/
|
|
14
|
+
wheels/
|
|
15
|
+
|
|
16
|
+
# 虚拟环境
|
|
17
|
+
.venv/
|
|
18
|
+
venv/
|
|
19
|
+
env/
|
|
20
|
+
ENV/
|
|
21
|
+
.env
|
|
22
|
+
|
|
23
|
+
# 测试与缓存
|
|
24
|
+
.pytest_cache/
|
|
25
|
+
.mypy_cache/
|
|
26
|
+
.ruff_cache/
|
|
27
|
+
.coverage
|
|
28
|
+
htmlcov/
|
|
29
|
+
|
|
30
|
+
# IDE / 编辑器
|
|
31
|
+
.vscode/
|
|
32
|
+
.idea/
|
|
33
|
+
*.swp
|
|
34
|
+
*.swo
|
|
35
|
+
*~
|
|
36
|
+
|
|
37
|
+
# OS
|
|
38
|
+
.DS_Store
|
|
39
|
+
Thumbs.db
|
|
40
|
+
|
|
41
|
+
# 日志
|
|
42
|
+
*.log
|
|
43
|
+
|
|
44
|
+
# 集成测试脚本(不需要进镜像)
|
|
45
|
+
scripts/
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# MCP 传输与认证
|
|
2
|
+
MCP_TRANSPORT=stdio
|
|
3
|
+
# MCP_HOST=0.0.0.0
|
|
4
|
+
# MCP_PORT=8000
|
|
5
|
+
# MCP_AUTH_TOKEN=
|
|
6
|
+
# MCP_STATELESS_HTTP=false
|
|
7
|
+
# MCP_LOG_LEVEL=info
|
|
8
|
+
|
|
9
|
+
# APISIX 连接
|
|
10
|
+
APISIX_BASE_URL=http://localhost:9180
|
|
11
|
+
APISIX_ADMIN_KEY=your-admin-key
|
|
12
|
+
APISIX_API_VERSION=auto
|
|
13
|
+
APISIX_READ_ONLY=true
|
|
14
|
+
APISIX_TIMEOUT=30
|
|
15
|
+
APISIX_INSECURE=false
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# 设计文档与调研报告:不参与版本提交
|
|
2
|
+
docs/
|
|
3
|
+
|
|
4
|
+
# Python 缓存与构建产物
|
|
5
|
+
__pycache__/
|
|
6
|
+
*.py[cod]
|
|
7
|
+
*$py.class
|
|
8
|
+
*.so
|
|
9
|
+
build/
|
|
10
|
+
dist/
|
|
11
|
+
*.egg-info/
|
|
12
|
+
.eggs/
|
|
13
|
+
wheels/
|
|
14
|
+
|
|
15
|
+
# 虚拟环境
|
|
16
|
+
.venv/
|
|
17
|
+
venv/
|
|
18
|
+
env/
|
|
19
|
+
ENV/
|
|
20
|
+
.env
|
|
21
|
+
|
|
22
|
+
# 测试与缓存
|
|
23
|
+
.pytest_cache/
|
|
24
|
+
.mypy_cache/
|
|
25
|
+
.ruff_cache/
|
|
26
|
+
.coverage
|
|
27
|
+
htmlcov/
|
|
28
|
+
|
|
29
|
+
# IDE / 编辑器
|
|
30
|
+
.vscode/
|
|
31
|
+
.idea/
|
|
32
|
+
*.swp
|
|
33
|
+
*.swo
|
|
34
|
+
*~
|
|
35
|
+
|
|
36
|
+
# macOS
|
|
37
|
+
.DS_Store
|
|
38
|
+
Thumbs.db
|
|
39
|
+
|
|
40
|
+
# 日志
|
|
41
|
+
*.log
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# syntax=docker/dockerfile:1
|
|
2
|
+
|
|
3
|
+
########## 构建阶段 ##########
|
|
4
|
+
FROM python:3.13-slim AS builder
|
|
5
|
+
|
|
6
|
+
WORKDIR /app
|
|
7
|
+
|
|
8
|
+
# 仅复制构建所需文件,最大化利用缓存
|
|
9
|
+
COPY pyproject.toml README.md ./
|
|
10
|
+
COPY src ./src
|
|
11
|
+
|
|
12
|
+
# 构建 wheel 并安装到独立前缀,便于拷贝到运行阶段
|
|
13
|
+
RUN pip install --no-cache-dir --upgrade pip build \
|
|
14
|
+
&& pip wheel --no-cache-dir --no-deps --wheel-dir /wheels . \
|
|
15
|
+
&& pip install --no-cache-dir --prefix=/install .
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
########## 运行阶段 ##########
|
|
19
|
+
FROM python:3.13-slim AS runtime
|
|
20
|
+
|
|
21
|
+
# OCI 元数据:关联源码仓库,便于溯源,并让 GHCR 包页自动关联到 GitHub 仓库
|
|
22
|
+
LABEL org.opencontainers.image.source="https://github.com/zhouweico/mcp-apisix" \
|
|
23
|
+
org.opencontainers.image.title="mcp-apisix" \
|
|
24
|
+
org.opencontainers.image.description="MCP Server for Apache APISIX Admin API (stdio/sse/streamable-http, token auth)" \
|
|
25
|
+
org.opencontainers.image.url="https://github.com/zhouweico/mcp-apisix" \
|
|
26
|
+
org.opencontainers.image.licenses="MIT"
|
|
27
|
+
|
|
28
|
+
# 运行时环境变量默认值(可在 docker run / compose 中覆盖)
|
|
29
|
+
ENV PYTHONUNBUFFERED=1 \
|
|
30
|
+
PYTHONDONTWRITEBYTECODE=1 \
|
|
31
|
+
MCP_TRANSPORT=streamable-http \
|
|
32
|
+
MCP_HOST=0.0.0.0 \
|
|
33
|
+
MCP_PORT=8000
|
|
34
|
+
|
|
35
|
+
WORKDIR /app
|
|
36
|
+
|
|
37
|
+
# 拷贝已安装的依赖与包
|
|
38
|
+
COPY --from=builder /install /usr/local
|
|
39
|
+
|
|
40
|
+
# 使用非 root 用户运行
|
|
41
|
+
RUN useradd --create-home --uid 10001 appuser
|
|
42
|
+
USER appuser
|
|
43
|
+
|
|
44
|
+
EXPOSE 8000
|
|
45
|
+
|
|
46
|
+
# 健康检查:HTTP 传输下 /health 免鉴权返回 200
|
|
47
|
+
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
|
|
48
|
+
CMD python -c "import os,urllib.request,sys; \
|
|
49
|
+
port=os.getenv('MCP_PORT','8000'); \
|
|
50
|
+
sys.exit(0) if os.getenv('MCP_TRANSPORT','stdio')=='stdio' else \
|
|
51
|
+
sys.exit(0 if urllib.request.urlopen(f'http://127.0.0.1:{port}/health', timeout=3).status==200 else 1)"
|
|
52
|
+
|
|
53
|
+
# 入口:通过控制台脚本启动,具体协议由 MCP_TRANSPORT 决定
|
|
54
|
+
ENTRYPOINT ["mcp-apisix"]
|
mcp_apisix-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 zhouweico
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,441 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mcp-apisix
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: MCP Server for Apache APISIX Admin API
|
|
5
|
+
Project-URL: Homepage, https://github.com/zhouweico/mcp-apisix
|
|
6
|
+
Project-URL: Repository, https://github.com/zhouweico/mcp-apisix
|
|
7
|
+
Author: zhouweico
|
|
8
|
+
License-Expression: MIT
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Keywords: admin-api,apisix,gateway,mcp,model-context-protocol
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Requires-Python: >=3.10
|
|
20
|
+
Requires-Dist: httpx2>=1.0.0
|
|
21
|
+
Requires-Dist: mcp<3.0.0,>=2.0.0
|
|
22
|
+
Requires-Dist: pydantic>=2.0.0
|
|
23
|
+
Requires-Dist: starlette>=0.37.0
|
|
24
|
+
Requires-Dist: uvicorn>=0.27.0
|
|
25
|
+
Provides-Extra: dev
|
|
26
|
+
Requires-Dist: mypy>=1.10.0; extra == 'dev'
|
|
27
|
+
Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
|
|
28
|
+
Requires-Dist: pytest>=8.0.0; extra == 'dev'
|
|
29
|
+
Requires-Dist: ruff>=0.4.0; extra == 'dev'
|
|
30
|
+
Description-Content-Type: text/markdown
|
|
31
|
+
|
|
32
|
+
# mcp-apisix
|
|
33
|
+
|
|
34
|
+
Apache APISIX Admin API MCP Server —— 让 AI 助手查询与管理 APISIX 网关配置。
|
|
35
|
+
|
|
36
|
+
兼容 APISIX 2.x/3.x,响应格式(v2/v3)自动探测(优先依据 `X-API-VERSION` 响应头,头缺失时按响应体结构推断)。
|
|
37
|
+
|
|
38
|
+
## 特性
|
|
39
|
+
|
|
40
|
+
- **多协议传输**:`stdio`(默认)、`sse`、`streamable-http`
|
|
41
|
+
- **HTTP 接口认证**:Bearer Token 保护,未授权请求返回 `401`
|
|
42
|
+
- **写前确认**:创建 / 更新 / 切换状态等写操作触发 MCP 2.0 Elicitation 确认
|
|
43
|
+
- **MCP Resources**:`apisix://` URI 暴露服务器环境等只读元数据
|
|
44
|
+
- **Stateless HTTP**:无会话状态,适配 Serverless / 多副本部署
|
|
45
|
+
- **凭据脱敏**:强制启用(不可关闭),消费者凭据、插件密钥等响应时自动遮盖
|
|
46
|
+
- **默认只读**:写工具默认不注册,需显式 `APISIX_READ_ONLY=false` 开启
|
|
47
|
+
- **灵活部署**:`uvx` 免安装、Docker 公开镜像、或本地构建
|
|
48
|
+
|
|
49
|
+
## 快速开始
|
|
50
|
+
|
|
51
|
+
### MCP 客户端(stdio,本地)
|
|
52
|
+
|
|
53
|
+
Claude Code 示例,写入项目 `.mcp.json` 或全局 `~/.claude.json`:
|
|
54
|
+
|
|
55
|
+
```json
|
|
56
|
+
{
|
|
57
|
+
"mcpServers": {
|
|
58
|
+
"apisix": {
|
|
59
|
+
"type": "stdio",
|
|
60
|
+
"command": "uvx",
|
|
61
|
+
"args": ["mcp-apisix"],
|
|
62
|
+
"env": {
|
|
63
|
+
"APISIX_BASE_URL": "http://localhost:9180",
|
|
64
|
+
"APISIX_ADMIN_KEY": "your-admin-key",
|
|
65
|
+
"APISIX_READ_ONLY": "false"
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Cursor / OpenCode / Claude Desktop 等客户端格式相同:`command: uvx` + `args: ["mcp-apisix"]` + `APISIX_*` 环境变量。
|
|
73
|
+
|
|
74
|
+
**`APISIX_BASE_URL` 格式**:`scheme://host[:port]`。Admin API 默认独立监听 `9180`,Data Plane 监听 `9080`,二者分离。典型取值:
|
|
75
|
+
|
|
76
|
+
| 部署形态 | `APISIX_BASE_URL` 示例 |
|
|
77
|
+
|---|---|
|
|
78
|
+
| 默认 | `http://<host>:9180` |
|
|
79
|
+
| 经反向代理转发 | 填代理对外完整地址 |
|
|
80
|
+
| 自签名 TLS | `https://<host>:9180` + `APISIX_INSECURE=true` |
|
|
81
|
+
|
|
82
|
+
### Docker(公开镜像,免构建)
|
|
83
|
+
|
|
84
|
+
公开镜像:`ghcr.io/zhouweico/mcp-apisix:latest`。
|
|
85
|
+
|
|
86
|
+
**方式一:stdio(客户端拉起容器)**
|
|
87
|
+
|
|
88
|
+
```json
|
|
89
|
+
{
|
|
90
|
+
"mcpServers": {
|
|
91
|
+
"apisix": {
|
|
92
|
+
"type": "stdio",
|
|
93
|
+
"command": "docker",
|
|
94
|
+
"args": ["run", "-i", "--rm", "ghcr.io/zhouweico/mcp-apisix:latest"],
|
|
95
|
+
"env": {
|
|
96
|
+
"APISIX_BASE_URL": "http://your-apisix-host:9180",
|
|
97
|
+
"APISIX_ADMIN_KEY": "your-admin-key",
|
|
98
|
+
"APISIX_READ_ONLY": "false"
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
> 必须带 `-i`(保持 stdin 管道)。
|
|
106
|
+
|
|
107
|
+
**方式二:HTTP + 认证(容器独立运行)**
|
|
108
|
+
|
|
109
|
+
> 容器启动时会校验 `APISIX_ADMIN_KEY`(缺失则 `${VAR:?...}` 报错退出),必须显式传入。
|
|
110
|
+
|
|
111
|
+
启动容器:
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
docker run -d -p 8000:8000 \
|
|
115
|
+
-e MCP_TRANSPORT=streamable-http \
|
|
116
|
+
-e MCP_AUTH_TOKEN=your-strong-token \
|
|
117
|
+
-e APISIX_BASE_URL=http://your-apisix-host:9180 \
|
|
118
|
+
-e APISIX_ADMIN_KEY=your-admin-key \
|
|
119
|
+
-e APISIX_READ_ONLY=false \
|
|
120
|
+
ghcr.io/zhouweico/mcp-apisix:latest
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
客户端 `.mcp.json`:
|
|
124
|
+
|
|
125
|
+
```json
|
|
126
|
+
{
|
|
127
|
+
"mcpServers": {
|
|
128
|
+
"apisix": {
|
|
129
|
+
"type": "streamable-http",
|
|
130
|
+
"url": "http://localhost:8000/mcp",
|
|
131
|
+
"headers": {
|
|
132
|
+
"Authorization": "Bearer your-strong-token"
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## 可用工具
|
|
140
|
+
|
|
141
|
+
共 22 个原子工具 + 1 个 MCP Resource。
|
|
142
|
+
|
|
143
|
+
### 资源读取(11 个,只读)
|
|
144
|
+
|
|
145
|
+
所有 `list_*` 工具共享通用参数:`page` / `page_size`(有效区间 [10, 500])/ `detail`(返回完整配置)/ `fields`(JSON 数组,覆盖默认投影;`detail=true` 时忽略)。所有资源响应统一经过脱敏层。
|
|
146
|
+
|
|
147
|
+
| 工具 | 对应端点 | 资源特有过滤参数 | 只读模式 |
|
|
148
|
+
|------|----------|------------------|----------|
|
|
149
|
+
| `apisix_list_routes` | `GET /routes` | `name` / `uri` / `label`(v3)/ `service_id` / `upstream_id`(引用过滤,≥3.13) | ✅ |
|
|
150
|
+
| `apisix_get_route` | `GET /routes/{id}` | — | ✅ |
|
|
151
|
+
| `apisix_list_services` | `GET /services` | 无 | ✅ |
|
|
152
|
+
| `apisix_get_service` | `GET /services/{id}` | — | ✅ |
|
|
153
|
+
| `apisix_list_upstreams` | `GET /upstreams` | 无 | ✅ |
|
|
154
|
+
| `apisix_get_upstream` | `GET /upstreams/{id}` | — | ✅ |
|
|
155
|
+
| `apisix_list_consumers` | `GET /consumers` | 无(凭据字段已脱敏) | ✅ |
|
|
156
|
+
| `apisix_get_consumer` | `GET /consumers/{username}` | —(凭据字段已脱敏) | ✅ |
|
|
157
|
+
| `apisix_list_global_rules` | `GET /global_rules` | 无 | ✅ |
|
|
158
|
+
| `apisix_list_stream_routes` | `GET /stream_routes` | 无 | ✅ |
|
|
159
|
+
| `apisix_list_plugin_configs` | `GET /plugin_configs` | 无 | ✅ |
|
|
160
|
+
|
|
161
|
+
> `global_rules` / `stream_routes` / `plugin_configs` 有意只提供 list,不提供 get:资源数量通常很少,一次 list 即可获取全部。需完整配置时传 `detail=true`。
|
|
162
|
+
|
|
163
|
+
### 语义支撑(3 个,只读)
|
|
164
|
+
|
|
165
|
+
| 工具 | 对应端点 | 说明 | 只读模式 |
|
|
166
|
+
|------|----------|------|----------|
|
|
167
|
+
| `apisix_list_plugins` | `GET /plugins/list` | 插件名数组(按 priority 降序,不含 schema);`subsystem` 取 `http`(默认)或 `stream` | ✅ |
|
|
168
|
+
| `apisix_get_plugin_schema` | `GET /schema/plugins/{name}` | 单个插件字段定义、类型、必填项、默认值(含 `metadata_schema` 与 `consumer_schema`) | ✅ |
|
|
169
|
+
| `apisix_get_server_info` | 探测层数据 | 响应格式(v2/v3)与可用能力清单,告知 AI 当前环境的能力边界 | ✅ |
|
|
170
|
+
|
|
171
|
+
### 资源配置校验(1 个,只读)
|
|
172
|
+
|
|
173
|
+
| 工具 | 对应端点 | 说明 | 只读模式 |
|
|
174
|
+
|------|----------|------|----------|
|
|
175
|
+
| `apisix_validate_resource_config` | `POST /schema/validate/{resource}`(≥3.5) | 校验配置是否符合 JSON schema;仅校验 schema,不校验引用存在性与插件合法性;通过不代表写入必定成功 | ✅ |
|
|
176
|
+
|
|
177
|
+
### 写操作(7 个,`APISIX_READ_ONLY=true` 时不注册)
|
|
178
|
+
|
|
179
|
+
| 工具 | 语义 | 只读模式 |
|
|
180
|
+
|------|------|----------|
|
|
181
|
+
| `apisix_create_route` | POST 创建(服务端生成 id) | ❌ |
|
|
182
|
+
| `apisix_update_route` | PATCH 增量(带乐观锁) | ❌ |
|
|
183
|
+
| `apisix_toggle_route` | PATCH `status` 0/1(仅 route 有此字段) | ❌ |
|
|
184
|
+
| `apisix_create_upstream` | POST 创建(服务端生成 id) | ❌ |
|
|
185
|
+
| `apisix_update_upstream` | PATCH 增量 | ❌ |
|
|
186
|
+
| `apisix_create_service` | POST 创建(服务端生成 id) | ❌ |
|
|
187
|
+
| `apisix_update_service` | PATCH 增量 | ❌ |
|
|
188
|
+
|
|
189
|
+
**写操作约定**:
|
|
190
|
+
|
|
191
|
+
- **create 严格用 POST**,服务端生成 id,不接受 `id` 参数;禁止 PUT(会静默全量覆盖且无乐观锁)
|
|
192
|
+
- **update 用 PATCH**,仅传需修改字段,未提及字段保持不变;自带乐观锁,配置在读取后被其他来源修改会返回冲突提示
|
|
193
|
+
- **toggle 仅限 route**:upstream 和 service 的 schema 无 `status` 字段,不提供 toggle
|
|
194
|
+
- **不提供 DELETE**:破坏性过大,需删除时通过 APISIX Dashboard 或 Admin API 手动处理
|
|
195
|
+
- **不提供 consumer 写操作**:consumer 涉及凭据写入,风险过高
|
|
196
|
+
|
|
197
|
+
**写前确认**:所有写工具执行前通过 `ctx.elicit()` 向用户确认;stdio 等不支持 Elicitation 的客户端降级直接执行,返回结果中标注"未经人工确认"。
|
|
198
|
+
|
|
199
|
+
**多来源共管风险**:APISIX 配置可能同时被 Dashboard、Ingress Controller(源自 ApisixRoute 等 CRD)等多方管理。若目标资源由声明式控制器管理,此处修改可能在数秒后被控制器按 CRD 覆盖回原状。写工具的返回结果中会显式提示此风险。
|
|
200
|
+
|
|
201
|
+
### APISIX 概念
|
|
202
|
+
|
|
203
|
+
- **route**:核心路由配置,匹配请求并指向 upstream 或 service
|
|
204
|
+
- **service**:可复用的服务配置(upstream + plugins),被 route 引用
|
|
205
|
+
- **upstream**:后端节点集合(含负载均衡策略、健康检查等)
|
|
206
|
+
- **consumer**:消费者身份,承载认证凭据(如 key-auth 的 key)与限流配额
|
|
207
|
+
- **global_rules**:全局生效的插件配置,作用于所有路由
|
|
208
|
+
- **plugin_configs**:可复用的插件配置组,被 route 引用
|
|
209
|
+
- **stream_routes**:四层(TCP/UDP)流路由
|
|
210
|
+
|
|
211
|
+
> **响应格式 v2/v3**:APISIX 3.x 可通过 `deployment.admin.admin_api_version` 配置返回 v2 格式,APISIX 2.x 原生返回 v2 格式。本 Server 自动探测响应格式(优先依据 `X-API-VERSION` 响应头,头缺失时按响应体结构推断),无需手动配置。v2 格式下分页与过滤参数被服务端静默忽略,返回结果中会显式告知。
|
|
212
|
+
|
|
213
|
+
## 配置
|
|
214
|
+
|
|
215
|
+
### 环境变量
|
|
216
|
+
|
|
217
|
+
**MCP 传输与认证**
|
|
218
|
+
|
|
219
|
+
| 变量 | 说明 | 默认值 |
|
|
220
|
+
|------|------|--------|
|
|
221
|
+
| `MCP_TRANSPORT` | 传输协议:`stdio` / `sse` / `streamable-http` | `stdio` |
|
|
222
|
+
| `MCP_HOST` | HTTP 监听地址(stdio 忽略) | `0.0.0.0` |
|
|
223
|
+
| `MCP_PORT` | HTTP 监听端口(stdio 忽略) | `8000` |
|
|
224
|
+
| `MCP_AUTH_TOKEN` | 非空时启用 Bearer Token 认证 | -(不鉴权) |
|
|
225
|
+
| `MCP_STATELESS_HTTP` | 启用无状态 HTTP(适配 Serverless) | `false` |
|
|
226
|
+
| `MCP_LOG_LEVEL` | 日志级别:`debug` / `info` / `warning` / `error` | `info` |
|
|
227
|
+
|
|
228
|
+
**APISIX 连接**
|
|
229
|
+
|
|
230
|
+
| 变量 | 说明 | 默认值 |
|
|
231
|
+
|------|------|--------|
|
|
232
|
+
| `APISIX_BASE_URL` | Admin API 地址,格式 `scheme://host[:port]` | `http://localhost:9180` |
|
|
233
|
+
| `APISIX_ADMIN_KEY` | **必填**。映射到 `X-API-KEY` 请求头 | - |
|
|
234
|
+
| `APISIX_API_VERSION` | 响应格式:`auto`(自动探测)/ `v2` / `v3` | `auto` |
|
|
235
|
+
| `APISIX_READ_ONLY` | 只读模式(禁用写工具) | `true` |
|
|
236
|
+
| `APISIX_TIMEOUT` | 请求超时秒数 | `30` |
|
|
237
|
+
| `APISIX_INSECURE` | 跳过 TLS 证书验证(自签名 / 内部 CA 场景) | `false` |
|
|
238
|
+
|
|
239
|
+
### 只读模式
|
|
240
|
+
|
|
241
|
+
默认开启,写工具(create / update / toggle)不注册,Agent 看不到也调不到。开启写操作:
|
|
242
|
+
|
|
243
|
+
```json
|
|
244
|
+
{ "env": { "APISIX_READ_ONLY": "false" } }
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
### 响应格式探测
|
|
248
|
+
|
|
249
|
+
`APISIX_API_VERSION=auto`(默认)时,从成功响应(2xx)中自动探测:优先读取 `X-API-VERSION` 响应头,头缺失时按响应体结构推断(`node`+`action` → v2,`list`+`total` → v3)。探测未完成前按 v3 处理。可强制指定 `v2` 或 `v3` 跳过探测。
|
|
250
|
+
|
|
251
|
+
> 探测结果在进程生命周期内缓存,不主动失效。若 APISIX 实例重启并切换了配置,需重启 MCP 进程。
|
|
252
|
+
|
|
253
|
+
### TLS 证书验证
|
|
254
|
+
|
|
255
|
+
默认验证 TLS 证书(行为与 httpx 一致)。自签名或内部 CA 环境:
|
|
256
|
+
|
|
257
|
+
```json
|
|
258
|
+
{ "env": { "APISIX_INSECURE": "true" } }
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
> 禁用证书验证不安全,生产环境应使用受信任 CA 签发的有效证书。
|
|
262
|
+
|
|
263
|
+
## 多协议传输
|
|
264
|
+
|
|
265
|
+
| 协议 | 端点 | 适用 |
|
|
266
|
+
|---|---|---|
|
|
267
|
+
| `stdio`(默认) | - | 本地客户端集成(Claude Code、Cursor 等) |
|
|
268
|
+
| `sse` | `http://<host>:<port>/sse` | SSE 传输(已废弃) |
|
|
269
|
+
| `streamable-http` | `http://<host>:<port>/mcp` | 远程部署 / 多客户端共享 |
|
|
270
|
+
|
|
271
|
+
启动示例:
|
|
272
|
+
|
|
273
|
+
```bash
|
|
274
|
+
MCP_TRANSPORT=streamable-http \
|
|
275
|
+
MCP_HOST=0.0.0.0 MCP_PORT=8000 \
|
|
276
|
+
MCP_AUTH_TOKEN=your-strong-token \
|
|
277
|
+
APISIX_BASE_URL=http://localhost:9180 \
|
|
278
|
+
APISIX_ADMIN_KEY=your-admin-key \
|
|
279
|
+
mcp-apisix
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
## 接口认证
|
|
283
|
+
|
|
284
|
+
`MCP_AUTH_TOKEN` 非空时,HTTP 请求需携带:
|
|
285
|
+
|
|
286
|
+
```
|
|
287
|
+
Authorization: Bearer <MCP_AUTH_TOKEN>
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
兼容 `X-Auth-Token` / `X-MCP-Token` 请求头。`GET /health` 免鉴权(容器探活)。
|
|
291
|
+
|
|
292
|
+
> `stdio` 不经过网络,不做 Token 认证。未设 `MCP_AUTH_TOKEN` 时 HTTP 接口不鉴权,生产环境务必配置。
|
|
293
|
+
|
|
294
|
+
## MCP Resources
|
|
295
|
+
|
|
296
|
+
| URI | 说明 |
|
|
297
|
+
|---|---|
|
|
298
|
+
| `apisix://server-info` | APISIX 服务器环境信息(响应格式 v2/v3、可用能力清单) |
|
|
299
|
+
|
|
300
|
+
会话建立时探测层尚无数据,Resource 返回配置值 + 探测状态"未知";首次调用 Admin API 后探测完成,后续读取返回准确格式。每次读取动态返回,非静态快照。
|
|
301
|
+
|
|
302
|
+
## Stateless HTTP 模式
|
|
303
|
+
|
|
304
|
+
`MCP_STATELESS_HTTP=true`:每次请求独立处理,不保留会话状态。适配 Serverless(AWS Lambda、阿里云函数计算)或多副本部署。
|
|
305
|
+
|
|
306
|
+
```bash
|
|
307
|
+
MCP_TRANSPORT=streamable-http \
|
|
308
|
+
MCP_STATELESS_HTTP=true \
|
|
309
|
+
MCP_HOST=0.0.0.0 MCP_PORT=8000 \
|
|
310
|
+
mcp-apisix
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
> Stateless 模式不支持 SSE 流式响应,每个 HTTP 请求独立完成后返回。
|
|
314
|
+
|
|
315
|
+
## 容器化部署
|
|
316
|
+
|
|
317
|
+
### 本地构建(Docker)
|
|
318
|
+
|
|
319
|
+
```bash
|
|
320
|
+
docker build -t mcp-apisix:latest .
|
|
321
|
+
|
|
322
|
+
docker run -d --name mcp-apisix -p 8000:8000 \
|
|
323
|
+
-e MCP_TRANSPORT=streamable-http \
|
|
324
|
+
-e MCP_AUTH_TOKEN=your-strong-token \
|
|
325
|
+
-e APISIX_BASE_URL=http://your-apisix-host:9180 \
|
|
326
|
+
-e APISIX_ADMIN_KEY=your-admin-key \
|
|
327
|
+
-e APISIX_READ_ONLY=false \
|
|
328
|
+
mcp-apisix:latest
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
### Docker Compose
|
|
332
|
+
|
|
333
|
+
```bash
|
|
334
|
+
cp .env.example .env # 按需修改
|
|
335
|
+
docker compose up -d
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
`docker-compose.yml` 已内置:基于 Dockerfile 构建(标记为 `mcp-apisix:latest`)、`/health` 健康检查、非 root 用户运行。
|
|
339
|
+
|
|
340
|
+
> 跳过本地构建、直接拉取公开镜像:删除 `build:` 段,只保留 `image: ghcr.io/zhouweico/mcp-apisix:latest`。
|
|
341
|
+
|
|
342
|
+
## 使用示例
|
|
343
|
+
|
|
344
|
+
下面示例均为自然语言提示,AI 助手会自动映射到对应 MCP 工具。
|
|
345
|
+
|
|
346
|
+
### 资源查询
|
|
347
|
+
|
|
348
|
+
```
|
|
349
|
+
列出 APISIX 里所有的路由(只看 id、name、uri)
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
```
|
|
353
|
+
查看路由 r1 的完整配置
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
```
|
|
357
|
+
列出所有上游,按名称过滤包含 "user-service" 的
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
```
|
|
361
|
+
查看消费者 alice 的配置
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
```
|
|
365
|
+
列出所有全局规则,返回完整配置
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
### 语义查询
|
|
369
|
+
|
|
370
|
+
```
|
|
371
|
+
APISIX 支持哪些插件?按优先级列出来
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
```
|
|
375
|
+
查看 key-auth 插件的 schema,需要哪些字段
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
```
|
|
379
|
+
当前 APISIX 实例返回的是 v2 还是 v3 格式?支持引用过滤吗?
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
### 配置校验
|
|
383
|
+
|
|
384
|
+
```
|
|
385
|
+
帮我校验这份路由配置是否符合 schema:
|
|
386
|
+
{"uri": "/api/v1/*", "upstream": {"type": "roundrobin", "nodes": {"127.0.0.1:8080": 1}}}
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
### 写操作(需 `APISIX_READ_ONLY=false`)
|
|
390
|
+
|
|
391
|
+
```
|
|
392
|
+
创建一个路由,uri 是 /api/v1/users,转发到 upstream u1
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
```
|
|
396
|
+
更新路由 r1,把 priority 改成 100
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
```
|
|
400
|
+
禁用路由 r1
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
```
|
|
404
|
+
创建一个上游,类型 roundrobin,节点 127.0.0.1:8080 权重 1
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
```
|
|
408
|
+
更新上游 u1,把超时改成 10 秒
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
```
|
|
412
|
+
创建一个服务,绑定 upstream u1,开启 key-auth 插件
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
> 写操作属破坏性操作,支持 Elicitation 的客户端会弹出二次确认;stdio 等不支持的客户端直接执行,返回结果中标注"未经人工确认"。
|
|
416
|
+
|
|
417
|
+
### 字段投影
|
|
418
|
+
|
|
419
|
+
```
|
|
420
|
+
列出所有路由,只返回 id、name、uri、upstream_id 这几个字段
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
```
|
|
424
|
+
列出路由的完整配置(不要裁剪字段)
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
> `labels` 为强制保留字段,任何投影都会包含(用于识别资源归属)。
|
|
428
|
+
|
|
429
|
+
### 只读模式(`APISIX_READ_ONLY=true`)
|
|
430
|
+
|
|
431
|
+
写工具在只读模式下不注册,AI 只能执行查询类操作:
|
|
432
|
+
|
|
433
|
+
```
|
|
434
|
+
只读模式下:帮我禁用路由 r1
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
AI 会回复该操作不可用,引导用户关闭只读模式或手动处理。
|
|
438
|
+
|
|
439
|
+
## License
|
|
440
|
+
|
|
441
|
+
MIT
|