CtrlK
CommunityDocumentationLog inGet started
Tessl Logo

tessl/maven-org-springframework-ai--spring-ai-starter-mcp-server

Spring Boot Starter for building Model Context Protocol (MCP) servers with auto-configuration, annotation-based tool/resource/prompt definitions, and support for STDIO, SSE, and Streamable-HTTP transports

Overview
Eval results
Files

utilities.mddocs/reference/

Utilities

Helper classes and methods for working with MCP tools and specifications.

Capabilities

McpToolUtils

Utility class with helper methods for MCP tool operations.

/**
 * Utility class for MCP tool operations
 * Location: org.springframework.ai.mcp.McpToolUtils
 */
class McpToolUtils {
    /**
     * Generate a prefixed tool name with optional title
     * @param prefix The prefix to use
     * @param title Optional title (can be null)
     * @param toolName The original tool name
     * @return Prefixed and formatted tool name
     */
    static String prefixedToolName(String prefix, String title, String toolName);

    /**
     * Generate a prefixed tool name
     * @param prefix The prefix to use
     * @param toolName The original tool name
     * @return Prefixed and formatted tool name
     */
    static String prefixedToolName(String prefix, String toolName);

    /**
     * Format a tool name (alphanumeric, underscore, hyphen only)
     * @param input The input string to format
     * @return Formatted tool name
     */
    static String format(String input);

    /**
     * Convert list of ToolCallbacks to sync tool specifications
     * @param callbacks List of Spring AI ToolCallbacks
     * @return List of MCP sync tool specifications
     */
    static List<SyncToolSpecification> toSyncToolSpecification(List<ToolCallback> callbacks);

    /**
     * Convert varargs ToolCallbacks to sync tool specifications
     * @param callbacks ToolCallback varargs
     * @return List of MCP sync tool specifications
     */
    static List<SyncToolSpecification> toSyncToolSpecifications(ToolCallback... callbacks);

    /**
     * Convert single ToolCallback to sync tool specification
     * @param callback Spring AI ToolCallback
     * @return MCP sync tool specification
     */
    static SyncToolSpecification toSyncToolSpecification(ToolCallback callback);

    /**
     * Convert ToolCallback to sync tool specification with MIME type
     * @param callback Spring AI ToolCallback
     * @param mimeType MIME type for tool response
     * @return MCP sync tool specification
     */
    static SyncToolSpecification toSyncToolSpecification(ToolCallback callback, MimeType mimeType);

    /**
     * Convert ToolCallback to stateless sync tool specification
     * @param callback Spring AI ToolCallback
     * @param mimeType MIME type for tool response
     * @return Stateless MCP sync tool specification
     */
    static McpStatelessServerFeatures.SyncToolSpecification toStatelessSyncToolSpecification(
        ToolCallback callback, MimeType mimeType);

    /**
     * Convert list of ToolCallbacks to async tool specifications
     * @param callbacks List of Spring AI ToolCallbacks
     * @return List of MCP async tool specifications
     */
    static List<AsyncToolSpecification> toAsyncToolSpecifications(List<ToolCallback> callbacks);

    /**
     * Convert varargs ToolCallbacks to async tool specifications
     * @param callbacks ToolCallback varargs
     * @return List of MCP async tool specifications
     */
    static List<AsyncToolSpecification> toAsyncToolSpecifications(ToolCallback... callbacks);

    /**
     * Convert single ToolCallback to async tool specification
     * @param callback Spring AI ToolCallback
     * @return MCP async tool specification
     */
    static AsyncToolSpecification toAsyncToolSpecification(ToolCallback callback);

    /**
     * Convert ToolCallback to async tool specification with MIME type
     * @param callback Spring AI ToolCallback
     * @param mimeType MIME type for tool response
     * @return MCP async tool specification
     */
    static AsyncToolSpecification toAsyncToolSpecification(ToolCallback callback, MimeType mimeType);

