fix: honor tool registration flag
Some checks failed
Deploy to OCIWP / deploy (push) Failing after 0s

This commit is contained in:
jade
2026-08-11 10:28:46 +09:00
parent 4275f76104
commit 041f939c33
4 changed files with 65 additions and 7 deletions

View File

@@ -91,11 +91,13 @@ public class ToolRegistryHeartbeatSender {
String subToolName = mcpProperties.getNamespace() != null && !mcpProperties.getNamespace().isEmpty()
? mcpProperties.getNamespace() + "_" + rawSubToolName
: rawSubToolName;
// 요청에 따라 @ToolHint 의 register 값과 상관없이 무조건 등록(true) 처리합니다.
boolean isRegister = true;
if (hintAnnotation != null && !hintAnnotation.register()) {
log.info(" [HeartbeatSender] '{}' 툴은 원래 register=false 이지만 강제로 외부 등록(Redis) 대상에 포함합니다. (최종 이름: {})", baseName, subToolName);
// @ToolHint(register = false)인 Tool은 메타데이터 조회에는 남기되,
// Gateway 등록 및 heartbeat 전송 대상에서는 제외합니다.
// ToolHint가 없는 기존 Tool은 이전 동작과 동일하게 등록합니다.
boolean isRegister = hintAnnotation == null || hintAnnotation.register();
if (!isRegister) {
log.info(" [HeartbeatSender] '{}' Tool is excluded from Gateway registration because register=false. (tool name: {})",
baseName, subToolName);
}
ToolMetadata meta = new ToolMetadata();

View File

@@ -81,7 +81,7 @@ public class ToolScaffolder {
String inputSchemaResource = useSchemaResource ? schemaResourceDirectory + toKebabCase(baseName) + "-resource-input-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);
}

View File

@@ -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() {
}
}
}

View File

@@ -6,6 +6,6 @@ import io.shinhanlife.dap.mcc.biz.oth.dto.*;
public interface Onnba3011UseCase {
@McpTool(name = "oth_oth_onnba3011_call", description = "Onnba3011 호출 툴")
@ToolHint(categoryKey = "oth", register = true)
@ToolHint(categoryKey = "oth", register = false)
Object execute(Onnba3011Request req);
}