jade 1a70495686
All checks were successful
Deploy to OCIWP / deploy (push) Successful in 1m51s
feat(ui): add tool-test-console and tester dashboards
- Add Auto-Tester Dashboard (tester.html) in gateway for batch testing tools

- Add standalone Tool Test Console (tool-test-console.html) in core

- Fix Tailwind CSS Preflight conflicts in console UI

- Update console payload schema resolution to support both gateway and pod modes

- Strip JSON-RPC metadata from tool payload output in console

- Add unified navigation headers across all static HTML pages
2026-08-04 18:24:52 +09:00
2026-07-22 15:31:13 +09:00

AX HUB MCP Tool

신한라이프 업무 시스템과 AI Agent를 연결하는 MCP(Model Context Protocol) Gateway 및 Tool 서버 프로젝트입니다.

Agent는 Gateway에서 Tool 목록과 입력 명세를 받고, Gateway는 권한과 정책을 확인한 뒤 Tool 서버로 요청을 전달합니다. 업무 Tool은 DTO → UseCase → Converter → MCI/EAI Client 구조로 레거시 시스템을 호출합니다.

전체 흐름

AI Agent / MCP Client
        │
        ▼
MCP Gateway (dap-gateway)
  ├─ Tool 목록·스키마 제공
  ├─ Tool 권한·승인·가드레일 확인
  ├─ Redis Registry 및 실행 추적
  └─ 대상 Tool 서버로 라우팅
        │
        ▼
Tool Server (dap-tool-sms / dap-tool-oth)
  └─ BusinessToolController
        │
        ▼
UseCase → Converter → MCI/EAI Client → 레거시 시스템

현재 구조와 목표 구조

현재는 Gateway와 두 개의 Tool 애플리케이션으로 구성됩니다.

현재: Gateway + SMS Tool Pod + OTH Tool Pod
목표: Gateway + 고객 Pod + 영업 Pod + 지급/납입 Pod + 알림 Pod + 인사 Pod + 공통 Pod

dap-tool-oth에는 여러 업무 카테고리가 함께 있습니다. AA 협의 후에는 부서·업무 소유권 단위로 Tool 서버, 이미지, Pod, 배포 파이프라인을 분리합니다. 이 목표 구조는 향후 전환 방향이며 현재 구현 완료 상태가 아닙니다.

Gradle 멀티모듈

모듈 역할 실행 포트
dap-gateway MCP 진입점, Tool Registry, 라우팅, 권한·가드레일, Chat API 8081
dap-tool-core 공통 어노테이션, Controller, JSON Schema, MCI/EAI 지원, 보안·로깅 공통 기능 라이브러리
dap-tool-sms SMS/알림 Tool 서버 8082
dap-tool-oth 공통·업무·샘플·MCI Tool 서버 8084

기술 기준은 Java 21, Spring Boot 4, Gradle, Spring AI MCP Server, Redis, MapStruct, MyBatis, Resilience4j입니다.

환경 (Environment)

항목 버전 / 기준
Java 21
Spring Boot 4.0.5
Gradle Wrapper 8.14.3
Spring AI BOM 2.0.0
Spring AI MCP Server spring-ai-starter-mcp-server-webmvc
Redis Client Lettuce 6.6.0.RELEASE
Resilience Resilience4j 2.2.0
MyBatis Spring Boot Starter 3.0.3
MapStruct 1.5.5.Final
Lombok 1.18.32
JSON Schema Validator networknt 1.4.0
OpenAPI UI springdoc 2.5.0
컨테이너 실행 Docker Compose

프로젝트는 JDK 21을 기준으로 컴파일됩니다. IntelliJ에서는 Project SDK, Gradle JVM, Run Configuration JRE를 모두 JDK 21로 맞춰야 합니다.

5분 빠른 시작

Docker와 JDK 21이 준비된 로컬 개발 환경 기준입니다.

# 1. Redis와 MCI Mock만 먼저 실행
$env:ACTIVE_PROFILE = 'local'
docker compose up -d redis mci-mock

# 2. Gateway 실행 (새 PowerShell)
$env:SPRING_PROFILES_ACTIVE = 'local'
$env:OPENROUTER_API_KEY = '<개발용 비밀 저장소의 키>'
.\gradlew.bat :dap-gateway:bootRun