    /**
     * Convert ToolCallback to stateless async tool specification
     * @param callback Spring AI ToolCallback
     * @param mimeType MIME type for tool response
     * @return Stateless MCP async tool specification
     */
    static McpStatelessServerFeatures.AsyncToolSpecification toStatelessAsyncToolSpecification(
        ToolCallback callback, MimeType mimeType);

    /**
     * Create a ToolDefinition from prefixed name and MCP tool
     * @param prefixedToolName The prefixed tool name
     * @param tool The MCP tool
     * @return Spring AI ToolDefinition
     */
    static ToolDefinition createToolDefinition(String prefixedToolName, Tool tool);

    /**
     * Retrieve McpSyncServerExchange from ToolContext
     * @param toolContext Spring AI ToolContext
     * @return Optional containing McpSyncServerExchange if present
     */
    static Optional<McpSyncServerExchange> getMcpExchange(ToolContext toolContext);

    /**
     * Get tool callbacks from sync MCP clients
     * @param clients List of MCP sync clients
     * @return List of ToolCallbacks
     */
    static List<ToolCallback> getToolCallbacksFromSyncClients(List<McpSyncClient> clients);

    /**
     * Get tool callbacks from sync MCP clients (varargs)
     * @param clients Varargs of MCP sync clients
     * @return List of ToolCallbacks
     */
    static List<ToolCallback> getToolCallbacksFromSyncClients(McpSyncClient... clients);

    /**
     * Get tool callbacks from async MCP clients
     * @param clients List of MCP async clients
     * @return List of ToolCallbacks
     */
    static List<ToolCallback> getToolCallbacksFromAsyncClients(List<McpAsyncClient> clients);

    /**
     * Get tool callbacks from async MCP clients (varargs)
     * @param clients Varargs of MCP async clients
     * @return List of ToolCallbacks
     */
    static List<ToolCallback> getToolCallbacksFromAsyncClients(McpAsyncClient... clients);

    /**
     * Context key for MCP exchange in ToolContext
     */
    static final String TOOL_CONTEXT_MCP_EXCHANGE_KEY = "exchange";
}

Usage Examples:

Formatting tool names:

String formatted = McpToolUtils.format("My Tool Name!");
// Result: "my_tool_name"

String prefixed = McpToolUtils.prefixedToolName("myserver", "My Tool");
// Result: "myserver_my_tool"

String prefixedWithTitle = McpToolUtils.prefixedToolName("srv", "Utilities", "format");
// Result: "srv_utilities_format"

Converting ToolCallbacks to specifications:

import org.springframework.ai.ToolCallback;
import org.springframework.ai.mcp.McpToolUtils;

// Single callback
ToolCallback callback = createMyCallback();
SyncToolSpecification syncSpec = McpToolUtils.toSyncToolSpecification(callback);
AsyncToolSpecification asyncSpec = McpToolUtils.toAsyncToolSpecification(callback);

// Multiple callbacks
List<ToolCallback> callbacks = List.of(callback1, callback2, callback3);
List<SyncToolSpecification> syncSpecs = McpToolUtils.toSyncToolSpecification(callbacks);
List<AsyncToolSpecification> asyncSpecs = McpToolUtils.toAsyncToolSpecifications(callbacks);

// With MIME type
SyncToolSpecification imageSpec = McpToolUtils.toSyncToolSpecification(
    imageCallback,
    MimeType.valueOf("image/png")
);

Creating ToolDefinitions:

Tool mcpTool = new Tool("calculate", "Calculator", schema);
ToolDefinition definition = McpToolUtils.createToolDefinition("calc_calculate", mcpTool);

Accessing MCP exchange from ToolContext:

public String myToolCallbackMethod(ToolContext context) {
    Optional<McpSyncServerExchange> exchange = McpToolUtils.getMcpExchange(context);

    if (exchange.isPresent()) {
        McpSyncServerExchange mcpExchange = exchange.get();

        // Use MCP-specific features
        mcpExchange.loggingNotification(
            LoggingMessageNotification.builder()
                .level(LoggingLevel.INFO)
                .data("Tool called via MCP")
                .build()
        );
    }

    return "Result";
}

