This is an automated email from the ASF dual-hosted git repository.

jianbin pushed a commit to branch 2.x
in repository https://gitbox.apache.org/repos/asf/incubator-seata.git


The following commit(s) were added to refs/heads/2.x by this push:
     new ece45acad1 feature: add MCP custom configuration and authentication 
code (#7876)
ece45acad1 is described below

commit ece45acad1de73e9091914fec00fe43f164c52dd
Author: 徐博 洪 <[email protected]>
AuthorDate: Tue Dec 23 15:54:19 2025 +0800

    feature: add MCP custom configuration and authentication code (#7876)
---
 changes/en-us/2.x.md                               |   1 +
 changes/zh-cn/2.x.md                               |   1 +
 .../seata/console/config/WebSecurityConfig.java    |  33 ++++++-
 .../apache/seata/mcp/core/props/MCPProperties.java | 109 +++++++++++++++++++++
 namingserver/src/main/resources/application.yml    |  15 +++
 5 files changed, 154 insertions(+), 5 deletions(-)

diff --git a/changes/en-us/2.x.md b/changes/en-us/2.x.md
index 2bf4c7db59..44dcd804df 100644
--- a/changes/en-us/2.x.md
+++ b/changes/en-us/2.x.md
@@ -34,6 +34,7 @@ Add changes here for all PR submitted to the 2.x branch.
 - [[#7826](https://github.com/apache/incubator-seata/pull/7826)] Support 
HTTP/2 response handling for the Watch API in Server Raft mode
 - [[#7870](https://github.com/apache/incubator-seata/pull/7870)] upgrade the 
namingserver and console modules to JDK 25 and SpringBoot 3.5, and add the 
spring-ai dependency in the console module.
 - [[#7872](https://github.com/apache/incubator-seata/pull/7872)] Automatically 
calculate the values for JVM parameters
+- [[#7876](https://github.com/apache/incubator-seata/pull/7876)] feature: add 
MCP custom configuration and authentication code
 - [[#7878](https://github.com/apache/incubator-seata/pull/7878)] console 
supports creation and modification of transaction groups for Raft clusters
 
 
diff --git a/changes/zh-cn/2.x.md b/changes/zh-cn/2.x.md
index ced6b7e49d..e97981cb84 100644
--- a/changes/zh-cn/2.x.md
+++ b/changes/zh-cn/2.x.md
@@ -34,6 +34,7 @@
 - [[#7826](https://github.com/apache/incubator-seata/pull/7826)] 在 Server Raft 
模式下,为 Watch API 提供对 HTTP/2 响应处理的支持
 - [[#7870](https://github.com/apache/incubator-seata/pull/7870)] 
将namingserver和console模块升级到JDK 25和SpringBoot 3.5, 并在console模块中添加spring-ai依赖。
 - [[#7872](https://github.com/apache/incubator-seata/pull/7872)] 根据当前内存值自动计算 
JVM 参数
+- [[#7876](https://github.com/apache/incubator-seata/pull/7876)] feature: 
添加MCP服务自定义配置属性和鉴权功能
 - [[#7878](https://github.com/apache/incubator-seata/pull/7878)] 
控制台支持raft集群模式的事务分组管理
 
 
diff --git 
a/console/src/main/java/org/apache/seata/console/config/WebSecurityConfig.java 
b/console/src/main/java/org/apache/seata/console/config/WebSecurityConfig.java
index 410ba91a23..387a846550 100644
--- 
a/console/src/main/java/org/apache/seata/console/config/WebSecurityConfig.java
+++ 
b/console/src/main/java/org/apache/seata/console/config/WebSecurityConfig.java
@@ -21,10 +21,11 @@ import 
org.apache.seata.console.filter.JwtAuthenticationTokenFilter;
 import org.apache.seata.console.security.CustomUserDetailsServiceImpl;
 import org.apache.seata.console.security.JwtAuthenticationEntryPoint;
 import org.apache.seata.console.utils.JwtTokenUtils;
+import org.apache.seata.mcp.core.props.MCPProperties;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
-import org.springframework.core.env.Environment;
 import org.springframework.security.authentication.AuthenticationManager;
 import org.springframework.security.authentication.ProviderManager;
 import 
org.springframework.security.authentication.dao.DaoAuthenticationProvider;
@@ -42,6 +43,7 @@ import 
org.springframework.security.web.util.matcher.AntPathRequestMatcher;
 import org.springframework.security.web.util.matcher.RequestMatcher;
 
 import java.util.Arrays;
+import java.util.List;
 
 /**
  * Spring security config
@@ -82,7 +84,13 @@ public class WebSecurityConfig {
     private JwtTokenUtils tokenProvider;
 
     @Autowired
-    private Environment env;
+    private MCPProperties mcpProperties;
+
+    @Value("${seata.security.ignore.urls:/**}")
+    String ignoreURLs;
+
+    @Value("${seata.security.csrf-ignore-urls:/**}")
+    String csrfIgnoreUrls;
 
     @Bean
     public PasswordEncoder passwordEncoder() {
@@ -98,7 +106,15 @@ public class WebSecurityConfig {
 
     @Bean
     public WebSecurityCustomizer webSecurityCustomizer() {
-        RequestMatcher[] ignoredMatchers = 
buildAntMatchers(env.getProperty("seata.security.ignore.urls", "/**"));
+        StringBuilder ignoreURLsBuilder = new StringBuilder(ignoreURLs);
+        if (!mcpProperties.isEnableAuth()) {
+            List<String> mcpEndpoints = mcpProperties.getEndpoints();
+            for (String endpoint : mcpEndpoints) {
+                ignoreURLsBuilder.append(",").append(endpoint);
+            }
+        }
+        RequestMatcher[] ignoredMatchers =
+                buildAntMatchers(ignoreURLsBuilder.toString().trim());
         return web -> {
             if (ignoredMatchers.length > 0) {
                 web.ignoring().requestMatchers(ignoredMatchers);
@@ -109,8 +125,15 @@ public class WebSecurityConfig {
     @Bean
     public SecurityFilterChain securityFilterChain(HttpSecurity http, 
AuthenticationManager authenticationManager)
             throws Exception {
-        RequestMatcher[] csrfIgnored = 
buildAntMatchers(env.getProperty("seata.security.csrf-ignore-urls"));
-
+        StringBuilder csrfIgnoreUrlsBuilder = new 
StringBuilder(csrfIgnoreUrls);
+        if (mcpProperties.isEnableAuth()) {
+            List<String> mcpEndpoints = mcpProperties.getEndpoints();
+            for (String endpoint : mcpEndpoints) {
+                csrfIgnoreUrlsBuilder.append(",").append(endpoint);
+            }
+        }
+        RequestMatcher[] csrfIgnored =
+                buildAntMatchers(csrfIgnoreUrlsBuilder.toString().trim());
         http.authenticationManager(authenticationManager)
                 .authorizeHttpRequests(authz -> 
authz.anyRequest().authenticated())
                 .exceptionHandling(exception -> 
exception.authenticationEntryPoint(unauthorizedHandler))
diff --git 
a/console/src/main/java/org/apache/seata/mcp/core/props/MCPProperties.java 
b/console/src/main/java/org/apache/seata/mcp/core/props/MCPProperties.java
new file mode 100644
index 0000000000..25cd1134ca
--- /dev/null
+++ b/console/src/main/java/org/apache/seata/mcp/core/props/MCPProperties.java
@@ -0,0 +1,109 @@
+/*
+ * 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.Nullable;
+import jakarta.annotation.PostConstruct;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import 
org.springframework.ai.mcp.server.common.autoconfigure.properties.McpServerProperties;
+import 
org.springframework.ai.mcp.server.common.autoconfigure.properties.McpServerSseProperties;
+import 
org.springframework.ai.mcp.server.common.autoconfigure.properties.McpServerStreamableHttpProperties;
+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.Collections;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+@Component
+public class MCPProperties {
+
+    private final Environment env;
+
+    private boolean enableAuth = true;
+
+    private Long queryDuration = TimeUnit.DAYS.toMillis(1);
+
+    private final McpServerProperties mcpServerProperties;
+
+    private final McpServerSseProperties mcpServerSseProperties;
+
+    private final McpServerStreamableHttpProperties 
mcpServerStreamableHttpProperties;
+
+    private final List<String> endpoints = new ArrayList<>();
+
+    private final Logger logger = LoggerFactory.getLogger(MCPProperties.class);
+
+    @Autowired
+    public MCPProperties(
+            @Nullable McpServerProperties mcpServerProperties,
+            Environment env,
+            @Nullable McpServerSseProperties serverSseProperties,
+            @Nullable McpServerStreamableHttpProperties 
serverStreamableHttpProperties) {
+        this.mcpServerProperties = mcpServerProperties;
+        this.env = env;
+        this.mcpServerSseProperties = serverSseProperties;
+        this.mcpServerStreamableHttpProperties = 
serverStreamableHttpProperties;
+    }
+
+    public List<String> getEndpoints() {
+        return Collections.unmodifiableList(endpoints);
+    }
+
+    public Long getQueryDuration() {
+        return queryDuration;
+    }
+
+    @PostConstruct
+    public void init() {
+        String maxQueryDurationStr = 
env.getProperty("seata.mcp.query.max-query-duration", "86400000");
+        try {
+            queryDuration = Long.parseLong(maxQueryDurationStr);
+        } catch (NumberFormatException ex) {
+            queryDuration = TimeUnit.DAYS.toMillis(1);
+        }
+        enableAuth = 
Boolean.parseBoolean(env.getProperty("seata.mcp.auth.enabled", "true"));
+
+        if (!enableAuth) {
+            logger.warn(
+                    "MCP server authentication is disabled. This creates a 
security risk. It is strongly recommended to enable authentication by setting 
seata.mcp.auth.enabled=true");
+        }
+
+        if (mcpServerProperties != null) {
+            McpServerProperties.ServerProtocol protocol = 
mcpServerProperties.getProtocol();
+            if (protocol == McpServerProperties.ServerProtocol.SSE && 
mcpServerSseProperties != null) {
+                endpoints.add(mcpServerSseProperties.getSseEndpoint());
+                endpoints.add(mcpServerSseProperties.getSseMessageEndpoint());
+            } else if (protocol == 
McpServerProperties.ServerProtocol.STREAMABLE
+                    && mcpServerStreamableHttpProperties != null) {
+                
endpoints.add(mcpServerStreamableHttpProperties.getMcpEndpoint());
+            } else {
+                throw new IllegalStateException(
+                        "MCP server properties not properly configured or 
unsupported protocol");
+            }
+        } else {
+            logger.warn("MCP server properties not properly configured");
+        }
+    }
+
+    public boolean isEnableAuth() {
+        return enableAuth;
+    }
+}
diff --git a/namingserver/src/main/resources/application.yml 
b/namingserver/src/main/resources/application.yml
index ea243e2401..ba10362f93 100644
--- a/namingserver/src/main/resources/application.yml
+++ b/namingserver/src/main/resources/application.yml
@@ -23,6 +23,14 @@ spring:
   mvc:
     pathmatch:
       matching-strategy: ant_path_matcher
+  ai:
+    mcp:
+      server:
+        protocol: streamable
+        streamable-http:
+          mcp-endpoint: /mcp
+        name: mcp-server
+        version: 1.0.0
   application:
     name: seata-namingserver
 logging:
@@ -39,3 +47,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:
+    # Maximum query time interval, The unit is milliseconds, Default one day
+    query:
+      max-query-duration: 86400000
+    auth:
+      enabled: true
\ No newline at end of file


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

Reply via email to