跳到主要内容

SDK 内容

Java MCP 概览 Java MCP 客户端 [Java MCP 服务端]

服务器功能

MCP 服务端是模型上下文协议 (MCP) 架构中的核心组件,为客户端提供工具、资源和能力。它实现了协议的服务端部分,负责:
  • 暴露客户端可以发现并执行的工具。支持输入和输出模式,并返回结构化和非结构化的内容类型。
  • 通过基于 URI 的访问模式管理资源
  • 提供提示词模板并处理提示词请求
  • 支持与客户端的能力协商
  • 实现服务端协议操作
  • 管理并发客户端连接
  • 提供结构化日志、进度跟踪和通知
  • 提供 STDIOStreamable-HTTPSSE 服务端传输实现,无需外部 Web 框架。
  • 可选的 Spring 特定传输依赖:io.modelcontextprotocol.sdk:mcp-spring-webfluxio.modelcontextprotocol.sdk:mcp-spring-webmvc,供 Spring AI 用户使用。
这个基于 Spring AI MCP 的快速入门演示将向您展示如何构建 MCP 服务端。
服务端同时支持同步和异步 API,允许在不同的应用上下文中灵活集成。
// Create a server with custom configuration
McpSyncServer syncServer = McpServer.sync(transportProvider)
    .serverInfo("my-server", "1.0.0")
    .capabilities(ServerCapabilities.builder()
        .resources(false, true)  // Enable resource support
        .tools(true)             // Enable tool support
        .prompts(true)           // Enable prompt support
        .logging()               // Enable logging support
        .completions()           // Enable completions support
        .build())
    .build();

// Register tools, resources, and prompts
syncServer.addTool(syncToolSpecification);
syncServer.addResource(syncResourceSpecification);
syncServer.addPrompt(syncPromptSpecification);

// Close the server when done
syncServer.close();

在处理器中保留线程本地变量 (Thread-locals)

McpSyncServer 将执行委托给底层的 McpAsyncServer。工具、资源等处理器的执行可能不会在调用方法的线程上发生。在这种情况下,线程本地变量会丢失,这可能会破坏依赖线程绑定工作的框架中的某些功能。为确保在调用线程上执行并保持线程本地变量可用,请设置 McpServer.sync(...).immediateExecution(true)
这仅适用于同步服务端。异步服务端使用响应式堆栈,不应依赖线程本地变量。

服务端传输层提供者

MCP SDK 中的传输层负责处理客户端和服务端之间的通信。它提供不同的实现来支持各种通信协议和模式。SDK 包含几个内置的传输提供者实现:
创建进程内 (In-process) 传输
StdioServerTransportProvider transportProvider = new StdioServerTransportProvider(new ObjectMapper());
通过标准输入/输出流提供双向 JSON-RPC 消息处理,具有非阻塞消息处理、序列化/反序列化和优雅停机支持。关键特性:
  • 通过 stdin/stdout 进行双向通信
  • 支持基于进程的集成
  • 简单的安装和配置
  • 轻量级实现

服务端能力

服务端可以配置各种能力
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 logging level INFO)
    .build();

工具 (Tool) 规范

模型上下文协议允许服务端暴露工具,这些工具可以被语言模型调用。Java SDK 允许实现带有处理器函数的工具规范。工具使 AI 模型能够进行计算、访问外部 API、查询数据库和操作文件。
// Sync tool specification
var schema = """
            {
              "type" : "object",
              "id" : "urn:jsonschema:Operation",
              "properties" : {
                "operation" : {
                  "type" : "string"
                },
                "a" : {
                  "type" : "number"
                },
                "b" : {
                  "type" : "number"
                }
              }
            }
            """;
var syncToolSpecification = new McpServerFeatures.SyncToolSpecification(
    new Tool("calculator", "Basic calculator", schema),
    (exchange, arguments) -> {
        // Tool implementation
        return new CallToolResult(result, false);
    }
);
工具规范包括一个具有 name(名称)、description(描述)和 parameter schema(参数模式)的工具定义,以及一个实现工具逻辑的调用处理器。函数的第一个参数是用于客户端交互的 McpAsyncServerExchange,第二个参数是工具参数的映射。

资源 (Resource) 规范

