Improve the the MCP server demo code
This commit is contained in:
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.ai.mcp.sample.webmvc.client;
|
||||
package org.springframework.ai.mcp.sample.servlet.client;
|
||||
|
||||
import org.springframework.ai.mcp.client.transport.ServerParameters;
|
||||
import org.springframework.ai.mcp.client.transport.StdioClientTransport;
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.ai.mcp.sample.webmvc.client;
|
||||
package org.springframework.ai.mcp.sample.servlet.client;
|
||||
|
||||
import org.springframework.ai.mcp.client.transport.HttpClientSseClientTransport;
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.ai.mcp.sample.webmvc.client;
|
||||
package org.springframework.ai.mcp.sample.servlet.client;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@@ -50,15 +50,12 @@ public class SampleClient {
|
||||
ListToolsResult toolsList = client.listTools();
|
||||
System.out.println("Available Tools = " + toolsList);
|
||||
|
||||
CallToolResult weatherResponse = client.callTool(new CallToolRequest("weather", Map.of("city", "Sofia")));
|
||||
System.out.println("Weather Response = " + weatherResponse);
|
||||
CallToolResult upperCaseResult = client
|
||||
.callTool(new CallToolRequest("toUpperCase", Map.of("input", "accountName")));
|
||||
System.out.println("Upper case Response = " + upperCaseResult);
|
||||
|
||||
CallToolResult paymentStatus = client.callTool(
|
||||
new CallToolRequest("paymentTransactionStatus", Map.of("transactionId", "006", "accountName", "John")));
|
||||
System.out.println("Payment Status Response = " + paymentStatus);
|
||||
|
||||
CallToolResult parks = client.callTool(new CallToolRequest("getBooks", Map.of("title", "Spring Framework")));
|
||||
System.out.println("Books Response = " + parks);
|
||||
CallToolResult books = client.callTool(new CallToolRequest("getBooks", Map.of("title", "Spring Framework")));
|
||||
System.out.println("Books Response = " + books);
|
||||
|
||||
// List and demonstrate resources
|
||||
var resourcesList = client.listResources();
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.springframework.ai.mcp.sample.webmvc.server;
|
||||
package org.springframework.ai.mcp.sample.servlet.server;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -16,9 +16,7 @@ import org.springframework.ai.mcp.server.McpServer.ToolRegistration;
|
||||
import org.springframework.ai.mcp.server.transport.HttpServletSseServerTransport;
|
||||
import org.springframework.ai.mcp.server.transport.StdioServerTransport;
|
||||
import org.springframework.ai.mcp.spec.McpSchema;
|
||||
import org.springframework.ai.mcp.spec.McpSchema.CallToolResult;
|
||||
import org.springframework.ai.mcp.spec.McpSchema.GetPromptResult;
|
||||
import org.springframework.ai.mcp.spec.McpSchema.LoggingMessageNotification;
|
||||
import org.springframework.ai.mcp.spec.McpSchema.PromptMessage;
|
||||
import org.springframework.ai.mcp.spec.McpSchema.Role;
|
||||
import org.springframework.ai.mcp.spec.McpSchema.TextContent;
|
||||
@@ -74,32 +72,19 @@ public class McpServerConfig implements WebMvcConfigurer {
|
||||
|
||||
// Create the server with both tool and resource capabilities
|
||||
var server = McpServer.using(transport)
|
||||
.serverInfo("MCP Demo Server", "1.0.0")
|
||||
.serverInfo("MCP Demo Servlet Server", "1.0.0")
|
||||
.capabilities(capabilities)
|
||||
.resources(systemInfoResourceRegistration())
|
||||
.prompts(greetingPromptRegistration())
|
||||
.tools(
|
||||
ToolHelper.toToolRegistration(
|
||||
FunctionCallback.builder()
|
||||
.method("paymentTransactionStatus",String.class, String.class)
|
||||
.description("Get transaction payment status")
|
||||
.targetClass(McpServerConfig.class)
|
||||
.build()),
|
||||
ToolHelper.toToolRegistration(
|
||||
FunctionCallback.builder()
|
||||
.function("toUpperCase", new Function<ToUpperCaseInput, String>() {
|
||||
@Override
|
||||
public String apply(ToUpperCaseInput s) {
|
||||
return s.input().toUpperCase();
|
||||
}
|
||||
})
|
||||
.function("toUpperCase", (Function<ToUpperCaseInput, String>) s -> s.input().toUpperCase())
|
||||
.description("To upper case")
|
||||
.inputType(ToUpperCaseInput.class)
|
||||
.build()))
|
||||
.tools(openLibraryToolRegistrations(openLibrary))
|
||||
.async();
|
||||
|
||||
server.addTool(weatherToolRegistration(server));
|
||||
.async();
|
||||
return server; // @formatter:on
|
||||
} // @formatter:on
|
||||
|
||||
@@ -172,40 +157,6 @@ public class McpServerConfig implements WebMvcConfigurer {
|
||||
});
|
||||
}
|
||||
|
||||
private static ToolRegistration weatherToolRegistration(McpAsyncServer server) {
|
||||
String emptyJsonSchema = """
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"type": "object",
|
||||
"properties": {"city" : "string"}
|
||||
}
|
||||
""";
|
||||
return new ToolRegistration(new McpSchema.Tool("weather", "Weather forecast tool by location", emptyJsonSchema),
|
||||
(arguments) -> {
|
||||
String city = (String) arguments.get("city");
|
||||
|
||||
// Create the result
|
||||
var result = new CallToolResult(
|
||||
List.of(new TextContent("Weather forecast for " + city + " is sunny")), false);
|
||||
|
||||
// Send the logging notification and ignore its completion
|
||||
server
|
||||
.loggingNotification(LoggingMessageNotification.builder()
|
||||
.data("This is a log message from the weather tool")
|
||||
.build())
|
||||
.subscribe(null, error -> {
|
||||
// Log any errors but don't fail the operation
|
||||
logger.error("Failed to send logging notification", error);
|
||||
});
|
||||
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
public static String paymentTransactionStatus(String transactionId, String accountName) {
|
||||
return "The status for " + transactionId + ", by " + accountName + " is PENDING";
|
||||
}
|
||||
|
||||
@Bean
|
||||
public OpenLibrary openLibrary() {
|
||||
return new OpenLibrary(RestClient.builder());
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.springframework.ai.mcp.sample.webmvc.server;
|
||||
package org.springframework.ai.mcp.sample.servlet.server;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.ai.mcp.sample.webmvc.server;
|
||||
package org.springframework.ai.mcp.sample.servlet.server;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -50,19 +50,12 @@ public class SampleClient {
|
||||
ListToolsResult toolsList = client.listTools();
|
||||
System.out.println("Available Tools = " + toolsList);
|
||||
|
||||
CallToolResult weatherResponse = client.callTool(new CallToolRequest("weather", Map.of("city", "Sofia")));
|
||||
System.out.println("Weather Response = " + weatherResponse);
|
||||
CallToolResult upperCaseResult = client
|
||||
.callTool(new CallToolRequest("toUpperCase", Map.of("input", "accountName")));
|
||||
System.out.println("Upper case Response = " + upperCaseResult);
|
||||
|
||||
CallToolResult calcResponse = client
|
||||
.callTool(new CallToolRequest("calculator", Map.of("operation", "multiply", "a", 2.0, "b", 3.0)));
|
||||
System.out.println("Calculator Response = " + calcResponse);
|
||||
|
||||
CallToolResult paymentStatus = client.callTool(
|
||||
new CallToolRequest("paymentTransactionStatus", Map.of("transactionId", "006", "accountName", "John")));
|
||||
System.out.println("Payment Status Response = " + paymentStatus);
|
||||
|
||||
CallToolResult parks = client.callTool(new CallToolRequest("getBooks", Map.of("title", "Spring Framework")));
|
||||
System.out.println("Books Response = " + parks);
|
||||
CallToolResult books = client.callTool(new CallToolRequest("getBooks", Map.of("title", "Spring Framework")));
|
||||
System.out.println("Books Response = " + books);
|
||||
|
||||
// List and demonstrate resources
|
||||
var resourcesList = client.listResources();
|
||||
|
||||
@@ -74,33 +74,19 @@ public class McpServerConfig {
|
||||
|
||||
// Create the server with both tool and resource capabilities
|
||||
var server = McpServer.using(transport)
|
||||
.serverInfo("MCP Demo Server", "1.0.0")
|
||||
.serverInfo("MCP Demo WebFlux Server", "1.0.0")
|
||||
.capabilities(capabilities)
|
||||
.resources(systemInfoResourceRegistration())
|
||||
.prompts(greetingPromptRegistration())
|
||||
.tools(calculatorToolRegistration(),
|
||||
ToolHelper.toToolRegistration(
|
||||
.resources(systemInfoResourceRegistration()) // Resources
|
||||
.prompts(greetingPromptRegistration()) // Prompts
|
||||
.tools(openLibraryToolRegistrations(openLibrary)) // Method based tools
|
||||
.tools(ToolHelper.toToolRegistration( // java.util.Function based tools
|
||||
FunctionCallback.builder()
|
||||
.method("paymentTransactionStatus",String.class, String.class)
|
||||
.description("Get transaction payment status")
|
||||
.targetClass(McpServerConfig.class)
|
||||
.build()),
|
||||
ToolHelper.toToolRegistration(
|
||||
FunctionCallback.builder()
|
||||
.function("toUpperCase", new Function<ToUpperCaseInput, String>() {
|
||||
@Override
|
||||
public String apply(ToUpperCaseInput s) {
|
||||
return s.input().toUpperCase();
|
||||
}
|
||||
})
|
||||
.function("toUpperCase", (Function<ToUpperCaseInput, String>) s -> s.input().toUpperCase())
|
||||
.description("To upper case")
|
||||
.inputType(ToUpperCaseInput.class)
|
||||
.build())
|
||||
)
|
||||
.tools(openLibraryToolRegistrations(openLibrary))
|
||||
.build()))
|
||||
.async();
|
||||
|
||||
server.addTool(weatherToolRegistration(server));
|
||||
return server; // @formatter:on
|
||||
} // @formatter:on
|
||||
|
||||
@@ -173,96 +159,6 @@ public class McpServerConfig {
|
||||
});
|
||||
}
|
||||
|
||||
private static ToolRegistration weatherToolRegistration(McpAsyncServer server) {
|
||||
String emptyJsonSchema = """
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"type": "object",
|
||||
"properties": {"city" : "string"}
|
||||
}
|
||||
""";
|
||||
return new ToolRegistration(new McpSchema.Tool("weather", "Weather forecast tool by location", emptyJsonSchema),
|
||||
(arguments) -> {
|
||||
String city = (String) arguments.get("city");
|
||||
|
||||
// Create the result
|
||||
var result = new CallToolResult(
|
||||
List.of(new TextContent("Weather forecast for " + city + " is sunny")), false);
|
||||
|
||||
// Send the logging notification and ignore its completion
|
||||
server
|
||||
.loggingNotification(LoggingMessageNotification.builder()
|
||||
.data("This is a log message from the weather tool")
|
||||
.build())
|
||||
.subscribe(null, error -> {
|
||||
// Log any errors but don't fail the operation
|
||||
logger.error("Failed to send logging notification", error);
|
||||
});
|
||||
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
private static ToolRegistration calculatorToolRegistration() {
|
||||
return new ToolRegistration(new McpSchema.Tool("calculator",
|
||||
"Performs basic arithmetic operations (add, subtract, multiply, divide)", """
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"operation": {
|
||||
"type": "string",
|
||||
"enum": ["add", "subtract", "multiply", "divide"],
|
||||
"description": "The arithmetic operation to perform"
|
||||
},
|
||||
"a": {
|
||||
"type": "number",
|
||||
"description": "First operand"
|
||||
},
|
||||
"b": {
|
||||
"type": "number",
|
||||
"description": "Second operand"
|
||||
}
|
||||
},
|
||||
"required": ["operation", "a", "b"]
|
||||
}
|
||||
"""), arguments -> {
|
||||
String operation = (String) arguments.get("operation");
|
||||
double a = (Integer) arguments.get("a");
|
||||
double b = (Integer) arguments.get("b");
|
||||
|
||||
double result;
|
||||
switch (operation) {
|
||||
case "add":
|
||||
result = a + b;
|
||||
break;
|
||||
case "subtract":
|
||||
result = a - b;
|
||||
break;
|
||||
case "multiply":
|
||||
result = a * b;
|
||||
break;
|
||||
case "divide":
|
||||
if (b == 0) {
|
||||
return new McpSchema.CallToolResult(
|
||||
java.util.List.of(new McpSchema.TextContent("Division by zero")), true);
|
||||
}
|
||||
result = a / b;
|
||||
break;
|
||||
default:
|
||||
return new McpSchema.CallToolResult(
|
||||
java.util.List.of(new McpSchema.TextContent("Unknown operation: " + operation)),
|
||||
true);
|
||||
}
|
||||
|
||||
return new McpSchema.CallToolResult(
|
||||
java.util.List.of(new McpSchema.TextContent(String.valueOf(result))), false);
|
||||
});
|
||||
}
|
||||
|
||||
public static String paymentTransactionStatus(String transactionId, String accountName) {
|
||||
return "The status for " + transactionId + ", by " + accountName + " is PENDING";
|
||||
}
|
||||
|
||||
@Bean
|
||||
public OpenLibrary openLibrary() {
|
||||
return new OpenLibrary(RestClient.builder());
|
||||
|
||||
@@ -50,19 +50,12 @@ public class SampleClient {
|
||||
ListToolsResult toolsList = client.listTools();
|
||||
System.out.println("Available Tools = " + toolsList);
|
||||
|
||||
CallToolResult weatherResponse = client.callTool(new CallToolRequest("weather", Map.of("city", "Sofia")));
|
||||
System.out.println("Weather Response = " + weatherResponse);
|
||||
CallToolResult upperCaseResult = client
|
||||
.callTool(new CallToolRequest("toUpperCase", Map.of("input", "accountName")));
|
||||
System.out.println("Upper case Response = " + upperCaseResult);
|
||||
|
||||
CallToolResult calcResponse = client
|
||||
.callTool(new CallToolRequest("calculator", Map.of("operation", "multiply", "a", 2.0, "b", 3.0)));
|
||||
System.out.println("Calculator Response = " + calcResponse);
|
||||
|
||||
CallToolResult paymentStatus = client.callTool(
|
||||
new CallToolRequest("paymentTransactionStatus", Map.of("transactionId", "006", "accountName", "John")));
|
||||
System.out.println("Payment Status Response = " + paymentStatus);
|
||||
|
||||
CallToolResult parks = client.callTool(new CallToolRequest("getBooks", Map.of("title", "Spring Framework")));
|
||||
System.out.println("Books Response = " + parks);
|
||||
CallToolResult books = client.callTool(new CallToolRequest("getBooks", Map.of("title", "Spring Framework")));
|
||||
System.out.println("Books Response = " + books);
|
||||
|
||||
// List and demonstrate resources
|
||||
var resourcesList = client.listResources();
|
||||
|
||||
@@ -75,32 +75,19 @@ public class McpServerConfig implements WebMvcConfigurer {
|
||||
|
||||
// Create the server with both tool and resource capabilities
|
||||
var server = McpServer.using(transport)
|
||||
.serverInfo("MCP Demo Server", "1.0.0")
|
||||
.serverInfo("MCP Demo WebMVC Server", "1.0.0")
|
||||
.capabilities(capabilities)
|
||||
.resources(systemInfoResourceRegistration())
|
||||
.prompts(greetingPromptRegistration())
|
||||
.tools(calculatorToolRegistration(),
|
||||
.tools(
|
||||
ToolHelper.toToolRegistration(
|
||||
FunctionCallback.builder()
|
||||
.method("paymentTransactionStatus",String.class, String.class)
|
||||
.description("Get transaction payment status")
|
||||
.targetClass(McpServerConfig.class)
|
||||
.build()),
|
||||
ToolHelper.toToolRegistration(
|
||||
FunctionCallback.builder()
|
||||
.function("toUpperCase", new Function<ToUpperCaseInput, String>() {
|
||||
@Override
|
||||
public String apply(ToUpperCaseInput s) {
|
||||
return s.input().toUpperCase();
|
||||
}
|
||||
})
|
||||
.description("To upper case")
|
||||
.inputType(ToUpperCaseInput.class)
|
||||
.build()))
|
||||
.function("toUpperCase", (Function<ToUpperCaseInput, String>) s -> s.input().toUpperCase())
|
||||
.description("To upper case")
|
||||
.inputType(ToUpperCaseInput.class)
|
||||
.build()))
|
||||
.tools(openLibraryToolRegistrations(openLibrary))
|
||||
.async();
|
||||
|
||||
server.addTool(weatherToolRegistration(server));
|
||||
return server; // @formatter:on
|
||||
} // @formatter:on
|
||||
|
||||
@@ -173,96 +160,6 @@ public class McpServerConfig implements WebMvcConfigurer {
|
||||
});
|
||||
}
|
||||
|
||||
private static ToolRegistration weatherToolRegistration(McpAsyncServer server) {
|
||||
String emptyJsonSchema = """
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"type": "object",
|
||||
"properties": {"city" : "string"}
|
||||
}
|
||||
""";
|
||||
return new ToolRegistration(new McpSchema.Tool("weather", "Weather forecast tool by location", emptyJsonSchema),
|
||||
(arguments) -> {
|
||||
String city = (String) arguments.get("city");
|
||||
|
||||
// Create the result
|
||||
var result = new CallToolResult(
|
||||
List.of(new TextContent("Weather forecast for " + city + " is sunny")), false);
|
||||
|
||||
// Send the logging notification and ignore its completion
|
||||
server
|
||||
.loggingNotification(LoggingMessageNotification.builder()
|
||||
.data("This is a log message from the weather tool")
|
||||
.build())
|
||||
.subscribe(null, error -> {
|
||||
// Log any errors but don't fail the operation
|
||||
logger.error("Failed to send logging notification", error);
|
||||
});
|
||||
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
private static ToolRegistration calculatorToolRegistration() {
|
||||
return new ToolRegistration(new McpSchema.Tool("calculator",
|
||||
"Performs basic arithmetic operations (add, subtract, multiply, divide)", """
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"operation": {
|
||||
"type": "string",
|
||||
"enum": ["add", "subtract", "multiply", "divide"],
|
||||
"description": "The arithmetic operation to perform"
|
||||
},
|
||||
"a": {
|
||||
"type": "number",
|
||||
"description": "First operand"
|
||||
},
|
||||
"b": {
|
||||
"type": "number",
|
||||
"description": "Second operand"
|
||||
}
|
||||
},
|
||||
"required": ["operation", "a", "b"]
|
||||
}
|
||||
"""), arguments -> {
|
||||
String operation = (String) arguments.get("operation");
|
||||
double a = (Integer) arguments.get("a");
|
||||
double b = (Integer) arguments.get("b");
|
||||
|
||||
double result;
|
||||
switch (operation) {
|
||||
case "add":
|
||||
result = a + b;
|
||||
break;
|
||||
case "subtract":
|
||||
result = a - b;
|
||||
break;
|
||||
case "multiply":
|
||||
result = a * b;
|
||||
break;
|
||||
case "divide":
|
||||
if (b == 0) {
|
||||
return new McpSchema.CallToolResult(
|
||||
java.util.List.of(new McpSchema.TextContent("Division by zero")), true);
|
||||
}
|
||||
result = a / b;
|
||||
break;
|
||||
default:
|
||||
return new McpSchema.CallToolResult(
|
||||
java.util.List.of(new McpSchema.TextContent("Unknown operation: " + operation)),
|
||||
true);
|
||||
}
|
||||
|
||||
return new McpSchema.CallToolResult(
|
||||
java.util.List.of(new McpSchema.TextContent(String.valueOf(result))), false);
|
||||
});
|
||||
}
|
||||
|
||||
public static String paymentTransactionStatus(String transactionId, String accountName) {
|
||||
return "The status for " + transactionId + ", by " + accountName + " is PENDING";
|
||||
}
|
||||
|
||||
@Bean
|
||||
public OpenLibrary openLibrary() {
|
||||
return new OpenLibrary(RestClient.builder());
|
||||
|
||||
Reference in New Issue
Block a user