Getting callbacks from MCP clients:

@Bean
public List<ToolCallback> clientTools(List<McpSyncClient> syncClients) {
    // Discover tools from all connected MCP servers
    return McpToolUtils.getToolCallbacksFromSyncClients(syncClients);
}

@Bean
public List<ToolCallback> asyncClientTools(List<McpAsyncClient> asyncClients) {
    return McpToolUtils.getToolCallbacksFromAsyncClients(asyncClients);
}

DefaultMcpToolNamePrefixGenerator

Default implementation for generating prefixed tool names with uniqueness guarantees.

/**
 * Default implementation of McpToolNamePrefixGenerator
 * Ensures unique tool names with fallback numbering
 */
class DefaultMcpToolNamePrefixGenerator implements McpToolNamePrefixGenerator {
    /**
     * Generate a unique prefixed tool name
     * @param connectionInfo MCP connection information
     * @param tool The MCP tool
     * @return Unique prefixed tool name
     */
    @Override
    String prefixedToolName(McpConnectionInfo connectionInfo, Tool tool);
}

Usage Example:

McpToolNamePrefixGenerator generator = new DefaultMcpToolNamePrefixGenerator();

// First tool with name "add"
String name1 = generator.prefixedToolName(connection1, addTool);
// Result: "server1_add"

// Second tool with same name from different connection
String name2 = generator.prefixedToolName(connection2, addTool);
// Result: "server2_add"

// Third tool with same name and same connection (collision)
String name3 = generator.prefixedToolName(connection1, addTool);
// Result: "server1_add_1" (fallback with number)

SyncMcpAnnotationProviders

Utility class for creating MCP specifications from annotated methods (synchronous).

/**
 * Provides MCP specification factories for annotated methods (sync)
 * Location: org.springframework.ai.mcp.annotation.spring.SyncMcpAnnotationProviders
 */
class SyncMcpAnnotationProviders {
    /**
     * Create tool specifications from annotated beans
     * @param beans List of Spring beans with @McpTool annotations
     * @return List of sync tool specifications
     */
    static List<SyncToolSpecification> toolSpecifications(List<Object> beans);

    /**
     * Create completion specifications from annotated beans
     * @param beans List of Spring beans with @McpComplete annotations
     * @return List of sync completion specifications
     */
    static List<SyncCompletionSpecification> completeSpecifications(List<Object> beans);

    /**
     * Create prompt specifications from annotated beans
     * @param beans List of Spring beans with @McpPrompt annotations
     * @return List of sync prompt specifications
     */
    static List<SyncPromptSpecification> promptSpecifications(List<Object> beans);

    /**
     * Create resource specifications from annotated beans
     * @param beans List of Spring beans with @McpResource annotations
     * @return List of sync resource specifications
     */
    static List<SyncResourceSpecification> resourceSpecifications(List<Object> beans);

    /**
     * Create resource template specifications from annotated beans
     * @param beans List of Spring beans with @McpResource annotations (with URI templates)
     * @return List of sync resource template specifications
     */
    static List<SyncResourceTemplateSpecification> resourceTemplateSpecifications(List<Object> beans);

    /**
     * Create logging specifications from annotated beans
     * @param beans List of Spring beans with @McpLogging annotations
     * @return List of sync logging specifications
     */
    static List<SyncLoggingSpecification> loggingSpecifications(List<Object> beans);

    /**
     * Create sampling specifications from annotated beans
     * @param beans List of Spring beans with @McpSampling annotations
     * @return List of sync sampling specifications
     */
    static List<SyncSamplingSpecification> samplingSpecifications(List<Object> beans);

    /**
     * Create elicitation specifications from annotated beans
     * @param beans List of Spring beans with @McpElicitation annotations
     * @return List of sync elicitation specifications
     */
    static List<SyncElicitationSpecification> elicitationSpecifications(List<Object> beans);