# 3. OTH Tool 실행 (또 다른 PowerShell)
$env:SPRING_PROFILES_ACTIVE = 'local'
$env:AXHUB_GATEWAY_URL = 'http://localhost:8081'
$env:AXHUB_TOOL_URL = 'http://localhost:8084'
.\gradlew.bat :dap-tool-oth:bootRun

Tool 서버가 기동된 뒤 아래 URL로 등록된 Tool 목록을 확인합니다.

http://localhost:8081/mcp/api/v1/tools/list

SMS Tool도 함께 확인하려면 별도 PowerShell에서 아래 명령을 실행합니다.

$env:SPRING_PROFILES_ACTIVE = 'local'
$env:AXHUB_GATEWAY_URL = 'http://localhost:8081'
$env:AXHUB_TOOL_URL = 'http://localhost:8082'
.\gradlew.bat :dap-tool-sms:bootRun

전체 컨테이너 환경이 필요하면 개별 실행 대신 다음 한 줄을 사용합니다.

$env:ACTIVE_PROFILE = 'local'
docker compose up -d --build

Tool 등록과 실행

등록과 목록 제공

  1. Tool 서버 기동 시 ToolRegistryHeartbeatSender@McpTool, @McpFunction을 스캔합니다.
  2. Tool 이름, 설명, 입력 JSON Schema, categoryKey, 연동 방식, 실행 URL을 메타데이터로 생성합니다.
  3. Gateway Redis Registry에 등록·Heartbeat 정보를 전송합니다.
  4. Agent와 관리 화면은 Gateway에서 Tool 목록과 명세를 조회합니다.

실행

  1. Agent가 Gateway에 Tool 이름과 입력값을 보냅니다.
  2. Gateway가 Tool 존재 여부, 허용 Tool, 쓰기 승인, 가드레일을 확인합니다.
  3. Gateway가 Tool 서버의 /mcp/{toolName}으로 요청을 전달합니다.
  4. BusinessToolController가 Tool 메서드를 찾아 DTO로 변환하고 JSON Schema를 검증합니다.
  5. UseCase가 업무 흐름을 수행합니다.
  6. Converter가 업무 DTO를 인터페이스 ID 기반 MCI 요청 DTO로 변환합니다.
  7. MCI/EAI Client가 레거시를 호출하고 결과를 Tool 응답으로 반환합니다.

주요 URL

로컬에서 Gateway를 직접 실행할 때의 기준입니다. Docker Compose를 사용하면 Gateway 호스트 포트는 8281입니다.

용도 메서드 URL
Tool 목록 GET http://localhost:8081/mcp/api/v1/tools/list
Tool 실행 POST http://localhost:8081/mcp/api/v1/tools/call
Tool Markdown 문서 GET http://localhost:8081/mcp/api/v1/tools/docs/markdown
카테고리별 SSE MCP 연결 GET http://localhost:8081/mcp/sse/{categoryKey}
카테고리별 MCP 호출 채널 POST http://localhost:8081/mcp/custom/{categoryKey}
Chat 스트리밍 API POST http://localhost:8081/api/chat
Scaffold API POST http://localhost:8081/api/v1/scaffold/pod 또는 /tool

/mcp/sse/{categoryKey}는 SSE 연결을 여는 전송 경로이고, /mcp/custom/{categoryKey}는 같은 카테고리의 MCP 요청을 처리하는 호출 경로입니다. 두 URL은 역할이 다릅니다.

Tool 개발 표준

구성 요소 책임
XxxRequest, XxxResponse Agent/Tool 관점의 입력·응답 DTO
XxxUseCase Tool 계약과 MCP 메타데이터 선언
XxxUseCaseImpl 업무 흐름 조합과 Client 호출
XxxConverter 업무 DTO와 레거시 인터페이스 DTO 사이 변환
MciXxxClient Glow/MCI 또는 EAI 통신 호출
INTERFACE_ID_I, INTERFACE_ID_O 인터페이스 ID 기준 MCI 요청·응답 DTO

Tool 선언

Tool 그룹에는 @McpTool, Agent가 호출하는 함수에는 @McpFunction을 사용합니다.

@McpTool(routingType = "MCI", categoryKey = "claim")
public interface ClaimInquiryUseCase {

    @McpFunction(
        name = "claim_inquiry",
        displayName = "보험금 청구 조회",
        description = "청구 번호로 보험금 청구 상태를 조회합니다.",
        mappingId = "CLM00000001"
    )
    ClaimInquiryResponse inquire(ClaimInquiryRequest request);
}

