MCP:深入理解 MCP Client,剖析sdk实现源码并提供代码示例!

作者:房杰

在# 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 中的工具
相关推荐
大鸡腿同学7 小时前
手心向上,手心向下
后端
CCblandy7 小时前
令牌桶在 0.9 倍负载超发 19%、固定窗口边界放行 20 个:四种限流算法同构实测
后端·python·算法·性能优化·架构
凤山老林9 小时前
Spring Boot 集成 Sa-Token 实现高可用权限认证:登录鉴权、动态路由权限与接口防重放实战
spring boot·后端·sa-token·bootstrap
Bazingga10 小时前
一次推理的完整旅程:ReAct推理深度解析
后端
姜鱼问生10 小时前
Nginx gzip 压缩:一个配置让页面加载快 3 倍
后端·算法·架构
颜酱10 小时前
一栋商业大厦,讲清 InnoDB 的表空间、段、区和页
后端·mysql
码事漫谈11 小时前
1956 亿行数据该怎么存:金仓时序数据库的三个实测
后端
Wx-bishekaifayuan11 小时前
springboot桂味美食分享系统40540-计算机课程设计、毕业设计
spring boot·后端·python·django·课程设计·express·旅游
彭亚川Allen11 小时前
从零手搓 RAG 之检索全流程,给大模型接上自己的知识库
前端·后端·ai编程
IT_陈寒11 小时前
别让Java字符串拼接偷偷吃掉你的内存
前端·人工智能·后端