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 4435b8fe68 feature: add global and branch session and lock management 
MCP tools (#7893)
4435b8fe68 is described below

commit 4435b8fe6873e04ba8fade53a68e32436ea8c5dc
Author: 徐博 洪 <[email protected]>
AuthorDate: Sun Dec 28 13:45:11 2025 +0800

    feature: add global and branch session and lock management MCP tools (#7893)
---
 changes/en-us/2.x.md                               |   1 +
 changes/zh-cn/2.x.md                               |   1 +
 .../seata/common/NamingServerLocalMarker.java      |  19 ++
 .../core/constants/ServerTableColumnsName.java     |   0
 .../org/apache/seata/core/model/GlobalStatus.java  |   0
 .../console/entity/param/GlobalLockParam.java      |   0
 .../console/entity/param/GlobalSessionParam.java   |   0
 .../server/console/entity/vo/BranchSessionVO.java  |   0
 .../server/console/entity/vo/GlobalSessionVO.java  |   0
 .../seata/console/config/WebSecurityConfig.java    |  18 +-
 .../filter/JwtAuthenticationTokenFilter.java       |   6 +
 .../apache/seata/console/utils/JwtTokenUtils.java  |   2 +-
 .../core/config/TimestampToStringDeserializer.java |  39 ++++
 .../seata/mcp/core/constant/RPCConstant.java       |  30 +++
 .../apache/seata/mcp/core/props/MCPProperties.java |  12 -
 .../seata/mcp/core/props/NameSpaceDetail.java      |  56 +++++
 .../mcp/core/props/NamingServerProperties.java     |  52 +++++
 .../org/apache/seata/mcp/core/utils/DateUtils.java |  80 +++++++
 .../org/apache/seata/mcp/core/utils/UrlUtils.java  |  88 ++++++++
 .../mcp/entity/dto/McpGlobalLockParamDto.java      |  97 +++++---
 .../mcp/entity/dto/McpGlobalSessionParamDto.java   | 142 ++++++++++++
 .../param/McpGlobalAbnormalSessionParam.java       |  69 ++++++
 .../mcp/entity/param/McpGlobalLockDeleteParam.java |  53 +----
 .../seata/mcp/entity/param/McpGlobalLockParam.java |  43 ++++
 .../mcp/entity/param/McpGlobalSessionParam.java    |  48 ++++
 .../seata/mcp/entity/vo/McpBranchSessionVO.java    |  53 +++++
 .../seata/mcp/entity/vo/McpGlobalLockVO.java       | 121 +++++-----
 .../seata/mcp/entity/vo/McpGlobalSessionVO.java    |  76 +++++++
 .../seata/mcp/exception/ServiceCallException.java  |  54 +++++
 .../seata/mcp/service/ConsoleApiService.java       |  48 ++++
 .../seata/mcp/service/ModifyConfirmService.java    |  26 +++
 .../mcp/service/impl/ConsoleRemoteServiceImpl.java | 244 +++++++++++++++++++++
 .../mcp/service/impl/ModifyConfirmServiceImpl.java |  73 ++++++
 .../apache/seata/mcp/tools/BranchSessionTools.java | 105 +++++++++
 .../apache/seata/mcp/tools/GlobalLockTools.java    | 141 ++++++++++++
 .../apache/seata/mcp/tools/GlobalSessionTools.java | 231 +++++++++++++++++++
 .../apache/seata/mcp/tools/ModifyConfirmTools.java |  59 +++++
 .../org/apache/seata/mcp/tools/NameSpaceTools.java |  58 +++++
 .../service/ConsoleLocalServiceImpl.java           | 169 ++++++++++++++
 .../service/NamingServerLocalMarkerImpl.java       |  23 ++
 namingserver/src/main/resources/application.yml    |   9 +-
 41 files changed, 2187 insertions(+), 159 deletions(-)

diff --git a/changes/en-us/2.x.md b/changes/en-us/2.x.md
index 99e2dcbe56..f40ffda695 100644
--- a/changes/en-us/2.x.md
+++ b/changes/en-us/2.x.md
@@ -36,6 +36,7 @@ Add changes here for all PR submitted to the 2.x branch.
 - [[#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
+- [[#7893](https://github.com/apache/incubator-seata/pull/7893)] add global 
and branch session and lock management MCP tools
 
 
 ### bugfix:
diff --git a/changes/zh-cn/2.x.md b/changes/zh-cn/2.x.md
index 5b97efd42b..d9986ebc21 100644
--- a/changes/zh-cn/2.x.md
+++ b/changes/zh-cn/2.x.md
@@ -36,6 +36,7 @@
 - [[#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集群模式的事务分组管理
+- [[#7893](https://github.com/apache/incubator-seata/pull/7893)] 
添加全局和分支事务及锁管理MCP工具
 
 
 ### bugfix:
diff --git 
a/common/src/main/java/org/apache/seata/common/NamingServerLocalMarker.java 
b/common/src/main/java/org/apache/seata/common/NamingServerLocalMarker.java
new file mode 100644
index 0000000000..2724008df9
--- /dev/null
+++ b/common/src/main/java/org/apache/seata/common/NamingServerLocalMarker.java
@@ -0,0 +1,19 @@
+/*
+ * 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.common;
+
+public interface NamingServerLocalMarker {}
diff --git 
a/core/src/main/java/org/apache/seata/core/constants/ServerTableColumnsName.java
 
b/common/src/main/java/org/apache/seata/core/constants/ServerTableColumnsName.java
similarity index 100%
rename from 
core/src/main/java/org/apache/seata/core/constants/ServerTableColumnsName.java
rename to 
common/src/main/java/org/apache/seata/core/constants/ServerTableColumnsName.java
diff --git a/core/src/main/java/org/apache/seata/core/model/GlobalStatus.java 
b/common/src/main/java/org/apache/seata/core/model/GlobalStatus.java
similarity index 100%
rename from core/src/main/java/org/apache/seata/core/model/GlobalStatus.java
rename to common/src/main/java/org/apache/seata/core/model/GlobalStatus.java
diff --git 
a/server/src/main/java/org/apache/seata/server/console/entity/param/GlobalLockParam.java
 
b/common/src/main/java/org/apache/seata/server/console/entity/param/GlobalLockParam.java
similarity index 100%
copy from 
server/src/main/java/org/apache/seata/server/console/entity/param/GlobalLockParam.java
copy to 
common/src/main/java/org/apache/seata/server/console/entity/param/GlobalLockParam.java
diff --git 
a/server/src/main/java/org/apache/seata/server/console/entity/param/GlobalSessionParam.java
 
b/common/src/main/java/org/apache/seata/server/console/entity/param/GlobalSessionParam.java
similarity index 100%
rename from 
server/src/main/java/org/apache/seata/server/console/entity/param/GlobalSessionParam.java
rename to 
common/src/main/java/org/apache/seata/server/console/entity/param/GlobalSessionParam.java
diff --git 
a/server/src/main/java/org/apache/seata/server/console/entity/vo/BranchSessionVO.java
 
b/common/src/main/java/org/apache/seata/server/console/entity/vo/BranchSessionVO.java
similarity index 100%
rename from 
server/src/main/java/org/apache/seata/server/console/entity/vo/BranchSessionVO.java
rename to 
common/src/main/java/org/apache/seata/server/console/entity/vo/BranchSessionVO.java
diff --git 
a/server/src/main/java/org/apache/seata/server/console/entity/vo/GlobalSessionVO.java
 
b/common/src/main/java/org/apache/seata/server/console/entity/vo/GlobalSessionVO.java
similarity index 100%
rename from 
server/src/main/java/org/apache/seata/server/console/entity/vo/GlobalSessionVO.java
rename to 
common/src/main/java/org/apache/seata/server/console/entity/vo/GlobalSessionVO.java
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 387a846550..dc773eeabb 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
@@ -106,15 +106,7 @@ public class WebSecurityConfig {
 
     @Bean
     public WebSecurityCustomizer webSecurityCustomizer() {
-        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());
+        RequestMatcher[] ignoredMatchers = buildAntMatchers(ignoreURLs.trim());
         return web -> {
             if (ignoredMatchers.length > 0) {
                 web.ignoring().requestMatchers(ignoredMatchers);
@@ -126,11 +118,9 @@ public class WebSecurityConfig {
     public SecurityFilterChain securityFilterChain(HttpSecurity http, 
AuthenticationManager authenticationManager)
             throws Exception {
         StringBuilder csrfIgnoreUrlsBuilder = new 
StringBuilder(csrfIgnoreUrls);
-        if (mcpProperties.isEnableAuth()) {
-            List<String> mcpEndpoints = mcpProperties.getEndpoints();
-            for (String endpoint : mcpEndpoints) {
-                csrfIgnoreUrlsBuilder.append(",").append(endpoint);
-            }
+        List<String> mcpEndpoints = mcpProperties.getEndpoints();
+        for (String endpoint : mcpEndpoints) {
+            csrfIgnoreUrlsBuilder.append(",").append(endpoint);
         }
         RequestMatcher[] csrfIgnored =
                 buildAntMatchers(csrfIgnoreUrlsBuilder.toString().trim());
diff --git 
a/console/src/main/java/org/apache/seata/console/filter/JwtAuthenticationTokenFilter.java
 
b/console/src/main/java/org/apache/seata/console/filter/JwtAuthenticationTokenFilter.java
index 2994c9a473..74c0607f5d 100644
--- 
a/console/src/main/java/org/apache/seata/console/filter/JwtAuthenticationTokenFilter.java
+++ 
b/console/src/main/java/org/apache/seata/console/filter/JwtAuthenticationTokenFilter.java
@@ -69,6 +69,12 @@ public class JwtAuthenticationTokenFilter extends 
OncePerRequestFilter {
         chain.doFilter(request, response);
     }
 
+    @Override
+    protected boolean shouldNotFilterAsyncDispatch() {
+        // allow this filter to run during async dispatch so JWT is applied 
for async requests
+        return false;
+    }
+
     /**
      * Get token from header
      */
diff --git 
a/console/src/main/java/org/apache/seata/console/utils/JwtTokenUtils.java 
b/console/src/main/java/org/apache/seata/console/utils/JwtTokenUtils.java
index 803da87937..e78ce33c5a 100644
--- a/console/src/main/java/org/apache/seata/console/utils/JwtTokenUtils.java
+++ b/console/src/main/java/org/apache/seata/console/utils/JwtTokenUtils.java
@@ -109,7 +109,7 @@ public class JwtTokenUtils {
                 AuthorityUtils.commaSeparatedStringToAuthorityList((String) 
claims.get(AUTHORITIES_KEY));
 
         User principal = new User(claims.getSubject(), "", authorities);
-        return new UsernamePasswordAuthenticationToken(principal, "", 
authorities);
+        return new UsernamePasswordAuthenticationToken(principal, token, 
authorities);
     }
 
     /**
diff --git 
a/console/src/main/java/org/apache/seata/mcp/core/config/TimestampToStringDeserializer.java
 
b/console/src/main/java/org/apache/seata/mcp/core/config/TimestampToStringDeserializer.java
new file mode 100644
index 0000000000..c53baf2af0
--- /dev/null
+++ 
b/console/src/main/java/org/apache/seata/mcp/core/config/TimestampToStringDeserializer.java
@@ -0,0 +1,39 @@
+/*
+ * 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.config;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+
+import java.io.IOException;
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
+
+public class TimestampToStringDeserializer extends JsonDeserializer<String> {
+    private static final DateTimeFormatter FORMATTER = 
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+
+    @Override
+    public String deserialize(JsonParser p, DeserializationContext cxt) throws 
IOException {
+        long timestamp = p.getLongValue();
+        LocalDateTime dateTime =
+                
Instant.ofEpochMilli(timestamp).atZone(ZoneId.systemDefault()).toLocalDateTime();
+        return dateTime.format(FORMATTER);
+    }
+}
diff --git 
a/console/src/main/java/org/apache/seata/mcp/core/constant/RPCConstant.java 
b/console/src/main/java/org/apache/seata/mcp/core/constant/RPCConstant.java
new file mode 100644
index 0000000000..650e59ec4e
--- /dev/null
+++ b/console/src/main/java/org/apache/seata/mcp/core/constant/RPCConstant.java
@@ -0,0 +1,30 @@
+/*
+ * 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.constant;
+
+public class RPCConstant {
+
+    public static final String GLOBAL_SESSION_BASE_URL = 
"/api/v1/console/globalSession";
+
+    public static final String BRANCH_SESSION_BASE_URL = 
"/api/v1/console/branchSession";
+
+    public static final String GLOBAL_LOCK_BASE_URL = 
"/api/v1/console/globalLock";
+
+    public static final String SERVER_LOG_BASE_URL = 
"/api/v1/console/serverLog";
+
+    public static final String GET_NAMESPACE_PATH = "/api/v1/naming/namespace";
+}
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
index 25cd1134ca..50c6cbf964 100644
--- 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
@@ -37,8 +37,6 @@ public class MCPProperties {
 
     private final Environment env;
 
-    private boolean enableAuth = true;
-
     private Long queryDuration = TimeUnit.DAYS.toMillis(1);
 
     private final McpServerProperties mcpServerProperties;
@@ -79,12 +77,6 @@ public class MCPProperties {
         } 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();
@@ -102,8 +94,4 @@ public class MCPProperties {
             logger.warn("MCP server properties not properly configured");
         }
     }
-
-    public boolean isEnableAuth() {
-        return enableAuth;
-    }
 }
diff --git 
a/console/src/main/java/org/apache/seata/mcp/core/props/NameSpaceDetail.java 
b/console/src/main/java/org/apache/seata/mcp/core/props/NameSpaceDetail.java
new file mode 100644
index 0000000000..4b51222ecc
--- /dev/null
+++ b/console/src/main/java/org/apache/seata/mcp/core/props/NameSpaceDetail.java
@@ -0,0 +1,56 @@
+/*
+ * 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 org.apache.seata.common.util.StringUtils;
+
+public class NameSpaceDetail {
+    private String namespace;
+    private String cluster;
+    private String vGroup;
+
+    public String getNamespace() {
+        return namespace;
+    }
+
+    public void setNamespace(String namespace) {
+        this.namespace = namespace;
+    }
+
+    public String getCluster() {
+        return cluster;
+    }
+
+    public void setCluster(String cluster) {
+        this.cluster = cluster;
+    }
+
+    public String getvGroup() {
+        return vGroup;
+    }
+
+    public void setvGroup(String vGroup) {
+        this.vGroup = vGroup;
+    }
+
+    public boolean isValid() {
+        if (StringUtils.isBlank(namespace)) {
+            return false;
+        }
+        return !StringUtils.isBlank(vGroup) || !StringUtils.isBlank(cluster);
+    }
+}
diff --git 
a/console/src/main/java/org/apache/seata/mcp/core/props/NamingServerProperties.java
 
b/console/src/main/java/org/apache/seata/mcp/core/props/NamingServerProperties.java
new file mode 100644
index 0000000000..6654f6818c
--- /dev/null
+++ 
b/console/src/main/java/org/apache/seata/mcp/core/props/NamingServerProperties.java
@@ -0,0 +1,52 @@
+/*
+ * 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 org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.ThreadLocalRandom;
+
+@ConfigurationProperties(prefix = "console.namingserver")
+@Component
+public class NamingServerProperties {
+
+    /**
+     * http, https
+     */
+    private String protocol = "http";
+
+    private List<String> addr = Collections.singletonList("127.0.0.1:8081");
+
+    public String getNamingServerUrl() {
+        if (addr == null || addr.isEmpty()) {
+            throw new IllegalStateException("No naming servers addr 
configured");
+        }
+        int index = ThreadLocalRandom.current().nextInt(addr.size());
+        return protocol + "://" + addr.get(index);
+    }
+
+    public void setAddr(List<String> addr) {
+        this.addr = addr;
+    }
+
+    public void setProtocol(String protocol) {
+        this.protocol = protocol;
+    }
+}
diff --git 
a/console/src/main/java/org/apache/seata/mcp/core/utils/DateUtils.java 
b/console/src/main/java/org/apache/seata/mcp/core/utils/DateUtils.java
new file mode 100644
index 0000000000..237ec494e8
--- /dev/null
+++ b/console/src/main/java/org/apache/seata/mcp/core/utils/DateUtils.java
@@ -0,0 +1,80 @@
+/*
+ * 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.utils;
+
+import java.time.DateTimeException;
+import java.time.Instant;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeParseException;
+import java.util.regex.Pattern;
+
+public class DateUtils {
+
+    public static final Long ONE_DAY_TIMESTAMP = 86400000L;
+
+    private static final Pattern DATE_PATTERN = 
Pattern.compile("^\\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$");
+
+    public static boolean isValidDate(String dateStr) {
+        return DATE_PATTERN.matcher(dateStr).matches();
+    }
+
+    public static long convertToTimestampFromDate(String dateStr) {
+        if (!isValidDate(dateStr)) {
+            throw new DateTimeException("The time format does not match 
yyyy-MM-dd");
+        }
+        LocalDate date = LocalDate.parse(dateStr);
+        ZonedDateTime zonedDateTime = 
date.atStartOfDay(ZoneId.systemDefault());
+        return zonedDateTime.toInstant().toEpochMilli();
+    }
+
+    public static long convertToTimeStampFromDateTime(String dateTimeStr) {
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd 
HH:mm:ss");
+
+        try {
+            LocalDateTime dateTime = LocalDateTime.parse(dateTimeStr, 
formatter);
+            return 
dateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
+        } catch (DateTimeParseException e) {
+            throw new DateTimeException("The time format does not match 
yyyy-MM-dd HH:mm:ss", e);
+        }
+    }
+
+    public static String convertToDateTimeFromTimestamp(Long timestamp) {
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd 
HH:mm:ss");
+        LocalDateTime dateTime;
+        try {
+            dateTime = Instant.ofEpochMilli(timestamp)
+                    .atZone(ZoneId.systemDefault())
+                    .toLocalDateTime();
+        } catch (DateTimeException | ArithmeticException e) {
+            return "Parse Failed, please check that the timestamp is correct";
+        }
+        return dateTime.format(formatter);
+    }
+
+    public static boolean judgeExceedTimeDuration(Long startTime, Long 
endTime, Long maxDuration) {
+        if (endTime < startTime) throw new IllegalArgumentException("endTime 
must not be earlier than startTime");
+        return endTime - startTime > maxDuration;
+    }
+
+    public static Long convertToHourFromTimeStamp(Long timestamp) {
+        return timestamp / (60 * 60 * 1000);
+    }
+}
diff --git 
a/console/src/main/java/org/apache/seata/mcp/core/utils/UrlUtils.java 
b/console/src/main/java/org/apache/seata/mcp/core/utils/UrlUtils.java
new file mode 100644
index 0000000000..44345f9387
--- /dev/null
+++ b/console/src/main/java/org/apache/seata/mcp/core/utils/UrlUtils.java
@@ -0,0 +1,88 @@
+/*
+ * 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.utils;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.util.UriComponentsBuilder;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+public class UrlUtils {
+
+    private static final Logger logger = 
LoggerFactory.getLogger(UrlUtils.class);
+
+    public static String buildUrl(
+            String baseUrl, String path, Map<String, String> 
queryStringParams, Map<String, Object> queryObjectParams) {
+
+        UriComponentsBuilder builder =
+                UriComponentsBuilder.fromUriString(baseUrl).path(path);
+
+        if (queryStringParams != null && !queryStringParams.isEmpty()) {
+            for (Map.Entry<String, String> entry : 
queryStringParams.entrySet()) {
+                builder.queryParam(entry.getKey(), entry.getValue());
+            }
+        }
+
+        if (queryObjectParams != null && !queryObjectParams.isEmpty()) {
+            for (Map.Entry<String, Object> entry : 
queryObjectParams.entrySet()) {
+                if (entry.getValue() instanceof Iterable) {
+                    for (Object value : (Iterable<?>) entry.getValue()) {
+                        builder.queryParam(entry.getKey(), value);
+                    }
+                } else if (entry.getValue() != null
+                        && entry.getValue().getClass().isArray()) {
+                    Object[] array = (Object[]) entry.getValue();
+                    for (Object value : array) {
+                        builder.queryParam(entry.getKey(), value);
+                    }
+                } else {
+                    builder.queryParam(entry.getKey(), entry.getValue());
+                }
+            }
+        }
+
+        return builder.build().toUriString();
+    }
+
+    public static Map<String, Object> objectToQueryParamMap(Object obj, 
ObjectMapper objectMapper) {
+        if (obj == null) {
+            return Collections.emptyMap();
+        }
+        if (obj instanceof Map) {
+            Map<?, ?> map = (Map<?, ?>) obj;
+            Map<String, Object> result = new HashMap<>(map.size());
+            map.forEach((k, v) -> {
+                if (k != null && v != null) {
+                    result.put(k.toString(), v);
+                }
+            });
+            return result;
+        }
+
+        try {
+            return objectMapper.convertValue(obj, new 
TypeReference<Map<String, Object>>() {});
+        } catch (IllegalArgumentException e) {
+            logger.warn("Failed to convert object to map: {}", e.getMessage());
+            return Collections.emptyMap();
+        }
+    }
+}
diff --git 
a/server/src/main/java/org/apache/seata/server/console/entity/param/GlobalLockParam.java
 
b/console/src/main/java/org/apache/seata/mcp/entity/dto/McpGlobalLockParamDto.java
similarity index 54%
copy from 
server/src/main/java/org/apache/seata/server/console/entity/param/GlobalLockParam.java
copy to 
console/src/main/java/org/apache/seata/mcp/entity/dto/McpGlobalLockParamDto.java
index ec13f0b30e..56982afec6 100644
--- 
a/server/src/main/java/org/apache/seata/server/console/entity/param/GlobalLockParam.java
+++ 
b/console/src/main/java/org/apache/seata/mcp/entity/dto/McpGlobalLockParamDto.java
@@ -14,44 +14,82 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.seata.server.console.entity.param;
+package org.apache.seata.mcp.entity.dto;
 
-import org.apache.seata.common.result.BaseParam;
+import org.springaicommunity.mcp.annotation.McpToolParam;
 
 import java.io.Serializable;
 
-/**
- * Global lock param
- */
-public class GlobalLockParam extends BaseParam implements Serializable {
+public class McpGlobalLockParamDto implements Serializable {
 
     private static final long serialVersionUID = 615412528070131284L;
 
-    /**
-     * the xid
-     */
+    @McpToolParam(description = "Global transaction ID", required = false)
     private String xid;
-    /**
-     * the table name
-     */
+
+    @McpToolParam(description = "The table name", required = false)
     private String tableName;
-    /**
-     * the transaction id
-     */
+
+    @McpToolParam(description = "The transaction id", required = false)
     private String transactionId;
-    /**
-     * the branch id
-     */
+
+    @McpToolParam(description = "The branch id", required = false)
     private String branchId;
-    /**
-     * the primary Key
-     */
+
+    @McpToolParam(description = "the primary Key", required = false)
     private String pk;
-    /**
-     * the resourceId
-     */
+
+    @McpToolParam(description = "resourceId", required = false)
     private String resourceId;
 
+    @McpToolParam(description = "Page number")
+    private int pageNum;
+
+    @McpToolParam(description = "Page size")
+    private int pageSize;
+
+    @McpToolParam(
+            description = "Start time, The global lock create time is after 
this time (yyyy-MM-dd HH:mm:ss)",
+            required = false)
+    private String timeStart;
+
+    @McpToolParam(
+            description = "End time, The global lock create time is before 
this time (yyyy-MM-dd HH:mm:ss)",
+            required = false)
+    private String timeEnd;
+
+    public int getPageNum() {
+        return pageNum;
+    }
+
+    public void setPageNum(int pageNum) {
+        this.pageNum = pageNum;
+    }
+
+    public int getPageSize() {
+        return pageSize;
+    }
+
+    public void setPageSize(int pageSize) {
+        this.pageSize = pageSize;
+    }
+
+    public String getTimeStart() {
+        return timeStart;
+    }
+
+    public void setTimeStart(String timeStart) {
+        this.timeStart = timeStart;
+    }
+
+    public String getTimeEnd() {
+        return timeEnd;
+    }
+
+    public void setTimeEnd(String timeEnd) {
+        this.timeEnd = timeEnd;
+    }
+
     public String getTransactionId() {
         return transactionId;
     }
@@ -99,15 +137,4 @@ public class GlobalLockParam extends BaseParam implements 
Serializable {
     public void setResourceId(String resourceId) {
         this.resourceId = resourceId;
     }
-
-    @Override
-    public String toString() {
-        return "GlobalLockParam{" + "xid='"
-                + xid + '\'' + ", tableName='"
-                + tableName + '\'' + ", transactionId='"
-                + transactionId + '\'' + ", branchId='"
-                + branchId + '\'' + ", pk='"
-                + pk + '\'' + ", resourceId='"
-                + resourceId + '\'' + '}';
-    }
 }
diff --git 
a/console/src/main/java/org/apache/seata/mcp/entity/dto/McpGlobalSessionParamDto.java
 
b/console/src/main/java/org/apache/seata/mcp/entity/dto/McpGlobalSessionParamDto.java
new file mode 100644
index 0000000000..c7f4c95499
--- /dev/null
+++ 
b/console/src/main/java/org/apache/seata/mcp/entity/dto/McpGlobalSessionParamDto.java
@@ -0,0 +1,142 @@
+/*
+ * 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.entity.dto;
+
+import org.apache.seata.common.util.StringUtils;
+import org.apache.seata.mcp.entity.param.McpGlobalAbnormalSessionParam;
+import org.springaicommunity.mcp.annotation.McpToolParam;
+
+import java.io.Serializable;
+
+public class McpGlobalSessionParamDto implements Serializable {
+
+    private static final long serialVersionUID = 115488252809011284L;
+
+    @McpToolParam(description = "Global transaction ID", required = false)
+    private String xid;
+
+    @McpToolParam(description = "applicationId", required = false)
+    private String applicationId;
+
+    @McpToolParam(description = "The valid values are defined in prompts", 
required = false)
+    private Integer status;
+
+    @McpToolParam(description = "The name of the transaction", required = 
false)
+    private String transactionName;
+
+    @McpToolParam(description = "Whether or not it contains branch transaction 
information", required = false)
+    private boolean withBranch;
+
+    @McpToolParam(description = "Page number")
+    private int pageNum;
+
+    @McpToolParam(description = "Page size")
+    private int pageSize;
+
+    @McpToolParam(description = "The transaction start time is after this time 
(yyyy-MM-dd HH:mm:ss)", required = false)
+    private String timeStart;
+
+    @McpToolParam(
+            description = "The transaction start time is before this time 
(yyyy-MM-dd HH:mm:ss)",
+            required = false)
+    private String timeEnd;
+
+    public int getPageNum() {
+        return pageNum;
+    }
+
+    public void setPageNum(int pageNum) {
+        this.pageNum = pageNum;
+    }
+
+    public int getPageSize() {
+        return pageSize;
+    }
+
+    public void setPageSize(int pageSize) {
+        this.pageSize = pageSize;
+    }
+
+    public String getTimeStart() {
+        return timeStart;
+    }
+
+    public void setTimeStart(String timeStart) {
+        this.timeStart = timeStart;
+    }
+
+    public String getTimeEnd() {
+        return timeEnd;
+    }
+
+    public void setTimeEnd(String timeEnd) {
+        this.timeEnd = timeEnd;
+    }
+
+    public String getXid() {
+        return xid;
+    }
+
+    public void setXid(String xid) {
+        this.xid = xid;
+    }
+
+    public String getTransactionName() {
+        return transactionName;
+    }
+
+    public void setTransactionName(String transactionName) {
+        this.transactionName = transactionName;
+    }
+
+    public String getApplicationId() {
+        return applicationId;
+    }
+
+    public void setApplicationId(String applicationId) {
+        this.applicationId = applicationId;
+    }
+
+    public Integer getStatus() {
+        return status;
+    }
+
+    public void setStatus(Integer status) {
+        this.status = status;
+    }
+
+    public boolean isWithBranch() {
+        return withBranch;
+    }
+
+    public void setWithBranch(boolean withBranch) {
+        this.withBranch = withBranch;
+    }
+
+    public static McpGlobalSessionParamDto 
convertFromAbnormalParam(McpGlobalAbnormalSessionParam abParam) {
+        McpGlobalSessionParamDto param = new McpGlobalSessionParamDto();
+        if (StringUtils.isNotBlank(abParam.getTimeStart())) {
+            param.setTimeStart(abParam.getTimeStart());
+        }
+        if (StringUtils.isNotBlank(abParam.getTimeEnd())) {
+            param.setTimeEnd(abParam.getTimeEnd());
+        }
+        param.setWithBranch(abParam.isWithBranch());
+        param.setPageNum(abParam.getPageNum());
+        return param;
+    }
+}
diff --git 
a/console/src/main/java/org/apache/seata/mcp/entity/param/McpGlobalAbnormalSessionParam.java
 
b/console/src/main/java/org/apache/seata/mcp/entity/param/McpGlobalAbnormalSessionParam.java
new file mode 100644
index 0000000000..dc09b21a95
--- /dev/null
+++ 
b/console/src/main/java/org/apache/seata/mcp/entity/param/McpGlobalAbnormalSessionParam.java
@@ -0,0 +1,69 @@
+/*
+ * 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.entity.param;
+
+import org.springaicommunity.mcp.annotation.McpToolParam;
+
+public class McpGlobalAbnormalSessionParam {
+    @McpToolParam(
+            description = "Whether or not it contains branch transaction 
information, default is true",
+            required = false)
+    private boolean withBranch = true;
+
+    @McpToolParam(description = "The transaction start time is after this time 
(yyyy-MM-dd HH:mm:ss)", required = false)
+    private String timeStart;
+
+    @McpToolParam(
+            description = "The transaction start time is before this time 
(yyyy-MM-dd HH:mm:ss)",
+            required = false)
+    private String timeEnd;
+
+    @McpToolParam(description = "Page number")
+    private int pageNum;
+
+    public boolean isWithBranch() {
+        return withBranch;
+    }
+
+    public void setWithBranch(boolean withBranch) {
+        this.withBranch = withBranch;
+    }
+
+    public String getTimeStart() {
+        return timeStart;
+    }
+
+    public void setTimeStart(String timeStart) {
+        this.timeStart = timeStart;
+    }
+
+    public String getTimeEnd() {
+        return timeEnd;
+    }
+
+    public void setTimeEnd(String timeEnd) {
+        this.timeEnd = timeEnd;
+    }
+
+    public int getPageNum() {
+        return pageNum;
+    }
+
+    public void setPageNum(int pageNum) {
+        this.pageNum = pageNum;
+    }
+}
diff --git 
a/server/src/main/java/org/apache/seata/server/console/entity/param/GlobalLockParam.java
 
b/console/src/main/java/org/apache/seata/mcp/entity/param/McpGlobalLockDeleteParam.java
similarity index 64%
copy from 
server/src/main/java/org/apache/seata/server/console/entity/param/GlobalLockParam.java
copy to 
console/src/main/java/org/apache/seata/mcp/entity/param/McpGlobalLockDeleteParam.java
index ec13f0b30e..eb53a90d82 100644
--- 
a/server/src/main/java/org/apache/seata/server/console/entity/param/GlobalLockParam.java
+++ 
b/console/src/main/java/org/apache/seata/mcp/entity/param/McpGlobalLockDeleteParam.java
@@ -14,51 +14,33 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.seata.server.console.entity.param;
+package org.apache.seata.mcp.entity.param;
 
-import org.apache.seata.common.result.BaseParam;
+import org.springaicommunity.mcp.annotation.McpToolParam;
 
 import java.io.Serializable;
 
 /**
  * Global lock param
  */
-public class GlobalLockParam extends BaseParam implements Serializable {
+public class McpGlobalLockDeleteParam implements Serializable {
 
     private static final long serialVersionUID = 615412528070131284L;
 
-    /**
-     * the xid
-     */
+    @McpToolParam(description = "Global transaction id")
     private String xid;
-    /**
-     * the table name
-     */
+
+    @McpToolParam(description = "the table name")
     private String tableName;
-    /**
-     * the transaction id
-     */
-    private String transactionId;
-    /**
-     * the branch id
-     */
+
+    @McpToolParam(description = "the branch id")
     private String branchId;
-    /**
-     * the primary Key
-     */
-    private String pk;
-    /**
-     * the resourceId
-     */
-    private String resourceId;
 
-    public String getTransactionId() {
-        return transactionId;
-    }
+    @McpToolParam(description = "the primary Key")
+    private String pk;
 
-    public void setTransactionId(String transactionId) {
-        this.transactionId = transactionId;
-    }
+    @McpToolParam(description = "resourceId")
+    private String resourceId;
 
     public String getBranchId() {
         return branchId;
@@ -99,15 +81,4 @@ public class GlobalLockParam extends BaseParam implements 
Serializable {
     public void setResourceId(String resourceId) {
         this.resourceId = resourceId;
     }
-
-    @Override
-    public String toString() {
-        return "GlobalLockParam{" + "xid='"
-                + xid + '\'' + ", tableName='"
-                + tableName + '\'' + ", transactionId='"
-                + transactionId + '\'' + ", branchId='"
-                + branchId + '\'' + ", pk='"
-                + pk + '\'' + ", resourceId='"
-                + resourceId + '\'' + '}';
-    }
 }
diff --git 
a/console/src/main/java/org/apache/seata/mcp/entity/param/McpGlobalLockParam.java
 
b/console/src/main/java/org/apache/seata/mcp/entity/param/McpGlobalLockParam.java
new file mode 100644
index 0000000000..42be0cf67d
--- /dev/null
+++ 
b/console/src/main/java/org/apache/seata/mcp/entity/param/McpGlobalLockParam.java
@@ -0,0 +1,43 @@
+/*
+ * 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.entity.param;
+
+import org.apache.seata.common.util.PageUtil;
+import org.apache.seata.common.util.StringUtils;
+import org.apache.seata.mcp.core.utils.DateUtils;
+import org.apache.seata.mcp.entity.dto.McpGlobalLockParamDto;
+import org.apache.seata.server.console.entity.param.GlobalLockParam;
+import org.springframework.beans.BeanUtils;
+
+/**
+ * Global lock param
+ */
+public class McpGlobalLockParam extends GlobalLockParam {
+
+    public static McpGlobalLockParam convertFromParamDto(McpGlobalLockParamDto 
paramDto) {
+        PageUtil.checkParam(paramDto.getPageNum(), paramDto.getPageSize());
+        McpGlobalLockParam param = new McpGlobalLockParam();
+        BeanUtils.copyProperties(paramDto, param);
+        if (StringUtils.isNotBlank(paramDto.getTimeStart())) {
+            
param.setTimeStart(DateUtils.convertToTimeStampFromDateTime(paramDto.getTimeStart()));
+        }
+        if (StringUtils.isNotBlank(paramDto.getTimeEnd())) {
+            
param.setTimeEnd(DateUtils.convertToTimeStampFromDateTime(paramDto.getTimeEnd()));
+        }
+        return param;
+    }
+}
diff --git 
a/console/src/main/java/org/apache/seata/mcp/entity/param/McpGlobalSessionParam.java
 
b/console/src/main/java/org/apache/seata/mcp/entity/param/McpGlobalSessionParam.java
new file mode 100644
index 0000000000..8adaec20cb
--- /dev/null
+++ 
b/console/src/main/java/org/apache/seata/mcp/entity/param/McpGlobalSessionParam.java
@@ -0,0 +1,48 @@
+/*
+ * 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.entity.param;
+
+import org.apache.seata.common.util.PageUtil;
+import org.apache.seata.common.util.StringUtils;
+import org.apache.seata.mcp.core.utils.DateUtils;
+import org.apache.seata.mcp.entity.dto.McpGlobalSessionParamDto;
+import org.apache.seata.server.console.entity.param.GlobalSessionParam;
+
+/**
+ * Global session param
+ */
+public class McpGlobalSessionParam extends GlobalSessionParam {
+
+    public static McpGlobalSessionParam 
convertFromDtoParam(McpGlobalSessionParamDto paramDto) {
+        PageUtil.checkParam(paramDto.getPageNum(), paramDto.getPageSize());
+        McpGlobalSessionParam param = new McpGlobalSessionParam();
+        param.setPageSize(paramDto.getPageSize());
+        param.setPageNum(paramDto.getPageNum());
+        param.setStatus(paramDto.getStatus());
+        param.setXid(paramDto.getXid());
+        param.setApplicationId(paramDto.getApplicationId());
+        param.setTransactionName(paramDto.getTransactionName());
+        param.setWithBranch(paramDto.isWithBranch());
+        if (StringUtils.isNotBlank(paramDto.getTimeStart())) {
+            
param.setTimeStart(DateUtils.convertToTimeStampFromDateTime(paramDto.getTimeStart()));
+        }
+        if (StringUtils.isNotBlank(paramDto.getTimeEnd())) {
+            
param.setTimeEnd(DateUtils.convertToTimeStampFromDateTime(paramDto.getTimeEnd()));
+        }
+        return param;
+    }
+}
diff --git 
a/console/src/main/java/org/apache/seata/mcp/entity/vo/McpBranchSessionVO.java 
b/console/src/main/java/org/apache/seata/mcp/entity/vo/McpBranchSessionVO.java
new file mode 100644
index 0000000000..e753afa95f
--- /dev/null
+++ 
b/console/src/main/java/org/apache/seata/mcp/entity/vo/McpBranchSessionVO.java
@@ -0,0 +1,53 @@
+/*
+ * 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.entity.vo;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import org.apache.seata.mcp.core.config.TimestampToStringDeserializer;
+import org.apache.seata.server.console.entity.vo.BranchSessionVO;
+
+import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.ANY;
+import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.NONE;
+
+@JsonAutoDetect(getterVisibility = NONE, fieldVisibility = ANY)
+public class McpBranchSessionVO extends BranchSessionVO {
+
+    private String createTime;
+    private String modifiedTime;
+
+    @JsonProperty("gmtCreate")
+    @JsonDeserialize(using = TimestampToStringDeserializer.class)
+    public String getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(String createTime) {
+        this.createTime = createTime;
+    }
+
+    @JsonProperty("gmtModified")
+    @JsonDeserialize(using = TimestampToStringDeserializer.class)
+    public String getModifiedTime() {
+        return modifiedTime;
+    }
+
+    public void setModifiedTime(String modifiedTime) {
+        this.modifiedTime = modifiedTime;
+    }
+}
diff --git 
a/server/src/main/java/org/apache/seata/server/console/entity/param/GlobalLockParam.java
 b/console/src/main/java/org/apache/seata/mcp/entity/vo/McpGlobalLockVO.java
similarity index 63%
rename from 
server/src/main/java/org/apache/seata/server/console/entity/param/GlobalLockParam.java
rename to 
console/src/main/java/org/apache/seata/mcp/entity/vo/McpGlobalLockVO.java
index ec13f0b30e..eaa4562cfe 100644
--- 
a/server/src/main/java/org/apache/seata/server/console/entity/param/GlobalLockParam.java
+++ b/console/src/main/java/org/apache/seata/mcp/entity/vo/McpGlobalLockVO.java
@@ -14,66 +14,60 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.seata.server.console.entity.param;
+package org.apache.seata.mcp.entity.vo;
 
-import org.apache.seata.common.result.BaseParam;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import org.apache.seata.mcp.core.config.TimestampToStringDeserializer;
 
-import java.io.Serializable;
+public class McpGlobalLockVO {
 
-/**
- * Global lock param
- */
-public class GlobalLockParam extends BaseParam implements Serializable {
-
-    private static final long serialVersionUID = 615412528070131284L;
-
-    /**
-     * the xid
-     */
     private String xid;
-    /**
-     * the table name
-     */
-    private String tableName;
-    /**
-     * the transaction id
-     */
+
     private String transactionId;
-    /**
-     * the branch id
-     */
+
     private String branchId;
-    /**
-     * the primary Key
-     */
+
+    private String resourceId;
+
+    private String tableName;
+
     private String pk;
+
+    private String rowKey;
+
     /**
-     * the resourceId
+     * the vgroup
      */
-    private String resourceId;
+    private String vgroup;
 
-    public String getTransactionId() {
-        return transactionId;
+    @JsonDeserialize(using = TimestampToStringDeserializer.class)
+    private String gmtCreate;
+
+    @JsonDeserialize(using = TimestampToStringDeserializer.class)
+    private String gmtModified;
+
+    public String getXid() {
+        return xid;
     }
 
-    public void setTransactionId(String transactionId) {
-        this.transactionId = transactionId;
+    public void setXid(String xid) {
+        this.xid = xid;
     }
 
-    public String getBranchId() {
-        return branchId;
+    public String getTransactionId() {
+        return transactionId;
     }
 
-    public void setBranchId(String branchId) {
-        this.branchId = branchId;
+    public String getBranchId() {
+        return branchId;
     }
 
-    public String getXid() {
-        return xid;
+    public String getResourceId() {
+        return resourceId;
     }
 
-    public void setXid(String xid) {
-        this.xid = xid;
+    public void setResourceId(String resourceId) {
+        this.resourceId = resourceId;
     }
 
     public String getTableName() {
@@ -92,22 +86,43 @@ public class GlobalLockParam extends BaseParam implements 
Serializable {
         this.pk = pk;
     }
 
-    public String getResourceId() {
-        return resourceId;
+    public String getRowKey() {
+        return rowKey;
     }
 
-    public void setResourceId(String resourceId) {
-        this.resourceId = resourceId;
+    public void setRowKey(String rowKey) {
+        this.rowKey = rowKey;
+    }
+
+    public String getGmtCreate() {
+        return gmtCreate;
+    }
+
+    public void setGmtCreate(String gmtCreate) {
+        this.gmtCreate = gmtCreate;
+    }
+
+    public String getGmtModified() {
+        return gmtModified;
+    }
+
+    public void setGmtModified(String gmtModified) {
+        this.gmtModified = gmtModified;
+    }
+
+    public void setTransactionId(String transactionId) {
+        this.transactionId = transactionId;
+    }
+
+    public void setBranchId(String branchId) {
+        this.branchId = branchId;
+    }
+
+    public String getVgroup() {
+        return vgroup;
     }
 
-    @Override
-    public String toString() {
-        return "GlobalLockParam{" + "xid='"
-                + xid + '\'' + ", tableName='"
-                + tableName + '\'' + ", transactionId='"
-                + transactionId + '\'' + ", branchId='"
-                + branchId + '\'' + ", pk='"
-                + pk + '\'' + ", resourceId='"
-                + resourceId + '\'' + '}';
+    public void setVgroup(String vgroup) {
+        this.vgroup = vgroup;
     }
 }
diff --git 
a/console/src/main/java/org/apache/seata/mcp/entity/vo/McpGlobalSessionVO.java 
b/console/src/main/java/org/apache/seata/mcp/entity/vo/McpGlobalSessionVO.java
new file mode 100644
index 0000000000..594b5577fb
--- /dev/null
+++ 
b/console/src/main/java/org/apache/seata/mcp/entity/vo/McpGlobalSessionVO.java
@@ -0,0 +1,76 @@
+/*
+ * 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.entity.vo;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import org.apache.seata.mcp.core.config.TimestampToStringDeserializer;
+import org.apache.seata.server.console.entity.vo.GlobalSessionVO;
+
+import java.util.Set;
+
+import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.ANY;
+import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.NONE;
+
+@JsonAutoDetect(getterVisibility = NONE, fieldVisibility = ANY)
+public class McpGlobalSessionVO extends GlobalSessionVO {
+
+    private String beginTime;
+    private String createTime;
+    private String modifiedTime;
+    private Set<McpBranchSessionVO> mcpBranchSessionVOS;
+
+    @JsonProperty("beginTime")
+    @JsonDeserialize(using = TimestampToStringDeserializer.class)
+    public String getBegin() {
+        return beginTime;
+    }
+
+    public void setBeginTime(String beginTime) {
+        this.beginTime = beginTime;
+    }
+
+    @JsonProperty("gmtCreate")
+    @JsonDeserialize(using = TimestampToStringDeserializer.class)
+    public String getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(String createTime) {
+        this.createTime = createTime;
+    }
+
+    @JsonProperty("gmtModified")
+    @JsonDeserialize(using = TimestampToStringDeserializer.class)
+    public String getModifiedTime() {
+        return modifiedTime;
+    }
+
+    public void setModifiedTime(String modifiedTime) {
+        this.modifiedTime = modifiedTime;
+    }
+
+    @JsonProperty("branchSessionVOs")
+    public Set<McpBranchSessionVO> getMcpBranchSessionVOS() {
+        return mcpBranchSessionVOS;
+    }
+
+    public void setMcpBranchSessionVOS(Set<McpBranchSessionVO> 
mcpBranchSessionVOS) {
+        this.mcpBranchSessionVOS = mcpBranchSessionVOS;
+    }
+}
diff --git 
a/console/src/main/java/org/apache/seata/mcp/exception/ServiceCallException.java
 
b/console/src/main/java/org/apache/seata/mcp/exception/ServiceCallException.java
new file mode 100644
index 0000000000..3e4e4f78f2
--- /dev/null
+++ 
b/console/src/main/java/org/apache/seata/mcp/exception/ServiceCallException.java
@@ -0,0 +1,54 @@
+/*
+ * 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.exception;
+
+import org.springframework.http.HttpStatusCode;
+
+import java.time.Instant;
+import java.util.HashMap;
+import java.util.Map;
+
+public class ServiceCallException extends RuntimeException {
+    private final HttpStatusCode httpStatus;
+    private final Instant timestamp;
+
+    public ServiceCallException(String message, Throwable cause) {
+        super(message, cause);
+        this.httpStatus = null;
+        this.timestamp = Instant.now();
+    }
+
+    public ServiceCallException(String message) {
+        super(message);
+        this.httpStatus = null;
+        this.timestamp = Instant.now();
+    }
+
+    public ServiceCallException(String message, HttpStatusCode httpStatus) {
+        super(message);
+        this.httpStatus = httpStatus;
+        this.timestamp = Instant.now();
+    }
+
+    public Map<String, Object> toErrorResponse() {
+        Map<String, Object> error = new HashMap<>();
+        error.put("message", this.getMessage());
+        error.put("timestamp", timestamp.toString());
+        error.put("httpStatus", httpStatus != null ? httpStatus.value() : 
null);
+        return error;
+    }
+}
diff --git 
a/console/src/main/java/org/apache/seata/mcp/service/ConsoleApiService.java 
b/console/src/main/java/org/apache/seata/mcp/service/ConsoleApiService.java
new file mode 100644
index 0000000000..fda62cebe3
--- /dev/null
+++ b/console/src/main/java/org/apache/seata/mcp/service/ConsoleApiService.java
@@ -0,0 +1,48 @@
+/*
+ * 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.service;
+
+import org.apache.seata.mcp.core.props.NameSpaceDetail;
+import org.springframework.http.HttpHeaders;
+
+import java.util.Map;
+
+public interface ConsoleApiService {
+
+    String getCallTC(
+            NameSpaceDetail nameSpaceDetail,
+            String path,
+            Object objectQueryParams,
+            Map<String, String> queryParams,
+            HttpHeaders headers);
+
+    String deleteCallTC(
+            NameSpaceDetail nameSpaceDetail,
+            String path,
+            Object objectQueryParams,
+            Map<String, String> queryParams,
+            HttpHeaders headers);
+
+    String putCallTC(
+            NameSpaceDetail nameSpaceDetail,
+            String path,
+            Object objectQueryParams,
+            Map<String, String> queryParams,
+            HttpHeaders headers);
+
+    String getCallNameSpace(String path);
+}
diff --git 
a/console/src/main/java/org/apache/seata/mcp/service/ModifyConfirmService.java 
b/console/src/main/java/org/apache/seata/mcp/service/ModifyConfirmService.java
new file mode 100644
index 0000000000..2993d81c3f
--- /dev/null
+++ 
b/console/src/main/java/org/apache/seata/mcp/service/ModifyConfirmService.java
@@ -0,0 +1,26 @@
+/*
+ * 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.service;
+
+import java.util.Map;
+
+public interface ModifyConfirmService {
+
+    Map<String, String> confirmAndGetKey();
+
+    Boolean isValidKey(String key);
+}
diff --git 
a/console/src/main/java/org/apache/seata/mcp/service/impl/ConsoleRemoteServiceImpl.java
 
b/console/src/main/java/org/apache/seata/mcp/service/impl/ConsoleRemoteServiceImpl.java
new file mode 100644
index 0000000000..0047f9b81d
--- /dev/null
+++ 
b/console/src/main/java/org/apache/seata/mcp/service/impl/ConsoleRemoteServiceImpl.java
@@ -0,0 +1,244 @@
+/*
+ * 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.service.impl;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.seata.common.NamingServerLocalMarker;
+import org.apache.seata.common.exception.AuthenticationFailedException;
+import org.apache.seata.common.util.StringUtils;
+import org.apache.seata.console.config.WebSecurityConfig;
+import org.apache.seata.console.utils.JwtTokenUtils;
+import org.apache.seata.mcp.core.props.NameSpaceDetail;
+import org.apache.seata.mcp.core.props.NamingServerProperties;
+import org.apache.seata.mcp.exception.ServiceCallException;
+import org.apache.seata.mcp.service.ConsoleApiService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import 
org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.stereotype.Service;
+import org.springframework.web.client.RestClientException;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.Map;
+
+import static org.apache.seata.mcp.core.utils.UrlUtils.buildUrl;
+import static org.apache.seata.mcp.core.utils.UrlUtils.objectToQueryParamMap;
+
+@ConditionalOnMissingBean(NamingServerLocalMarker.class)
+@Service
+public class ConsoleRemoteServiceImpl implements ConsoleApiService {
+
+    private final JwtTokenUtils jwtTokenUtils;
+
+    private final RestTemplate restTemplate;
+
+    private final ObjectMapper objectMapper;
+
+    private final NamingServerProperties namingServerProperties;
+
+    public ConsoleRemoteServiceImpl(
+            JwtTokenUtils jwtTokenUtils,
+            RestTemplate restTemplate,
+            ObjectMapper objectMapper,
+            NamingServerProperties namingServerProperties) {
+        this.jwtTokenUtils = jwtTokenUtils;
+        this.restTemplate = restTemplate;
+        this.objectMapper = objectMapper;
+        this.namingServerProperties = namingServerProperties;
+    }
+
+    private final Logger logger = 
LoggerFactory.getLogger(ConsoleRemoteServiceImpl.class);
+
+    public String getToken() {
+        Authentication auth = 
SecurityContextHolder.getContext().getAuthentication();
+        if (auth == null || !auth.isAuthenticated()) {
+            throw new AuthenticationFailedException("No right to be 
identified");
+        }
+        String originJwt = (String) auth.getCredentials();
+        if (!jwtTokenUtils.validateToken(originJwt)) {
+            throw new AuthenticationFailedException("Invalid token, please log 
in to get a new token");
+        }
+        return WebSecurityConfig.TOKEN_PREFIX + originJwt;
+    }
+
+    public void setNamespaceHeaderAndQueryParam(
+            NameSpaceDetail nameSpaceDetail, HttpHeaders headers, Map<String, 
String> queryParams) {
+        headers.add("x-seata-namespace", nameSpaceDetail.getNamespace());
+        if (StringUtils.isNotBlank(nameSpaceDetail.getvGroup())) {
+            if (queryParams != null) {
+                queryParams.put("vGroup", nameSpaceDetail.getvGroup());
+            }
+            return;
+        }
+        if (nameSpaceDetail.getCluster() != null) {
+            headers.add("x-seata-cluster", nameSpaceDetail.getCluster());
+        }
+    }
+
+    @Override
+    public String getCallNameSpace(String path) {
+        HttpHeaders headers = new HttpHeaders();
+        headers.add(WebSecurityConfig.AUTHORIZATION_HEADER, getToken());
+        String url = buildUrl(namingServerProperties.getNamingServerUrl(), 
path, null, null);
+        HttpEntity<String> entity = new HttpEntity<>(headers);
+        String responseBody;
+        try {
+            ResponseEntity<String> response = restTemplate.exchange(url, 
HttpMethod.GET, entity, String.class);
+
+            responseBody = response.getBody();
+
+            if (!response.getStatusCode().is2xxSuccessful()) {
+                String errorMsg = String.format(
+                        "MCP GET request failed with status: %s, response: %s",
+                        response.getStatusCode(), response.getBody());
+                logger.warn(errorMsg);
+                throw new ServiceCallException(errorMsg, 
response.getStatusCode());
+            }
+            return responseBody;
+        } catch (RestClientException e) {
+            String errorMsg = "MCP GET Call NameSpace Failed.";
+            logger.error(errorMsg, e);
+            throw new ServiceCallException(errorMsg);
+        }
+    }
+
+    @Override
+    public String getCallTC(
+            NameSpaceDetail nameSpaceDetail,
+            String path,
+            Object objectQueryParams,
+            Map<String, String> queryParams,
+            HttpHeaders headers) {
+        if (headers == null) {
+            headers = new HttpHeaders();
+        }
+        if (nameSpaceDetail == null || !nameSpaceDetail.isValid()) {
+            return "If you have not specified the namespace of the TC/Server, 
specify the namespace first";
+        } else {
+            setNamespaceHeaderAndQueryParam(nameSpaceDetail, headers, 
queryParams);
+        }
+        headers.add(WebSecurityConfig.AUTHORIZATION_HEADER, getToken());
+        Map<String, Object> queryParamsMap = 
objectToQueryParamMap(objectQueryParams, objectMapper);
+        String url = buildUrl(namingServerProperties.getNamingServerUrl(), 
path, queryParams, queryParamsMap);
+        HttpEntity<String> entity = new HttpEntity<>(headers);
+        String responseBody;
+        try {
+            ResponseEntity<String> response = restTemplate.exchange(url, 
HttpMethod.GET, entity, String.class);
+
+            responseBody = response.getBody();
+
+            if (!response.getStatusCode().is2xxSuccessful()) {
+                String errorMsg = String.format(
+                        "MCP GET request failed with status: %s, response: %s",
+                        response.getStatusCode(), response.getBody());
+                logger.warn(errorMsg);
+                throw new ServiceCallException(errorMsg, 
response.getStatusCode());
+            }
+            return responseBody;
+        } catch (RestClientException e) {
+            String errorMsg = "MCP GET Call TC Failed.";
+            logger.error(errorMsg, e);
+            throw new ServiceCallException(errorMsg);
+        }
+    }
+
+    @Override
+    public String deleteCallTC(
+            NameSpaceDetail nameSpaceDetail,
+            String path,
+            Object objectQueryParams,
+            Map<String, String> queryParams,
+            HttpHeaders headers) {
+        if (headers == null) {
+            headers = new HttpHeaders();
+        }
+        if (nameSpaceDetail == null || !nameSpaceDetail.isValid()) {
+            return "If you have not specified the namespace of the TC/Server, 
specify the namespace first";
+        } else {
+            setNamespaceHeaderAndQueryParam(nameSpaceDetail, headers, 
queryParams);
+        }
+        headers.add(WebSecurityConfig.AUTHORIZATION_HEADER, getToken());
+        Map<String, Object> queryParamsMap = 
objectToQueryParamMap(objectQueryParams, objectMapper);
+        String url = buildUrl(namingServerProperties.getNamingServerUrl(), 
path, queryParams, queryParamsMap);
+        HttpEntity<String> entity = new HttpEntity<>(headers);
+        String responseBody;
+        try {
+            ResponseEntity<String> response = restTemplate.exchange(url, 
HttpMethod.DELETE, entity, String.class);
+
+            responseBody = response.getBody();
+
+            if (!response.getStatusCode().is2xxSuccessful()) {
+                String errorMsg = String.format(
+                        "MCP DELETE request returned non-success status: %s, 
response: %s",
+                        response.getStatusCode(), response.getBody());
+                logger.warn(errorMsg);
+                throw new ServiceCallException(errorMsg, 
response.getStatusCode());
+            }
+            return responseBody;
+        } catch (RestClientException e) {
+            String errorMsg = "MCP DELETE Call TC Failed.";
+            logger.error(errorMsg, e);
+            throw new ServiceCallException(errorMsg);
+        }
+    }
+
+    @Override
+    public String putCallTC(
+            NameSpaceDetail nameSpaceDetail,
+            String path,
+            Object objectQueryParams,
+            Map<String, String> queryParams,
+            HttpHeaders headers) {
+        if (headers == null) {
+            headers = new HttpHeaders();
+        }
+        if (nameSpaceDetail == null || !nameSpaceDetail.isValid()) {
+            return "If you have not specified the namespace of the TC/Server, 
specify the namespace first";
+        } else {
+            setNamespaceHeaderAndQueryParam(nameSpaceDetail, headers, 
queryParams);
+        }
+        headers.add(WebSecurityConfig.AUTHORIZATION_HEADER, getToken());
+        Map<String, Object> queryParamsMap = 
objectToQueryParamMap(objectQueryParams, objectMapper);
+        String url = buildUrl(namingServerProperties.getNamingServerUrl(), 
path, queryParams, queryParamsMap);
+        HttpEntity<String> entity = new HttpEntity<>(headers);
+        String responseBody;
+        try {
+            ResponseEntity<String> response = restTemplate.exchange(url, 
HttpMethod.PUT, entity, String.class);
+
+            responseBody = response.getBody();
+
+            if (!response.getStatusCode().is2xxSuccessful()) {
+                String errorMsg = String.format(
+                        "MCP PUT request returned non-success status: %s, 
response: %s",
+                        response.getStatusCode(), response.getBody());
+                logger.warn(errorMsg);
+                throw new ServiceCallException(errorMsg, 
response.getStatusCode());
+            }
+            return responseBody;
+        } catch (RestClientException e) {
+            String errorMsg = "MCP PUT Call TC Failed.";
+            logger.error(errorMsg, e);
+            throw new ServiceCallException(errorMsg);
+        }
+    }
+}
diff --git 
a/console/src/main/java/org/apache/seata/mcp/service/impl/ModifyConfirmServiceImpl.java
 
b/console/src/main/java/org/apache/seata/mcp/service/impl/ModifyConfirmServiceImpl.java
new file mode 100644
index 0000000000..41e74bc4e6
--- /dev/null
+++ 
b/console/src/main/java/org/apache/seata/mcp/service/impl/ModifyConfirmServiceImpl.java
@@ -0,0 +1,73 @@
+/*
+ * 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.service.impl;
+
+import io.jsonwebtoken.Jwts;
+import io.jsonwebtoken.SignatureAlgorithm;
+import io.jsonwebtoken.io.Decoders;
+import org.apache.seata.console.utils.JwtTokenUtils;
+import org.apache.seata.mcp.service.ModifyConfirmService;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.stereotype.Service;
+
+import javax.crypto.spec.SecretKeySpec;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+@Service
+public class ModifyConfirmServiceImpl implements ModifyConfirmService {
+
+    private final JwtTokenUtils jwtTokenUtils;
+
+    private static final long MODIFY_TOKEN_VALIDITY_IN_MILLISECONDS = 180_000;
+
+    @Value("${seata.security.secretKey}")
+    private String secretKey;
+
+    public ModifyConfirmServiceImpl(JwtTokenUtils jwtTokenUtils) {
+        this.jwtTokenUtils = jwtTokenUtils;
+    }
+
+    @Override
+    public Map<String, String> confirmAndGetKey() {
+        Authentication authentication = 
SecurityContextHolder.getContext().getAuthentication();
+        long now = (new Date()).getTime();
+        Date expirationDate = new Date(now + 
MODIFY_TOKEN_VALIDITY_IN_MILLISECONDS);
+        SecretKeySpec secretKeySpec =
+                new SecretKeySpec(Decoders.BASE64.decode(secretKey), 
SignatureAlgorithm.HS256.getJcaName());
+        String key = Jwts.builder()
+                .setSubject(authentication.getName())
+                .claim("modify", "")
+                .setExpiration(expirationDate)
+                .signWith(secretKeySpec, SignatureAlgorithm.HS256)
+                .compact();
+        Map<String, String> map = new HashMap<>();
+        map.put("modify_key", key);
+        map.put(
+                "Important!!!",
+                "You need to repeat the content to be modified by the user and 
get confirmation from the user before you can continue to call the modification 
tool");
+        return map;
+    }
+
+    @Override
+    public Boolean isValidKey(String key) {
+        return jwtTokenUtils.validateToken(key);
+    }
+}
diff --git 
a/console/src/main/java/org/apache/seata/mcp/tools/BranchSessionTools.java 
b/console/src/main/java/org/apache/seata/mcp/tools/BranchSessionTools.java
new file mode 100644
index 0000000000..23dd37bf16
--- /dev/null
+++ b/console/src/main/java/org/apache/seata/mcp/tools/BranchSessionTools.java
@@ -0,0 +1,105 @@
+/*
+ * 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.tools;
+
+import org.apache.seata.common.util.StringUtils;
+import org.apache.seata.mcp.core.constant.RPCConstant;
+import org.apache.seata.mcp.core.props.NameSpaceDetail;
+import org.apache.seata.mcp.service.ConsoleApiService;
+import org.apache.seata.mcp.service.ModifyConfirmService;
+import org.springaicommunity.mcp.annotation.McpTool;
+import org.springaicommunity.mcp.annotation.McpToolParam;
+import org.springframework.stereotype.Service;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@Service
+public class BranchSessionTools {
+
+    private final ConsoleApiService mcpRPCService;
+
+    private final ModifyConfirmService modifyConfirmService;
+
+    public BranchSessionTools(ConsoleApiService mcpRPCService, 
ModifyConfirmService modifyConfirmService) {
+        this.mcpRPCService = mcpRPCService;
+        this.modifyConfirmService = modifyConfirmService;
+    }
+
+    @McpTool(description = "Delete branch transactions, Get the modify key 
before you delete")
+    public String deleteBranchSession(
+            @McpToolParam(description = "Specify the namespace of the TC 
node") NameSpaceDetail nameSpaceDetail,
+            @McpToolParam(description = "Global transaction id") String xid,
+            @McpToolParam(description = "Branch transaction id") String 
branchId,
+            @McpToolParam(description = "Modify key") String modifyKey) {
+        if (!modifyConfirmService.isValidKey(modifyKey)) {
+            return "The modify key is not available";
+        }
+        Map<String, String> pathParams = new HashMap<>();
+        pathParams.put("xid", xid);
+        pathParams.put("branchId", branchId);
+        String result = mcpRPCService.deleteCallTC(
+                nameSpaceDetail, RPCConstant.BRANCH_SESSION_BASE_URL + 
"/deleteBranchSession", null, pathParams, null);
+        if (StringUtils.isBlank(result)) {
+            return String.format("delete branch session failed, xid: %s, 
branchId: %s", xid, branchId);
+        } else {
+            return result;
+        }
+    }
+
+    @McpTool(description = "Stop the branch transaction retry, Get the modify 
key before you stop")
+    public String stopBranchSession(
+            @McpToolParam(description = "Specify the namespace of the TC 
node") NameSpaceDetail nameSpaceDetail,
+            @McpToolParam(description = "Global transaction id") String xid,
+            @McpToolParam(description = "Branch transaction id") String 
branchId,
+            @McpToolParam(description = "Modify key") String modifyKey) {
+        if (!modifyConfirmService.isValidKey(modifyKey)) {
+            return "The modify key is not available";
+        }
+        Map<String, String> pathParams = new HashMap<>();
+        pathParams.put("xid", xid);
+        pathParams.put("branchId", branchId);
+        String result = mcpRPCService.putCallTC(
+                nameSpaceDetail, RPCConstant.BRANCH_SESSION_BASE_URL + 
"/stopBranchSession", null, pathParams, null);
+        if (StringUtils.isBlank(result)) {
+            return String.format("stop branch session failed, xid: %s, 
branchId: %s", xid, branchId);
+        } else {
+            return result;
+        }
+    }
+
+    @McpTool(description = "Initiate a branch transaction retries, Get the 
modify key before you start")
+    public String startBranchRetry(
+            @McpToolParam(description = "Specify the namespace of the TC 
node") NameSpaceDetail nameSpaceDetail,
+            @McpToolParam(description = "Global transaction id") String xid,
+            @McpToolParam(description = "Branch transaction id") String 
branchId,
+            @McpToolParam(description = "Modify key") String modifyKey) {
+        if (!modifyConfirmService.isValidKey(modifyKey)) {
+            return "The modify key is not available";
+        }
+        Map<String, String> pathParams = new HashMap<>();
+        pathParams.put("xid", xid);
+        pathParams.put("branchId", branchId);
+        String result = mcpRPCService.putCallTC(
+                nameSpaceDetail, RPCConstant.BRANCH_SESSION_BASE_URL + 
"/startBranchSession", null, pathParams, null);
+        if (StringUtils.isBlank(result)) {
+            return String.format("start branch session failed, xid: %s, 
branchId: %s", xid, branchId);
+        } else {
+            return result;
+        }
+    }
+}
diff --git 
a/console/src/main/java/org/apache/seata/mcp/tools/GlobalLockTools.java 
b/console/src/main/java/org/apache/seata/mcp/tools/GlobalLockTools.java
new file mode 100644
index 0000000000..ca6e034ea6
--- /dev/null
+++ b/console/src/main/java/org/apache/seata/mcp/tools/GlobalLockTools.java
@@ -0,0 +1,141 @@
+/*
+ * 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.tools;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.seata.common.result.PageResult;
+import org.apache.seata.common.util.StringUtils;
+import org.apache.seata.mcp.core.constant.RPCConstant;
+import org.apache.seata.mcp.core.props.MCPProperties;
+import org.apache.seata.mcp.core.props.NameSpaceDetail;
+import org.apache.seata.mcp.core.utils.DateUtils;
+import org.apache.seata.mcp.entity.dto.McpGlobalLockParamDto;
+import org.apache.seata.mcp.entity.param.McpGlobalLockDeleteParam;
+import org.apache.seata.mcp.entity.param.McpGlobalLockParam;
+import org.apache.seata.mcp.entity.vo.McpGlobalLockVO;
+import org.apache.seata.mcp.service.ConsoleApiService;
+import org.apache.seata.mcp.service.ModifyConfirmService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springaicommunity.mcp.annotation.McpTool;
+import org.springaicommunity.mcp.annotation.McpToolParam;
+import org.springframework.stereotype.Service;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@Service
+public class GlobalLockTools {
+
+    private final Logger logger = 
LoggerFactory.getLogger(GlobalLockTools.class);
+
+    private final ConsoleApiService mcpRPCService;
+
+    private final MCPProperties mcpProperties;
+
+    private final ModifyConfirmService modifyConfirmService;
+
+    private final ObjectMapper objectMapper;
+
+    public GlobalLockTools(
+            ConsoleApiService mcpRPCService,
+            MCPProperties mcpProperties,
+            ModifyConfirmService modifyConfirmService,
+            ObjectMapper objectMapper) {
+        this.mcpRPCService = mcpRPCService;
+        this.mcpProperties = mcpProperties;
+        this.modifyConfirmService = modifyConfirmService;
+        this.objectMapper = objectMapper;
+    }
+
+    @McpTool(description = "Query the global lock information")
+    public PageResult<McpGlobalLockVO> queryGlobalLock(
+            @McpToolParam(description = "Specify the namespace of the TC 
node") NameSpaceDetail nameSpaceDetail,
+            @McpToolParam(description = "Global lock parameters") 
McpGlobalLockParamDto paramDto) {
+        McpGlobalLockParam param = 
McpGlobalLockParam.convertFromParamDto(paramDto);
+        Long timeStart = param.getTimeStart();
+        Long timeEnd = param.getTimeEnd();
+        Long maxQueryDuration = mcpProperties.getQueryDuration();
+        if (timeStart != null || timeEnd != null) {
+            if (timeStart == null) {
+                timeStart = timeEnd - maxQueryDuration;
+                param.setTimeStart(timeStart);
+            }
+            if (timeEnd == null) {
+                timeEnd = timeStart + maxQueryDuration;
+                param.setTimeEnd(timeEnd);
+            }
+            if (DateUtils.judgeExceedTimeDuration(timeStart, timeEnd, 
maxQueryDuration)) {
+                return PageResult.failure(
+                        "",
+                        String.format(
+                                "The query time span is not allowed to exceed 
the max query duration: %s hours",
+                                
DateUtils.convertToHourFromTimeStamp(maxQueryDuration)));
+            }
+        }
+        PageResult<McpGlobalLockVO> result = null;
+        String response = mcpRPCService.getCallTC(
+                nameSpaceDetail, RPCConstant.GLOBAL_LOCK_BASE_URL + "/query", 
param, null, null);
+        try {
+            result = objectMapper.readValue(response, new 
TypeReference<PageResult<McpGlobalLockVO>>() {});
+        } catch (JsonProcessingException e) {
+            logger.error(e.getMessage());
+        }
+        if (result == null) {
+            return PageResult.failure("", "query global lock failed");
+        } else {
+            return result;
+        }
+    }
+
+    @McpTool(description = "Delete the global lock, Get the modify key before 
you delete")
+    public String deleteGlobalLock(
+            @McpToolParam(description = "Specify the namespace of the TC 
node") NameSpaceDetail nameSpaceDetail,
+            @McpToolParam(description = "Global lock delete parameters") 
McpGlobalLockDeleteParam param,
+            @McpToolParam(description = "Modify key") String modifyKey) {
+        if (!modifyConfirmService.isValidKey(modifyKey)) {
+            return "The modify key is not available";
+        }
+        String result = mcpRPCService.deleteCallTC(
+                nameSpaceDetail, RPCConstant.GLOBAL_LOCK_BASE_URL + "/delete", 
param, null, null);
+        if (StringUtils.isBlank(result)) {
+            return String.format(
+                    "delete global lock failed, xid: %s, branchId: %s", 
param.getXid(), param.getBranchId());
+        } else {
+            return result;
+        }
+    }
+
+    @McpTool(description = "Check if the branch session has a lock")
+    public String checkGlobalLock(
+            @McpToolParam(description = "Specify the namespace of the TC 
node") NameSpaceDetail nameSpaceDetail,
+            @McpToolParam(description = "Global transaction id") String xid,
+            @McpToolParam(description = "Branch transaction id") String 
branchId) {
+        Map<String, String> pathParams = new HashMap<>();
+        pathParams.put("xid", xid);
+        pathParams.put("branchId", branchId);
+        String result = mcpRPCService.getCallTC(
+                nameSpaceDetail, RPCConstant.GLOBAL_LOCK_BASE_URL + "/check", 
null, pathParams, null);
+        if (StringUtils.isBlank(result)) {
+            return String.format("check global lock failed, xid: %s, branchId: 
%s", xid, branchId);
+        } else {
+            return result;
+        }
+    }
+}
diff --git 
a/console/src/main/java/org/apache/seata/mcp/tools/GlobalSessionTools.java 
b/console/src/main/java/org/apache/seata/mcp/tools/GlobalSessionTools.java
new file mode 100644
index 0000000000..b3697e5dde
--- /dev/null
+++ b/console/src/main/java/org/apache/seata/mcp/tools/GlobalSessionTools.java
@@ -0,0 +1,231 @@
+/*
+ * 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.tools;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.seata.common.result.PageResult;
+import org.apache.seata.common.util.StringUtils;
+import org.apache.seata.core.model.GlobalStatus;
+import org.apache.seata.mcp.core.constant.RPCConstant;
+import org.apache.seata.mcp.core.props.MCPProperties;
+import org.apache.seata.mcp.core.props.NameSpaceDetail;
+import org.apache.seata.mcp.core.utils.DateUtils;
+import org.apache.seata.mcp.entity.dto.McpGlobalSessionParamDto;
+import org.apache.seata.mcp.entity.param.McpGlobalAbnormalSessionParam;
+import org.apache.seata.mcp.entity.param.McpGlobalSessionParam;
+import org.apache.seata.mcp.entity.vo.McpGlobalSessionVO;
+import org.apache.seata.mcp.service.ConsoleApiService;
+import org.apache.seata.mcp.service.ModifyConfirmService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springaicommunity.mcp.annotation.McpTool;
+import org.springaicommunity.mcp.annotation.McpToolParam;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Service
+public class GlobalSessionTools {
+
+    private final Logger logger = 
LoggerFactory.getLogger(GlobalSessionTools.class);
+
+    private final ConsoleApiService mcpRPCService;
+
+    private final MCPProperties mcpProperties;
+
+    private final ObjectMapper objectMapper;
+
+    private final ModifyConfirmService modifyConfirmService;
+
+    private final List<Integer> exceptionStatus = new ArrayList<>();
+
+    public static final int ABNORMAL_SESSION_PAGE_SIZE = 30;
+
+    public GlobalSessionTools(
+            ConsoleApiService mcpRPCService,
+            MCPProperties mcpProperties,
+            ObjectMapper objectMapper,
+            ModifyConfirmService modifyConfirmService) {
+        this.mcpRPCService = mcpRPCService;
+        this.mcpProperties = mcpProperties;
+        this.objectMapper = objectMapper;
+        this.modifyConfirmService = modifyConfirmService;
+        exceptionStatus.add(GlobalStatus.CommitFailed.getCode());
+        exceptionStatus.add(GlobalStatus.TimeoutRollbackFailed.getCode());
+        exceptionStatus.add(GlobalStatus.RollbackFailed.getCode());
+    }
+
+    @McpTool(description = "Query global transactions")
+    public PageResult<McpGlobalSessionVO> queryGlobalSession(
+            @McpToolParam(description = "Specify the namespace of the TC 
node") NameSpaceDetail nameSpaceDetail,
+            @McpToolParam(description = "Query parameter objects") 
McpGlobalSessionParamDto paramDto) {
+        McpGlobalSessionParam param = 
McpGlobalSessionParam.convertFromDtoParam(paramDto);
+        Long timeStart = param.getTimeStart();
+        Long timeEnd = param.getTimeEnd();
+        Long maxQueryDuration = mcpProperties.getQueryDuration();
+        if (timeStart != null || timeEnd != null) {
+            if (timeStart == null) {
+                timeStart = timeEnd - maxQueryDuration;
+                param.setTimeStart(timeStart);
+            }
+            if (timeEnd == null) {
+                timeEnd = timeStart + maxQueryDuration;
+                param.setTimeEnd(timeEnd);
+            }
+            if (DateUtils.judgeExceedTimeDuration(timeStart, timeEnd, 
maxQueryDuration)) {
+                return PageResult.failure(
+                        "",
+                        String.format(
+                                "The query time span is not allowed to exceed 
the max query duration: %s hours",
+                                
DateUtils.convertToHourFromTimeStamp(maxQueryDuration)));
+            }
+        }
+        PageResult<McpGlobalSessionVO> pageResult = null;
+        String result = mcpRPCService.getCallTC(
+                nameSpaceDetail, RPCConstant.GLOBAL_SESSION_BASE_URL + 
"/query", param, null, null);
+        try {
+            pageResult = objectMapper.readValue(result, new 
TypeReference<PageResult<McpGlobalSessionVO>>() {});
+        } catch (JsonProcessingException e) {
+            logger.error(e.getMessage());
+        }
+        if (pageResult == null) {
+            return PageResult.failure("", "query global session failed");
+        } else {
+            return pageResult;
+        }
+    }
+
+    @McpTool(description = "Delete the global session, Get the modify key 
before you delete")
+    public String deleteGlobalSession(
+            @McpToolParam(description = "Specify the namespace of the TC 
node") NameSpaceDetail nameSpaceDetail,
+            @McpToolParam(description = "Global transaction id") String xid,
+            @McpToolParam(description = "Modify key") String modifyKey) {
+        if (!modifyConfirmService.isValidKey(modifyKey)) {
+            return "The modify key is not available";
+        }
+        Map<String, String> pathParams = new HashMap<>();
+        pathParams.put("xid", xid);
+        String result = mcpRPCService.deleteCallTC(
+                nameSpaceDetail, RPCConstant.GLOBAL_SESSION_BASE_URL + 
"/deleteGlobalSession", null, pathParams, null);
+        if (StringUtils.isBlank(result)) {
+            return String.format("delete global session failed, xid: %s", xid);
+        } else {
+            return result;
+        }
+    }
+
+    @McpTool(description = "Stop the global session retry, Get the modify key 
before you stop")
+    public String stopGlobalSession(
+            @McpToolParam(description = "Specify the namespace of the TC 
node") NameSpaceDetail nameSpaceDetail,
+            @McpToolParam(description = "Global transaction id") String xid,
+            @McpToolParam(description = "Modify key") String modifyKey) {
+        if (!modifyConfirmService.isValidKey(modifyKey)) {
+            return "The modify key is not available";
+        }
+        Map<String, String> pathParams = new HashMap<>();
+        pathParams.put("xid", xid);
+        String result = mcpRPCService.putCallTC(
+                nameSpaceDetail, RPCConstant.GLOBAL_SESSION_BASE_URL + 
"/stopGlobalSession", null, pathParams, null);
+        if (StringUtils.isBlank(result)) {
+            return String.format("stop global session retry failed, xid: %s", 
xid);
+        } else {
+            return result;
+        }
+    }
+
+    @McpTool(description = "Start the global session retry, Get the modify key 
before you start")
+    public String startGlobalSession(
+            @McpToolParam(description = "Specify the namespace of the TC 
node") NameSpaceDetail nameSpaceDetail,
+            @McpToolParam(description = "Global transaction id") String xid,
+            @McpToolParam(description = "Modify key") String modifyKey) {
+        if (!modifyConfirmService.isValidKey(modifyKey)) {
+            return "The modify key is not available";
+        }
+        Map<String, String> pathParams = new HashMap<>();
+        pathParams.put("xid", xid);
+        String result = mcpRPCService.putCallTC(
+                nameSpaceDetail, RPCConstant.GLOBAL_SESSION_BASE_URL + 
"/startGlobalSession", null, pathParams, null);
+        if (StringUtils.isBlank(result)) {
+            return String.format("start the global session retry failed, xid: 
%s", xid);
+        } else {
+            return result;
+        }
+    }
+
+    @McpTool(description = "Send global session to commit or rollback to rm, 
Get the modify key before you send")
+    public String sendCommitOrRollback(
+            @McpToolParam(description = "Specify the namespace of the TC 
node") NameSpaceDetail nameSpaceDetail,
+            @McpToolParam(description = "Global transaction id") String xid,
+            @McpToolParam(description = "Modify key") String modifyKey) {
+        if (!modifyConfirmService.isValidKey(modifyKey)) {
+            return "The modify key is not available";
+        }
+        Map<String, String> pathParams = new HashMap<>();
+        pathParams.put("xid", xid);
+        String result = mcpRPCService.putCallTC(
+                nameSpaceDetail, RPCConstant.GLOBAL_SESSION_BASE_URL + 
"/sendCommitOrRollback", null, pathParams, null);
+        if (StringUtils.isBlank(result)) {
+            return String.format("send global session to commit or rollback to 
rm failed, xid: %s", xid);
+        } else {
+            return result;
+        }
+    }
+
+    @McpTool(
+            description =
+                    "Change the global session status, Used to change 
transactions that are in a failed commit or rollback failed state to a retry 
state, Get the modify key before you change")
+    public String changeGlobalStatus(
+            @McpToolParam(description = "Specify the namespace of the TC 
node") NameSpaceDetail nameSpaceDetail,
+            @McpToolParam(description = "Global transaction id") String xid,
+            @McpToolParam(description = "Modify key") String modifyKey) {
+        if (!modifyConfirmService.isValidKey(modifyKey)) {
+            return "The modify key is not available";
+        }
+        Map<String, String> pathParams = new HashMap<>();
+        pathParams.put("xid", xid);
+        String result = mcpRPCService.putCallTC(
+                nameSpaceDetail, RPCConstant.GLOBAL_SESSION_BASE_URL + 
"/changeGlobalStatus", null, pathParams, null);
+        if (StringUtils.isBlank(result)) {
+            return String.format("change the global session status failed, 
xid: %s", xid);
+        } else {
+            return result;
+        }
+    }
+
+    @McpTool(description = "Check out the abnormal transaction")
+    public List<McpGlobalSessionVO> getAbnormalSessions(
+            @McpToolParam(description = "Specify the namespace of the TC 
node") NameSpaceDetail nameSpaceDetail,
+            @McpToolParam(description = "Query Param") 
McpGlobalAbnormalSessionParam abnormalSessionParam) {
+        List<McpGlobalSessionVO> result = new ArrayList<>();
+        McpGlobalSessionParamDto param = 
McpGlobalSessionParamDto.convertFromAbnormalParam(abnormalSessionParam);
+        param.setPageSize(ABNORMAL_SESSION_PAGE_SIZE);
+        for (Integer status : exceptionStatus) {
+            param.setStatus(status);
+            List<McpGlobalSessionVO> datas =
+                    queryGlobalSession(nameSpaceDetail, param).getData();
+            if (datas != null && !datas.isEmpty()) {
+                result.addAll(datas);
+            }
+        }
+        return result;
+    }
+}
diff --git 
a/console/src/main/java/org/apache/seata/mcp/tools/ModifyConfirmTools.java 
b/console/src/main/java/org/apache/seata/mcp/tools/ModifyConfirmTools.java
new file mode 100644
index 0000000000..39663c1ed2
--- /dev/null
+++ b/console/src/main/java/org/apache/seata/mcp/tools/ModifyConfirmTools.java
@@ -0,0 +1,59 @@
+/*
+ * 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.tools;
+
+import org.apache.seata.common.util.StringUtils;
+import org.apache.seata.mcp.service.ModifyConfirmService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springaicommunity.mcp.annotation.McpTool;
+import org.springaicommunity.mcp.annotation.McpToolParam;
+import org.springframework.stereotype.Service;
+
+import java.util.Map;
+
+@Service
+public class ModifyConfirmTools {
+
+    private static final Logger LOGGER = 
LoggerFactory.getLogger(ModifyConfirmTools.class);
+
+    private final ModifyConfirmService modifyConfirmService;
+
+    public ModifyConfirmTools(ModifyConfirmService modifyConfirmService) {
+        this.modifyConfirmService = modifyConfirmService;
+    }
+
+    @McpTool(
+            description = "Before modifying (update or delete) a transaction 
or lock, the user MUST manually confirm."
+                    + "You are NOT allowed to fabricate or auto-confirm on 
behalf of the user.")
+    public Map<String, String> confirmAndGetKey(
+            @McpToolParam(
+                            description =
+                                    "The confirmation string provided by the 
USER (not generated by the LLM).The content must repeat the modification action 
clearly.")
+                    String userInputStr) {
+        if (StringUtils.isBlank(userInputStr)) {
+            throw new IllegalArgumentException("User confirmation string is 
required.");
+        }
+        if (!userInputStr.contains("确认") && !userInputStr.contains("confirm")) 
{
+            throw new IllegalArgumentException(
+                    "Confirmation string must explicitly contain '确认' or 
'confirm' and repeat the modification content. This must come from the user.");
+        }
+        Map<String, String> keyMap = modifyConfirmService.confirmAndGetKey();
+        LOGGER.info("the user obtains a modify key:{}", 
keyMap.get("modify_key"));
+        return keyMap;
+    }
+}
diff --git 
a/console/src/main/java/org/apache/seata/mcp/tools/NameSpaceTools.java 
b/console/src/main/java/org/apache/seata/mcp/tools/NameSpaceTools.java
new file mode 100644
index 0000000000..1decea8773
--- /dev/null
+++ b/console/src/main/java/org/apache/seata/mcp/tools/NameSpaceTools.java
@@ -0,0 +1,58 @@
+/*
+ * 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.tools;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.seata.common.result.SingleResult;
+import org.apache.seata.mcp.core.constant.RPCConstant;
+import org.apache.seata.mcp.service.ConsoleApiService;
+import org.springaicommunity.mcp.annotation.McpTool;
+import org.springframework.stereotype.Service;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@Service
+public class NameSpaceTools {
+
+    private final ConsoleApiService mcpRPCService;
+
+    private final ObjectMapper objectMapper;
+
+    public NameSpaceTools(ConsoleApiService mcpRPCService, ObjectMapper 
objectMapper) {
+        this.mcpRPCService = mcpRPCService;
+        this.objectMapper = objectMapper;
+    }
+
+    @McpTool(description = "Get the namespace and cluster or vgroup where all 
TC/Servers are located")
+    public SingleResult<?> getTCNameSpaces() {
+        String result = 
mcpRPCService.getCallNameSpace(RPCConstant.GET_NAMESPACE_PATH);
+        Map<String, Object> nameSpacesVo = new HashMap<>();
+        try {
+            JsonNode root = objectMapper.readTree(result);
+            JsonNode dataNode = root.get("data");
+            if (dataNode != null && !dataNode.isNull()) {
+                nameSpacesVo.put("namespaces", dataNode.toString());
+            }
+        } catch (JsonProcessingException e) {
+            return SingleResult.failure("Get namespace failed:" + 
e.getMessage());
+        }
+        return SingleResult.success(nameSpacesVo);
+    }
+}
diff --git 
a/namingserver/src/main/java/org/apache/seata/namingserver/service/ConsoleLocalServiceImpl.java
 
b/namingserver/src/main/java/org/apache/seata/namingserver/service/ConsoleLocalServiceImpl.java
new file mode 100644
index 0000000000..808f46552d
--- /dev/null
+++ 
b/namingserver/src/main/java/org/apache/seata/namingserver/service/ConsoleLocalServiceImpl.java
@@ -0,0 +1,169 @@
+/*
+ * 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.namingserver.service;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.seata.common.metadata.ClusterRole;
+import org.apache.seata.common.metadata.Node;
+import org.apache.seata.common.metadata.namingserver.NamingServerNode;
+import org.apache.seata.common.util.CollectionUtils;
+import org.apache.seata.common.util.StringUtils;
+import org.apache.seata.mcp.core.props.NameSpaceDetail;
+import org.apache.seata.mcp.exception.ServiceCallException;
+import org.apache.seata.mcp.service.ConsoleApiService;
+import org.apache.seata.mcp.service.impl.ConsoleRemoteServiceImpl;
+import org.apache.seata.namingserver.manager.NamingManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
+import org.springframework.context.annotation.Primary;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Service;
+import org.springframework.web.client.RestClientException;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ThreadLocalRandom;
+
+import static org.apache.seata.common.Constants.RAFT_GROUP_HEADER;
+import static org.apache.seata.mcp.core.utils.UrlUtils.buildUrl;
+import static org.apache.seata.mcp.core.utils.UrlUtils.objectToQueryParamMap;
+
+@ConditionalOnBean(ConsoleRemoteServiceImpl.class)
+@Primary
+@Service
+public class ConsoleLocalServiceImpl implements ConsoleApiService {
+
+    private final Logger logger = LoggerFactory.getLogger(this.getClass());
+
+    private final NamingManager namingManager;
+
+    private final RestTemplate restTemplate;
+
+    private final ObjectMapper objectMapper;
+
+    public ConsoleLocalServiceImpl(NamingManager namingManager, RestTemplate 
restTemplate, ObjectMapper objectMapper) {
+        this.namingManager = namingManager;
+        this.restTemplate = restTemplate;
+        this.objectMapper = objectMapper;
+    }
+
+    public String getResult(
+            NameSpaceDetail nameSpaceDetail,
+            HttpMethod httpMethod,
+            String path,
+            Object objectQueryParams,
+            Map<String, String> queryParams,
+            HttpHeaders headers) {
+        String namespace = nameSpaceDetail.getNamespace();
+        String cluster = nameSpaceDetail.getCluster();
+        String vgroup = nameSpaceDetail.getvGroup();
+        if (StringUtils.isNotBlank(namespace) && 
(StringUtils.isNotBlank(cluster) || StringUtils.isNotBlank(vgroup))) {
+            List<NamingServerNode> list = null;
+            if (StringUtils.isNotBlank(vgroup)) {
+                list = namingManager.getInstancesByVgroupAndNamespace(
+                        namespace, vgroup, HttpMethod.GET.equals(httpMethod));
+            } else if (StringUtils.isNotBlank(cluster)) {
+                list = namingManager.getInstances(namespace, cluster);
+            }
+            if (CollectionUtils.isNotEmpty(list)) {
+                // Randomly select a node from the list
+                NamingServerNode node = 
list.get(ThreadLocalRandom.current().nextInt(list.size()));
+                Node.Endpoint controlEndpoint = node.getControl();
+                if (controlEndpoint != null) {
+                    // Construct the target URL
+                    String baseUrl = "http://"; + controlEndpoint.getHost() + 
":" + controlEndpoint.getPort();
+                    Map<String, Object> queryParamsMap = 
objectToQueryParamMap(objectQueryParams, objectMapper);
+                    String targetUrl = buildUrl(baseUrl, path, queryParams, 
queryParamsMap);
+                    if (node.getRole() == ClusterRole.LEADER) {
+                        headers.add(RAFT_GROUP_HEADER, node.getUnit());
+                    }
+                    HttpEntity<String> entity = new HttpEntity<>(headers);
+                    String responseBody;
+                    try {
+                        ResponseEntity<String> response =
+                                restTemplate.exchange(targetUrl, httpMethod, 
entity, String.class);
+
+                        responseBody = response.getBody();
+
+                        if (!response.getStatusCode().is2xxSuccessful()) {
+                            String errorMsg = String.format(
+                                    "MCP request failed with status: %s, 
response: %s",
+                                    response.getStatusCode(), 
response.getBody());
+                            logger.warn(errorMsg);
+                            throw new ServiceCallException(errorMsg, 
response.getStatusCode());
+                        }
+                        return responseBody;
+                    } catch (RestClientException e) {
+                        String errorMsg = "MCP Call TC Failed.";
+                        logger.error(errorMsg, e);
+                        throw new ServiceCallException(errorMsg);
+                    }
+                }
+            }
+            throw new IllegalArgumentException("Couldn't find target node 
url");
+        }
+        throw new IllegalArgumentException("Invalid NameSpace Detail");
+    }
+
+    @Override
+    public String getCallTC(
+            NameSpaceDetail nameSpaceDetail,
+            String path,
+            Object objectQueryParams,
+            Map<String, String> queryParams,
+            HttpHeaders headers) {
+        return getResult(nameSpaceDetail, HttpMethod.GET, path, 
objectQueryParams, queryParams, headers);
+    }
+
+    @Override
+    public String deleteCallTC(
+            NameSpaceDetail nameSpaceDetail,
+            String path,
+            Object objectQueryParams,
+            Map<String, String> queryParams,
+            HttpHeaders headers) {
+        return getResult(nameSpaceDetail, HttpMethod.DELETE, path, 
objectQueryParams, queryParams, headers);
+    }
+
+    @Override
+    public String putCallTC(
+            NameSpaceDetail nameSpaceDetail,
+            String path,
+            Object objectQueryParams,
+            Map<String, String> queryParams,
+            HttpHeaders headers) {
+        return getResult(nameSpaceDetail, HttpMethod.PUT, path, 
objectQueryParams, queryParams, headers);
+    }
+
+    @Override
+    public String getCallNameSpace(String path) {
+        String namespace;
+        try {
+            namespace = 
objectMapper.writeValueAsString(namingManager.namespace());
+        } catch (JsonProcessingException e) {
+            logger.error("Get NameSpace failed: {}", e.getMessage());
+            return "Failed to get namespace";
+        }
+        return namespace;
+    }
+}
diff --git 
a/namingserver/src/main/java/org/apache/seata/namingserver/service/NamingServerLocalMarkerImpl.java
 
b/namingserver/src/main/java/org/apache/seata/namingserver/service/NamingServerLocalMarkerImpl.java
new file mode 100644
index 0000000000..bc6e22e6e9
--- /dev/null
+++ 
b/namingserver/src/main/java/org/apache/seata/namingserver/service/NamingServerLocalMarkerImpl.java
@@ -0,0 +1,23 @@
+/*
+ * 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.namingserver.service;
+
+import org.apache.seata.common.NamingServerLocalMarker;
+import org.springframework.stereotype.Service;
+
+@Service
+public class NamingServerLocalMarkerImpl implements NamingServerLocalMarker {}
diff --git a/namingserver/src/main/resources/application.yml 
b/namingserver/src/main/resources/application.yml
index ba10362f93..b76b4638e5 100644
--- a/namingserver/src/main/resources/application.yml
+++ b/namingserver/src/main/resources/application.yml
@@ -40,6 +40,11 @@ logging:
 heartbeat:
   threshold: 90000
   period: 60000
+console:
+  namingserver:
+    protocol: http
+    addr:
+      - 127.0.0.1:8081
 seata:
   security:
     secretKey: SeataSecretKey0c382ef121d778043159209298fd40bf3850a017
@@ -51,6 +56,4 @@ seata:
   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
+      max-query-duration: 86400000
\ No newline at end of file


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

Reply via email to