Skip to content

Commit a878028

Browse files
relat-ivity3200105739
andauthored
[FEL]MCP Streamable Client implement with Java MCP SDK (#361)
* MCP SDK Client first commit. * MCP SDK Client first commit. * 实现fit接口 * 因为jsonMapper问题暂时回退0.12.0版本 * SDK版本更新为0.15.0 * 格式化,加callTool错误日志更新 * 修改客户端默认超时时间 * 优化过长类 * 修改工厂类逻辑 * 添加测试,修改log格式 * 修改client和server部分日志输出 * 移除elicitation能力 * 恢复testcontroller * 删除testcontroller的log依赖 * 删除service的sdk依赖 * 声明线程不安全,以及加this. --------- Co-authored-by: 3200105739 <[email protected]>
1 parent c32b6cc commit a878028

File tree

11 files changed

+412
-566
lines changed

11 files changed

+412
-566
lines changed

framework/fel/java/plugins/tool-mcp-client/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@
3737
<groupId>org.fitframework.fel</groupId>
3838
<artifactId>tool-mcp-client-service</artifactId>
3939
</dependency>
40+
<dependency>
41+
<groupId>io.modelcontextprotocol.sdk</groupId>
42+
<artifactId>mcp</artifactId>
43+
<version>0.15.0</version>
44+
</dependency>
4045

4146
<!-- Test -->
4247
<dependency>

framework/fel/java/plugins/tool-mcp-client/src/main/java/modelengine/fel/tool/mcp/client/support/DefaultMcpClient.java

Lines changed: 0 additions & 429 deletions
This file was deleted.

framework/fel/java/plugins/tool-mcp-client/src/main/java/modelengine/fel/tool/mcp/client/support/DefaultMcpClientFactory.java

Lines changed: 7 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -6,52 +6,33 @@
66

77
package modelengine.fel.tool.mcp.client.support;
88

9-
import static modelengine.fitframework.inspection.Validation.notNull;
10-
119
import modelengine.fel.tool.mcp.client.McpClient;
1210
import modelengine.fel.tool.mcp.client.McpClientFactory;
13-
import modelengine.fit.http.client.HttpClassicClient;
14-
import modelengine.fit.http.client.HttpClassicClientFactory;
1511
import modelengine.fitframework.annotation.Component;
16-
import modelengine.fitframework.annotation.Fit;
1712
import modelengine.fitframework.annotation.Value;
18-
import modelengine.fitframework.serialization.ObjectSerializer;
1913

2014
/**
21-
* Represents a factory for creating instances of the DefaultMcpClient.
22-
* This class is responsible for initializing and configuring the HTTP client and JSON serializer
23-
* required by the DefaultMcpClient.
15+
* Represents a factory for creating instances of the {@link DefaultMcpStreamableClient}.
16+
* This class is responsible for initializing and configuring.
2417
*
2518
* @author 季聿阶
2619
* @since 2025-05-21
2720
*/
2821
@Component
2922
public class DefaultMcpClientFactory implements McpClientFactory {
30-
private final HttpClassicClient client;
31-
private final ObjectSerializer jsonSerializer;
32-
private final long pingInterval;
23+
private final int requestTimeoutSeconds;
3324

3425
/**
3526
* Constructs a new instance of the DefaultMcpClientFactory.
3627
*
37-
* @param clientFactory The factory used to create the HTTP client.
38-
* @param jsonSerializer The JSON serializer used for serialization and deserialization.
39-
* @param pingInterval The interval between ping requests. Units: milliseconds.
28+
* @param requestTimeoutSeconds The timeout duration of requests. Units: seconds.
4029
*/
41-
public DefaultMcpClientFactory(HttpClassicClientFactory clientFactory,
42-
@Fit(alias = "json") ObjectSerializer jsonSerializer,
43-
@Value("${mcp.client.ping-interval}") long pingInterval) {
44-
this.client = clientFactory.create(HttpClassicClientFactory.Config.builder()
45-
.connectTimeout(30_000)
46-
.socketTimeout(60_000)
47-
.connectionRequestTimeout(60_000)
48-
.build());
49-
this.jsonSerializer = notNull(jsonSerializer, "The json serializer cannot be null.");
50-
this.pingInterval = pingInterval;
30+
public DefaultMcpClientFactory(@Value("${mcp.client.request.timeout-seconds}") int requestTimeoutSeconds) {
31+
this.requestTimeoutSeconds = requestTimeoutSeconds > 0 ? requestTimeoutSeconds : 180;
5132
}
5233

5334
@Override
5435
public McpClient create(String baseUri, String sseEndpoint) {
55-
return new DefaultMcpClient(this.jsonSerializer, this.client, baseUri, sseEndpoint, this.pingInterval);
36+
return new DefaultMcpStreamableClient(baseUri, sseEndpoint, requestTimeoutSeconds);
5637
}
5738
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) 2025 Huawei Technologies Co., Ltd. All rights reserved.
3+
* This file is a part of the ModelEngine Project.
4+
* Licensed under the MIT License. See License.txt in the project root for license information.
5+
*--------------------------------------------------------------------------------------------*/
6+
7+
package modelengine.fel.tool.mcp.client.support;
8+
9+
import io.modelcontextprotocol.spec.McpSchema;
10+
import modelengine.fitframework.log.Logger;
11+
12+
/**
13+
* Handles MCP client messages received from MCP server,
14+
* including logging notifications and elicitation requests.
15+
*
16+
* @author 黄可欣
17+
* @since 2025-11-03
18+
*/
19+
public class DefaultMcpClientLogHandler {
20+
private static final Logger log = Logger.get(DefaultMcpClientLogHandler.class);
21+
private final String clientId;
22+
23+
/**
24+
* Constructs a new instance of DefaultMcpClientLogHandler.
25+
*
26+
* @param clientId The unique identifier of the MCP client.
27+
*/
28+
public DefaultMcpClientLogHandler(String clientId) {
29+
this.clientId = clientId;
30+
}
31+
32+
/**
33+
* Handles logging messages received from the MCP server.
34+
* Includes the client UUID in the log message for tracking.
35+
*
36+
* @param notification The {@link McpSchema.LoggingMessageNotification} containing the log level and data.
37+
*/
38+
public void handleLoggingMessage(McpSchema.LoggingMessageNotification notification) {
39+
log.info("Received logging message from MCP server. [clientId={}, level={}, data={}]",
40+
this.clientId,
41+
notification.level(),
42+
notification.data());
43+
}
44+
}

0 commit comments

Comments
 (0)