fix: honor tool registration flag
Some checks failed
Deploy to OCIWP / deploy (push) Failing after 0s
Some checks failed
Deploy to OCIWP / deploy (push) Failing after 0s
This commit is contained in:
@@ -91,11 +91,13 @@ public class ToolRegistryHeartbeatSender {
|
|||||||
String subToolName = mcpProperties.getNamespace() != null && !mcpProperties.getNamespace().isEmpty()
|
String subToolName = mcpProperties.getNamespace() != null && !mcpProperties.getNamespace().isEmpty()
|
||||||
? mcpProperties.getNamespace() + "_" + rawSubToolName
|
? mcpProperties.getNamespace() + "_" + rawSubToolName
|
||||||
: rawSubToolName;
|
: rawSubToolName;
|
||||||
|
// @ToolHint(register = false)인 Tool은 메타데이터 조회에는 남기되,
|
||||||
// 요청에 따라 @ToolHint 의 register 값과 상관없이 무조건 등록(true) 처리합니다.
|
// Gateway 등록 및 heartbeat 전송 대상에서는 제외합니다.
|
||||||
boolean isRegister = true;
|
// ToolHint가 없는 기존 Tool은 이전 동작과 동일하게 등록합니다.
|
||||||
if (hintAnnotation != null && !hintAnnotation.register()) {
|
boolean isRegister = hintAnnotation == null || hintAnnotation.register();
|
||||||
log.info(" [HeartbeatSender] '{}' 툴은 원래 register=false 이지만 강제로 외부 등록(Redis) 대상에 포함합니다. (최종 이름: {})", baseName, subToolName);
|
if (!isRegister) {
|
||||||
|
log.info(" [HeartbeatSender] '{}' Tool is excluded from Gateway registration because register=false. (tool name: {})",
|
||||||
|
baseName, subToolName);
|
||||||
}
|
}
|
||||||
|
|
||||||
ToolMetadata meta = new ToolMetadata();
|
ToolMetadata meta = new ToolMetadata();
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ public class ToolScaffolder {
|
|||||||
String inputSchemaResource = useSchemaResource ? schemaResourceDirectory + toKebabCase(baseName) + "-resource-input-schema.json" : null;
|
String inputSchemaResource = useSchemaResource ? schemaResourceDirectory + toKebabCase(baseName) + "-resource-input-schema.json" : null;
|
||||||
String outputSchemaResource = useSchemaResource ? schemaResourceDirectory + toKebabCase(baseName) + "-resource-output-schema.json" : null;
|
String outputSchemaResource = useSchemaResource ? schemaResourceDirectory + toKebabCase(baseName) + "-resource-output-schema.json" : null;
|
||||||
|
|
||||||
String result = scaffold(baseName, interfaceId, description, group, routingType, moduleName, author, createDate, true, null, inputSchemaResource, outputSchemaResource);
|
String result = scaffold(baseName, interfaceId, description, group, routingType, moduleName, author, createDate, false, null, inputSchemaResource, outputSchemaResource);
|
||||||
System.out.println(result);
|
System.out.println(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
package io.shinhanlife.dap.lib.mcp;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import io.shinhanlife.dap.lib.annotation.ToolHint;
|
||||||
|
import io.shinhanlife.dap.lib.config.McpProperties;
|
||||||
|
import io.shinhanlife.dap.lib.util.ToolSchemaResolver;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springaicommunity.mcp.annotation.McpTool;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
|
||||||
|
class ToolRegistryHeartbeatSenderTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void excludesRegisterFalseToolFromGatewayRegistrationTargets() throws Exception {
|
||||||
|
ApplicationContext applicationContext = mock(ApplicationContext.class);
|
||||||
|
when(applicationContext.getBeansOfType(Object.class)).thenReturn(Map.of("disabledTool", new DisabledTool()));
|
||||||
|
ToolRegistryHeartbeatSender sender = new ToolRegistryHeartbeatSender(
|
||||||
|
applicationContext, new ObjectMapper(), new McpProperties(), mock(ToolSchemaResolver.class));
|
||||||
|
|
||||||
|
setField(sender, "podUrl", "http://localhost:8084");
|
||||||
|
|
||||||
|
sender.init();
|
||||||
|
|
||||||
|
assertThat(sender.getAllScannedTools()).singleElement()
|
||||||
|
.extracting(tool -> tool.getIsRegistered())
|
||||||
|
.isEqualTo(false);
|
||||||
|
assertThat(registeredTools(sender)).isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setField(Object target, String name, Object value) throws Exception {
|
||||||
|
Field field = target.getClass().getDeclaredField(name);
|
||||||
|
field.setAccessible(true);
|
||||||
|
field.set(target, value);
|
||||||
|
}
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private List<?> registeredTools(ToolRegistryHeartbeatSender sender) throws Exception {
|
||||||
|
Field field = ToolRegistryHeartbeatSender.class.getDeclaredField("registeredTools");
|
||||||
|
field.setAccessible(true);
|
||||||
|
return (List<?>) field.get(sender);
|
||||||
|
}
|
||||||
|
|
||||||
|
static class DisabledTool {
|
||||||
|
|
||||||
|
@McpTool(name = "test_disabled_tool")
|
||||||
|
@ToolHint(register = false)
|
||||||
|
void execute() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,6 +6,6 @@ import io.shinhanlife.dap.mcc.biz.oth.dto.*;
|
|||||||
|
|
||||||
public interface Onnba3011UseCase {
|
public interface Onnba3011UseCase {
|
||||||
@McpTool(name = "oth_oth_onnba3011_call", description = "Onnba3011 호출 툴")
|
@McpTool(name = "oth_oth_onnba3011_call", description = "Onnba3011 호출 툴")
|
||||||
@ToolHint(categoryKey = "oth", register = true)
|
@ToolHint(categoryKey = "oth", register = false)
|
||||||
Object execute(Onnba3011Request req);
|
Object execute(Onnba3011Request req);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user