    /**
     * Create progress specifications from annotated beans
     * @param beans List of Spring beans with @McpProgress annotations
     * @return List of sync progress specifications
     */
    static List<SyncProgressSpecification> progressSpecifications(List<Object> beans);

    /**
     * Create tool list changed specifications
     * @param beans List of annotated beans
     * @return List of sync tool list changed specifications
     */
    static List<SyncToolListChangedSpecification> toolListChangedSpecifications(List<Object> beans);

    /**
     * Create resource list changed specifications
     * @param beans List of annotated beans
     * @return List of sync resource list changed specifications
     */
    static List<SyncResourceListChangedSpecification> resourceListChangedSpecifications(List<Object> beans);

    /**
     * Create prompt list changed specifications
     * @param beans List of annotated beans
     * @return List of sync prompt list changed specifications
     */
    static List<SyncPromptListChangedSpecification> promptListChangedSpecifications(List<Object> beans);

    // Stateless variants
    /**
     * Create stateless tool specifications
     */
    static List<StatelessSyncToolSpecification> statelessToolSpecifications(List<Object> beans);

    /**
     * Create stateless completion specifications
     */
    static List<StatelessSyncCompletionSpecification> statelessCompleteSpecifications(List<Object> beans);

    /**
     * Create stateless prompt specifications
     */
    static List<StatelessSyncPromptSpecification> statelessPromptSpecifications(List<Object> beans);

    /**
     * Create stateless resource specifications
     */
    static List<StatelessSyncResourceSpecification> statelessResourceSpecifications(List<Object> beans);

    /**
     * Create stateless resource template specifications
     */
    static List<StatelessSyncResourceTemplateSpecification> statelessResourceTemplateSpecifications(List<Object> beans);
}

Usage Example:

import org.springframework.ai.mcp.annotation.spring.SyncMcpAnnotationProviders;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class CustomAnnotationConfig {

    @Bean
    public List<SyncToolSpecification> customTools(ApplicationContext context) {
        // Get all beans with @McpTool annotations
        List<Object> annotatedBeans = findAnnotatedBeans(context);

        // Convert to specifications manually
        return SyncMcpAnnotationProviders.toolSpecifications(annotatedBeans);
    }

    @Bean
    public List<SyncResourceSpecification> customResources(ApplicationContext context) {
        List<Object> annotatedBeans = findAnnotatedBeans(context);
        return SyncMcpAnnotationProviders.resourceSpecifications(annotatedBeans);
    }

    private List<Object> findAnnotatedBeans(ApplicationContext context) {
        // Custom logic to find annotated beans
        return Arrays.asList(context.getBeansOfType(MyService.class).values().toArray());
    }
}

AsyncMcpAnnotationProviders

Utility class for creating MCP specifications from annotated methods (asynchronous).

/**
 * Provides MCP specification factories for annotated methods (async)
 * Location: org.springframework.ai.mcp.annotation.spring.AsyncMcpAnnotationProviders
 */
class AsyncMcpAnnotationProviders {
    /**
     * Create async tool specifications from annotated beans
     */
    static List<AsyncToolSpecification> toolSpecifications(List<Object> beans);

    /**
     * Create async completion specifications from annotated beans
     */
    static List<AsyncCompletionSpecification> completeSpecifications(List<Object> beans);

    /**
     * Create async prompt specifications from annotated beans
     */
    static List<AsyncPromptSpecification> promptSpecifications(List<Object> beans);

    /**
     * Create async resource specifications from annotated beans
     */
    static List<AsyncResourceSpecification> resourceSpecifications(List<Object> beans);

    /**
     * Create async resource template specifications from annotated beans
     */
    static List<AsyncResourceTemplateSpecification> resourceTemplateSpecifications(List<Object> beans);

    /**
     * Create async logging specifications from annotated beans
     */
    static List<AsyncLoggingSpecification> loggingSpecifications(List<Object> beans);