categoryKey는 Tool의 업무 그룹입니다. Gateway의 목록 필터링, Agent 권한, 동적 MCP 서버 구분에 사용하므로 합의된 업무 키를 사용합니다.

  • MCI: 사내 MCI 인터페이스 호출
  • EAI: EAI 연동
  • DIRECT: 외부 HTTP 또는 내부 직접 연동

변환 원칙

UseCase 구현체는 Tool 요청을 레거시 요청과 섞어 쓰지 않습니다. Converter에서 변환한 뒤 Client에 전달합니다.

@Override
public ClaimInquiryResponse inquire(ClaimInquiryRequest request) {
    CLM00000001_I mciRequest = converter.toMciRequest(request);
    CLM00000001_O mciResponse = mciClmClient.callClm00000001(mciRequest);
    return converter.toResponse(mciResponse);
}

MCI 입출력 객체는 업무 이름이 아니라 인터페이스 ID를 기준으로 둡니다.

CLCNNB00001_I  : CLCNNB00001 요청 DTO
CLCNNB00001_O  : CLCNNB00001 응답 DTO

예를 들어 Onnba3011RequestCLCNNB00001_I는 같은 업무 데이터를 담을 수 있지만 같은 객체가 아닙니다. 둘 사이의 변환 책임은 Onnba3011Converter에 둡니다.

새 Tool 추가 체크리스트

새 업무 Tool을 추가할 때는 아래 순서로 확인합니다.

  • 소속 모듈과 categoryKey를 업무 소유 조직 기준으로 결정한다.
  • Agent 입력·응답 DTO인 XxxRequest, XxxResponse를 만든다.
  • XxxUseCase@McpTool을 선언하고, 호출 메서드에 @McpFunction의 이름·설명·연동 ID를 선언한다.
  • XxxUseCaseImpl에서 업무 흐름만 조합한다.
  • XxxConverter에 업무 DTO ↔ 인터페이스 ID DTO 변환을 둔다.
  • MciXxxClientINTERFACE_ID_I, INTERFACE_ID_O를 인터페이스 ID 기준으로 만든다.
  • DTO에 Bean Validation을 선언하고, 중첩 DTO가 있으면 입력 Schema와 검증 대상에 포함되는지 확인한다.
  • 조회·변경 작업 특성에 따라 readOnlyHint, requiresApproval, idempotentHint를 설정한다.
  • 단위 테스트를 작성하고 :dap-tool-core:test 또는 대상 모듈 테스트를 실행한다.
  • Tool 서버 기동 후 /mcp/api/v1/tools/list에서 이름, 설명, category, JSON Schema가 맞는지 확인한다.
  • 요청·응답 로그에 개인정보나 인증값이 남지 않는지 확인한다.

등록·노출 제어

속성 의미
register Redis Registry와 Gateway 카탈로그에 등록할지 여부
visible Agent/클라이언트 목록에 표시할지 여부
requiresApproval 쓰기·고위험 작업의 승인 요구 여부
readOnlyHint, destructiveHint, idempotentHint Agent 호출 특성 힌트

register = false인 Tool은 자동 카탈로그 등록 대상이 아닙니다. 별도 실행 목적이 있는 경우에만 사용하고, 필요한 fallback 경로를 운영 설정으로 확인합니다.

빌드·테스트·로컬 실행

사전 조건

  • JDK 21
  • Gradle Wrapper 사용 권장
  • 로컬 Redis 또는 Docker Compose 환경
  • 필요 시 MCI Mock 또는 사내 MCI/EAI 접근 환경

전체 빌드와 대표 검증

.\gradlew.bat clean build
.\gradlew.bat :dap-tool-core:test
.\gradlew.bat :dap-tool-core:compileJava

애플리케이션 실행

각 애플리케이션은 별도 PowerShell에서 실행합니다.

# Gateway
.\gradlew.bat :dap-gateway:bootRun

# SMS Tool
.\gradlew.bat :dap-tool-sms:bootRun

# 기타 업무 Tool
.\gradlew.bat :dap-tool-oth:bootRun

기본 프로필은 local입니다. 개발 서버 설정이 필요하면 실행 환경에 프로필을 지정합니다.

$env:SPRING_PROFILES_ACTIVE = 'dev'
.\gradlew.bat :dap-tool-oth:bootRun

Docker Compose 실행

