Skip to content

Commit 7de2558

Browse files
[feat] mcp streamable http (#6061)
* [feat] mcp server plugin, init to support streamable http. * [feat] mcp server plugin, let streamable http and sse use single McpAsyncServer. * [feat] mcp server plugin, remove default tool for McpAsyncServer. * [feat] mcp server plugin, session reconnection and stateless session support for Streamable http. * [feat] mcp server plugin, debug session reconnection and stateless session support for Streamable http. * [feat] mcp server plugin, Remove handle noSessionId exchange for ShenyuToolCallback . * [feat] mcp server plugin, Add tools config examples . * [feat] mcp server plugin, Modify Body writer for POST request . * [feat] mcp server plugin, Modify rpc type when need do call. * [feat] mcp server plugin, Modify parameter format & support grpc. * [feat] mcp server plugin, fix streamable http after support custom message endpoint. * [feat] mcp server plugin, Modify javadoc for more. * [feat] mcp server plugin, fix check style. * [feat] mcp server plugin, use compositeTransportMap remove sseTransportMap & streamableHttpTransportMap. * [feat] mcp server plugin, reuse ObjectMapper & remove protocolMap. * [feat] mcp server plugin, fix mistakes for Copilot check.
1 parent aca751a commit 7de2558

File tree

14 files changed

+4272
-493
lines changed

14 files changed

+4272
-493
lines changed

shenyu-plugin/shenyu-plugin-mcp-server/MCP_TOOL_EXAMPLES.md

Lines changed: 492 additions & 0 deletions
Large diffs are not rendered by default.

shenyu-plugin/shenyu-plugin-mcp-server/MCP_TOOL_EXAMPLES_EN.md

Lines changed: 499 additions & 0 deletions
Large diffs are not rendered by default.

shenyu-plugin/shenyu-plugin-mcp-server/src/main/java/org/apache/shenyu/plugin/mcp/server/McpServerPlugin.java

Lines changed: 539 additions & 120 deletions
Large diffs are not rendered by default.

shenyu-plugin/shenyu-plugin-mcp-server/src/main/java/org/apache/shenyu/plugin/mcp/server/callback/ShenyuToolCallback.java

Lines changed: 556 additions & 125 deletions
Large diffs are not rendered by default.

shenyu-plugin/shenyu-plugin-mcp-server/src/main/java/org/apache/shenyu/plugin/mcp/server/handler/McpServerPluginDataHandler.java

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -46,30 +46,32 @@
4646
* The type McpServer plugin data handler.
4747
*/
4848
public class McpServerPluginDataHandler implements PluginDataHandler {
49-
50-
public static final Supplier<CommonHandleCache<String, ShenyuMcpServerTool>> CACHED_TOOL = new BeanHolder<>(
51-
CommonHandleCache::new);
52-
49+
5350
public static final Supplier<CommonHandleCache<String, ShenyuMcpServer>> CACHED_SERVER = new BeanHolder<>(
5451
CommonHandleCache::new);
55-
52+
53+
public static final Supplier<CommonHandleCache<String, ShenyuMcpServerTool>> CACHED_TOOL = new BeanHolder<>(
54+
CommonHandleCache::new);
55+
56+
private static final String DEFAULT_MESSAGE_ENDPOINT = "{\"messageEndpoint\":\"/message\"}";
57+
5658
private static final String SLASH = "/";
57-
59+
5860
private static final String STAR = "/**";
59-
61+
6062
private final ShenyuMcpServerManager shenyuMcpServerManager;
61-
63+
6264
public McpServerPluginDataHandler(
6365
final ShenyuMcpServerManager shenyuMcpServerManager) {
6466
this.shenyuMcpServerManager = shenyuMcpServerManager;
6567
}
66-
68+
6769
@Override
6870
public void handlerSelector(final SelectorData selectorData) {
6971
if (Objects.isNull(selectorData) || Objects.isNull(selectorData.getId())) {
7072
return;
7173
}
72-
74+
7375
if (CollectionUtils.isEmpty(selectorData.getConditionList())) {
7476
return;
7577
}
@@ -80,10 +82,10 @@ public void handlerSelector(final SelectorData selectorData) {
8082
.map(ConditionData::getParamValue)
8183
.findFirst()
8284
.orElse(null);
83-
85+
8486
String path = StringUtils.removeEnd(uri, SLASH);
8587
path = StringUtils.removeEnd(path, STAR);
86-
ShenyuMcpServer shenyuMcpServer = GsonUtils.getInstance().fromJson(selectorData.getHandle(), ShenyuMcpServer.class);
88+
ShenyuMcpServer shenyuMcpServer = GsonUtils.getInstance().fromJson(Objects.isNull(selectorData.getHandle()) ? DEFAULT_MESSAGE_ENDPOINT : selectorData.getHandle(), ShenyuMcpServer.class);
8789
shenyuMcpServer.setPath(path);
8890
CACHED_SERVER.get().cachedHandle(
8991
selectorData.getId(),
@@ -93,18 +95,18 @@ public void handlerSelector(final SelectorData selectorData) {
9395
if (StringUtils.isNotBlank(uri) && !shenyuMcpServerManager.hasMcpServer(uri)) {
9496
shenyuMcpServerManager.getOrCreateMcpServerTransport(uri, messageEndpoint);
9597
}
96-
98+
9799
// the update is also need to clean, but there is no way to
98100
// distinguish between crate and update, so it is always clean
99101
MetaDataCache.getInstance().clean();
100102
}
101-
103+
102104
@Override
103105
public void removeSelector(final SelectorData selectorData) {
104106
UpstreamCacheManager.getInstance().removeByKey(selectorData.getId());
105107
MetaDataCache.getInstance().clean();
106108
CACHED_TOOL.get().removeHandle(CacheKeyUtils.INST.getKey(selectorData.getId(), Constants.DEFAULT_RULE));
107-
109+
108110
// Remove the McpServer for this URI
109111
// First try to get URI from handle, then from condition list
110112
String uri = selectorData.getHandle();
@@ -116,14 +118,14 @@ public void removeSelector(final SelectorData selectorData) {
116118
.findFirst()
117119
.orElse(null);
118120
}
119-
121+
120122
CACHED_SERVER.get().removeHandle(selectorData.getId());
121-
123+
122124
if (StringUtils.isNotBlank(uri) && shenyuMcpServerManager.hasMcpServer(uri)) {
123125
shenyuMcpServerManager.removeMcpServer(uri);
124126
}
125127
}
126-
128+
127129
@Override
128130
public void handlerRule(final RuleData ruleData) {
129131
Optional.ofNullable(ruleData.getHandle()).ifPresent(s -> {
@@ -132,9 +134,9 @@ public void handlerRule(final RuleData ruleData) {
132134
// the update is also need to clean, but there is no way to
133135
// distinguish between crate and update, so it is always clean
134136
MetaDataCache.getInstance().clean();
135-
137+
136138
List<McpServerToolParameter> parameters = mcpServerTool.getParameters();
137-
139+
138140
// Create JSON schema from parameters
139141
String inputSchema = JsonSchemaUtil.createParameterSchema(parameters);
140142
ShenyuMcpServer server = CACHED_SERVER.get().obtainHandle(ruleData.getSelectorId());
@@ -148,7 +150,7 @@ public void handlerRule(final RuleData ruleData) {
148150
}
149151
});
150152
}
151-
153+
152154
@Override
153155
public void removeRule(final RuleData ruleData) {
154156
Optional.ofNullable(ruleData.getHandle()).ifPresent(s -> {
@@ -158,10 +160,10 @@ public void removeRule(final RuleData ruleData) {
158160
});
159161
MetaDataCache.getInstance().clean();
160162
}
161-
163+
162164
@Override
163165
public String pluginNamed() {
164166
return PluginEnum.MCP_SERVER.getName();
165167
}
166-
168+
167169
}

0 commit comments

Comments
 (0)