    /**
     * Create async sampling specifications from annotated beans
     */
    static List<AsyncSamplingSpecification> samplingSpecifications(List<Object> beans);

    /**
     * Create async elicitation specifications from annotated beans
     */
    static List<AsyncElicitationSpecification> elicitationSpecifications(List<Object> beans);

    /**
     * Create async progress specifications from annotated beans
     */
    static List<AsyncProgressSpecification> progressSpecifications(List<Object> beans);

    /**
     * Create async tool list changed specifications
     */
    static List<AsyncToolListChangedSpecification> toolListChangedSpecifications(List<Object> beans);

    /**
     * Create async resource list changed specifications
     */
    static List<AsyncResourceListChangedSpecification> resourceListChangedSpecifications(List<Object> beans);

    /**
     * Create async prompt list changed specifications
     */
    static List<AsyncPromptListChangedSpecification> promptListChangedSpecifications(List<Object> beans);

    // Stateless variants
    static List<StatelessAsyncToolSpecification> statelessToolSpecifications(List<Object> beans);
    static List<StatelessAsyncCompletionSpecification> statelessCompleteSpecifications(List<Object> beans);
    static List<StatelessAsyncPromptSpecification> statelessPromptSpecifications(List<Object> beans);
    static List<StatelessAsyncResourceSpecification> statelessResourceSpecifications(List<Object> beans);
    static List<StatelessAsyncResourceTemplateSpecification> statelessResourceTemplateSpecifications(List<Object> beans);
}

Usage Example:

@Configuration
public class AsyncAnnotationConfig {

    @Bean
    public List<AsyncToolSpecification> asyncTools(ApplicationContext context) {
        List<Object> beans = findReactiveBeans(context);
        return AsyncMcpAnnotationProviders.toolSpecifications(beans);
    }

    @Bean
    public List<AsyncResourceSpecification> asyncResources(ApplicationContext context) {
        List<Object> beans = findReactiveBeans(context);
        return AsyncMcpAnnotationProviders.resourceSpecifications(beans);
    }
}

AnnotationProviderUtil

Utility for scanning bean methods with annotations.

/**
 * Utility for scanning bean methods
 * Location: org.springframework.ai.mcp.annotation.spring.AnnotationProviderUtil
 */
class AnnotationProviderUtil {
    /**
     * Get all declared methods of a bean, sorted
     * @param bean The Spring bean
     * @return Array of methods
     */
    static Method[] beanMethods(Object bean);
}

Usage Example:

Object myBean = context.getBean(MyService.class);
Method[] methods = AnnotationProviderUtil.beanMethods(myBean);

for (Method method : methods) {
    if (method.isAnnotationPresent(McpTool.class)) {
        McpTool annotation = method.getAnnotation(McpTool.class);
        System.out.println("Found tool: " + annotation.name());
    }
}

Utility Patterns

Converting Callbacks to Specifications

// Convert existing ToolCallback implementations to MCP specs
List<ToolCallback> existingCallbacks = getExistingCallbacks();

// For sync server
List<SyncToolSpecification> syncSpecs =
    McpToolUtils.toSyncToolSpecification(existingCallbacks);

// For async server
List<AsyncToolSpecification> asyncSpecs =
    McpToolUtils.toAsyncToolSpecifications(existingCallbacks);

Custom Tool Name Formatting

String rawName = "My Complex Tool Name (v2.0)!";
String formatted = McpToolUtils.format(rawName);
// Result: "my_complex_tool_name_v2_0"

String prefixed = McpToolUtils.prefixedToolName("myapp", formatted);
// Result: "myapp_my_complex_tool_name_v2_0"

Accessing MCP Features from ToolCallback

@Component
public class MyToolCallback implements ToolCallback {