Docker Compose는 Redis, Gateway, MCI Mock, SMS Tool, OTH Tool을 함께 기동합니다.

$env:ACTIVE_PROFILE = 'local'
docker compose up -d --build
docker compose ps
서비스 컨테이너 포트 호스트 포트
Redis 6379 6379
Gateway 8081 8281
MCI Mock 8080 8089
SMS Tool 8082 8282
OTH Tool 8084 8284

컨테이너 내부와 PC 브라우저의 접속 주소는 다릅니다.

컨테이너 내부: http://gateway:8081, http://tool-oth:8084
PC 브라우저:    http://localhost:8281, http://localhost:8284

환경 설정

프로필

기본 프로필은 local입니다. Tool 서버와 Gateway 모두 local, dev 프로필 파일을 사용합니다.

프로필 목적 주요 설정 파일
local PC 개발·MCI Mock·H2 메모리 DB 기반 실행 application-local.yml
dev 개발 서버 배포 실행 application-dev.yml

프로필은 환경 변수로 지정합니다.

# 로컬 개발
$env:SPRING_PROFILES_ACTIVE = 'local'

# 개발 서버 설정으로 실행
$env:SPRING_PROFILES_ACTIVE = 'dev'

환경별 연결 주소 비교

항목 local 프로세스 실행 Docker Compose dev 프로필
Gateway 접근 주소 http://localhost:8081 컨테이너 내부 http://gateway:8081 배포 환경 Gateway URL
SMS Tool 주소 http://localhost:8082 http://tool-sms:8082 PORT 기본 8082
OTH Tool 주소 http://localhost:8084 http://tool-oth:8084 PORT 기본 8084
Redis 주소 로컬 Redis 또는 localhost:6379 redis:6379 운영/개발 Redis 설정
MCI/EAI 대상 MCI Mock 또는 로컬 설정 mci-mock:8080 개발망 연동 설정
브라우저 Gateway 접속 http://localhost:8081 http://localhost:8281 운영·개발 도메인

local에서 프로세스를 직접 실행하면 Tool의 AXHUB_GATEWAY_URLlocalhost를 사용합니다. Docker에서는 각 컨테이너가 서로 다른 네트워크 공간에 있으므로 반드시 Compose 서비스 이름을 사용합니다.

Gateway 환경 변수

변수 적용 대상 설명 로컬 기본값/예시
SPRING_PROFILES_ACTIVE Gateway, 모든 Tool 활성 Spring 프로필 local
OPENROUTER_API_KEY Gateway Chat/LLM 호출 API 키 운영·개발 환경의 비밀 저장소에서 주입
SPRING_DATA_REDIS_HOST Gateway, 모든 Tool Redis 호스트 Docker: redis
SPRING_DATA_REDIS_PORT Gateway, 모든 Tool Redis 포트 6379
MCP_GATEWAY_FALLBACK_DEFAULT_URL Gateway Registry에 없는 Tool의 기본 fallback URL Docker: http://tool-oth:8084
MCP_GATEWAY_FALLBACK_ROUTES_SMS Gateway SMS 계열 fallback URL Docker: http://tool-sms:8082
ACTIVE_PROFILE Docker Compose Compose가 SPRING_PROFILES_ACTIVE에 전달할 프로필 local

OPENROUTER_API_KEY 같은 인증값은 application.yml, README, Git 커밋에 직접 넣지 않습니다. 개발·운영 환경의 Secret, CI/CD 변수 또는 안전한 환경 변수로 주입합니다.

Tool 서버 환경 변수

변수 적용 대상 설명 로컬 기본값/예시
PORT dap-tool-sms, dap-tool-oth 개발 프로필에서 Tool 서버 포트 변경 SMS 8082, OTH 8084
AXHUB_GATEWAY_URL 모든 Tool Tool 등록·Heartbeat 대상 Gateway 주소 로컬 http://localhost:8081, Docker http://gateway:8081
AXHUB_TOOL_URL 모든 Tool Gateway가 해당 Tool Pod를 호출할 주소 로컬 http://localhost:{server.port}
GLOW_COMMUNICATION_MCI_HOMT Docker Tool 컨테이너 MCI 대상 호스트 로컬 Compose는 mci-mock
GLOW_COMMUNICATION_MCI_PORT Docker Tool 컨테이너 MCI 대상 포트 로컬 Compose는 8080
GLOW_COMMUNICATION_EAI_HOMT Docker Tool 컨테이너 EAI 대상 호스트 로컬 Compose는 mci-mock
GLOW_COMMUNICATION_EAI_PORT Docker Tool 컨테이너 EAI 대상 포트 로컬 Compose는 8080

