Refactor: ToolService 인터페이스 분리 및 GlowEaiComponent 로드 에러 수정
Some checks failed
Deploy to OCIWP / deploy (push) Has been cancelled
Some checks failed
Deploy to OCIWP / deploy (push) Has been cancelled
This commit is contained in:
@@ -16,4 +16,10 @@ public class GlowMockConfig {
|
|||||||
public GlowMciComponent glowMciComponent() {
|
public GlowMciComponent glowMciComponent() {
|
||||||
return new 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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,49 +1,7 @@
|
|||||||
package io.shinhanlife.dap.dapmt.service;
|
package io.shinhanlife.dap.dapmt.service;
|
||||||
|
|
||||||
import io.shinhanlife.dap.dapmt.annotation.McpFunction;
|
import io.shinhanlife.dap.dapmt.dto.*;
|
||||||
import io.shinhanlife.dap.dapmt.annotation.McpTool;
|
|
||||||
import io.shinhanlife.dap.dapmt.dto.EmailSendReq;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
public interface EmailToolService {
|
||||||
import java.util.Map;
|
Object sendEmail(EmailSendReq req);
|
||||||
|
|
||||||
/**
|
|
||||||
* @package io.shinhanlife.dap.dapmt.email
|
|
||||||
* @className EmailToolService
|
|
||||||
* @description AX HUB 시스템 처리 클래스
|
|
||||||
* @author 0986406
|
|
||||||
* @create 2026.09.01
|
|
||||||
* <pre>
|
|
||||||
* ---------- 개정이력 ----------
|
|
||||||
* 수정일 수정자 수정내용
|
|
||||||
* ---------- -------- ---------------------------
|
|
||||||
* 2026.09.01 0986406 최초생성
|
|
||||||
*
|
|
||||||
* </pre>
|
|
||||||
*/
|
|
||||||
@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<String, Object> payload = new HashMap<>();
|
|
||||||
payload.put("address", req.getEmailAddress());
|
|
||||||
payload.put("subject", req.getSubject());
|
|
||||||
payload.put("content", req.getBody());
|
|
||||||
|
|
||||||
// 레거시 시스템 연동 (EAI)
|
|
||||||
Map<String, Object> result = executeLegacy("EAI", "EMAIL_SEND_001", payload);
|
|
||||||
|
|
||||||
// 결과 가공
|
|
||||||
if ("SUCCESS".equals(result.get("status"))) {
|
|
||||||
result.put("message", "이메일이 성공적으로 발송되었습니다.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -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
|
||||||
|
* <pre>
|
||||||
|
* ---------- 개정이력 ----------
|
||||||
|
* 수정일 수정자 수정내용
|
||||||
|
* ---------- -------- ---------------------------
|
||||||
|
* 2026.09.01 0986406 최초생성
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
@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<String, Object> payload = new HashMap<>();
|
||||||
|
payload.put("address", req.getEmailAddress());
|
||||||
|
payload.put("subject", req.getSubject());
|
||||||
|
payload.put("content", req.getBody());
|
||||||
|
|
||||||
|
// 레거시 시스템 연동 (EAI)
|
||||||
|
Map<String, Object> result = executeLegacy("EAI", "EMAIL_SEND_001", payload);
|
||||||
|
|
||||||
|
// 결과 가공
|
||||||
|
if ("SUCCESS".equals(result.get("status"))) {
|
||||||
|
result.put("message", "이메일이 성공적으로 발송되었습니다.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,52 +1,7 @@
|
|||||||
package io.shinhanlife.dap.dapmt.service;
|
package io.shinhanlife.dap.dapmt.service;
|
||||||
|
|
||||||
|
import io.shinhanlife.dap.dapmt.dto.*;
|
||||||
|
|
||||||
/**
|
public interface BalanceService {
|
||||||
* @package io.shinhanlife.dap.dapmt.service
|
Object execute(BalanceReq req);
|
||||||
* @className BalanceService
|
|
||||||
* @description AX HUB 시스템 처리 클래스
|
|
||||||
* @author 0986406
|
|
||||||
* @create 2026.09.01
|
|
||||||
* <pre>
|
|
||||||
* ---------- 개정이력 ----------
|
|
||||||
* 수정일 수정자 수정내용
|
|
||||||
* ---------- -------- ---------------------------
|
|
||||||
* 2026.09.01 0986406 최초생성
|
|
||||||
*
|
|
||||||
* </pre>
|
|
||||||
*/
|
|
||||||
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<String, Object> 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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,68 +1,7 @@
|
|||||||
package io.shinhanlife.dap.dapmt.service;
|
package io.shinhanlife.dap.dapmt.service;
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.type.TypeReference;
|
import io.shinhanlife.dap.dapmt.dto.*;
|
||||||
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 java.util.HashMap;
|
public interface BillingProcessService {
|
||||||
import java.util.Map;
|
Object getStatus(BillingStatusReq req);
|
||||||
|
|
||||||
@McpTool(
|
|
||||||
routingType = "MCI",
|
|
||||||
categoryKey = "claim"
|
|
||||||
)
|
|
||||||
/**
|
|
||||||
* @package io.shinhanlife.dap.dapmt.service
|
|
||||||
* @className BillingProcessService
|
|
||||||
* @description AX HUB 시스템 처리 클래스
|
|
||||||
* @author 0986406
|
|
||||||
* @create 2026.09.01
|
|
||||||
* <pre>
|
|
||||||
* ---------- 개정이력 ----------
|
|
||||||
* 수정일 수정자 수정내용
|
|
||||||
* ---------- -------- ---------------------------
|
|
||||||
* 2026.09.01 0986406 최초생성
|
|
||||||
*
|
|
||||||
* </pre>
|
|
||||||
*/
|
|
||||||
@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<String, Object> payload;
|
|
||||||
if (data == null) {
|
|
||||||
payload = new HashMap<>();
|
|
||||||
} else {
|
|
||||||
ObjectMapper mapper = new ObjectMapper();
|
|
||||||
payload = mapper.convertValue(data, new TypeReference<Map<String, Object>>() {});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 커스텀 전처리
|
|
||||||
payload.put("custom_injected_data", "Billing System Check OK");
|
|
||||||
log.info(" [Billing] 커스텀 파라미터 주입 완료");
|
|
||||||
|
|
||||||
// 부모 클래스의 레거시 공통 연동 메서드 호출 (PII 마스킹 포함)
|
|
||||||
Map<String, Object> result = executeLegacy("MCI", mappingId, payload);
|
|
||||||
|
|
||||||
// 커스텀 후처리
|
|
||||||
if ("SUCCESS".equals(result.get("status"))) {
|
|
||||||
result.put("billing_custom_insight", "청구 특화 후처리 로직이 적용되었습니다.");
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,37 +1,7 @@
|
|||||||
package io.shinhanlife.dap.dapmt.service;
|
package io.shinhanlife.dap.dapmt.service;
|
||||||
|
|
||||||
import io.shinhanlife.dap.dapmt.annotation.McpFunction;
|
import io.shinhanlife.dap.dapmt.dto.*;
|
||||||
import io.shinhanlife.dap.dapmt.annotation.McpTool;
|
|
||||||
import io.shinhanlife.dap.dapmt.dto.BondCheckReq;
|
|
||||||
import io.shinhanlife.dap.dapmt.dto.BondIssueReq;
|
|
||||||
|
|
||||||
@McpTool(
|
public interface BondIssueService {
|
||||||
routingType = "EAI",
|
Object check(BondCheckReq req);
|
||||||
categoryKey = "policy"
|
|
||||||
)
|
|
||||||
/**
|
|
||||||
* @package io.shinhanlife.dap.dapmt.service
|
|
||||||
* @className BondIssueService
|
|
||||||
* @description AX HUB 시스템 처리 클래스
|
|
||||||
* @author 0986406
|
|
||||||
* @create 2026.09.01
|
|
||||||
* <pre>
|
|
||||||
* ---------- 개정이력 ----------
|
|
||||||
* 수정일 수정자 수정내용
|
|
||||||
* ---------- -------- ---------------------------
|
|
||||||
* 2026.09.01 0986406 최초생성
|
|
||||||
*
|
|
||||||
* </pre>
|
|
||||||
*/
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,43 +1,7 @@
|
|||||||
package io.shinhanlife.dap.dapmt.service;
|
package io.shinhanlife.dap.dapmt.service;
|
||||||
|
|
||||||
import io.shinhanlife.dap.dapmt.annotation.McpFunction;
|
import io.shinhanlife.dap.dapmt.dto.*;
|
||||||
import io.shinhanlife.dap.dapmt.annotation.McpTool;
|
|
||||||
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
|
|
||||||
* <pre>
|
|
||||||
* ---------- 개정이력 ----------
|
|
||||||
* 수정일 수정자 수정내용
|
|
||||||
* ---------- -------- ---------------------------
|
|
||||||
* 2026.09.01 0986406 최초생성
|
|
||||||
*
|
|
||||||
* </pre>
|
|
||||||
*/
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
public interface CommonUtilityService {
|
||||||
|
Object registerVacation(VacationRegisterReq req);
|
||||||
}
|
}
|
||||||
@@ -1,37 +1,7 @@
|
|||||||
package io.shinhanlife.dap.dapmt.service;
|
package io.shinhanlife.dap.dapmt.service;
|
||||||
|
|
||||||
import io.shinhanlife.dap.dapmt.annotation.McpFunction;
|
import io.shinhanlife.dap.dapmt.dto.*;
|
||||||
import io.shinhanlife.dap.dapmt.annotation.McpTool;
|
|
||||||
import io.shinhanlife.dap.dapmt.dto.ContractDetailReq;
|
|
||||||
import io.shinhanlife.dap.dapmt.dto.ContractStatusReq;
|
|
||||||
|
|
||||||
@McpTool(
|
public interface ContractInquiryService {
|
||||||
routingType = "HTTP",
|
Object getStatus(ContractStatusReq req);
|
||||||
categoryKey = "contract"
|
|
||||||
)
|
|
||||||
/**
|
|
||||||
* @package io.shinhanlife.dap.dapmt.service
|
|
||||||
* @className ContractInquiryService
|
|
||||||
* @description AX HUB 시스템 처리 클래스
|
|
||||||
* @author 0986406
|
|
||||||
* @create 2026.09.01
|
|
||||||
* <pre>
|
|
||||||
* ---------- 개정이력 ----------
|
|
||||||
* 수정일 수정자 수정내용
|
|
||||||
* ---------- -------- ---------------------------
|
|
||||||
* 2026.09.01 0986406 최초생성
|
|
||||||
*
|
|
||||||
* </pre>
|
|
||||||
*/
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,37 +1,7 @@
|
|||||||
package io.shinhanlife.dap.dapmt.service;
|
package io.shinhanlife.dap.dapmt.service;
|
||||||
|
|
||||||
import io.shinhanlife.dap.dapmt.annotation.McpFunction;
|
import io.shinhanlife.dap.dapmt.dto.*;
|
||||||
import io.shinhanlife.dap.dapmt.annotation.McpTool;
|
|
||||||
import io.shinhanlife.dap.dapmt.dto.CustomerDetailReq;
|
|
||||||
import io.shinhanlife.dap.dapmt.dto.CustomerGradeReq;
|
|
||||||
|
|
||||||
@McpTool(
|
public interface CustomerInfoService {
|
||||||
routingType = "TCP",
|
Object getGrade(CustomerGradeReq req);
|
||||||
categoryKey = "customer"
|
|
||||||
)
|
|
||||||
/**
|
|
||||||
* @package io.shinhanlife.dap.dapmt.service
|
|
||||||
* @className CustomerInfoService
|
|
||||||
* @description AX HUB 시스템 처리 클래스
|
|
||||||
* @author 0986406
|
|
||||||
* @create 2026.09.01
|
|
||||||
* <pre>
|
|
||||||
* ---------- 개정이력 ----------
|
|
||||||
* 수정일 수정자 수정내용
|
|
||||||
* ---------- -------- ---------------------------
|
|
||||||
* 2026.09.01 0986406 최초생성
|
|
||||||
*
|
|
||||||
* </pre>
|
|
||||||
*/
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,55 +1,7 @@
|
|||||||
package io.shinhanlife.dap.dapmt.service;
|
package io.shinhanlife.dap.dapmt.service;
|
||||||
|
|
||||||
import io.shinhanlife.dap.dapmt.annotation.McpFunction;
|
import io.shinhanlife.dap.dapmt.dto.*;
|
||||||
import io.shinhanlife.dap.dapmt.annotation.McpTool;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
import java.util.List;
|
public interface DailyQuoteToolService {
|
||||||
import java.util.Random;
|
io.shinhanlife.dap.dapmt.service.impl.DailyQuoteToolServiceImpl.DailyQuoteRes execute(io.shinhanlife.dap.dapmt.service.impl.DailyQuoteToolServiceImpl.DailyQuoteReq req);
|
||||||
|
|
||||||
/**
|
|
||||||
* @package io.shinhanlife.dap.dapmt.service
|
|
||||||
* @className DailyQuoteToolService
|
|
||||||
* @description 랜덤 명언 제공 툴
|
|
||||||
* @author 0986406
|
|
||||||
* @create 2026.09.01
|
|
||||||
* <pre>
|
|
||||||
* ---------- 개정이력 ----------
|
|
||||||
* 수정일 수정자 수정내용
|
|
||||||
* ---------- -------- ---------------------------
|
|
||||||
* 2026.09.01 0986406 최초생성
|
|
||||||
*
|
|
||||||
* </pre>
|
|
||||||
*/
|
|
||||||
@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<DailyQuoteRes> 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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,59 +1,7 @@
|
|||||||
package io.shinhanlife.dap.dapmt.service;
|
package io.shinhanlife.dap.dapmt.service;
|
||||||
|
|
||||||
import io.shinhanlife.dap.dapmt.annotation.McpFunction;
|
import io.shinhanlife.dap.dapmt.dto.*;
|
||||||
import io.shinhanlife.dap.dapmt.annotation.McpTool;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import org.springframework.web.client.RestClient;
|
|
||||||
|
|
||||||
/**
|
public interface ExchangeRateToolService {
|
||||||
* @package io.shinhanlife.dap.dapmt.service
|
io.shinhanlife.dap.dapmt.service.impl.ExchangeRateToolServiceImpl.ExchangeRateRes execute(io.shinhanlife.dap.dapmt.service.impl.ExchangeRateToolServiceImpl.ExchangeRateReq req);
|
||||||
* @className ExchangeRateToolService
|
|
||||||
* @description 실시간 환율 조회 툴
|
|
||||||
* @author 0986406
|
|
||||||
* @create 2026.09.01
|
|
||||||
* <pre>
|
|
||||||
* ---------- 개정이력 ----------
|
|
||||||
* 수정일 수정자 수정내용
|
|
||||||
* ---------- -------- ---------------------------
|
|
||||||
* 2026.09.01 0986406 최초생성
|
|
||||||
*
|
|
||||||
* </pre>
|
|
||||||
*/
|
|
||||||
@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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,71 +1,7 @@
|
|||||||
package io.shinhanlife.dap.dapmt.service;
|
package io.shinhanlife.dap.dapmt.service;
|
||||||
|
|
||||||
import io.shinhanlife.dap.common.integration.mci.component.AxhubMciComponent;
|
import io.shinhanlife.dap.dapmt.dto.*;
|
||||||
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;
|
|
||||||
|
|
||||||
/**
|
public interface OnnbaMciToolService {
|
||||||
* @package io.shinhanlife.dap.dapmt.service
|
Object callOnnba3011(Onnba3011Req req);
|
||||||
* @className OnnbaMciToolService
|
|
||||||
* @description 보종By가입설계한도계산조회 MCI 연동 툴
|
|
||||||
* @author 0986406
|
|
||||||
* @create 2026.09.01
|
|
||||||
* <pre>
|
|
||||||
* ---------- 개정이력 ----------
|
|
||||||
* 수정일 수정자 수정내용
|
|
||||||
* ---------- -------- ---------------------------
|
|
||||||
* 2026.09.01 0986406 최초생성
|
|
||||||
*
|
|
||||||
* </pre>
|
|
||||||
*/
|
|
||||||
@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<Object> 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() + "\"}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,84 +1,7 @@
|
|||||||
package io.shinhanlife.dap.dapmt.service;
|
package io.shinhanlife.dap.dapmt.service;
|
||||||
|
|
||||||
import io.shinhanlife.dap.common.adapter.sender.ShinhanMciSender;
|
import io.shinhanlife.dap.dapmt.dto.*;
|
||||||
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;
|
|
||||||
|
|
||||||
/**
|
public interface SampleMciToolService {
|
||||||
* @package io.shinhanlife.dap.dapmt.service
|
Object inquiryCustomerInfo(io.shinhanlife.dap.dapmt.service.impl.SampleMciToolServiceImpl.SampleMciReqDto req);
|
||||||
* @className SampleMciToolService
|
|
||||||
* @description AX HUB 시스템 처리 클래스
|
|
||||||
* @author 0986406
|
|
||||||
* @create 2026.09.01
|
|
||||||
* <pre>
|
|
||||||
* ---------- 개정이력 ----------
|
|
||||||
* 수정일 수정자 수정내용
|
|
||||||
* ---------- -------- ---------------------------
|
|
||||||
* 2026.09.01 0986406 최초생성
|
|
||||||
*
|
|
||||||
* </pre>
|
|
||||||
*/
|
|
||||||
@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<SampleMciReqDto> 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() + "\"}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,56 +1,7 @@
|
|||||||
package io.shinhanlife.dap.dapmt.service;
|
package io.shinhanlife.dap.dapmt.service;
|
||||||
|
|
||||||
import io.shinhanlife.dap.dapmt.annotation.McpFunction;
|
import io.shinhanlife.dap.dapmt.dto.*;
|
||||||
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 java.util.List;
|
public interface SampleStringToolService {
|
||||||
import java.util.Map;
|
Object execute(SampleStringReq req);
|
||||||
|
|
||||||
/**
|
|
||||||
* @package io.shinhanlife.dap.dapmt.service
|
|
||||||
* @className SampleStringToolService
|
|
||||||
* @description AX HUB 시스템 처리 클래스
|
|
||||||
* @author 0986406
|
|
||||||
* @create 2026.09.01
|
|
||||||
* <pre>
|
|
||||||
* ---------- 개정이력 ----------
|
|
||||||
* 수정일 수정자 수정내용
|
|
||||||
* ---------- -------- ---------------------------
|
|
||||||
* 2026.09.01 0986406 최초생성
|
|
||||||
*
|
|
||||||
* </pre>
|
|
||||||
*/
|
|
||||||
@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<Map<String, Object>> spec = List.of(
|
|
||||||
Map.of("mciFormat", "STRING")
|
|
||||||
);
|
|
||||||
Map<String, Object> 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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,64 +1,7 @@
|
|||||||
package io.shinhanlife.dap.dapmt.service;
|
package io.shinhanlife.dap.dapmt.service;
|
||||||
|
|
||||||
import io.shinhanlife.dap.dapmt.annotation.McpFunction;
|
import io.shinhanlife.dap.dapmt.dto.*;
|
||||||
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 java.util.Collections;
|
public interface TemplateUtilityService {
|
||||||
import java.util.HashMap;
|
java.util.Map<String, Object> getTemplateFileUrl(TemplateDownloadReq req);
|
||||||
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
|
|
||||||
* <pre>
|
|
||||||
* ---------- 개정이력 ----------
|
|
||||||
* 수정일 수정자 수정내용
|
|
||||||
* ---------- -------- ---------------------------
|
|
||||||
* 2026.09.01 0986406 최초생성
|
|
||||||
*
|
|
||||||
* </pre>
|
|
||||||
*/
|
|
||||||
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<String, Object> 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<String, Object> result = new HashMap<>();
|
|
||||||
result.put("status", "success");
|
|
||||||
|
|
||||||
Map<String, Object> 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,115 +1,7 @@
|
|||||||
package io.shinhanlife.dap.dapmt.service;
|
package io.shinhanlife.dap.dapmt.service;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
import io.shinhanlife.dap.dapmt.dto.*;
|
||||||
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 java.time.LocalDateTime;
|
public interface WeatherToolService {
|
||||||
import java.time.format.DateTimeFormatter;
|
WeatherRes execute(WeatherReq req);
|
||||||
|
|
||||||
/**
|
|
||||||
* @package io.shinhanlife.dap.dapmt.service
|
|
||||||
* @className WeatherToolService
|
|
||||||
* @description AX HUB 시스템 처리 클래스
|
|
||||||
* @author 0986406
|
|
||||||
* @create 2026.07.14
|
|
||||||
* <pre>
|
|
||||||
* ---------- 개정이력 ----------
|
|
||||||
* 수정일 수정자 수정내용
|
|
||||||
* ---------- -------- ---------------------------
|
|
||||||
* 2026.07.14 0986406 최초생성
|
|
||||||
*
|
|
||||||
* </pre>
|
|
||||||
*/
|
|
||||||
@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)";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
* <pre>
|
||||||
|
* ---------- 개정이력 ----------
|
||||||
|
* 수정일 수정자 수정내용
|
||||||
|
* ---------- -------- ---------------------------
|
||||||
|
* 2026.09.01 0986406 최초생성
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
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<String, Object> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
* <pre>
|
||||||
|
* ---------- 개정이력 ----------
|
||||||
|
* 수정일 수정자 수정내용
|
||||||
|
* ---------- -------- ---------------------------
|
||||||
|
* 2026.09.01 0986406 최초생성
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
@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<String, Object> payload;
|
||||||
|
if (data == null) {
|
||||||
|
payload = new HashMap<>();
|
||||||
|
} else {
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
payload = mapper.convertValue(data, new TypeReference<Map<String, Object>>() {});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 커스텀 전처리
|
||||||
|
payload.put("custom_injected_data", "Billing System Check OK");
|
||||||
|
log.info(" [Billing] 커스텀 파라미터 주입 완료");
|
||||||
|
|
||||||
|
// 부모 클래스의 레거시 공통 연동 메서드 호출 (PII 마스킹 포함)
|
||||||
|
Map<String, Object> result = executeLegacy("MCI", mappingId, payload);
|
||||||
|
|
||||||
|
// 커스텀 후처리
|
||||||
|
if ("SUCCESS".equals(result.get("status"))) {
|
||||||
|
result.put("billing_custom_insight", "청구 특화 후처리 로직이 적용되었습니다.");
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
* <pre>
|
||||||
|
* ---------- 개정이력 ----------
|
||||||
|
* 수정일 수정자 수정내용
|
||||||
|
* ---------- -------- ---------------------------
|
||||||
|
* 2026.09.01 0986406 최초생성
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
* <pre>
|
||||||
|
* ---------- 개정이력 ----------
|
||||||
|
* 수정일 수정자 수정내용
|
||||||
|
* ---------- -------- ---------------------------
|
||||||
|
* 2026.09.01 0986406 최초생성
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
* <pre>
|
||||||
|
* ---------- 개정이력 ----------
|
||||||
|
* 수정일 수정자 수정내용
|
||||||
|
* ---------- -------- ---------------------------
|
||||||
|
* 2026.09.01 0986406 최초생성
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
* <pre>
|
||||||
|
* ---------- 개정이력 ----------
|
||||||
|
* 수정일 수정자 수정내용
|
||||||
|
* ---------- -------- ---------------------------
|
||||||
|
* 2026.09.01 0986406 최초생성
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
* <pre>
|
||||||
|
* ---------- 개정이력 ----------
|
||||||
|
* 수정일 수정자 수정내용
|
||||||
|
* ---------- -------- ---------------------------
|
||||||
|
* 2026.09.01 0986406 최초생성
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
@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<DailyQuoteRes> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
* <pre>
|
||||||
|
* ---------- 개정이력 ----------
|
||||||
|
* 수정일 수정자 수정내용
|
||||||
|
* ---------- -------- ---------------------------
|
||||||
|
* 2026.09.01 0986406 최초생성
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
@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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
* <pre>
|
||||||
|
* ---------- 개정이력 ----------
|
||||||
|
* 수정일 수정자 수정내용
|
||||||
|
* ---------- -------- ---------------------------
|
||||||
|
* 2026.09.01 0986406 최초생성
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
@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<Object> 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() + "\"}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
* <pre>
|
||||||
|
* ---------- 개정이력 ----------
|
||||||
|
* 수정일 수정자 수정내용
|
||||||
|
* ---------- -------- ---------------------------
|
||||||
|
* 2026.09.01 0986406 최초생성
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
@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<SampleMciReqDto> 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() + "\"}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
* <pre>
|
||||||
|
* ---------- 개정이력 ----------
|
||||||
|
* 수정일 수정자 수정내용
|
||||||
|
* ---------- -------- ---------------------------
|
||||||
|
* 2026.09.01 0986406 최초생성
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
@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<Map<String, Object>> spec = List.of(
|
||||||
|
Map.of("mciFormat", "STRING")
|
||||||
|
);
|
||||||
|
Map<String, Object> 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
* <pre>
|
||||||
|
* ---------- 개정이력 ----------
|
||||||
|
* 수정일 수정자 수정내용
|
||||||
|
* ---------- -------- ---------------------------
|
||||||
|
* 2026.09.01 0986406 최초생성
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
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<String, Object> 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<String, Object> result = new HashMap<>();
|
||||||
|
result.put("status", "success");
|
||||||
|
|
||||||
|
Map<String, Object> 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
* <pre>
|
||||||
|
* ---------- 개정이력 ----------
|
||||||
|
* 수정일 수정자 수정내용
|
||||||
|
* ---------- -------- ---------------------------
|
||||||
|
* 2026.07.14 0986406 최초생성
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
@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)";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,54 +1,7 @@
|
|||||||
package io.shinhanlife.dap.dapmt.service;
|
package io.shinhanlife.dap.dapmt.service;
|
||||||
|
|
||||||
import io.shinhanlife.dap.dapmt.annotation.McpFunction;
|
import io.shinhanlife.dap.dapmt.dto.*;
|
||||||
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 java.util.Map;
|
public interface PaymentApprovalService {
|
||||||
import java.util.UUID;
|
Object execute(PaymentApprovalReq req);
|
||||||
|
|
||||||
/**
|
|
||||||
* @package io.shinhanlife.dap.dapmt.service
|
|
||||||
* @className PaymentApprovalService
|
|
||||||
* @description AX HUB 시스템 처리 클래스
|
|
||||||
* @author 0986406
|
|
||||||
* @create 2026.09.01
|
|
||||||
* <pre>
|
|
||||||
* ---------- 개정이력 ----------
|
|
||||||
* 수정일 수정자 수정내용
|
|
||||||
* ---------- -------- ---------------------------
|
|
||||||
* 2026.09.01 0986406 최초생성
|
|
||||||
*
|
|
||||||
* </pre>
|
|
||||||
*/
|
|
||||||
@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<String, Object> 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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
* <pre>
|
||||||
|
* ---------- 개정이력 ----------
|
||||||
|
* 수정일 수정자 수정내용
|
||||||
|
* ---------- -------- ---------------------------
|
||||||
|
* 2026.09.01 0986406 최초생성
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
@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<String, Object> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,51 +1,7 @@
|
|||||||
package io.shinhanlife.dap.dapmt.service;
|
package io.shinhanlife.dap.dapmt.service;
|
||||||
|
|
||||||
import io.shinhanlife.dap.dapmt.annotation.McpFunction;
|
import io.shinhanlife.dap.dapmt.dto.*;
|
||||||
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 java.util.Map;
|
public interface SmsToolService {
|
||||||
|
Object sendSms(SmsSendReq req);
|
||||||
/**
|
|
||||||
* @package io.shinhanlife.dap.dapmt.sms
|
|
||||||
* @className SmsToolService
|
|
||||||
* @description AX HUB 시스템 처리 클래스
|
|
||||||
* @author 0986406
|
|
||||||
* @create 2026.09.01
|
|
||||||
* <pre>
|
|
||||||
* ---------- 개정이력 ----------
|
|
||||||
* 수정일 수정자 수정내용
|
|
||||||
* ---------- -------- ---------------------------
|
|
||||||
* 2026.09.01 0986406 최초생성
|
|
||||||
*
|
|
||||||
* </pre>
|
|
||||||
*/
|
|
||||||
@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<String, Object> result = executeLegacy("EAI", "SMS_SEND_001", legacyReq);
|
|
||||||
|
|
||||||
// 결과 가공
|
|
||||||
if ("SUCCESS".equals(result.get("status"))) {
|
|
||||||
result.put("message", "SMS가 성공적으로 발송되었습니다.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -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
|
||||||
|
* <pre>
|
||||||
|
* ---------- 개정이력 ----------
|
||||||
|
* 수정일 수정자 수정내용
|
||||||
|
* ---------- -------- ---------------------------
|
||||||
|
* 2026.09.01 0986406 최초생성
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
@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<String, Object> result = executeLegacy("EAI", "SMS_SEND_001", legacyReq);
|
||||||
|
|
||||||
|
// 결과 가공
|
||||||
|
if ("SUCCESS".equals(result.get("status"))) {
|
||||||
|
result.put("message", "SMS가 성공적으로 발송되었습니다.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user