Skip to content

Commit ad6e17a

Browse files
authored
feat: add async providers and rename completion providers for consistency (spring-ai-community#30)
* feat: add async providers and rename completion providers for consistency - Rename SyncMcpCompletionProvider to SyncMcpCompleteProvider for consistency - Add new async provider classes: - AsyncMcpCompleteProvider for async completion operations - AsyncMcpPromptProvider for async prompt operations - AsyncMcpResourceProvider for async resource operations - Update Spring integration with new provider support: - Add async/sync complete, prompt, and resource provider utilities - Add prompt list changed provider support - Reorganize provider methods with proper categorization - Update documentation to reflect correct provider class names - Bump MCP Java SDK version to 0.12.0-SNAPSHOT - Add comprehensive test coverage for all new provider classes This change provides complete async provider support and improves naming consistency across the MCP annotations framework. Signed-off-by: Christian Tzolov <[email protected]>
1 parent 4413ee8 commit ad6e17a

File tree

16 files changed

+4119
-21
lines changed

16 files changed

+4119
-21
lines changed

README.md

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -200,9 +200,12 @@ The modules provide callback implementations for each operation type:
200200
The project includes provider classes that scan for annotated methods and create appropriate callbacks:
201201

202202
#### Stateful Providers (using McpSyncServerExchange/McpAsyncServerExchange)
203-
- `SyncMcpCompletionProvider` - Processes `@McpComplete` annotations for synchronous operations
203+
- `SyncMcpCompleteProvider` - Processes `@McpComplete` annotations for synchronous operations
204+
- `AsyncMcpCompleteProvider` - Processes `@McpComplete` annotations for asynchronous operations
204205
- `SyncMcpPromptProvider` - Processes `@McpPrompt` annotations for synchronous operations
206+
- `AsyncMcpPromptProvider` - Processes `@McpPrompt` annotations for asynchronous operations
205207
- `SyncMcpResourceProvider` - Processes `@McpResource` annotations for synchronous operations
208+
- `AsyncMcpResourceProvider` - Processes `@McpResource` annotations for asynchronous operations
206209
- `SyncMcpToolProvider` - Processes `@McpTool` annotations for synchronous operations
207210
- `AsyncMcpToolProvider` - Processes `@McpTool` annotations for asynchronous operations
208211
- `SyncMcpLoggingProvider` - Processes `@McpLogging` annotations for synchronous operations
@@ -895,7 +898,7 @@ public class McpServerFactory {
895898
new SyncMcpResourceProvider(List.of(myResourceProvider)).getResourceSpecifications();
896899

897900
List<SyncCompletionSpecification> completionSpecifications =
898-
new SyncMcpCompletionProvider(List.of(autocompleteProvider)).getCompleteSpecifications();
901+
new SyncMcpCompleteProvider(List.of(autocompleteProvider)).getCompleteSpecifications();
899902

900903
List<SyncPromptSpecification> promptSpecifications =
901904
new SyncMcpPromptProvider(List.of(promptProvider)).getPromptSpecifications();
@@ -1908,6 +1911,12 @@ public class McpConfig {
19081911
return SyncMcpAnnotationProviders.completeSpecifications(completeProviders);
19091912
}
19101913

1914+
@Bean
1915+
public List<McpStatelessServerFeatures.SyncCompletionSpecification> syncStatelessCompleteSpecifications(
1916+
List<StatelessAutocompleteProvider> statelessCompleteProviders) {
1917+
return SyncMcpAnnotationProviders.statelessCompleteSpecifications(statelessCompleteProviders);
1918+
}
1919+
19111920
@Bean
19121921
public List<SyncPromptSpecification> syncPromptSpecifications(
19131922
List<PromptProvider> promptProviders) {
@@ -2060,7 +2069,7 @@ public class McpConfig {
20602069

20612070
- Java 17 or higher
20622071
- Reactor Core (for async operations)
2063-
- MCP Java SDK 0.11.2 or higher
2072+
- MCP Java SDK 0.12.0-SNAPSHOT or higher
20642073
- Spring Framework and Spring AI (for mcp-annotations-spring module)
20652074

20662075
## Building from Source

mcp-annotations-spring/src/main/java/org/springaicommunity/mcp/spring/AsyncMcpAnnotationProviders.java

Lines changed: 135 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,23 +18,33 @@
1818
import java.lang.reflect.Method;
1919
import java.util.List;
2020

21+
import org.springaicommunity.mcp.method.changed.prompt.AsyncPromptListChangedSpecification;
2122
import org.springaicommunity.mcp.method.changed.resource.AsyncResourceListChangedSpecification;
2223
import org.springaicommunity.mcp.method.changed.tool.AsyncToolListChangedSpecification;
2324
import org.springaicommunity.mcp.method.elicitation.AsyncElicitationSpecification;
2425
import org.springaicommunity.mcp.method.logging.AsyncLoggingSpecification;
2526
import org.springaicommunity.mcp.method.progress.AsyncProgressSpecification;
2627
import org.springaicommunity.mcp.method.sampling.AsyncSamplingSpecification;
28+
import org.springaicommunity.mcp.provider.changed.prompt.AsyncMcpPromptListChangedProvider;
29+
import org.springaicommunity.mcp.provider.changed.prompt.SyncMcpPromptListChangedProvider;
2730
import org.springaicommunity.mcp.provider.changed.resource.AsyncMcpResourceListChangedProvider;
2831
import org.springaicommunity.mcp.provider.changed.tool.AsyncMcpToolListChangedProvider;
32+
import org.springaicommunity.mcp.provider.complete.AsyncMcpCompleteProvider;
33+
import org.springaicommunity.mcp.provider.complete.AsyncStatelessMcpCompleteProvider;
2934
import org.springaicommunity.mcp.provider.elicitation.AsyncMcpElicitationProvider;
3035
import org.springaicommunity.mcp.provider.logging.AsyncMcpLoggingProvider;
3136
import org.springaicommunity.mcp.provider.progress.AsyncMcpProgressProvider;
37+
import org.springaicommunity.mcp.provider.prompt.AsyncMcpPromptProvider;
3238
import org.springaicommunity.mcp.provider.prompt.AsyncStatelessMcpPromptProvider;
39+
import org.springaicommunity.mcp.provider.resource.AsyncMcpResourceProvider;
3340
import org.springaicommunity.mcp.provider.resource.AsyncStatelessMcpResourceProvider;
3441
import org.springaicommunity.mcp.provider.sampling.AsyncMcpSamplingProvider;
3542
import org.springaicommunity.mcp.provider.tool.AsyncMcpToolProvider;
3643
import org.springaicommunity.mcp.provider.tool.AsyncStatelessMcpToolProvider;
3744

45+
import io.modelcontextprotocol.server.McpServerFeatures.AsyncCompletionSpecification;
46+
import io.modelcontextprotocol.server.McpServerFeatures.AsyncPromptSpecification;
47+
import io.modelcontextprotocol.server.McpServerFeatures.AsyncResourceSpecification;
3848
import io.modelcontextprotocol.server.McpServerFeatures.AsyncToolSpecification;
3949
import io.modelcontextprotocol.server.McpStatelessServerFeatures;
4050

@@ -43,6 +53,7 @@
4353
*/
4454
public class AsyncMcpAnnotationProviders {
4555

56+
// LOGGING (CLIENT)
4657
private static class SpringAiAsyncMcpLoggingProvider extends AsyncMcpLoggingProvider {
4758

4859
public SpringAiAsyncMcpLoggingProvider(List<Object> loggingObjects) {
@@ -56,6 +67,7 @@ protected Method[] doGetClassMethods(Object bean) {
5667

5768
}
5869

70+
// SAMPLING (CLIENT)
5971
private static class SpringAiAsyncMcpSamplingProvider extends AsyncMcpSamplingProvider {
6072

6173
public SpringAiAsyncMcpSamplingProvider(List<Object> samplingObjects) {
@@ -69,6 +81,7 @@ protected Method[] doGetClassMethods(Object bean) {
6981

7082
}
7183

84+
// ELICITATION (CLIENT)
7285
private static class SpringAiAsyncMcpElicitationProvider extends AsyncMcpElicitationProvider {
7386

7487
public SpringAiAsyncMcpElicitationProvider(List<Object> elicitationObjects) {
@@ -82,6 +95,21 @@ protected Method[] doGetClassMethods(Object bean) {
8295

8396
}
8497

98+
// PROGRESS (CLIENT)
99+
private static class SpringAiAsyncMcpProgressProvider extends AsyncMcpProgressProvider {
100+
101+
public SpringAiAsyncMcpProgressProvider(List<Object> progressObjects) {
102+
super(progressObjects);
103+
}
104+
105+
@Override
106+
protected Method[] doGetClassMethods(Object bean) {
107+
return AnnotationProviderUtil.beanMethods(bean);
108+
}
109+
110+
}
111+
112+
// TOOL
85113
private static class SpringAiAsyncMcpToolProvider extends AsyncMcpToolProvider {
86114

87115
public SpringAiAsyncMcpToolProvider(List<Object> toolObjects) {
@@ -108,6 +136,47 @@ protected Method[] doGetClassMethods(Object bean) {
108136

109137
}
110138

139+
// COMPLETE
140+
private static class SpringAiAsyncMcpCompleteProvider extends AsyncMcpCompleteProvider {
141+
142+
public SpringAiAsyncMcpCompleteProvider(List<Object> completeObjects) {
143+
super(completeObjects);
144+
}
145+
146+
@Override
147+
protected Method[] doGetClassMethods(Object bean) {
148+
return AnnotationProviderUtil.beanMethods(bean);
149+
}
150+
151+
};
152+
153+
private static class SpringAiAsyncStatelessMcpCompleteProvider extends AsyncStatelessMcpCompleteProvider {
154+
155+
public SpringAiAsyncStatelessMcpCompleteProvider(List<Object> completeObjects) {
156+
super(completeObjects);
157+
}
158+
159+
@Override
160+
protected Method[] doGetClassMethods(Object bean) {
161+
return AnnotationProviderUtil.beanMethods(bean);
162+
}
163+
164+
};
165+
166+
// PROMPT
167+
private static class SpringAiAsyncPromptProvider extends AsyncMcpPromptProvider {
168+
169+
public SpringAiAsyncPromptProvider(List<Object> promptObjects) {
170+
super(promptObjects);
171+
}
172+
173+
@Override
174+
protected Method[] doGetClassMethods(Object bean) {
175+
return AnnotationProviderUtil.beanMethods(bean);
176+
}
177+
178+
}
179+
111180
private static class SpringAiAsyncStatelessPromptProvider extends AsyncStatelessMcpPromptProvider {
112181

113182
public SpringAiAsyncStatelessPromptProvider(List<Object> promptObjects) {
@@ -121,9 +190,10 @@ protected Method[] doGetClassMethods(Object bean) {
121190

122191
}
123192

124-
private static class SpringAiAsyncStatelessResourceProvider extends AsyncStatelessMcpResourceProvider {
193+
// RESOURCE
194+
private static class SpringAiAsyncResourceProvider extends AsyncMcpResourceProvider {
125195

126-
public SpringAiAsyncStatelessResourceProvider(List<Object> resourceObjects) {
196+
public SpringAiAsyncResourceProvider(List<Object> resourceObjects) {
127197
super(resourceObjects);
128198
}
129199

@@ -134,10 +204,10 @@ protected Method[] doGetClassMethods(Object bean) {
134204

135205
}
136206

137-
private static class SpringAiAsyncMcpProgressProvider extends AsyncMcpProgressProvider {
207+
private static class SpringAiAsyncStatelessResourceProvider extends AsyncStatelessMcpResourceProvider {
138208

139-
public SpringAiAsyncMcpProgressProvider(List<Object> progressObjects) {
140-
super(progressObjects);
209+
public SpringAiAsyncStatelessResourceProvider(List<Object> resourceObjects) {
210+
super(resourceObjects);
141211
}
142212

143213
@Override
@@ -147,6 +217,7 @@ protected Method[] doGetClassMethods(Object bean) {
147217

148218
}
149219

220+
// TOOL LIST CHANGED
150221
private static class SpringAiAsyncMcpToolListChangedProvider extends AsyncMcpToolListChangedProvider {
151222

152223
public SpringAiAsyncMcpToolListChangedProvider(List<Object> toolListChangedObjects) {
@@ -160,6 +231,7 @@ protected Method[] doGetClassMethods(Object bean) {
160231

161232
}
162233

234+
// RESOURCE LIST CHANGED
163235
private static class SpringAiAsyncMcpResourceListChangedProvider extends AsyncMcpResourceListChangedProvider {
164236

165237
public SpringAiAsyncMcpResourceListChangedProvider(List<Object> resourceListChangedObjects) {
@@ -173,18 +245,45 @@ protected Method[] doGetClassMethods(Object bean) {
173245

174246
}
175247

248+
// PROMPT LIST CHANGED
249+
private static class SpringAiAsyncMcpPromptListChangedProvider extends AsyncMcpPromptListChangedProvider {
250+
251+
public SpringAiAsyncMcpPromptListChangedProvider(List<Object> promptListChangedObjects) {
252+
super(promptListChangedObjects);
253+
}
254+
255+
@Override
256+
protected Method[] doGetClassMethods(Object bean) {
257+
return AnnotationProviderUtil.beanMethods(bean);
258+
}
259+
260+
}
261+
262+
//
263+
// UTILITIES
264+
//
265+
266+
// LOGGING (CLIENT)
176267
public static List<AsyncLoggingSpecification> loggingSpecifications(List<Object> loggingObjects) {
177268
return new SpringAiAsyncMcpLoggingProvider(loggingObjects).getLoggingSpecifications();
178269
}
179270

271+
// SAMPLING (CLIENT)
180272
public static List<AsyncSamplingSpecification> samplingSpecifications(List<Object> samplingObjects) {
181273
return new SpringAiAsyncMcpSamplingProvider(samplingObjects).getSamplingSpecifictions();
182274
}
183275

276+
// ELICITATION (CLIENT)
184277
public static List<AsyncElicitationSpecification> elicitationSpecifications(List<Object> elicitationObjects) {
185278
return new SpringAiAsyncMcpElicitationProvider(elicitationObjects).getElicitationSpecifications();
186279
}
187280

281+
// PROGRESS (CLIENT)
282+
public static List<AsyncProgressSpecification> progressSpecifications(List<Object> progressObjects) {
283+
return new SpringAiAsyncMcpProgressProvider(progressObjects).getProgressSpecifications();
284+
}
285+
286+
// TOOL
188287
public static List<AsyncToolSpecification> toolSpecifications(List<Object> toolObjects) {
189288
return new SpringAiAsyncMcpToolProvider(toolObjects).getToolSpecifications();
190289
}
@@ -194,29 +293,54 @@ public static List<McpStatelessServerFeatures.AsyncToolSpecification> statelessT
194293
return new SpringAiAsyncStatelessMcpToolProvider(toolObjects).getToolSpecifications();
195294
}
196295

296+
// COMPLETE
297+
public static List<AsyncCompletionSpecification> completeSpecifications(List<Object> completeObjects) {
298+
return new SpringAiAsyncMcpCompleteProvider(completeObjects).getCompleteSpecifications();
299+
}
300+
301+
public static List<McpStatelessServerFeatures.AsyncCompletionSpecification> statelessCompleteSpecifications(
302+
List<Object> completeObjects) {
303+
return new SpringAiAsyncStatelessMcpCompleteProvider(completeObjects).getCompleteSpecifications();
304+
}
305+
306+
// PROMPT
307+
public static List<AsyncPromptSpecification> promptSpecifications(List<Object> promptObjects) {
308+
return new SpringAiAsyncPromptProvider(promptObjects).getPromptSpecifications();
309+
}
310+
197311
public static List<McpStatelessServerFeatures.AsyncPromptSpecification> statelessPromptSpecifications(
198312
List<Object> promptObjects) {
199313
return new SpringAiAsyncStatelessPromptProvider(promptObjects).getPromptSpecifications();
200314
}
201315

316+
// RESOURCE
317+
public static List<AsyncResourceSpecification> resourceSpecifications(List<Object> resourceObjects) {
318+
return new SpringAiAsyncResourceProvider(resourceObjects).getResourceSpecifications();
319+
}
320+
202321
public static List<McpStatelessServerFeatures.AsyncResourceSpecification> statelessResourceSpecifications(
203322
List<Object> resourceObjects) {
204323
return new SpringAiAsyncStatelessResourceProvider(resourceObjects).getResourceSpecifications();
205324
}
206325

207-
public static List<AsyncProgressSpecification> progressSpecifications(List<Object> progressObjects) {
208-
return new SpringAiAsyncMcpProgressProvider(progressObjects).getProgressSpecifications();
326+
// RESOURCE LIST CHANGED
327+
public static List<AsyncResourceListChangedSpecification> resourceListChangedSpecifications(
328+
List<Object> resourceListChangedObjects) {
329+
return new SpringAiAsyncMcpResourceListChangedProvider(resourceListChangedObjects)
330+
.getResourceListChangedSpecifications();
209331
}
210332

333+
// TOOL LIST CHANGED
211334
public static List<AsyncToolListChangedSpecification> toolListChangedSpecifications(
212335
List<Object> toolListChangedObjects) {
213336
return new SpringAiAsyncMcpToolListChangedProvider(toolListChangedObjects).getToolListChangedSpecifications();
214337
}
215338

216-
public static List<AsyncResourceListChangedSpecification> resourceListChangedSpecifications(
217-
List<Object> resourceListChangedObjects) {
218-
return new SpringAiAsyncMcpResourceListChangedProvider(resourceListChangedObjects)
219-
.getResourceListChangedSpecifications();
339+
// PROMPT LIST CHANGED
340+
public static List<AsyncPromptListChangedSpecification> promptListChangedSpecifications(
341+
List<Object> promptListChangedObjects) {
342+
return new SpringAiAsyncMcpPromptListChangedProvider(promptListChangedObjects)
343+
.getPromptListChangedSpecifications();
220344
}
221345

222346
}

0 commit comments

Comments
 (0)