AXHUB_TOOL_URL은 반드시 Gateway가 실제로 접근 가능한 주소여야 합니다. PC에서 각각 실행할 때는 localhost를 사용하고, Docker 컨테이너 안에서는 tool-sms, tool-oth 같은 Compose 서비스 이름을 사용합니다.

로컬 실행용 권장 설정

아래는 키 값 없이 로컬 프로세스를 실행하는 예시입니다. Redis를 Docker로 먼저 기동하거나 전체 Docker Compose를 사용합니다.

# 선택 1: Redis만 기동
$env:ACTIVE_PROFILE = 'local'
docker compose up -d redis mci-mock

# 선택 2: 각 프로세스를 로컬에서 기동
$env:SPRING_PROFILES_ACTIVE = 'local'
$env:OPENROUTER_API_KEY = '<개인 또는 개발용 비밀 저장소의 키>'
.\gradlew.bat :dap-gateway:bootRun

다른 PowerShell에서 Tool을 실행합니다.

$env:SPRING_PROFILES_ACTIVE = 'local'
$env:AXHUB_GATEWAY_URL = 'http://localhost:8081'
$env:AXHUB_TOOL_URL = 'http://localhost:8084'
.\gradlew.bat :dap-tool-oth:bootRun

권한 도메인 설정

mcp.security.tenant-domains는 테넌트 또는 호출 주체가 접근할 수 있는 categoryKey를 정의합니다. 운영 환경에서는 ALL을 무분별하게 사용하지 않고, Agent·조직별 허용 도메인을 최소 권한으로 설정합니다.

mcp:
  security:
    tenant-domains:
      claims-agent: claim, customer
      notification-agent: notification

공통 기능과 운영 기준

Redis

Redis는 Tool Registry의 등록 상태와 Heartbeat, Gateway 실행 추적 정보에 사용됩니다. 현재 Redis는 PII 원문 보관소가 아닙니다.

권한과 승인

Gateway는 Agent가 전달한 허용 Tool 목록, 서버 정책, 신뢰된 Claim 여부, 쓰기 승인 여부를 확인합니다. Tool마다 권한 로직을 중복 구현하지 말고 Gateway 공통 정책과 @McpFunction 메타데이터를 사용합니다.

Trace ID와 Request ID

trace-id   : 사용자 요청 전체에서 유지되는 상관관계 ID
request-id : Gateway → Tool, Tool → MCI 등 HTTP 호출마다 새로 생성되는 ID

Gateway와 Tool에는 관련 헤더 및 MDC 기반 로그 처리가 있습니다. 신규 HTTP Client도 공통 전파 정책을 따르며, Tool별로 임의의 헤더 이름을 추가하지 않습니다.

로그와 개인정보

Gateway에는 민감 키와 일부 형식을 마스킹하는 공통 기능이 있습니다. 마스킹은 원문을 Agent에서 분리하는 PII 토큰화와는 다릅니다.

  • 요청·응답 전문을 로그에 남길 때는 반드시 마스킹합니다.
  • 운영 로그에 주민번호, 계좌번호, 전화번호, 이메일, 인증값을 남기지 않습니다.
  • Tool 서버의 신규 로그도 같은 마스킹 정책을 적용합니다.
  • 민감정보 복원 필요 여부는 Tool 개발자가 임의로 결정하지 않고 보안·AA 정책을 따릅니다.

AA 협의 기반 향후 전환 과제

아래 항목은 현재 구현 완료 기능이 아니라 회의에서 합의한 목표 구조입니다.

부서별 Tool Pod와 저장소 경계

현재 dap-tool-oth에 함께 있는 업무 Tool을 부서·업무 소유권 단위로 분리합니다. 각 Pod는 독립 이미지, 독립 배포, 독립 장애 범위를 갖도록 구성합니다. 실제 분리는 AA가 확정한 Tool 소유 부서와 운영 책임 매핑을 기준으로 수행합니다.

Agent별 Tool 노출 수 제한

Agent에게 모든 Tool을 한 번에 제공하지 않고, 업무 도메인과 권한에 따라 약 10~20개 수준의 Tool 그룹을 제공합니다. categoryKey는 이를 위한 기초 메타데이터이며, 향후 Agent-Tool Group 정책으로 확장합니다.

