zhou zhou
13 小时以前 ffbf67765d2ae447d62333eed85100a15685d781
rsf-server/src/main/java/com/vincent/rsf/server/ai/service/impl/BuiltinMcpToolRegistryImpl.java
@@ -2,6 +2,7 @@
import com.vincent.rsf.framework.exception.CoolException;
import com.vincent.rsf.server.ai.config.AiDefaults;
import com.vincent.rsf.server.ai.dto.AiMcpToolPreviewDto;
import com.vincent.rsf.server.ai.entity.AiMcpMount;
import com.vincent.rsf.server.ai.service.BuiltinMcpToolRegistry;
import com.vincent.rsf.server.ai.tool.RsfWmsBaseTools;
@@ -15,7 +16,9 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@Service
@RequiredArgsConstructor
@@ -41,21 +44,52 @@
        validateBuiltinCode(builtinCode);
        if (AiDefaults.MCP_BUILTIN_RSF_WMS.equals(builtinCode)) {
            List<ToolCallback> callbacks = new ArrayList<>();
            callbacks.addAll(Arrays.asList(ToolCallbacks.from(rsfWmsStockTools)));
            callbacks.addAll(Arrays.asList(ToolCallbacks.from(rsfWmsTaskTools)));
            callbacks.addAll(Arrays.asList(ToolCallbacks.from(rsfWmsBaseTools)));
            callbacks.addAll(createValidatedCallbacks(rsfWmsStockTools, AiDefaults.MCP_BUILTIN_RSF_WMS_STOCK));
            callbacks.addAll(createValidatedCallbacks(rsfWmsTaskTools, AiDefaults.MCP_BUILTIN_RSF_WMS_TASK));
            callbacks.addAll(createValidatedCallbacks(rsfWmsBaseTools, AiDefaults.MCP_BUILTIN_RSF_WMS_BASE));
            return callbacks;
        }
        if (AiDefaults.MCP_BUILTIN_RSF_WMS_STOCK.equals(builtinCode)) {
            return Arrays.asList(ToolCallbacks.from(rsfWmsStockTools));
            return createValidatedCallbacks(rsfWmsStockTools, builtinCode);
        }
        if (AiDefaults.MCP_BUILTIN_RSF_WMS_TASK.equals(builtinCode)) {
            return Arrays.asList(ToolCallbacks.from(rsfWmsTaskTools));
            return createValidatedCallbacks(rsfWmsTaskTools, builtinCode);
        }
        if (AiDefaults.MCP_BUILTIN_RSF_WMS_BASE.equals(builtinCode)) {
            return Arrays.asList(ToolCallbacks.from(rsfWmsBaseTools));
            return createValidatedCallbacks(rsfWmsBaseTools, builtinCode);
        }
        throw new CoolException("不支持的内置 MCP 编码: " + builtinCode);
    }
    @Override
    public List<AiMcpToolPreviewDto> listBuiltinToolCatalog(String builtinCode) {
        validateBuiltinCode(builtinCode);
        if (AiDefaults.MCP_BUILTIN_RSF_WMS.equals(builtinCode)) {
            List<AiMcpToolPreviewDto> catalog = new ArrayList<>();
            catalog.addAll(catalogByBuiltinCode(AiDefaults.MCP_BUILTIN_RSF_WMS_STOCK).values());
            catalog.addAll(catalogByBuiltinCode(AiDefaults.MCP_BUILTIN_RSF_WMS_TASK).values());
            catalog.addAll(catalogByBuiltinCode(AiDefaults.MCP_BUILTIN_RSF_WMS_BASE).values());
            return catalog;
        }
        return new ArrayList<>(catalogByBuiltinCode(builtinCode).values());
    }
    private List<ToolCallback> createValidatedCallbacks(Object toolBean, String builtinCode) {
        List<ToolCallback> callbacks = Arrays.asList(ToolCallbacks.from(toolBean));
        Map<String, AiMcpToolPreviewDto> catalog = catalogByBuiltinCode(builtinCode);
        for (ToolCallback callback : callbacks) {
            if (callback == null || callback.getToolDefinition() == null) {
                continue;
            }
            String toolName = callback.getToolDefinition().name();
            if (!StringUtils.hasText(toolName) || !toolName.startsWith("rsf_query_")) {
                throw new CoolException("内置工具命名不符合规范,必须以 rsf_query_ 开头: " + toolName);
            }
            if (!catalog.containsKey(toolName)) {
                throw new CoolException("内置工具缺少治理目录配置: " + toolName);
            }
        }
        return callbacks;
    }
    private List<String> supportedBuiltinCodes() {
@@ -66,4 +100,80 @@
                AiDefaults.MCP_BUILTIN_RSF_WMS_BASE
        );
    }
    private Map<String, AiMcpToolPreviewDto> catalogByBuiltinCode(String builtinCode) {
        if (AiDefaults.MCP_BUILTIN_RSF_WMS_STOCK.equals(builtinCode)) {
            Map<String, AiMcpToolPreviewDto> catalog = new LinkedHashMap<>();
            catalog.put("rsf_query_available_inventory", buildCatalogItem(
                    "rsf_query_available_inventory",
                    "库存查询",
                    "查询指定物料当前可用于出库的库存明细。",
                    "必须提供物料编码或物料名称,并且最多返回 50 条库存记录。",
                    List.of("查询物料 MAT001 当前可出库库存", "按物料名称查询托盘库存明细")
            ));
            catalog.put("rsf_query_station_list", buildCatalogItem(
                    "rsf_query_station_list",
                    "库存查询",
                    "查询指定作业类型可用的设备站点。",
                    "必须提供站点类型列表,类型数量最多 10 个,最多返回 50 个站点。",
                    List.of("查询入库和出库作业可用站点", "列出 AGV_PICK 类型的作业站点")
            ));
            return catalog;
        }
        if (AiDefaults.MCP_BUILTIN_RSF_WMS_TASK.equals(builtinCode)) {
            Map<String, AiMcpToolPreviewDto> catalog = new LinkedHashMap<>();
            catalog.put("rsf_query_task_list", buildCatalogItem(
                    "rsf_query_task_list",
                    "任务查询",
                    "按任务号、状态、类型或站点条件查询任务列表。",
                    "至少提供一个过滤条件,最多返回 50 条任务记录,不支持全表扫描。",
                    List.of("查询最近 10 条状态为执行中的任务", "按任务号关键字查询任务列表")
            ));
            catalog.put("rsf_query_task_detail", buildCatalogItem(
                    "rsf_query_task_detail",
                    "任务查询",
                    "按任务 ID 或任务号查询单个任务详情。",
                    "必须提供任务 ID 或任务号之一,只返回单个任务。",
                    List.of("查询任务 12345 的详情", "根据任务号 TASK24001 查看执行明细")
            ));
            return catalog;
        }
        if (AiDefaults.MCP_BUILTIN_RSF_WMS_BASE.equals(builtinCode)) {
            Map<String, AiMcpToolPreviewDto> catalog = new LinkedHashMap<>();
            catalog.put("rsf_query_warehouses", buildCatalogItem(
                    "rsf_query_warehouses",
                    "基础资料",
                    "查询仓库基础信息。",
                    "至少提供仓库编码或名称,最多返回 50 条仓库记录。",
                    List.of("查询编码包含 WH 的仓库", "按仓库名称查询仓库地址")
            ));
            catalog.put("rsf_query_bas_stations", buildCatalogItem(
                    "rsf_query_bas_stations",
                    "基础资料",
                    "查询基础站点信息。",
                    "至少提供站点编号、站点名称或使用状态之一,最多返回 50 条站点记录。",
                    List.of("查询使用中的基础站点", "按站点编号查询基础站点")
            ));
            catalog.put("rsf_query_dict_data", buildCatalogItem(
                    "rsf_query_dict_data",
                    "基础资料",
                    "查询指定字典类型下的字典数据。",
                    "必须提供字典类型编码,最多返回 100 条字典记录。",
                    List.of("查询 task_status 字典", "按字典标签过滤 task_type 字典数据")
            ));
            return catalog;
        }
        throw new CoolException("不支持的内置 MCP 编码: " + builtinCode);
    }
    private AiMcpToolPreviewDto buildCatalogItem(String name, String toolGroup, String toolPurpose,
                                                 String queryBoundary, List<String> exampleQuestions) {
        return AiMcpToolPreviewDto.builder()
                .name(name)
                .toolGroup(toolGroup)
                .toolPurpose(toolPurpose)
                .queryBoundary(queryBoundary)
                .exampleQuestions(exampleQuestions)
                .build();
    }
}