Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -200,9 +200,12 @@ The modules provide callback implementations for each operation type:
The project includes provider classes that scan for annotated methods and create appropriate callbacks:

#### Stateful Providers (using McpSyncServerExchange/McpAsyncServerExchange)
- `SyncMcpCompletionProvider` - Processes `@McpComplete` annotations for synchronous operations
- `SyncMcpCompleteProvider` - Processes `@McpComplete` annotations for synchronous operations
- `AsyncMcpCompleteProvider` - Processes `@McpComplete` annotations for asynchronous operations
- `SyncMcpPromptProvider` - Processes `@McpPrompt` annotations for synchronous operations
- `AsyncMcpPromptProvider` - Processes `@McpPrompt` annotations for asynchronous operations
- `SyncMcpResourceProvider` - Processes `@McpResource` annotations for synchronous operations
- `AsyncMcpResourceProvider` - Processes `@McpResource` annotations for asynchronous operations
- `SyncMcpToolProvider` - Processes `@McpTool` annotations for synchronous operations
- `AsyncMcpToolProvider` - Processes `@McpTool` annotations for asynchronous operations
- `SyncMcpLoggingProvider` - Processes `@McpLogging` annotations for synchronous operations
Expand Down Expand Up @@ -895,7 +898,7 @@ public class McpServerFactory {
new SyncMcpResourceProvider(List.of(myResourceProvider)).getResourceSpecifications();

List<SyncCompletionSpecification> completionSpecifications =
new SyncMcpCompletionProvider(List.of(autocompleteProvider)).getCompleteSpecifications();
new SyncMcpCompleteProvider(List.of(autocompleteProvider)).getCompleteSpecifications();

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

@Bean
public List<McpStatelessServerFeatures.SyncCompletionSpecification> syncStatelessCompleteSpecifications(
List<StatelessAutocompleteProvider> statelessCompleteProviders) {
return SyncMcpAnnotationProviders.statelessCompleteSpecifications(statelessCompleteProviders);
}

@Bean
public List<SyncPromptSpecification> syncPromptSpecifications(
List<PromptProvider> promptProviders) {
Expand Down Expand Up @@ -2060,7 +2069,7 @@ public class McpConfig {

- Java 17 or higher
- Reactor Core (for async operations)
- MCP Java SDK 0.11.2 or higher
- MCP Java SDK 0.12.0-SNAPSHOT or higher
- Spring Framework and Spring AI (for mcp-annotations-spring module)

## Building from Source
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,33 @@
import java.lang.reflect.Method;
import java.util.List;

import org.springaicommunity.mcp.method.changed.prompt.AsyncPromptListChangedSpecification;
import org.springaicommunity.mcp.method.changed.resource.AsyncResourceListChangedSpecification;
import org.springaicommunity.mcp.method.changed.tool.AsyncToolListChangedSpecification;
import org.springaicommunity.mcp.method.elicitation.AsyncElicitationSpecification;
import org.springaicommunity.mcp.method.logging.AsyncLoggingSpecification;
import org.springaicommunity.mcp.method.progress.AsyncProgressSpecification;
import org.springaicommunity.mcp.method.sampling.AsyncSamplingSpecification;
import org.springaicommunity.mcp.provider.changed.prompt.AsyncMcpPromptListChangedProvider;
import org.springaicommunity.mcp.provider.changed.prompt.SyncMcpPromptListChangedProvider;
import org.springaicommunity.mcp.provider.changed.resource.AsyncMcpResourceListChangedProvider;
import org.springaicommunity.mcp.provider.changed.tool.AsyncMcpToolListChangedProvider;
import org.springaicommunity.mcp.provider.complete.AsyncMcpCompleteProvider;
import org.springaicommunity.mcp.provider.complete.AsyncStatelessMcpCompleteProvider;
import org.springaicommunity.mcp.provider.elicitation.AsyncMcpElicitationProvider;
import org.springaicommunity.mcp.provider.logging.AsyncMcpLoggingProvider;
import org.springaicommunity.mcp.provider.progress.AsyncMcpProgressProvider;
import org.springaicommunity.mcp.provider.prompt.AsyncMcpPromptProvider;
import org.springaicommunity.mcp.provider.prompt.AsyncStatelessMcpPromptProvider;
import org.springaicommunity.mcp.provider.resource.AsyncMcpResourceProvider;
import org.springaicommunity.mcp.provider.resource.AsyncStatelessMcpResourceProvider;
import org.springaicommunity.mcp.provider.sampling.AsyncMcpSamplingProvider;
import org.springaicommunity.mcp.provider.tool.AsyncMcpToolProvider;
import org.springaicommunity.mcp.provider.tool.AsyncStatelessMcpToolProvider;

import io.modelcontextprotocol.server.McpServerFeatures.AsyncCompletionSpecification;
import io.modelcontextprotocol.server.McpServerFeatures.AsyncPromptSpecification;
import io.modelcontextprotocol.server.McpServerFeatures.AsyncResourceSpecification;
import io.modelcontextprotocol.server.McpServerFeatures.AsyncToolSpecification;
import io.modelcontextprotocol.server.McpStatelessServerFeatures;

Expand All @@ -43,6 +53,7 @@
*/
public class AsyncMcpAnnotationProviders {

// LOGGING (CLIENT)
private static class SpringAiAsyncMcpLoggingProvider extends AsyncMcpLoggingProvider {

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

}

// SAMPLING (CLIENT)
private static class SpringAiAsyncMcpSamplingProvider extends AsyncMcpSamplingProvider {

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

}

// ELICITATION (CLIENT)
private static class SpringAiAsyncMcpElicitationProvider extends AsyncMcpElicitationProvider {

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

}

// PROGRESS (CLIENT)
private static class SpringAiAsyncMcpProgressProvider extends AsyncMcpProgressProvider {

public SpringAiAsyncMcpProgressProvider(List<Object> progressObjects) {
super(progressObjects);
}

@Override
protected Method[] doGetClassMethods(Object bean) {
return AnnotationProviderUtil.beanMethods(bean);
}

}

// TOOL
private static class SpringAiAsyncMcpToolProvider extends AsyncMcpToolProvider {

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

}

// COMPLETE
private static class SpringAiAsyncMcpCompleteProvider extends AsyncMcpCompleteProvider {

public SpringAiAsyncMcpCompleteProvider(List<Object> completeObjects) {
super(completeObjects);
}

@Override
protected Method[] doGetClassMethods(Object bean) {
return AnnotationProviderUtil.beanMethods(bean);
}

};

private static class SpringAiAsyncStatelessMcpCompleteProvider extends AsyncStatelessMcpCompleteProvider {

public SpringAiAsyncStatelessMcpCompleteProvider(List<Object> completeObjects) {
super(completeObjects);
}

@Override
protected Method[] doGetClassMethods(Object bean) {
return AnnotationProviderUtil.beanMethods(bean);
}

};

// PROMPT
private static class SpringAiAsyncPromptProvider extends AsyncMcpPromptProvider {

public SpringAiAsyncPromptProvider(List<Object> promptObjects) {
super(promptObjects);
}

@Override
protected Method[] doGetClassMethods(Object bean) {
return AnnotationProviderUtil.beanMethods(bean);
}

}

private static class SpringAiAsyncStatelessPromptProvider extends AsyncStatelessMcpPromptProvider {

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

}

private static class SpringAiAsyncStatelessResourceProvider extends AsyncStatelessMcpResourceProvider {
// RESOURCE
private static class SpringAiAsyncResourceProvider extends AsyncMcpResourceProvider {

public SpringAiAsyncStatelessResourceProvider(List<Object> resourceObjects) {
public SpringAiAsyncResourceProvider(List<Object> resourceObjects) {
super(resourceObjects);
}

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

}

private static class SpringAiAsyncMcpProgressProvider extends AsyncMcpProgressProvider {
private static class SpringAiAsyncStatelessResourceProvider extends AsyncStatelessMcpResourceProvider {

public SpringAiAsyncMcpProgressProvider(List<Object> progressObjects) {
super(progressObjects);
public SpringAiAsyncStatelessResourceProvider(List<Object> resourceObjects) {
super(resourceObjects);
}

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

}

// TOOL LIST CHANGED
private static class SpringAiAsyncMcpToolListChangedProvider extends AsyncMcpToolListChangedProvider {

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

}

// RESOURCE LIST CHANGED
private static class SpringAiAsyncMcpResourceListChangedProvider extends AsyncMcpResourceListChangedProvider {

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

}

// PROMPT LIST CHANGED
private static class SpringAiAsyncMcpPromptListChangedProvider extends AsyncMcpPromptListChangedProvider {

public SpringAiAsyncMcpPromptListChangedProvider(List<Object> promptListChangedObjects) {
super(promptListChangedObjects);
}

@Override
protected Method[] doGetClassMethods(Object bean) {
return AnnotationProviderUtil.beanMethods(bean);
}

}

//
// UTILITIES
//

// LOGGING (CLIENT)
public static List<AsyncLoggingSpecification> loggingSpecifications(List<Object> loggingObjects) {
return new SpringAiAsyncMcpLoggingProvider(loggingObjects).getLoggingSpecifications();
}

// SAMPLING (CLIENT)
public static List<AsyncSamplingSpecification> samplingSpecifications(List<Object> samplingObjects) {
return new SpringAiAsyncMcpSamplingProvider(samplingObjects).getSamplingSpecifictions();
}

// ELICITATION (CLIENT)
public static List<AsyncElicitationSpecification> elicitationSpecifications(List<Object> elicitationObjects) {
return new SpringAiAsyncMcpElicitationProvider(elicitationObjects).getElicitationSpecifications();
}

// PROGRESS (CLIENT)
public static List<AsyncProgressSpecification> progressSpecifications(List<Object> progressObjects) {
return new SpringAiAsyncMcpProgressProvider(progressObjects).getProgressSpecifications();
}

// TOOL
public static List<AsyncToolSpecification> toolSpecifications(List<Object> toolObjects) {
return new SpringAiAsyncMcpToolProvider(toolObjects).getToolSpecifications();
}
Expand All @@ -194,29 +293,54 @@ public static List<McpStatelessServerFeatures.AsyncToolSpecification> statelessT
return new SpringAiAsyncStatelessMcpToolProvider(toolObjects).getToolSpecifications();
}

// COMPLETE
public static List<AsyncCompletionSpecification> completeSpecifications(List<Object> completeObjects) {
return new SpringAiAsyncMcpCompleteProvider(completeObjects).getCompleteSpecifications();
}

public static List<McpStatelessServerFeatures.AsyncCompletionSpecification> statelessCompleteSpecifications(
List<Object> completeObjects) {
return new SpringAiAsyncStatelessMcpCompleteProvider(completeObjects).getCompleteSpecifications();
}

// PROMPT
public static List<AsyncPromptSpecification> promptSpecifications(List<Object> promptObjects) {
return new SpringAiAsyncPromptProvider(promptObjects).getPromptSpecifications();
}

public static List<McpStatelessServerFeatures.AsyncPromptSpecification> statelessPromptSpecifications(
List<Object> promptObjects) {
return new SpringAiAsyncStatelessPromptProvider(promptObjects).getPromptSpecifications();
}

// RESOURCE
public static List<AsyncResourceSpecification> resourceSpecifications(List<Object> resourceObjects) {
return new SpringAiAsyncResourceProvider(resourceObjects).getResourceSpecifications();
}

public static List<McpStatelessServerFeatures.AsyncResourceSpecification> statelessResourceSpecifications(
List<Object> resourceObjects) {
return new SpringAiAsyncStatelessResourceProvider(resourceObjects).getResourceSpecifications();
}

public static List<AsyncProgressSpecification> progressSpecifications(List<Object> progressObjects) {
return new SpringAiAsyncMcpProgressProvider(progressObjects).getProgressSpecifications();
// RESOURCE LIST CHANGED
public static List<AsyncResourceListChangedSpecification> resourceListChangedSpecifications(
List<Object> resourceListChangedObjects) {
return new SpringAiAsyncMcpResourceListChangedProvider(resourceListChangedObjects)
.getResourceListChangedSpecifications();
}

// TOOL LIST CHANGED
public static List<AsyncToolListChangedSpecification> toolListChangedSpecifications(
List<Object> toolListChangedObjects) {
return new SpringAiAsyncMcpToolListChangedProvider(toolListChangedObjects).getToolListChangedSpecifications();
}

public static List<AsyncResourceListChangedSpecification> resourceListChangedSpecifications(
List<Object> resourceListChangedObjects) {
return new SpringAiAsyncMcpResourceListChangedProvider(resourceListChangedObjects)
.getResourceListChangedSpecifications();
// PROMPT LIST CHANGED
public static List<AsyncPromptListChangedSpecification> promptListChangedSpecifications(
List<Object> promptListChangedObjects) {
return new SpringAiAsyncMcpPromptListChangedProvider(promptListChangedObjects)
.getPromptListChangedSpecifications();
}

}
Loading