作者:房杰
在# Model Context Protocol (MCP)是什么?带你深入MCP核心内容! 文章介绍了 MCP 协议的核心概念,有些内容可能还是有点晦涩难懂,后续文章将通过实现一些实际的案例,深入理解并清楚其使用的场景和效果。
MCP Client 理解为可以支持 MCP 协议的客户端,本文重点在于如何使用 SDK 开发一个 MCP Client。我们直入主题,直接看 Java SDK 源码以及如何开发一个 MCP Client。
MCP 支持的语言
MCP 官方支持四种语言的 SDK, Python、TypeScript、Java、Kotlin,并有其对应实现的SDK;
根据自己的语言选型,选择不同的语言的 SDK进行开发,通过查看 SDK 文档,Python SDK 和 TypeScript SDK 文档比较详细,示例比较多,其次是 Kotlin SDK,最差的就是关于 Java SDK 的示例代码。基本上都是硬蹭 Spring AI MCP 相关内容。
本文对 Java SDK 源码进行分析,并直接使用Java SDK 进行开发示例,暂不使用 Spring AI MCP Staters。
Java MCP SDK 依赖
截止 2025-03-07 最新版本的 SDK 版本为 0.7.0,具体版本大家可以在 - modelcontextprotocol/java-sdk 找到。我们基于 0.7.0 版本进行分析。
pom
<dependencies>
<dependency>
<groupId>io.modelcontextprotocol.sdk</groupId>
<artifactId>mcp</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.modelcontextprotocol.sdk</groupId>
<artifactId>mcp-bom</artifactId>
<version>0.7.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
MCP Client SDK 源码
McpClient 接口
MCP Client 支持的能力;
- 工具的发现 与 调用
- 资源的访问 与 管理
- 提示词模版的处理
- 通过变更订阅实时处理工具、资源以及提示词模板的变化
- 自定义 sampling 策略
- 根据日志级别进行结构化日志记录
java
public interface McpClient {
// 通过 ClientMcpTransport 创建一个同步client。
static SyncSpec sync(ClientMcpTransport transport) {
return new SyncSpec(transport);
}
// 创建一异步client
static AsyncSpec async(ClientMcpTransport transport) {
return new AsyncSpec(transport);
}
/**
* 同步客户端规范,使用建造者模式,提供流式 API 设置自定义配置,主要配置如下;
* 1. 客户端与服务器之间的传输层
* 2. 请求超时时间
* 3. 客户端功能协商
* 4. 客户端版本实现跟踪
* 5. 资源访问限制
* 6. 工具、资源、提示词变更处理
*/
class SyncSpec {
// 里面细节不在分析,主要完成以上 6个方面内容
public McpSyncClient build() {
McpClientFeatures.Sync syncFeatures = new McpClientFeatures.Sync(this.clientInfo, this.capabilities,
this.roots, this.toolsChangeConsumers, this.resourcesChangeConsumers, this.promptsChangeConsumers,
this.loggingConsumers, this.samplingHandler);
McpClientFeatures.Async asyncFeatures = McpClientFeatures.Async.fromSync(syncFeatures);
return new McpSyncClient(new McpAsyncClient(transport, this.requestTimeout, asyncFeatures));
}
}
/**
* 异步客户端规范,同 同步客户端
*/
class AsyncSpec {
}
}
-
McpSyncClient
-
McpAsyncClient
实现 Mcp Client
java
package com.ivy.mcp;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.modelcontextprotocol.client.McpClient;
import io.modelcontextprotocol.client.McpSyncClient;
import io.modelcontextprotocol.client.transport.ServerParameters;
import io.modelcontextprotocol.client.transport.StdioClientTransport;
import io.modelcontextprotocol.spec.McpSchema;
import java.time.Duration;
import java.util.Map;
public class McpClientExample {
public static void main(String[] args) {
StdioClientTransport transport = new StdioClientTransport(
ServerParameters.builder("npx")
.args("-y",
"@modelcontextprotocol/server-filesystem",
"/Users/fangjie33/jdcs/mcp-client-examples")
.build(),
new ObjectMapper()
);
try (McpSyncClient client = McpClient.sync(transport)
.clientInfo(
new McpSchema.Implementation("my-client", "1.0.0")
)
.capabilities(
McpSchema.ClientCapabilities.builder().roots(true).sampling().build()
)
.requestTimeout(Duration.ofSeconds(60))
.build()) {
McpSchema.InitializeResult initialize = client.initialize();
System.out.println("client initialized: " + initialize);
tools(client); // 打印 MCP 工具列表
createDirectory(client); // 创建目录
createFile(client); // 创建文件
}
}
public static void tools (McpSyncClient client) {
McpSchema.ListToolsResult listToolsResult = client.listTools();
listToolsResult.tools().forEach(System.out::println);
}
public static void createDirectory(McpSyncClient client) {
McpSchema.CallToolRequest callToolRequest = new McpSchema.CallToolRequest(
"create_directory",
Map.of("path", "mcp")
);
McpSchema.CallToolResult callToolResult = client.callTool(callToolRequest);
System.out.println(callToolResult.content());
}
public static void createFile(McpSyncClient client) {
McpSchema.CallToolRequest callToolRequest = new McpSchema.CallToolRequest(
"write_file",
Map.of("path", "mcp/test.txt", "content", "hello world")
);
McpSchema.CallToolResult callToolResult = client.callTool(callToolRequest);
System.out.println(callToolResult.content());
}
}
大家运行代码自行测试其效果。
MCP 客户端
MCP 已经存在大量客户端或者编辑器,比如 Claude Desktop App,AI 代码开发工具 Cursor 等,大家可以直接下载使用,后续也会选择一些比较热门的编辑器进行演示使用。
客户端 | Resources | Prompts | Tools | Sampling | Roots | 说明 |
---|---|---|---|---|---|---|
Claude Desktop App | ✅ | ✅ | ✅ | ❌ | ❌ | 完全支持 MCP 所有特性 |
5ire | ❌ | ❌ | ✅ | ❌ | ❌ | 支持工具。 |
BeeAI Framework | ❌ | ❌ | ✅ | ❌ | ❌ | 支持代理工作流中的工具。 |
Cline | ✅ | ❌ | ✅ | ❌ | ❌ | 支持工具和资源。 |
Continue | ✅ | ✅ | ✅ | ❌ | ❌ | 完全支持 MCP 所有特性 |
Cursor | ❌ | ❌ | ✅ | ❌ | ❌ | 支持工具。 |
Emacs Mcp | ❌ | ❌ | ✅ | ❌ | ❌ | 支持 Emacs 中的工具。 |
Firebase Genkit | ⚠️ | ✅ | ✅ | ❌ | ❌ | 支持通过工具进行资源列表和查找。 |
GenAIScript | ❌ | ❌ | ✅ | ❌ | ❌ | 支持工具。 |
Goose | ❌ | ❌ | ✅ | ❌ | ❌ | 支持工具。 |
LibreChat | ❌ | ❌ | ✅ | ❌ | ❌ | Supports tools for Agents |
mcp-agent | ❌ | ❌ | ✅ | ⚠️ | ❌ | 支持工具、服务器连接管理和代理工作流程。 |
Roo Code | ✅ | ❌ | ✅ | ❌ | ❌ | 支持工具和资源。 |
Sourcegraph Cody | ✅ | ❌ | ❌ | ❌ | ❌ | 通过 OpenCTX 支持资源 |
Superinterface | ❌ | ❌ | ✅ | ❌ | ❌ | 支持工具 |
TheiaAI/TheiaIDE | ❌ | ❌ | ✅ | ❌ | ❌ | 支持 Theia AI 和 AI 驱动的 Theia IDE 中的 Agent 工具 |
Windsurf Editor | ❌ | ❌ | ✅ | ❌ | ❌ | 支持带有 AI Flow 的工具以进行协作开发。 |
Zed | ❌ | ✅ | ❌ | ❌ | ❌ | Prompts appear as slash commands 提示符显示为斜杠命令 |
OpenSumi | ❌ | ❌ | ✅ | ❌ | ❌ | 支持 OpenSumi 中的工具 |