MCP Server

Overview

The MCP Server is a foundational component in the Model Context Protocol (MCP) architecture that provides tools, resources, and capabilities to clients. It implements the server-side of the protocol, responsible for:

  • Exposing tools that clients can discover and execute
  • Managing resources with URI-based access patterns
  • Providing prompt templates and handling prompt requests
  • Supporting capability negotiation with clients
  • Implementing server-side protocol operations
  • Managing concurrent client connections
  • Providing structured logging and notifications

The server supports both synchronous and asynchronous APIs, allowing for flexible integration in different application contexts.

// Create a server with custom configuration
McpSyncServer syncServer = McpServer.sync(transport)
    .serverInfo("my-server", "1.0.0")
    .capabilities(ServerCapabilities.builder()
        .resources(true)     // Enable resource support
        .tools(true)         // Enable tool support
        .prompts(true)       // Enable prompt support
        .logging()           // Enable logging support
        .build())
    .build();

// Register tools, resources, and prompts
syncServer.addTool(syncToolRegistration);
syncServer.addResource(syncResourceRegistration);
syncServer.addPrompt(syncPromptRegistration);

// Send logging notifications
syncServer.loggingNotification(LoggingMessageNotification.builder()
    .level(LoggingLevel.INFO)
    .logger("custom-logger")
    .data("Server initialized")
    .build());

// Close the server when done
syncServer.close();
// Create an async server with custom configuration
McpAsyncServer asyncServer = McpServer.async(transport)
    .serverInfo("my-server", "1.0.0")
    .capabilities(ServerCapabilities.builder()
        .resources(true)     // Enable resource support
        .tools(true)         // Enable tool support
        .prompts(true)       // Enable prompt support
        .logging()           // Enable logging support
        .build())
    .build();

// Register tools, resources, and prompts
asyncServer.addTool(asyncToolRegistration)
    .doOnSuccess(v -> logger.info("Tool registered"))
    .subscribe();

asyncServer.addResource(asyncResourceRegistration)
    .doOnSuccess(v -> logger.info("Resource registered"))
    .subscribe();

asyncServer.addPrompt(asyncPromptRegistration)
    .doOnSuccess(v -> logger.info("Prompt registered"))
    .subscribe();

// Send logging notifications
asyncServer.loggingNotification(LoggingMessageNotification.builder()
    .level(LoggingLevel.INFO)
    .logger("custom-logger")
    .data("Server initialized")
    .build());

// Close the server when done
asyncServer.close()
    .doOnSuccess(v -> logger.info("Server closed"))
    .subscribe();

Server Transport

Create in-process based transport:

StdioServerTransport transport = new StdioServerTransport(new ObjectMapper());

Provides bidirectional JSON-RPC message handling over standard input/output streams with non-blocking message processing, serialization/deserialization, and graceful shutdown support.

Key features:

  • Bidirectional communication through stdin/stdout
  • Process-based integration support
  • Simple setup and configuration
  • Lightweight implementation

Creates WebFlux-based SSE server transport. Requires the mcp-spring-webflux dependency.

@Configuration
class McpConfig {
    @Bean
    WebFluxSseServerTransport webFluxSseServerTransport(ObjectMapper mapper) {
        return new WebFluxSseServerTransport(mapper, "/mcp/message");
    }

    @Bean
    RouterFunction<?> mcpRouterFunction(WebFluxSseServerTransport transport) {
        return transport.getRouterFunction();
    }
}

Implements the MCP HTTP with SSE transport specification, providing:

  • Reactive HTTP streaming with WebFlux
  • Concurrent client connections through SSE endpoints
  • Message routing and session management
  • Graceful shutdown capabilities

Creates WebMvc-based SSE server transport. Requires the mcp-spring-webmvc dependency.

@Configuration
@EnableWebMvc
class McpConfig {
    @Bean
    WebMvcSseServerTransport webMvcSseServerTransport(ObjectMapper mapper) {
        return new WebMvcSseServerTransport(mapper, "/mcp/message");
    }

    @Bean
    RouterFunction<ServerResponse> mcpRouterFunction(WebMvcSseServerTransport transport) {
        return transport.getRouterFunction();
    }
}

Implements the MCP HTTP with SSE transport specification, providing:

  • Server-side event streaming
  • Integration with Spring WebMVC
  • Support for traditional web applications
  • Synchronous operation handling