带有处理器函数的资源规范。资源通过暴露如下数据为 AI 模型提供上下文:文件内容、数据库记录、API 响应、系统信息、应用程序状态。资源规范示例:
// Sync resource specification
var syncResourceSpecification = new McpServerFeatures.SyncResourceSpecification(
    new Resource("custom://resource", "name", "description", "mime-type", null),
    (exchange, request) -> {
        // Resource read implementation
        return new ReadResourceResult(contents);
    }
);
资源规范由资源定义和资源读取处理器组成。资源定义包括 namedescriptionMIME type。处理资源读取请求的函数第一个参数是 McpAsyncServerExchange,服务端可以通过它与连接的客户端交互。第二个参数是 McpSchema.ReadResourceRequest

提示词 (Prompt) 规范

作为提示词能力的一部分,MCP 为服务端向客户端暴露提示词模板提供了一种标准化方式。提示词规范是 AI 模型交互的结构化模板,支持一致的消息格式化、参数替换、上下文注入、响应格式化和指令模板化。
// Sync prompt specification
var syncPromptSpecification = new McpServerFeatures.SyncPromptSpecification(
    new Prompt("greeting", "description", List.of(
        new PromptArgument("name", "description", true)
    )),
    (exchange, request) -> {
        // Prompt implementation
        return new GetPromptResult(description, messages);
    }
);
提示词定义包括名称(提示词的标识符)、描述(提示词的用途)和参数列表(模板化所需的参数)。处理器函数处理请求并返回格式化后的模板。第一个参数是用于客户端交互的 McpAsyncServerExchange,第二个参数是 GetPromptRequest 实例。

补全 (Completion) 规范

作为补全能力的一部分,MCP 为服务端提供了一种标准化方式,为提示词和资源 URI 提供参数自动补全建议。
// Sync completion specification
var syncCompletionSpecification = new McpServerFeatures.SyncCompletionSpecification(
			new McpSchema.PromptReference("code_review"), (exchange, request) -> {

        // completion implementation ...

        return new McpSchema.CompleteResult(
            new CompleteResult.CompleteCompletion(
              List.of("python", "pytorch", "pyside"),
              10, // total
              false // hasMore
            ));
      }
);

// Create a sync server with completion capabilities
var mcpServer = McpServer.sync(mcpServerTransportProvider)
  .capabilities(ServerCapabilities.builder()
    .completions() // enable completions support
      // ...
    .build())
  // ...
  .completions(syncCompletionSpecification) // register completion specification
  .build();

McpSchema.CompletionReference 定义了补全规范的类型(PromptReferenceResourceReference)和标识符(例如处理器)。处理器函数处理请求并返回补全响应。第一个参数是用于客户端交互的 McpAsyncServerExchange,第二个参数是 CompleteRequest 实例。 查看使用补全以了解如何在客户端使用补全能力。

从服务端使用采样 (Sampling)

要使用采样能力,您需要一个支持采样的兼容客户端。不需要特殊的服务端配置,但在发起请求前请验证客户端的采样支持。了解关于客户端采样支持的信息。 当兼容的客户端连接到有状态服务端时,服务端可以请求语言模型生成:
// Create a server
McpSyncServer server = McpServer.sync(transportProvider)
    .serverInfo("my-server", "1.0.0")
    .build();

