跳转到主要内容
SEO Title

category

Java MCP客户端

了解如何使用模型上下文协议(MCP)客户端与MCP服务器交互

转到Java MCP服务器了解如何构建MCP服务器,或转到Java MCP概述了解整体架构。
 

模型上下文协议客户端

MCP客户端是模型上下文协议(MCP)架构中的关键组件,负责建立和管理与MCP服务器的连接。它实现了协议的客户端,处理:

  • 协议版本协商,以确保与服务器的兼容性
  • 能力协商以确定可用功能
  • 消息传输和JSON-RPC通信
  • 工具发现和执行
  • 资源访问和管理
  • 及时的系统交互
  • 可选功能,如根管理和采样支持
     

核心io.modelcontextprotocol.sdk:mcp模块提供STDIO和SSE客户端传输实现,无需外部web框架。
Spring特定的传输实现可作为可选依赖项io.modelcontextprotocol.sdk:mcp-Spring-webflux提供给Spring Framework用户。
这个基于Spring AI MCP的快速入门演示将向您展示如何构建连接到MCP服务器的AI客户端。
客户端提供同步和异步API,以在不同的应用程序上下文中实现灵活性。

  •  
// Create a sync client with custom configuration
McpSyncClient client = McpClient.sync(transport)
    .requestTimeout(Duration.ofSeconds(10))
    .capabilities(ClientCapabilities.builder()
        .roots(true)      // Enable roots capability
        .sampling()       // Enable sampling capability
        .build())
    .sampling(request -> new CreateMessageResult(response))
    .build();

// Initialize connection
client.initialize();

// List available tools
ListToolsResult tools = client.listTools();

// Call a tool
CallToolResult result = client.callTool(
    new CallToolRequest("calculator",
        Map.of("operation", "add", "a", 2, "b", 3))
);

// List and read resources
ListResourcesResult resources = client.listResources();
ReadResourceResult resource = client.readResource(
    new ReadResourceRequest("resource://uri")
);

// List and use prompts
ListPromptsResult prompts = client.listPrompts();
GetPromptResult prompt = client.getPrompt(
    new GetPromptRequest("greeting", Map.of("name", "Spring"))
);

// Add/remove roots
client.addRoot(new Root("file:///path", "description"));
client.removeRoot("file:///path");

// Close client
client.closeGracefully();
// Create an async client with custom configuration
McpAsyncClient client = McpClient.async(transport)
    .requestTimeout(Duration.ofSeconds(10))
    .capabilities(ClientCapabilities.builder()
        .roots(true)      // Enable roots capability
        .sampling()       // Enable sampling capability
        .build())
    .sampling(request -> Mono.just(new CreateMessageResult(response)))
    .toolsChangeConsumer(tools -> Mono.fromRunnable(() -> {
        logger.info("Tools updated: {}", tools);
    }))
    .resourcesChangeConsumer(resources -> Mono.fromRunnable(() -> {
        logger.info("Resources updated: {}", resources);
    }))
    .promptsChangeConsumer(prompts -> Mono.fromRunnable(() -> {
        logger.info("Prompts updated: {}", prompts);
    }))
    .build();

// Initialize connection and use features
client.initialize()
    .flatMap(initResult -> client.listTools())
    .flatMap(tools -> {
        return client.callTool(new CallToolRequest(
            "calculator",
            Map.of("operation", "add", "a", 2, "b", 3)
        ));
    })
    .flatMap(result -> {
        return client.listResources()
            .flatMap(resources ->
                client.readResource(new ReadResourceRequest("resource://uri"))
            );
    })
    .flatMap(resource -> {
        return client.listPrompts()
            .flatMap(prompts ->
                client.getPrompt(new GetPromptRequest(
                    "greeting",
                    Map.of("name", "Spring")
                ))
            );
    })
    .flatMap(prompt -> {
        return client.addRoot(new Root("file:///path", "description"))
            .then(client.removeRoot("file:///path"));
    })
    .doFinally(signalType -> {
        client.closeGracefully().subscribe();
    })
    .subscribe();

 

客户端传输


传输层处理MCP客户端和服务器之间的通信,为各种用例提供不同的实现。客户端传输管理消息序列化、连接建立和特定于协议的通信模式。

Creates transport for in-process based communication

ServerParameters params = ServerParameters.builder("npx")
    .args("-y", "@modelcontextprotocol/server-everything", "dir")
    .build();
McpTransport transport = new StdioClientTransport(params);
  •  

Creates a framework agnostic (pure Java API) SSE client transport. Included in the core mcp module.

McpTransport transport = new HttpClientSseClientTransport("http://your-mcp-server");

 

Creates WebFlux-based SSE client transport. Requires the mcp-webflux-sse-transport dependency.