Creates a Servlet-based SSE server transport. It is included in the core mcp module. The HttpServletSseServerTransport can be used with any Servlet container. To use it with a Spring Web application, you can register it as a Servlet bean:

@Configuration
@EnableWebMvc
public class McpServerConfig implements WebMvcConfigurer {

    @Bean
    public HttpServletSseServerTransport servletSseServerTransport() {
        return new HttpServletSseServerTransport(new ObjectMapper(), "/mcp/message");
    }

    @Bean
    public ServletRegistrationBean customServletBean(HttpServletSseServerTransport servlet) {
        return new ServletRegistrationBean(servlet);
    }
}

Implements the MCP HTTP with SSE transport specification using the traditional Servlet API, providing:

  • Asynchronous message handling using Servlet 6.0 async support
  • Session management for multiple client connections
  • Two types of endpoints:
    • SSE endpoint (/sse) for server-to-client events
    • Message endpoint (configurable) for client-to-server requests
  • Error handling and response formatting
  • Graceful shutdown support

Server Capabilities

The server can be configured with various capabilities:

var capabilities = ServerCapabilities.builder()
    .resources(false, true)  // Resource support with list changes notifications
    .tools(true)            // Tool support with list changes notifications
    .prompts(true)          // Prompt support with list changes notifications
    .logging()              // Enable logging support (enabled by default with loging level INFO)
    .build();

Logging Support

The server provides structured logging capabilities that allow sending log messages to clients with different severity levels:

// Send a log message to clients
server.loggingNotification(LoggingMessageNotification.builder()
    .level(LoggingLevel.INFO)
    .logger("custom-logger")
    .data("Custom log message")
    .build());

Clients can control the minimum logging level they receive through the mcpClient.setLoggingLevel(level) request. Messages below the set level will be filtered out. Supported logging levels (in order of increasing severity): DEBUG (0), INFO (1), NOTICE (2), WARNING (3), ERROR (4), CRITICAL (5), ALERT (6), EMERGENCY (7)

Tool Registration

// Sync tool registration
var syncToolRegistration = new McpServerFeatures.SyncToolRegistration(
    new Tool("calculator", "Basic calculator", Map.of(
        "operation", "string",
        "a", "number",
        "b", "number"
    )),
    arguments -> {
        // Tool implementation
        return new CallToolResult(result, false);
    }
);
// Async tool registration
var asyncToolRegistration = new McpServerFeatures.AsyncToolRegistration(
    new Tool("calculator", "Basic calculator", Map.of(
        "operation", "string",
        "a", "number",
        "b", "number"
    )),
    arguments -> {
        // Tool implementation
        return Mono.just(new CallToolResult(result, false));
    }
);

Resource Registration

// Sync resource registration
var syncResourceRegistration = new McpServerFeatures.SyncResourceRegistration(
    new Resource("custom://resource", "name", "description", "mime-type", null),
    request -> {
        // Resource read implementation
        return new ReadResourceResult(contents);
    }
);
// Async resource registration
var asyncResourceRegistration = new McpServerFeatures.AsyncResourceRegistration(
    new Resource("custom://resource", "name", "description", "mime-type", null),
    request -> {
        // Resource read implementation
        return Mono.just(new ReadResourceResult(contents));
    }
);

Prompt Registration

// Sync prompt registration
var syncPromptRegistration = new McpServerFeatures.SyncPromptRegistration(
    new Prompt("greeting", "description", List.of(
        new PromptArgument("name", "description", true)
    )),
    request -> {
        // Prompt implementation
        return new GetPromptResult(description, messages);
    }
);
// Async prompt registration
var asyncPromptRegistration = new McpServerFeatures.AsyncPromptRegistration(
    new Prompt("greeting", "description", List.of(
        new PromptArgument("name", "description", true)
    )),
    request -> {
        // Prompt implementation
        return Mono.just(new GetPromptResult(description, messages));
    }
);

Error Handling

The SDK provides comprehensive error handling through the McpError class, covering protocol compatibility, transport communication, JSON-RPC messaging, tool execution, resource management, prompt handling, timeouts, and connection issues. This unified error handling approach ensures consistent and reliable error management across both synchronous and asynchronous operations.