// Define a tool that uses sampling
var calculatorTool = new McpServerFeatures.SyncToolSpecification(
    new Tool("ai-calculator", "Performs calculations using AI", schema),
    (exchange, arguments) -> {
        // Check if client supports sampling
        if (exchange.getClientCapabilities().sampling() == null) {
            return new CallToolResult("Client does not support AI capabilities", false);
        }

        // Create a sampling request
        McpSchema.CreateMessageRequest request = McpSchema.CreateMessageRequest.builder()
            .messages(List.of(new McpSchema.SamplingMessage(McpSchema.Role.USER,
                new McpSchema.TextContent("Calculate: " + arguments.get("expression")))
            .modelPreferences(McpSchema.ModelPreferences.builder()
                .hints(List.of(
                    McpSchema.ModelHint.of("claude-3-sonnet"),
                    McpSchema.ModelHint.of("claude")
                ))
                .intelligencePriority(0.8)  // Prioritize intelligence
                .speedPriority(0.5)         // Moderate speed importance
                .build())
            .systemPrompt("You are a helpful calculator assistant. Provide only the numerical answer.")
            .maxTokens(100)
            .build();

        // Request sampling from the client
        McpSchema.CreateMessageResult result = exchange.createMessage(request);

        // Process the result
        String answer = result.content().text();
        return new CallToolResult(answer, false);
    }
);

// Add the tool to the server
server.addTool(calculatorTool);
CreateMessageRequest 对象允许您指定:Content(模型的输入文本或图像)、Model Preferences(模型选择的提示和优先级)、System Prompt(模型行为指令)以及 Max Tokens(生成响应的最大长度)。

从服务端使用启发 (Elicitation)

要使用启发能力,您需要一个支持启发的兼容客户端。不需要特殊的服务端配置,但在发起请求前请验证客户端的启发支持。了解关于客户端启发支持的信息。 当兼容的客户端连接到有状态服务端时,服务端可以向用户请求额外信息:
// Create a server
McpSyncServer server = McpServer.sync(transportProvider)
    .serverInfo("my-server", "1.0.0")
    .build();

// Define a tool that uses elicitation
var calculatorTool = new McpServerFeatures.SyncToolSpecification(
    new Tool("ai-calculator", "Performs calculations using AI", schema),
    (exchange, arguments) -> {
        // Check if client supports elicitation
        if (exchange.getClientCapabilities().elicitation() == null) {
            return new CallToolResult("Client does not support elicitation capabilities", false);
        }

        // Create an elicitation request
        McpSchema.ElicitRequest request = McpSchema.ElicitRequest.builder()
					.message("Test message")
					.requestedSchema(
							Map.of("type", "object", "properties", Map.of("message", Map.of("type", "string"))))
					.build();

        // Request elicitation from the client
        McpSchema.ElicitResult result = exchange.createElicitation(request);

        // Process the result
        Map<String, Object> answer = result.content();
        return new CallToolResult(answer, false);
    }
);

// Add the tool to the server
server.addTool(calculatorTool);

日志支持

服务端提供结构化日志记录能力,允许向客户端发送具有不同严重程度级别的日志消息。日志通知只能从现有的客户端会话(如工具、资源和提示词调用)内发送。 例如,我们可以在工具处理器函数中发送日志消息。在客户端,您可以注册一个日志消费者来接收来自服务端的日志消息,并设置最小日志级别以过滤消息。
var mcpClient = McpClient.sync(transport)
        .loggingConsumer(notification -> {
            System.out.println("Received log message: " + notification.data());
        })
        .build();

mcpClient.initialize();

mcpClient.setLoggingLevel(McpSchema.LoggingLevel.INFO);

// Call the tool that sends logging notifications
CallToolResult result = mcpClient.callTool(new McpSchema.CallToolRequest("logging-test", Map.of()));
服务端可以在工具/资源/提示词处理器函数中使用 McpAsyncServerExchange/McpSyncServerExchange 对象发送日志消息。
var tool = new McpServerFeatures.AsyncToolSpecification(
    new McpSchema.Tool("logging-test", "Test logging notifications", emptyJsonSchema),
    (exchange, request) -> {

      exchange.loggingNotification( // Use the exchange to send log messages
          McpSchema.LoggingMessageNotification.builder()
            .level(McpSchema.LoggingLevel.DEBUG)
            .logger("test-logger")
            .data("Debug message")
            .build())
        .block();

      return Mono.just(new CallToolResult("Logging test completed", false));
    });

var mcpServer = McpServer.async(mcpServerTransportProvider)
  .serverInfo("test-server", "1.0.0")
  .capabilities(
    ServerCapabilities.builder()
      .logging() // Enable logging support
      .tools(true)
      .build())
  .tools(tool)
  .build();
客户端可以通过 mcpClient.setLoggingLevel(level) 请求控制其接收的最小日志级别。低于设置级别的消息将被过滤掉。支持的日志级别(按严重程度递增排序):DEBUG (0), INFO (1), NOTICE (2), WARNING (3), ERROR (4), CRITICAL (5), ALERT (6), EMERGENCY (7)

错误处理

SDK 通过 McpError 类提供全面的错误处理,涵盖协议兼容性、传输通信、JSON-RPC 消息传递、工具执行、资源管理、提示词处理、超时和连接问题。这种统一的错误处理方法确保了在同步和异步操作中都能实现一致且可靠的错误管理。