From 7dd47d39b92ea33ade5c6adf1e0c4108c8a7fd12 Mon Sep 17 00:00:00 2001 From: devmrko Date: Tue, 4 Aug 2026 14:55:24 +0900 Subject: [PATCH] refs #744: expose DDS MCP under public context path --- .../ddsbackoffice/config/SecurityConfig.java | 4 ++-- .../ddsbackoffice/web/DdsMcpSseController.java | 15 +++++++++++---- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/dds-backoffice/src/main/java/com/cloudhandson/ddsbackoffice/config/SecurityConfig.java b/dds-backoffice/src/main/java/com/cloudhandson/ddsbackoffice/config/SecurityConfig.java index 03cdae8..8f9c26b 100644 --- a/dds-backoffice/src/main/java/com/cloudhandson/ddsbackoffice/config/SecurityConfig.java +++ b/dds-backoffice/src/main/java/com/cloudhandson/ddsbackoffice/config/SecurityConfig.java @@ -24,13 +24,13 @@ public class SecurityConfig { } return http - .csrf(csrf -> csrf.ignoringRequestMatchers("/dds/mcp/messages")) + .csrf(csrf -> csrf.ignoringRequestMatchers("/dds/mcp/messages", "/mcp/dds/messages")) .headers(headers -> headers.httpStrictTransportSecurity(hsts -> hsts .includeSubDomains(true) .maxAgeInSeconds(31_536_000))) .authorizeHttpRequests(auth -> auth .requestMatchers("/css/**", "/js/**", "/health", "/login", - "/dds/mcp/sse", "/dds/mcp/messages").permitAll() + "/dds/mcp/sse", "/dds/mcp/messages", "/mcp/dds/sse", "/mcp/dds/messages").permitAll() .anyRequest().authenticated()) .httpBasic(basic -> { }) diff --git a/dds-backoffice/src/main/java/com/cloudhandson/ddsbackoffice/web/DdsMcpSseController.java b/dds-backoffice/src/main/java/com/cloudhandson/ddsbackoffice/web/DdsMcpSseController.java index b3f9342..f4d6c37 100644 --- a/dds-backoffice/src/main/java/com/cloudhandson/ddsbackoffice/web/DdsMcpSseController.java +++ b/dds-backoffice/src/main/java/com/cloudhandson/ddsbackoffice/web/DdsMcpSseController.java @@ -6,6 +6,7 @@ import com.cloudhandson.ddsbackoffice.service.DdsMcpSseService; import com.cloudhandson.vpdbackoffice.service.AppException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ObjectNode; +import jakarta.servlet.http.HttpServletRequest; import java.io.IOException; import java.util.Map; import java.util.UUID; @@ -38,8 +39,11 @@ public class DdsMcpSseController { this.service = service; } - @GetMapping(path = "/dds/mcp/sse", produces = MediaType.TEXT_EVENT_STREAM_VALUE) - public SseEmitter sse(@RequestHeader(name = "Authorization", required = false) String authorization) throws IOException { + @GetMapping(path = {"/dds/mcp/sse", "/mcp/dds/sse"}, produces = MediaType.TEXT_EVENT_STREAM_VALUE) + public SseEmitter sse( + @RequestHeader(name = "Authorization", required = false) String authorization, + HttpServletRequest request + ) throws IOException { DdsMcpAuthenticatedUser user = bearerAuthenticator.authenticate(authorization); String sessionId = UUID.randomUUID().toString(); SseEmitter emitter = new SseEmitter(SSE_TIMEOUT_MILLIS); @@ -47,11 +51,14 @@ public class DdsMcpSseController { emitter.onCompletion(() -> sessions.remove(sessionId)); emitter.onTimeout(() -> sessions.remove(sessionId)); emitter.onError(error -> sessions.remove(sessionId)); - emitter.send(SseEmitter.event().name("endpoint").data("/dds/mcp/messages?sessionId=" + sessionId)); + String messagesPath = request.getRequestURI().startsWith("/mcp/dds/") + ? "/mcp/dds/messages" + : "/dds/mcp/messages"; + emitter.send(SseEmitter.event().name("endpoint").data(messagesPath + "?sessionId=" + sessionId)); return emitter; } - @PostMapping(path = "/dds/mcp/messages", consumes = MediaType.APPLICATION_JSON_VALUE) + @PostMapping(path = {"/dds/mcp/messages", "/mcp/dds/messages"}, consumes = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity message( @RequestHeader(name = "Authorization", required = false) String authorization, @RequestParam(required = false) String sessionId,