MCP 服务器

概述

MCP服务器是模型上下文协议(MCP)架构中的基础组件,为客户端提供工具、资源和功能。它实现了协议的服务器端,负责:

  • 暴露客户端可以发现和执行的工具
  • 管理基于URI的资源访问模式
  • 提供提示模板并处理提示请求
  • 支持与客户端的能力协商
  • 实现服务器端协议操作
  • 管理并发客户端连接
  • 提供结构化日志和通知

服务器同时支持同步和异步API,允许在不同的应用场景中灵活集成。

// 创建具有自定义配置的服务器
McpSyncServer syncServer = McpServer.sync(transport)
    .serverInfo("my-server", "1.0.0")
    .capabilities(ServerCapabilities.builder()
        .resources(true)     // 启用资源支持
        .tools(true)         // 启用工具支持
        .prompts(true)       // 启用提示支持
        .logging()           // 启用日志支持
        .build())
    .build();

// 注册工具、资源和提示
syncServer.addTool(syncToolRegistration);
syncServer.addResource(syncResourceRegistration);
syncServer.addPrompt(syncPromptRegistration);

// 发送日志通知
syncServer.loggingNotification(LoggingMessageNotification.builder()
    .level(LoggingLevel.INFO)
    .logger("custom-logger")
    .data("服务器已初始化")
    .build());

// 完成后关闭服务器
syncServer.close();
// 创建具有自定义配置的异步服务器
McpAsyncServer asyncServer = McpServer.async(transport)
    .serverInfo("my-server", "1.0.0") 
    .capabilities(ServerCapabilities.builder()
        .resources(true)     // 启用资源支持
        .tools(true)         // 启用工具支持
        .prompts(true)       // 启用提示支持
        .logging()           // 启用日志支持
        .build())
    .build();

// 注册工具、资源和提示
asyncServer.addTool(asyncToolRegistration);
asyncServer.addResource(asyncResourceRegistration);
asyncServer.addPrompt(asyncPromptRegistration);

// 发送日志通知
asyncServer.loggingNotification(LoggingMessageNotification.builder()
    .level(LoggingLevel.INFO)
    .logger("custom-logger")
    .data("服务器已初始化")
    .build());

// 完成后关闭服务器
asyncServer.close();

服务器传输

创建基于进程的传输:

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

提供基于标准输入/输出流的双向JSON-RPC消息处理,具有非阻塞消息处理、序列化/反序列化和优雅关闭支持。

主要特性:

  • 通过stdin/stdout进行双向通信
  • 支持基于进程的集成
  • 简单的设置和配置
  • 轻量级实现

创建基于WebFlux的SSE服务器传输。 需要 mcp-spring-webflux 依赖。

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

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

实现了带SSE传输规范的MCP HTTP,提供:

  • 基于WebFlux的响应式HTTP流
  • 通过SSE端点的并发客户端连接
  • 消息路由和会话管理
  • 优雅关闭功能

创建基于WebMvc的SSE服务器传输。 需要 mcp-spring-webmvc 依赖。

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

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

实现了带SSE传输规范的MCP HTTP,提供:

  • 服务器端事件流
  • 与Spring WebMVC的集成
  • 支持传统Web应用
  • 同步操作处理

创建基于Servlet的SSE服务器传输。包含在核心mcp模块中。 HttpServletSseServerTransport可以与任何Servlet容器一起使用。 要在Spring Web应用程序中使用它,你可以将其注册为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);
    }
}

使用传统Servlet API实现MCP HTTP与SSE传输规范,提供:

  • 使用Servlet 6.0异步支持的异步消息处理
  • 多客户端连接的会话管理
  • 两种类型的端点:
    • SSE端点(/sse)用于服务器到客户端的事件
    • 消息端点(可配置)用于客户端到服务器的请求
  • 错误处理和响应格式化
  • 优雅关闭支持

服务器功能

服务器可以配置多种功能来支持不同的使用场景。以下是主要的服务器功能:

工具支持

工具允许服务器向客户端暴露可执行的功能。每个工具都有一个唯一的名称和一组参数:

