diff --git a/Agent Builder MCP Integration Blueprint.pptx b/Agent Builder MCP Integration Blueprint.pptx new file mode 100644 index 0000000..8e0fd2f Binary files /dev/null and b/Agent Builder MCP Integration Blueprint.pptx differ diff --git a/McpBridge.java b/McpBridge.java index 3ca4f32..627e5ec 100644 --- a/McpBridge.java +++ b/McpBridge.java @@ -96,13 +96,26 @@ public class McpBridge { int idx = line.indexOf("\"id\":"); if (idx == -1) return "null"; int start = idx + 5; - while (start < line.length() && (line.charAt(start) == ' ' || line.charAt(start) == '\"')) { + while (start < line.length() && line.charAt(start) == ' ') { start++; } + if (start >= line.length()) return "null"; + int end = start; - while (end < line.length() && Character.isDigit(line.charAt(end))) { - end++; + if (line.charAt(start) == '\"') { + end = start + 1; + while (end < line.length() && line.charAt(end) != '\"') { + end++; + } + if (end < line.length()) { + end++; // include closing quote + } + } else { + while (end < line.length() && Character.isDigit(line.charAt(end))) { + end++; + } } + if (start == end) return "null"; return line.substring(start, end); } diff --git a/axhub-tool-core/src/main/java/io/shinhanlife/axhub/biz/mcp/tool/presentation/BusinessToolController.java b/axhub-tool-core/src/main/java/io/shinhanlife/axhub/biz/mcp/tool/presentation/BusinessToolController.java index ec7d67d..b496ba9 100644 --- a/axhub-tool-core/src/main/java/io/shinhanlife/axhub/biz/mcp/tool/presentation/BusinessToolController.java +++ b/axhub-tool-core/src/main/java/io/shinhanlife/axhub/biz/mcp/tool/presentation/BusinessToolController.java @@ -123,9 +123,16 @@ public class BusinessToolController { } } log.error("[Tool] 실행할 함수(Method)를 찾을 수 없습니다: {}. 현재 스캔된 툴 메서드 목록: {}", functionName, availableFunctions); + Map errorDetails = new HashMap<>(); + errorDetails.put("status", "404"); + Map errorBody = new HashMap<>(); + errorBody.put("code", "TOOL_NOT_FOUND"); + errorBody.put("message", "실행할 함수를 찾을 수 없습니다: " + functionName); + errorBody.put("details", errorDetails); + Map error = new HashMap<>(); error.put("jsonrpc", "2.0"); - error.put("error", Map.of("code", -32601, "message", "실행할 함수를 찾을 수 없습니다: " + functionName)); + error.put("error", errorBody); error.put("id", payload != null ? payload.get("id") : null); return error; } @@ -145,13 +152,20 @@ public class BusinessToolController { Set errors = schema.validate(objectMapper.valueToTree(arguments)); if (!errors.isEmpty()) { log.error("[Tool] 파라미터 유효성 검증 실패: {}", errors); - Map error = new HashMap<>(); - error.put("jsonrpc", "2.0"); List errorMessages = new ArrayList<>(); for (ValidationMessage vm : errors) { errorMessages.add(vm.getMessage()); } - error.put("error", Map.of("code", -32602, "message", "파라미터 유효성 검증 실패: " + String.join(", ", errorMessages))); + Map errorDetails = new HashMap<>(); + errorDetails.put("status", "422"); + Map errorBody = new HashMap<>(); + errorBody.put("code", "INVALID_PARAM"); + errorBody.put("message", "파라미터 유효성 검증 실패: " + String.join(", ", errorMessages)); + errorBody.put("details", errorDetails); + + Map error = new HashMap<>(); + error.put("jsonrpc", "2.0"); + error.put("error", errorBody); error.put("id", payload != null ? payload.get("id") : null); return error; } @@ -177,15 +191,23 @@ public class BusinessToolController { // 4. 메서드 실행 Object methodResult = targetMethod.invoke(targetBean, invokeArgument); - // 5. 결과 조립 (JSON-RPC 응답) - Map resultPayload = new HashMap<>(); + // 5. 결과 조립 (JSON-RPC 응답 - Agent Builder 규격 적용) + Map innerResult = new HashMap<>(); if (methodResult instanceof Map) { - resultPayload = (Map) methodResult; - } else { - resultPayload.put("status", "SUCCESS"); - resultPayload.put("legacy_response", methodResult); + innerResult.putAll((Map) methodResult); } - resultPayload.put("ai_insight", "다이렉트 메서드(" + targetMethod.getName() + ") 통신이 성공적으로 수행되었습니다."); + if (!innerResult.containsKey("contracts")) { + List contracts = new ArrayList<>(); + if (methodResult != null) { + contracts.add(methodResult); + } + innerResult.put("contracts", contracts); + } + + Map resultPayload = new HashMap<>(); + resultPayload.put("status", "ok"); + resultPayload.put("result", innerResult); + resultPayload.put("error code", null); Map rpcResponse = new java.util.LinkedHashMap<>(); // 순서 보장을 위해 LinkedHashMap 사용 rpcResponse.put("jsonrpc", "2.0"); @@ -201,9 +223,16 @@ public class BusinessToolController { } catch (Exception e) { log.error("[Tool] 리플렉션 실행 중 예외 발생: {}", e.getMessage()); + Map errorDetails = new HashMap<>(); + errorDetails.put("status", "500"); + Map errorBody = new HashMap<>(); + errorBody.put("code", "TOOL_ERROR"); + errorBody.put("message", "메서드 실행 중 예외 발생: " + (e.getCause() != null ? e.getCause().getMessage() : e.getMessage())); + errorBody.put("details", errorDetails); + Map error = new HashMap<>(); error.put("jsonrpc", "2.0"); - error.put("error", Map.of("code", -32000, "message", "메서드 실행 중 예외 발생: " + (e.getCause() != null ? e.getCause().getMessage() : e.getMessage()))); + error.put("error", errorBody); error.put("id", payload != null ? payload.get("id") : null); return error; } diff --git a/axhub-tool-hr/Dockerfile b/axhub-tool-hr/Dockerfile deleted file mode 100644 index 3343e67..0000000 --- a/axhub-tool-hr/Dockerfile +++ /dev/null @@ -1,4 +0,0 @@ -FROM eclipse-temurin:21-jdk-alpine -WORKDIR /app -COPY build/libs/axhub-tool-hr-0.0.1-SNAPSHOT.jar app.jar -ENTRYPOINT ["java", "-jar", "app.jar"] diff --git a/axhub-tool-hr/build.gradle b/axhub-tool-hr/build.gradle deleted file mode 100644 index 997adcb..0000000 --- a/axhub-tool-hr/build.gradle +++ /dev/null @@ -1,10 +0,0 @@ -plugins { - id 'org.springframework.boot' -} -dependencies { - implementation project(':axhub-tool-core') -} -dependencies { - compileOnly 'org.projectlombok:lombok:1.18.32' - annotationProcessor 'org.projectlombok:lombok:1.18.32' -} diff --git a/axhub-tool-hr/src/main/java/io/shinhanlife/axhub/biz/mcp/tool/hr/HrToolApplication.java b/axhub-tool-hr/src/main/java/io/shinhanlife/axhub/biz/mcp/tool/hr/HrToolApplication.java deleted file mode 100644 index 11da8ae..0000000 --- a/axhub-tool-hr/src/main/java/io/shinhanlife/axhub/biz/mcp/tool/hr/HrToolApplication.java +++ /dev/null @@ -1,28 +0,0 @@ -package io.shinhanlife.axhub.biz.mcp.tool.hr; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.cache.annotation.EnableCaching; - -/** - * @package io.shinhanlife.axhub.biz.mcp.tool.hr - * @className HrToolApplication - * @description AX HUB 시스템 처리 클래스 - * @author - * @create - *
- * ---------- 개정이력 ----------
- * 수정일      수정자    수정내용
- * ---------- -------- ---------------------------
- *       최초생성
- *
- * 
- */ -@SpringBootApplication(scanBasePackages = {"io.shinhanlife.axhub.biz.mcp.tool", "io.shinhanlife.axhub.biz.mcp.adapter", "io.shinhanlife.axhub.common.mcp", "io.shinhanlife.axhub.common.config"}) -@org.springframework.boot.context.properties.ConfigurationPropertiesScan(basePackages = {"io.shinhanlife.axhub.biz.mcp.tool", "io.shinhanlife.axhub.biz.mcp.adapter", "io.shinhanlife.axhub.common.mcp", "io.shinhanlife.axhub.common.config"}) -@EnableCaching -public class HrToolApplication { - public static void main(String[] args) { - SpringApplication.run(HrToolApplication.class, args); - } -} diff --git a/axhub-tool-hr/src/main/resources/application-local.properties b/axhub-tool-hr/src/main/resources/application-local.properties deleted file mode 100644 index 54d056d..0000000 --- a/axhub-tool-hr/src/main/resources/application-local.properties +++ /dev/null @@ -1,32 +0,0 @@ -# Local 환경 전용 설정 (H2 메모리 DB 등) -spring.datasource.url=jdbc:p6spy:h2:mem:testdb;DB_CLOSE_DELAY=-1; -spring.datasource.driverClassName=com.p6spy.engine.spy.P6SpyDriver -spring.datasource.username=sa -spring.datasource.password=password - -spring.h2.console.enabled=true -# EIMS 동적 라우팅 접속 정보 -eims.http.url=http://localhost:${server.port}/api/gateway -eims.tcp.host=127.0.0.1 -eims.tcp.port=8090 -eims.tcp.timeout=5000 -eims.jsp.form.url=http://localhost:${server.port}/mock/jsp-form -eims.jsp.json.url=http://localhost:${server.port}/mock/jsp-json -eims.mci.url=http://localhost:${server.port}/api/mock/esb/api -eims.mcistring.url=http://localhost:${server.port}/api/mock/esb/string - -# API 보안 키 설정 -mcp.security.api-keys.SHINHAN_MCP_SECRET_KEY_2026=mcp-client-1 -mcp.security.api-keys.SHINHAN_MCP_TEST_KEY_9999=mcp-client-2 -mcp.security.tenant-domains.mcp-client-1=CUSTOMER,COMMON -mcp.security.tenant-domains.mcp-client-2=ALL - -# Gateway/Tool URLs -axhub.gateway.url=http://localhost:8081 -axhub.tool.url=http://localhost:${server.port} - -# Disable Kafka -spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration - -# Suppress Kafka Connection Logs -logging.level.org.apache.kafka=ERROR diff --git a/axhub-tool-hr/src/main/resources/application-local.yml b/axhub-tool-hr/src/main/resources/application-local.yml deleted file mode 100644 index 2c12d7c..0000000 --- a/axhub-tool-hr/src/main/resources/application-local.yml +++ /dev/null @@ -1,12 +0,0 @@ -spring: - application: - name: axhub-tool-hr - config: - import: "classpath:config/application-glow-local.yml" - -server: - port: 8086 - -axhub: - tool: - url: "http://tool-hr:8086" diff --git a/axhub-tool-hr/src/main/resources/application.properties b/axhub-tool-hr/src/main/resources/application.properties deleted file mode 100644 index 1a4d891..0000000 --- a/axhub-tool-hr/src/main/resources/application.properties +++ /dev/null @@ -1,2 +0,0 @@ -spring.profiles.active=local -mcp.namespace=hr diff --git a/axhub-tool-other/src/main/java/io/shinhanlife/axhub/biz/mcp/tool/service/BondIssueService.java b/axhub-tool-other/src/main/java/io/shinhanlife/axhub/biz/mcp/tool/service/BondIssueService.java index 57d638c..e82ed98 100644 --- a/axhub-tool-other/src/main/java/io/shinhanlife/axhub/biz/mcp/tool/service/BondIssueService.java +++ b/axhub-tool-other/src/main/java/io/shinhanlife/axhub/biz/mcp/tool/service/BondIssueService.java @@ -30,7 +30,7 @@ public class BondIssueService extends AbstractMcpToolService { return executeLegacy("EAI", "BOND_001", data); } - @McpFunction(name = "issue", register = true, description = "증권 발행 테스트", prompt = "디지털 증권 발행 프로세스를 실행해.", mappingId = "BOND_002") +1 @McpFunction(name = "issue", register = true, description = "증권 발행 테스트1", prompt = "디지털 증권 발행 프로세스를 실행해.", mappingId = "BOND_002") public Object issue(BondIssueReq data) { return executeLegacy("EAI", "BOND_002", data); }