From 0ebac4e375acd41080199545ac3ee986ea9945ba Mon Sep 17 00:00:00 2001 From: jade Date: Fri, 17 Jul 2026 18:08:12 +0900 Subject: [PATCH] =?UTF-8?q?McpFunction=EC=97=90=20MCP=20=ED=91=9C=EC=A4=80?= =?UTF-8?q?=20=ED=9E=8C=ED=8A=B8=204=EA=B0=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dap/biz/mcp/gateway/dto/ToolMetadata.java | 14 +++++++++++++- .../sync/RegistryMcpToolSpecificationFactory.java | 6 ++++++ .../dap/biz/mcp/tool/annotation/McpFunction.java | 5 +++++ .../dap/biz/mcp/tool/dto/ToolMetadata.java | 13 ++++++++++++- .../tool/service/ToolRegistryHeartbeatSender.java | 6 +++++- 5 files changed, 41 insertions(+), 3 deletions(-) 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 +}