forked from kimhyungsik/ax_hub_mcp_tool
fix: align tool service routing manifest schema
All checks were successful
Deploy Tools / deploy (push) Successful in 1m24s
All checks were successful
Deploy Tools / deploy (push) Successful in 1m24s
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
mcp:
|
||||
manifest:
|
||||
routing-functions:
|
||||
- name: route_to_dat_was_cus
|
||||
description: 고객 업무 서버로 요청을 라우팅합니다.
|
||||
- name: route_to_dat-was-cus
|
||||
description-serialization: 고객 업무 서버로 요청을 라우팅합니다. 고객 정보와 고객 상담 업무를 처리합니다. 요청의 주요 엔티티와 업무 영역을 기준으로 고객 서버를 선택합니다.
|
||||
server-id: dat-was-cus
|
||||
category-key: cus
|
||||
product-boundary: insurance
|
||||
@@ -12,5 +12,5 @@ mcp:
|
||||
capabilities: [고객 조회, 고객 정보 수정, 상담 이력 조회]
|
||||
select-if: 고객 또는 상담 관련 요청인 경우
|
||||
reject-if: 계약, 상품, 시스템 운영 업무가 주된 요청인 경우
|
||||
confidence-server-ids: [dat-was-cus]
|
||||
confusable-servers: [dat-was-sal, dat-was-pro, dat-was-sys]
|
||||
decision-policy: 요청의 주요 엔티티와 업무 영역을 기준으로 고객 서버를 선택합니다.
|
||||
|
||||
@@ -39,7 +39,7 @@ public class McpProperties {
|
||||
@Data
|
||||
public static class RoutingFunction {
|
||||
private String name;
|
||||
private String description;
|
||||
private String descriptionSerialization;
|
||||
private String serverId;
|
||||
private String categoryKey;
|
||||
private String productBoundary;
|
||||
@@ -49,7 +49,7 @@ public class McpProperties {
|
||||
private List<String> capabilities = List.of();
|
||||
private String selectIf;
|
||||
private String rejectIf;
|
||||
private List<String> confidenceServerIds = List.of();
|
||||
private List<String> confusableServers = List.of();
|
||||
private String decisionPolicy;
|
||||
}
|
||||
|
||||
|
||||
@@ -65,8 +65,11 @@ public class ToolManifestService {
|
||||
public ToolServiceManifestResponse currentToolServiceManifest() {
|
||||
McpProperties.Manifest manifest = properties.getManifest();
|
||||
String bundleId = manifest == null ? null : manifest.getBundleId();
|
||||
List<McpProperties.RoutingFunction> routingFunctions = manifest == null
|
||||
List<McpProperties.RoutingFunction> configured = manifest == null
|
||||
? List.of() : defaultRoutingList(manifest.getRoutingFunctions());
|
||||
List<Map<String, Object>> routingFunctions = configured.stream()
|
||||
.map(this::toRoutingFunctionEnvelope)
|
||||
.toList();
|
||||
try {
|
||||
String source = objectMapper.writeValueAsString(Map.of("bundleId", bundleId,
|
||||
"routingFunctions", routingFunctions));
|
||||
@@ -187,10 +190,50 @@ public class ToolManifestService {
|
||||
return value == null ? List.of() : List.copyOf(value);
|
||||
}
|
||||
|
||||
private Map<String, Object> toRoutingFunctionEnvelope(McpProperties.RoutingFunction route) {
|
||||
Map<String, Object> contract = new LinkedHashMap<>();
|
||||
contract.put("schema_version", "3.0");
|
||||
contract.put("server_id", route.getServerId());
|
||||
contract.put("category_key", route.getCategoryKey());
|
||||
contract.put("product_boundary", route.getProductBoundary());
|
||||
contract.put("business_domain", route.getBusinessDomain());
|
||||
contract.put("business_outcome", route.getBusinessOutcome());
|
||||
contract.put("primary_entities", defaultList(route.getPrimaryEntities()));
|
||||
contract.put("select_if", route.getSelectIf());
|
||||
contract.put("reject_if", route.getRejectIf());
|
||||
contract.put("capability_index", defaultList(route.getCapabilities()));
|
||||
contract.put("confusable_servers", defaultList(route.getConfusableServers()));
|
||||
contract.put("decision_policy", route.getDecisionPolicy());
|
||||
|
||||
Map<String, Object> function = new LinkedHashMap<>();
|
||||
function.put("name", route.getName());
|
||||
function.put("description_serialization", routingDescription(route, contract));
|
||||
function.put("routing_contract", contract);
|
||||
function.put("parameters", emptySchema());
|
||||
|
||||
Map<String, Object> envelope = new LinkedHashMap<>();
|
||||
envelope.put("type", "function");
|
||||
envelope.put("function", function);
|
||||
return envelope;
|
||||
}
|
||||
|
||||
private String routingDescription(McpProperties.RoutingFunction route, Map<String, Object> contract) {
|
||||
try {
|
||||
return defaultString(route.getDescriptionSerialization(), String.join(" ",
|
||||
nonBlank(route.getBusinessOutcome()), nonBlank(route.getDecisionPolicy())).trim());
|
||||
} catch (Exception exception) {
|
||||
throw new IllegalStateException("Failed to serialize routing contract", exception);
|
||||
}
|
||||
}
|
||||
|
||||
private String sha256(String value) throws Exception {
|
||||
byte[] digest = MessageDigest.getInstance("SHA-256").digest(value.getBytes(StandardCharsets.UTF_8));
|
||||
StringBuilder result = new StringBuilder();
|
||||
for (byte item : digest) result.append(String.format("%02x", item));
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
private String nonBlank(String value) {
|
||||
return value == null ? "" : value.trim();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package io.shinhanlife.dat.lib.manifest;
|
||||
|
||||
import io.shinhanlife.dat.lib.config.McpProperties;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/** Server-level routing metadata loaded from tool-service-manifest.yml. */
|
||||
public record ToolServiceManifestResponse(String bundleId, String revision,
|
||||
List<McpProperties.RoutingFunction> routingFunctions) {
|
||||
List<Map<String, Object>> routingFunctions) {
|
||||
}
|
||||
|
||||
@@ -389,7 +389,7 @@ public class PodScaffolder {
|
||||
manifest:
|
||||
routing-functions:
|
||||
- name: route_to_%s
|
||||
description: %s 업무 서버로 요청을 라우팅합니다.
|
||||
description-serialization: %s 업무 서버로 요청을 라우팅합니다. %s 관련 업무를 처리합니다. 요청의 주요 업무 영역을 기준으로 서버를 선택합니다.
|
||||
server-id: %s
|
||||
category-key: %s
|
||||
product-boundary: insurance
|
||||
@@ -399,9 +399,9 @@ public class PodScaffolder {
|
||||
capabilities: []
|
||||
select-if: %s 관련 요청인 경우
|
||||
reject-if: 다른 업무 영역이 주된 요청인 경우
|
||||
confidence-server-ids: [%s]
|
||||
confusable-servers: []
|
||||
decision-policy: 요청의 주요 업무 영역을 기준으로 서버를 선택합니다.
|
||||
""".formatted(moduleName.replace("-", "_"), key, moduleName, key, key, key, key, moduleName);
|
||||
""".formatted(moduleName, key, key, moduleName, key, key, key, key);
|
||||
}
|
||||
|
||||
private static String capitalize(String str) {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
mcp:
|
||||
manifest:
|
||||
routing-functions:
|
||||
- name: route_to_dat_was_pro
|
||||
description: 처리계 업무 서버로 요청을 라우팅합니다.
|
||||
- name: route_to_dat-was-pro
|
||||
description-serialization: 처리계 업무 서버로 요청을 라우팅합니다. 보험 계약, 청약, 변경 및 보험금 지급 업무를 처리합니다. 요청의 주요 엔티티와 업무 영역을 기준으로 처리계 서버를 선택합니다.
|
||||
server-id: dat-was-pro
|
||||
category-key: pro
|
||||
product-boundary: insurance
|
||||
@@ -12,5 +12,5 @@ mcp:
|
||||
capabilities: [계약 조회, 청약 처리, 계약 변경, 보험금 지급 조회]
|
||||
select-if: 보험 계약, 청약, 계약 변경, 보험금 또는 지급 관련 요청인 경우
|
||||
reject-if: 상품 소개, 고객 일반정보, 영업조직, 시스템 운영 업무가 주된 요청인 경우
|
||||
confidence-server-ids: [dat-was-pro]
|
||||
confusable-servers: [dat-was-cus, dat-was-sal, dat-was-sys]
|
||||
decision-policy: 요청의 주요 엔티티와 업무 영역을 기준으로 처리계 서버를 선택합니다.
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
mcp:
|
||||
manifest:
|
||||
routing-functions:
|
||||
- name: route_to_dat_was_sal
|
||||
description: 영업 업무 서버로 요청을 라우팅합니다.
|
||||
- name: route_to_dat-was-sal
|
||||
description-serialization: 영업 업무 서버로 요청을 라우팅합니다. 영업 조직과 설계사 업무를 처리합니다. 요청의 주요 엔티티와 업무 영역을 기준으로 영업 서버를 선택합니다.
|
||||
server-id: dat-was-sal
|
||||
category-key: sal
|
||||
product-boundary: insurance
|
||||
@@ -12,5 +12,5 @@ mcp:
|
||||
capabilities: [설계사 조회, 영업조직 조회, 실적 조회]
|
||||
select-if: 설계사, 영업조직 또는 영업실적 관련 요청인 경우
|
||||
reject-if: 고객, 계약, 상품, 시스템 운영 업무가 주된 요청인 경우
|
||||
confidence-server-ids: [dat-was-sal]
|
||||
confusable-servers: [dat-was-cus, dat-was-pro, dat-was-sys]
|
||||
decision-policy: 요청의 주요 엔티티와 업무 영역을 기준으로 영업 서버를 선택합니다.
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
mcp:
|
||||
manifest:
|
||||
routing-functions:
|
||||
- name: route_to_dat_was_sys
|
||||
description: 시스템 업무 서버로 요청을 라우팅합니다.
|
||||
- name: route_to_dat-was-sys
|
||||
description-serialization: 시스템 업무 서버로 요청을 라우팅합니다. 시스템 상태와 공통 운영 업무를 처리합니다. 요청의 주요 엔티티와 업무 영역을 기준으로 시스템 서버를 선택합니다.
|
||||
server-id: dat-was-sys
|
||||
category-key: sys
|
||||
product-boundary: insurance
|
||||
@@ -12,5 +12,5 @@ mcp:
|
||||
capabilities: [시스템 조회, 사용자 조회, 권한 조회]
|
||||
select-if: 시스템 운영, 사용자, 권한 관련 요청인 경우
|
||||
reject-if: 고객, 계약, 상품, 영업 업무가 주된 요청인 경우
|
||||
confidence-server-ids: [dat-was-sys]
|
||||
confusable-servers: [dat-was-cus, dat-was-pro, dat-was-sal]
|
||||
decision-policy: 요청의 주요 엔티티와 업무 영역을 기준으로 시스템 서버를 선택합니다.
|
||||
|
||||
Reference in New Issue
Block a user