Day 15 / 共 20 天 · 第 3 周 AI/插件/消费者

MCP Server 管理

第 3 周收官。MCP(Model Context Protocol)让大模型能调用外部工具。今天看 Console 怎么管理 MCP Server:三种类型、双策略工厂(开闭原则的漂亮范例),以及它"不是独立 CRD"的存储设计。

📍 你在整门课的位置 · 第 3 周 AI/插件/消费者(Day 11-15,本周收官)
D11 AI供应商/路由 D12 插件管理 D13 消费者鉴权 D14 路由/服务源 D15 MCP管理
L01

MCP 是什么

🤔 痛点:大模型只会"聊天",不会干活 你问大模型"我 3 号的订单到哪了?"——它没法真的去查你的订单数据库,只能编。要让它真正"动手查、调 API",得给它一套能调用的工具,还得是它认识的标准格式。
💡 本质:给大模型配一个"工具箱适配器" MCP(Model Context Protocol)是一套让大模型"调用工具"的标准协议——就像给电器配一个通用转接头,任何 API/数据库经过它包装后,大模型都能直接"插上就用"。Higress 负责把你现成的 REST API / 数据库包装成 MCP 工具;Console 就是配置"把哪个东西暴露成 MCP Server"的遥控器。
📝 举个例子 输入一份订单系统的 OpenAPI/Swagger 文档 → 经 swaggerToMcpConfig 转换 → 输出一份 MCP 工具配置,里面多了个 queryOrder(orderId) 工具 → 大模型就能"调用 queryOrder 查 3 号订单"了。
用大白话讲 MCP 大模型本身只会"聊天",不会查数据库、调 API。MCP(Model Context Protocol)是一套标准,让大模型能"调用工具"——比如"帮我查订单"就去调订单 API。Higress 能把普通的 REST API / 数据库"包装"成 MCP 工具,让大模型直接用。Console 的 MCP 管理就是配置"把哪个 API/数据库暴露成 MCP Server 给大模型用"。(上一站 Higress 的 mcp-server 插件是底层实现。)
L02

McpServerController 8 端点

controller/mcp/McpServerController.java/v1/mcpServer:53-57,注入 McpServerService + McpServerHelper):

POST /swaggerToMcpConfig   :65   // Swagger/OpenAPI → MCP 工具配置
PUT  /                     :73   // addOrUpdateWithAuthorization
GET  /                     :82   // list
GET  /{name}               :90
DELETE /{name}             :98
PUT  /consumers            :107  // 加允许的消费者
DELETE /consumers          :117
GET  /consumers            :127
L03

三种 MCP 类型

McpServerTypeEnumsdk/model/mcp/):

  • OPEN_API:把 REST API 转成 MCP 工具,走 mcp-server Wasm 插件。
  • DATABASE:把数据库暴露成固定的工具集(query / execute / list tables / describe table)。
  • DIRECT_ROUTE:上游本身就是 MCP 服务,只做直路由/重写。
读法:三种类型 = 三种"把什么东西包成 MCP"的来源:现成的 REST API、数据库、本来就是 MCP 的服务。McpServerDBTypeEnum 支持 mysql/postgres/sqlite/clickhouse。
L04

双策略工厂(本课设计亮点)

👶 小白 vs 👨‍🏫 老师 👶:三种 MCP 类型的保存逻辑不同,为什么不写一个 if type==OPEN_API … else if … 就完了?
👨‍🏫:能跑,但每加一种类型就要回去改那个大方法,越改越乱、越容易改坏别人。
👶:那"策略工厂"好在哪?
👨‍🏫:每种类型一个策略类,工厂用 support() 挑出匹配的那个。加第四种类型 = 新增一个策略类 + 注册,老代码一行不动——这就是开闭原则(对扩展开放、对修改关闭)。回想 Day 11 的 Handler 注册表,是同一招。

McpServiceContextImpl.java:67)构造时装配两个工厂(:85-87):McpServerSaveStrategyFactory(保存)和 McpServerDetailStrategyFactory(查详情)。

保存策略(mcp/save/):工厂用 getService(McpServer) 遍历各策略的 support() 找到匹配的。三种实现:OpenApiSaveStrategy / DatabaseSaveStrategy / DirectRoutingSaveStrategy。详情策略(mcp/detail/)对称三个。

