Feat support mcp registry api#13376
Conversation
|
Thanks for your this PR. 🙏 感谢您提交的PR。 🙏 |
新增MCP注册API支持多版本管理及前端界面优化变更文件
时序图sequenceDiagram
participant MC as McpRegistryController
participant MS as McpServerOperationService
participant MI as McpServerMemoryIndex
participant CD as ConfigDetailService
MC->>MS: listMcpServers()
MS->>MI: searchMcpServerByName()
MI-->>MS: 返回索引数据
MS->>CD: 查询配置详情
CD-->>MS: 配置内容
MS-->>MC: 返回服务器列表
sequenceDiagram
participant MD as McpDetail
participant MS as McpServerOperationService
MD->>MS: getMcpServerDetail()
MS->>MI: 获取索引信息
MI-->>MS: 返回服务器元数据
MS->>CD: 查询版本配置
CD-->>MS: 返回版本详情
MS-->>MD: 返回完整服务器信息
💡 小贴士与 lingma-agents 交流的方式📜 直接回复评论
📜 在代码行处标记
📜 在讨论中提问
|
There was a problem hiding this comment.
🔍 代码评审报告
🎯 评审意见概览
| 严重度 | 数量 | 说明 |
|---|---|---|
| 🔴 Blocker | 4 | 阻断性问题,需立即修复。例如:系统崩溃、关键功能不可用或严重安全漏洞。 |
| 🟠 Critical | 3 | 严重问题,高优先级修复。例如:核心功能异常或性能瓶颈影响用户体验。 |
| 🟡 Major | 15 | 主要问题,建议修复。例如:非核心功能缺陷或代码维护性较差。 |
| 🟢 Minor | 8 | 次要问题,酌情优化。例如:代码格式不规范或注释缺失。 |
总计: 30 个问题
⚠️ **需要立即关注的阻断性问题**
ai/src/main/java/com/alibaba/nacos/ai/form/mcp/admin/McpForm.java
- 参数验证逻辑缺失可能导致无效数据 (L43)
ai/src/main/java/com/alibaba/nacos/ai/utils/McpRequestUtil.java
- 导入语句未同步修改导致编译错误 (L19)
api/src/main/java/com/alibaba/nacos/api/ai/model/mcp/McpServerBasicInfo.java
- 删除version字段后未处理遗留方法调用 (L43)
console-ui/src/pages/AI/McpDetail/McpDetail.js
- API参数拼写错误可能导致接口调用失败 (L46)
📋 评审意见详情
💡 单文件建议
以下是文件级别的代码建议,聚焦于代码的可读性、可维护性和潜在问题。
☕ ai/src/main/java/com/alibaba/nacos/ai/controller/McpRegistryController.java (2 💬)
- 使用硬编码字符串替代常量可能导致配置不一致 (L63)
- API接口缺少权限验证注解 (L40)
☕ ai/src/main/java/com/alibaba/nacos/ai/form/mcp/admin/McpForm.java (1 💬)
- 参数验证逻辑缺失可能导致无效数据 (L43)
☕ ai/src/main/java/com/alibaba/nacos/ai/index/McpServerMemoryIndex.java (3 💬)
- 使用System.out.println进行日志输出不符合规范 (L51)
- 分页逻辑存在潜在越界风险 (L79)
- 初始化索引时未处理异常可能导致服务启动失败 (L37)
☕ ai/src/main/java/com/alibaba/nacos/ai/service/McpEndpointOperationService.java (1 💬)
- 修复创建MCP服务时错误使用命名空间ID的问题 (L85)
☕ ai/src/main/java/com/alibaba/nacos/ai/model/mcp/McpServerIndexData.java (1 💬)
- 为字段添加Javadoc注释以提高代码可维护性 (L4-L6)
☕ ai/src/main/java/com/alibaba/nacos/ai/service/McpServerOperationService.java (3 💬)
- 日期格式字符串应提取为常量以提高代码可维护性 (L220-L221)
- 未检查版本列表为空时的索引越界风险 (L130-L131)
- 分页参数计算存在潜在越界风险 (L97)
☕ ai/src/main/java/com/alibaba/nacos/ai/service/McpToolOperationService.java (1 💬)
- 未对删除操作的参数进行有效性验证 (L77)
☕ ai/src/main/java/com/alibaba/nacos/ai/utils/McpRequestUtil.java (1 💬)
- 导入语句未同步修改导致编译错误 (L19)
☕ api/src/main/java/com/alibaba/nacos/api/ai/constant/AiConstants.java (1 💬)
- 命名空间常量值变更需同步前端配置 (L28)
☕ api/src/main/java/com/alibaba/nacos/api/ai/model/mcp/McpServerBasicInfo.java (1 💬)
- 删除version字段后未处理遗留方法调用 (L43)
☕ api/src/main/java/com/alibaba/nacos/api/ai/model/mcp/registry/McpRegistryServer.java (1 💬)
- 变量命名不符合驼峰规范 (L7)
☕ api/src/main/java/com/alibaba/nacos/api/ai/model/mcp/registry/Remote.java (1 💬)
- 变量命名不符合驼峰规范 (L5)
📜 console-ui/src/components/NameSpaceList/NameSpaceList.js (1 💬)
- 生产代码中包含调试日志 (L204)
☕ api/src/main/java/com/alibaba/nacos/api/ai/model/mcp/registry/Repository.java (1 💬)
- 空类未添加注释说明 (L3)
☕ api/src/main/java/com/alibaba/nacos/api/ai/model/mcp/McpServerVersionInfo.java (1 💬)
- 方法名与字段名不一致 (L19)
📜 console-ui/src/locales/zh-CN.js (1 💬)
- 重复的翻译条目可能导致显示错误 (L881-L882)
📜 console-ui/src/pages/AI/McpDetail/CreateTools/index.js (3 💬)
- 未使用的导入语句增加维护成本 (L18)
- 未验证的props可能导致运行时错误 (L23-L30)
- 未清理的调试代码影响代码清晰度 (L50-L62)
📜 console-ui/src/pages/AI/McpDetail/McpDetail.js (1 💬)
- API参数拼写错误可能导致接口调用失败 (L46)
📜 console-ui/src/pages/AI/McpManagement/McpManagement.js (2 💬)
- 硬编码的搜索参数应改为配置或常量 (L275)
- 删除操作缺少错误处理机制 (L508)
📜 console-ui/src/pages/AI/NewMcpServer/NewMcpServer.js (3 💬)
- 修复协议类型参数传递不一致问题 (L151-L154)
- 修复表单验证正则表达式逻辑错误 (L291-L293)
- 移除废弃的命名空间选择功能 (L561-L563)
🚀 跨文件建议
以下是对代码架构和设计的综合分析,聚焦于跨文件交互、系统一致性和潜在优化空间。
🔍 1. 接口参数不一致导致客户端适配困难
MCP管理接口和注册接口使用不同的分页参数(pageNo/pageSize vs offset/limit),且版本参数传递方式不一致(McpForm的version字段与McpDetailForm的versionDetail嵌套结构)。这种参数设计差异会导致客户端需要处理两种不同的API规范,增加维护成本。
📌 关键代码:
pageForm.getPageNo(), pageForm.getPageSize()))offset / limit, limit)🔍 2. 未验证的版本参数引发安全漏洞
McpRegistryController的getServer接口未对版本参数进行有效性验证,允许客户端任意指定版本获取服务详情。若存在未发布的版本,可能泄露未公开的配置信息。
📌 关键代码:
McpServerDetailInfo mcpServerDetail = mcpServerOperationService.getMcpServerDetail(Strings.EMPTY, id, getServerForm.getVersion());🔍 3. ID与名称双重标识体系存在数据不一致风险
McpForm同时维护id和mcpName字段,但McpServerBasicInfo使用id作为主键而保留name字段。这种双重标识体系可能导致数据不一致,特别是在名称变更时无法通过ID定位资源。
📌 关键代码:
private String id; private String mcpName;private String id; private String name;🔍 4. 内存索引未实现集群一致性
McpServerMemoryIndex作为单例内存缓存,未考虑分布式集群环境下的数据同步问题。当多个节点同时修改数据时,缓存数据可能不一致,导致查询结果错误。
📌 关键代码:
@Service public class McpServerMemoryIndex implements McpServerIndex {🔍 5. 版本控制逻辑存在设计缺陷
McpServerVersionInfo的versions字段与versionDetails字段命名冲突,且版本发布逻辑未限制只能发布最新版本。允许任意版本覆盖可能导致版本回滚风险。
📌 关键代码:
private List<ServerVersionDetail> versions;🔍 6. 跨服务数据模型不一致
McpServerBasicInfo保留version字段而改用versionDetail嵌套结构,但旧代码如McpController仍使用version字段,存在字段含义不一致问题。
📌 关键代码:
private ServerVersionDetail versionDetail;mcpProxy.getMcpServer(mcpForm.getNamespaceId(), mcpForm.getMcpName(), mcpForm.getVersion());🔍 7. 删除操作未实现原子性
McpServerOperationService的deleteMcpServer方法分多次删除不同版本的数据,但未使用事务机制。中途失败可能导致数据残留或不一致状态。
📌 关键代码:
for (String versionNeedDelete : versionsNeedDelete) {🔍 8. 跨层数据转换未做类型校验
McpRequestUtil的parseMcpServerBasicInfo等方法直接转换表单数据,未对JSON结构进行完整性校验。非法输入可能导致运行时异常或数据损坏。
📌 关键代码:
BeanUtils.copyProperties(serverSpecification, newSpecification);🔍 9. 版本控制缺少变更审计
版本发布和删除操作未记录变更日志,无法追溯版本变更的历史记录和责任人,不符合企业级系统审计要求。
🔍 10. 协议转换缺少兼容性设计
HTTP转MCP服务功能未与Higress组件实现解耦,硬编码依赖文档说明而非程序化验证,可能导致配置错误时无法及时发现。
📌 关键代码:
restToMcpNeedHigress: '存量http服务转化为MCP服务需要搭配higress使用,请参考文档'💡 小贴士
与 lingma-agents 交流的方式
📜 直接回复评论
直接回复本条评论,lingma-agents 将自动处理您的请求。例如:
-
在当前代码中添加详细的注释说明。
-
请详细介绍一下你说的 LRU 改造方案,并使用伪代码加以说明。
📜 在代码行处标记
在文件的特定位置创建评论并 @lingma-agents。例如:
-
@Lingma-Agent 分析这个方法的性能瓶颈并提供优化建议。
-
@Lingma-Agent 对这个方法生成优化代码。
📜 在讨论中提问
在任何讨论中 @lingma-agents 来获取帮助。例如:
-
@Lingma-Agent 请总结上述讨论并提出解决方案。
-
@Lingma-Agent 请根据讨论内容生成优化代码。
| throws NacosException { | ||
| int limit = listServerForm.getLimit(); | ||
| int offset = listServerForm.getOffset(); | ||
| Page<McpServerBasicInfo> servers = mcpServerOperationService.listMcpServer(listServerForm.getNamespaceId(), Strings.EMPTY, "blur", offset / limit, limit); |
There was a problem hiding this comment.
使用硬编码字符串替代常量可能导致配置不一致
🟡 Major | 🧹 Code Smells
📋 问题详情
在listMcpServers方法中,参数search传入了硬编码字符串'blur',而Constants类中已定义MCP_LIST_SEARCH_ACCURATE和MCP_LIST_SEARCH_BLUR常量。直接使用字符串字面量违反了代码标准化原则,可能导致后续维护时出现配置不一致问题。
💡 解决方案
将硬编码字符串替换为Constants.MCP_LIST_SEARCH_BLUR常量
- "blur"
+ Constants.MCP_LIST_SEARCH_BLUR您的反馈对我们很重要!(建议右键在新标签页中打开以下链接)
| * @author xinluo | ||
| */ | ||
| @NacosApi | ||
| @RestController |
There was a problem hiding this comment.
| private String namespaceId; | ||
|
|
||
| private String version; | ||
|
|
There was a problem hiding this comment.
参数验证逻辑缺失可能导致无效数据
🔴 Blocker | 🐞 Bugs
📋 问题详情
在validate方法中移除了对mcpName的验证,但该字段通过setId接收值。当客户端未传入id参数时,会导致后续服务端操作出现空指针或无效参数错误。需要恢复必要的参数验证逻辑。
💡 解决方案
补充参数有效性检查
+ if (StringUtils.isEmpty(id)) {
+ throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING, "Required parameter 'id' type String is not present");
+ }您的反馈对我们很重要!(建议右键在新标签页中打开以下链接)
| id2InfoCache.put(versionInfo.getId(), data); | ||
| } | ||
| } | ||
| System.out.println("Init index " + JacksonUtils.toJson(id2InfoCache)); |
There was a problem hiding this comment.
使用System.out.println进行日志输出不符合规范
🟡 Major | 🧹 Code Smells
📋 问题详情
在initIndex和addIndex方法中使用System.out.println输出调试信息,这在生产环境会导致日志不可控。应替换为合适的日志框架(如log4j)实现标准化日志记录。
💡 解决方案
替换为log4j日志输出
- System.out.println(...)
+ logger.info("Init index: {}", JacksonUtils.toJson(id2InfoCache));您的反馈对我们很重要!(建议右键在新标签页中打开以下链接)
| }).sorted(Comparator.comparing(McpServerIndexData::getId)).toList(); | ||
|
|
||
| Page<McpServerIndexData> result = new Page<>(); | ||
| int end = Math.min(limit, allServers.size()); |
There was a problem hiding this comment.
分页逻辑存在潜在越界风险
🟡 Major | 🐞 Bugs
📋 问题详情
searchMcpServerByName方法中分页计算存在错误:当offset+limit超过列表长度时,subList(offset, end)可能引发IndexOutOfBoundsException。当前end计算方式未考虑总长度,应修正为offset+limit
💡 解决方案
修正分页索引计算
- int end = Math.min(limit, allServers.size());
+ int end = Math.min(offset + limit, allServers.size());您的反馈对我们很重要!(建议右键在新标签页中打开以下链接)
| {!this.state.restToMcpSwitch && ( | ||
| <FormItem label={locale.exportPath} required help={locale.exportPathDesc}> | ||
| <Input |
There was a problem hiding this comment.
修复服务暴露路径显示条件错误
🟡 Major | 🧹 Code Smells
📋 问题详情
exportPath表单项的显示条件依赖restToMcpSwitch状态,当选择非stdio协议但未开启转换时,必要字段可能被隐藏导致表单验证失败
💡 解决方案
- {!this.state.restToMcpSwitch && (
+ {['mcp-sse', 'mcp-streamble'].includes(this.state.frontProtocol) && (根据协议类型正确控制暴露路径显示条件
您的反馈对我们很重要!(建议右键在新标签页中打开以下链接)
| versionDetail: { | ||
| version: values?.version || '1.0.0', | ||
| }, |
There was a problem hiding this comment.
| public void updateMcpServer(String namespaceId, String mcpName, boolean isPublish, McpServerBasicInfo serverSpecification, | ||
| McpToolSpecification toolSpecification, McpEndpointSpec endpointSpecification) throws NacosException { | ||
| clientHolder.getAiMaintainerService() | ||
| .updateMcpServer(mcpName, serverSpecification, toolSpecification, endpointSpecification); | ||
| } | ||
|
|
||
| @Override | ||
| public void deleteMcpServer(String namespaceId, String mcpName) throws NacosException { | ||
| public void deleteMcpServer(String namespaceId, String mcpName, String version) throws NacosException { |
There was a problem hiding this comment.
更新MCP服务器时未传递新添加的isPublish参数
🟠 Critical | 🐞 Bugs
📋 问题详情
在McpRemoteHandler的updateMcpServer方法中,调用AiMaintainerService的updateMcpServer时未传递新增的isPublish参数。原接口需要该参数,可能导致功能缺失或逻辑错误。
💡 解决方案
需要将isPublish参数加入调用:
+ clientHolder.getAiMaintainerService().updateMcpServer(mcpName, isPublish, serverSpecification, toolSpecification, endpointSpecification);您的反馈对我们很重要!(建议右键在新标签页中打开以下链接)
| ServerVersionDetail versionDetail = new ServerVersionDetail(); | ||
| versionDetail.setVersion(version); | ||
| serverSpec.setVersionDetail(versionDetail); |
There was a problem hiding this comment.
版本信息封装不完整可能导致数据丢失
🟡 Major | 🧹 Code Smells
📋 问题详情
在createLocalMcpServer和createRemoteMcpServer方法中,将version设置到ServerVersionDetail对象后,未处理该对象的其他必要字段。需要确保ServerVersionDetail的其他字段(如描述、创建时间等)也被正确初始化,否则可能引发数据不完整问题。
💡 解决方案
建议补充必要字段的初始化:
+ versionDetail.setDescription("Initial version");
+ versionDetail.setCreateTime(System.currentTimeMillis());您的反馈对我们很重要!(建议右键在新标签页中打开以下链接)
| public Result<String> deleteMcpServer(McpForm mcpForm) throws NacosException { | ||
| mcpForm.validate(); | ||
| mcpProxy.deleteMcpServer(mcpForm.getNamespaceId(), mcpForm.getMcpName()); | ||
| mcpProxy.deleteMcpServer(mcpForm.getNamespaceId(), mcpForm.getMcpName(), mcpForm.getVersion()); |
There was a problem hiding this comment.
删除MCP服务器时未验证版本参数有效性
🟡 Major | 📝 Reliability
📋 问题详情
在deleteMcpServer方法中,直接使用mcpForm.getVersion()参数,但未做空值或格式校验。若版本参数无效可能导致服务器删除操作失败或数据不一致。
💡 解决方案
建议添加参数校验:
+ if (StringUtils.isEmpty(mcpForm.getVersion())) {
+ throw new IllegalArgumentException("Version is required");
+ }您的反馈对我们很重要!(建议右键在新标签页中打开以下链接)
* Feat support mcp registry api (#13376) * Support tag fuzzy search (#13387) * support tag fuzzy search * support tag fuzzy search * Merge pull request #13391 from luoxiner/support-mcp-multi-version Feat Support Mcp Registry * Add copyright for mcp-adapter pom. * Support version in ai maintainer sdk and fix some errors when build (#13401) * add version for ai maintainer sdk and support display mcp server config * fix pmd errors * fix empty endpoint * remote publish api * fix tag fuzzy search sql unit test (#13402) * Fix unit test. --------- Co-authored-by: Xin Luo <65529035+luoxiner@users.noreply.github.com> Co-authored-by: Sunrisea <49605583+Sunrisea@users.noreply.github.com> Co-authored-by: luoxin.luo <luoxin.luo@alibaba-inc.com>
Please do not create a Pull Request without creating an issue first.
What is the purpose of the change
Feat support mcp registry api
Brief changelog
Verifying this change
XXXX
Follow this checklist to help us incorporate your contribution quickly and easily:
[ISSUE #123] Fix UnknownException when host config not exist. Each commit in the pull request should have a meaningful subject line and body.mvn -B clean package apache-rat:check findbugs:findbugs -Dmaven.test.skip=trueto make sure basic checks pass. Runmvn clean install -DskipITsto make sure unit-test pass. Runmvn clean test-compile failsafe:integration-testto make sure integration-test pass.