Skip to main content
Glama

Apifox MCP 服务器(改造版 · 支持按模块动态读取)

让 AI 助手通过 MCP 协议管理 Apifox 项目的接口文档:创建/更新/审计 API、管理数据模型、检查命名与响应一致性。 本仓库是 iwen-conf/apifox-mcp改造版: 原版 Python MCP 包不支持按模块读取,本版新增 APIFOX_MODULE_ID 支持(按模块动态导出/导入),并修复了导入写操作落错模块的问题。

⚠️ 安全:凡涉及 API Token 处均为占位符,真实 Token 只存在于本机 .zcode/config.json 的环境变量中,严禁写入任何将要上传 git 的文件


目录结构

apifox-mcp/
├── src/                      # MCP 服务器源码(唯一需要部署的包)
│   ├── config.py  utils.py  main.py  __init__.py
│   └── tools/               # 8 个工具模块(22 个 MCP 工具)
├── scripts/                 # 本地开发脚本(不上生产)
│   └── send_mcp.py          # JSON-RPC 验证脚本(token 从环境变量读取)
├── requirements.txt         # 依赖(锁定 mcp[cli]==1.29.0)
├── README.md                # 本文件
├── venv/                    # 虚拟环境(.gitignore 已忽略,不上传)
└── src/*.old                 # 上游原版文件对照(.gitignore 已忽略,仅本地参考)

.old 后缀文件是上游原版(config.py.oldutils.py.oldtools/*.old 等), 与改造版同目录存放,便于 diff 对照;它们不会被 Python 加载,也不会上传 git。


快速开始

1. 安装依赖(必须锁定 mcp 1.x)

python -m venv venv
venv/Scripts/pip install -r requirements.txt   # Windows
venv/bin/pip install -r requirements.txt       # Linux/macOS
  • 不能装 mcp 2.x——它移除了 FastMCP API,本包会启动失败。

  • Python ≥ 3.10(mcp 1.x 要求)。

  • ⚠️ Windows 下系统 PATH 里的 python 可能是 Microsoft Store 占位符(WindowsApps),不可用,务必用 venv 内的解释器。

2. 配置环境变量(四件套)

变量

说明

APIFOX_TOKEN

Apifox 开放 API Token(登录 Apifox 后获取)

APIFOX_PROJECT_ID

项目 ID

APIFOX_MODULE_ID

目标模块 ID(配置后按模块动态读取/写入)

PYTHONPATH

指向本仓库根目录的绝对路径(clone 后所在目录,不限定盘符,如 <仓库根目录>

3. 注册 MCP 服务器

服务器名 = 探测出的模块名 + " API 文档"(如"管理侧接口 API 文档")。

探测模块名:调一次导出接口,响应 info.title 即模块名:

POST https://api.apifox.com/v1/projects/{项目ID}/export-openapi?locale=zh-CN
Header: Authorization: Bearer {Token}  +  X-Apifox-Api-Version: 2024-03-28
Body: {"scope":{"type":"ALL"},"oasVersion":"3.1","exportFormat":"JSON","moduleId":{模块ID}}

注册方式(命令指向 venv python,args ["-m","src.main"]):

  • Claude Code:claude mcp add <名称> -- <venv python> -m src.main(用 --env 传四件套)

  • Codex / Gemini CLI:codex mcp add ... / gemini mcp add ...

  • Cursor / Windsurf / WorkBuddy:写入对应 mcp.json / mcp_config.jsonmcpServers 条目)

  • 项目下 .mcp.json:合并写入

  • zcode(本机客户端):写 workspace 级 <repo>/.zcode/config.json

{
  "mcp": {
    "servers": {
      "管理侧接口 API 文档": {
        "command": "<venv python 绝对路径>",
        "args": ["-m", "src.main"],
        "env": {
          "APIFOX_TOKEN": "<Token>",
          "APIFOX_PROJECT_ID": "<你的项目ID>",
          "APIFOX_MODULE_ID": "<你的模块ID>",
          "PYTHONPATH": "<仓库根目录绝对路径>"
        }
      }
    }
  }
}

zcode 对 workspace 级 MCP 默认信任并自动连接,配置后需重启会话生效。 ⚠️ .zcode/ 含明文 token,务必加入 .gitignore

4. 验证

向 MCP 进程 stdin 发 JSON-RPC(或直接跑 scripts/send_mcp.py):

  1. initialize(protocolVersion 2024-11-05

  2. notifications/initialized

  3. tools/list → 应含 list_api_endpoints 等 22 个工具

  4. tools/calllist_api_endpoints → 能返回接口列表

⚠️ Windows 下不要用 select 读子进程 stdout(用线程+队列);手写测试脚本时子进程要继承完整系统环境env = dict(os.environ) 再叠加),否则 Python 的 _overlapped(Winsock)加载失败报 WinError 10106。 zcode 客户端本身会继承父进程环境,不受此影响。


改造记录(相对上游)

改动文件清单

文件

改动

config.py

新增 APIFOX_MODULE_ID 环境变量;统一注释风格

utils.py

新增 _build_export_payload()import_openapimoduleIddelete_unmatched 支持;统一 export_openapi / import_openapi / import_counters 封装,移除死代码

tools/api_tools.py

重写:create/update/delete 全部基于统一封装;更新走全量快照覆盖,new_path/new_method 走真实改名

tools/schema_tools.py

重写:新增 delete_schema(真实删除)与 update_schemanew_name 改名

tools/*.py(其余 6 个)

统一 export/import helper,去 emoji/序号/装饰线,统一注释与命名

main.py / __init__.py

清理入口日志与注释

scripts/

send_mcp.py 从根目录归位;移除一次性迁移脚本(modify.pycheck_tasks_map.py

核心改造点

① 按模块动态读取(config.py)

APIFOX_MODULE_ID = os.getenv("APIFOX_MODULE_ID")  # 可选,指定模块 ID 实现按模块动态读取

② 统一导出请求体(utils.py)

def _build_export_payload(scope_type: str = "ALL") -> Dict[str, Any]:
    """构建导出 OpenAPI 的请求体。配置了 APIFOX_MODULE_ID 时自动带上 moduleId,实现按模块动态导出。"""
    payload: Dict[str, Any] = {
        "scope": {"type": scope_type},
        "options": {"includeApifoxExtensionProperties": True, "addFoldersToTags": False},
        "oasVersion": "3.1",
        "exportFormat": "JSON"
    }
    if APIFOX_MODULE_ID:
        try:
            payload["moduleId"] = int(APIFOX_MODULE_ID)
        except ValueError:
            pass
    return payload

③ 导入写操作带 moduleId(api_tools / crud_tools)

# 配置了 APIFOX_MODULE_ID 时导入到指定模块,否则保持原逻辑落到默认模块
if APIFOX_MODULE_ID:
    import_payload["options"]["moduleId"] = APIFOX_MODULE_ID

⚠️ moduleId 必须放在 options 对象内——放在请求体顶层会被 Apifox 忽略, 接口会落进项目默认模块(默认模块与目标模块是两套独立实体,客户端看不到变化)。 这是曾污染默认模块的根因,务必遵守。


能力边界与踩坑记录

  1. 导入不写 moduleId → 全落默认模块:见上文改造点③,本仓库曾因此污染默认模块。

  2. 参数名targetEndpointFolderId / targetSchemaFolderId 是正确参数名(与上游 Go CLI 一致),endpointFolderId 也能用,二者皆可。

  3. security(鉴权)写不进 token 值:import 对 security 只做方案关联(schemeGroups 引用 bearerAuth),authConfigs.token具体值写不进去(合并保留旧值/置空)。token 值请在客户端用「继承」+ 环境变量({{bearerToken}} / {{refreshToken}})实现。注意:刷新 token 类接口用 {{refreshToken}},其余用 {{bearerToken}};登录类接口无需鉴权。

  4. 删除/改名能力(v2 新增,基于"全量快照 + deleteUnmatchedResources"):官方开放 API 无独立删除端点,但 import-openapi 支持 deleteUnmatchedResources: true(删除导入源中不存在的接口/模型)。本版据此实现了真实删除与改名:

    • delete_api_endpoint:导出全量快照 → 移除目标接口 → 全量回导(其余接口原样保留)

    • update_api_endpointnew_path/new_method:导出全量 → 删旧建新 → 全量回导(即"改名")

    • delete_schema / update_schemanew_name:同样基于全量快照

    • ⚠️ 安全红线:这类操作必须基于 export_openapi 的全量结果修改,严禁手工拼一个残缺快照再 delete——那会连带删除快照里没有的接口与模型。所有删除/改名工具都带 confirm=True 二次确认。

    • ⚠️ 模块范围deleteUnmatchedResources 的作用范围与导出/导入一致;配置了 APIFOX_MODULE_ID 时只影响该模块,未配置时作用于整个项目,多模块项目务必先确认作用域。

  5. update 不再有"改路径即新建"陷阱(v2 已修复):旧版 update_api_endpointnew_path 会被当成新端点新建、旧端点残留(公开 API 无删除能力时只能客户端清理)。v2 起:

    • 只传 path+method(不含 new_path/new_method)→ 全量快照 + 原位覆盖(保留目录位置)

    • 传了 new_path / new_method → 全量快照 + 改名(旧端点删除,创建新端点)

    • 改名后如需改路径模板参数名(如 {taskId} → {taskCode}),直接体现在 new_path 字符串里即可生效,不再产生副本

  6. 客户端看到旧数据:MCP 摘要/详情接口导出时带 moduleId,Apifox 服务端对该参数组合有导出缓存;不带 moduleId 的导出是准的。客户端刷新(Cmd/Ctrl+R)可强制更新。

  7. 数据模型 id 分段:目标模块与默认模块的数据模型 id 段不同,清理时认 id 段,别误删。

上游能力边界(源自上游 README / AGENTS / SKILL)

  • 上游官方主推 Go CLIcmd/apifox-cli),Python MCP 包为 legacy 兼容层;本仓库专注 Python 版。

  • 上游 import-openapi 的 options 参数名:targetEndpointFolderId / targetSchemaFolderId


收尾自查清单

  • 服务器名(探测出的模块名 + " API 文档")

  • 配置写入位置(哪个工具/文件)与是否需重启/信任

  • 导入类工具带 options.moduleId

  • 仓库无明文 token(grep -r "afxp_" . 应无命中)


License

MIT(上游同源)。