为什么用"策略工厂"? 三种 MCP 类型的保存/查询逻辑完全不同。与其在一个大方法里 if type==OPEN_API...else if type==DATABASE...,不如每种类型一个策略类,工厂按类型挑选。加第四种类型 = 加一个策略类 + 注册,老代码不动——这就是开闭原则(对扩展开放、对修改关闭)。基类 save = saveRoute + saveMcpServerConfigsaveWithAuthorization 再加 saveAuthInfo
L05

存储 = Route + ConfigMap(非独立 CRD)

OPEN_API DATABASE DIRECT_ROUTE 三种类型 SaveStrategyFactory按 support() 挑策略 内部 Route(Ingress)前缀 mcp-server- higress-config ConfigMapmcpServer 段 MCP Server 不是独立 CRD,而是"Route + ConfigMap 段"复用现有资源
三种类型 → 工厂挑策略 → 落成"内部 Route + ConfigMap 的 mcpServer 段"。DIRECT_ROUTE 类型只重写路由、不写 ConfigMap。

MCP Server 不是独立 CRD,而是"内部 Route(底层 Ingress,前缀 mcp-server-)+ higress-config ConfigMap 的 mcpServer 段"。McpServiceContextImpl:query(:101-111)、list(:113-130,label higress.io/resource-biz-type=mcp-server)、delete(:132-137)。

McpServerConfigMapHelper.updateMcpConfig2ConfigMap:146-224增量合并不覆盖用户字段;data key higress,段 mcpServer(含 sse_path_suffix=/sseenable、redis 占位、match_listservers)。

读法:又一次"复用现有资源而非新造 CRD":一条路由承载流量入口,ConfigMap 段承载 MCP 特有配置。DIRECT_ROUTE 类型保存时不写 ConfigMap,只重写上游 SSE 路径、从 McpBridge 查 DNS 域名做 host 重写——呼应 Day 14 的 McpBridge。
L06

Swagger → MCP 转换

McpServerHelper.swaggerToMcpConfig:65-113)通过 ProcessBuilder 调外部脚本 openapiToMcpserver.sh(Day 19 会看到它被打进 Docker 镜像),把 OpenAPI 文档转成 MCP 工具配置,并带命令注入防护 trimCmdWithCh:115-130)。

为什么调外部脚本而不用 Java 写? "OpenAPI → MCP 工具"的转换逻辑用 Go 写成了一个独立小工具(跨语言复用)。Java 后端直接用 ProcessBuilder 启动这个进程、传入 OpenAPI、读回结果——不重复造轮子。trimCmdWithCh 是安全护栏:拼命令行时过滤危险字符,防"命令注入"攻击(别人在参数里塞 ; rm -rf 之类)。
L07

MCP 消费者

MCP 也能配"谁能访问"。addAllowConsumers/deleteAllowConsumers:139-153)最终落到该 MCP 对应 Route 的 key-auth allow list(ADD/REMOVE),保存时 saveAuthInfo 用 REPLACE 全量替换。无独立存储

读法:看,又回到 Day 13 的 allow list 机制!MCP 的鉴权复用了消费者那套 key-auth allow list——整个 Console 的鉴权只有一套底层机制。模型 ConsumerAuthInfo(type/enable/allowedConsumers)承载这些信息。
L08

今日小结 + 动手(第 3 周收官)

🧠 第 3 周你应该能回答

  • MCP 是什么?三种类型分别包装什么?
  • 双策略工厂怎么体现开闭原则?
  • MCP Server 存储为什么不是独立 CRD?
  • Swagger→MCP 为什么调外部脚本?命令注入怎么防?
  • MCP 鉴权和消费者鉴权是不是一套机制?

✋ 动手

cd /Users/bitmart/work/codes/github/higress-group/higress-console/backend
find . -path '*/service/mcp/*' -name '*.java' | head -30
sed -n '65,130p' sdk/src/main/java/com/alibaba/higress/sdk/service/mcp/McpServerHelper.java 2>/dev/null || \
  grep -rn "swaggerToMcpConfig\|trimCmdWithCh" sdk/
下周预告 · 第 4 周:切到 前端与部署——React/ice.js 技术栈、页面与路由、最精华的"从 JSONSchema 动态渲染插件表单"、以及 Docker/Helm 部署闭环和全课收官。
← Day 14 Day 16 · 前端技术栈 →