refactor: remove claim schema sample tool
Some checks failed
Deploy to OCIWP / deploy (push) Failing after 1m56s
Some checks failed
Deploy to OCIWP / deploy (push) Failing after 1m56s
This commit is contained in:
@@ -144,7 +144,7 @@ UI에서 사용하는 Tailwind CSS와 Chart.js는 `dap-gateway/src/main/resource
|
||||
"jsonrpc": "2.0",
|
||||
"method": "tools/call",
|
||||
"params": {
|
||||
"name": "cmm_claim_schema_search",
|
||||
"name": "cmm_claim_search",
|
||||
"arguments": {
|
||||
"claimNo": "CLM2026070100120"
|
||||
}
|
||||
@@ -171,7 +171,7 @@ Tool 함수명은 아래 4단계 규칙을 사용합니다.
|
||||
|
||||
```text
|
||||
pod_domain_service_action
|
||||
예: cmm_claim_schema_search
|
||||
예: cmm_claim_search
|
||||
```
|
||||
|
||||
- `pod`: Tool Pod 식별자 (`oth`, `sms` 등)
|
||||
@@ -268,4 +268,4 @@ Tool 관련 공통 기능은 `dap-was-*` 모듈명만 기준으로 동작합니
|
||||
- `validateMcpToolNames`는 `dap-was-*` Tool Pod를 탐색하여 이름 규칙과 전역 중복을 검사합니다.
|
||||
- Tool Scaffold는 Pod 이름을 Tool 함수명에 포함하지 않습니다. 함수명은 `도메인_비즈니스_행위` 형식입니다. 예: `cmm_notification_send`
|
||||
- Pod Scaffold와 Gateway Scaffold 화면/API의 모듈 목록도 `dap-was-*` 명칭으로 통일되어 있습니다.
|
||||
- Tool Source Update 기능은 `dap-was-*` 아래의 `*UseCase.java`를 검색합니다.
|
||||
- Tool Source Update 기능은 `dap-was-*` 아래의 `*UseCase.java`를 검색합니다.
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
package io.shinhanlife.dap.mcc.biz.cmm.dto;
|
||||
|
||||
|
||||
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import org.springaicommunity.mcp.annotation.McpToolParam;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* 보험금 청구 조회 Tool의 입력 DTO 샘플이다.
|
||||
* 청구번호 또는 계약번호 중 하나를 반드시 입력받는다.
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class ClaimSearchRequest {
|
||||
|
||||
@McpToolParam(description = "청구번호. CLM 다음 숫자 13자리 형식이다.")
|
||||
@Schema(pattern = "^CLM[0-9]{13}$", example = "CLM2026070100123")
|
||||
private String claimNo;
|
||||
|
||||
@McpToolParam(description = "계약번호. 숫자 11자리 형식이다.")
|
||||
@Schema(pattern = "^[0-9]{11}$", example = "10023456789")
|
||||
private String contractNo;
|
||||
|
||||
@McpToolParam(description = "청구 상태 필터")
|
||||
@Schema(example = "RECEIVED", allowableValues = {
|
||||
"RECEIVED", "REVIEWING", "ADDITIONAL_DOC_REQUIRED",
|
||||
"APPROVED", "PAID", "REJECTED", "WITHDRAWN"
|
||||
})
|
||||
private String status;
|
||||
|
||||
@McpToolParam(description = "청구 유형 필터")
|
||||
@Schema(example = "MEDICAL", allowableValues = {
|
||||
"MEDICAL", "SURGERY", "HOSPITALIZATION",
|
||||
"DIAGNOSIS", "DEATH", "DISABILITY"
|
||||
})
|
||||
private String claimType;
|
||||
|
||||
@McpToolParam(description = "접수일 조회 시작일(YYYY-MM-DD)")
|
||||
@Schema(format = "date", example = "2026-01-01")
|
||||
private String fromDate;
|
||||
|
||||
@McpToolParam(description = "접수일 조회 종료일(YYYY-MM-DD)")
|
||||
@Schema(format = "date", example = "2026-07-31")
|
||||
private String toDate;
|
||||
|
||||
@McpToolParam(description = "반환할 최대 건수 (기본값: 20, 최대: 50)")
|
||||
@Schema(pattern = "^[1-9][0-9]?$|^50$", defaultValue = "20", example = "20")
|
||||
private String size;
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
package io.shinhanlife.dap.mcc.biz.cmm.dto;
|
||||
|
||||
|
||||
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import org.springaicommunity.mcp.annotation.McpToolParam;
|
||||
import java.util.List;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* Claim search response sample.
|
||||
* Complex response rules are defined by outputSchemaResource; annotations document
|
||||
* the same simple field constraints for automatic schema generation examples.
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class ClaimSearchResponse {
|
||||
|
||||
@McpToolParam(description = "Execution result code.")
|
||||
@Schema(required = true, allowableValues = {"SUCCESS", "FAILURE"})
|
||||
private String resultCode;
|
||||
|
||||
@McpToolParam(description = "User-readable label for resultCode.")
|
||||
@Schema(required = true, maxLength = 100)
|
||||
private String resultLabel;
|
||||
|
||||
@McpToolParam(description = "Current claim processing status code.")
|
||||
@Schema(required = true, allowableValues = {
|
||||
"RECEIVED", "REVIEWING", "ADDITIONAL_DOC_REQUIRED",
|
||||
"APPROVED", "PAID", "REJECTED", "WITHDRAWN"
|
||||
})
|
||||
private String status;
|
||||
|
||||
@McpToolParam(description = "User-readable label for status.")
|
||||
@Schema(required = true, maxLength = 100)
|
||||
private String statusLabel;
|
||||
|
||||
@McpToolParam(description = "Approved amount. Null before review; do not interpret null as zero.")
|
||||
@Schema(minimum = "0", nullable = true)
|
||||
private Long approvedAmount;
|
||||
|
||||
@McpToolParam(description = "Present only when status is REJECTED; otherwise null.")
|
||||
@Schema(maxLength = 200, nullable = true)
|
||||
private String rejectionReason;
|
||||
|
||||
@McpToolParam(description = "Claim summaries, ordered by received date descending.")
|
||||
@Schema(required = true)
|
||||
private List<ClaimSummary> items;
|
||||
|
||||
@McpToolParam(description = "True when additional results exist beyond this response.")
|
||||
@Schema(required = true)
|
||||
private Boolean hasMore;
|
||||
|
||||
@McpToolParam(description = "Total number of matched claims.")
|
||||
@Schema(required = true, nullable = true)
|
||||
private Integer totalCount;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class ClaimSummary {
|
||||
|
||||
@McpToolParam(description = "Claim processing status code.")
|
||||
private String status;
|
||||
|
||||
@McpToolParam(description = "User-readable label for status.")
|
||||
private String statusLabel;
|
||||
|
||||
@McpToolParam(description = "Received date in YYYY-MM-DD format.")
|
||||
@Schema(required = true, format = "date")
|
||||
private String receivedDate;
|
||||
|
||||
@McpToolParam(description = "Approved amount. Null before review; do not interpret null as zero.")
|
||||
@Schema(nullable = true)
|
||||
private Long approvedAmount;
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
package io.shinhanlife.dap.mcc.biz.cmm.usecase;
|
||||
|
||||
import org.springaicommunity.mcp.annotation.McpTool;
|
||||
import io.shinhanlife.dap.lib.annotation.ToolHint;
|
||||
|
||||
import io.shinhanlife.dap.mcc.biz.cmm.dto.ClaimSearchRequest;
|
||||
import io.shinhanlife.dap.mcc.biz.cmm.dto.ClaimSearchResponse;
|
||||
|
||||
public interface ClaimSearchSchemaSampleUseCase {
|
||||
|
||||
@McpTool(name = "cmm_claim_schema_search", title = "청구 조회 스키마 샘플", description = "Claim search Tool sample using input and output JSON Schema resources.", annotations = @McpTool.McpAnnotations(readOnlyHint = true, idempotentHint = true))
|
||||
@ToolHint(register = false, categoryKey = "cmm",
|
||||
inputSchemaResource = "classpath:tool-schemas/cmm/claim-search-resource-input-schema.json",
|
||||
outputSchemaResource = "classpath:tool-schemas/cmm/claim-search-resource-output-schema.json")
|
||||
ClaimSearchResponse search(ClaimSearchRequest request);
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
package io.shinhanlife.dap.mcc.biz.cmm.usecase.impl;
|
||||
|
||||
import io.shinhanlife.dap.mcc.biz.cmm.dto.ClaimSearchRequest;
|
||||
import io.shinhanlife.dap.mcc.biz.cmm.dto.ClaimSearchResponse;
|
||||
import io.shinhanlife.dap.mcc.biz.cmm.usecase.ClaimSearchSchemaSampleUseCase;
|
||||
import java.util.List;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* Non-exposed sample Tool. It does not call MCI or EIMS.
|
||||
*/
|
||||
@Service
|
||||
public class ClaimSearchSchemaSampleUseCaseImpl implements ClaimSearchSchemaSampleUseCase {
|
||||
|
||||
@Override
|
||||
public ClaimSearchResponse search(ClaimSearchRequest request) {
|
||||
ClaimSearchResponse.ClaimSummary item = ClaimSearchResponse.ClaimSummary.builder()
|
||||
.status("REVIEWING")
|
||||
.statusLabel("Under review")
|
||||
.receivedDate("2026-08-04")
|
||||
.approvedAmount(null)
|
||||
.build();
|
||||
|
||||
return ClaimSearchResponse.builder()
|
||||
.resultCode("SUCCESS")
|
||||
.resultLabel("Success")
|
||||
.status("REVIEWING")
|
||||
.statusLabel("Under review")
|
||||
.approvedAmount(null)
|
||||
.rejectionReason(null)
|
||||
.items(List.of(item))
|
||||
.hasMore(false)
|
||||
.totalCount(1)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@ import io.shinhanlife.dap.lib.annotation.ToolHint;
|
||||
import io.shinhanlife.dap.mcc.biz.oth.dto.*;
|
||||
|
||||
public interface Onnba3011UseCase {
|
||||
@McpTool(name = "onnba3011_call", description = "Onnba3011 호출 툴")
|
||||
@McpTool(name = "oth_onnba3011_call", description = "Onnba3011 호출 툴")
|
||||
@ToolHint(categoryKey = "oth", register = false)
|
||||
Object execute(Onnba3011Request req);
|
||||
}
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
{
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"claimNo": {
|
||||
"type": "string",
|
||||
"description": "청구번호. CLM 이후 숫자 13자리 형식입니다.",
|
||||
"pattern": "^CLM[0-9]{13}$",
|
||||
"example": "CLM2026070100123"
|
||||
},
|
||||
"contractNo": {
|
||||
"type": "string",
|
||||
"description": "계약번호. 숫자 11자리 형식입니다.",
|
||||
"pattern": "^[0-9]{11}$",
|
||||
"example": "10023456789"
|
||||
},
|
||||
"status": {
|
||||
"type": "string",
|
||||
"description": "청구 상태 필터",
|
||||
"enum": ["RECEIVED", "REVIEWING", "ADDITIONAL_DOC_REQUIRED", "APPROVED", "PAID", "REJECTED", "WITHDRAWN"],
|
||||
"example": "RECEIVED"
|
||||
},
|
||||
"claimType": {
|
||||
"type": "string",
|
||||
"description": "청구 유형 필터",
|
||||
"enum": ["MEDICAL", "SURGERY", "HOSPITALIZATION", "DIAGNOSIS", "DEATH", "DISABILITY"],
|
||||
"example": "MEDICAL"
|
||||
},
|
||||
"fromDate": {
|
||||
"type": "string",
|
||||
"description": "접수일 조회 시작일 (YYYY-MM-DD)",
|
||||
"format": "date",
|
||||
"example": "2026-01-01"
|
||||
},
|
||||
"toDate": {
|
||||
"type": "string",
|
||||
"description": "접수일 조회 종료일 (YYYY-MM-DD)",
|
||||
"format": "date",
|
||||
"example": "2026-07-31"
|
||||
},
|
||||
"size": {
|
||||
"type": "string",
|
||||
"description": "반환할 최대 건수 (기본값: 20, 최대: 50)",
|
||||
"pattern": "^[1-9][0-9]?$|^50$",
|
||||
"default": "20",
|
||||
"example": "20"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
{
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"resultCode": {
|
||||
"type": "string",
|
||||
"description": "실행 결과 코드",
|
||||
"enum": ["SUCCESS", "FAILURE"]
|
||||
},
|
||||
"resultLabel": {
|
||||
"type": "string",
|
||||
"description": "resultCode의 사용자 표시 라벨",
|
||||
"maxLength": 100
|
||||
},
|
||||
"status": {
|
||||
"type": "string",
|
||||
"description": "현재 청구 처리 상태 코드",
|
||||
"enum": ["RECEIVED", "REVIEWING", "ADDITIONAL_DOC_REQUIRED", "APPROVED", "PAID", "REJECTED", "WITHDRAWN"]
|
||||
},
|
||||
"statusLabel": {
|
||||
"type": "string",
|
||||
"description": "status의 사용자 표시 라벨",
|
||||
"maxLength": 100
|
||||
},
|
||||
"approvedAmount": {
|
||||
"anyOf": [
|
||||
{"type": "integer", "minimum": 0},
|
||||
{"type": "null"}
|
||||
],
|
||||
"description": "승인 금액. 심사 전에는 null이며 0으로 해석하지 않습니다."
|
||||
},
|
||||
"rejectionReason": {
|
||||
"anyOf": [
|
||||
{"type": "string", "maxLength": 200},
|
||||
{"type": "null"}
|
||||
],
|
||||
"description": "status가 REJECTED일 때만 존재하며, 그 외에는 null입니다."
|
||||
},
|
||||
"items": {
|
||||
"type": "array",
|
||||
"description": "수령일 내림차순으로 정렬된 청구 요약 목록",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"status": {
|
||||
"type": "string",
|
||||
"description": "청구 처리 상태 코드"
|
||||
},
|
||||
"statusLabel": {
|
||||
"type": "string",
|
||||
"description": "status의 사용자 표시 라벨"
|
||||
},
|
||||
"receivedDate": {
|
||||
"type": "string",
|
||||
"description": "접수일 (YYYY-MM-DD 형식)",
|
||||
"format": "date"
|
||||
},
|
||||
"approvedAmount": {
|
||||
"anyOf": [
|
||||
{"type": "integer", "minimum": 0},
|
||||
{"type": "null"}
|
||||
],
|
||||
"description": "승인 금액. 심사 전에는 null"
|
||||
}
|
||||
},
|
||||
"required": ["receivedDate"]
|
||||
}
|
||||
},
|
||||
"hasMore": {
|
||||
"type": "boolean",
|
||||
"description": "이 응답 이후 추가 결과가 있는지 여부"
|
||||
},
|
||||
"totalCount": {
|
||||
"anyOf": [
|
||||
{"type": "integer", "minimum": 0},
|
||||
{"type": "null"}
|
||||
],
|
||||
"description": "매칭된 청구 건수 합계"
|
||||
}
|
||||
},
|
||||
"required": ["resultCode", "resultLabel", "status", "statusLabel", "items", "hasMore"]
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"claimNo": {
|
||||
"type": "string",
|
||||
"description": "청구번호. CLM 다음 숫자 13자리 형식이다.",
|
||||
"pattern": "^CLM[0-9]{13}$",
|
||||
"examples": ["CLM2026070100123"]
|
||||
},
|
||||
"contractNo": {
|
||||
"type": "string",
|
||||
"description": "계약번호. 숫자 11자리 형식이다.",
|
||||
"pattern": "^[0-9]{11}$",
|
||||
"examples": ["10023456789"]
|
||||
},
|
||||
"status": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"RECEIVED", "REVIEWING", "ADDITIONAL_DOC_REQUIRED",
|
||||
"APPROVED", "PAID", "REJECTED", "WITHDRAWN"
|
||||
]
|
||||
},
|
||||
"size": {
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"maximum": 50,
|
||||
"default": 20
|
||||
}
|
||||
},
|
||||
"required": [],
|
||||
"additionalProperties": false,
|
||||
"anyOf": [
|
||||
{ "required": ["claimNo"] },
|
||||
{ "required": ["contractNo"] }
|
||||
]
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"type": "object",
|
||||
"description": "Claim search response. This schema intentionally excludes employee identifiers, customer names, contact details, account information, and other PII.",
|
||||
"properties": {
|
||||
"resultCode": {
|
||||
"type": "string",
|
||||
"enum": ["SUCCESS", "FAILURE"],
|
||||
"description": "Machine-readable execution result code."
|
||||
},
|
||||
"resultLabel": {
|
||||
"type": "string",
|
||||
"description": "User-readable label for resultCode."
|
||||
},
|
||||
"status": {
|
||||
"type": "string",
|
||||
"enum": ["RECEIVED", "REVIEWING", "ADDITIONAL_DOC_REQUIRED", "APPROVED", "PAID", "REJECTED", "WITHDRAWN"],
|
||||
"description": "Current claim processing status code."
|
||||
},
|
||||
"statusLabel": {
|
||||
"type": "string",
|
||||
"description": "User-readable label for status."
|
||||
},
|
||||
"approvedAmount": {
|
||||
"anyOf": [
|
||||
{ "type": "number", "minimum": 0 },
|
||||
{ "type": "null" }
|
||||
],
|
||||
"description": "Approved amount. It is null before review and must not be interpreted as zero."
|
||||
},
|
||||
"rejectionReason": {
|
||||
"type": ["string", "null"],
|
||||
"maxLength": 200,
|
||||
"description": "Has a value only when status is REJECTED. It is null for every other status."
|
||||
},
|
||||
"items": {
|
||||
"type": "array",
|
||||
"description": "Claim summaries ordered by receivedDate descending. No personally identifiable information is included.",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"status": { "type": "string", "description": "Claim status code." },
|
||||
"statusLabel": { "type": "string", "description": "User-readable label for status." },
|
||||
"receivedDate": { "type": "string", "format": "date", "description": "Claim received date." },
|
||||
"approvedAmount": {
|
||||
"anyOf": [
|
||||
{ "type": "number", "minimum": 0 },
|
||||
{ "type": "null" }
|
||||
],
|
||||
"description": "Null before review; do not interpret as zero."
|
||||
}
|
||||
},
|
||||
"required": ["status", "statusLabel", "receivedDate"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"hasMore": {
|
||||
"type": "boolean",
|
||||
"description": "True when additional results exist beyond this response."
|
||||
},
|
||||
"totalCount": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"description": "Total number of matched claims."
|
||||
}
|
||||
},
|
||||
"required": ["resultCode", "resultLabel", "status", "statusLabel", "items", "hasMore", "totalCount"],
|
||||
"allOf": [
|
||||
{
|
||||
"if": {
|
||||
"properties": { "status": { "const": "REJECTED" } },
|
||||
"required": ["status"]
|
||||
},
|
||||
"then": {
|
||||
"properties": { "rejectionReason": { "type": "string", "minLength": 1 } },
|
||||
"required": ["rejectionReason"]
|
||||
}
|
||||
}
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
package io.shinhanlife.dap.mcc.biz.cmm.dto;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import io.shinhanlife.dap.lib.util.JsonSchemaGenerator;
|
||||
import io.shinhanlife.dap.lib.util.ToolSchemaResolver;
|
||||
import io.shinhanlife.dap.lib.annotation.ToolHint;
|
||||
import io.shinhanlife.dap.mcc.biz.cmm.usecase.impl.ClaimSearchSchemaSampleUseCaseImpl;
|
||||
import io.shinhanlife.dap.lib.validation.ToolArgumentSchemaValidator;import io.shinhanlife.dap.mcc.biz.cmm.usecase.ClaimSearchSchemaSampleUseCase;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springaicommunity.mcp.annotation.McpTool;
|
||||
|
||||
class ClaimSearchRequestSchemaTest {
|
||||
|
||||
@Test
|
||||
void generatesClaimOrContractSearchSchema() {
|
||||
Map<String, Object> schema = JsonSchemaGenerator.generateSchema(ClaimSearchRequest.class);
|
||||
Map<String, Map<String, Object>> properties = properties(schema);
|
||||
|
||||
assertEquals(false, schema.get("additionalProperties"));
|
||||
assertEquals("^CLM[0-9]{13}$", properties.get("claimNo").get("pattern"));
|
||||
assertEquals("^[1-9][0-9]?$|^50$", properties.get("size").get("pattern"));
|
||||
assertEquals("20", properties.get("size").get("default"));
|
||||
assertFalse(schema.containsKey("anyOf"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void resolvesSchemaFromToolModuleResource() throws Exception {
|
||||
Method method = ClaimSearchSchemaSampleUseCase.class
|
||||
.getDeclaredMethod("search", ClaimSearchRequest.class);
|
||||
McpTool function = method.getAnnotation(McpTool.class);
|
||||
ToolHint hint = method.getAnnotation(ToolHint.class);
|
||||
|
||||
Map<String, Object> schema = new ToolSchemaResolver(new ObjectMapper())
|
||||
.resolve(function, hint, ClaimSearchRequest.class);
|
||||
|
||||
assertEquals("https://json-schema.org/draft/2020-12/schema", schema.get("$schema"));
|
||||
assertTrue(schema.containsKey("anyOf"));
|
||||
assertEquals(50, property(schema, "size").get("maximum"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void resolvesOutputSchemaFromToolModuleResource() throws Exception {
|
||||
Method method = ClaimSearchSchemaSampleUseCase.class
|
||||
.getDeclaredMethod("search", ClaimSearchRequest.class);
|
||||
McpTool function = method.getAnnotation(McpTool.class);
|
||||
ToolHint hint = method.getAnnotation(ToolHint.class);
|
||||
Map<String, Object> schema = new ToolSchemaResolver(new ObjectMapper())
|
||||
.resolveOutput(function, ClaimSearchResponse.class, hint);
|
||||
assertEquals("https://json-schema.org/draft/2020-12/schema", schema.get("$schema"));
|
||||
assertTrue(properties(schema).containsKey("resultCode"));
|
||||
assertTrue(properties(schema).containsKey("statusLabel"));
|
||||
assertTrue(properties(schema).containsKey("hasMore"));
|
||||
assertTrue(schema.containsKey("allOf"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void sampleResponseConformsToOutputSchema() throws Exception {
|
||||
Method method = ClaimSearchSchemaSampleUseCase.class
|
||||
.getDeclaredMethod("search", ClaimSearchRequest.class);
|
||||
Map<String, Object> schema = new ToolSchemaResolver(new ObjectMapper())
|
||||
.resolveOutput(method.getAnnotation(McpTool.class), ClaimSearchResponse.class,
|
||||
method.getAnnotation(ToolHint.class));
|
||||
|
||||
ClaimSearchResponse response = new ClaimSearchSchemaSampleUseCaseImpl().search(new ClaimSearchRequest());
|
||||
ToolArgumentSchemaValidator validator = new ToolArgumentSchemaValidator(new ObjectMapper());
|
||||
|
||||
assertTrue(validator.validateValue(schema, response).isEmpty());
|
||||
}
|
||||
@Test
|
||||
void sampleResponseConformsToAutomaticallyGeneratedOutputSchema() throws Exception {
|
||||
Map<String, Object> schema = JsonSchemaGenerator.generateSchema(ClaimSearchResponse.class);
|
||||
ClaimSearchResponse response = new ClaimSearchSchemaSampleUseCaseImpl().search(new ClaimSearchRequest());
|
||||
ToolArgumentSchemaValidator validator = new ToolArgumentSchemaValidator(new ObjectMapper());
|
||||
|
||||
assertTrue(validator.validateValue(schema, response).isEmpty());
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
private Map<String, Map<String, Object>> properties(Map<String, Object> schema) {
|
||||
return (Map<String, Map<String, Object>>) schema.get("properties");
|
||||
}
|
||||
|
||||
private Map<String, Object> property(Map<String, Object> schema, String name) {
|
||||
return properties(schema).get(name);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user