Copilot commented on code in PR #7876:
URL: https://github.com/apache/incubator-seata/pull/7876#discussion_r2636963475


##########
console/src/main/java/org/apache/seata/mcp/core/props/MCPProperties.java:
##########
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.seata.mcp.core.props;
+
+import jakarta.annotation.PostConstruct;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.env.Environment;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+@Component
+public class MCPProperties {
+
+    public static final String SSE_TYPE = "sse";
+    public static final String STREAMABLE_TYPE = "streamable";
+
+    private boolean enableAuth = true;
+
+    private Long queryDuration = TimeUnit.DAYS.toMillis(1);
+
+    private String mcpType = SSE_TYPE;
+
+    private StreamableProperties streamableProperties;
+
+    private SseServerProperties sseServerProperties;
+
+    public MCPProperties() {}
+
+    public boolean isSseType() {
+        return mcpType.equals(SSE_TYPE);
+    }
+
+    public List<String> getEndpoints() {
+        List<String> result = new ArrayList<>();
+        if (isSseType()) {
+            result.add(sseServerProperties.sseEndpoint);
+            result.add(sseServerProperties.messageEndpoint);
+        } else {
+            result.add(streamableProperties.mcpEndPoint);
+        }
+        return result;

Review Comment:
   The getEndpoints method can throw a NullPointerException if called before 
the init method completes, or if init fails to initialize the properties. When 
mcpType is SSE_TYPE, sseServerProperties might be null. When mcpType is not 
SSE_TYPE, streamableProperties might be null. Consider adding null checks or 
ensuring proper initialization validation.



##########
console/src/main/java/org/apache/seata/console/filter/MCPAuthenticationFilter.java:
##########
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.seata.console.filter;
+
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import org.apache.seata.console.security.User;
+import org.springframework.http.HttpStatus;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.BadCredentialsException;
+import 
org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.web.filter.OncePerRequestFilter;
+
+import java.io.IOException;
+
+public class MCPAuthenticationFilter extends OncePerRequestFilter {
+
+    private final AuthenticationManager authenticationManager;
+
+    /**
+     * Instantiates a new Jwt authentication token filter.
+     *
+     * @param authenticationManager the token provider
+     */
+    public MCPAuthenticationFilter(AuthenticationManager 
authenticationManager) {
+        this.authenticationManager = authenticationManager;
+    }
+
+    @Override
+    protected void doFilterInternal(HttpServletRequest request, 
HttpServletResponse response, FilterChain chain)
+            throws IOException, ServletException {
+
+        Authentication existingAuth = 
SecurityContextHolder.getContext().getAuthentication();
+        if (existingAuth != null && existingAuth.isAuthenticated()) {
+            chain.doFilter(request, response);
+            return;
+        }
+
+        User user = resolveHeaders(request);
+
+        UsernamePasswordAuthenticationToken authenticationToken =
+                new UsernamePasswordAuthenticationToken(user.getUsername(), 
user.getPassword());
+
+        try {
+            Authentication authentication = 
authenticationManager.authenticate(authenticationToken);
+            
SecurityContextHolder.getContext().setAuthentication(authentication);
+        } catch (BadCredentialsException e) {
+            response.sendError(HttpStatus.UNAUTHORIZED.value(), "Invalid 
credentials");
+            return;
+        }
+
+        chain.doFilter(request, response);
+    }
+
+    /**
+     * Get userDetails from header
+     */
+    private User resolveHeaders(HttpServletRequest request) {
+        String username = request.getHeader("X-Mcp-Username");
+        String password = request.getHeader("X-Mcp-Password");
+        return new User(username, password);
+    }

Review Comment:
   Sensitive credentials (username and password) are being transmitted in 
custom HTTP headers. This approach can lead to credentials being logged by 
proxies, load balancers, or application logs. Consider using standard 
authentication mechanisms like HTTP Basic Authentication or Bearer tokens, 
which have better tooling support and are less likely to be inadvertently 
logged.



##########
console/src/main/java/org/apache/seata/console/filter/MCPAuthenticationFilter.java:
##########
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.seata.console.filter;
+
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import org.apache.seata.console.security.User;
+import org.springframework.http.HttpStatus;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.BadCredentialsException;
+import 
org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.web.filter.OncePerRequestFilter;
+
+import java.io.IOException;
+
+public class MCPAuthenticationFilter extends OncePerRequestFilter {
+
+    private final AuthenticationManager authenticationManager;
+
+    /**
+     * Instantiates a new Jwt authentication token filter.
+     *
+     * @param authenticationManager the token provider

Review Comment:
   The Javadoc comment incorrectly states "Instantiates a new Jwt 
authentication token filter" and refers to "the token provider". This should be 
updated to reflect that this is an MCP authentication filter that uses 
username/password from headers, not JWT tokens.
   ```suggestion
        * Instantiates a new MCP authentication filter that authenticates 
requests
        * using username and password provided in HTTP headers.
        *
        * @param authenticationManager the authentication manager used to 
validate credentials
   ```



##########
console/src/main/java/org/apache/seata/console/config/MCPFiltersConfig.java:
##########
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.seata.console.config;
+
+import org.apache.seata.console.filter.MCPAuthenticationFilter;
+import org.apache.seata.mcp.core.props.MCPProperties;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.web.servlet.FilterRegistrationBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.Ordered;
+import org.springframework.security.authentication.AuthenticationManager;
+
+@Configuration
+public class MCPFiltersConfig {
+
+    @Autowired
+    private AuthenticationManager authenticationManager;
+
+    @Autowired
+    private MCPProperties mcpProperties;
+
+    private static final Logger LOGGER = 
LoggerFactory.getLogger(MCPFiltersConfig.class);
+
+    @Bean
+    public FilterRegistrationBean<MCPAuthenticationFilter> 
mcpJwtAuthenticationTokenFilterRegistration() {
+
+        MCPAuthenticationFilter mcpJwtAuthenticationTokenFilter = new 
MCPAuthenticationFilter(authenticationManager);
+
+        FilterRegistrationBean<MCPAuthenticationFilter> registration = new 
FilterRegistrationBean<>();
+
+        registration.setFilter(mcpJwtAuthenticationTokenFilter);
+
+        for (String endPoint : mcpProperties.getEndpoints()) {
+            registration.addUrlPatterns(endPoint);
+        }
+
+        registration.setName("mcpJwtAuthenticationTokenFilter");

Review Comment:
   The method name 'mcpJwtAuthenticationTokenFilterRegistration' and variable 
'mcpJwtAuthenticationTokenFilter' reference 'Jwt' but this filter performs 
basic username/password authentication, not JWT authentication. The naming 
should reflect the actual authentication mechanism, such as 
'mcpAuthenticationFilterRegistration' and 'mcpAuthenticationFilter'.
   ```suggestion
       public FilterRegistrationBean<MCPAuthenticationFilter> 
mcpAuthenticationFilterRegistration() {
   
           MCPAuthenticationFilter mcpAuthenticationFilter = new 
MCPAuthenticationFilter(authenticationManager);
   
           FilterRegistrationBean<MCPAuthenticationFilter> registration = new 
FilterRegistrationBean<>();
   
           registration.setFilter(mcpAuthenticationFilter);
   
           for (String endPoint : mcpProperties.getEndpoints()) {
               registration.addUrlPatterns(endPoint);
           }
   
           registration.setName("mcpAuthenticationFilter");
   ```



##########
namingserver/src/main/resources/application.yml:
##########
@@ -40,3 +48,10 @@ seata:
     csrf-ignore-urls: /naming/v1/**,/api/v1/naming/**
     ignore:
       urls: 
/,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.jpeg,/**/*.ico,/api/v1/auth/login,/version.json,/naming/v1/health,/error
+  # MCP Server Configuration
+  mcp:
+    # Query limits the maximum time interval, The unit is milliseconds, 
Default one day
+    query:
+      max_query_duration: 86400000

Review Comment:
   The configuration property uses snake_case 'max_query_duration' which is 
inconsistent with typical Spring Boot property naming conventions that use 
kebab-case. This should be 'max-query-duration' to follow Spring Boot 
conventions.
   ```suggestion
         max-query-duration: 86400000
   ```



##########
console/src/main/java/org/apache/seata/console/filter/MCPAuthenticationFilter.java:
##########
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.seata.console.filter;
+
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import org.apache.seata.console.security.User;
+import org.springframework.http.HttpStatus;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.BadCredentialsException;
+import 
org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.web.filter.OncePerRequestFilter;
+
+import java.io.IOException;
+
+public class MCPAuthenticationFilter extends OncePerRequestFilter {
+
+    private final AuthenticationManager authenticationManager;
+
+    /**
+     * Instantiates a new Jwt authentication token filter.
+     *
+     * @param authenticationManager the token provider
+     */
+    public MCPAuthenticationFilter(AuthenticationManager 
authenticationManager) {
+        this.authenticationManager = authenticationManager;
+    }
+
+    @Override
+    protected void doFilterInternal(HttpServletRequest request, 
HttpServletResponse response, FilterChain chain)
+            throws IOException, ServletException {
+
+        Authentication existingAuth = 
SecurityContextHolder.getContext().getAuthentication();
+        if (existingAuth != null && existingAuth.isAuthenticated()) {
+            chain.doFilter(request, response);
+            return;
+        }
+
+        User user = resolveHeaders(request);
+
+        UsernamePasswordAuthenticationToken authenticationToken =
+                new UsernamePasswordAuthenticationToken(user.getUsername(), 
user.getPassword());
+
+        try {
+            Authentication authentication = 
authenticationManager.authenticate(authenticationToken);
+            
SecurityContextHolder.getContext().setAuthentication(authentication);
+        } catch (BadCredentialsException e) {
+            response.sendError(HttpStatus.UNAUTHORIZED.value(), "Invalid 
credentials");
+            return;
+        }
+
+        chain.doFilter(request, response);
+    }
+
+    /**
+     * Get userDetails from header
+     */
+    private User resolveHeaders(HttpServletRequest request) {
+        String username = request.getHeader("X-Mcp-Username");
+        String password = request.getHeader("X-Mcp-Password");

Review Comment:
   The resolveHeaders method does not validate that username and password 
headers are present. If these headers are missing, null values will be passed 
to the User constructor and subsequently to 
UsernamePasswordAuthenticationToken. This could lead to unexpected behavior or 
NullPointerException during authentication. Consider adding validation to 
return a clear error when required headers are missing.
   ```suggestion
           String password = request.getHeader("X-Mcp-Password");
           if (username == null || password == null) {
               throw new BadCredentialsException("Missing authentication 
headers");
           }
   ```



##########
console/src/main/java/org/apache/seata/mcp/core/props/MCPProperties.java:
##########
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.seata.mcp.core.props;
+
+import jakarta.annotation.PostConstruct;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.env.Environment;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+@Component
+public class MCPProperties {
+
+    public static final String SSE_TYPE = "sse";
+    public static final String STREAMABLE_TYPE = "streamable";
+
+    private boolean enableAuth = true;
+
+    private Long queryDuration = TimeUnit.DAYS.toMillis(1);
+
+    private String mcpType = SSE_TYPE;
+
+    private StreamableProperties streamableProperties;
+
+    private SseServerProperties sseServerProperties;
+
+    public MCPProperties() {}
+
+    public boolean isSseType() {
+        return mcpType.equals(SSE_TYPE);
+    }
+
+    public List<String> getEndpoints() {
+        List<String> result = new ArrayList<>();
+        if (isSseType()) {
+            result.add(sseServerProperties.sseEndpoint);
+            result.add(sseServerProperties.messageEndpoint);
+        } else {
+            result.add(streamableProperties.mcpEndPoint);
+        }
+        return result;
+    }
+
+    public Long getQueryDuration() {
+        return queryDuration;
+    }
+
+    public static class StreamableProperties {
+        private final String mcpEndPoint;
+
+        public StreamableProperties(String mcpEndPoint) {
+            this.mcpEndPoint = mcpEndPoint;
+        }
+    }
+
+    public static class SseServerProperties {
+
+        private final String sseEndpoint;
+
+        private final String messageEndpoint;
+
+        public SseServerProperties(String sseEndpoint, String messageEndpoint) 
{
+            this.sseEndpoint = sseEndpoint;
+            this.messageEndpoint = messageEndpoint;
+        }
+    }
+
+    @Autowired
+    private Environment env;

Review Comment:
   Field injection is used for the Environment dependency. Constructor 
injection is preferred over field injection as it makes dependencies explicit, 
enables immutability, facilitates testing, and prevents NullPointerException 
risks. Consider using constructor injection instead.



##########
console/src/main/java/org/apache/seata/console/filter/MCPAuthenticationFilter.java:
##########
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.seata.console.filter;
+
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import org.apache.seata.console.security.User;
+import org.springframework.http.HttpStatus;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.BadCredentialsException;
+import 
org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.web.filter.OncePerRequestFilter;
+
+import java.io.IOException;
+
+public class MCPAuthenticationFilter extends OncePerRequestFilter {
+
+    private final AuthenticationManager authenticationManager;
+
+    /**
+     * Instantiates a new Jwt authentication token filter.
+     *
+     * @param authenticationManager the token provider
+     */
+    public MCPAuthenticationFilter(AuthenticationManager 
authenticationManager) {
+        this.authenticationManager = authenticationManager;
+    }
+
+    @Override
+    protected void doFilterInternal(HttpServletRequest request, 
HttpServletResponse response, FilterChain chain)
+            throws IOException, ServletException {
+
+        Authentication existingAuth = 
SecurityContextHolder.getContext().getAuthentication();
+        if (existingAuth != null && existingAuth.isAuthenticated()) {
+            chain.doFilter(request, response);
+            return;
+        }

Review Comment:
   The authentication check at line 52 uses a weak condition. An authentication 
object can exist but represent an anonymous user. The check should verify both 
that authentication exists and that it represents a properly authenticated, 
non-anonymous user. Consider using `existingAuth.isAuthenticated() && 
!(existingAuth instanceof AnonymousAuthenticationToken)`.



##########
namingserver/src/main/resources/application.yml:
##########
@@ -40,3 +48,10 @@ seata:
     csrf-ignore-urls: /naming/v1/**,/api/v1/naming/**
     ignore:
       urls: 
/,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.jpeg,/**/*.ico,/api/v1/auth/login,/version.json,/naming/v1/health,/error
+  # MCP Server Configuration
+  mcp:
+    # Query limits the maximum time interval, The unit is milliseconds, 
Default one day

Review Comment:
   Comment says "Query limits the maximum time interval" but should say "Query 
limit for the maximum time interval" or "Maximum query time interval". The 
plural form "limits" is grammatically incorrect here.
   ```suggestion
       # Maximum query time interval, The unit is milliseconds, Default one day
   ```



##########
console/src/main/java/org/apache/seata/console/filter/MCPAuthenticationFilter.java:
##########
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.seata.console.filter;
+
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import org.apache.seata.console.security.User;
+import org.springframework.http.HttpStatus;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.BadCredentialsException;
+import 
org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.web.filter.OncePerRequestFilter;
+
+import java.io.IOException;
+
+public class MCPAuthenticationFilter extends OncePerRequestFilter {
+
+    private final AuthenticationManager authenticationManager;
+
+    /**
+     * Instantiates a new Jwt authentication token filter.
+     *
+     * @param authenticationManager the token provider
+     */
+    public MCPAuthenticationFilter(AuthenticationManager 
authenticationManager) {
+        this.authenticationManager = authenticationManager;
+    }
+
+    @Override
+    protected void doFilterInternal(HttpServletRequest request, 
HttpServletResponse response, FilterChain chain)
+            throws IOException, ServletException {
+
+        Authentication existingAuth = 
SecurityContextHolder.getContext().getAuthentication();
+        if (existingAuth != null && existingAuth.isAuthenticated()) {
+            chain.doFilter(request, response);
+            return;
+        }
+
+        User user = resolveHeaders(request);
+
+        UsernamePasswordAuthenticationToken authenticationToken =
+                new UsernamePasswordAuthenticationToken(user.getUsername(), 
user.getPassword());
+
+        try {
+            Authentication authentication = 
authenticationManager.authenticate(authenticationToken);
+            
SecurityContextHolder.getContext().setAuthentication(authentication);
+        } catch (BadCredentialsException e) {
+            response.sendError(HttpStatus.UNAUTHORIZED.value(), "Invalid 
credentials");
+            return;
+        }

Review Comment:
   The code only catches BadCredentialsException but the 
authenticationManager.authenticate() can throw other AuthenticationException 
subtypes such as DisabledException, LockedException, or 
AccountExpiredException. These exceptions would propagate uncaught, potentially 
exposing stack traces. Consider catching the broader AuthenticationException to 
handle all authentication failures gracefully.



##########
console/src/main/java/org/apache/seata/mcp/core/props/MCPProperties.java:
##########
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.seata.mcp.core.props;
+
+import jakarta.annotation.PostConstruct;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.env.Environment;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+@Component
+public class MCPProperties {
+
+    public static final String SSE_TYPE = "sse";
+    public static final String STREAMABLE_TYPE = "streamable";
+
+    private boolean enableAuth = true;
+
+    private Long queryDuration = TimeUnit.DAYS.toMillis(1);
+
+    private String mcpType = SSE_TYPE;
+
+    private StreamableProperties streamableProperties;
+
+    private SseServerProperties sseServerProperties;
+
+    public MCPProperties() {}
+
+    public boolean isSseType() {
+        return mcpType.equals(SSE_TYPE);
+    }
+
+    public List<String> getEndpoints() {
+        List<String> result = new ArrayList<>();
+        if (isSseType()) {
+            result.add(sseServerProperties.sseEndpoint);
+            result.add(sseServerProperties.messageEndpoint);
+        } else {
+            result.add(streamableProperties.mcpEndPoint);
+        }
+        return result;
+    }
+
+    public Long getQueryDuration() {
+        return queryDuration;
+    }
+
+    public static class StreamableProperties {
+        private final String mcpEndPoint;
+
+        public StreamableProperties(String mcpEndPoint) {
+            this.mcpEndPoint = mcpEndPoint;
+        }
+    }
+
+    public static class SseServerProperties {
+
+        private final String sseEndpoint;
+
+        private final String messageEndpoint;
+
+        public SseServerProperties(String sseEndpoint, String messageEndpoint) 
{
+            this.sseEndpoint = sseEndpoint;
+            this.messageEndpoint = messageEndpoint;
+        }
+    }
+
+    @Autowired
+    private Environment env;
+
+    @PostConstruct
+    public void init() {
+        mcpType = env.getProperty("spring.ai.mcp.server.protocol", "sse");
+        if (mcpType.equals(STREAMABLE_TYPE)) {
+            String mcpEndPoint = 
env.getProperty("spring.ai.mcp.server.streamable-http.mcp-endpoint", "/mcp");
+            streamableProperties = new StreamableProperties(mcpEndPoint);
+        } else {
+            mcpType = SSE_TYPE;
+            String sseEndpoint = 
env.getProperty("spring.ai.mcp.server.sse-endpoint", "/sse");
+            String messageEndpoint = 
env.getProperty("spring.ai.mcp.server.sse-message-endpoint", "/mcp/message");
+            sseServerProperties = new SseServerProperties(sseEndpoint, 
messageEndpoint);
+        }
+        queryDuration = 
Long.parseLong(env.getProperty("seata.mcp.query.max_query_duration", 
"86400000"));

Review Comment:
   Potential uncaught 'java.lang.NumberFormatException'.
   ```suggestion
           String maxQueryDurationStr = 
env.getProperty("seata.mcp.query.max_query_duration", "86400000");
           try {
               queryDuration = Long.parseLong(maxQueryDurationStr);
           } catch (NumberFormatException ex) {
               queryDuration = TimeUnit.DAYS.toMillis(1);
           }
   ```



##########
console/src/main/java/org/apache/seata/mcp/core/props/MCPProperties.java:
##########
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.seata.mcp.core.props;
+
+import jakarta.annotation.PostConstruct;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.env.Environment;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+@Component
+public class MCPProperties {
+
+    public static final String SSE_TYPE = "sse";
+    public static final String STREAMABLE_TYPE = "streamable";
+
+    private boolean enableAuth = true;
+
+    private Long queryDuration = TimeUnit.DAYS.toMillis(1);
+
+    private String mcpType = SSE_TYPE;
+
+    private StreamableProperties streamableProperties;
+
+    private SseServerProperties sseServerProperties;
+
+    public MCPProperties() {}
+
+    public boolean isSseType() {
+        return mcpType.equals(SSE_TYPE);
+    }
+
+    public List<String> getEndpoints() {
+        List<String> result = new ArrayList<>();
+        if (isSseType()) {
+            result.add(sseServerProperties.sseEndpoint);
+            result.add(sseServerProperties.messageEndpoint);
+        } else {
+            result.add(streamableProperties.mcpEndPoint);
+        }
+        return result;
+    }
+
+    public Long getQueryDuration() {
+        return queryDuration;
+    }
+
+    public static class StreamableProperties {
+        private final String mcpEndPoint;

Review Comment:
   The naming convention 'mcpEndPoint' uses inconsistent capitalization - 
'Point' should be 'point' (camelCase). For consistency with Java naming 
conventions, this should be 'mcpEndpoint'.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to