// 定义同步工具
var calculator = new SyncToolRegistration(
    "calculator",                    // 工具名称
    "简单的计算器工具",              // 描述
    Map.of(                         // 参数定义
        "operation", ParameterType.STRING,
        "a", ParameterType.NUMBER,
        "b", ParameterType.NUMBER
    ),
    request -> {                    // 执行逻辑
        var operation = request.getParameter("operation");
        var a = request.getParameter("a", Double.class);
        var b = request.getParameter("b", Double.class);
        
        double result = switch(operation) {
            case "add" -> a + b;
            case "subtract" -> a - b;
            case "multiply" -> a * b;
            case "divide" -> a / b;
            default -> throw new IllegalArgumentException("未知操作");
        };
        
        return new ToolResult(Map.of("result", result));
    }
);

// 注册工具
syncServer.addTool(calculator);
// 定义异步工具
var calculator = new AsyncToolRegistration(
    "calculator",                    // 工具名称
    "简单的计算器工具",              // 描述
    Map.of(                         // 参数定义
        "operation", ParameterType.STRING,
        "a", ParameterType.NUMBER,
        "b", ParameterType.NUMBER
    ),
    request -> Mono.fromCallable(() -> {
        var operation = request.getParameter("operation");
        var a = request.getParameter("a", Double.class);
        var b = request.getParameter("b", Double.class);
        
        double result = switch(operation) {
            case "add" -> a + b;
            case "subtract" -> a - b;
            case "multiply" -> a * b;
            case "divide" -> a / b;
            default -> throw new IllegalArgumentException("未知操作");
        };
        
        return new ToolResult(Map.of("result", result));
    })
);

// 注册工具
asyncServer.addTool(calculator);

资源支持

资源允许客户端通过URI模板访问服务器端数据。每个资源都有唯一的URI模式和相关的元数据:

// 定义同步资源
var fileResource = new SyncResourceRegistration(
    "file",                         // 资源名称
    "文件系统资源",                  // 描述
    Map.of(                        // URI参数定义
        "path", ParameterType.STRING
    ),
    request -> {                   // 访问逻辑
        var path = request.getParameter("path");
        var content = Files.readString(Path.of(path));
        return new ResourceResult(content);
    }
);

// 注册资源
syncServer.addResource(fileResource);
// 定义异步资源
var fileResource = new AsyncResourceRegistration(
    "file",                         // 资源名称
    "文件系统资源",                  // 描述
    Map.of(                        // URI参数定义
        "path", ParameterType.STRING
    ),
    request -> Mono.fromCallable(() -> {
        var path = request.getParameter("path");
        var content = Files.readString(Path.of(path));
        return new ResourceResult(content);
    })
);

// 注册资源
asyncServer.addResource(fileResource);

提示支持

提示系统允许服务器定义可复用的提示模板。每个提示模板都有一个名称和一组参数:

// 定义同步提示
var echoPrompt = new SyncPromptRegistration(
    "echo",                         // 提示名称
    "回显输入文本",                  // 描述
    Map.of(                        // 参数定义
        "text", ParameterType.STRING
    ),
    request -> {                   // 执行逻辑
        var text = request.getParameter("text");
        return new PromptResult(text);
    }
);

// 注册提示
syncServer.addPrompt(echoPrompt);
// 定义异步提示
var echoPrompt = new AsyncPromptRegistration(
    "echo",                         // 提示名称
    "回显输入文本",                  // 描述
    Map.of(                        // 参数定义
        "text", ParameterType.STRING
    ),
    request -> Mono.fromCallable(() -> {
        var text = request.getParameter("text");
        return new PromptResult(text);
    })
);

// 注册提示
asyncServer.addPrompt(echoPrompt);

日志支持

服务器提供结构化日志功能,允许使用不同严重级别向客户端发送日志消息:

// 向客户端发送日志消息
server.loggingNotification(LoggingMessageNotification.builder()
    .level(LoggingLevel.INFO)
    .logger("custom-logger")
    .data("自定义日志消息")
    .build());

客户端可以通过mcpClient.setLoggingLevel(level)请求控制他们接收的最低日志级别。低于设置级别的消息将被过滤掉。 支持的日志级别(按严重程度递增排序):DEBUG (0)、INFO (1)、NOTICE (2)、WARNING (3)、ERROR (4)、CRITICAL (5)、ALERT (6)、EMERGENCY (7)

错误处理

SDK通过McpError类提供全面的错误处理,涵盖:

  • 协议兼容性问题
  • 传输通信错误
  • JSON-RPC消息传递异常
  • 工具执行错误
  • 资源管理问题
  • 提示处理异常
  • 超时和连接问题

这种统一的错误处理方法确保了同步和异步操作中一致且可靠的错误管理。