refs #703 #704: finalize smilegate game data poc

This commit is contained in:
devmrko
2026-07-22 15:35:02 +09:00
parent 20c6a82338
commit 211dd2b2c8
42 changed files with 576 additions and 445 deletions

View File

@@ -8,30 +8,29 @@ import com.fasterxml.jackson.databind.node.ObjectNode;
import java.util.List;
import org.springframework.stereotype.Service;
/** MCP boundary exposing only the row-access-aware GPT-5.4-mini Select AI query tool. */
/** MCP boundary exposing the Smilegate game-data Select AI SHOWSQL tool. */
@Service
public class McpSseService {
private static final String SELECT_AI_VPD_QUERY_TOOL = "ords.query.kb_select_ai_vpd";
private static final String SELECT_AI_VPD_QUERY_PATH = "cb-ords/kb-select-ai-vpd/query";
private static final String SELECT_AI_VPD_QUERY_PROFILE =
"KB_AIDP_SELECTAI_GPT54_MINI_FULLMETA_PROFILE_V1";
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,
"GPT-5.4-mini Select AI 자연어 질의를 행 접근 컨텍스트로 실행합니다. 테이블/컬럼 comment, annotation, constraint 메타데이터를 사용하고 생성 SQL은 KB 업무 테이블의 읽기 전용 SELECT/WITH만 허용합니다.",
"SGMP_POC_HAIKU45 프로파일로 게임 로그·서비스 데이터용 읽기 전용 SELECT/WITH SQL을 생성합니다. 생성 SQL은 자동 실행하지 않으며 테이블·컬럼 comment, annotation, constraint를 참고합니다.",
-1L,
"KB Select AI 행 접근 자연어 조회",
"Smilegate 게임 데이터 Text2SQL",
SELECT_AI_VPD_QUERY_PATH
);
private final SelectAiAgentOrdsService selectAiAgentOrdsService;
private final SmilegateSelectAiService smilegateSelectAiService;
private final ObjectMapper objectMapper;
public McpSseService(
SelectAiAgentOrdsService selectAiAgentOrdsService,
SmilegateSelectAiService smilegateSelectAiService,
ObjectMapper objectMapper
) {
this.selectAiAgentOrdsService = selectAiAgentOrdsService;
this.smilegateSelectAiService = smilegateSelectAiService;
this.objectMapper = objectMapper;
}
@@ -106,17 +105,10 @@ public class McpSseService {
ObjectNode prompt = objectMapper.createObjectNode();
prompt.put("type", "string");
prompt.put("description", "KB 업무 원장에 대해 조회할 내용을 자연어로 입력합니다.");
prompt.put("description", "Smilegate 게임 로그·서비스 데이터에 대해 조회할 내용을 자연어로 입력합니다.");
prompt.put("maxLength", 4000);
properties.set("prompt", prompt);
ObjectNode limit = objectMapper.createObjectNode();
limit.put("type", "integer");
limit.put("description", "최대 반환 행 수. 1부터 100까지 허용하며 기본값은 50입니다.");
limit.put("minimum", 1);
limit.put("maximum", 100);
properties.set("limit", limit);
schema.set("properties", properties);
ArrayNode required = objectMapper.createArrayNode();
required.add("prompt");
@@ -139,11 +131,7 @@ public class McpSseService {
}
JsonNode response;
try {
response = selectAiAgentOrdsService.run(
token,
arguments.path("prompt").asText(""),
normalizeLimit(arguments.path("limit").asInt(50))
);
response = smilegateSelectAiService.generateShowSql(token, arguments.path("prompt").asText(""));
} catch (VpdTokenAccessDeniedException ignored) {
return tokenAccessDeniedResult();
}
@@ -181,13 +169,6 @@ public class McpSseService {
return result;
}
private int normalizeLimit(int limit) {
if (limit < 1) {
return 50;
}
return Math.min(limit, 100);
}
private String pretty(Object value) {
try {
return objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(value);