diff --git a/dap-gateway/src/main/java/io/shinhanlife/dap/biz/mcp/gateway/dto/ToolMetadata.java b/dap-gateway/src/main/java/io/shinhanlife/dap/biz/mcp/gateway/dto/ToolMetadata.java index c3af4e2..18f0eec 100644 --- a/dap-gateway/src/main/java/io/shinhanlife/dap/biz/mcp/gateway/dto/ToolMetadata.java +++ b/dap-gateway/src/main/java/io/shinhanlife/dap/biz/mcp/gateway/dto/ToolMetadata.java @@ -71,6 +71,18 @@ public class ToolMetadata { @Builder.Default private Boolean requiresApproval = false; + @Builder.Default + private Boolean readOnlyHint = false; + + @Builder.Default + private Boolean destructiveHint = false; + + @Builder.Default + private Boolean idempotentHint = false; + + @Builder.Default + private Boolean openWorldHint = false; + // 3. 연동 아키텍처 구분 (DIRECT / MCI_EAI) @@ -113,4 +125,4 @@ public class ToolMetadata { if (parametersSchema == null || !parametersSchema.containsKey("required")) return Set.of(); return new HashSet<>((List) parametersSchema.get("required")); } -} \ No newline at end of file +} diff --git a/dap-gateway/src/main/java/io/shinhanlife/dap/biz/mcp/gateway/sync/RegistryMcpToolSpecificationFactory.java b/dap-gateway/src/main/java/io/shinhanlife/dap/biz/mcp/gateway/sync/RegistryMcpToolSpecificationFactory.java index e8717cb..79234bd 100644 --- a/dap-gateway/src/main/java/io/shinhanlife/dap/biz/mcp/gateway/sync/RegistryMcpToolSpecificationFactory.java +++ b/dap-gateway/src/main/java/io/shinhanlife/dap/biz/mcp/gateway/sync/RegistryMcpToolSpecificationFactory.java @@ -52,6 +52,12 @@ public class RegistryMcpToolSpecificationFactory { .name(entry.getName()) .description(description(entry)) .inputSchema(inputSchema(entry)) + .annotations(McpSchema.ToolAnnotations.builder() + .readOnlyHint(Boolean.TRUE.equals(entry.getReadOnlyHint())) + .destructiveHint(Boolean.TRUE.equals(entry.getDestructiveHint())) + .idempotentHint(Boolean.TRUE.equals(entry.getIdempotentHint())) + .openWorldHint(Boolean.TRUE.equals(entry.getOpenWorldHint())) + .build()) .build(); return McpServerFeatures.SyncToolSpecification.builder() diff --git a/dap-tool-core/src/main/java/io/shinhanlife/dap/biz/mcp/tool/annotation/McpFunction.java b/dap-tool-core/src/main/java/io/shinhanlife/dap/biz/mcp/tool/annotation/McpFunction.java index 0e4271a..201946e 100644 --- a/dap-tool-core/src/main/java/io/shinhanlife/dap/biz/mcp/tool/annotation/McpFunction.java +++ b/dap-tool-core/src/main/java/io/shinhanlife/dap/biz/mcp/tool/annotation/McpFunction.java @@ -39,5 +39,10 @@ public @interface McpFunction { // 추가: HITL 승인 체계 지원 (실행 전 사용자 승인 필요 여부) boolean requiresApproval() default false; + boolean readOnlyHint() default false; + boolean destructiveHint() default false; + boolean idempotentHint() default false; + boolean openWorldHint() default false; + // 추가: 툴 별 기본 Timeout 설정 (기본 300초 = 300000ms) } diff --git a/dap-tool-core/src/main/java/io/shinhanlife/dap/biz/mcp/tool/dto/ToolMetadata.java b/dap-tool-core/src/main/java/io/shinhanlife/dap/biz/mcp/tool/dto/ToolMetadata.java index 476b30f..99734cd 100644 --- a/dap-tool-core/src/main/java/io/shinhanlife/dap/biz/mcp/tool/dto/ToolMetadata.java +++ b/dap-tool-core/src/main/java/io/shinhanlife/dap/biz/mcp/tool/dto/ToolMetadata.java @@ -58,6 +58,17 @@ public class ToolMetadata { @Builder.Default private Boolean requiresApproval = false; + @Builder.Default + private Boolean readOnlyHint = false; + + @Builder.Default + private Boolean destructiveHint = false; + + @Builder.Default + private Boolean idempotentHint = false; + + @Builder.Default + private Boolean openWorldHint = false; -} \ No newline at end of file +} diff --git a/dap-tool-core/src/main/java/io/shinhanlife/dap/biz/mcp/tool/service/ToolRegistryHeartbeatSender.java b/dap-tool-core/src/main/java/io/shinhanlife/dap/biz/mcp/tool/service/ToolRegistryHeartbeatSender.java index 1bee996..3dacff7 100644 --- a/dap-tool-core/src/main/java/io/shinhanlife/dap/biz/mcp/tool/service/ToolRegistryHeartbeatSender.java +++ b/dap-tool-core/src/main/java/io/shinhanlife/dap/biz/mcp/tool/service/ToolRegistryHeartbeatSender.java @@ -107,6 +107,10 @@ public class ToolRegistryHeartbeatSender { meta.setVisible(isVisible); meta.setIsRegistered(isRegister); meta.setRequiresApproval(functionAnnotation.requiresApproval()); + meta.setReadOnlyHint(functionAnnotation.readOnlyHint()); + meta.setDestructiveHint(functionAnnotation.destructiveHint()); + meta.setIdempotentHint(functionAnnotation.idempotentHint()); + meta.setOpenWorldHint(functionAnnotation.openWorldHint()); Map prompts = new HashMap<>(); String promptText = functionAnnotation.prompt(); @@ -174,4 +178,4 @@ public class ToolRegistryHeartbeatSender { log.error(" [HeartbeatSender] 툴 등록 실패: {}", ex.getMessage()); } } -} \ No newline at end of file +}