    @Override
    public String call(String input, ToolContext context) {
        // Check if running in MCP context
        Optional<McpSyncServerExchange> exchange = McpToolUtils.getMcpExchange(context);

        if (exchange.isPresent()) {
            // Use MCP-specific features
            exchange.get().loggingNotification(
                LoggingMessageNotification.builder()
                    .level(LoggingLevel.INFO)
                    .data("Processing request")
                    .build()
            );
        }

        return processInput(input);
    }
}

Manual Annotation Processing

@Configuration
public class ManualAnnotationConfig {

    @Bean
    public List<SyncToolSpecification> manuallyProcessedTools() {
        // Create instances of annotated classes manually
        List<Object> beans = List.of(
            new MyCalculator(),
            new MyWeatherService(),
            new MyDatabaseService()
        );

        // Process annotations
        return SyncMcpAnnotationProviders.toolSpecifications(beans);
    }
}

Constants

/**
 * Key used to store McpSyncServerExchange in ToolContext
 */
static final String TOOL_CONTEXT_MCP_EXCHANGE_KEY = "exchange";

Usage:

// Storing exchange in context (done automatically by the framework)
ToolContext context = new ToolContext();
context.getContext().put(McpToolUtils.TOOL_CONTEXT_MCP_EXCHANGE_KEY, exchange);

// Retrieving exchange
McpSyncServerExchange exchange = (McpSyncServerExchange)
    context.getContext().get(McpToolUtils.TOOL_CONTEXT_MCP_EXCHANGE_KEY);

Core Imports

// Utility classes
import org.springframework.ai.mcp.McpToolUtils;
import org.springframework.ai.mcp.DefaultMcpToolNamePrefixGenerator;
import org.springframework.ai.mcp.annotation.spring.SyncMcpAnnotationProviders;
import org.springframework.ai.mcp.annotation.spring.AsyncMcpAnnotationProviders;
import org.springframework.ai.mcp.annotation.spring.AnnotationProviderUtil;

// Tool callback types
import org.springframework.ai.tool.ToolCallback;
import org.springframework.ai.tool.ToolDefinition;
import org.springframework.ai.tool.ToolContext;

// MCP specification types
import org.springaicommunity.mcp.server.SyncToolSpecification;
import org.springaicommunity.mcp.server.AsyncToolSpecification;
import org.springaicommunity.mcp.server.SyncResourceSpecification;
import org.springaicommunity.mcp.server.AsyncResourceSpecification;
import org.springaicommunity.mcp.server.SyncResourceTemplateSpecification;
import org.springaicommunity.mcp.server.AsyncResourceTemplateSpecification;
import org.springaicommunity.mcp.server.SyncPromptSpecification;
import org.springaicommunity.mcp.server.AsyncPromptSpecification;
import org.springaicommunity.mcp.server.SyncCompletionSpecification;
import org.springaicommunity.mcp.server.AsyncCompletionSpecification;

// Stateless specification variants
import org.springaicommunity.mcp.server.StatelessSyncToolSpecification;
import org.springaicommunity.mcp.server.StatelessAsyncToolSpecification;
import org.springaicommunity.mcp.server.StatelessSyncResourceSpecification;
import org.springaicommunity.mcp.server.StatelessAsyncResourceSpecification;
import org.springaicommunity.mcp.server.StatelessSyncPromptSpecification;
import org.springaicommunity.mcp.server.StatelessAsyncPromptSpecification;

// MCP schema types
import org.springaicommunity.mcp.schema.McpSchema.Tool;

// MCP client types
import org.springaicommunity.mcp.client.McpSyncClient;
import org.springaicommunity.mcp.client.McpAsyncClient;

// Server exchange types
import org.springaicommunity.mcp.server.McpSyncServerExchange;
import org.springaicommunity.mcp.server.McpAsyncServerExchange;

// Connection info
import org.springframework.ai.mcp.McpConnectionInfo;

// MIME type
import org.springframework.util.MimeType;

// Java standard library
import java.util.List;
import java.util.Optional;
tessl i tessl/maven-org-springframework-ai--spring-ai-starter-mcp-server@1.1.0

docs

index.md

tile.json