PII 토큰화

원문 개인정보
  → PII Gateway가 Redis에 짧은 TTL로 보관
  → Agent에는 PII 토큰 또는 안전한 식별자만 전달
  → 인가된 Tool이 MCI 호출 직전에 필요한 항목만 복원

이 전환 전까지는 현행 마스킹 기능을 PII 분리 구현으로 오해하지 않아야 합니다.

MCP SDK와 Glow Framework

Gateway에는 Spring AI MCP Server 의존성이 포함되어 있습니다. MCP SDK/Glow 표준 적용 시에는 업무 Tool을 재작성하지 않고, 기존 @McpTool·@McpFunction과 UseCase를 표준 MCP Tool 명세·호출 콜백으로 연결하는 Adapter 계층을 공통 Core에 추가합니다.

MCP SDK 표준 tools/list, tools/call
        ↓
공통 Adapter
        ↓
기존 UseCase → Converter → MCI Client

따라서 업무 DTO, Converter, MCI Client의 책임은 유지됩니다.

참고 소스

주제 대표 위치
Gateway Tool API dap-gateway/.../presentation/McpRouterController.java
동적 MCP SSE/호출 경로 dap-gateway/.../sync/DynamicMcpController.java
Tool 실행 Controller dap-tool-core/.../presentation/BusinessToolController.java
Tool 자동 등록 dap-tool-core/.../usecase/ToolRegistryHeartbeatSender.java
Tool 어노테이션 dap-tool-core/.../annotation/McpTool.java, McpFunction.java
Tool 예시 dap-tool-oth/.../biz/oth, biz/sol, biz/smp
SMS Tool 예시 dap-tool-sms/.../biz/sms
Docker 환경 docker-compose.yml

문서에 없는 업무·보안·배포 기준은 임의로 추가하지 말고 AA 및 플랫폼 운영 기준과 먼저 합의합니다.

Input/Output Schema 작성 가이드

Tool Schema는 Agent가 Tool을 정확히 호출하고, 반환값의 의미를 일관되게 해석하도록 하는 계약입니다. 인증 정보·사번·주민번호 등 민감정보(PII)는 Input/Output Schema와 Tool 응답에 포함하지 않습니다.

Input Schema

Input Schema는 Agent가 Tool에 전달하는 파라미터의 이름, 타입, 필수 여부, 허용값, 형식 등을 정의합니다.

적용 우선순위는 다음과 같습니다.

  1. inputSchemaResource — 복잡한 규칙을 담은 JSON Schema 리소스
  2. inputSchema — 어노테이션에 직접 선언한 JSON Schema
  3. 요청 DTO 필드의 @McpValidation — 자동 JSON Schema 생성

단순한 요청 DTO는 @McpValidation만으로 관리합니다.

public class ClaimSearchRequest {

    @McpValidation(required = true, pattern = "^CLM[0-9]{13}$")
    private String claimNo;

    @McpValidation(minimum = 1, maximum = 100)
    private Integer size;
}

Output Schema

Output Schema는 Tool이 반환하는 결과의 타입과 의미를 정의합니다. BusinessToolController는 Tool 실행 후 반환값을 Output Schema 기준으로 검증합니다.

적용 우선순위는 다음과 같습니다.

  1. outputSchemaResource — 조건부 필드·중첩 배열 등 복잡한 규칙을 담은 JSON Schema 리소스
  2. outputSchema — 어노테이션에 직접 선언한 JSON Schema
  3. 반환 DTO의 @McpOutputSchema와 필드 @McpValidation — 자동 JSON Schema 생성
  4. 위 설정이 모두 없으면 Output Schema 검증을 수행하지 않음

따라서 단순한 응답은 별도 outputSchemaResource 없이 반환 DTO에 @McpOutputSchema를 선언하면 됩니다. null이 정상 값일 수 있는 필드는 nullable = true를 반드시 지정합니다.

@McpOutputSchema
public class ClaimSearchResponse {

    @McpValidation(required = true, allowedValues = {"SUCCESS", "FAILURE"})
    private String resultCode;

    @McpValidation(nullable = true, minimum = 0)
    private Long approvedAmount;
}

복잡한 Schema는 Tool 모듈별 리소스로 관리

조건부 응답, 중첩 DTO, 배열 정렬 기준처럼 어노테이션만으로 표현하기 어려운 규칙은 Tool Core가 아니라 각 Tool 모듈의 리소스에 JSON Schema로 둡니다.

