66
77package modelengine .fel .tool .mcp .client .support ;
88
9+ import static modelengine .fitframework .inspection .Validation .notBlank ;
10+
911import com .fasterxml .jackson .databind .ObjectMapper ;
12+
1013import io .modelcontextprotocol .client .McpSyncClient ;
1114import io .modelcontextprotocol .client .transport .HttpClientStreamableHttpTransport ;
12- import io .modelcontextprotocol .json .McpJsonMapper ;
1315import io .modelcontextprotocol .json .jackson .JacksonMcpJsonMapper ;
14- import io .modelcontextprotocol .json .schema .JsonSchemaValidator ;
1516import io .modelcontextprotocol .json .schema .jackson .DefaultJsonSchemaValidator ;
1617import io .modelcontextprotocol .spec .McpSchema ;
1718import modelengine .fel .tool .mcp .client .McpClient ;
2526import java .util .Map ;
2627import java .util .stream .Collectors ;
2728
28- import static modelengine .fitframework .inspection .Validation .notBlank ;
29-
3029/**
3130 * A default implementation of the MCP client that uses the MCP SDK's streamable HTTP transport.
3231 *
@@ -57,9 +56,7 @@ public DefaultMcpStreamableClient(String baseUri, String sseEndpoint, int reques
5756 .build ();
5857 this .mcpSyncClient = io .modelcontextprotocol .client .McpClient .sync (transport )
5958 .requestTimeout (Duration .ofSeconds (requestTimeoutSeconds > 0 ? requestTimeoutSeconds : 5 ))
60- .capabilities (McpSchema .ClientCapabilities .builder ()
61- .elicitation ()
62- .build ())
59+ .capabilities (McpSchema .ClientCapabilities .builder ().elicitation ().build ())
6360 .loggingConsumer (McpClientMessageHandler ::handleLoggingMessage )
6461 .elicitation (McpClientMessageHandler ::handleElicitationRequest )
6562 .jsonSchemaValidator (new DefaultJsonSchemaValidator (mapper ))
@@ -96,18 +93,16 @@ public List<Tool> getTools() {
9693 if (!this .initialized ) {
9794 throw new IllegalStateException ("MCP client is not initialized. Please wait a moment." );
9895 }
99-
96+
10097 try {
10198 McpSchema .ListToolsResult result = this .mcpSyncClient .listTools ();
10299 if (result == null || result .tools () == null ) {
103100 log .warn ("Failed to get tools from MCP server: result is null." );
104101 throw new IllegalStateException ("Failed to get tools from MCP server: result is null." );
105102 }
106-
107- List <Tool > tools = result .tools ().stream ()
108- .map (this ::convertToFelTool )
109- .collect (Collectors .toList ());
110-
103+
104+ List <Tool > tools = result .tools ().stream ().map (this ::convertToFelTool ).collect (Collectors .toList ());
105+
111106 log .info ("Successfully retrieved {} tools from MCP server." , tools .size ());
112107 tools .forEach (tool -> log .info ("Tool - Name: {}, Description: {}" , tool .getName (), tool .getDescription ()));
113108 return tools ;
@@ -136,24 +131,31 @@ public Object callTool(String name, Map<String, Object> arguments) {
136131 if (!this .initialized ) {
137132 throw new IllegalStateException ("MCP client is not initialized. Please wait a moment." );
138133 }
139-
134+
140135 try {
141136 log .info ("Calling tool: {} with arguments: {}" , name , arguments );
142- McpSchema .CallToolResult result = this .mcpSyncClient .callTool (
143- new McpSchema .CallToolRequest (name , arguments )
144- );
145-
137+ McpSchema .CallToolResult result =
138+ this .mcpSyncClient .callTool (new McpSchema .CallToolRequest (name , arguments ));
139+
146140 if (result == null ) {
147141 log .error ("Failed to call tool '{}': result is null." , name );
148142 throw new IllegalStateException ("Failed to call tool '" + name + "': result is null." );
149143 }
150144
151145 if (result .isError () != null && result .isError ()) {
152- String errorMsg = "Tool '" + name + "' returned an error." ;
146+ String errorMsg = "Tool '" + name + "' returned an error" ;
147+ if (result .content () != null && !result .content ().isEmpty ()) {
148+ Object errorContent = result .content ().get (0 );
149+ if (errorContent instanceof McpSchema .TextContent textContent ) {
150+ errorMsg += ": " + textContent .text ();
151+ } else {
152+ errorMsg += ": " + errorContent ;
153+ }
154+ }
153155 log .error (errorMsg );
154156 throw new IllegalStateException (errorMsg );
155157 }
156-
158+
157159 if (result .content () == null || result .content ().isEmpty ()) {
158160 log .warn ("Tool '{}' returned empty content." , name );
159161 return null ;
@@ -170,7 +172,7 @@ public Object callTool(String name, Map<String, Object> arguments) {
170172 log .info ("Successfully called tool '{}', content type: {}" , name , content .getClass ().getSimpleName ());
171173 return content ;
172174 }
173-
175+
174176 } catch (Exception e ) {
175177 log .error ("Failed to call tool '{}' from MCP server." , name , e );
176178 throw new IllegalStateException ("Failed to call tool '" + name + "': " + e .getMessage (), e );
0 commit comments