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
- SSE endpoint (
- 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.