src/main/resources/
└─ tool-schemas/
   └─ {categoryKey}/
      ├─ claim-search-resource-input-schema.json
      └─ claim-search-resource-output-schema.json

예를 들어 categoryKeycmm이면 아래와 같이 선언합니다.

@McpFunction(
    name = "oth.cmm.claim.search",
    inputSchemaResource = "classpath:tool-schemas/cmm/claim-search-resource-input-schema.json",
    outputSchemaResource = "classpath:tool-schemas/cmm/claim-search-resource-output-schema.json"
)
public ClaimSearchResponse search(ClaimSearchRequest request) {
    // ...
}

inputSchemaResourceoutputSchemaResource는 복잡한 경우에만 선언합니다. 단순한 Tool까지 JSON 파일을 별도 생성할 필요는 없습니다.

Output 설계 규칙

  • 코드와 표시용 라벨을 함께 반환합니다. 예: status + statusLabel
  • null이 정상인 값은 의미를 설명에 명시하고 DTO에는 nullable = true를 설정합니다.
  • 조건부 필드는 어떤 조건에서 값이 존재하는지 JSON Schema에 명시합니다.
  • 배열은 정렬 기준을 설명에 명시합니다. 예: 접수일 내림차순
  • 목록 응답에는 추가 조회 여부를 나타내는 hasMore를 포함합니다.
  • 민감정보는 마스킹보다 응답에서 제외하는 것을 우선합니다.

실행 로그 및 확인

Tool 실행이 끝나면 아래 로그는 Schema 정의가 아니라 검증을 통과한 실제 최종 응답값을 출력합니다.

[Tool -> MCP Gateway] Output Schema Result: { ... }

따라서 로그에도 실제 응답이 남으므로, 응답 DTO와 Output Schema에 민감정보가 포함되지 않도록 설계해야 합니다.

스키마 리소스와 DTO 기반 자동 Schema는 아래 테스트로 함께 검증할 수 있습니다.

.\gradlew.bat :dap-tool-oth:test --tests "io.shinhanlife.dap.mcc.biz.cmm.dto.ClaimSearchRequestSchemaTest"

Tool Naming Convention

All Tool names use the four-level lowercase format pod.domain.service.action. Do not use underscores or CamelCase; use a hyphen (-) only when a single level has multiple words.

  • pod: deployment Tool Pod/module (dap-tool-othoth, dap-tool-smssms)
  • domain: business-domain package (cmm, smp, sol, etc.)
  • service: business service or resource
  • action: the requested operation (search, list, detail, issue, inquiry, etc.)
oth.cmm.bond.issue
oth.cmm.claim.search
oth.sol.request.list
oth.smp.weather.inquiry

When Scaffold receives dap-tool-oth, cmm, and ClaimSearch, it generates oth.cmm.claim.search. The validateMcpToolNames Gradle task rejects both a duplicate name and any name outside this format before packaging, including its source file and line number.

Tool Test Console

각 Tool Pod는 공통 테스트 화면을 제공합니다.

http://localhost:8084/tool-test-console.html

화면은 현재 Pod의 /tool-manifest에서 Tool 목록과 inputSchema를 읽습니다. Tool을 선택한 뒤 Schema 샘플 채우기로 요청 JSON을 만들고 실행할 수 있습니다. 업무에 맞게 보정한 요청은 현재 요청 저장으로 브라우저의 localStorage에 보관합니다.

Run saved cases는 저장된 테스트 케이스를 순차 실행해 성공/실패, HTTP 상태, 소요 시간을 보여줍니다. 따라서 Tool이 수백 개여도 각 Tool마다 테스트 화면을 만들 필요 없이, 유효한 업무 테스트 데이터만 한 번 저장하면 이후에는 몇 번의 클릭으로 회귀 테스트할 수 있습니다.

  • Tool 호출은 현재 Pod의 /mcp/{toolName}로 수행합니다.
  • 매 실행마다 trace-id, request-id를 새로 생성하여 응답과 함께 표시합니다.
  • 외부 MCI/EAI Tool은 샘플값 대신 개발계에서 허용된 테스트 데이터를 저장해서 사용해야 합니다.
Description
ax_hub_mcp_tool
Readme 95 MiB
Languages
Java 59.8%
HTML 40%
Dockerfile 0.2%