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

Aias00 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shenyu.git


The following commit(s) were added to refs/heads/master by this push:
     new 837bd31655 fix(mcp): use complete tool-input URLs as the request 
target (#7430)
837bd31655 is described below

commit 837bd3165577551584a61a85e2616f46fc8de430
Author: Sean-Walker0 <[email protected]>
AuthorDate: Tue Oct 6 10:36:44 2026 +0800

    fix(mcp): use complete tool-input URLs as the request target (#7430)
    
    RequestConfigHelper#buildPath can return a complete URL taken from the
    tool input arguments, but ShenyuToolCallback#setTargetUri always
    prefixed the gateway request scheme and authority onto the built path.
    A tool input URL like https://target.example/api was rewritten into a
    malformed target such as 
http://gateway.example:9195https://target.example/api,
    so tool calls that rely on complete URLs could never reach their
    backend.
    
    When the built path is itself an absolute http(s) URL, set it as the
    request target unchanged; relative paths keep the gateway-origin
    prefix. Regression tests cover both directions (red on the previous
    code, which produced the corrupted gateway URL).
    
    Fixes #6472
    
    Co-authored-by: Sean-Walker0 
<[email protected]>
---
 .../mcp/server/callback/ShenyuToolCallback.java    |  6 ++++++
 .../server/callback/ShenyuToolCallbackTest.java    | 23 ++++++++++++++++++++++
 2 files changed, 29 insertions(+)

diff --git 
a/shenyu-plugin/shenyu-plugin-mcp-server/src/main/java/org/apache/shenyu/plugin/mcp/server/callback/ShenyuToolCallback.java
 
b/shenyu-plugin/shenyu-plugin-mcp-server/src/main/java/org/apache/shenyu/plugin/mcp/server/callback/ShenyuToolCallback.java
index 524da0a726..aa1bd65707 100644
--- 
a/shenyu-plugin/shenyu-plugin-mcp-server/src/main/java/org/apache/shenyu/plugin/mcp/server/callback/ShenyuToolCallback.java
+++ 
b/shenyu-plugin/shenyu-plugin-mcp-server/src/main/java/org/apache/shenyu/plugin/mcp/server/callback/ShenyuToolCallback.java
@@ -597,6 +597,12 @@ public class ShenyuToolCallback implements ToolCallback {
                               final ServerWebExchange originExchange,
                               final String path) {
         try {
+            if (path.startsWith("http://";) || path.startsWith("https://";)) {
+                // RequestConfigHelper#buildPath can return a complete URL 
from the tool input;
+                // prefixing the gateway origin would corrupt it
+                requestBuilder.uri(new URI(path));
+                return;
+            }
             final URI oldUri = originExchange.getRequest().getURI();
             final String newUriStr = oldUri.getScheme() + "://" + 
oldUri.getAuthority() + path;
             requestBuilder.uri(new URI(newUriStr));
diff --git 
a/shenyu-plugin/shenyu-plugin-mcp-server/src/test/java/org/apache/shenyu/plugin/mcp/server/callback/ShenyuToolCallbackTest.java
 
b/shenyu-plugin/shenyu-plugin-mcp-server/src/test/java/org/apache/shenyu/plugin/mcp/server/callback/ShenyuToolCallbackTest.java
index 4a4b079582..856caa704c 100644
--- 
a/shenyu-plugin/shenyu-plugin-mcp-server/src/test/java/org/apache/shenyu/plugin/mcp/server/callback/ShenyuToolCallbackTest.java
+++ 
b/shenyu-plugin/shenyu-plugin-mcp-server/src/test/java/org/apache/shenyu/plugin/mcp/server/callback/ShenyuToolCallbackTest.java
@@ -43,6 +43,7 @@ import 
org.springframework.mock.web.server.MockServerWebExchange;
 import org.springframework.web.server.ServerWebExchange;
 import reactor.core.publisher.Mono;
 
+import java.net.URI;
 import java.util.HashMap;
 import java.util.concurrent.atomic.AtomicBoolean;
 
@@ -304,6 +305,28 @@ class ShenyuToolCallbackTest {
         exchangeHolderMock.verify(() -> 
ShenyuMcpExchangeHolder.get("legacy-session"));
     }
 
+    @Test
+    void testSetTargetUriUsesCompleteUrlAsIs() {
+        shenyuToolCallback = new ShenyuToolCallback(toolDefinition);
+        ServerHttpRequest.Builder builder = 
MockServerHttpRequest.get("http://gateway.example:9195/mcp";).build().mutate();
+
+        ReflectionTestUtils.invokeMethod(shenyuToolCallback, "setTargetUri", 
builder, exchange, "https://target.example/api";);
+
+        assertEquals(URI.create("https://target.example/api";), 
builder.build().getURI());
+    }
+
+    @Test
+    void testSetTargetUriPrefixesGatewayOriginForRelativePath() {
+        shenyuToolCallback = new ShenyuToolCallback(toolDefinition);
+        when(exchange.getRequest()).thenReturn(request);
+        
when(request.getURI()).thenReturn(URI.create("http://gateway.example:9195/mcp";));
+        ServerHttpRequest.Builder builder = 
MockServerHttpRequest.get("http://gateway.example:9195/mcp";).build().mutate();
+
+        ReflectionTestUtils.invokeMethod(shenyuToolCallback, "setTargetUri", 
builder, exchange, "/api/order");
+
+        assertEquals(URI.create("http://gateway.example:9195/api/order";), 
builder.build().getURI());
+    }
+
     @Test
     void testConstructorWithValidToolDefinition() {
         ShenyuToolCallback callback = new ShenyuToolCallback(toolDefinition);

Reply via email to