diff --git a/dap-gateway/src/main/java/io/shinhanlife/dap/mcg/service/ExecuteService.java b/dap-gateway/src/main/java/io/shinhanlife/dap/mcg/service/ExecuteService.java index 1f05976..368dc3b 100644 --- a/dap-gateway/src/main/java/io/shinhanlife/dap/mcg/service/ExecuteService.java +++ b/dap-gateway/src/main/java/io/shinhanlife/dap/mcg/service/ExecuteService.java @@ -230,20 +230,13 @@ public class ExecuteService { if (metadata.getPodUrl() != null && !metadata.getPodUrl().isEmpty()) { targetUrl = metadata.getPodUrl(); } - String executeApiUrl = targetUrl + "/mcp/api/v1/tools/call"; + String executeApiUrl = targetUrl + "/mcp/" + metadata.getName(); ObjectNode pageArguments = paginationValidator.normalize(arguments); LargeToolResponseService.Collector collector = largeResponses.newCollector(metadata.getName(), context.requestId()); while (true) { - Map pagePayload = new HashMap<>(payload); - if (pagePayload.containsKey("params")) { - Map params = new HashMap<>((Map) pagePayload.get("params")); - params.put("arguments", objectMapper.convertValue(pageArguments, Map.class)); - pagePayload.put("params", params); - } else { - pagePayload.put("arguments", objectMapper.convertValue(pageArguments, Map.class)); - } + Map pagePayload = objectMapper.convertValue(pageArguments, Map.class); try { log.info(" [ExecuteService] 요청 페이로드(마스킹 적용): {}", objectMapper.writeValueAsString(dataMasker.mask(objectMapper.valueToTree(pagePayload)))); diff --git a/dap-tool-core/src/main/java/io/shinhanlife/dap/mcc/presentation/BusinessToolController.java b/dap-tool-core/src/main/java/io/shinhanlife/dap/mcc/presentation/BusinessToolController.java index 65c9080..b66c71f 100644 --- a/dap-tool-core/src/main/java/io/shinhanlife/dap/mcc/presentation/BusinessToolController.java +++ b/dap-tool-core/src/main/java/io/shinhanlife/dap/mcc/presentation/BusinessToolController.java @@ -65,26 +65,23 @@ public class BusinessToolController { return toolRegistryHeartbeatSender.getAllScannedTools(); } - // JSON RPC 기반 단일 라우팅 엔드포인트 - @PostMapping("/mcp/api/v1/tools/call") - public ResponseEntity> executeDynamicTool( + // 순수 REST 기반 동적 라우팅 엔드포인트 + @PostMapping("/mcp/{name}") + public ResponseEntity executeDynamicTool( + @PathVariable("name") String functionName, @RequestHeader(value = "X-Request-Id", required = false) String headerRequestId, - @RequestBody(required = false) Map payload) { + @RequestBody(required = false) Map arguments) { - String finalRequestId = headerRequestId != null ? headerRequestId : (payload != null && payload.get("id") != null ? String.valueOf(payload.get("id")) : null); - Map params = payload != null ? (Map) payload.get("params") : null; - String functionName = params != null ? (String) params.get("name") : null; + String finalRequestId = headerRequestId; log.info("\n [Tool] 동적 툴 실행 요청 수신 (함수명): {}", functionName); - if (payload != null) { + if (arguments != null) { try { - log.info(" [Tool] 호출 파라미터: {}", objectMapper.writeValueAsString(payload)); + log.info(" [Tool] 호출 파라미터: {}", objectMapper.writeValueAsString(arguments)); } catch (Exception e) { - log.info(" [Tool] 호출 파라미터: {}", payload); + log.info(" [Tool] 호출 파라미터: {}", arguments); } } - - Map arguments = params != null ? (Map) params.get("arguments") : null; Object targetBean = null; Method targetMethod = null; McpFunction targetFunctionAnnotation = null; @@ -135,11 +132,7 @@ public class BusinessToolController { errorBody.put("details", errorDetails); if (finalRequestId != null) errorBody.put("request_id", finalRequestId); - Map error = new HashMap<>(); - error.put("jsonrpc", "2.0"); - error.put("error", errorBody); - error.put("id", payload != null ? payload.get("id") : null); - return ResponseEntity.status(404).body(error); + return ResponseEntity.status(404).body(errorBody); } // (기존 차단 로직 제거됨) @@ -169,11 +162,7 @@ public class BusinessToolController { errorBody.put("details", errorDetails); if (finalRequestId != null) errorBody.put("request_id", finalRequestId); - Map error = new HashMap<>(); - error.put("jsonrpc", "2.0"); - error.put("error", errorBody); - error.put("id", payload != null ? payload.get("id") : null); - return ResponseEntity.status(422).body(error); + return ResponseEntity.status(422).body(errorBody); } } catch (Exception e) { log.error("[Tool] 스키마 검증 중 오류 발생: {}", e.getMessage()); @@ -202,60 +191,14 @@ public class BusinessToolController { long elapsed = System.currentTimeMillis() - startTime; - // 5. 결과 조립 (JSON-RPC 응답 - Agent Builder 규격 적용) - Map innerResult = new HashMap<>(); - if (methodResult instanceof Map && ((Map) methodResult).containsKey("contracts")) { - innerResult.putAll((Map) methodResult); - } else { - List contracts = new ArrayList<>(); - if (methodResult != null) { - contracts.add(methodResult); - } - innerResult.put("contracts", contracts); - - if (methodResult instanceof Map && ((Map) methodResult).containsKey("status")) { - innerResult.put("status", ((Map) methodResult).get("status")); - } else { - innerResult.put("status", "SUCCESS"); - } - } - - Map resultPayload = new HashMap<>(); - resultPayload.put("status", "ok"); - resultPayload.put("result", innerResult); - resultPayload.put("error_code", null); - resultPayload.put("error_message", null); - resultPayload.put("elapsed_ms", elapsed); - resultPayload.put("truncated", false); - int originalSize = 0; + // 5. 결과 반환 (순수 REST 응답) try { - if (methodResult instanceof Map && ((Map) methodResult).containsKey("legacy_response")) { - Object legacyResp = ((Map) methodResult).get("legacy_response"); - if (legacyResp instanceof String) { - originalSize = ((String) legacyResp).getBytes(java.nio.charset.StandardCharsets.UTF_8).length; - } - } else { - String jsonStr = objectMapper.writeValueAsString(innerResult); - originalSize = jsonStr.getBytes(java.nio.charset.StandardCharsets.UTF_8).length; - } + log.info("[Tool -> MCP Gateway] 동적 툴 실행 결과 반환: {}", objectMapper.writeValueAsString(methodResult)); } catch (Exception e) { - log.warn("Failed to calculate original_size", e); - } - resultPayload.put("original_size", originalSize); - - Map rpcResponse = new LinkedHashMap<>(); // 순서 보장을 위해 LinkedHashMap 사용 - rpcResponse.put("jsonrpc", "2.0"); - rpcResponse.put("result", resultPayload); - rpcResponse.put("id", payload != null ? payload.get("id") : null); - - try { - log.info("[Tool -> MCP Gateway] 동적 툴 실행 결과 반환: {}", objectMapper.writeValueAsString(rpcResponse)); - } catch (Exception e) { - log.info("[Tool -> MCP Gateway] 동적 툴 실행 결과 반환: {}", rpcResponse); + log.info("[Tool -> MCP Gateway] 동적 툴 실행 결과 반환: {}", methodResult); } - - return ResponseEntity.ok(rpcResponse); + return ResponseEntity.ok(methodResult); } catch (Exception e) { log.error("[Tool] 리플렉션 실행 중 예외 발생: {}", e.getMessage()); @@ -268,11 +211,7 @@ public class BusinessToolController { errorBody.put("details", errorDetails); if (finalRequestId != null) errorBody.put("request_id", finalRequestId); - Map error = new HashMap<>(); - error.put("jsonrpc", "2.0"); - error.put("error", errorBody); - error.put("id", payload != null ? payload.get("id") : null); - return ResponseEntity.status(502).body(error); + return ResponseEntity.status(502).body(errorBody); } } } \ No newline at end of file