diff --git a/axhub-gateway/src/main/java/io/shinhanlife/axhub/biz/mcp/gateway/config/GatewayFallbackProperties.java b/axhub-gateway/src/main/java/io/shinhanlife/axhub/biz/mcp/gateway/config/GatewayFallbackProperties.java new file mode 100644 index 0000000..5092e68 --- /dev/null +++ b/axhub-gateway/src/main/java/io/shinhanlife/axhub/biz/mcp/gateway/config/GatewayFallbackProperties.java @@ -0,0 +1,16 @@ +package io.shinhanlife.axhub.biz.mcp.gateway.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +import java.util.HashMap; +import java.util.Map; + +@Data +@Configuration +@ConfigurationProperties(prefix = "mcp.gateway.fallback") +public class GatewayFallbackProperties { + private Map routes = new HashMap<>(); + private String defaultUrl; +} diff --git a/axhub-gateway/src/main/java/io/shinhanlife/axhub/biz/mcp/gateway/service/ToolPlanner.java b/axhub-gateway/src/main/java/io/shinhanlife/axhub/biz/mcp/gateway/service/ToolPlanner.java index 6d12e6b..f5cba6b 100644 --- a/axhub-gateway/src/main/java/io/shinhanlife/axhub/biz/mcp/gateway/service/ToolPlanner.java +++ b/axhub-gateway/src/main/java/io/shinhanlife/axhub/biz/mcp/gateway/service/ToolPlanner.java @@ -3,6 +3,7 @@ package io.shinhanlife.axhub.biz.mcp.gateway.service; import io.shinhanlife.axhub.common.mcp.security.SecurityProperties; import io.shinhanlife.axhub.biz.mcp.gateway.registry.RedisRegistryService; import io.shinhanlife.axhub.biz.mcp.gateway.dto.ToolMetadata; +import io.shinhanlife.axhub.biz.mcp.gateway.config.GatewayFallbackProperties; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; @@ -17,6 +18,7 @@ public class ToolPlanner { private final RedisRegistryService redisRegistryService; private final SecurityProperties securityProperties; + private final GatewayFallbackProperties fallbackProperties; /** * 요청(payload)을 분석하여 실행해야 할 Tool의 계획을 생성합니다. @@ -37,8 +39,30 @@ public class ToolPlanner { var toolMetadata = redisRegistryService.getTool(toolName); if (toolMetadata == null) { - log.warn(" [Planner] 등록되지 않은 툴 요청: {}", toolName); - throw new RuntimeException("해당 툴(" + toolName + ")이 레지스트리에 존재하지 않습니다."); + log.warn(" [Planner] 등록되지 않은 툴 요청: {}. Fallback 라우팅 규칙을 확인합니다.", toolName); + + String fallbackPodUrl = fallbackProperties.getDefaultUrl(); + if (fallbackProperties.getRoutes() != null) { + for (Map.Entry entry : fallbackProperties.getRoutes().entrySet()) { + if (toolName.contains(entry.getKey())) { + fallbackPodUrl = entry.getValue(); + break; + } + } + } + + if (fallbackPodUrl == null || fallbackPodUrl.isEmpty()) { + log.error(" [Planner] Fallback 라우팅 대상이 아닙니다. 툴: {}", toolName); + throw new RuntimeException("해당 툴(" + toolName + ")이 레지스트리에 존재하지 않습니다."); + } + + log.info(" [Planner] Fallback 라우팅 매칭됨: {} -> {}", toolName, fallbackPodUrl); + + toolMetadata = ToolMetadata.builder() + .toolName(toolName) + .integrationType("DIRECT") + .podUrl(fallbackPodUrl) + .build(); } // 2-1. [신규] 도메인 그룹핑 기반 권한 검증 diff --git a/axhub-gateway/src/main/resources/application.properties b/axhub-gateway/src/main/resources/application.properties index 64a97a5..54c2f34 100644 --- a/axhub-gateway/src/main/resources/application.properties +++ b/axhub-gateway/src/main/resources/application.properties @@ -1,4 +1,11 @@ spring.application.name=axhub-admin +spring.main.web-application-type=reactive + +# Gateway Fallback Routing (For unregistered tools) +mcp.gateway.fallback.routes.email=http://tool-email:8083 +mcp.gateway.fallback.routes.sms=http://tool-sms:8082 +mcp.gateway.fallback.default-url=http://tool-other:8084 + server.port=8081 server.http2.enabled=true diff --git a/axhub-tool-other/src/main/java/io/shinhanlife/axhub/biz/mcp/tool/service/TemplateUtilityService.java b/axhub-tool-other/src/main/java/io/shinhanlife/axhub/biz/mcp/tool/service/TemplateUtilityService.java index 08bdb62..d20bea5 100644 --- a/axhub-tool-other/src/main/java/io/shinhanlife/axhub/biz/mcp/tool/service/TemplateUtilityService.java +++ b/axhub-tool-other/src/main/java/io/shinhanlife/axhub/biz/mcp/tool/service/TemplateUtilityService.java @@ -17,7 +17,7 @@ public class TemplateUtilityService extends AbstractMcpToolService { name = "get_template_file_url", description = "특정 템플릿의 양식 파일(엑셀, 워드 등)을 다운로드 받을 수 있는 시스템 URL을 반환합니다. AI는 이 URL을 사용자에게 마크다운 링크 형태로 제공해야 합니다.", prompt = "요청하신 템플릿 양식 파일 다운로드 URL은 다음과 같습니다. 클릭하여 다운로드하세요:", - visible = false + register = false ) public Map getTemplateFileUrl(TemplateDownloadReq data) { try {