diff --git a/model-context-protocol/mcp-servlet-server/src/main/java/org/springframework/ai/mcp/sample/webmvc/client/ClientStdio.java b/model-context-protocol/mcp-servlet-server/src/main/java/org/springframework/ai/mcp/sample/servlet/client/ClientStdio.java similarity index 95% rename from model-context-protocol/mcp-servlet-server/src/main/java/org/springframework/ai/mcp/sample/webmvc/client/ClientStdio.java rename to model-context-protocol/mcp-servlet-server/src/main/java/org/springframework/ai/mcp/sample/servlet/client/ClientStdio.java index 4885940..77fc262 100644 --- a/model-context-protocol/mcp-servlet-server/src/main/java/org/springframework/ai/mcp/sample/webmvc/client/ClientStdio.java +++ b/model-context-protocol/mcp-servlet-server/src/main/java/org/springframework/ai/mcp/sample/servlet/client/ClientStdio.java @@ -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; diff --git a/model-context-protocol/mcp-servlet-server/src/main/java/org/springframework/ai/mcp/sample/webmvc/client/HttpClientSse.java b/model-context-protocol/mcp-servlet-server/src/main/java/org/springframework/ai/mcp/sample/servlet/client/HttpClientSse.java similarity index 94% rename from model-context-protocol/mcp-servlet-server/src/main/java/org/springframework/ai/mcp/sample/webmvc/client/HttpClientSse.java rename to model-context-protocol/mcp-servlet-server/src/main/java/org/springframework/ai/mcp/sample/servlet/client/HttpClientSse.java index 27f7964..5155f85 100644 --- a/model-context-protocol/mcp-servlet-server/src/main/java/org/springframework/ai/mcp/sample/webmvc/client/HttpClientSse.java +++ b/model-context-protocol/mcp-servlet-server/src/main/java/org/springframework/ai/mcp/sample/servlet/client/HttpClientSse.java @@ -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; diff --git a/model-context-protocol/mcp-servlet-server/src/main/java/org/springframework/ai/mcp/sample/webmvc/client/SampleClient.java b/model-context-protocol/mcp-servlet-server/src/main/java/org/springframework/ai/mcp/sample/servlet/client/SampleClient.java similarity index 80% rename from model-context-protocol/mcp-servlet-server/src/main/java/org/springframework/ai/mcp/sample/webmvc/client/SampleClient.java rename to model-context-protocol/mcp-servlet-server/src/main/java/org/springframework/ai/mcp/sample/servlet/client/SampleClient.java index 3d536d2..4b7fad4 100644 --- a/model-context-protocol/mcp-servlet-server/src/main/java/org/springframework/ai/mcp/sample/webmvc/client/SampleClient.java +++ b/model-context-protocol/mcp-servlet-server/src/main/java/org/springframework/ai/mcp/sample/servlet/client/SampleClient.java @@ -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(); diff --git a/model-context-protocol/mcp-servlet-server/src/main/java/org/springframework/ai/mcp/sample/webmvc/server/McpServerConfig.java b/model-context-protocol/mcp-servlet-server/src/main/java/org/springframework/ai/mcp/sample/servlet/server/McpServerConfig.java similarity index 75% rename from model-context-protocol/mcp-servlet-server/src/main/java/org/springframework/ai/mcp/sample/webmvc/server/McpServerConfig.java rename to model-context-protocol/mcp-servlet-server/src/main/java/org/springframework/ai/mcp/sample/servlet/server/McpServerConfig.java index 04a47bd..2c68023 100644 --- a/model-context-protocol/mcp-servlet-server/src/main/java/org/springframework/ai/mcp/sample/webmvc/server/McpServerConfig.java +++ b/model-context-protocol/mcp-servlet-server/src/main/java/org/springframework/ai/mcp/sample/servlet/server/McpServerConfig.java @@ -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() { - @Override - public String apply(ToUpperCaseInput s) { - return s.input().toUpperCase(); - } - }) + .function("toUpperCase", (Function) 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()); diff --git a/model-context-protocol/mcp-servlet-server/src/main/java/org/springframework/ai/mcp/sample/webmvc/server/McpServletServerApplication.java b/model-context-protocol/mcp-servlet-server/src/main/java/org/springframework/ai/mcp/sample/servlet/server/McpServletServerApplication.java similarity index 83% rename from model-context-protocol/mcp-servlet-server/src/main/java/org/springframework/ai/mcp/sample/webmvc/server/McpServletServerApplication.java rename to model-context-protocol/mcp-servlet-server/src/main/java/org/springframework/ai/mcp/sample/servlet/server/McpServletServerApplication.java index 56eada5..146dc7f 100644 --- a/model-context-protocol/mcp-servlet-server/src/main/java/org/springframework/ai/mcp/sample/webmvc/server/McpServletServerApplication.java +++ b/model-context-protocol/mcp-servlet-server/src/main/java/org/springframework/ai/mcp/sample/servlet/server/McpServletServerApplication.java @@ -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; diff --git a/model-context-protocol/mcp-servlet-server/src/main/java/org/springframework/ai/mcp/sample/webmvc/server/OpenLibrary.java b/model-context-protocol/mcp-servlet-server/src/main/java/org/springframework/ai/mcp/sample/servlet/server/OpenLibrary.java similarity index 97% rename from model-context-protocol/mcp-servlet-server/src/main/java/org/springframework/ai/mcp/sample/webmvc/server/OpenLibrary.java rename to model-context-protocol/mcp-servlet-server/src/main/java/org/springframework/ai/mcp/sample/servlet/server/OpenLibrary.java index 3dfe835..b67b192 100644 --- a/model-context-protocol/mcp-servlet-server/src/main/java/org/springframework/ai/mcp/sample/webmvc/server/OpenLibrary.java +++ b/model-context-protocol/mcp-servlet-server/src/main/java/org/springframework/ai/mcp/sample/servlet/server/OpenLibrary.java @@ -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; diff --git a/model-context-protocol/mcp-webflux-server/src/main/java/org/springframework/ai/mcp/sample/client/SampleClient.java b/model-context-protocol/mcp-webflux-server/src/main/java/org/springframework/ai/mcp/sample/client/SampleClient.java index 61e855a..2cb4910 100644 --- a/model-context-protocol/mcp-webflux-server/src/main/java/org/springframework/ai/mcp/sample/client/SampleClient.java +++ b/model-context-protocol/mcp-webflux-server/src/main/java/org/springframework/ai/mcp/sample/client/SampleClient.java @@ -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(); diff --git a/model-context-protocol/mcp-webflux-server/src/main/java/org/springframework/ai/mcp/sample/server/McpServerConfig.java b/model-context-protocol/mcp-webflux-server/src/main/java/org/springframework/ai/mcp/sample/server/McpServerConfig.java index 04ecd54..eb223d9 100644 --- a/model-context-protocol/mcp-webflux-server/src/main/java/org/springframework/ai/mcp/sample/server/McpServerConfig.java +++ b/model-context-protocol/mcp-webflux-server/src/main/java/org/springframework/ai/mcp/sample/server/McpServerConfig.java @@ -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() { - @Override - public String apply(ToUpperCaseInput s) { - return s.input().toUpperCase(); - } - }) + .function("toUpperCase", (Function) 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()); diff --git a/model-context-protocol/mcp-webmvc-server/src/main/java/org/springframework/ai/mcp/sample/webmvc/client/SampleClient.java b/model-context-protocol/mcp-webmvc-server/src/main/java/org/springframework/ai/mcp/sample/webmvc/client/SampleClient.java index d9a29f6..1972c7f 100644 --- a/model-context-protocol/mcp-webmvc-server/src/main/java/org/springframework/ai/mcp/sample/webmvc/client/SampleClient.java +++ b/model-context-protocol/mcp-webmvc-server/src/main/java/org/springframework/ai/mcp/sample/webmvc/client/SampleClient.java @@ -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(); diff --git a/model-context-protocol/mcp-webmvc-server/src/main/java/org/springframework/ai/mcp/sample/webmvc/server/McpServerConfig.java b/model-context-protocol/mcp-webmvc-server/src/main/java/org/springframework/ai/mcp/sample/webmvc/server/McpServerConfig.java index adc2da5..6bf0a94 100644 --- a/model-context-protocol/mcp-webmvc-server/src/main/java/org/springframework/ai/mcp/sample/webmvc/server/McpServerConfig.java +++ b/model-context-protocol/mcp-webmvc-server/src/main/java/org/springframework/ai/mcp/sample/webmvc/server/McpServerConfig.java @@ -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() { - @Override - public String apply(ToUpperCaseInput s) { - return s.input().toUpperCase(); - } - }) - .description("To upper case") - .inputType(ToUpperCaseInput.class) - .build())) + .function("toUpperCase", (Function) 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());