diff --git a/src/main/java/com/cloudhandson/vpdbackoffice/service/McpSseService.java b/src/main/java/com/cloudhandson/vpdbackoffice/service/McpSseService.java index 4cc7b72..1b64004 100644 --- a/src/main/java/com/cloudhandson/vpdbackoffice/service/McpSseService.java +++ b/src/main/java/com/cloudhandson/vpdbackoffice/service/McpSseService.java @@ -1,5 +1,6 @@ package com.cloudhandson.vpdbackoffice.service; +import com.cloudhandson.vpdbackoffice.config.BackofficeProperties; import com.cloudhandson.vpdbackoffice.domain.mcp.McpToolView; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; @@ -14,24 +15,20 @@ public class McpSseService { private static final String SELECT_AI_VPD_QUERY_TOOL = "oracle.select_ai.smilegate_game_text2sql"; private static final String SELECT_AI_VPD_QUERY_PATH = "/mcp (tools/call)"; - private static final String SELECT_AI_VPD_QUERY_PROFILE = "SGMP_POC_HAIKU45"; - private static final McpToolView SELECT_AI_VPD_QUERY_VIEW = new McpToolView( - SELECT_AI_VPD_QUERY_TOOL, - "SGMP_POC_HAIKU45 프로파일로 게임 로그·서비스 데이터용 읽기 전용 SELECT/WITH SQL을 생성하고, 검증 후 읽기 전용 트랜잭션에서 실행합니다. 생성 SQL과 최대 100건의 조회 결과를 함께 반환하며 DDL/DML/잠금/패키지 호출은 실행하지 않습니다.", - -1L, - "Smilegate 게임 데이터 Text2SQL", - SELECT_AI_VPD_QUERY_PATH - ); + private static final String DEFAULT_SELECT_AI_PROFILE = "SGMP_POC_OCI_GPT54MINI"; private final SmilegateSelectAiService smilegateSelectAiService; private final ObjectMapper objectMapper; + private final BackofficeProperties properties; public McpSseService( SmilegateSelectAiService smilegateSelectAiService, - ObjectMapper objectMapper + ObjectMapper objectMapper, + BackofficeProperties properties ) { this.smilegateSelectAiService = smilegateSelectAiService; this.objectMapper = objectMapper; + this.properties = properties; } public ObjectNode handle(String contextPath, JsonNode request) { @@ -70,7 +67,7 @@ public class McpSseService { /** The only tool registered by this MCP server. */ public List registeredTools() { - return List.of(SELECT_AI_VPD_QUERY_VIEW); + return List.of(selectAiVpdQueryView()); } private ObjectNode initializeResult(String contextPath) { @@ -97,7 +94,7 @@ public class McpSseService { private ObjectNode selectAiVpdQueryTool() { ObjectNode item = objectMapper.createObjectNode(); item.put("name", SELECT_AI_VPD_QUERY_TOOL); - item.put("description", SELECT_AI_VPD_QUERY_VIEW.description()); + item.put("description", selectAiVpdQueryView().description()); ObjectNode schema = objectMapper.createObjectNode(); schema.put("type", "object"); @@ -138,7 +135,7 @@ public class McpSseService { ObjectNode payload = objectMapper.createObjectNode(); payload.put("toolName", SELECT_AI_VPD_QUERY_TOOL); - payload.put("profile", SELECT_AI_VPD_QUERY_PROFILE); + payload.put("profile", selectAiProfile()); payload.put("ordsPath", SELECT_AI_VPD_QUERY_PATH); payload.set("response", response); @@ -169,6 +166,25 @@ public class McpSseService { return result; } + private McpToolView selectAiVpdQueryView() { + String profile = selectAiProfile(); + return new McpToolView( + SELECT_AI_VPD_QUERY_TOOL, + profile + " 프로파일로 게임 로그·서비스 데이터용 읽기 전용 SELECT/WITH SQL을 생성하고, 검증 후 읽기 전용 트랜잭션에서 실행합니다. 생성 SQL과 최대 100건의 조회 결과를 함께 반환하며 DDL/DML/잠금/패키지 호출은 실행하지 않습니다.", + -1L, + "Smilegate 게임 데이터 Text2SQL", + SELECT_AI_VPD_QUERY_PATH + ); + } + + private String selectAiProfile() { + BackofficeProperties.SelectAi selectAi = properties == null ? null : properties.selectAi(); + if (selectAi == null || selectAi.profile() == null || selectAi.profile().isBlank()) { + return DEFAULT_SELECT_AI_PROFILE; + } + return selectAi.profile().trim(); + } + private String pretty(Object value) { try { return objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(value); diff --git a/src/test/java/com/cloudhandson/vpdbackoffice/service/McpSseServiceTest.java b/src/test/java/com/cloudhandson/vpdbackoffice/service/McpSseServiceTest.java index 335a649..bd84be6 100644 --- a/src/test/java/com/cloudhandson/vpdbackoffice/service/McpSseServiceTest.java +++ b/src/test/java/com/cloudhandson/vpdbackoffice/service/McpSseServiceTest.java @@ -1,6 +1,7 @@ package com.cloudhandson.vpdbackoffice.service; import static org.assertj.core.api.Assertions.assertThat; +import com.cloudhandson.vpdbackoffice.config.BackofficeProperties; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ObjectNode; @@ -12,7 +13,14 @@ class McpSseServiceTest { private final SmilegateSelectAiService selectAiService = new CapturingSmilegateSelectAiService(); private final McpSseService service = new McpSseService( selectAiService, - objectMapper + objectMapper, + new BackofficeProperties( + null, + null, + null, + null, + new BackofficeProperties.SelectAi("", "", "", "SGMP_POC_OCI_GPT54MINI") + ) ); @Test @@ -23,6 +31,7 @@ class McpSseServiceTest { assertThat(tools).hasSize(1); var selectAi = tools.get(0); assertThat(selectAi.path("name").asText()).isEqualTo("oracle.select_ai.smilegate_game_text2sql"); + assertThat(selectAi.path("description").asText()).contains("SGMP_POC_OCI_GPT54MINI"); assertThat(selectAi.path("inputSchema").path("required")) .extracting(node -> node.asText()) .contains("prompt");