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]