diff --git a/README.md b/README.md index 21798e2..e818e11 100644 --- a/README.md +++ b/README.md @@ -234,7 +234,8 @@ The project includes provider classes that scan for annotated methods and create The Spring integration module provides: -- `SpringAiMcpAnnotationProvider` - Handles Spring-specific concerns when processing MCP annotations +- `AsyncMcpAnnotationProviders` - Handles Spring-specific concerns when processing asynchronous MCP annotations +- `SyncMcpAnnotationProviders` - Handles Spring-specific concerns when processing synchronous MCP annotations - Integration with Spring AOP proxies - Support for Spring AI model abstractions @@ -1904,115 +1905,115 @@ public class McpConfig { @Bean public List syncCompletionSpecifications( List completeProviders) { - return SpringAiMcpAnnotationProvider.createSyncCompleteSpecifications(completeProviders); + return SyncMcpAnnotationProviders.completeSpecifications(completeProviders); } @Bean public List syncPromptSpecifications( List promptProviders) { - return SpringAiMcpAnnotationProvider.createSyncPromptSpecifications(promptProviders); + return SyncMcpAnnotationProviders.promptSpecifications(promptProviders); } @Bean public List syncResourceSpecifications( List resourceProviders) { - return SpringAiMcpAnnotationProvider.createSyncResourceSpecifications(resourceProviders); + return SyncMcpAnnotationProviders.resourceSpecifications(resourceProviders); } @Bean public List syncToolSpecifications( List toolProviders) { - return SpringAiMcpAnnotationProvider.createSyncToolSpecifications(toolProviders); + return SyncMcpAnnotationProviders.toolSpecifications(toolProviders); } @Bean public List asyncToolSpecifications( List asyncToolProviders) { - return SpringAiMcpAnnotationProvider.createAsyncToolSpecifications(asyncToolProviders); + return AsyncMcpAnnotationProviders.toolSpecifications(asyncToolProviders); } @Bean public List syncLoggingSpecifications( List loggingHandlers) { - return SpringAiMcpAnnotationProvider.createSyncLoggingSpecifications(loggingHandlers); + return SyncMcpAnnotationProviders.loggingSpecifications(loggingHandlers); } @Bean public List asyncLoggingSpecifications( List asyncLoggingHandlers) { - return SpringAiMcpAnnotationProvider.createAsyncLoggingSpecifications(asyncLoggingHandlers); + return AsyncMcpAnnotationProviders.loggingSpecifications(asyncLoggingHandlers); } @Bean public List syncSamplingSpecifications( List samplingHandlers) { - return SpringAiMcpAnnotationProvider.createSyncSamplingSpecifications(samplingHandlers); + return SyncMcpAnnotationProviders.samplingSpecifications(samplingHandlers); } @Bean public List asyncSamplingSpecifications( List asyncSamplingHandlers) { - return SpringAiMcpAnnotationProvider.createAsyncSamplingSpecifications(asyncSamplingHandlers); + return AsyncMcpAnnotationProviders.samplingSpecifications(asyncSamplingHandlers); } @Bean public List syncElicitationSpecifications( List elicitationHandlers) { - return SpringAiMcpAnnotationProvider.createSyncElicitationSpecifications(elicitationHandlers); + return SyncMcpAnnotationProviders.elicitationSpecifications(elicitationHandlers); } @Bean public List asyncElicitationSpecifications( List asyncElicitationHandlers) { - return SpringAiMcpAnnotationProvider.createAsyncElicitationSpecifications(asyncElicitationHandlers); + return AsyncMcpAnnotationProviders.elicitationSpecifications(asyncElicitationHandlers); } @Bean public List syncProgressSpecifications( List progressHandlers) { - return SpringAiMcpAnnotationProvider.createSyncProgressSpecifications(progressHandlers); + return SyncMcpAnnotationProviders.progressSpecifications(progressHandlers); } @Bean public List asyncProgressSpecifications( List asyncProgressHandlers) { - return SpringAiMcpAnnotationProvider.createAsyncProgressSpecifications(asyncProgressHandlers); + return AsyncMcpAnnotationProviders.progressSpecifications(asyncProgressHandlers); } @Bean public List syncToolListChangedSpecifications( List toolListChangedHandlers) { - return SpringAiMcpAnnotationProvider.createSyncToolListChangedSpecifications(toolListChangedHandlers); + return SyncMcpAnnotationProviders.toolListChangedSpecifications(toolListChangedHandlers); } @Bean public List asyncToolListChangedSpecifications( List asyncToolListChangedHandlers) { - return SpringAiMcpAnnotationProvider.createAsyncToolListChangedSpecifications(asyncToolListChangedHandlers); + return AsyncMcpAnnotationProviders.toolListChangedSpecifications(asyncToolListChangedHandlers); } @Bean public List syncResourceListChangedSpecifications( List resourceListChangedHandlers) { - return SpringAiMcpAnnotationProvider.createSyncResourceListChangedSpecifications(resourceListChangedHandlers); + return SyncMcpAnnotationProviders.resourceListChangedSpecifications(resourceListChangedHandlers); } @Bean public List asyncResourceListChangedSpecifications( List asyncResourceListChangedHandlers) { - return SpringAiMcpAnnotationProvider.createAsyncResourceListChangedSpecifications(asyncResourceListChangedHandlers); + return AsyncMcpAnnotationProviders.resourceListChangedSpecifications(asyncResourceListChangedHandlers); } @Bean public List syncPromptListChangedSpecifications( List promptListChangedHandlers) { - return SpringAiMcpAnnotationProvider.createSyncPromptListChangedSpecifications(promptListChangedHandlers); + return SyncMcpAnnotationProviders.promptListChangedSpecifications(promptListChangedHandlers); } @Bean public List asyncPromptListChangedSpecifications( List asyncPromptListChangedHandlers) { - return SpringAiMcpAnnotationProvider.createAsyncPromptListChangedSpecifications(asyncPromptListChangedHandlers); + return AsyncMcpAnnotationProviders.promptListChangedSpecifications(asyncPromptListChangedHandlers); } // Stateless Spring Integration Examples @@ -2020,19 +2021,19 @@ public class McpConfig { @Bean public List syncStatelessToolSpecifications( List statelessToolProviders) { - return SpringAiMcpAnnotationProvider.createSyncStatelessToolSpecifications(statelessToolProviders); + return SyncMcpAnnotationProviders.statelessToolSpecifications(statelessToolProviders); } @Bean public List syncStatelessPromptSpecifications( List statelessPromptProviders) { - return SpringAiMcpAnnotationProvider.createSyncStatelessPromptSpecifications(statelessPromptProviders); + return SyncMcpAnnotationProviders.statelessPromptSpecifications(statelessPromptProviders); } @Bean public List syncStatelessResourceSpecifications( List statelessResourceProviders) { - return SpringAiMcpAnnotationProvider.createSyncStatelessResourceSpecifications(statelessResourceProviders); + return SyncMcpAnnotationProviders.statelessResourceSpecifications(statelessResourceProviders); } } ``` diff --git a/mcp-annotations-spring/src/main/java/org/springaicommunity/mcp/spring/AsyncMcpAnnotationProvider.java b/mcp-annotations-spring/src/main/java/org/springaicommunity/mcp/spring/AsyncMcpAnnotationProviders.java similarity index 87% rename from mcp-annotations-spring/src/main/java/org/springaicommunity/mcp/spring/AsyncMcpAnnotationProvider.java rename to mcp-annotations-spring/src/main/java/org/springaicommunity/mcp/spring/AsyncMcpAnnotationProviders.java index 7bf2b68..11860ec 100644 --- a/mcp-annotations-spring/src/main/java/org/springaicommunity/mcp/spring/AsyncMcpAnnotationProvider.java +++ b/mcp-annotations-spring/src/main/java/org/springaicommunity/mcp/spring/AsyncMcpAnnotationProviders.java @@ -41,7 +41,7 @@ /** * @author Christian Tzolov */ -public class AsyncMcpAnnotationProvider { +public class AsyncMcpAnnotationProviders { private static class SpringAiAsyncMcpLoggingProvider extends AsyncMcpLoggingProvider { @@ -173,48 +173,47 @@ protected Method[] doGetClassMethods(Object bean) { } - public static List createAsyncLoggingSpecifications(List loggingObjects) { + public static List loggingSpecifications(List loggingObjects) { return new SpringAiAsyncMcpLoggingProvider(loggingObjects).getLoggingSpecifications(); } - public static List createAsyncSamplingSpecifications(List samplingObjects) { + public static List samplingSpecifications(List samplingObjects) { return new SpringAiAsyncMcpSamplingProvider(samplingObjects).getSamplingSpecifictions(); } - public static List createAsyncElicitationSpecifications( - List elicitationObjects) { + public static List elicitationSpecifications(List elicitationObjects) { return new SpringAiAsyncMcpElicitationProvider(elicitationObjects).getElicitationSpecifications(); } - public static List createAsyncToolSpecifications(List toolObjects) { + public static List toolSpecifications(List toolObjects) { return new SpringAiAsyncMcpToolProvider(toolObjects).getToolSpecifications(); } - public static List createAsyncStatelessToolSpecifications( + public static List statelessToolSpecifications( List toolObjects) { return new SpringAiAsyncStatelessMcpToolProvider(toolObjects).getToolSpecifications(); } - public static List createAsyncStatelessPromptSpecifications( + public static List statelessPromptSpecifications( List promptObjects) { return new SpringAiAsyncStatelessPromptProvider(promptObjects).getPromptSpecifications(); } - public static List createAsyncStatelessResourceSpecifications( + public static List statelessResourceSpecifications( List resourceObjects) { return new SpringAiAsyncStatelessResourceProvider(resourceObjects).getResourceSpecifications(); } - public static List createAsyncProgressSpecifications(List progressObjects) { + public static List progressSpecifications(List progressObjects) { return new SpringAiAsyncMcpProgressProvider(progressObjects).getProgressSpecifications(); } - public static List createAsyncToolListChangedSpecifications( + public static List toolListChangedSpecifications( List toolListChangedObjects) { return new SpringAiAsyncMcpToolListChangedProvider(toolListChangedObjects).getToolListChangedSpecifications(); } - public static List createAsyncResourceListChangedSpecifications( + public static List resourceListChangedSpecifications( List resourceListChangedObjects) { return new SpringAiAsyncMcpResourceListChangedProvider(resourceListChangedObjects) .getResourceListChangedSpecifications(); diff --git a/mcp-annotations-spring/src/main/java/org/springaicommunity/mcp/spring/SyncMcpAnnotationProvider.java b/mcp-annotations-spring/src/main/java/org/springaicommunity/mcp/spring/SyncMcpAnnotationProviders.java similarity index 87% rename from mcp-annotations-spring/src/main/java/org/springaicommunity/mcp/spring/SyncMcpAnnotationProvider.java rename to mcp-annotations-spring/src/main/java/org/springaicommunity/mcp/spring/SyncMcpAnnotationProviders.java index 3a673be..88ecc07 100644 --- a/mcp-annotations-spring/src/main/java/org/springaicommunity/mcp/spring/SyncMcpAnnotationProvider.java +++ b/mcp-annotations-spring/src/main/java/org/springaicommunity/mcp/spring/SyncMcpAnnotationProviders.java @@ -47,7 +47,7 @@ /** * @author Christian Tzolov */ -public class SyncMcpAnnotationProvider { +public class SyncMcpAnnotationProviders { private static class SpringAiSyncMcpCompletionProvider extends SyncMcpCompletionProvider { @@ -218,60 +218,59 @@ protected Method[] doGetClassMethods(Object bean) { } - public static List createSyncToolSpecifications(List toolObjects) { + public static List toolSpecifications(List toolObjects) { return new SpringAiSyncToolProvider(toolObjects).getToolSpecifications(); } - public static List createSyncStatelessToolSpecifications( + public static List statelessToolSpecifications( List toolObjects) { return new SpringAiSyncStatelessToolProvider(toolObjects).getToolSpecifications(); } - public static List createSyncCompleteSpecifications(List completeObjects) { + public static List completeSpecifications(List completeObjects) { return new SpringAiSyncMcpCompletionProvider(completeObjects).getCompleteSpecifications(); } - public static List createSyncPromptSpecifications(List promptObjects) { + public static List promptSpecifications(List promptObjects) { return new SpringAiSyncMcpPromptProvider(promptObjects).getPromptSpecifications(); } - public static List createSyncStatelessPromptSpecifications( + public static List statelessPromptSpecifications( List promptObjects) { return new SpringAiSyncStatelessPromptProvider(promptObjects).getPromptSpecifications(); } - public static List createSyncResourceSpecifications(List resourceObjects) { + public static List resourceSpecifications(List resourceObjects) { return new SpringAiSyncMcpResourceProvider(resourceObjects).getResourceSpecifications(); } - public static List createSyncStatelessResourceSpecifications( + public static List statelessResourceSpecifications( List resourceObjects) { return new SpringAiSyncStatelessResourceProvider(resourceObjects).getResourceSpecifications(); } - public static List createSyncLoggingSpecifications(List loggingObjects) { + public static List loggingSpecifications(List loggingObjects) { return new SpringAiSyncMcpLoggingProvider(loggingObjects).getLoggingSpecifications(); } - public static List createSyncSamplingSpecifications(List samplingObjects) { + public static List samplingSpecifications(List samplingObjects) { return new SpringAiSyncMcpSamplingProvider(samplingObjects).getSamplingSpecifications(); } - public static List createSyncElicitationSpecifications( - List elicitationObjects) { + public static List elicitationSpecifications(List elicitationObjects) { return new SpringAiSyncMcpElicitationProvider(elicitationObjects).getElicitationSpecifications(); } - public static List createSyncProgressSpecifications(List progressObjects) { + public static List progressSpecifications(List progressObjects) { return new SpringAiSyncMcpProgressProvider(progressObjects).getProgressSpecifications(); } - public static List createSyncToolListChangedSpecifications( + public static List toolListChangedSpecifications( List toolListChangedObjects) { return new SpringAiSyncMcpToolListChangedProvider(toolListChangedObjects).getToolListChangedSpecifications(); } - public static List createSyncResourceListChangedSpecifications( + public static List resourceListChangedSpecifications( List resourceListChangedObjects) { return new SpringAiSyncMcpResourceListChangedProvider(resourceListChangedObjects) .getResourceListChangedSpecifications(); diff --git a/mcp-annotations/src/test/java/org/springaicommunity/mcp/provider/logging/AsyncMcpLoggingProviderTests.java b/mcp-annotations/src/test/java/org/springaicommunity/mcp/provider/logging/AsyncMcpLoggingProviderTests.java index 6848ac3..c05d0df 100644 --- a/mcp-annotations/src/test/java/org/springaicommunity/mcp/provider/logging/AsyncMcpLoggingProviderTests.java +++ b/mcp-annotations/src/test/java/org/springaicommunity/mcp/provider/logging/AsyncMcpLoggingProviderTests.java @@ -16,7 +16,6 @@ import io.modelcontextprotocol.spec.McpSchema.LoggingLevel; import io.modelcontextprotocol.spec.McpSchema.LoggingMessageNotification; import reactor.core.publisher.Mono; -import reactor.test.StepVerifier; /** * Tests for {@link AsyncMcpLoggingProvider}. @@ -28,7 +27,7 @@ public class AsyncMcpLoggingProviderTests { /** * Test class with logging consumer methods. */ - static class AsyncLoggingHandler { + static class TestAsyncLoggingProvider { private LoggingMessageNotification lastNotification; @@ -68,7 +67,7 @@ public Mono notAnnotatedMethod(LoggingMessageNotification notification) { @Test void testGetLoggingConsumers() { - AsyncLoggingHandler loggingHandler = new AsyncLoggingHandler(); + TestAsyncLoggingProvider loggingHandler = new TestAsyncLoggingProvider(); AsyncMcpLoggingProvider provider = new AsyncMcpLoggingProvider(List.of(loggingHandler)); List specifications = provider.getLoggingSpecifications(); @@ -83,7 +82,7 @@ void testGetLoggingConsumers() { LoggingMessageNotification notification = new LoggingMessageNotification(LoggingLevel.INFO, "test-logger", "This is a test message"); - StepVerifier.create(consumers.get(0).apply(notification)).verifyComplete(); + consumers.get(0).apply(notification).block(); // Verify that the method was called assertThat(loggingHandler.lastNotification).isEqualTo(notification); @@ -92,7 +91,7 @@ void testGetLoggingConsumers() { loggingHandler.lastNotification = null; // Test the second consumer (Mono return type with parameters) - StepVerifier.create(consumers.get(1).apply(notification)).verifyComplete(); + consumers.get(1).apply(notification).block(); // Verify that the method was called assertThat(loggingHandler.lastLevel).isEqualTo(notification.level()); @@ -100,7 +99,7 @@ void testGetLoggingConsumers() { assertThat(loggingHandler.lastData).isEqualTo(notification.data()); // Test the third consumer (void return type) - StepVerifier.create(consumers.get(2).apply(notification)).verifyComplete(); + consumers.get(2).apply(notification).block(); // Verify that the method was called assertThat(loggingHandler.lastNotification).isEqualTo(notification); @@ -121,8 +120,8 @@ void testEmptyList() { @Test void testMultipleObjects() { - AsyncLoggingHandler handler1 = new AsyncLoggingHandler(); - AsyncLoggingHandler handler2 = new AsyncLoggingHandler(); + TestAsyncLoggingProvider handler1 = new TestAsyncLoggingProvider(); + TestAsyncLoggingProvider handler2 = new TestAsyncLoggingProvider(); AsyncMcpLoggingProvider provider = new AsyncMcpLoggingProvider(List.of(handler1, handler2)); List specifications = provider.getLoggingSpecifications();