Skip to content
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions framework/fel/java/plugins/tool-mcp-client/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@
<groupId>org.fitframework.fel</groupId>
<artifactId>tool-mcp-client-service</artifactId>
</dependency>
<dependency>
<groupId>io.modelcontextprotocol.sdk</groupId>
<artifactId>mcp</artifactId>
<version>0.15.0</version>
</dependency>

<!-- Test -->
<dependency>
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -6,52 +6,63 @@

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

import static modelengine.fitframework.inspection.Validation.notNull;

import io.modelcontextprotocol.spec.McpSchema;
import modelengine.fel.tool.mcp.client.McpClient;
import modelengine.fel.tool.mcp.client.McpClientFactory;
import modelengine.fit.http.client.HttpClassicClient;
import modelengine.fit.http.client.HttpClassicClientFactory;
import modelengine.fitframework.annotation.Component;
import modelengine.fitframework.annotation.Fit;
import modelengine.fitframework.annotation.Value;
import modelengine.fitframework.serialization.ObjectSerializer;

import java.util.function.Consumer;
import java.util.function.Function;

/**
* Represents a factory for creating instances of the DefaultMcpClient.
* This class is responsible for initializing and configuring the HTTP client and JSON serializer
* required by the DefaultMcpClient.
* Represents a factory for creating instances of the {@link DefaultMcpStreamableClient}.
* This class is responsible for initializing and configuring.
*
* @author 季聿阶
* @since 2025-05-21
*/
@Component
public class DefaultMcpClientFactory implements McpClientFactory {
private final HttpClassicClient client;
private final ObjectSerializer jsonSerializer;
private final long pingInterval;
private final int requestTimeoutSeconds;

/**
* Constructs a new instance of the DefaultMcpClientFactory.
*
* @param clientFactory The factory used to create the HTTP client.
* @param jsonSerializer The JSON serializer used for serialization and deserialization.
* @param pingInterval The interval between ping requests. Units: milliseconds.
* @param requestTimeoutSeconds The timeout duration of requests. Units: seconds.
*/
public DefaultMcpClientFactory(HttpClassicClientFactory clientFactory,
@Fit(alias = "json") ObjectSerializer jsonSerializer,
@Value("${mcp.client.ping-interval}") long pingInterval) {
this.client = clientFactory.create(HttpClassicClientFactory.Config.builder()
.connectTimeout(30_000)
.socketTimeout(60_000)
.connectionRequestTimeout(60_000)
.build());
this.jsonSerializer = notNull(jsonSerializer, "The json serializer cannot be null.");
this.pingInterval = pingInterval;
public DefaultMcpClientFactory(@Value("${mcp.client.request.timeout-seconds}") int requestTimeoutSeconds) {
this.requestTimeoutSeconds = requestTimeoutSeconds > 0 ? requestTimeoutSeconds : 180;
}

@Override
public McpClient create(String baseUri, String sseEndpoint) {
return new DefaultMcpClient(this.jsonSerializer, this.client, baseUri, sseEndpoint, this.pingInterval);
return create(baseUri, sseEndpoint, DefaultMcpClientMessageHandler::defaultLoggingMessageHandler, null);
}

@Override
public McpClient create(String baseUri, String sseEndpoint,
Consumer<McpSchema.LoggingMessageNotification> loggingConsumer) {
return create(baseUri, sseEndpoint, loggingConsumer, null);
}

@Override
public McpClient create(String baseUri, String sseEndpoint,
Function<McpSchema.ElicitRequest, McpSchema.ElicitResult> elicitationHandler) {
return create(baseUri,
sseEndpoint,
DefaultMcpClientMessageHandler::defaultLoggingMessageHandler,
elicitationHandler);
}

@Override
public McpClient create(String baseUri, String sseEndpoint,
Consumer<McpSchema.LoggingMessageNotification> loggingConsumer,
Function<McpSchema.ElicitRequest, McpSchema.ElicitResult> elicitationHandler) {
return new DefaultMcpStreamableClient(baseUri,
sseEndpoint,
requestTimeoutSeconds,
loggingConsumer,
elicitationHandler);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) 2025 Huawei Technologies Co., Ltd. All rights reserved.
* This file is a part of the ModelEngine Project.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

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

import io.modelcontextprotocol.spec.McpSchema;
import modelengine.fitframework.annotation.Component;
import modelengine.fitframework.log.Logger;

import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

/**
* Handles MCP client messages received from MCP server,
* including logging notifications and elicitation requests.
*
* @author 黄可欣
* @since 2025-11-03
*/
@Component
public class DefaultMcpClientMessageHandler {
private static final Logger log = Logger.get(DefaultMcpClientMessageHandler.class);

/**
* Handles logging messages received from the MCP server.
*
* @param notification The {@link McpSchema.LoggingMessageNotification} containing the log level and data.
*/
public static void defaultLoggingMessageHandler(McpSchema.LoggingMessageNotification notification) {
log.info("Received logging message from MCP server. [level={}, data={}]",
notification.level(),
notification.data());
}
}
Loading