MCP Toolbox Java SDK(Core)实战指南:在 Java 应用中加载、认证并调用数据库与 API 工具
【免费下载链接】mcp-toolboxMCP Toolbox for Databases is an open source MCP server for databases.项目地址: https://gitcode.com/GitHub_Trending/ge/mcp-toolbox
导读
MCP Toolbox(MCP Toolbox for Databases)是一个基于 Model Context Protocol(MCP)构建的开源数据库工具服务端,它将数据库查询、API 连接器等能力统一封装为可被 GenAI 应用调用的"工具"。本文围绕 Java SDK 的 Core 包展开,讲解如何用McpToolboxClient在自己的 Java 应用中完成工具集加载、工具定义获取、工具调用、两阶段认证(客户端认证与工具级认证)以及参数绑定,并借助仓库源码(服务端 API 路由、参数解析实现、工具 Manifest 定义)解释其背后的真实调用链,让读者既能照抄代码快速接入,也能理解 SDK 与服务端的交互原理。
概览:Java SDK 与服务端的分工
Java SDK 是 MCP Toolbox 服务端的官方客户端之一(Python、JavaScript/TypeScript、Go SDK 见 connect-to 总览)。它并不替代服务端,而是充当"客户端代理",负责:
- 从运行中的 MCP Toolbox 实例拉取工具定义(tool definition);
- 将工具表示为便捷的 Java 对象或函数;
- 调用工具(触发服务端执行底层配置好的 SQL、API 调用等逻辑);
- 按需处理认证与参数绑定。
从仓库源码看,服务端通过/api前缀的 REST 路由向 SDK 暴露能力(internal/server/api.go):
r.Get("/toolset", func(w http.ResponseWriter, r *http.Request) { toolsetHandler(s, w, r) }) r.Get("/toolset/{toolsetName}", func(w http.ResponseWriter, r *http.Request) { toolsetHandler(s, w, r) }) r.Route("/tool/{toolName}", func(r chi.Router) { r.Get("/", func(w http.ResponseWriter, r *http.Request) { toolGetHandler(s, w, r) }) r.Post("/invoke", func(w http.ResponseWriter, r *http.Request) { toolInvokeHandler(s, w, r) }) })Java SDK 的loadToolset()、loadTool()、invokeTool()正是分别对应这些路由;返回的工具定义在服务端被称为 Manifest,源码注释明确写着:"Manifest is the representation of tools sent to Client SDKs"(internal/tools/tools.go)。
安装
Java SDK(Core 包)以com.google.cloud.mcp:mcp-toolbox-sdk-java的坐标发布在 Maven Central Repository,支持 Maven 与 Gradle 两种方式接入(版本号请以 Maven Central 上该坐标的最新发布版本为准)。
Maven
在pom.xml中添加依赖:
<dependency> <groupId>com.google.cloud.mcp</groupId> <artifactId>mcp-toolbox-sdk-java</artifactId> <!-- Replace 'VERSION' with the latest version --> <version>VERSION</version> <scope>compile</scope> </dependency>Gradle
在build.gradle的 dependencies 中声明:
dependencies { // Replace 'VERSION' with the latest version implementation("com.google.cloud.mcp:mcp-toolbox-sdk-java:VERSION") }前置条件:请先确保 MCP Toolbox Server 已经完成配置并运行(本地或 Cloud Run 部署均可),接入方式与部署细节可参考 配置文档 与 getting-started 文档。
快速开始:最小可用代码
下面是最小化的连接代码——创建客户端、调用一个工具并打印结果:
import com.google.cloud.mcp.McpToolboxClient; import java.util.Map; public class App { public static void main(String[] args) { // 1. Create the Client McpToolboxClient client = McpToolboxClient.builder() .baseUrl("https://my-toolbox-service.a.run.app/mcp") .build(); // 2. Invoke a Tool client.invokeTool("get-toy-price", Map.of("description", "plush dinosaur")) .thenAccept(result -> { // Pick the first item from the response. System.out.println("Tool Output: " + result.content().get(0).text()); }) .exceptionally(ex -> { System.err.println("Error: " + ex.getMessage()); return null; }) .join(); // Wait for completion } }要点说明:
baseUrl指向服务端的 MCP 端点,通常形如http://localhost:5000/mcp(本地)或https://<service>.a.run.app/mcp(Cloud Run);- 调用参数以
Map<String, Object>传入,对应工具在服务端配置中的参数名; result.content().get(0).text()取响应内容中的第一条文本结果(MCP 标准 Content 结构)。
SDK 完整示例(包含更多调用方式的ExampleUsage.java)位于 Java SDK 仓库的example/src/main/java/cloudcode/helloworld/目录下,可与本文代码互相印证。
Async-First 设计:同步与异步两种写法
SDK 是"异步优先"(Async-First)设计的,全程基于 Java 的CompletableFuture,天然桥接异步与同步两种模式:
- 异步(非阻塞):使用
.thenCompose()、.thenAccept()、.exceptionally()链式编排; - 同步(阻塞):在链尾调用
.join(),阻塞直到执行完成。
// Async (Non-blocking) client.invokeTool("tool-name", args).thenAccept(result -> ...); // Sync (Blocking) ToolResult result = client.invokeTool("tool-name", args).join();使用详解
加载客户端
McpToolboxClient是整个 SDK 的入口对象,它是线程安全的,官方推荐只实例化一次并复用:
// Local Development McpToolboxClient client = McpToolboxClient.builder() .baseUrl("http://localhost:5000/mcp") .build(); // Cloud Run Production McpToolboxClient client = McpToolboxClient.builder() .baseUrl("https://my-toolbox-service.a.run.app/mcp") // .apiKey("...") // Optional: Overrides automatic Google Auth .build();baseUrl的末尾/mcp是 MCP Toolbox 服务端暴露 MCP 端点的固定路径;若服务端开启了访问控制,可在 builder 中显式传入.apiKey(...),它会覆盖下述的自动 Google 认证机制。
加载工具集(Toolset)
工具集是服务端对工具的分组管理概念(对应服务端的 group 机制)。loadToolset()不带参数时等价于listTools,返回全部工具的定义 Map;传入工具集名称则只加载该子集:
// Load all tools (alias for listTools) client.loadToolset().thenAccept(tools -> { System.out.println("Available Tools: " + tools.keySet()); tools.forEach((name, definition) -> { System.out.println("Tool: " + name); System.out.println("Description: " + definition.description()); }); });// Load a specific toolset (e.g., 'retail-tools') client.loadToolset("retail-tools").thenAccept(tools -> { System.out.println("Tools in Retail Set: " + tools.keySet()); });服务端视角:工具集信息由toolsetHandler通过PrimitiveMgr.GetGroup(toolsetName)查找分组,再生成ToolsetManifest返回(internal/server/api.go);GET /api/toolset/{toolsetName}即对应此逻辑。
加载单个工具
如果你已经明确要使用某个具体工具,可以直接加载其定义,用于调用前的参数校验或查看必填参数:
client.loadTool("get-toy-price").thenAccept(toolDef -> { System.out.println("Loaded Tool: " + toolDef.description()); System.out.println("Parameters: " + toolDef.parameters()); });服务端视角:toolGetHandler查找工具后返回ToolsManifest(以工具名为键的 Manifest 映射,internal/server/api.go)。Manifest 中的Parameters字段([]parameters.ParameterManifest,internal/tools/tools.go)正是 SDK 打印出的参数定义来源。
调用工具
invokeTool会向 MCP Server 发送执行请求,由服务端执行具体逻辑(SQL、API 调用等)。参数以Map<String, Object>传入:
import java.util.Map; Map<String, Object> args = Map.of( "description", "plush dinosaur", "limit", 5 ); client.invokeTool("get-toy-price", args).thenAccept(result -> { // Pick the first item from the response. System.out.println("Result: " + result.content().get(0).text()); });服务端视角:POST /api/tool/{toolName}/invoke的处理流程是完整的一整套管线(internal/server/api.go):
- 校验工具与数据源(Source)存在且有效;
- 提取
Authorization头中的访问令牌(tools.AccessToken); - 检查该工具是否需要客户端级授权(
RequiresClientAuthorization),需要但缺少令牌则返回401; - 遍历已配置的 Auth Service,从请求头解析 claims;
- 执行工具级授权检查(
tool.Authorized); - 用
parameters.ParseParams解析请求体参数(含认证参数解析,见下文); - 调用
tool.EmbedParams做参数嵌入,最后tool.Invoke真正执行。
认证:两阶段模型
MCP Toolbox 的认证分为两个层次:客户端到服务器的认证(你的应用访问 Toolbox 端点本身)与工具级认证(个别工具要求携带用户级 OAuth2 令牌才能执行)。SDK 对两者都有内置支持。
第一阶段:客户端到服务器认证
当服务端被配置为拒绝匿名请求时(例如 Cloud Run 默认的"Require authentication"、IAP 代理或自定义认证中间件),客户端必须提供有效的凭据;否则像listTools之类的操作会返回401 Unauthorized或403 Forbidden。
工作原理:Java SDK 借助 Google Auth Library 生成Authorization(Bearer token)请求头,并遵循Application Default Credentials(ADC)策略,根据代码运行环境自动寻找凭据。本地开发需要先配置 ADC(可通过gcloud完成)。
针对 Google Cloud 服务端(Cloud Run)的认证
1. 配置权限:在 Cloud Run 服务上,为调用方授予roles/run.invokerIAM 角色:
- 本地开发:授予你的用户账号邮箱;
- 生产环境:授予应用所挂载的服务账号。
2. 配置凭据,按运行环境三选一:
Option A:本地开发——在笔记本上使用gcloudCLI 登录用户凭据:
gcloud auth application-default loginSDK 会自动检测这些凭据,并为你的 MCP Toolbox URL 生成 OIDC ID Token。
Option B:Google Cloud 环境——在 Compute Engine、GKE、另一个 Cloud Run 服务、Cloud Functions 等环境内运行时,ADC 自动配置完成,SDK 直接使用环境的默认服务账号,无需任何额外代码或配置。
Option C:本地机房 / CI/CD——在 Google Cloud 之外(如 Jenkins、AWS)运行时,创建服务账号密钥(JSON)并设置环境变量:
export GOOGLE_APPLICATION_CREDENTIALS="/path/to/key.json"| 环境 | 凭据机制 | 需要做的配置 |
|---|---|---|
| 本地开发 | 用户凭据 | 运行gcloud auth application-default login |
| Cloud Run | 服务账号 | 无需配置(自动) |
| CI/CD | 服务账号密钥 | 设置GOOGLE_APPLICATION_CREDENTIALS=/path/to/key.json |
注意:如果在 builder 中提供了
.apiKey(),它将覆盖上述自动 ADC 机制。
第二阶段:工具级认证
服务端可以为单个工具配置"要求认证",只有授权用户或应用才能调用涉及敏感数据的工具。此时 SDK 客户端必须在该工具被调用时提供对应凭据(当前为 OAuth2 令牌)。
何时需要:认证是按工具在服务端配置的。如果目标工具在服务端被标记为需要认证,就必须通过 SDK 为它配置凭据提供器。配置方法(Authenticated Parameters 机制)详见 工具配置文档。
Step 1:在服务端配置工具:确保目标工具在 MCP Toolbox 服务中已正确配置为需要认证(authenticated parameters)。
Step 2:配置 SDK 客户端:应用需要一个能拿到当前用户令牌的途径。SDK 要求提供一个"令牌获取器"——AuthTokenGetter,它是一个返回CompletableFuture<String>的函数,具体实现取决于你的应用认证流程(例如读取已存令牌、发起 OAuth 流程)。
提供令牌获取函数:
注意:添加 getter 时使用的服务名(Auth Source)(如
"salesforce_auth")必须与工具配置中定义的 auth source 名称完全一致。
import com.google.cloud.mcp.AuthTokenGetter; // Define your token retrieval logic AuthTokenGetter salesforceTokenGetter = () -> { return CompletableFuture.supplyAsync(() -> fetchTokenFromVault()); }; //example tool: search-salesforce and related sample params client.loadTool("search-salesforce").thenCompose(tool -> { // Register the getter. It will be called every time 'execute' is run. tool.addAuthTokenGetter("salesforce_auth", salesforceTokenGetter); return tool.execute(Map.of("query", "recent leads")); });提示:令牌获取函数在每次工具调用需要认证参数时都会被调用。如果令牌有效期较长或获取过程较消耗资源,建议在函数内部实现缓存逻辑,避免重复获取或生成。
完整认证示例
import com.google.cloud.mcp.McpToolboxClient; import com.google.cloud.mcp.AuthTokenGetter; import java.util.Map; import java.util.concurrent.CompletableFuture; public class AuthExample { public static void main(String[] args) { // 1. Define your token retrieval logic AuthTokenGetter tokenGetter = () -> { // Logic to retrieve ID token (e.g., from local storage, OAuth flow) return CompletableFuture.completedFuture("YOUR_ID_TOKEN"); }; // 2. Initialize the client McpToolboxClient client = McpToolboxClient.builder() .baseUrl("http://127.0.0.1:5000/mcp") .build(); // 3. Load tool, attach auth, and execute client.loadTool("my-tool") .thenCompose(tool -> { // "my_auth" must match the name in the tool's authSource config tool.addAuthTokenGetter("my_auth", tokenGetter); return tool.execute(Map.of("input", "some input")); }) .thenAccept(result -> { // Pick the first item from the response. System.out.println(result.content().get(0).text()); }) .join(); } }服务端源码印证:工具级认证在服务端落地于两处——
- 参数解析:带认证服务的参数由
parseFromAuthService从 claims 中取值,若对应 auth service 的 claims 缺失或无效,会返回401错误(internal/util/parameters/parameters.go)。各类型参数(String/Int/Float/Boolean/Array/Map)均支持WithXxxAuth选项挂载AuthServices,并会在 Manifest 中仅暴露服务名列表(internal/util/parameters/parameters.go); - 授权校验:
toolInvokeHandler在真正执行前会比对"已验证的 auth services"与工具要求的 auth sources(tool.Authorized),不匹配则返回401(internal/server/api.go)。
安全提醒:请始终使用HTTPS连接应用与 MCP Toolbox 服务,尤其是在生产环境或涉及敏感数据(包括工具需要认证令牌的场景)时。明文 HTTP 缺乏加密,会使应用和数据暴露于窃听、篡改等重大安全风险中。
绑定参数值(Parameter Binding)
SDK 允许在工具被调用(甚至被传给 LLM)之前,为特定参数**预绑定(bind)**值。被绑定的值是固定的,LLM 在工具使用过程中不会请求或修改这些值。
为什么要绑定参数
- 保护敏感信息:API Key、密钥等;
- 强制一致性:确保某些参数始终为指定值;
- 预填已知数据:提供默认值或上下文。
注意:绑定时使用的参数名(如
"api_key")必须与工具在 MCP Toolbox 服务中配置的参数名完全一致。提示:使用 SDK 绑定参数无需修改服务端的工具配置。
方式 A:静态绑定
将固定值绑定到工具对象上,该工具实例后续调用都会携带此值:
client.loadTool("get-toy-price").thenCompose(tool -> { // Bind 'currency' to 'USD' permanently for this tool instance tool.bindParam("currency", "USD"); // Now invoke without specifying currency return tool.execute(Map.of("description", "lego set")); });方式 B:动态绑定
除了静态值,还可以把参数绑定到同步或异步函数(Supplier)上。该函数会在每次工具调用时执行,动态决定参数在运行时的值:
client.loadTool("check-order-status").thenCompose(tool -> { // Bind 'user_id' to a function that fetches the current user from context tool.bindParam("user_id", () -> SecurityContext.getCurrentUser().getId()); // Invoke: The SDK will call the supplier to fill 'user_id' return tool.execute(Map.of("order_id", "12345")); });动态绑定非常适合"从当前安全上下文取用户身份""从密钥库取令牌"这类随调用而变化的值,且同样不需要改动服务端配置。
错误处理
SDK 基于CompletableFutureAPI:网络问题、4xx/5xx响应等错误会以异常形式传播,并被包装在CompletionException中。推荐用.handle()同时处理成功与失败两条路径:
client.invokeTool("invalid-tool", Map.of()) .handle((result, ex) -> { if (ex != null) { System.err.println("Invocation Failed: " + ex.getCause().getMessage()); return null; // Handle error } return result; // Success path });与此对应,服务端在调用失败时会区分错误类别:Agent 类错误(业务校验失败)以 200 返回错误信息,Server 类错误则按具体状态码返回(401/403透传,其余默认500),未知错误统一500(internal/server/api.go)。理解这一分类有助于在客户端精准解析异常根因。
总结:接入路线图
- 部署服务端:完成 MCP Toolbox Server 的配置与运行(本地或 Cloud Run);
- 引入 SDK:按 Maven/Gradle 坐标
com.google.cloud.mcp:mcp-toolbox-sdk-java添加依赖; - 创建客户端:
McpToolboxClient.builder().baseUrl(...).build(),单例复用; - 加载并调用:
loadToolset()/loadTool()获取工具定义,invokeTool()或tool.execute()执行; - 配置认证:按运行环境完成 ADC 配置(客户端认证),对受保护工具注册
AuthTokenGetter(工具级认证); - 绑定与容错:用静态/动态绑定隐藏敏感参数与上下文数据,用
.handle()/.exceptionally()处理异步错误。
这套链路与仓库中的服务端实现(internal/server/api.go、internal/util/parameters/parameters.go、internal/tools/tools.go)一一对应,读者既可以在数分钟内完成 Java 应用接入,也可以顺着上述文件深入理解 MCP Toolbox 的工具管理、参数解析与认证授权机制。
【免费下载链接】mcp-toolboxMCP Toolbox for Databases is an open source MCP server for databases.项目地址: https://gitcode.com/GitHub_Trending/ge/mcp-toolbox
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考