WebClient.Builder webClientBuilder = WebClient.builder()
    .baseUrl("http://your-mcp-server");
McpTransport transport = new WebFluxSseClientTransport(webClientBuilder);

Client Capabilities

The client can be configured with various capabilities:

var capabilities = ClientCapabilities.builder()
    .roots(true)      // Enable filesystem roots support with list changes notifications
    .sampling()       // Enable LLM sampling support
    .build();

Roots Support

Roots define the boundaries of where servers can operate within the filesystem:

// Add a root dynamically
client.addRoot(new Root("file:///path", "description"));

// Remove a root
client.removeRoot("file:///path");

// Notify server of roots changes
client.rootsListChangedNotification();

The roots capability allows servers to:

  • Request the list of accessible filesystem roots
  • Receive notifications when the roots list changes
  • Understand which directories and files they have access to

Sampling Support

Sampling enables servers to request LLM interactions (“completions” or “generations”) through the client:

// Configure sampling handler
Function<CreateMessageRequest, CreateMessageResult> samplingHandler = request -> {
    // Sampling implementation that interfaces with LLM
    return new CreateMessageResult(response);
};

// Create client with sampling support
var client = McpClient.sync(transport)
    .capabilities(ClientCapabilities.builder()
        .sampling()
        .build())
    .sampling(samplingHandler)
    .build();

This capability allows:

  • 无需API密钥即可利用人工智能功能的服务器
  • 客户端保持对模型访问和权限的控制
  • 支持基于文本和图像的交互
  • 在提示中可选地包含MCP服务器上下文

Logging Support

The client can register a logging consumer to receive log messages from the server and set the minimum logging level to filter messages:

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 can sends logging notifications
CallToolResult result = mcpClient.callTool(new McpSchema.CallToolRequest("logging-test", Map.of()));

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)

使用MCP客户端

工具执行

 

工具是客户端可以发现和执行的服务器端功能。MCP客户端提供列出可用工具并使用特定参数执行这些工具的方法。每个工具都有一个唯一的名称,并接受参数映射。

  •  
// List available tools and their names
var tools = client.listTools();
tools.forEach(tool -> System.out.println(tool.getName()));

// Execute a tool with parameters
var result = client.callTool("calculator", Map.of(
    "operation", "add",
    "a", 1,
    "b", 2
));

 

// List available tools and their names
var tools = client.listTools();
tools.forEach(tool -> System.out.println(tool.getName()));

// Execute a tool with parameters
var result = client.callTool("calculator", Map.of(
    "operation", "add",
    "a", 1,
    "b", 2
));

 

资源访问


资源表示客户端可以使用URI模板访问的服务器端数据源。MCP客户端提供了通过标准化接口发现可用资源并检索其内容的方法。

  •  
// List available resources and their names
var resources = client.listResources();
resources.forEach(resource -> System.out.println(resource.getName()));

// Retrieve resource content using a URI template
var content = client.getResource("file", Map.of(
    "path", "/path/to/file.txt"
));

 

// List available resources and their names
var resources = client.listResources();
resources.forEach(resource -> System.out.println(resource.getName()));

// Retrieve resource content using a URI template
var content = client.getResource("file", Map.of(
    "path", "/path/to/file.txt"
));

 

提示系统


提示系统允许与服务器端提示模板进行交互。这些模板可以使用自定义参数进行发现和执行,从而允许基于预定义模式进行动态文本生成。

  •  
// List available prompt templates
var prompts = client.listPrompts();
prompts.forEach(prompt -> System.out.println(prompt.getName()));

// Execute a prompt template with parameters
var response = client.executePrompt("echo", Map.of(
    "text", "Hello, World!"
));

 

// List available prompt templates
var prompts = client.listPrompts();
prompts.forEach(prompt -> System.out.println(prompt.getName()));

// Execute a prompt template with parameters
var response = client.executePrompt("echo", Map.of(
    "text", "Hello, World!"
));

 

使用完成


作为完成功能的一部分,MCP为服务器提供了一种标准化的方式,为提示和资源URI提供参数自动完成建议。
检查服务器完成功能,了解如何在服务器端启用和配置完成。
在客户端,MCP客户端提供请求自动补全的方法:

  •  

CompleteRequest request = new CompleteRequest(
        new PromptReference("code_review"),
        new CompleteRequest.CompleteArgument("language", "py"));

CompleteResult result = syncMcpClient.completeCompletion(request);



CompleteRequest request = new CompleteRequest(
        new PromptReference("code_review"),
        new CompleteRequest.CompleteArgument("language", "py"));

CompleteResult result = syncMcpClient.completeCompletion(request);

 

文章链接

标签