Skip to content

Commit 9d5e552

Browse files
author
“â黄可欣
committed
添加测试,修改log格式
1 parent c38ae25 commit 9d5e552

File tree

5 files changed

+146
-52
lines changed

5 files changed

+146
-52
lines changed

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

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,18 @@ public McpClient create(String baseUri, String sseEndpoint) {
4141
}
4242

4343
@Override
44-
public McpClient create(String baseUri, String sseEndpoint, Consumer<McpSchema.LoggingMessageNotification> loggingConsumer) {
44+
public McpClient create(String baseUri, String sseEndpoint,
45+
Consumer<McpSchema.LoggingMessageNotification> loggingConsumer) {
4546
return create(baseUri, sseEndpoint, loggingConsumer, null);
4647
}
4748

4849
@Override
49-
public McpClient create(String baseUri, String sseEndpoint, Function<McpSchema.ElicitRequest, McpSchema.ElicitResult> elicitationHandler) {
50-
return create(baseUri, sseEndpoint, DefaultMcpClientMessageHandler::defaultLoggingMessageHandler, elicitationHandler);
50+
public McpClient create(String baseUri, String sseEndpoint,
51+
Function<McpSchema.ElicitRequest, McpSchema.ElicitResult> elicitationHandler) {
52+
return create(baseUri,
53+
sseEndpoint,
54+
DefaultMcpClientMessageHandler::defaultLoggingMessageHandler,
55+
elicitationHandler);
5156
}
5257

5358
@Override

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ public class DefaultMcpClientMessageHandler {
3131
* @param notification The {@link McpSchema.LoggingMessageNotification} containing the log level and data.
3232
*/
3333
public static void defaultLoggingMessageHandler(McpSchema.LoggingMessageNotification notification) {
34-
log.info("[Client] log: {}-{}", notification.level(), notification.data());
34+
log.info("Received logging message from MCP server. [level={}, data={}]",
35+
notification.level(),
36+
notification.data());
3537
}
3638
}

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

Lines changed: 48 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ public DefaultMcpStreamableClient(String baseUri, String sseEndpoint, int reques
5858
this.clientId = UUID.randomUUID().toString();
5959
notBlank(baseUri, "The MCP server base URI cannot be blank.");
6060
notBlank(sseEndpoint, "The MCP server SSE endpoint cannot be blank.");
61-
log.info("Creating MCP client [{}] for server: {}", clientId, baseUri);
61+
log.info("Creating MCP client. [clientId={}, baseUri={}]", clientId, baseUri);
6262
ObjectMapper mapper = new ObjectMapper();
6363
HttpClientStreamableHttpTransport transport = HttpClientStreamableHttpTransport.builder(baseUri)
6464
.jsonMapper(new JacksonMcpJsonMapper(mapper))
@@ -99,7 +99,7 @@ public void initialize() {
9999
ensureNotClosed();
100100
mcpSyncClient.initialize();
101101
this.initialized = true;
102-
log.info("MCP client [{}] initialized successfully.", clientId);
102+
log.info("MCP client initialized successfully. [clientId={}]", clientId);
103103
}
104104

105105
/**
@@ -112,22 +112,23 @@ public void initialize() {
112112
@Override
113113
public List<Tool> getTools() {
114114
ensureReady();
115-
116115
try {
117116
McpSchema.ListToolsResult result = this.mcpSyncClient.listTools();
118117
if (result == null || result.tools() == null) {
119-
log.warn("MCP client [{}] failed to get tools: result is null.", clientId);
118+
log.warn("Failed to get tools: result is null. [clientId={}]", clientId);
120119
throw new IllegalStateException("Failed to get tools from MCP server: result is null.");
121120
}
122121

123122
List<Tool> tools = result.tools().stream().map(this::convertToFelTool).collect(Collectors.toList());
124123

125-
log.info("MCP client [{}] successfully retrieved {} tools.", clientId, tools.size());
126-
tools.forEach(tool -> log.debug("Tool - Name: {}, Description: {}", tool.getName(), tool.getDescription()));
124+
log.info("Successfully retrieved tools. [clientId={}, count={}]", clientId, tools.size());
125+
tools.forEach(tool -> log.debug("Tool information. [name={}, description={}]",
126+
tool.getName(),
127+
tool.getDescription()));
127128
return tools;
128129
} catch (Exception e) {
129-
log.error("MCP client [{}] failed to get tools: {}", clientId, e);
130-
throw new IllegalStateException("Failed to get tools from MCP server: " + e.getMessage(), e);
130+
log.error("Failed to get tools. [clientId={}, error={}]", clientId, e.getMessage());
131+
throw new IllegalStateException("Failed to get tools from MCP server. [error=" + e.getMessage() + "]", e);
131132
}
132133
}
133134

@@ -146,39 +147,20 @@ public List<Tool> getTools() {
146147
public Object callTool(String name, Map<String, Object> arguments) {
147148
ensureReady();
148149
try {
149-
log.info("MCP client [{}] calling tool: {} with arguments: {}", clientId, name, arguments);
150+
log.info("Calling tool. [clientId={}, name={}, arguments={}]", clientId, name, arguments);
150151
McpSchema.CallToolResult result =
151152
this.mcpSyncClient.callTool(new McpSchema.CallToolRequest(name, arguments));
152153

153154
if (result == null) {
154-
log.error("MCP client [{}] failed to call tool '{}': result is null.", clientId, name);
155-
throw new IllegalStateException("Failed to call tool '" + name + "': result is null.");
155+
log.error("Failed to call tool: result is null. [clientId={}, name={}]", clientId, name);
156+
throw new IllegalStateException("Failed to call tool: result is null. [name=" + name + "]");
156157
}
157158
return processToolResult(result, name);
158159
} catch (Exception e) {
159-
log.error("MCP client [{}] failed to call tool '{}': {}", clientId, name, e);
160-
throw new IllegalStateException("Failed to call tool '" + name + "': " + e.getMessage(), e);
161-
}
162-
}
163-
164-
/**
165-
* Builds an error message from tool result content.
166-
*
167-
* @param name The name of the tool that was called.
168-
* @param content The content list from the tool result.
169-
* @return The formatted error message.
170-
*/
171-
private String buildToolErrorMessage(String name, List<McpSchema.Content> content) {
172-
String errorMsg = "Tool '" + name + "' returned an error";
173-
if (content != null && !content.isEmpty()) {
174-
McpSchema.Content errorContent = content.get(0);
175-
if (errorContent instanceof McpSchema.TextContent textContent) {
176-
errorMsg += ": " + textContent.text();
177-
} else {
178-
errorMsg += ": " + errorContent;
179-
}
160+
log.error("Failed to call tool. [clientId={}, name={}, error={}]", clientId, name, e.getMessage());
161+
throw new IllegalStateException("Failed to call tool. [name=" + name + ", error=" + e.getMessage() + "]",
162+
e);
180163
}
181-
return errorMsg;
182164
}
183165

184166
/**
@@ -194,25 +176,29 @@ private String buildToolErrorMessage(String name, List<McpSchema.Content> conten
194176
*/
195177
private Object processToolResult(McpSchema.CallToolResult result, String name) {
196178
if (result.isError() != null && result.isError()) {
197-
String errorMsg = buildToolErrorMessage(name, result.content());
198-
log.error("MCP client [{}]: {}", clientId, errorMsg);
199-
throw new IllegalStateException(errorMsg);
179+
String errorDetails = extractErrorDetails(result.content());
180+
log.error("Tool returned an error. [clientId={}, name={}, details={}]", clientId, name, errorDetails);
181+
throw new IllegalStateException(
182+
"Tool returned an error. [name=" + name + ", details=" + errorDetails + "]");
200183
}
201184

202185
if (result.content() == null || result.content().isEmpty()) {
203-
log.warn("MCP client [{}] tool '{}' returned empty content.", clientId, name);
186+
log.warn("Tool returned empty content. [clientId={}, name={}]", clientId, name);
204187
return null;
205188
}
206189

207190
Object content = result.content().get(0);
208191
if (content instanceof McpSchema.TextContent textContent) {
209-
log.info("MCP client [{}] successfully called tool '{}', result: {}", clientId, name, textContent.text());
192+
log.info("Successfully called tool. [clientId={}, name={}, result={}]", clientId, name, textContent.text());
210193
return textContent.text();
211194
} else if (content instanceof McpSchema.ImageContent imageContent) {
212-
log.info("MCP client [{}] successfully called tool '{}', returned image content.", clientId, name);
195+
log.info("Successfully called tool: image content. [clientId={}, name={}]", clientId, name);
213196
return imageContent;
214197
} else {
215-
log.info("MCP client [{}] successfully called tool '{}', content type: {}", clientId, name, content.getClass().getSimpleName());
198+
log.info("Successfully called tool. [clientId={}, name={}, contentType={}]",
199+
clientId,
200+
name,
201+
content.getClass().getSimpleName());
216202
return content;
217203
}
218204
}
@@ -227,7 +213,7 @@ public void close() throws IOException {
227213
ensureNotClosed();
228214
this.closed = true;
229215
this.mcpSyncClient.closeGracefully();
230-
log.info("MCP client [{}] closed.", clientId);
216+
log.info("MCP client closed. [clientId={}]", clientId);
231217
}
232218

233219
/**
@@ -265,7 +251,7 @@ private Tool convertToFelTool(McpSchema.Tool mcpTool) {
265251
*/
266252
private void ensureNotClosed() {
267253
if (this.closed) {
268-
throw new IllegalStateException("The MCP client is closed.");
254+
throw new IllegalStateException("The MCP client is closed. [clientId=" + clientId + "]");
269255
}
270256
}
271257

@@ -277,7 +263,26 @@ private void ensureNotClosed() {
277263
private void ensureReady() {
278264
ensureNotClosed();
279265
if (!this.initialized) {
280-
throw new IllegalStateException("MCP client is not initialized. Please wait a moment.");
266+
throw new IllegalStateException(
267+
"MCP client is not initialized. Please wait a moment. [clientId=" + clientId + "]");
268+
}
269+
}
270+
271+
/**
272+
* Extracts error details from tool result content.
273+
*
274+
* @param content The content list from the tool result.
275+
* @return The error details as a string.
276+
*/
277+
private String extractErrorDetails(List<McpSchema.Content> content) {
278+
if (content != null && !content.isEmpty()) {
279+
McpSchema.Content errorContent = content.get(0);
280+
if (errorContent instanceof McpSchema.TextContent textContent) {
281+
return textContent.text();
282+
} else {
283+
return errorContent.toString();
284+
}
281285
}
286+
return "";
282287
}
283288
}

framework/fel/java/plugins/tool-mcp-test/src/main/java/modelengine/fel/tool/mcp/test/TestController.java

Lines changed: 83 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
package modelengine.fel.tool.mcp.test;
88

9+
import io.modelcontextprotocol.spec.McpSchema;
910
import modelengine.fel.tool.mcp.client.McpClient;
1011
import modelengine.fel.tool.mcp.client.McpClientFactory;
1112
import modelengine.fel.tool.mcp.entity.Tool;
@@ -15,8 +16,10 @@
1516
import modelengine.fit.http.annotation.RequestMapping;
1617
import modelengine.fit.http.annotation.RequestQuery;
1718
import modelengine.fitframework.annotation.Component;
19+
import modelengine.fitframework.log.Logger;
1820

1921
import java.io.IOException;
22+
import java.util.HashMap;
2023
import java.util.List;
2124
import java.util.Map;
2225

@@ -30,6 +33,8 @@
3033
@Component
3134
@RequestMapping(path = "/mcp-test")
3235
public class TestController {
36+
private static final Logger log = Logger.get(TestController.class);
37+
3338
private final McpClientFactory mcpClientFactory;
3439
private McpClient client;
3540

@@ -43,10 +48,12 @@ public TestController(McpClientFactory mcpClientFactory) {
4348
}
4449

4550
/**
46-
* Initializes the MCP client by creating an instance using the provided factory and initializing it.
47-
* This method sets up the connection to the MCP server and prepares it for further interactions.
51+
* Initializes the MCP client with default settings (default logging, no elicitation).
52+
* This method creates an instance using the provided factory and initializes it.
4853
*
49-
* @return A string indicating that the initialization was successful.
54+
* @param baseUri The base URI of the MCP server.
55+
* @param sseEndpoint The SSE endpoint of the MCP server.
56+
* @return A map with clientId and status message.
5057
*/
5158
@PostMapping(path = "/initialize")
5259
public String initialize(@RequestQuery(name = "baseUri") String baseUri,
@@ -56,6 +63,55 @@ public String initialize(@RequestQuery(name = "baseUri") String baseUri,
5663
return "Initialized";
5764
}
5865

66+
/**
67+
* Initializes the MCP client with custom logging consumer but without elicitation.
68+
* This demonstrates using a custom logging handler.
69+
*
70+
* @param baseUri The base URI of the MCP server.
71+
* @param sseEndpoint The SSE endpoint of the MCP server.
72+
* @return A string indicating that the initialization was successful.
73+
*/
74+
@PostMapping(path = "/initialize-with-log")
75+
public String initializeWithCustomLogging(@RequestQuery(name = "baseUri") String baseUri,
76+
@RequestQuery(name = "sseEndpoint") String sseEndpoint) {
77+
this.client = this.mcpClientFactory.create(baseUri, sseEndpoint, this::loggingConsumer);
78+
this.client.initialize();
79+
return "Initialized with custom logging";
80+
}
81+
82+
/**
83+
* Initializes the MCP client with elicitation capability.
84+
* This demonstrates enabling elicitation with default logging.
85+
*
86+
* @param baseUri The base URI of the MCP server.
87+
* @param sseEndpoint The SSE endpoint of the MCP server.
88+
* @return A string indicating that the initialization was successful.
89+
*/
90+
@PostMapping(path = "/initialize-with-elicitation")
91+
public String initializeWithElicitation(@RequestQuery(name = "baseUri") String baseUri,
92+
@RequestQuery(name = "sseEndpoint") String sseEndpoint) {
93+
this.client = this.mcpClientFactory.create(baseUri, sseEndpoint, this::elicitationHandler);
94+
this.client.initialize();
95+
return "Initialized with elicitation";
96+
}
97+
98+
/**
99+
* Initializes the MCP client with both custom logging and elicitation.
100+
* This demonstrates full customization of the client.
101+
*
102+
* @param baseUri The base URI of the MCP server.
103+
* @param sseEndpoint The SSE endpoint of the MCP server.
104+
* @return A string indicating that the initialization was successful.
105+
*/
106+
@PostMapping(path = "/initialize-full")
107+
public String initializeFullCustom(@RequestQuery(name = "baseUri") String baseUri,
108+
@RequestQuery(name = "sseEndpoint") String sseEndpoint) {
109+
this.client =
110+
this.mcpClientFactory.create(baseUri, sseEndpoint, this::loggingConsumer, this::elicitationHandler);
111+
this.client.initialize();
112+
return "Initialized with full customization";
113+
}
114+
59115
/**
60116
* Closes the MCP client and releases any resources associated with it.
61117
* This method ensures that the MCP client is properly closed and resources are released.
@@ -95,4 +151,28 @@ public List<Tool> toolsList() {
95151
public Object toolsCall(@RequestQuery(name = "name") String name, @RequestBody Map<String, Object> jsonArgs) {
96152
return this.client.callTool(name, jsonArgs);
97153
}
154+
155+
/**
156+
* Custom logging consumer for MCP client.
157+
*
158+
* @param notification The logging message notification from MCP server.
159+
*/
160+
private void loggingConsumer(McpSchema.LoggingMessageNotification notification) {
161+
log.info("Custom logging handler received message. [level={}, data={}]",
162+
notification.level(),
163+
notification.data());
164+
}
165+
166+
/**
167+
* Elicitation handler for MCP client.
168+
*
169+
* @param request The elicitation request from MCP server.
170+
* @return The elicitation result with action and user data.
171+
*/
172+
private McpSchema.ElicitResult elicitationHandler(McpSchema.ElicitRequest request) {
173+
log.info("Elicitation request received. [message={}, schema={}]", request.message(), request.requestedSchema());
174+
Map<String, Object> userData = new HashMap<>();
175+
userData.put("response", "Auto-accepted by test controller");
176+
return new McpSchema.ElicitResult(McpSchema.ElicitResult.Action.ACCEPT, userData);
177+
}
98178
}

framework/fel/java/services/tool-mcp-client-service/src/main/java/modelengine/fel/tool/mcp/client/McpClientFactory.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ public interface McpClientFactory {
3737
* @param loggingConsumer The consumer to handle logging messages from the MCP server.
3838
* @return The connected {@link McpClient} instance with custom logging consumer but without elicitation ability.
3939
*/
40-
McpClient create(String baseUri, String sseEndpoint, Consumer<McpSchema.LoggingMessageNotification> loggingConsumer);
40+
McpClient create(String baseUri, String sseEndpoint,
41+
Consumer<McpSchema.LoggingMessageNotification> loggingConsumer);
4142

4243
/**
4344
* Creates a {@link McpClient} instance with default logging consumer and elicitation ability.
@@ -47,7 +48,8 @@ public interface McpClientFactory {
4748
* @param elicitationHandler The function to handle elicitation requests from the MCP server.
4849
* @return The connected {@link McpClient} instance with default logging consumer and elicitation ability.
4950
*/
50-
McpClient create(String baseUri, String sseEndpoint, Function<McpSchema.ElicitRequest, McpSchema.ElicitResult> elicitationHandler);
51+
McpClient create(String baseUri, String sseEndpoint,
52+
Function<McpSchema.ElicitRequest, McpSchema.ElicitResult> elicitationHandler);
5153

5254
/**
5355
* Creates a {@link McpClient} instance with custom message handlers and elicitation ability.

0 commit comments

Comments
 (0)