diff --git a/dap-tool-core/src/main/java/io/shinhanlife/dap/common/integration/mci/config/GlowMockConfig.java b/dap-tool-core/src/main/java/io/shinhanlife/dap/common/integration/mci/config/GlowMockConfig.java index ad56d20c..6d7a520e 100644 --- a/dap-tool-core/src/main/java/io/shinhanlife/dap/common/integration/mci/config/GlowMockConfig.java +++ b/dap-tool-core/src/main/java/io/shinhanlife/dap/common/integration/mci/config/GlowMockConfig.java @@ -16,4 +16,10 @@ public class GlowMockConfig { public GlowMciComponent glowMciComponent() { return new GlowMciComponent(); } + + @Bean + @SuppressWarnings("rawtypes") + public io.shinhanlife.glow.communication.module.eai.component.GlowEaiComponent glowEaiComponent() { + return new io.shinhanlife.glow.communication.module.eai.component.GlowEaiComponent(); + } } diff --git a/dap-tool-email/src/main/java/io/shinhanlife/dap/dapmt/service/EmailToolService.java b/dap-tool-email/src/main/java/io/shinhanlife/dap/dapmt/service/EmailToolService.java index 62b6e427..87c4e45c 100644 --- a/dap-tool-email/src/main/java/io/shinhanlife/dap/dapmt/service/EmailToolService.java +++ b/dap-tool-email/src/main/java/io/shinhanlife/dap/dapmt/service/EmailToolService.java @@ -1,49 +1,7 @@ package io.shinhanlife.dap.dapmt.service; -import io.shinhanlife.dap.dapmt.annotation.McpFunction; -import io.shinhanlife.dap.dapmt.annotation.McpTool; -import io.shinhanlife.dap.dapmt.dto.EmailSendReq; -import lombok.extern.slf4j.Slf4j; +import io.shinhanlife.dap.dapmt.dto.*; -import java.util.HashMap; -import java.util.Map; - -/** - * @package io.shinhanlife.dap.dapmt.email - * @className EmailToolService - * @description AX HUB 시스템 처리 클래스 - * @author 0986406 - * @create 2026.09.01 - *
- * ---------- 개정이력 ----------
- * 수정일      수정자    수정내용
- * ---------- -------- ---------------------------
- * 2026.09.01  0986406    최초생성
- * 
- * 
- */ -@Slf4j -@McpTool(routingType = "EAI", categoryKey = "notification") -public class EmailToolService extends AbstractMcpToolService { - - @McpFunction(register = false, displayName = "send_email 툴", name = "send_email", description = "이메일 발송", prompt = "고객에게 이메일을 발송해줘.", mappingId = "EMAIL_SEND_001") - public Object sendEmail(EmailSendReq req) { - log.info("[Email] 이메일 발송 요청 수신. 수신자: {}", req.getEmailAddress()); - - // EAI 연동을 위한 파라미터 변환 - Map payload = new HashMap<>(); - payload.put("address", req.getEmailAddress()); - payload.put("subject", req.getSubject()); - payload.put("content", req.getBody()); - - // 레거시 시스템 연동 (EAI) - Map result = executeLegacy("EAI", "EMAIL_SEND_001", payload); - - // 결과 가공 - if ("SUCCESS".equals(result.get("status"))) { - result.put("message", "이메일이 성공적으로 발송되었습니다."); - } - - return result; - } -} \ No newline at end of file +public interface EmailToolService { + Object sendEmail(EmailSendReq req); +} diff --git a/dap-tool-email/src/main/java/io/shinhanlife/dap/dapmt/service/impl/EmailToolServiceImpl.java b/dap-tool-email/src/main/java/io/shinhanlife/dap/dapmt/service/impl/EmailToolServiceImpl.java new file mode 100644 index 00000000..0f013e10 --- /dev/null +++ b/dap-tool-email/src/main/java/io/shinhanlife/dap/dapmt/service/impl/EmailToolServiceImpl.java @@ -0,0 +1,52 @@ +package io.shinhanlife.dap.dapmt.service.impl; + +import io.shinhanlife.dap.dapmt.annotation.McpFunction; +import io.shinhanlife.dap.dapmt.annotation.McpTool; +import io.shinhanlife.dap.dapmt.service.EmailToolService; +import io.shinhanlife.dap.dapmt.service.AbstractMcpToolService; +import io.shinhanlife.dap.dapmt.dto.EmailSendReq; +import lombok.extern.slf4j.Slf4j; + +import java.util.HashMap; +import java.util.Map; + +/** + * @package io.shinhanlife.dap.dapmt.email + * @className EmailToolService + * @description AX HUB 시스템 처리 클래스 + * @author 0986406 + * @create 2026.09.01 + *
+ * ---------- 개정이력 ----------
+ * 수정일      수정자    수정내용
+ * ---------- -------- ---------------------------
+ * 2026.09.01  0986406    최초생성
+ * 
+ * 
+ */ +@Slf4j +@McpTool(routingType = "EAI", categoryKey = "notification") +public class EmailToolServiceImpl extends AbstractMcpToolService implements EmailToolService { + + @McpFunction(register = false, displayName = "send_email 툴", name = "send_email", description = "이메일 발송", prompt = "고객에게 이메일을 발송해줘.", mappingId = "EMAIL_SEND_001") + @Override + public Object sendEmail(EmailSendReq req) { + log.info("[Email] 이메일 발송 요청 수신. 수신자: {}", req.getEmailAddress()); + + // EAI 연동을 위한 파라미터 변환 + Map payload = new HashMap<>(); + payload.put("address", req.getEmailAddress()); + payload.put("subject", req.getSubject()); + payload.put("content", req.getBody()); + + // 레거시 시스템 연동 (EAI) + Map result = executeLegacy("EAI", "EMAIL_SEND_001", payload); + + // 결과 가공 + if ("SUCCESS".equals(result.get("status"))) { + result.put("message", "이메일이 성공적으로 발송되었습니다."); + } + + return result; + } +} \ No newline at end of file diff --git a/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/BalanceService.java b/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/BalanceService.java index 524dccd6..3897e51e 100644 --- a/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/BalanceService.java +++ b/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/BalanceService.java @@ -1,52 +1,7 @@ package io.shinhanlife.dap.dapmt.service; +import io.shinhanlife.dap.dapmt.dto.*; -/** - * @package io.shinhanlife.dap.dapmt.service - * @className BalanceService - * @description AX HUB 시스템 처리 클래스 - * @author 0986406 - * @create 2026.09.01 - *
- * ---------- 개정이력 ----------
- * 수정일      수정자    수정내용
- * ---------- -------- ---------------------------
- * 2026.09.01  0986406    최초생성
- * 
- * 
- */ -import io.shinhanlife.dap.dapmt.annotation.McpFunction; -import io.shinhanlife.dap.dapmt.annotation.McpTool; -import io.shinhanlife.dap.dapmt.dto.BalanceReq; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -import java.util.Map; - -@Slf4j -@Service -@McpTool(routingType = "MCI", categoryKey = "common") -public class BalanceService extends AbstractMcpToolService { - - @McpFunction(register = false, displayName = "balance 툴", name = "balance", - description = "고객의 계좌 잔액을 조회합니다.", - prompt = "고객 계좌 잔액을 조회해줘.", - mappingId = "ACC_001" - ) - public Object execute(BalanceReq req) { - log.info("[Balance] 계좌 잔액 조회 요청 수신. 계좌번호: {}", req.getAccountNumber()); - - // 레거시 연동 - Map result = executeLegacy("MCI", "ACC_001", req); - - // 가짜 데이터 응답 매핑 (AI 에이전트가 그럴듯하게 보여주기 위함) - if ("SUCCESS".equals(result.get("status"))) { - result.put("accountNumber", req.getAccountNumber()); - result.put("balance", 1520300); // 1,520,300원 (가상의 잔액) - result.put("currency", "KRW"); - result.put("message", "잔액 조회가 완료되었습니다."); - } - - return result; - } +public interface BalanceService { + Object execute(BalanceReq req); } diff --git a/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/BillingProcessService.java b/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/BillingProcessService.java index f78c902c..22df29f7 100644 --- a/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/BillingProcessService.java +++ b/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/BillingProcessService.java @@ -1,68 +1,7 @@ package io.shinhanlife.dap.dapmt.service; -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; -import io.shinhanlife.dap.dapmt.annotation.McpFunction; -import io.shinhanlife.dap.dapmt.annotation.McpTool; -import io.shinhanlife.dap.dapmt.dto.BillingProcessReq; -import io.shinhanlife.dap.dapmt.dto.BillingStatusReq; +import io.shinhanlife.dap.dapmt.dto.*; -import java.util.HashMap; -import java.util.Map; - -@McpTool( - routingType = "MCI", - categoryKey = "claim" -) -/** - * @package io.shinhanlife.dap.dapmt.service - * @className BillingProcessService - * @description AX HUB 시스템 처리 클래스 - * @author 0986406 - * @create 2026.09.01 - *
- * ---------- 개정이력 ----------
- * 수정일      수정자    수정내용
- * ---------- -------- ---------------------------
- * 2026.09.01  0986406    최초생성
- * 
- * 
- */ -@lombok.extern.slf4j.Slf4j -public class BillingProcessService extends AbstractMcpToolService { - - @McpFunction(register = false, displayName = "status 툴", name = "status", description = "청구심사 상태 조회", prompt = "현재 접수된 청구건 상태를 알려줘.", mappingId = "BILL_001") - public Object getStatus(BillingStatusReq data) { - return executeBillingLogic("BILL_001", data); - } - - @McpFunction(register = false, displayName = "process 툴", name = "process", description = "청구 처리", prompt = "현재 접수된 청구건에 대한 심사 처리를 진행해.", mappingId = "BILL_002") - public Object processBilling(BillingProcessReq data) { - return executeBillingLogic("BILL_002", data); - } - - private Object executeBillingLogic(String mappingId, Object data) { - log.info(" [Billing] 청구 처리 전용 커스텀 전/후처리 로직 수행 시작"); - - Map payload; - if (data == null) { - payload = new HashMap<>(); - } else { - ObjectMapper mapper = new ObjectMapper(); - payload = mapper.convertValue(data, new TypeReference>() {}); - } - - // 커스텀 전처리 - payload.put("custom_injected_data", "Billing System Check OK"); - log.info(" [Billing] 커스텀 파라미터 주입 완료"); - - // 부모 클래스의 레거시 공통 연동 메서드 호출 (PII 마스킹 포함) - Map result = executeLegacy("MCI", mappingId, payload); - - // 커스텀 후처리 - if ("SUCCESS".equals(result.get("status"))) { - result.put("billing_custom_insight", "청구 특화 후처리 로직이 적용되었습니다."); - } - return result; - } -} \ No newline at end of file +public interface BillingProcessService { + Object getStatus(BillingStatusReq req); +} diff --git a/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/BondIssueService.java b/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/BondIssueService.java index 6a8aa40d..7998368c 100644 --- a/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/BondIssueService.java +++ b/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/BondIssueService.java @@ -1,37 +1,7 @@ package io.shinhanlife.dap.dapmt.service; -import io.shinhanlife.dap.dapmt.annotation.McpFunction; -import io.shinhanlife.dap.dapmt.annotation.McpTool; -import io.shinhanlife.dap.dapmt.dto.BondCheckReq; -import io.shinhanlife.dap.dapmt.dto.BondIssueReq; +import io.shinhanlife.dap.dapmt.dto.*; -@McpTool( - routingType = "EAI", - categoryKey = "policy" -) -/** - * @package io.shinhanlife.dap.dapmt.service - * @className BondIssueService - * @description AX HUB 시스템 처리 클래스 - * @author 0986406 - * @create 2026.09.01 - *
- * ---------- 개정이력 ----------
- * 수정일      수정자    수정내용
- * ---------- -------- ---------------------------
- * 2026.09.01  0986406    최초생성
- * 
- * 
- */ -public class BondIssueService extends AbstractMcpToolService { - - @McpFunction(displayName = "check 툴", name = "check", register = false, description = "발행 가능 여부 조회 테스트", prompt = "디지털 증권 발행 한도가 충분한지 확인해줘.", mappingId = "BOND_001") - public Object check(BondCheckReq data) { - return executeLegacy("EAI", "BOND_001", data); - } - - @McpFunction(displayName = "issue 툴", name = "issue", register = false, description = "증권 발행 테스트1", prompt = "디지털 증권 발행 프로세스를 실행해.", mappingId = "BOND_002") - public Object issue(BondIssueReq data) { - return executeLegacy("EAI", "BOND_002", data); - } -} \ No newline at end of file +public interface BondIssueService { + Object check(BondCheckReq req); +} diff --git a/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/CommonUtilityService.java b/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/CommonUtilityService.java index 9b307da0..2fdb5bc3 100644 --- a/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/CommonUtilityService.java +++ b/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/CommonUtilityService.java @@ -1,43 +1,7 @@ package io.shinhanlife.dap.dapmt.service; -import io.shinhanlife.dap.dapmt.annotation.McpFunction; -import io.shinhanlife.dap.dapmt.annotation.McpTool; -import io.shinhanlife.dap.dapmt.dto.LeaveCountReq; -import io.shinhanlife.dap.dapmt.dto.VacationRegisterReq; +import io.shinhanlife.dap.dapmt.dto.*; -@McpTool( - routingType = "HTTP", - categoryKey = "hr" -) -/** - * @package io.shinhanlife.dap.dapmt.service - * @className CommonUtilityService - * @description AX HUB 시스템 처리 클래스 - * @author 0986406 - * @create 2026.09.01 - *
- * ---------- 개정이력 ----------
- * 수정일      수정자    수정내용
- * ---------- -------- ---------------------------
- * 2026.09.01  0986406    최초생성
- * 
- * 
- */ -public class CommonUtilityService extends AbstractMcpToolService { - - @McpFunction(register = false, displayName = "register_vacation 툴", name = "register_vacation", description = "휴가 등록", prompt = "내일 하루 연차 휴가를 등록해줘.", mappingId = "HR_VAC_01") - public Object registerVacation(VacationRegisterReq data) { - return executeLegacy("HTTP", "HR_VAC_01", data); - } - - @McpFunction(register = false, displayName = "get_leave_count 툴", name = "get_leave_count", description = "연차 갯수 조회", prompt = "현재 사용 가능한 남은 연차 일수를 알려줘.", mappingId = "HR_VAC_02") - public Object getLeaveCount(LeaveCountReq data) { - return executeLegacy("HTTP", "HR_VAC_02", data); - } - - @McpFunction(register = false, displayName = "secret_tool 툴", name = "secret_tool", description = "비공개 툴 테스트", prompt = "숨겨진 툴 강제 호출", mappingId = "SECRET_001", visible = false) - public Object secretTool(LeaveCountReq data) { - return executeLegacy("HTTP", "SECRET_001", data); - } - -} \ No newline at end of file +public interface CommonUtilityService { + Object registerVacation(VacationRegisterReq req); +} diff --git a/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/ContractInquiryService.java b/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/ContractInquiryService.java index 6498de73..633a41ed 100644 --- a/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/ContractInquiryService.java +++ b/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/ContractInquiryService.java @@ -1,37 +1,7 @@ package io.shinhanlife.dap.dapmt.service; -import io.shinhanlife.dap.dapmt.annotation.McpFunction; -import io.shinhanlife.dap.dapmt.annotation.McpTool; -import io.shinhanlife.dap.dapmt.dto.ContractDetailReq; -import io.shinhanlife.dap.dapmt.dto.ContractStatusReq; +import io.shinhanlife.dap.dapmt.dto.*; -@McpTool( - routingType = "HTTP", - categoryKey = "contract" -) -/** - * @package io.shinhanlife.dap.dapmt.service - * @className ContractInquiryService - * @description AX HUB 시스템 처리 클래스 - * @author 0986406 - * @create 2026.09.01 - *
- * ---------- 개정이력 ----------
- * 수정일      수정자    수정내용
- * ---------- -------- ---------------------------
- * 2026.09.01  0986406    최초생성
- * 
- * 
- */ -public class ContractInquiryService extends AbstractMcpToolService { - - @McpFunction(register = false, displayName = "contract_status 툴", name = "contract_status", description = "계약상태 조회", prompt = "김신한 고객의 현재 계약 상태를 조회해줘.", mappingId = "CNTR_001") - public Object getStatus(ContractStatusReq data) { - return executeLegacy("HTTP", "CNTR_001", data); - } - - @McpFunction(register = false, displayName = "contract_detail 툴", name = "contract_detail", description = "계약상세 조회", prompt = "김신한 고객의 계약 상세 내역을 알려줘.", mappingId = "CNTR_002") - public Object getDetail(ContractDetailReq data) { - return executeLegacy("HTTP", "CNTR_002", data); - } -} \ No newline at end of file +public interface ContractInquiryService { + Object getStatus(ContractStatusReq req); +} diff --git a/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/CustomerInfoService.java b/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/CustomerInfoService.java index 5d7c779a..f72abc14 100644 --- a/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/CustomerInfoService.java +++ b/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/CustomerInfoService.java @@ -1,37 +1,7 @@ package io.shinhanlife.dap.dapmt.service; -import io.shinhanlife.dap.dapmt.annotation.McpFunction; -import io.shinhanlife.dap.dapmt.annotation.McpTool; -import io.shinhanlife.dap.dapmt.dto.CustomerDetailReq; -import io.shinhanlife.dap.dapmt.dto.CustomerGradeReq; +import io.shinhanlife.dap.dapmt.dto.*; -@McpTool( - routingType = "TCP", - categoryKey = "customer" -) -/** - * @package io.shinhanlife.dap.dapmt.service - * @className CustomerInfoService - * @description AX HUB 시스템 처리 클래스 - * @author 0986406 - * @create 2026.09.01 - *
- * ---------- 개정이력 ----------
- * 수정일      수정자    수정내용
- * ---------- -------- ---------------------------
- * 2026.09.01  0986406    최초생성
- * 
- * 
- */ -public class CustomerInfoService extends AbstractMcpToolService { - - @McpFunction(register = false, displayName = "grade 툴", name = "grade", description = "고객등급 조회", prompt = "이 고객의 VIP 등급을 조회해줘.", mappingId = "CRM_001") - public Object getGrade(CustomerGradeReq req) { - return executeLegacy("TCP", "CRM_001", req); - } - - @McpFunction(register = false, displayName = "detail 툴", name = "detail", description = "고객상세 정보 조회", prompt = "이 고객의 상세 기본정보(주소, 연락처 등)를 알려줘.", mappingId = "CRM_002") - public Object getDetail(CustomerDetailReq data) { - return executeLegacy("TCP", "CRM_002", data); - } -} \ No newline at end of file +public interface CustomerInfoService { + Object getGrade(CustomerGradeReq req); +} diff --git a/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/DailyQuoteToolService.java b/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/DailyQuoteToolService.java index e5ac581a..6c954ece 100644 --- a/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/DailyQuoteToolService.java +++ b/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/DailyQuoteToolService.java @@ -1,55 +1,7 @@ package io.shinhanlife.dap.dapmt.service; -import io.shinhanlife.dap.dapmt.annotation.McpFunction; -import io.shinhanlife.dap.dapmt.annotation.McpTool; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; +import io.shinhanlife.dap.dapmt.dto.*; -import java.util.List; -import java.util.Random; - -/** - * @package io.shinhanlife.dap.dapmt.service - * @className DailyQuoteToolService - * @description 랜덤 명언 제공 툴 - * @author 0986406 - * @create 2026.09.01 - *
- * ---------- 개정이력 ----------
- * 수정일      수정자    수정내용
- * ---------- -------- ---------------------------
- * 2026.09.01  0986406    최초생성
- * 
- * 
- */ -@Slf4j -@Service -@McpTool( - routingType = "DIRECT", - categoryKey = "sample" -) -public class DailyQuoteToolService extends AbstractMcpToolService { - - public record DailyQuoteReq(String category) {} - public record DailyQuoteRes(String quote, String author) {} - - private final List quotes = List.of( - new DailyQuoteRes("성공은 매일 반복한 작은 노력들의 합이다.", "로버트 콜리어"), - new DailyQuoteRes("시작이 반이다.", "아리스토텔레스"), - new DailyQuoteRes("포기하지 않는 한 실패는 없다.", "알베르트 아인슈타인"), - new DailyQuoteRes("가장 큰 위험은 위험 없는 삶이다.", "스티븐 코비") - ); - - @McpFunction(register = false, displayName = "랜덤 명언 툴", name = "daily_quote", - description = "무작위로 영감을 주는 명언을 하나 가져옵니다.", - prompt = "오늘의 명언 하나 알려줘, 동기부여 명언 등", - mappingId = "QUOTE_001" - ) - public DailyQuoteRes execute(DailyQuoteReq req) { - int index = new Random().nextInt(quotes.size()); - DailyQuoteRes selected = quotes.get(index); - - log.info("[DailyQuoteTool] 명언 제공 완료: {}", selected.author()); - return selected; - } +public interface DailyQuoteToolService { + io.shinhanlife.dap.dapmt.service.impl.DailyQuoteToolServiceImpl.DailyQuoteRes execute(io.shinhanlife.dap.dapmt.service.impl.DailyQuoteToolServiceImpl.DailyQuoteReq req); } diff --git a/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/ExchangeRateToolService.java b/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/ExchangeRateToolService.java index b7f5918f..52f7abf8 100644 --- a/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/ExchangeRateToolService.java +++ b/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/ExchangeRateToolService.java @@ -1,59 +1,7 @@ package io.shinhanlife.dap.dapmt.service; -import io.shinhanlife.dap.dapmt.annotation.McpFunction; -import io.shinhanlife.dap.dapmt.annotation.McpTool; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; -import org.springframework.web.client.RestClient; +import io.shinhanlife.dap.dapmt.dto.*; -/** - * @package io.shinhanlife.dap.dapmt.service - * @className ExchangeRateToolService - * @description 실시간 환율 조회 툴 - * @author 0986406 - * @create 2026.09.01 - *
- * ---------- 개정이력 ----------
- * 수정일      수정자    수정내용
- * ---------- -------- ---------------------------
- * 2026.09.01  0986406    최초생성
- * 
- * 
- */ -@Slf4j -@Service -@McpTool( - routingType = "DIRECT", - categoryKey = "sample" -) -public class ExchangeRateToolService extends AbstractMcpToolService { - - public record ExchangeRateReq(String currencyCode) {} - public record ExchangeRateRes(String baseCurrency, String targetCurrency, double rate) {} - - private final RestClient restClient; - - public ExchangeRateToolService() { - this.restClient = RestClient.create(); - } - - @McpFunction(register = false, displayName = "실시간 환율 조회 툴", name = "exchange_rate", - description = "원하는 통화의 실시간 환율을 조회합니다. (예: USD, EUR, JPY)", - prompt = "현재 달러 환율 알려줘, 엔화 환율은?", - mappingId = "EXCHANGE_001" - ) - public ExchangeRateRes execute(ExchangeRateReq req) { - String targetCurrency = req.currencyCode() != null ? req.currencyCode().toUpperCase().trim() : "USD"; - - // 간단한 모의 데이터로 반환 (실제 구현 시 외부 연동) - double dummyRate = 1350.50; - if (targetCurrency.contains("JPY")) { - dummyRate = 905.20; - } else if (targetCurrency.contains("EUR")) { - dummyRate = 1450.30; - } - - log.info("[ExchangeRateTool] 환율 조회 완료: {} -> {}", targetCurrency, dummyRate); - return new ExchangeRateRes("KRW", targetCurrency, dummyRate); - } +public interface ExchangeRateToolService { + io.shinhanlife.dap.dapmt.service.impl.ExchangeRateToolServiceImpl.ExchangeRateRes execute(io.shinhanlife.dap.dapmt.service.impl.ExchangeRateToolServiceImpl.ExchangeRateReq req); } diff --git a/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/OnnbaMciToolService.java b/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/OnnbaMciToolService.java index 8ef520df..4a46bbad 100644 --- a/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/OnnbaMciToolService.java +++ b/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/OnnbaMciToolService.java @@ -1,71 +1,7 @@ package io.shinhanlife.dap.dapmt.service; -import io.shinhanlife.dap.common.integration.mci.component.AxhubMciComponent; -import io.shinhanlife.dap.dapmt.annotation.McpFunction; -import io.shinhanlife.dap.dapmt.annotation.McpTool; -import io.shinhanlife.dap.dapmt.dto.Onnba3011Req; -import io.shinhanlife.glow.communication.dto.Transfer; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; +import io.shinhanlife.dap.dapmt.dto.*; -/** - * @package io.shinhanlife.dap.dapmt.service - * @className OnnbaMciToolService - * @description 보종By가입설계한도계산조회 MCI 연동 툴 - * @author 0986406 - * @create 2026.09.01 - *
- * ---------- 개정이력 ----------
- * 수정일      수정자    수정내용
- * ---------- -------- ---------------------------
- * 2026.09.01  0986406    최초생성
- * 
- * 
- */ -@Slf4j -@Service -@RequiredArgsConstructor -@McpTool(routingType = "MCI", categoryKey = "other") -public class OnnbaMciToolService { - - private static final String INTERFACE_CODE_3011 = "CLCNNB00001"; - - // Glow 기반의 AxhubMciComponent 주입 - private final AxhubMciComponent mci; - - /** - * AI Agent가 호출하게 될 메서드입니다. - * @McpFunction 어노테이션 하나로 AI 도구로 자동 노출 및 라우팅됩니다. - */ - @McpFunction( - register = false, - name = "calculate_subscription_limit", - displayName = "보종By가입설계한도계산조회", - description = "MCI 연동을 통해 보종By가입설계한도계산조회를 수행합니다.", - prompt = "가입설계 한도를 계산하고 조회해줘.", - mappingId = INTERFACE_CODE_3011 - ) - public Object callOnnba3011(Onnba3011Req req) { - log.info("[MCI Tool] 보종By가입설계한도계산조회 요청 수신."); - - try { - // GlowMciComponent 표준 방식 (Transfer 객체 이용) - Transfer resTransfer = mci.callTo( - INTERFACE_CODE_3011, - null, // rcvSvcId - req, - Object.class - ); - - log.info("[MCI Tool] Glow 기반 MCI 연동 성공."); - - // 결과 반환 (실제로는 resTransfer.getBody() 리턴) - return resTransfer.getBody() != null ? resTransfer.getBody() : "{\"status\":\"SUCCESS\", \"message\":\"GlowMciComponent 통신 완료\"}"; - - } catch (Exception e) { - log.error("[MCI Tool] MCI 연동 중 오류 발생: {}", e.getMessage(), e); - return "{\"status\":\"ERROR\", \"message\":\"MCI 통신 실패: " + e.getMessage() + "\"}"; - } - } +public interface OnnbaMciToolService { + Object callOnnba3011(Onnba3011Req req); } diff --git a/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/SampleMciToolService.java b/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/SampleMciToolService.java index f6f55caf..1b38bd3f 100644 --- a/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/SampleMciToolService.java +++ b/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/SampleMciToolService.java @@ -1,84 +1,7 @@ package io.shinhanlife.dap.dapmt.service; -import io.shinhanlife.dap.common.adapter.sender.ShinhanMciSender; -import io.shinhanlife.dap.common.integration.mci.dto.MciRequestWrapper; -import io.shinhanlife.dap.common.integration.mci.dto.ShinhanCommonHeaderDto; -import io.shinhanlife.dap.dapmt.annotation.McpFunction; -import io.shinhanlife.dap.dapmt.annotation.McpTool; -import lombok.Data; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Value; +import io.shinhanlife.dap.dapmt.dto.*; -/** - * @package io.shinhanlife.dap.dapmt.service - * @className SampleMciToolService - * @description AX HUB 시스템 처리 클래스 - * @author 0986406 - * @create 2026.09.01 - *
- * ---------- 개정이력 ----------
- * 수정일      수정자    수정내용
- * ---------- -------- ---------------------------
- * 2026.09.01  0986406    최초생성
- * 
- * 
- */ -@Slf4j -@RequiredArgsConstructor -@McpTool(routingType = "MCI", categoryKey = "other") // MCP Tool 등록 어노테이션 -public class SampleMciToolService { - - // EIMS/MCI 발송을 담당하는 Sender 주입 - private final ShinhanMciSender shinhanMciSender; - - @Value("${shinhan.integration.mci.default-url:http://localhost:8081/api/mock/esb/api}") - private String mciTargetUrl; - - // AI가 인식할 파라미터 DTO - @Data - public static class SampleMciReqDto { - private String customerId; - private String inquiryType; - } - - /** - * AI Agent가 호출하게 될 메서드입니다. - */ - @McpFunction(register = false, name = "inquiry_customer_mci", - displayName = "고객 정보 조회 (MCI)", - description = "MCI 연동을 통해 고객의 상세 정보를 조회합니다.", - prompt = "고객 정보를 조회해줘.", - mappingId = "CUST_INQ_001" - ) - public Object inquiryCustomerInfo(SampleMciReqDto req) { - log.info("[MCI Tool] 고객 정보 조회 요청 수신. 고객ID: {}", req.getCustomerId()); - - try { - // 1. MCI 전문 통신을 위한 Wrapper 객체 생성 - MciRequestWrapper wrapper = new MciRequestWrapper<>(); - - // 2. 공통 헤더 세팅 (인터페이스 ID, 서비스 ID 등 업무에 맞게 설정) - ShinhanCommonHeaderDto header = new ShinhanCommonHeaderDto(); - header.setItrIfId("CUST_INQ_001"); - header.setRcvSvcId("INQ9040"); - wrapper.setTgrmCmnnhddValu(header); - - // 3. 비즈니스 데이터(Body) 세팅 - wrapper.setBody(req); - - // 4. ShinhanMciSender를 통해 실제 연동 수행 및 응답 수신 - log.info("[MCI Tool] ShinhanMciSender 연동 시작... (URL: {})", mciTargetUrl); - String responseJson = shinhanMciSender.send(mciTargetUrl, wrapper); - - log.info("[MCI Tool] MCI 연동 성공. 응답 수신 완료"); - - // 결과 반환 (이 문자열은 JSON 파싱되거나 그대로 AI에게 전달됩니다) - return responseJson; - - } catch (Exception e) { - log.error("[MCI Tool] MCI 연동 중 오류 발생: {}", e.getMessage(), e); - return "{\"status\":\"ERROR\", \"message\":\"MCI 통신 실패: " + e.getMessage() + "\"}"; - } - } +public interface SampleMciToolService { + Object inquiryCustomerInfo(io.shinhanlife.dap.dapmt.service.impl.SampleMciToolServiceImpl.SampleMciReqDto req); } diff --git a/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/SampleStringToolService.java b/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/SampleStringToolService.java index 4175fb00..0990d3ee 100644 --- a/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/SampleStringToolService.java +++ b/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/SampleStringToolService.java @@ -1,56 +1,7 @@ package io.shinhanlife.dap.dapmt.service; -import io.shinhanlife.dap.dapmt.annotation.McpFunction; -import io.shinhanlife.dap.dapmt.annotation.McpTool; -import io.shinhanlife.dap.dapmt.dto.MciSampleStringRes; -import io.shinhanlife.dap.dapmt.dto.SampleStringReq; -import io.shinhanlife.glow.util.GlowMciParser; -import org.springframework.stereotype.Service; +import io.shinhanlife.dap.dapmt.dto.*; -import java.util.List; -import java.util.Map; - -/** - * @package io.shinhanlife.dap.dapmt.service - * @className SampleStringToolService - * @description AX HUB 시스템 처리 클래스 - * @author 0986406 - * @create 2026.09.01 - *
- * ---------- 개정이력 ----------
- * 수정일      수정자    수정내용
- * ---------- -------- ---------------------------
- * 2026.09.01  0986406    최초생성
- * 
- * 
- */ -@Service -@McpTool( - routingType = "MCI", - categoryKey = "common" -) -public class SampleStringToolService extends AbstractMcpToolService { - - @McpFunction(register = false, displayName = "get_sample_string 툴", name = "get_sample_string", - description = "MCI String 버전과 GlowTrgmField 파싱을 테스트하는 샘플 툴입니다.", - prompt = "MCI 전문(String) 연계 및 고정 길이 파싱 테스트 해줘.", - mappingId = "TRGM_001" - ) - public Object execute(SampleStringReq req) { - // 1. EIMS(Legacy)를 통해 원본 고정 길이 문자열을 받아옵니다. - // 스펙에 mciFormat = STRING 힌트를 주어 전문 통신으로 자동 분기되게 합니다. - List> spec = List.of( - Map.of("mciFormat", "STRING") - ); - Map result = executeLegacy("MCI", "TRGM_001", req, spec); - - if (!"SUCCESS".equals(result.get("status"))) { - return result; - } - - String rawStringResponse = (String) result.get("legacy_response"); - - // 2. 받아온 고정 길이 전문(String)을 GlowMciParser를 이용해 DTO로 파싱합니다. - return GlowMciParser.parse(rawStringResponse, MciSampleStringRes.class); - } +public interface SampleStringToolService { + Object execute(SampleStringReq req); } diff --git a/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/TemplateUtilityService.java b/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/TemplateUtilityService.java index b444ad31..b761dc40 100644 --- a/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/TemplateUtilityService.java +++ b/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/TemplateUtilityService.java @@ -1,64 +1,7 @@ package io.shinhanlife.dap.dapmt.service; -import io.shinhanlife.dap.dapmt.annotation.McpFunction; -import io.shinhanlife.dap.dapmt.annotation.McpTool; -import io.shinhanlife.dap.dapmt.dto.TemplateDownloadReq; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; +import io.shinhanlife.dap.dapmt.dto.*; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -@Slf4j -@Service -@McpTool( - routingType = "HTTP", - categoryKey = "common" -) -/** - * @package io.shinhanlife.dap.dapmt.service - * @className TemplateUtilityService - * @description AX HUB 시스템 처리 클래스 - * @author 0986406 - * @create 2026.09.01 - *
- * ---------- 개정이력 ----------
- * 수정일      수정자    수정내용
- * ---------- -------- ---------------------------
- * 2026.09.01  0986406    최초생성
- * 
- * 
- */ -public class TemplateUtilityService extends AbstractMcpToolService { - - @McpFunction(register = false, displayName = "get_template_file_url 툴", name = "get_template_file_url", - description = "특정 템플릿의 양식 파일(엑셀, 워드 등)을 다운로드 받을 수 있는 시스템 URL을 반환합니다. AI는 이 URL을 사용자에게 마크다운 링크 형태로 제공해야 합니다.", - prompt = "요청하신 템플릿 양식 파일 다운로드 URL은 다음과 같습니다. 클릭하여 다운로드하세요:" - ) - public Map getTemplateFileUrl(TemplateDownloadReq data) { - try { - String templateId = (data != null && data.getTemplateId() != null) ? data.getTemplateId().toLowerCase() : "default"; - log.info("MCP 툴 호출됨: get_template_file_url, 요청 템플릿 ID: {}", templateId); - - String fileName = "sample_" + templateId + ".xlsx"; - String downloadUrl = "https://axhub-file-server.shinhanlife.io/downloads/" + fileName; - - Map result = new HashMap<>(); - result.put("status", "success"); - - Map contract = new HashMap<>(); - contract.put("fileName", fileName); - contract.put("downloadUrl", downloadUrl); - contract.put("message", "다운로드 링크가 성공적으로 생성되었습니다. AI는 이 링크를 마크다운 형식으로 사용자에게 전달해야 합니다."); - contract.put("status", "success"); - - result.put("contracts", Collections.singletonList(contract)); - - return result; - } catch (Exception e) { - log.error("getTemplateFileUrl 내부 예외 발생", e); - throw new RuntimeException("템플릿 URL 생성 실패", e); - } - } -} \ No newline at end of file +public interface TemplateUtilityService { + java.util.Map getTemplateFileUrl(TemplateDownloadReq req); +} diff --git a/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/WeatherToolService.java b/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/WeatherToolService.java index 7e899939..00294fde 100644 --- a/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/WeatherToolService.java +++ b/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/WeatherToolService.java @@ -1,115 +1,7 @@ package io.shinhanlife.dap.dapmt.service; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import io.shinhanlife.dap.dapmt.annotation.McpFunction; -import io.shinhanlife.dap.dapmt.annotation.McpTool; -import io.shinhanlife.dap.dapmt.dto.WeatherReq; -import io.shinhanlife.dap.dapmt.dto.WeatherRes; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; -import org.springframework.web.client.RestClient; +import io.shinhanlife.dap.dapmt.dto.*; -import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; - -/** - * @package io.shinhanlife.dap.dapmt.service - * @className WeatherToolService - * @description AX HUB 시스템 처리 클래스 - * @author 0986406 - * @create 2026.07.14 - *
- * ---------- 개정이력 ----------
- * 수정일      수정자    수정내용
- * ---------- -------- ---------------------------
- * 2026.07.14  0986406    최초생성
- * 
- * 
- */ -@Slf4j -@Service -@McpTool( - routingType = "DIRECT", - categoryKey = "sample" -) -public class WeatherToolService extends AbstractMcpToolService { - - private final RestClient restClient; - - public WeatherToolService() { - this.restClient = RestClient.create(); - } - - @McpFunction(register = false, displayName = "날씨 조회 툴", name = "weather", - description = "특정 도시의 현재 날씨, 온도, 풍속 정보를 조회합니다.", - prompt = "서울 날씨 알려줘, 부산 기온 알려줘 등 실시간 기상 조회", - mappingId = "WEATHER_001" - ) - public WeatherRes execute(WeatherReq req) { - String city = req.city() != null ? req.city().trim() : "서울"; - - // 지역별 위경도 매핑 (간단한 예시) - double lat = 37.566; - double lon = 126.978; - - if (city.contains("부산")) { - lat = 35.179; - lon = 129.075; - } else if (city.contains("제주")) { - lat = 33.499; - lon = 126.531; - } else if (city.contains("인천")) { - lat = 37.456; - lon = 126.705; - } - - try { - String newRequestId = java.util.UUID.randomUUID().toString(); - String url = String.format("https://api.open-meteo.com/v1/forecast?latitude=%f&longitude=%f¤t_weather=true", lat, lon); - - log.info("[WeatherTool] OUTBOUND HTTP IN - request-id: {}", newRequestId); - log.info("[WeatherTool] 날씨 조회 요청 URL: {}", url); - - String responseStr = restClient.get() - .uri(url) - .header("request-id", newRequestId) - .retrieve() - .body(String.class); - - log.info("[WeatherTool] OUTBOUND HTTP OUT - request-id: {}", newRequestId); - - ObjectMapper mapper = new ObjectMapper(); - JsonNode response = mapper.readTree(responseStr); - - if (response != null && response.has("current_weather")) { - JsonNode current = response.get("current_weather"); - double temp = current.path("temperature").asDouble(); - double windSpeed = current.path("windspeed").asDouble(); - String time = current.path("time").asText(); - - int weatherCode = current.path("weathercode").asInt(); - String summary = parseWeatherCode(weatherCode); - - String formattedTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")); - - return new WeatherRes(city, temp, windSpeed, formattedTime, summary); - } - } catch (Exception e) { - log.error("[WeatherTool] 날씨 API 연동 실패: {}", e.getMessage()); - return new WeatherRes(city, 0.0, 0.0, "", "날씨 정보를 불러오는데 실패했습니다."); - } - - return new WeatherRes(city, 0.0, 0.0, "", "알 수 없는 응답입니다."); - } - - private String parseWeatherCode(int code) { - if (code == 0) return "맑음 (Clear)"; - if (code >= 1 && code <= 3) return "구름조금/흐림 (Cloudy)"; - if (code >= 45 && code <= 48) return "안개 (Fog)"; - if (code >= 51 && code <= 67) return "비/이슬비 (Rain)"; - if (code >= 71 && code <= 77) return "눈 (Snow)"; - if (code >= 95) return "뇌우/천둥번개 (Thunderstorm)"; - return "알 수 없음 (Unknown)"; - } +public interface WeatherToolService { + WeatherRes execute(WeatherReq req); } diff --git a/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/impl/BalanceServiceImpl.java b/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/impl/BalanceServiceImpl.java new file mode 100644 index 00000000..592ec313 --- /dev/null +++ b/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/impl/BalanceServiceImpl.java @@ -0,0 +1,55 @@ +package io.shinhanlife.dap.dapmt.service.impl; + + +/** + * @package io.shinhanlife.dap.dapmt.service + * @className BalanceService + * @description AX HUB 시스템 처리 클래스 + * @author 0986406 + * @create 2026.09.01 + *
+ * ---------- 개정이력 ----------
+ * 수정일      수정자    수정내용
+ * ---------- -------- ---------------------------
+ * 2026.09.01  0986406    최초생성
+ * 
+ * 
+ */ +import io.shinhanlife.dap.dapmt.annotation.McpFunction; +import io.shinhanlife.dap.dapmt.annotation.McpTool; +import io.shinhanlife.dap.dapmt.service.BalanceService; +import io.shinhanlife.dap.dapmt.service.AbstractMcpToolService; +import io.shinhanlife.dap.dapmt.dto.BalanceReq; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.Map; + +@Slf4j +@Service +@McpTool(routingType = "MCI", categoryKey = "common") +public class BalanceServiceImpl extends AbstractMcpToolService implements BalanceService { + + @McpFunction(register = false, displayName = "balance 툴", name = "balance", + description = "고객의 계좌 잔액을 조회합니다.", + prompt = "고객 계좌 잔액을 조회해줘.", + mappingId = "ACC_001" + ) + @Override + public Object execute(BalanceReq req) { + log.info("[Balance] 계좌 잔액 조회 요청 수신. 계좌번호: {}", req.getAccountNumber()); + + // 레거시 연동 + Map result = executeLegacy("MCI", "ACC_001", req); + + // 가짜 데이터 응답 매핑 (AI 에이전트가 그럴듯하게 보여주기 위함) + if ("SUCCESS".equals(result.get("status"))) { + result.put("accountNumber", req.getAccountNumber()); + result.put("balance", 1520300); // 1,520,300원 (가상의 잔액) + result.put("currency", "KRW"); + result.put("message", "잔액 조회가 완료되었습니다."); + } + + return result; + } +} diff --git a/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/impl/BillingProcessServiceImpl.java b/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/impl/BillingProcessServiceImpl.java new file mode 100644 index 00000000..2ff649fc --- /dev/null +++ b/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/impl/BillingProcessServiceImpl.java @@ -0,0 +1,71 @@ +package io.shinhanlife.dap.dapmt.service.impl; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import io.shinhanlife.dap.dapmt.annotation.McpFunction; +import io.shinhanlife.dap.dapmt.annotation.McpTool; +import io.shinhanlife.dap.dapmt.service.BillingProcessService; +import io.shinhanlife.dap.dapmt.service.AbstractMcpToolService; +import io.shinhanlife.dap.dapmt.dto.BillingProcessReq; +import io.shinhanlife.dap.dapmt.dto.BillingStatusReq; + +import java.util.HashMap; +import java.util.Map; + +@McpTool( + routingType = "MCI", + categoryKey = "claim" +) +/** + * @package io.shinhanlife.dap.dapmt.service + * @className BillingProcessService + * @description AX HUB 시스템 처리 클래스 + * @author 0986406 + * @create 2026.09.01 + *
+ * ---------- 개정이력 ----------
+ * 수정일      수정자    수정내용
+ * ---------- -------- ---------------------------
+ * 2026.09.01  0986406    최초생성
+ * 
+ * 
+ */ +@lombok.extern.slf4j.Slf4j +public class BillingProcessServiceImpl extends AbstractMcpToolService implements BillingProcessService { + + @McpFunction(register = false, displayName = "status 툴", name = "status", description = "청구심사 상태 조회", prompt = "현재 접수된 청구건 상태를 알려줘.", mappingId = "BILL_001") + @Override + public Object getStatus(BillingStatusReq data) { + return executeBillingLogic("BILL_001", data); + } + + @McpFunction(register = false, displayName = "process 툴", name = "process", description = "청구 처리", prompt = "현재 접수된 청구건에 대한 심사 처리를 진행해.", mappingId = "BILL_002") + public Object processBilling(BillingProcessReq data) { + return executeBillingLogic("BILL_002", data); + } + + private Object executeBillingLogic(String mappingId, Object data) { + log.info(" [Billing] 청구 처리 전용 커스텀 전/후처리 로직 수행 시작"); + + Map payload; + if (data == null) { + payload = new HashMap<>(); + } else { + ObjectMapper mapper = new ObjectMapper(); + payload = mapper.convertValue(data, new TypeReference>() {}); + } + + // 커스텀 전처리 + payload.put("custom_injected_data", "Billing System Check OK"); + log.info(" [Billing] 커스텀 파라미터 주입 완료"); + + // 부모 클래스의 레거시 공통 연동 메서드 호출 (PII 마스킹 포함) + Map result = executeLegacy("MCI", mappingId, payload); + + // 커스텀 후처리 + if ("SUCCESS".equals(result.get("status"))) { + result.put("billing_custom_insight", "청구 특화 후처리 로직이 적용되었습니다."); + } + return result; + } +} \ No newline at end of file diff --git a/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/impl/BondIssueServiceImpl.java b/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/impl/BondIssueServiceImpl.java new file mode 100644 index 00000000..11339381 --- /dev/null +++ b/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/impl/BondIssueServiceImpl.java @@ -0,0 +1,40 @@ +package io.shinhanlife.dap.dapmt.service.impl; + +import io.shinhanlife.dap.dapmt.annotation.McpFunction; +import io.shinhanlife.dap.dapmt.annotation.McpTool; +import io.shinhanlife.dap.dapmt.service.BondIssueService; +import io.shinhanlife.dap.dapmt.service.AbstractMcpToolService; +import io.shinhanlife.dap.dapmt.dto.BondCheckReq; +import io.shinhanlife.dap.dapmt.dto.BondIssueReq; + +@McpTool( + routingType = "EAI", + categoryKey = "policy" +) +/** + * @package io.shinhanlife.dap.dapmt.service + * @className BondIssueService + * @description AX HUB 시스템 처리 클래스 + * @author 0986406 + * @create 2026.09.01 + *
+ * ---------- 개정이력 ----------
+ * 수정일      수정자    수정내용
+ * ---------- -------- ---------------------------
+ * 2026.09.01  0986406    최초생성
+ * 
+ * 
+ */ +public class BondIssueServiceImpl extends AbstractMcpToolService implements BondIssueService { + + @McpFunction(displayName = "check 툴", name = "check", register = false, description = "발행 가능 여부 조회 테스트", prompt = "디지털 증권 발행 한도가 충분한지 확인해줘.", mappingId = "BOND_001") + @Override + public Object check(BondCheckReq data) { + return executeLegacy("EAI", "BOND_001", data); + } + + @McpFunction(displayName = "issue 툴", name = "issue", register = false, description = "증권 발행 테스트1", prompt = "디지털 증권 발행 프로세스를 실행해.", mappingId = "BOND_002") + public Object issue(BondIssueReq data) { + return executeLegacy("EAI", "BOND_002", data); + } +} \ No newline at end of file diff --git a/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/impl/CommonUtilityServiceImpl.java b/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/impl/CommonUtilityServiceImpl.java new file mode 100644 index 00000000..56cc2d62 --- /dev/null +++ b/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/impl/CommonUtilityServiceImpl.java @@ -0,0 +1,46 @@ +package io.shinhanlife.dap.dapmt.service.impl; + +import io.shinhanlife.dap.dapmt.annotation.McpFunction; +import io.shinhanlife.dap.dapmt.annotation.McpTool; +import io.shinhanlife.dap.dapmt.service.CommonUtilityService; +import io.shinhanlife.dap.dapmt.service.AbstractMcpToolService; +import io.shinhanlife.dap.dapmt.dto.LeaveCountReq; +import io.shinhanlife.dap.dapmt.dto.VacationRegisterReq; + +@McpTool( + routingType = "HTTP", + categoryKey = "hr" +) +/** + * @package io.shinhanlife.dap.dapmt.service + * @className CommonUtilityService + * @description AX HUB 시스템 처리 클래스 + * @author 0986406 + * @create 2026.09.01 + *
+ * ---------- 개정이력 ----------
+ * 수정일      수정자    수정내용
+ * ---------- -------- ---------------------------
+ * 2026.09.01  0986406    최초생성
+ * 
+ * 
+ */ +public class CommonUtilityServiceImpl extends AbstractMcpToolService implements CommonUtilityService { + + @McpFunction(register = false, displayName = "register_vacation 툴", name = "register_vacation", description = "휴가 등록", prompt = "내일 하루 연차 휴가를 등록해줘.", mappingId = "HR_VAC_01") + @Override + public Object registerVacation(VacationRegisterReq data) { + return executeLegacy("HTTP", "HR_VAC_01", data); + } + + @McpFunction(register = false, displayName = "get_leave_count 툴", name = "get_leave_count", description = "연차 갯수 조회", prompt = "현재 사용 가능한 남은 연차 일수를 알려줘.", mappingId = "HR_VAC_02") + public Object getLeaveCount(LeaveCountReq data) { + return executeLegacy("HTTP", "HR_VAC_02", data); + } + + @McpFunction(register = false, displayName = "secret_tool 툴", name = "secret_tool", description = "비공개 툴 테스트", prompt = "숨겨진 툴 강제 호출", mappingId = "SECRET_001", visible = false) + public Object secretTool(LeaveCountReq data) { + return executeLegacy("HTTP", "SECRET_001", data); + } + +} \ No newline at end of file diff --git a/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/impl/ContractInquiryServiceImpl.java b/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/impl/ContractInquiryServiceImpl.java new file mode 100644 index 00000000..eebe0c87 --- /dev/null +++ b/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/impl/ContractInquiryServiceImpl.java @@ -0,0 +1,40 @@ +package io.shinhanlife.dap.dapmt.service.impl; + +import io.shinhanlife.dap.dapmt.annotation.McpFunction; +import io.shinhanlife.dap.dapmt.annotation.McpTool; +import io.shinhanlife.dap.dapmt.service.ContractInquiryService; +import io.shinhanlife.dap.dapmt.service.AbstractMcpToolService; +import io.shinhanlife.dap.dapmt.dto.ContractDetailReq; +import io.shinhanlife.dap.dapmt.dto.ContractStatusReq; + +@McpTool( + routingType = "HTTP", + categoryKey = "contract" +) +/** + * @package io.shinhanlife.dap.dapmt.service + * @className ContractInquiryService + * @description AX HUB 시스템 처리 클래스 + * @author 0986406 + * @create 2026.09.01 + *
+ * ---------- 개정이력 ----------
+ * 수정일      수정자    수정내용
+ * ---------- -------- ---------------------------
+ * 2026.09.01  0986406    최초생성
+ * 
+ * 
+ */ +public class ContractInquiryServiceImpl extends AbstractMcpToolService implements ContractInquiryService { + + @McpFunction(register = false, displayName = "contract_status 툴", name = "contract_status", description = "계약상태 조회", prompt = "김신한 고객의 현재 계약 상태를 조회해줘.", mappingId = "CNTR_001") + @Override + public Object getStatus(ContractStatusReq data) { + return executeLegacy("HTTP", "CNTR_001", data); + } + + @McpFunction(register = false, displayName = "contract_detail 툴", name = "contract_detail", description = "계약상세 조회", prompt = "김신한 고객의 계약 상세 내역을 알려줘.", mappingId = "CNTR_002") + public Object getDetail(ContractDetailReq data) { + return executeLegacy("HTTP", "CNTR_002", data); + } +} \ No newline at end of file diff --git a/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/impl/CustomerInfoServiceImpl.java b/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/impl/CustomerInfoServiceImpl.java new file mode 100644 index 00000000..9d60bd5c --- /dev/null +++ b/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/impl/CustomerInfoServiceImpl.java @@ -0,0 +1,40 @@ +package io.shinhanlife.dap.dapmt.service.impl; + +import io.shinhanlife.dap.dapmt.annotation.McpFunction; +import io.shinhanlife.dap.dapmt.annotation.McpTool; +import io.shinhanlife.dap.dapmt.service.CustomerInfoService; +import io.shinhanlife.dap.dapmt.service.AbstractMcpToolService; +import io.shinhanlife.dap.dapmt.dto.CustomerDetailReq; +import io.shinhanlife.dap.dapmt.dto.CustomerGradeReq; + +@McpTool( + routingType = "TCP", + categoryKey = "customer" +) +/** + * @package io.shinhanlife.dap.dapmt.service + * @className CustomerInfoService + * @description AX HUB 시스템 처리 클래스 + * @author 0986406 + * @create 2026.09.01 + *
+ * ---------- 개정이력 ----------
+ * 수정일      수정자    수정내용
+ * ---------- -------- ---------------------------
+ * 2026.09.01  0986406    최초생성
+ * 
+ * 
+ */ +public class CustomerInfoServiceImpl extends AbstractMcpToolService implements CustomerInfoService { + + @McpFunction(register = false, displayName = "grade 툴", name = "grade", description = "고객등급 조회", prompt = "이 고객의 VIP 등급을 조회해줘.", mappingId = "CRM_001") + @Override + public Object getGrade(CustomerGradeReq req) { + return executeLegacy("TCP", "CRM_001", req); + } + + @McpFunction(register = false, displayName = "detail 툴", name = "detail", description = "고객상세 정보 조회", prompt = "이 고객의 상세 기본정보(주소, 연락처 등)를 알려줘.", mappingId = "CRM_002") + public Object getDetail(CustomerDetailReq data) { + return executeLegacy("TCP", "CRM_002", data); + } +} \ No newline at end of file diff --git a/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/impl/DailyQuoteToolServiceImpl.java b/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/impl/DailyQuoteToolServiceImpl.java new file mode 100644 index 00000000..b0894a99 --- /dev/null +++ b/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/impl/DailyQuoteToolServiceImpl.java @@ -0,0 +1,57 @@ +package io.shinhanlife.dap.dapmt.service.impl; + +import io.shinhanlife.dap.dapmt.annotation.McpFunction; +import io.shinhanlife.dap.dapmt.annotation.McpTool; +import io.shinhanlife.dap.dapmt.service.DailyQuoteToolService; +import io.shinhanlife.dap.dapmt.service.AbstractMcpToolService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Random; + +/** + * @package io.shinhanlife.dap.dapmt.service + * @className DailyQuoteToolService + * @description 랜덤 명언 제공 툴 + * @author 0986406 + * @create 2026.09.01 + *
+ * ---------- 개정이력 ----------
+ * 수정일      수정자    수정내용
+ * ---------- -------- ---------------------------
+ * 2026.09.01  0986406    최초생성
+ * 
+ * 
+ */ +@Slf4j +@Service +@McpTool( + routingType = "DIRECT", + categoryKey = "sample" +) +public class DailyQuoteToolServiceImpl extends AbstractMcpToolService implements DailyQuoteToolService { + + public record DailyQuoteReq(String category) {} + public record DailyQuoteRes(String quote, String author) {} + + private final List quotes = List.of( + new DailyQuoteRes("성공은 매일 반복한 작은 노력들의 합이다.", "로버트 콜리어"), + new DailyQuoteRes("시작이 반이다.", "아리스토텔레스"), + new DailyQuoteRes("포기하지 않는 한 실패는 없다.", "알베르트 아인슈타인"), + new DailyQuoteRes("가장 큰 위험은 위험 없는 삶이다.", "스티븐 코비") + ); + + @McpFunction(register = false, displayName = "랜덤 명언 툴", name = "daily_quote", + description = "무작위로 영감을 주는 명언을 하나 가져옵니다.", + prompt = "오늘의 명언 하나 알려줘, 동기부여 명언 등", + mappingId = "QUOTE_001" + ) + public DailyQuoteRes execute(DailyQuoteReq req) { + int index = new Random().nextInt(quotes.size()); + DailyQuoteRes selected = quotes.get(index); + + log.info("[DailyQuoteTool] 명언 제공 완료: {}", selected.author()); + return selected; + } +} diff --git a/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/impl/ExchangeRateToolServiceImpl.java b/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/impl/ExchangeRateToolServiceImpl.java new file mode 100644 index 00000000..71b7db63 --- /dev/null +++ b/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/impl/ExchangeRateToolServiceImpl.java @@ -0,0 +1,61 @@ +package io.shinhanlife.dap.dapmt.service.impl; + +import io.shinhanlife.dap.dapmt.annotation.McpFunction; +import io.shinhanlife.dap.dapmt.annotation.McpTool; +import io.shinhanlife.dap.dapmt.service.ExchangeRateToolService; +import io.shinhanlife.dap.dapmt.service.AbstractMcpToolService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestClient; + +/** + * @package io.shinhanlife.dap.dapmt.service + * @className ExchangeRateToolService + * @description 실시간 환율 조회 툴 + * @author 0986406 + * @create 2026.09.01 + *
+ * ---------- 개정이력 ----------
+ * 수정일      수정자    수정내용
+ * ---------- -------- ---------------------------
+ * 2026.09.01  0986406    최초생성
+ * 
+ * 
+ */ +@Slf4j +@Service +@McpTool( + routingType = "DIRECT", + categoryKey = "sample" +) +public class ExchangeRateToolServiceImpl extends AbstractMcpToolService implements ExchangeRateToolService { + + public record ExchangeRateReq(String currencyCode) {} + public record ExchangeRateRes(String baseCurrency, String targetCurrency, double rate) {} + + private final RestClient restClient; + + public ExchangeRateToolServiceImpl() { + this.restClient = RestClient.create(); + } + + @McpFunction(register = false, displayName = "실시간 환율 조회 툴", name = "exchange_rate", + description = "원하는 통화의 실시간 환율을 조회합니다. (예: USD, EUR, JPY)", + prompt = "현재 달러 환율 알려줘, 엔화 환율은?", + mappingId = "EXCHANGE_001" + ) + public ExchangeRateRes execute(ExchangeRateReq req) { + String targetCurrency = req.currencyCode() != null ? req.currencyCode().toUpperCase().trim() : "USD"; + + // 간단한 모의 데이터로 반환 (실제 구현 시 외부 연동) + double dummyRate = 1350.50; + if (targetCurrency.contains("JPY")) { + dummyRate = 905.20; + } else if (targetCurrency.contains("EUR")) { + dummyRate = 1450.30; + } + + log.info("[ExchangeRateTool] 환율 조회 완료: {} -> {}", targetCurrency, dummyRate); + return new ExchangeRateRes("KRW", targetCurrency, dummyRate); + } +} diff --git a/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/impl/OnnbaMciToolServiceImpl.java b/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/impl/OnnbaMciToolServiceImpl.java new file mode 100644 index 00000000..dc1c0fc6 --- /dev/null +++ b/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/impl/OnnbaMciToolServiceImpl.java @@ -0,0 +1,74 @@ +package io.shinhanlife.dap.dapmt.service.impl; + +import io.shinhanlife.dap.common.integration.mci.component.AxhubMciComponent; +import io.shinhanlife.dap.dapmt.annotation.McpFunction; +import io.shinhanlife.dap.dapmt.annotation.McpTool; +import io.shinhanlife.dap.dapmt.service.OnnbaMciToolService; +import io.shinhanlife.dap.dapmt.service.AbstractMcpToolService; +import io.shinhanlife.dap.dapmt.dto.Onnba3011Req; +import io.shinhanlife.glow.communication.dto.Transfer; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * @package io.shinhanlife.dap.dapmt.service + * @className OnnbaMciToolService + * @description 보종By가입설계한도계산조회 MCI 연동 툴 + * @author 0986406 + * @create 2026.09.01 + *
+ * ---------- 개정이력 ----------
+ * 수정일      수정자    수정내용
+ * ---------- -------- ---------------------------
+ * 2026.09.01  0986406    최초생성
+ * 
+ * 
+ */ +@Slf4j +@Service +@RequiredArgsConstructor +@McpTool(routingType = "MCI", categoryKey = "other") +public class OnnbaMciToolServiceImpl implements OnnbaMciToolService { + + private static final String INTERFACE_CODE_3011 = "CLCNNB00001"; + + // Glow 기반의 AxhubMciComponent 주입 + private final AxhubMciComponent mci; + + /** + * AI Agent가 호출하게 될 메서드입니다. + * @McpFunction 어노테이션 하나로 AI 도구로 자동 노출 및 라우팅됩니다. + */ + @McpFunction( + register = false, + name = "calculate_subscription_limit", + displayName = "보종By가입설계한도계산조회", + description = "MCI 연동을 통해 보종By가입설계한도계산조회를 수행합니다.", + prompt = "가입설계 한도를 계산하고 조회해줘.", + mappingId = INTERFACE_CODE_3011 + ) + @Override + public Object callOnnba3011(Onnba3011Req req) { + log.info("[MCI Tool] 보종By가입설계한도계산조회 요청 수신."); + + try { + // GlowMciComponent 표준 방식 (Transfer 객체 이용) + Transfer resTransfer = mci.callTo( + INTERFACE_CODE_3011, + null, // rcvSvcId + req, + Object.class + ); + + log.info("[MCI Tool] Glow 기반 MCI 연동 성공."); + + // 결과 반환 (실제로는 resTransfer.getBody() 리턴) + return resTransfer.getBody() != null ? resTransfer.getBody() : "{\"status\":\"SUCCESS\", \"message\":\"GlowMciComponent 통신 완료\"}"; + + } catch (Exception e) { + log.error("[MCI Tool] MCI 연동 중 오류 발생: {}", e.getMessage(), e); + return "{\"status\":\"ERROR\", \"message\":\"MCI 통신 실패: " + e.getMessage() + "\"}"; + } + } +} diff --git a/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/impl/SampleMciToolServiceImpl.java b/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/impl/SampleMciToolServiceImpl.java new file mode 100644 index 00000000..0bd44b2c --- /dev/null +++ b/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/impl/SampleMciToolServiceImpl.java @@ -0,0 +1,87 @@ +package io.shinhanlife.dap.dapmt.service.impl; + +import io.shinhanlife.dap.common.adapter.sender.ShinhanMciSender; +import io.shinhanlife.dap.common.integration.mci.dto.MciRequestWrapper; +import io.shinhanlife.dap.common.integration.mci.dto.ShinhanCommonHeaderDto; +import io.shinhanlife.dap.dapmt.annotation.McpFunction; +import io.shinhanlife.dap.dapmt.annotation.McpTool; +import io.shinhanlife.dap.dapmt.service.SampleMciToolService; +import io.shinhanlife.dap.dapmt.service.AbstractMcpToolService; +import lombok.Data; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; + +/** + * @package io.shinhanlife.dap.dapmt.service + * @className SampleMciToolService + * @description AX HUB 시스템 처리 클래스 + * @author 0986406 + * @create 2026.09.01 + *
+ * ---------- 개정이력 ----------
+ * 수정일      수정자    수정내용
+ * ---------- -------- ---------------------------
+ * 2026.09.01  0986406    최초생성
+ * 
+ * 
+ */ +@Slf4j +@RequiredArgsConstructor +@McpTool(routingType = "MCI", categoryKey = "other") // MCP Tool 등록 어노테이션 +public class SampleMciToolServiceImpl implements SampleMciToolService { + + // EIMS/MCI 발송을 담당하는 Sender 주입 + private final ShinhanMciSender shinhanMciSender; + + @Value("${shinhan.integration.mci.default-url:http://localhost:8081/api/mock/esb/api}") + private String mciTargetUrl; + + // AI가 인식할 파라미터 DTO + @Data + public static class SampleMciReqDto { + private String customerId; + private String inquiryType; + } + + /** + * AI Agent가 호출하게 될 메서드입니다. + */ + @McpFunction(register = false, name = "inquiry_customer_mci", + displayName = "고객 정보 조회 (MCI)", + description = "MCI 연동을 통해 고객의 상세 정보를 조회합니다.", + prompt = "고객 정보를 조회해줘.", + mappingId = "CUST_INQ_001" + ) + @Override + public Object inquiryCustomerInfo(SampleMciReqDto req) { + log.info("[MCI Tool] 고객 정보 조회 요청 수신. 고객ID: {}", req.getCustomerId()); + + try { + // 1. MCI 전문 통신을 위한 Wrapper 객체 생성 + MciRequestWrapper wrapper = new MciRequestWrapper<>(); + + // 2. 공통 헤더 세팅 (인터페이스 ID, 서비스 ID 등 업무에 맞게 설정) + ShinhanCommonHeaderDto header = new ShinhanCommonHeaderDto(); + header.setItrIfId("CUST_INQ_001"); + header.setRcvSvcId("INQ9040"); + wrapper.setTgrmCmnnhddValu(header); + + // 3. 비즈니스 데이터(Body) 세팅 + wrapper.setBody(req); + + // 4. ShinhanMciSender를 통해 실제 연동 수행 및 응답 수신 + log.info("[MCI Tool] ShinhanMciSender 연동 시작... (URL: {})", mciTargetUrl); + String responseJson = shinhanMciSender.send(mciTargetUrl, wrapper); + + log.info("[MCI Tool] MCI 연동 성공. 응답 수신 완료"); + + // 결과 반환 (이 문자열은 JSON 파싱되거나 그대로 AI에게 전달됩니다) + return responseJson; + + } catch (Exception e) { + log.error("[MCI Tool] MCI 연동 중 오류 발생: {}", e.getMessage(), e); + return "{\"status\":\"ERROR\", \"message\":\"MCI 통신 실패: " + e.getMessage() + "\"}"; + } + } +} diff --git a/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/impl/SampleStringToolServiceImpl.java b/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/impl/SampleStringToolServiceImpl.java new file mode 100644 index 00000000..224fd959 --- /dev/null +++ b/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/impl/SampleStringToolServiceImpl.java @@ -0,0 +1,59 @@ +package io.shinhanlife.dap.dapmt.service.impl; + +import io.shinhanlife.dap.dapmt.annotation.McpFunction; +import io.shinhanlife.dap.dapmt.annotation.McpTool; +import io.shinhanlife.dap.dapmt.service.SampleStringToolService; +import io.shinhanlife.dap.dapmt.service.AbstractMcpToolService; +import io.shinhanlife.dap.dapmt.dto.MciSampleStringRes; +import io.shinhanlife.dap.dapmt.dto.SampleStringReq; +import io.shinhanlife.glow.util.GlowMciParser; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Map; + +/** + * @package io.shinhanlife.dap.dapmt.service + * @className SampleStringToolService + * @description AX HUB 시스템 처리 클래스 + * @author 0986406 + * @create 2026.09.01 + *
+ * ---------- 개정이력 ----------
+ * 수정일      수정자    수정내용
+ * ---------- -------- ---------------------------
+ * 2026.09.01  0986406    최초생성
+ * 
+ * 
+ */ +@Service +@McpTool( + routingType = "MCI", + categoryKey = "common" +) +public class SampleStringToolServiceImpl extends AbstractMcpToolService implements SampleStringToolService { + + @McpFunction(register = false, displayName = "get_sample_string 툴", name = "get_sample_string", + description = "MCI String 버전과 GlowTrgmField 파싱을 테스트하는 샘플 툴입니다.", + prompt = "MCI 전문(String) 연계 및 고정 길이 파싱 테스트 해줘.", + mappingId = "TRGM_001" + ) + @Override + public Object execute(SampleStringReq req) { + // 1. EIMS(Legacy)를 통해 원본 고정 길이 문자열을 받아옵니다. + // 스펙에 mciFormat = STRING 힌트를 주어 전문 통신으로 자동 분기되게 합니다. + List> spec = List.of( + Map.of("mciFormat", "STRING") + ); + Map result = executeLegacy("MCI", "TRGM_001", req, spec); + + if (!"SUCCESS".equals(result.get("status"))) { + return result; + } + + String rawStringResponse = (String) result.get("legacy_response"); + + // 2. 받아온 고정 길이 전문(String)을 GlowMciParser를 이용해 DTO로 파싱합니다. + return GlowMciParser.parse(rawStringResponse, MciSampleStringRes.class); + } +} diff --git a/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/impl/TemplateUtilityServiceImpl.java b/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/impl/TemplateUtilityServiceImpl.java new file mode 100644 index 00000000..67d38757 --- /dev/null +++ b/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/impl/TemplateUtilityServiceImpl.java @@ -0,0 +1,67 @@ +package io.shinhanlife.dap.dapmt.service.impl; + +import io.shinhanlife.dap.dapmt.annotation.McpFunction; +import io.shinhanlife.dap.dapmt.annotation.McpTool; +import io.shinhanlife.dap.dapmt.service.TemplateUtilityService; +import io.shinhanlife.dap.dapmt.service.AbstractMcpToolService; +import io.shinhanlife.dap.dapmt.dto.TemplateDownloadReq; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +@Slf4j +@Service +@McpTool( + routingType = "HTTP", + categoryKey = "common" +) +/** + * @package io.shinhanlife.dap.dapmt.service + * @className TemplateUtilityService + * @description AX HUB 시스템 처리 클래스 + * @author 0986406 + * @create 2026.09.01 + *
+ * ---------- 개정이력 ----------
+ * 수정일      수정자    수정내용
+ * ---------- -------- ---------------------------
+ * 2026.09.01  0986406    최초생성
+ * 
+ * 
+ */ +public class TemplateUtilityServiceImpl extends AbstractMcpToolService implements TemplateUtilityService { + + @Override + @McpFunction(register = false, displayName = "get_template_file_url 툴", name = "get_template_file_url", + description = "특정 템플릿의 양식 파일(엑셀, 워드 등)을 다운로드 받을 수 있는 시스템 URL을 반환합니다. AI는 이 URL을 사용자에게 마크다운 링크 형태로 제공해야 합니다.", + prompt = "요청하신 템플릿 양식 파일 다운로드 URL은 다음과 같습니다. 클릭하여 다운로드하세요:" + ) + public Map getTemplateFileUrl(TemplateDownloadReq data) { + try { + String templateId = (data != null && data.getTemplateId() != null) ? data.getTemplateId().toLowerCase() : "default"; + log.info("MCP 툴 호출됨: get_template_file_url, 요청 템플릿 ID: {}", templateId); + + String fileName = "sample_" + templateId + ".xlsx"; + String downloadUrl = "https://axhub-file-server.shinhanlife.io/downloads/" + fileName; + + Map result = new HashMap<>(); + result.put("status", "success"); + + Map contract = new HashMap<>(); + contract.put("fileName", fileName); + contract.put("downloadUrl", downloadUrl); + contract.put("message", "다운로드 링크가 성공적으로 생성되었습니다. AI는 이 링크를 마크다운 형식으로 사용자에게 전달해야 합니다."); + contract.put("status", "success"); + + result.put("contracts", Collections.singletonList(contract)); + + return result; + } catch (Exception e) { + log.error("getTemplateFileUrl 내부 예외 발생", e); + throw new RuntimeException("템플릿 URL 생성 실패", e); + } + } +} \ No newline at end of file diff --git a/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/impl/WeatherToolServiceImpl.java b/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/impl/WeatherToolServiceImpl.java new file mode 100644 index 00000000..880c914a --- /dev/null +++ b/dap-tool-other/src/main/java/io/shinhanlife/dap/dapmt/service/impl/WeatherToolServiceImpl.java @@ -0,0 +1,117 @@ +package io.shinhanlife.dap.dapmt.service.impl; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import io.shinhanlife.dap.dapmt.annotation.McpFunction; +import io.shinhanlife.dap.dapmt.annotation.McpTool; +import io.shinhanlife.dap.dapmt.service.WeatherToolService; +import io.shinhanlife.dap.dapmt.service.AbstractMcpToolService; +import io.shinhanlife.dap.dapmt.dto.WeatherReq; +import io.shinhanlife.dap.dapmt.dto.WeatherRes; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestClient; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + +/** + * @package io.shinhanlife.dap.dapmt.service + * @className WeatherToolService + * @description AX HUB 시스템 처리 클래스 + * @author 0986406 + * @create 2026.07.14 + *
+ * ---------- 개정이력 ----------
+ * 수정일      수정자    수정내용
+ * ---------- -------- ---------------------------
+ * 2026.07.14  0986406    최초생성
+ * 
+ * 
+ */ +@Slf4j +@Service +@McpTool( + routingType = "DIRECT", + categoryKey = "sample" +) +public class WeatherToolServiceImpl extends AbstractMcpToolService implements WeatherToolService { + + private final RestClient restClient; + + public WeatherToolServiceImpl() { + this.restClient = RestClient.create(); + } + + @McpFunction(register = false, displayName = "날씨 조회 툴", name = "weather", + description = "특정 도시의 현재 날씨, 온도, 풍속 정보를 조회합니다.", + prompt = "서울 날씨 알려줘, 부산 기온 알려줘 등 실시간 기상 조회", + mappingId = "WEATHER_001" + ) + public WeatherRes execute(WeatherReq req) { + String city = req.city() != null ? req.city().trim() : "서울"; + + // 지역별 위경도 매핑 (간단한 예시) + double lat = 37.566; + double lon = 126.978; + + if (city.contains("부산")) { + lat = 35.179; + lon = 129.075; + } else if (city.contains("제주")) { + lat = 33.499; + lon = 126.531; + } else if (city.contains("인천")) { + lat = 37.456; + lon = 126.705; + } + + try { + String newRequestId = java.util.UUID.randomUUID().toString(); + String url = String.format("https://api.open-meteo.com/v1/forecast?latitude=%f&longitude=%f¤t_weather=true", lat, lon); + + log.info("[WeatherTool] OUTBOUND HTTP IN - request-id: {}", newRequestId); + log.info("[WeatherTool] 날씨 조회 요청 URL: {}", url); + + String responseStr = restClient.get() + .uri(url) + .header("request-id", newRequestId) + .retrieve() + .body(String.class); + + log.info("[WeatherTool] OUTBOUND HTTP OUT - request-id: {}", newRequestId); + + ObjectMapper mapper = new ObjectMapper(); + JsonNode response = mapper.readTree(responseStr); + + if (response != null && response.has("current_weather")) { + JsonNode current = response.get("current_weather"); + double temp = current.path("temperature").asDouble(); + double windSpeed = current.path("windspeed").asDouble(); + String time = current.path("time").asText(); + + int weatherCode = current.path("weathercode").asInt(); + String summary = parseWeatherCode(weatherCode); + + String formattedTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")); + + return new WeatherRes(city, temp, windSpeed, formattedTime, summary); + } + } catch (Exception e) { + log.error("[WeatherTool] 날씨 API 연동 실패: {}", e.getMessage()); + return new WeatherRes(city, 0.0, 0.0, "", "날씨 정보를 불러오는데 실패했습니다."); + } + + return new WeatherRes(city, 0.0, 0.0, "", "알 수 없는 응답입니다."); + } + + private String parseWeatherCode(int code) { + if (code == 0) return "맑음 (Clear)"; + if (code >= 1 && code <= 3) return "구름조금/흐림 (Cloudy)"; + if (code >= 45 && code <= 48) return "안개 (Fog)"; + if (code >= 51 && code <= 67) return "비/이슬비 (Rain)"; + if (code >= 71 && code <= 77) return "눈 (Snow)"; + if (code >= 95) return "뇌우/천둥번개 (Thunderstorm)"; + return "알 수 없음 (Unknown)"; + } +} diff --git a/dap-tool-payment/src/main/java/io/shinhanlife/dap/dapmt/service/PaymentApprovalService.java b/dap-tool-payment/src/main/java/io/shinhanlife/dap/dapmt/service/PaymentApprovalService.java index 77ae7c95..a9336a2a 100644 --- a/dap-tool-payment/src/main/java/io/shinhanlife/dap/dapmt/service/PaymentApprovalService.java +++ b/dap-tool-payment/src/main/java/io/shinhanlife/dap/dapmt/service/PaymentApprovalService.java @@ -1,54 +1,7 @@ package io.shinhanlife.dap.dapmt.service; -import io.shinhanlife.dap.dapmt.annotation.McpFunction; -import io.shinhanlife.dap.dapmt.annotation.McpTool; -import io.shinhanlife.dap.dapmt.dto.PaymentApprovalReq; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; +import io.shinhanlife.dap.dapmt.dto.*; -import java.util.Map; -import java.util.UUID; - -/** - * @package io.shinhanlife.dap.dapmt.service - * @className PaymentApprovalService - * @description AX HUB 시스템 처리 클래스 - * @author 0986406 - * @create 2026.09.01 - *
- * ---------- 개정이력 ----------
- * 수정일      수정자    수정내용
- * ---------- -------- ---------------------------
- * 2026.09.01  0986406    최초생성
- * 
- * 
- */ -@Slf4j -@Service -@McpTool( - routingType = "MCI", - categoryKey = "payment" -) -public class PaymentApprovalService extends AbstractMcpToolService { - - @McpFunction(register = false, displayName = "paymentapproval 툴", name = "paymentapproval", - description = "결제 승인 처리", - prompt = "결제 승인 처리 해줘.", - mappingId = "PAY_001" - ) - public Object execute(PaymentApprovalReq req) { - log.info("[Payment] 결제 승인 요청 수신. 계좌: {}, 금액: {}", req.getAccountNumber(), req.getAmount()); - - // 레거시 연동 - Map result = executeLegacy("MCI", "PAY_001", req); - - // 가짜 데이터 응답 매핑 (AI 에이전트가 그럴듯하게 보여주기 위함) - if ("SUCCESS".equals(result.get("status"))) { - result.put("transactionId", "TX_" + UUID.randomUUID().toString().substring(0, 8).toUpperCase()); - result.put("approvedAmount", req.getAmount()); - result.put("message", "결제가 성공적으로 승인되었습니다."); - } - - return result; - } +public interface PaymentApprovalService { + Object execute(PaymentApprovalReq req); } diff --git a/dap-tool-payment/src/main/java/io/shinhanlife/dap/dapmt/service/impl/PaymentApprovalServiceImpl.java b/dap-tool-payment/src/main/java/io/shinhanlife/dap/dapmt/service/impl/PaymentApprovalServiceImpl.java new file mode 100644 index 00000000..24245de8 --- /dev/null +++ b/dap-tool-payment/src/main/java/io/shinhanlife/dap/dapmt/service/impl/PaymentApprovalServiceImpl.java @@ -0,0 +1,57 @@ +package io.shinhanlife.dap.dapmt.service.impl; + +import io.shinhanlife.dap.dapmt.annotation.McpFunction; +import io.shinhanlife.dap.dapmt.annotation.McpTool; +import io.shinhanlife.dap.dapmt.service.PaymentApprovalService; +import io.shinhanlife.dap.dapmt.service.AbstractMcpToolService; +import io.shinhanlife.dap.dapmt.dto.PaymentApprovalReq; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.Map; +import java.util.UUID; + +/** + * @package io.shinhanlife.dap.dapmt.service + * @className PaymentApprovalService + * @description AX HUB 시스템 처리 클래스 + * @author 0986406 + * @create 2026.09.01 + *
+ * ---------- 개정이력 ----------
+ * 수정일      수정자    수정내용
+ * ---------- -------- ---------------------------
+ * 2026.09.01  0986406    최초생성
+ * 
+ * 
+ */ +@Slf4j +@Service +@McpTool( + routingType = "MCI", + categoryKey = "payment" +) +public class PaymentApprovalServiceImpl extends AbstractMcpToolService implements PaymentApprovalService { + + @McpFunction(register = false, displayName = "paymentapproval 툴", name = "paymentapproval", + description = "결제 승인 처리", + prompt = "결제 승인 처리 해줘.", + mappingId = "PAY_001" + ) + @Override + public Object execute(PaymentApprovalReq req) { + log.info("[Payment] 결제 승인 요청 수신. 계좌: {}, 금액: {}", req.getAccountNumber(), req.getAmount()); + + // 레거시 연동 + Map result = executeLegacy("MCI", "PAY_001", req); + + // 가짜 데이터 응답 매핑 (AI 에이전트가 그럴듯하게 보여주기 위함) + if ("SUCCESS".equals(result.get("status"))) { + result.put("transactionId", "TX_" + UUID.randomUUID().toString().substring(0, 8).toUpperCase()); + result.put("approvedAmount", req.getAmount()); + result.put("message", "결제가 성공적으로 승인되었습니다."); + } + + return result; + } +} diff --git a/dap-tool-sms/src/main/java/io/shinhanlife/dap/dapmt/service/SmsToolService.java b/dap-tool-sms/src/main/java/io/shinhanlife/dap/dapmt/service/SmsToolService.java index 7521d299..180870ec 100644 --- a/dap-tool-sms/src/main/java/io/shinhanlife/dap/dapmt/service/SmsToolService.java +++ b/dap-tool-sms/src/main/java/io/shinhanlife/dap/dapmt/service/SmsToolService.java @@ -1,51 +1,7 @@ package io.shinhanlife.dap.dapmt.service; -import io.shinhanlife.dap.dapmt.annotation.McpFunction; -import io.shinhanlife.dap.dapmt.annotation.McpTool; -import io.shinhanlife.dap.dapmt.converter.SmsLegacyConverter; -import io.shinhanlife.dap.dapmt.dto.SmsSendReq; -import io.shinhanlife.dap.dapmt.legacy.SmsLegacyReq; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; +import io.shinhanlife.dap.dapmt.dto.*; -import java.util.Map; - -/** - * @package io.shinhanlife.dap.dapmt.sms - * @className SmsToolService - * @description AX HUB 시스템 처리 클래스 - * @author 0986406 - * @create 2026.09.01 - *
- * ---------- 개정이력 ----------
- * 수정일      수정자    수정내용
- * ---------- -------- ---------------------------
- * 2026.09.01  0986406    최초생성
- * 
- * 
- */ -@Slf4j -@RequiredArgsConstructor -@McpTool(routingType = "EAI", categoryKey = "notification") -public class SmsToolService extends AbstractMcpToolService { - - private final SmsLegacyConverter converter; - - @McpFunction(register = false, displayName = "send_sms 툴", name = "send_sms", description = "SMS 발송", prompt = "고객에게 SMS 메시지를 발송해줘.", mappingId = "SMS_SEND_001") - public Object sendSms(SmsSendReq req) { - log.info("[SMS] SMS 발송 요청 수신. 수신자: {}", req.getPhoneNumber()); - - // MapStruct를 이용한 자동 매핑 (AI DTO -> MCI DTO) - SmsLegacyReq legacyReq = converter.toLegacyReq(req); - - // 레거시 시스템 연동 (EAI) - DTO 객체를 그대로 넘김 - Map result = executeLegacy("EAI", "SMS_SEND_001", legacyReq); - - // 결과 가공 - if ("SUCCESS".equals(result.get("status"))) { - result.put("message", "SMS가 성공적으로 발송되었습니다."); - } - - return result; - } -} \ No newline at end of file +public interface SmsToolService { + Object sendSms(SmsSendReq req); +} diff --git a/dap-tool-sms/src/main/java/io/shinhanlife/dap/dapmt/service/impl/SmsToolServiceImpl.java b/dap-tool-sms/src/main/java/io/shinhanlife/dap/dapmt/service/impl/SmsToolServiceImpl.java new file mode 100644 index 00000000..fac39824 --- /dev/null +++ b/dap-tool-sms/src/main/java/io/shinhanlife/dap/dapmt/service/impl/SmsToolServiceImpl.java @@ -0,0 +1,54 @@ +package io.shinhanlife.dap.dapmt.service.impl; + +import io.shinhanlife.dap.dapmt.annotation.McpFunction; +import io.shinhanlife.dap.dapmt.annotation.McpTool; +import io.shinhanlife.dap.dapmt.service.SmsToolService; +import io.shinhanlife.dap.dapmt.service.AbstractMcpToolService; +import io.shinhanlife.dap.dapmt.converter.SmsLegacyConverter; +import io.shinhanlife.dap.dapmt.dto.SmsSendReq; +import io.shinhanlife.dap.dapmt.legacy.SmsLegacyReq; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import java.util.Map; + +/** + * @package io.shinhanlife.dap.dapmt.sms + * @className SmsToolService + * @description AX HUB 시스템 처리 클래스 + * @author 0986406 + * @create 2026.09.01 + *
+ * ---------- 개정이력 ----------
+ * 수정일      수정자    수정내용
+ * ---------- -------- ---------------------------
+ * 2026.09.01  0986406    최초생성
+ * 
+ * 
+ */ +@Slf4j +@RequiredArgsConstructor +@McpTool(routingType = "EAI", categoryKey = "notification") +public class SmsToolServiceImpl extends AbstractMcpToolService implements SmsToolService { + + private final SmsLegacyConverter converter; + + @McpFunction(register = false, displayName = "send_sms 툴", name = "send_sms", description = "SMS 발송", prompt = "고객에게 SMS 메시지를 발송해줘.", mappingId = "SMS_SEND_001") + @Override + public Object sendSms(SmsSendReq req) { + log.info("[SMS] SMS 발송 요청 수신. 수신자: {}", req.getPhoneNumber()); + + // MapStruct를 이용한 자동 매핑 (AI DTO -> MCI DTO) + SmsLegacyReq legacyReq = converter.toLegacyReq(req); + + // 레거시 시스템 연동 (EAI) - DTO 객체를 그대로 넘김 + Map result = executeLegacy("EAI", "SMS_SEND_001", legacyReq); + + // 결과 가공 + if ("SUCCESS".equals(result.get("status"))) { + result.put("message", "SMS가 성공적으로 발송되었습니다."); + } + + return result; + } +} \ No newline at end of file