refactor: apply new Naming standard (uid, categoryKey, subToolName) across modules

This commit is contained in:
jade
2026-07-11 00:37:29 +09:00
parent 406f093044
commit b9aa8e0169
25 changed files with 135 additions and 117 deletions

View File

@@ -6,7 +6,8 @@ import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface McpFunction {
String name();
String name(); // 사람이 읽는 라벨 (예: "고객 조회 툴")
String subToolName(); // MCP 서브툴 명칭 (예: "customer_search")
String description();
String prompt() default "";
String mappingId() default "";

View File

@@ -13,6 +13,6 @@ public @interface McpTool {
@AliasFor(annotation = Component.class)
String value() default "";
String group() default "COMMON";
String categoryKey() default "common";
String routingType() default "HTTP";
}

View File

@@ -28,11 +28,21 @@ import java.util.Map;
@NoArgsConstructor
@AllArgsConstructor
public class ToolMetadata {
private String toolName;
private String description;
// 1. Tool 기본 정보
private String uid; // UUID 형식의 고유 식별자
private String semver; // 버전 (예: 1.0.0)
private String name; // 사람이 읽는 라벨 (1-128자)
private String subToolName; // MCP 서브툴 명칭 (64자 이하, 예: CustomerSearchTool)
private String description; // 툴의 목적 및 설명 (LLM 프롬프트에 활용 가능)
// 2. 파라미터 스키마 (JSON Schema 형태의 Map)
private Map<String, Object> parametersSchema;
// 2-0. 프론트엔드 UI용 함수별 프롬프트 매핑 (추가됨)
private Map<String, String> actionPrompts;
private String domainGroup;
// 2-1. 도메인 부서 그룹명 (category_key, 슬러그 형식)
private String categoryKey;
private String endpoint;
private String podUrl;
private String integrationType;

View File

@@ -81,19 +81,23 @@ public class ToolRegistryHeartbeatSender {
McpFunction functionAnnotation = AnnotationUtils.findAnnotation(method, McpFunction.class);
if (functionAnnotation != null) {
String baseName = functionAnnotation.name();
String finalName = mcpProperties.getNamespace() != null && !mcpProperties.getNamespace().isEmpty()
? mcpProperties.getNamespace() + "_" + baseName
: baseName;
String rawSubToolName = functionAnnotation.subToolName();
String subToolName = mcpProperties.getNamespace() != null && !mcpProperties.getNamespace().isEmpty()
? mcpProperties.getNamespace() + "_" + rawSubToolName
: rawSubToolName;
boolean isRegister = functionAnnotation.register();
if (!isRegister) {
log.info(" [HeartbeatSender] '{}' 툴은 어노테이션 설정에 의해 외부 등록(Redis) 대상에서 제외되었습니다. (최종 이름: {})", baseName, finalName);
log.info(" [HeartbeatSender] '{}' 툴은 어노테이션 설정에 의해 외부 등록(Redis) 대상에서 제외되었습니다. (최종 이름: {})", baseName, subToolName);
}
ToolMetadata meta = new ToolMetadata();
meta.setToolName(finalName);
meta.setUid(java.util.UUID.nameUUIDFromBytes(subToolName.getBytes()).toString());
meta.setName(baseName);
meta.setSubToolName(subToolName);
meta.setSemver("1.0.0");
meta.setDescription(functionAnnotation.description());
meta.setDomainGroup(toolAnnotation.group());
meta.setCategoryKey(toolAnnotation.categoryKey());
meta.setIntegrationType(toolAnnotation.routingType());
meta.setMciServiceId(functionAnnotation.mappingId());
meta.setPodUrl(podUrl);
@@ -105,7 +109,7 @@ public class ToolRegistryHeartbeatSender {
Map<String, String> prompts = new HashMap<>();
String promptText = functionAnnotation.prompt();
prompts.put(finalName, promptText);
prompts.put(subToolName, promptText);
meta.setActionPrompts(prompts);
if (method.getParameterCount() > 0) {
@@ -117,7 +121,7 @@ public class ToolRegistryHeartbeatSender {
finalSchema.put("properties", schema);
meta.setParametersSchema(finalSchema);
} catch (Exception e) {
log.error("Failed to generate schema for {}", finalName, e);
log.error("Failed to generate schema for {}", subToolName, e);
}
}
@@ -125,7 +129,7 @@ public class ToolRegistryHeartbeatSender {
registeredTools.add(meta);
}
allScannedTools.add(meta);
log.info(" [HeartbeatSender] 도구 메타데이터 생성: {} (isRegistered: {})", meta.getToolName(), isRegister);
log.info(" [HeartbeatSender] 도구 메타데이터 생성: {} (isRegistered: {})", meta.getUid(), isRegister);
}
}
}
@@ -141,15 +145,15 @@ public class ToolRegistryHeartbeatSender {
.uri(gatewayUrl + "/mcp/api/v1/registry/heartbeat")
.header("Content-Type", "application/json")
.header("X-API-KEY", "SHINHAN_MCP_TEST_KEY_9999")
.body(tool.getToolName())
.body(tool.getUid())
.retrieve()
.toEntity(String.class);
if (response.getStatusCode().is2xxSuccessful()) {
log.info(" [HeartbeatSender] 하트비트 전송 성공: {}", tool.getToolName());
log.info(" [HeartbeatSender] 하트비트 전송 성공: {}", tool.getUid());
}
} catch (Exception e) {
log.warn(" [HeartbeatSender] 하트비트 전송 실패 ({}): {}. 재등록을 시도합니다.", tool.getToolName(), e.getMessage());
log.warn(" [HeartbeatSender] 하트비트 전송 실패 ({}): {}. 재등록을 시도합니다.", tool.getUid(), e.getMessage());
registerTool(tool);
}
}
@@ -164,7 +168,7 @@ public class ToolRegistryHeartbeatSender {
.body(tool)
.retrieve()
.toBodilessEntity();
log.info(" [HeartbeatSender] 툴 재등록 성공: {}", tool.getToolName());
log.info(" [HeartbeatSender] 툴 재등록 성공: {}", tool.getUid());
} catch (Exception ex) {
log.error(" [HeartbeatSender] 툴 등록 실패: {}", ex.getMessage());
}