mirror of
https://github.com/googleapis/genai-toolbox.git
synced 2026-02-19 03:14:29 -05:00
Compare commits
1 Commits
py-sdk-doc
...
dependabot
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8ae55b9b34 |
@@ -4,8 +4,8 @@ linkTitle: "Redis"
|
||||
type: docs
|
||||
weight: 1
|
||||
description: >
|
||||
Redis is a in-memory data structure store.
|
||||
|
||||
Redis is a in-memory data structure store.
|
||||
|
||||
---
|
||||
|
||||
## About
|
||||
@@ -44,9 +44,6 @@ password: ${MY_AUTH_STRING} # Omit this field if you don't have a password.
|
||||
# database: 0
|
||||
# clusterEnabled: false
|
||||
# useGCPIAM: false
|
||||
# tls:
|
||||
# enabled: false
|
||||
# insecureSkipVerify: false
|
||||
```
|
||||
|
||||
{{< notice tip >}}
|
||||
@@ -64,7 +61,7 @@ Here is an example tools.yaml config with [AUTH][auth] enabled:
|
||||
```yaml
|
||||
kind: sources
|
||||
name: my-redis-cluster-instance
|
||||
type: redis
|
||||
type: memorystore-redis
|
||||
address:
|
||||
- 127.0.0.1:6379
|
||||
password: ${MY_AUTH_STRING}
|
||||
@@ -81,7 +78,7 @@ using IAM authentication:
|
||||
```yaml
|
||||
kind: sources
|
||||
name: my-redis-cluster-instance
|
||||
type: redis
|
||||
type: memorystore-redis
|
||||
address:
|
||||
- 127.0.0.1:6379
|
||||
useGCPIAM: true
|
||||
@@ -92,16 +89,14 @@ clusterEnabled: true
|
||||
|
||||
## Reference
|
||||
|
||||
| **field** | **type** | **required** | **description** |
|
||||
|------------------------|:--------:|:------------:|-----------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| type | string | true | Must be "redis". |
|
||||
| address | string | true | Primary endpoint for the Memorystore Redis instance to connect to. |
|
||||
| username | string | false | If you are using a non-default user, specify the user name here. If you are using Memorystore for Redis, leave this field blank |
|
||||
| password | string | false | If you have [Redis AUTH][auth] enabled, specify the AUTH string here |
|
||||
| database | int | false | The Redis database to connect to. Not applicable for cluster enabled instances. The default database is `0`. |
|
||||
| tls.enabled | bool | false | Set it to `true` to enable TLS for the Redis connection. Defaults to `false`. |
|
||||
| tls.insecureSkipVerify | bool | false | Set it to `true` to skip TLS certificate verification. **Warning:** This is insecure and not recommended for production. Defaults to `false`. |
|
||||
| clusterEnabled | bool | false | Set it to `true` if using a Redis Cluster instance. Defaults to `false`. |
|
||||
| useGCPIAM | bool | false | Set it to `true` if you are using GCP's IAM authentication. Defaults to `false`. |
|
||||
| **field** | **type** | **required** | **description** |
|
||||
|----------------|:--------:|:------------:|---------------------------------------------------------------------------------------------------------------------------------|
|
||||
| type | string | true | Must be "memorystore-redis". |
|
||||
| address | string | true | Primary endpoint for the Memorystore Redis instance to connect to. |
|
||||
| username | string | false | If you are using a non-default user, specify the user name here. If you are using Memorystore for Redis, leave this field blank |
|
||||
| password | string | false | If you have [Redis AUTH][auth] enabled, specify the AUTH string here |
|
||||
| database | int | false | The Redis database to connect to. Not applicable for cluster enabled instances. The default database is `0`. |
|
||||
| clusterEnabled | bool | false | Set it to `true` if using a Redis Cluster instance. Defaults to `false`. |
|
||||
| useGCPIAM | string | false | Set it to `true` if you are using GCP's IAM authentication. Defaults to `false`. |
|
||||
|
||||
[auth]: https://cloud.google.com/memorystore/docs/redis/about-redis-auth
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
---
|
||||
title: "Javascript"
|
||||
type: docs
|
||||
weight: 2
|
||||
description: >
|
||||
Javascript SDKs to connect to the MCP Toolbox server.
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
The MCP Toolbox service provides a centralized way to manage and expose tools
|
||||
(like API connectors, database query tools, etc.) for use by GenAI applications.
|
||||
|
||||
These JS SDKs act as clients for that service. They handle the communication needed to:
|
||||
|
||||
* Fetch tool definitions from your running Toolbox instance.
|
||||
* Provide convenient JS objects or functions representing those tools.
|
||||
* Invoke the tools (calling the underlying APIs/services configured in Toolbox).
|
||||
* Handle authentication and parameter binding as needed.
|
||||
|
||||
By using these SDKs, you can easily leverage your Toolbox-managed tools directly
|
||||
within your JS applications or AI orchestration frameworks.
|
||||
|
||||
## Which Package Should I Use?
|
||||
|
||||
Choosing the right package depends on how you are building your application:
|
||||
|
||||
- [`@toolbox-sdk/core`](https://github.com/googleapis/mcp-toolbox-sdk-js/tree/main/packages/toolbox-core):
|
||||
This is a framework agnostic way to connect the tools to popular frameworks
|
||||
like Langchain, LlamaIndex and Genkit.
|
||||
- [`@toolbox-sdk/adk`](https://github.com/googleapis/mcp-toolbox-sdk-js/tree/main/packages/toolbox-adk):
|
||||
This package provides a seamless way to connect to [Google ADK TS](https://github.com/google/adk-js).
|
||||
|
||||
## Available Packages
|
||||
|
||||
This repository hosts the following TS packages. See the package-specific
|
||||
README for detailed installation and usage instructions:
|
||||
|
||||
| Package | Target Use Case | Integration | Path | Details (README) | Npm Version |
|
||||
| :------ | :---------- | :---------- | :---------------------- | :---------- | :---------- |
|
||||
| `toolbox-core` | Framework-agnostic / Custom applications | Use directly / Custom | `packages/toolbox-core/` | 📄 [View README](https://github.com/googleapis/mcp-toolbox-sdk-js/blob/main/packages/toolbox-core/README.md) |  |
|
||||
| `toolbox-adk` | ADK applications | ADK | `packages/toolbox-adk/` | 📄 [View README](https://github.com/googleapis/mcp-toolbox-sdk-js/blob/main/packages/toolbox-adk/README.md) |  |
|
||||
|
||||
|
||||
## Getting Started
|
||||
|
||||
To get started using Toolbox tools with an application, follow these general steps:
|
||||
|
||||
1. **Set up and Run the Toolbox Service:**
|
||||
|
||||
Before using the SDKs, you need the main MCP Toolbox service running. Follow
|
||||
the instructions here: [**Toolbox Getting Started
|
||||
Guide**](https://github.com/googleapis/genai-toolbox?tab=readme-ov-file#getting-started)
|
||||
|
||||
2. **Install the Appropriate SDK:**
|
||||
|
||||
Choose the package based on your needs (see "[Which Package Should I Use?](#which-package-should-i-use)" above) and install it:
|
||||
|
||||
```bash
|
||||
# For the core, framework-agnostic SDK
|
||||
npm install @toolbox-sdk/core
|
||||
|
||||
# For ADK applications
|
||||
npm install @toolbox-sdk/adk
|
||||
```
|
||||
|
||||
|
||||
|
||||
{{< notice note >}}
|
||||
Source code for [js-sdk](https://github.com/googleapis/mcp-toolbox-sdk-js)
|
||||
{{< /notice >}}
|
||||
@@ -1,477 +0,0 @@
|
||||
---
|
||||
title: "ADK"
|
||||
type: docs
|
||||
weight: 1
|
||||
description: >
|
||||
MCP Toolbox SDK for integrating functionalities of MCP Toolbox into your ADK apps.
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
The `@toolbox-sdk/adk` package provides a Javascript interface to the MCP Toolbox service, enabling you to load and invoke tools from your own applications.
|
||||
|
||||
## Supported Environments
|
||||
|
||||
This SDK is a standard Node.js package built with TypeScript, ensuring broad compatibility with the modern JavaScript ecosystem.
|
||||
|
||||
- Node.js: Actively supported on Node.js v18.x and higher. The package is compatible with both modern ES Module (import) and legacy CommonJS (require).
|
||||
- TypeScript: The SDK is written in TypeScript and ships with its own type declarations, providing a first-class development experience with autocompletion and type-checking out of the box.
|
||||
- JavaScript: Fully supports modern JavaScript in Node.js environments.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
npm install @toolbox-sdk/adk
|
||||
```
|
||||
|
||||
## Quickstart
|
||||
|
||||
|
||||
1. **Start the Toolbox Service**
|
||||
- Make sure the MCP Toolbox service is running. See the [Toolbox Getting Started Guide](/getting-started/introduction/#getting-started).
|
||||
|
||||
2. **Minimal Example**
|
||||
|
||||
Here's a minimal example to get you started. Ensure your Toolbox service is running and accessible.
|
||||
|
||||
```javascript
|
||||
|
||||
import { ToolboxClient } from '@toolbox-sdk/adk';
|
||||
const URL = 'http://127.0.0.1:5000'; // Replace with your Toolbox service URL
|
||||
const client = new ToolboxClient(URL);
|
||||
|
||||
async function quickstart() {
|
||||
try {
|
||||
const tools = await client.loadToolset();
|
||||
// Use tools
|
||||
} catch (error) {
|
||||
console.error("unable to load toolset:", error.message);
|
||||
}
|
||||
}
|
||||
quickstart();
|
||||
```
|
||||
|
||||
{{< notice note>}}
|
||||
This guide uses modern ES Module (`import`) syntax. If your project uses CommonJS, you can import the library using require: `const { ToolboxClient } = require('@toolbox-sdk/adk')`;.
|
||||
{{< /notice >}}
|
||||
|
||||
## Usage
|
||||
|
||||
Import and initialize a Toolbox client, pointing it to the URL of your running Toolbox service.
|
||||
|
||||
```javascript
|
||||
import { ToolboxClient } from '@toolbox-sdk/adk';
|
||||
|
||||
// Replace with the actual URL where your Toolbox service is running
|
||||
const URL = 'http://127.0.0.1:5000';
|
||||
|
||||
let client = new ToolboxClient(URL);
|
||||
const tools = await client.loadToolset();
|
||||
|
||||
// Use the client and tools as per requirement
|
||||
```
|
||||
|
||||
All interactions for loading and invoking tools happen through this client.
|
||||
|
||||
{{< notice note>}}
|
||||
Closing the `ToolboxClient` also closes the underlying network session shared by all tools loaded from that client. As a result, any tool instances you have loaded will cease to function and will raise an error if you attempt to invoke them after the client is closed.
|
||||
{{< /notice >}}
|
||||
|
||||
{{< notice note>}}
|
||||
For advanced use cases, you can provide an external `AxiosInstance` during initialization (e.g., `ToolboxClient(url, my_session)`).
|
||||
{{< /notice >}}
|
||||
|
||||
## Transport Protocols
|
||||
|
||||
The SDK supports multiple transport protocols to communicate with the Toolbox server. You can specify the protocol version during client initialization.
|
||||
|
||||
### Available Protocols
|
||||
|
||||
{{< notice note >}}
|
||||
The native Toolbox protocol (`Protocol.TOOLBOX`) is deprecated and will be removed on March 4, 2026. Please use `Protocol.MCP` or specific MCP versions.
|
||||
{{< /notice >}}
|
||||
|
||||
- `Protocol.MCP`: The default protocol version (currently aliases to `MCP_v20250618`).
|
||||
- `Protocol.MCP_v20241105`: Use this for compatibility with older MCP servers (November 2024 version).
|
||||
- `Protocol.MCP_v20250326`: March 2025 version.
|
||||
- `Protocol.MCP_v20250618`: June 2025 version.
|
||||
- `Protocol.MCP_v20251125`: November 2025 version.
|
||||
- `Protocol.TOOLBOX`: **Deprecated** Legacy Toolbox protocol.
|
||||
|
||||
### Specifying a Protocol
|
||||
|
||||
You can explicitly set the protocol by passing the `protocol` argument to the `ToolboxClient` constructor.
|
||||
|
||||
```javascript
|
||||
import { ToolboxClient, Protocol } from '@toolbox-sdk/adk';
|
||||
|
||||
const URL = 'http://127.0.0.1:5000';
|
||||
|
||||
// Initialize with a specific protocol version
|
||||
const client = new ToolboxClient(URL, null, null, Protocol.MCP_v20241105);
|
||||
|
||||
const tools = await client.loadToolset();
|
||||
```
|
||||
|
||||
## Loading Tools
|
||||
|
||||
You can load tools individually or in groups (toolsets) as defined in your Toolbox service configuration. Loading a toolset is convenient when working with multiple related functions, while loading a single tool offers more granular control.
|
||||
|
||||
### Load a toolset
|
||||
|
||||
A toolset is a collection of related tools. You can load all tools in a toolset or a specific one:
|
||||
|
||||
```javascript
|
||||
// Load all tools
|
||||
const tools = await toolbox.loadToolset()
|
||||
|
||||
// Load a specific toolset
|
||||
const tools = await toolbox.loadToolset("my-toolset")
|
||||
```
|
||||
|
||||
### Load a single tool
|
||||
|
||||
Loads a specific tool by its unique name. This provides fine-grained control.
|
||||
|
||||
```javascript
|
||||
const tool = await toolbox.loadTool("my-tool")
|
||||
```
|
||||
|
||||
## Invoking Tools
|
||||
|
||||
Once loaded, tools behave like awaitable JS functions. You invoke them using `await` and pass arguments corresponding to the parameters defined in the tool's configuration within the Toolbox service.
|
||||
|
||||
```javascript
|
||||
const tool = await client.loadTool("my-tool")
|
||||
const result = await tool.runAsync(args: {a: 5, b: 2})
|
||||
```
|
||||
|
||||
{{< notice tip>}}
|
||||
For a more comprehensive guide on setting up the Toolbox service itself, which you'll need running to use this SDK, please refer to the [Toolbox Quickstart Guide](getting-started/local_quickstart).
|
||||
{{< /notice >}}
|
||||
|
||||
## Client to Server Authentication
|
||||
|
||||
This section describes how to authenticate the ToolboxClient itself when
|
||||
connecting to a Toolbox server instance that requires authentication. This is
|
||||
crucial for securing your Toolbox server endpoint, especially when deployed on
|
||||
platforms like Cloud Run, GKE, or any environment where unauthenticated access is restricted.
|
||||
|
||||
This client-to-server authentication ensures that the Toolbox server can verify
|
||||
the identity of the client making the request before any tool is loaded or
|
||||
called. It is different from [Authenticating Tools](#authenticating-tools),
|
||||
which deals with providing credentials for specific tools within an already
|
||||
connected Toolbox session.
|
||||
|
||||
### When is Client-to-Server Authentication Needed?
|
||||
|
||||
You'll need this type of authentication if your Toolbox server is configured to
|
||||
deny unauthenticated requests. For example:
|
||||
|
||||
- Your Toolbox server is deployed on Cloud Run and configured to "Require authentication."
|
||||
- Your server is behind an Identity-Aware Proxy (IAP) or a similar
|
||||
authentication layer.
|
||||
- You have custom authentication middleware on your self-hosted Toolbox server.
|
||||
|
||||
Without proper client authentication in these scenarios, attempts to connect or
|
||||
make calls (like `load_tool`) will likely fail with `Unauthorized` errors.
|
||||
|
||||
### How it works
|
||||
|
||||
The `ToolboxClient` allows you to specify functions that dynamically generate
|
||||
HTTP headers for every request sent to the Toolbox server. The most common use
|
||||
case is to add an [Authorization
|
||||
header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Authorization)
|
||||
with a bearer token (e.g., a Google ID token).
|
||||
|
||||
These header-generating functions are called just before each request, ensuring
|
||||
that fresh credentials or header values can be used.
|
||||
|
||||
### Configuration
|
||||
|
||||
You can configure these dynamic headers as seen below:
|
||||
|
||||
```javascript
|
||||
import { ToolboxClient } from '@toolbox-sdk/adk';
|
||||
import {getGoogleIdToken} from '@toolbox-sdk/core/auth'
|
||||
|
||||
const URL = 'http://127.0.0.1:5000';
|
||||
const getGoogleIdTokenGetter = () => getGoogleIdToken(URL);
|
||||
const client = new ToolboxClient(URL, null, {"Authorization": getGoogleIdTokenGetter});
|
||||
|
||||
// Use the client as usual
|
||||
```
|
||||
|
||||
### Authenticating with Google Cloud Servers
|
||||
|
||||
For Toolbox servers hosted on Google Cloud (e.g., Cloud Run) and requiring
|
||||
`Google ID token` authentication, the helper module
|
||||
[auth_methods](src/toolbox_core/authMethods.ts) provides utility functions.
|
||||
|
||||
### Step by Step Guide for Cloud Run
|
||||
|
||||
1. **Configure Permissions**: [Grant](https://cloud.google.com/run/docs/securing/managing-access#service-add-principals) the `roles/run.invoker` IAM role on the Cloud
|
||||
Run service to the principal. This could be your `user account email` or a
|
||||
`service account`.
|
||||
2. **Configure Credentials**
|
||||
- Local Development: Set up
|
||||
[ADC](https://cloud.google.com/docs/authentication/set-up-adc-local-dev-environment).
|
||||
- Google Cloud Environments: When running within Google Cloud (e.g., Compute
|
||||
Engine, GKE, another Cloud Run service, Cloud Functions), ADC is typically
|
||||
configured automatically, using the environment's default service account.
|
||||
3. **Connect to the Toolbox Server**
|
||||
|
||||
```javascript
|
||||
import { ToolboxClient } from '@toolbox-sdk/adk';
|
||||
import {getGoogleIdToken} from '@toolbox-sdk/core/auth'
|
||||
|
||||
const URL = 'http://127.0.0.1:5000';
|
||||
const getGoogleIdTokenGetter = () => getGoogleIdToken(URL);
|
||||
const client = new ToolboxClient(URL, null, {"Authorization": getGoogleIdTokenGetter});
|
||||
|
||||
// Use the client as usual
|
||||
```
|
||||
|
||||
## Authenticating Tools
|
||||
|
||||
{{< notice note>}}
|
||||
**Always use HTTPS** to connect your application with the Toolbox service, especially in **production environments** or whenever the communication involves **sensitive data** (including scenarios where tools require authentication tokens). Using plain HTTP lacks encryption and exposes your application and data to significant security risks, such as eavesdropping and tampering.
|
||||
{{< /notice >}}
|
||||
|
||||
Tools can be configured within the Toolbox service to require authentication,
|
||||
ensuring only authorized users or applications can invoke them, especially when
|
||||
accessing sensitive data.
|
||||
|
||||
### When is Authentication Needed?
|
||||
|
||||
Authentication is configured per-tool within the Toolbox service itself. If a
|
||||
tool you intend to use is marked as requiring authentication in the service, you
|
||||
must configure the SDK client to provide the necessary credentials (currently
|
||||
Oauth2 tokens) when invoking that specific tool.
|
||||
|
||||
### Supported Authentication Mechanisms
|
||||
|
||||
The Toolbox service enables secure tool usage through **Authenticated Parameters**. For detailed information on how these mechanisms work within the Toolbox service and how to configure them, please refer to [Toolbox Service Documentation - Authenticated Parameters](resources/tools/#authenticated-parameters)
|
||||
|
||||
### Step 1: Configure Tools in Toolbox Service
|
||||
|
||||
First, ensure the target tool(s) are configured correctly in the Toolbox service
|
||||
to require authentication. Refer to the [Toolbox Service Documentation -
|
||||
Authenticated
|
||||
Parameters](resources/tools/#authenticated-parameters)
|
||||
for instructions.
|
||||
|
||||
### Step 2: Configure SDK Client
|
||||
|
||||
Your application needs a way to obtain the required Oauth2 token for the
|
||||
authenticated user. The SDK requires you to provide a function capable of
|
||||
retrieving this token *when the tool is invoked*.
|
||||
|
||||
#### Provide an ID Token Retriever Function
|
||||
|
||||
You must provide the SDK with a function (sync or async) that returns the
|
||||
necessary token when called. The implementation depends on your application's
|
||||
authentication flow (e.g., retrieving a stored token, initiating an OAuth flow).
|
||||
|
||||
{{< notice note>}}
|
||||
The name used when registering the getter function with the SDK (e.g., `"my_api_token"`) must exactly match the `name` of the corresponding `authServices` defined in the tool's configuration within the Toolbox service.
|
||||
{{< /notice >}}
|
||||
|
||||
```javascript
|
||||
|
||||
async function getAuthToken() {
|
||||
// ... Logic to retrieve ID token (e.g., from local storage, OAuth flow)
|
||||
// This example just returns a placeholder. Replace with your actual token retrieval.
|
||||
return "YOUR_ID_TOKEN" // Placeholder
|
||||
}
|
||||
```
|
||||
{{< notice tip>}}
|
||||
Your token retriever function is invoked every time an authenticated parameter requires a token for a tool call. Consider implementing caching logic within this function to avoid redundant token fetching or generation, especially for tokens with longer validity periods or if the retrieval process is resource-intensive.
|
||||
{{< /notice >}}
|
||||
|
||||
#### Option A: Add Authentication to a Loaded Tool
|
||||
|
||||
You can add the token retriever function to a tool object *after* it has been
|
||||
loaded. This modifies the specific tool instance.
|
||||
|
||||
```javascript
|
||||
const URL = 'http://127.0.0.1:5000';
|
||||
let client = new ToolboxClient(URL);
|
||||
let tool = await client.loadTool("my-tool")
|
||||
|
||||
const authTool = tool.addAuthTokenGetter("my_auth", get_auth_token) // Single token
|
||||
|
||||
// OR
|
||||
|
||||
const multiAuthTool = tool.addAuthTokenGetters({
|
||||
"my_auth_1": getAuthToken1,
|
||||
"my_auth_2": getAuthToken2,
|
||||
}) // Multiple tokens
|
||||
```
|
||||
|
||||
#### Option B: Add Authentication While Loading Tools
|
||||
|
||||
You can provide the token retriever(s) directly during the `loadTool` or
|
||||
`loadToolset` calls. This applies the authentication configuration only to the
|
||||
tools loaded in that specific call, without modifying the original tool objects
|
||||
if they were loaded previously.
|
||||
|
||||
```javascript
|
||||
const authTool = await toolbox.loadTool("toolName", {"myAuth": getAuthToken})
|
||||
|
||||
// OR
|
||||
|
||||
const authTools = await toolbox.loadToolset({"myAuth": getAuthToken})
|
||||
```
|
||||
|
||||
{{< notice note>}}
|
||||
Adding auth tokens during loading only affect the tools loaded within that call.
|
||||
{{< /notice >}}
|
||||
|
||||
### Complete Authentication Example
|
||||
|
||||
```javascript
|
||||
import { ToolboxClient } from '@toolbox-sdk/adk';
|
||||
|
||||
async function getAuthToken() {
|
||||
// ... Logic to retrieve ID token (e.g., from local storage, OAuth flow)
|
||||
// This example just returns a placeholder. Replace with your actual token retrieval.
|
||||
return "YOUR_ID_TOKEN" // Placeholder
|
||||
}
|
||||
|
||||
const URL = 'http://127.0.0.1:5000';
|
||||
let client = new ToolboxClient(URL);
|
||||
const tool = await client.loadTool("my-tool");
|
||||
const authTool = tool.addAuthTokenGetters({"my_auth": getAuthToken});
|
||||
const result = await authTool.runAsync(args: {input:"some input"});
|
||||
console.log(result);
|
||||
```
|
||||
|
||||
## Binding Parameter Values
|
||||
|
||||
The SDK allows you to pre-set, or "bind", values for specific tool parameters
|
||||
before the tool is invoked or even passed to an LLM. These bound values are
|
||||
fixed and will not be requested or modified by the LLM during tool use.
|
||||
|
||||
### Why Bind Parameters?
|
||||
|
||||
- **Protecting sensitive information:** API keys, secrets, etc.
|
||||
- **Enforcing consistency:** Ensuring specific values for certain parameters.
|
||||
- **Pre-filling known data:** Providing defaults or context.
|
||||
|
||||
{{< notice note>}}
|
||||
The parameter names used for binding (e.g., `"api_key"`) must exactly match the parameter names defined in the tool's configuration within the Toolbox service.
|
||||
{{< /notice >}}
|
||||
|
||||
{{< notice note>}}
|
||||
You do not need to modify the tool's configuration in the Toolbox service to
|
||||
> bind parameter values using the SDK.
|
||||
{{< /notice >}}
|
||||
|
||||
### Option A: Binding Parameters to a Loaded Tool
|
||||
|
||||
Bind values to a tool object *after* it has been loaded. This modifies the
|
||||
specific tool instance.
|
||||
|
||||
```javascript
|
||||
|
||||
import { ToolboxClient } from '@toolbox-sdk/adk';
|
||||
|
||||
const URL = 'http://127.0.0.1:5000';
|
||||
let client = new ToolboxClient(URL);
|
||||
const tool = await client.loadTool("my-tool");
|
||||
|
||||
const boundTool = tool.bindParam("param", "value");
|
||||
|
||||
// OR
|
||||
|
||||
const boundTool = tool.bindParams({"param": "value"});
|
||||
```
|
||||
|
||||
### Option B: Binding Parameters While Loading Tools
|
||||
|
||||
Specify bound parameters directly when loading tools. This applies the binding
|
||||
only to the tools loaded in that specific call.
|
||||
|
||||
```javascript
|
||||
const boundTool = await client.loadTool("my-tool", null, {"param": "value"})
|
||||
|
||||
// OR
|
||||
|
||||
const boundTools = await client.loadToolset(null, {"param": "value"})
|
||||
```
|
||||
|
||||
{{< notice note>}}
|
||||
Bound values during loading only affect the tools loaded in that call.
|
||||
{{< /notice >}}
|
||||
|
||||
### Binding Dynamic Values
|
||||
|
||||
Instead of a static value, you can bind a parameter to a synchronous or
|
||||
asynchronous function. This function will be called *each time* the tool is
|
||||
invoked to dynamically determine the parameter's value at runtime.
|
||||
|
||||
```javascript
|
||||
|
||||
async function getDynamicValue() {
|
||||
// Logic to determine the value
|
||||
return "dynamicValue";
|
||||
}
|
||||
|
||||
const dynamicBoundTool = tool.bindParam("param", getDynamicValue)
|
||||
```
|
||||
|
||||
{{< notice note>}}
|
||||
You don't need to modify tool configurations to bind parameter values.
|
||||
{{< /notice >}}
|
||||
|
||||
# Using with ADK
|
||||
|
||||
ADK JS:
|
||||
|
||||
```javascript
|
||||
import {FunctionTool, InMemoryRunner, LlmAgent} from '@google/adk';
|
||||
import {Content} from '@google/genai';
|
||||
import {ToolboxClient} from '@toolbox-sdk/core'
|
||||
|
||||
const toolboxClient = new ToolboxClient("http://127.0.0.1:5000");
|
||||
const loadedTools = await toolboxClient.loadToolset();
|
||||
|
||||
export const rootAgent = new LlmAgent({
|
||||
name: 'weather_time_agent',
|
||||
model: 'gemini-3-flash-preview',
|
||||
description:
|
||||
'Agent to answer questions about the time and weather in a city.',
|
||||
instruction:
|
||||
'You are a helpful agent who can answer user questions about the time and weather in a city.',
|
||||
tools: loadedTools,
|
||||
});
|
||||
|
||||
async function main() {
|
||||
const userId = 'test_user';
|
||||
const appName = rootAgent.name;
|
||||
const runner = new InMemoryRunner({agent: rootAgent, appName});
|
||||
const session = await runner.sessionService.createSession({
|
||||
appName,
|
||||
userId,
|
||||
});
|
||||
|
||||
const prompt = 'What is the weather in New York? And the time?';
|
||||
const content: Content = {
|
||||
role: 'user',
|
||||
parts: [{text: prompt}],
|
||||
};
|
||||
console.log(content);
|
||||
for await (const e of runner.runAsync({
|
||||
userId,
|
||||
sessionId: session.id,
|
||||
newMessage: content,
|
||||
})) {
|
||||
if (e.content?.parts?.[0]?.text) {
|
||||
console.log(`${e.author}: ${JSON.stringify(e.content, null, 2)}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
```
|
||||
@@ -1,520 +0,0 @@
|
||||
---
|
||||
title: "Core"
|
||||
type: docs
|
||||
weight: 2
|
||||
description: >
|
||||
MCP Toolbox Core SDK for integrating functionalities of MCP Toolbox into your Agentic apps.
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
The `@toolbox-sdk/core` package provides a Javascript interface to the MCP Toolbox service, enabling you to load and invoke tools from your own applications.
|
||||
|
||||
## Supported Environments
|
||||
|
||||
This SDK is a standard Node.js package built with TypeScript, ensuring broad compatibility with the modern JavaScript ecosystem.
|
||||
|
||||
- Node.js: Actively supported on Node.js v18.x and higher. The package is compatible with both modern ES Module (import) and legacy CommonJS (require).
|
||||
- TypeScript: The SDK is written in TypeScript and ships with its own type declarations, providing a first-class development experience with autocompletion and type-checking out of the box.
|
||||
- JavaScript: Fully supports modern JavaScript in Node.js environments.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
npm install @toolbox-sdk/core
|
||||
```
|
||||
|
||||
## Quickstart
|
||||
|
||||
|
||||
1. **Start the Toolbox Service**
|
||||
- Make sure the MCP Toolbox service is running. See the [Toolbox Getting Started Guide](/getting-started/introduction/#getting-started).
|
||||
|
||||
2. **Minimal Example**
|
||||
|
||||
Here's a minimal example to get you started. Ensure your Toolbox service is running and accessible.
|
||||
|
||||
```javascript
|
||||
|
||||
import { ToolboxClient } from '@toolbox-sdk/core';
|
||||
const URL = 'http://127.0.0.1:5000'; // Replace with your Toolbox service URL
|
||||
const client = new ToolboxClient(URL);
|
||||
|
||||
async function quickstart() {
|
||||
try {
|
||||
const tools = await client.loadToolset();
|
||||
// Use tools
|
||||
} catch (error) {
|
||||
console.error("unable to load toolset:", error.message);
|
||||
}
|
||||
}
|
||||
quickstart();
|
||||
```
|
||||
|
||||
{{< notice note>}}
|
||||
This guide uses modern ES Module (`import`) syntax. If your project uses CommonJS, you can import the library using require: `const { ToolboxClient } = require('@toolbox-sdk/core')`;.
|
||||
{{< /notice >}}
|
||||
|
||||
## Usage
|
||||
|
||||
Import and initialize a Toolbox client, pointing it to the URL of your running Toolbox service.
|
||||
|
||||
```javascript
|
||||
import { ToolboxClient } from '@toolbox-sdk/core';
|
||||
|
||||
// Replace with the actual URL where your Toolbox service is running
|
||||
const URL = 'http://127.0.0.1:5000';
|
||||
|
||||
let client = new ToolboxClient(URL);
|
||||
const tools = await client.loadToolset();
|
||||
|
||||
// Use the client and tools as per requirement
|
||||
```
|
||||
|
||||
All interactions for loading and invoking tools happen through this client.
|
||||
|
||||
{{< notice note>}}
|
||||
Closing the `ToolboxClient` also closes the underlying network session shared by all tools loaded from that client. As a result, any tool instances you have loaded will cease to function and will raise an error if you attempt to invoke them after the client is closed.
|
||||
{{< /notice >}}
|
||||
|
||||
{{< notice note>}}
|
||||
For advanced use cases, you can provide an external `AxiosInstance` during initialization (e.g., `ToolboxClient(url, my_session)`).
|
||||
{{< /notice >}}
|
||||
|
||||
## Transport Protocols
|
||||
|
||||
The SDK supports multiple transport protocols to communicate with the Toolbox server. You can specify the protocol version during client initialization.
|
||||
|
||||
### Available Protocols
|
||||
|
||||
{{ <notice note > }}
|
||||
The native Toolbox protocol (Protocol.TOOLBOX) is deprecated and will be removed on March 4, 2026. Please use Protocol.MCP or specific MCP versions.
|
||||
{{ < /notice >}}
|
||||
|
||||
- `Protocol.MCP`: The default protocol version (currently aliases to `MCP_v20250618`).
|
||||
- `Protocol.MCP_v20241105`: Use this for compatibility with older MCP servers (November 2024 version).
|
||||
- `Protocol.MCP_v20250326`: March 2025 version.
|
||||
- `Protocol.MCP_v20250618`: June 2025 version.
|
||||
- `Protocol.MCP_v20251125`: November 2025 version.
|
||||
- `Protocol.TOOLBOX`: **Deprecated** Legacy Toolbox protocol.
|
||||
|
||||
### Specifying a Protocol
|
||||
|
||||
You can explicitly set the protocol by passing the `protocol` argument to the `ToolboxClient` constructor.
|
||||
|
||||
```javascript
|
||||
import { ToolboxClient, Protocol } from '@toolbox-sdk/core';
|
||||
|
||||
const URL = 'http://127.0.0.1:5000';
|
||||
|
||||
// Initialize with a specific protocol version
|
||||
const client = new ToolboxClient(URL, null, null, Protocol.MCP_v20241105);
|
||||
|
||||
const tools = await client.loadToolset();
|
||||
```
|
||||
|
||||
## Loading Tools
|
||||
|
||||
You can load tools individually or in groups (toolsets) as defined in your Toolbox service configuration. Loading a toolset is convenient when working with multiple related functions, while loading a single tool offers more granular control.
|
||||
|
||||
### Load a toolset
|
||||
|
||||
A toolset is a collection of related tools. You can load all tools in a toolset or a specific one:
|
||||
|
||||
```javascript
|
||||
// Load all tools
|
||||
const tools = await client.loadToolset()
|
||||
|
||||
// Load a specific toolset
|
||||
const tools = await client.loadToolset("my-toolset")
|
||||
```
|
||||
|
||||
### Load a single tool
|
||||
|
||||
Loads a specific tool by its unique name. This provides fine-grained control.
|
||||
|
||||
```javascript
|
||||
const tool = await client.loadTool("my-tool")
|
||||
```
|
||||
|
||||
## Invoking Tools
|
||||
|
||||
Once loaded, tools behave like awaitable JS functions. You invoke them using `await` and pass arguments corresponding to the parameters defined in the tool's configuration within the Toolbox service.
|
||||
|
||||
```javascript
|
||||
const tool = await client.loadTool("my-tool")
|
||||
const result = await tool({a: 5, b: 2})
|
||||
```
|
||||
|
||||
{{< notice tip>}}
|
||||
For a more comprehensive guide on setting up the Toolbox service itself, which you'll need running to use this SDK, please refer to the [Toolbox Quickstart Guide](getting-started/local_quickstart).
|
||||
{{< /notice >}}
|
||||
|
||||
## Client to Server Authentication
|
||||
|
||||
This section describes how to authenticate the ToolboxClient itself when
|
||||
connecting to a Toolbox server instance that requires authentication. This is
|
||||
crucial for securing your Toolbox server endpoint, especially when deployed on
|
||||
platforms like Cloud Run, GKE, or any environment where unauthenticated access is restricted.
|
||||
|
||||
This client-to-server authentication ensures that the Toolbox server can verify
|
||||
the identity of the client making the request before any tool is loaded or
|
||||
called. It is different from [Authenticating Tools](#authenticating-tools),
|
||||
which deals with providing credentials for specific tools within an already
|
||||
connected Toolbox session.
|
||||
|
||||
### When is Client-to-Server Authentication Needed?
|
||||
|
||||
You'll need this type of authentication if your Toolbox server is configured to
|
||||
deny unauthenticated requests. For example:
|
||||
|
||||
- Your Toolbox server is deployed on Cloud Run and configured to "Require authentication."
|
||||
- Your server is behind an Identity-Aware Proxy (IAP) or a similar authentication layer.
|
||||
- You have custom authentication middleware on your self-hosted Toolbox server.
|
||||
|
||||
Without proper client authentication in these scenarios, attempts to connect or
|
||||
make calls (like `load_tool`) will likely fail with `Unauthorized` errors.
|
||||
|
||||
### How it works
|
||||
|
||||
The `ToolboxClient` allows you to specify functions that dynamically generate
|
||||
HTTP headers for every request sent to the Toolbox server. The most common use
|
||||
case is to add an [Authorization
|
||||
header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Authorization)
|
||||
with a bearer token (e.g., a Google ID token).
|
||||
|
||||
These header-generating functions are called just before each request, ensuring that fresh credentials or header values can be used.
|
||||
|
||||
### Configuration
|
||||
|
||||
You can configure these dynamic headers as seen below:
|
||||
|
||||
```javascript
|
||||
import { ToolboxClient } from '@toolbox-sdk/core';
|
||||
import {getGoogleIdToken} from '@toolbox-sdk/core/auth'
|
||||
|
||||
const URL = 'http://127.0.0.1:5000';
|
||||
const getGoogleIdTokenGetter = () => getGoogleIdToken(URL);
|
||||
const client = new ToolboxClient(URL, null, {"Authorization": getGoogleIdTokenGetter});
|
||||
|
||||
// Use the client as usual
|
||||
```
|
||||
|
||||
### Authenticating with Google Cloud Servers
|
||||
|
||||
For Toolbox servers hosted on Google Cloud (e.g., Cloud Run) and requiring
|
||||
`Google ID token` authentication, the helper module
|
||||
[auth_methods](https://github.com/googleapis/mcp-toolbox-sdk-js/blob/main/packages/toolbox-core/src/toolbox_core/authMethods.ts) provides utility functions.
|
||||
|
||||
### Step by Step Guide for Cloud Run
|
||||
|
||||
1. **Configure Permissions**: [Grant](https://cloud.google.com/run/docs/securing/managing-access#service-add-principals) the `roles/run.invoker` IAM role on the Cloud
|
||||
Run service to the principal. This could be your `user account email` or a
|
||||
`service account`.
|
||||
2. **Configure Credentials**
|
||||
- Local Development: Set up
|
||||
[ADC](https://cloud.google.com/docs/authentication/set-up-adc-local-dev-environment).
|
||||
- Google Cloud Environments: When running within Google Cloud (e.g., Compute
|
||||
Engine, GKE, another Cloud Run service, Cloud Functions), ADC is typically
|
||||
configured automatically, using the environment's default service account.
|
||||
3. **Connect to the Toolbox Server**
|
||||
|
||||
```javascript
|
||||
import { ToolboxClient } from '@toolbox-sdk/core';
|
||||
import {getGoogleIdToken} from '@toolbox-sdk/core/auth'
|
||||
|
||||
const URL = 'http://127.0.0.1:5000';
|
||||
const getGoogleIdTokenGetter = () => getGoogleIdToken(URL);
|
||||
const client = new ToolboxClient(URL, null, {"Authorization": getGoogleIdTokenGetter});
|
||||
|
||||
// Use the client as usual
|
||||
```
|
||||
|
||||
## Authenticating Tools
|
||||
|
||||
{{< notice note>}}
|
||||
**Always use HTTPS** to connect your application with the Toolbox service, especially in **production environments** or whenever the communication involves **sensitive data** (including scenarios where tools require authentication tokens). Using plain HTTP lacks encryption and exposes your application and data to significant security risks, such as eavesdropping and tampering.
|
||||
{{< /notice >}}
|
||||
|
||||
Tools can be configured within the Toolbox service to require authentication,
|
||||
ensuring only authorized users or applications can invoke them, especially when
|
||||
accessing sensitive data.
|
||||
|
||||
### When is Authentication Needed?
|
||||
|
||||
Authentication is configured per-tool within the Toolbox service itself. If a
|
||||
tool you intend to use is marked as requiring authentication in the service, you
|
||||
must configure the SDK client to provide the necessary credentials (currently
|
||||
Oauth2 tokens) when invoking that specific tool.
|
||||
|
||||
### Supported Authentication Mechanisms
|
||||
|
||||
The Toolbox service enables secure tool usage through **Authenticated Parameters**. For detailed information on how these mechanisms work within the Toolbox service and how to configure them, please refer to [Toolbox Service Documentation - Authenticated Parameters](resources/tools/#authenticated-parameters)
|
||||
|
||||
### Step 1: Configure Tools in Toolbox Service
|
||||
|
||||
First, ensure the target tool(s) are configured correctly in the Toolbox service
|
||||
to require authentication. Refer to the [Toolbox Service Documentation -
|
||||
Authenticated
|
||||
Parameters](resources/tools/#authenticated-parameters)
|
||||
for instructions.
|
||||
|
||||
### Step 2: Configure SDK Client
|
||||
|
||||
Your application needs a way to obtain the required Oauth2 token for the
|
||||
authenticated user. The SDK requires you to provide a function capable of
|
||||
retrieving this token *when the tool is invoked*.
|
||||
|
||||
#### Provide an ID Token Retriever Function
|
||||
|
||||
You must provide the SDK with a function (sync or async) that returns the
|
||||
necessary token when called. The implementation depends on your application's
|
||||
authentication flow (e.g., retrieving a stored token, initiating an OAuth flow).
|
||||
|
||||
{{< notice note>}}
|
||||
The name used when registering the getter function with the SDK (e.g., `"my_api_token"`) must exactly match the `name` of the corresponding `authServices` defined in the tool's configuration within the Toolbox service.
|
||||
{{< /notice >}}
|
||||
|
||||
```javascript
|
||||
|
||||
async function getAuthToken() {
|
||||
// ... Logic to retrieve ID token (e.g., from local storage, OAuth flow)
|
||||
// This example just returns a placeholder. Replace with your actual token retrieval.
|
||||
return "YOUR_ID_TOKEN" // Placeholder
|
||||
}
|
||||
```
|
||||
{{< notice tip>}}
|
||||
Your token retriever function is invoked every time an authenticated parameter requires a token for a tool call. Consider implementing caching logic within this function to avoid redundant token fetching or generation, especially for tokens with longer validity periods or if the retrieval process is resource-intensive.
|
||||
{{< /notice >}}
|
||||
|
||||
#### Option A: Add Authentication to a Loaded Tool
|
||||
|
||||
You can add the token retriever function to a tool object *after* it has been
|
||||
loaded. This modifies the specific tool instance.
|
||||
|
||||
```javascript
|
||||
const URL = 'http://127.0.0.1:5000';
|
||||
let client = new ToolboxClient(URL);
|
||||
let tool = await client.loadTool("my-tool")
|
||||
|
||||
const authTool = tool.addAuthTokenGetter("my_auth", get_auth_token) // Single token
|
||||
|
||||
// OR
|
||||
|
||||
const multiAuthTool = tool.addAuthTokenGetters({
|
||||
"my_auth_1": getAuthToken1,
|
||||
"my_auth_2": getAuthToken2,
|
||||
}) // Multiple tokens
|
||||
```
|
||||
|
||||
#### Option B: Add Authentication While Loading Tools
|
||||
|
||||
You can provide the token retriever(s) directly during the `loadTool` or
|
||||
`loadToolset` calls. This applies the authentication configuration only to the
|
||||
tools loaded in that specific call, without modifying the original tool objects
|
||||
if they were loaded previously.
|
||||
|
||||
```javascript
|
||||
const authTool = await client.loadTool("toolName", {"myAuth": getAuthToken})
|
||||
|
||||
// OR
|
||||
|
||||
const authTools = await client.loadToolset({"myAuth": getAuthToken})
|
||||
```
|
||||
|
||||
{{< notice note>}}
|
||||
Adding auth tokens during loading only affect the tools loaded within that call.
|
||||
{{< /notice >}}
|
||||
|
||||
### Complete Authentication Example
|
||||
|
||||
```javascript
|
||||
import { ToolboxClient } from '@toolbox-sdk/core';
|
||||
|
||||
async function getAuthToken() {
|
||||
// ... Logic to retrieve ID token (e.g., from local storage, OAuth flow)
|
||||
// This example just returns a placeholder. Replace with your actual token retrieval.
|
||||
return "YOUR_ID_TOKEN" // Placeholder
|
||||
}
|
||||
|
||||
const URL = 'http://127.0.0.1:5000';
|
||||
let client = new ToolboxClient(URL);
|
||||
const tool = await client.loadTool("my-tool");
|
||||
const authTool = tool.addAuthTokenGetters({"my_auth": getAuthToken});
|
||||
const result = await authTool({input:"some input"});
|
||||
console.log(result);
|
||||
```
|
||||
|
||||
## Binding Parameter Values
|
||||
|
||||
The SDK allows you to pre-set, or "bind", values for specific tool parameters
|
||||
before the tool is invoked or even passed to an LLM. These bound values are
|
||||
fixed and will not be requested or modified by the LLM during tool use.
|
||||
|
||||
### Why Bind Parameters?
|
||||
|
||||
- **Protecting sensitive information:** API keys, secrets, etc.
|
||||
- **Enforcing consistency:** Ensuring specific values for certain parameters.
|
||||
- **Pre-filling known data:** Providing defaults or context.
|
||||
|
||||
{{< notice note>}}
|
||||
The parameter names used for binding (e.g., `"api_key"`) must exactly match the parameter names defined in the tool's configuration within the Toolbox service.
|
||||
{{< /notice >}}
|
||||
|
||||
{{< notice note>}}
|
||||
You do not need to modify the tool's configuration in the Toolbox service to bind parameter values using the SDK.
|
||||
{{< /notice >}}
|
||||
|
||||
### Option A: Binding Parameters to a Loaded Tool
|
||||
|
||||
Bind values to a tool object *after* it has been loaded. This modifies the
|
||||
specific tool instance.
|
||||
|
||||
```javascript
|
||||
|
||||
import { ToolboxClient } from '@toolbox-sdk/core';
|
||||
|
||||
const URL = 'http://127.0.0.1:5000';
|
||||
let client = new ToolboxClient(URL);
|
||||
const tool = await client.loadTool("my-tool");
|
||||
|
||||
const boundTool = tool.bindParam("param", "value");
|
||||
|
||||
// OR
|
||||
|
||||
const boundTool = tool.bindParams({"param": "value"});
|
||||
```
|
||||
|
||||
### Option B: Binding Parameters While Loading Tools
|
||||
|
||||
Specify bound parameters directly when loading tools. This applies the binding
|
||||
only to the tools loaded in that specific call.
|
||||
|
||||
```javascript
|
||||
const boundTool = await client.loadTool("my-tool", null, {"param": "value"})
|
||||
|
||||
// OR
|
||||
|
||||
const boundTools = await client.loadToolset(null, {"param": "value"})
|
||||
```
|
||||
|
||||
{{< notice note>}}
|
||||
Bound values during loading only affect the tools loaded in that call.
|
||||
{{< /notice >}}
|
||||
|
||||
### Binding Dynamic Values
|
||||
|
||||
Instead of a static value, you can bind a parameter to a synchronous or
|
||||
asynchronous function. This function will be called *each time* the tool is
|
||||
invoked to dynamically determine the parameter's value at runtime.
|
||||
|
||||
|
||||
```javascript
|
||||
|
||||
async function getDynamicValue() {
|
||||
// Logic to determine the value
|
||||
return "dynamicValue";
|
||||
}
|
||||
|
||||
const dynamicBoundTool = tool.bindParam("param", getDynamicValue)
|
||||
```
|
||||
|
||||
{{< notice note>}}
|
||||
You don't need to modify tool configurations to bind parameter values.
|
||||
{{< /notice >}}
|
||||
|
||||
# Using with Orchestration Frameworks
|
||||
|
||||
<details open>
|
||||
|
||||
<summary>Langchain</summary>
|
||||
|
||||
[LangchainJS](https://js.langchain.com/docs/introduction/)
|
||||
|
||||
```javascript
|
||||
import {ToolboxClient} from "@toolbox-sdk/core"
|
||||
import { tool } from "@langchain/core/tools";
|
||||
|
||||
let client = ToolboxClient(URL)
|
||||
multiplyTool = await client.loadTool("multiply")
|
||||
|
||||
const multiplyNumbers = tool(multiplyTool, {
|
||||
name: multiplyTool.getName(),
|
||||
description: multiplyTool.getDescription(),
|
||||
schema: multiplyTool.getParamSchema()
|
||||
});
|
||||
|
||||
await multiplyNumbers.invoke({ a: 2, b: 3 });
|
||||
```
|
||||
|
||||
The `multiplyNumbers` tool is compatible with [Langchain/Langraph
|
||||
agents](http://js.langchain.com/docs/concepts/agents/)
|
||||
such as [React
|
||||
Agents](https://langchain-ai.github.io/langgraphjs/reference/functions/langgraph_prebuilt.createReactAgent.html).
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
|
||||
<summary>LlamaIndex</summary>
|
||||
|
||||
[LlamaindexTS](https://ts.llamaindex.ai/)
|
||||
|
||||
```javascript
|
||||
import {ToolboxClient} from "@toolbox-sdk/core"
|
||||
import { tool } from "llamaindex";
|
||||
|
||||
let client = ToolboxClient(URL)
|
||||
multiplyTool = await client.loadTool("multiply")
|
||||
|
||||
const multiplyNumbers = tool({
|
||||
name: multiplyTool.getName(),
|
||||
description: multiplyTool.getDescription(),
|
||||
parameters: multiplyTool.getParamSchema(),
|
||||
execute: multiplyTool
|
||||
});
|
||||
|
||||
await multiplyNumbers.call({ a: 2, b: 3 });
|
||||
```
|
||||
|
||||
The `multiplyNumbers` tool is compatible with LlamaIndex
|
||||
[agents](https://ts.llamaindex.ai/docs/llamaindex/migration/deprecated/agent)
|
||||
and [agent
|
||||
workflows](https://ts.llamaindex.ai/docs/llamaindex/modules/agents/agent_workflow).
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Genkit</summary>
|
||||
|
||||
[GenkitJS](https://genkit.dev/docs/get-started/#_top)
|
||||
```javascript
|
||||
import {ToolboxClient} from "@toolbox-sdk/core"
|
||||
import { genkit, z } from 'genkit';
|
||||
import { googleAI } from '@genkit-ai/googleai';
|
||||
|
||||
|
||||
let client = ToolboxClient(URL)
|
||||
multiplyTool = await client.loadTool("multiply")
|
||||
|
||||
const ai = genkit({
|
||||
plugins: [googleAI()],
|
||||
model: googleAI.model('gemini-3-flash-preview'),
|
||||
});
|
||||
|
||||
const multiplyNumbers = ai.defineTool({
|
||||
name: multiplyTool.getName(),
|
||||
description: multiplyTool.getDescription(),
|
||||
inputSchema: multiplyTool.getParamSchema(),
|
||||
},
|
||||
multiplyTool,
|
||||
);
|
||||
|
||||
await ai.generate({
|
||||
prompt: 'Can you multiply 5 and 7?',
|
||||
tools: [multiplyNumbers],
|
||||
});
|
||||
```
|
||||
|
||||
</details>
|
||||
15
docs/en/sdks/go-sdk.md
Normal file
15
docs/en/sdks/go-sdk.md
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
title: "Go SDK"
|
||||
weight: 2
|
||||
description: Go lang client SDK
|
||||
icon: fa-brands fa-golang
|
||||
manualLink: "https://github.com/googleapis/mcp-toolbox-sdk-go"
|
||||
manualLinkTarget: _blank
|
||||
---
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<link rel="canonical" href="https://github.com/googleapis/mcp-toolbox-sdk-go"/>
|
||||
<meta http-equiv="refresh" content="0;url=https://github.com/googleapis/mcp-toolbox-sdk-go"/>
|
||||
</head>
|
||||
</html>
|
||||
@@ -1,114 +0,0 @@
|
||||
---
|
||||
title: "Go"
|
||||
type: docs
|
||||
weight: 3
|
||||
description: >
|
||||
Go SDKs to connect to the MCP Toolbox server.
|
||||
---
|
||||
|
||||
|
||||
## Overview
|
||||
|
||||

|
||||
|
||||
# MCP Toolbox SDKs for Go
|
||||
|
||||
[](https://opensource.org/licenses/Apache-2.0)
|
||||
[](https://googleapis.github.io/genai-toolbox/)
|
||||
[](https://discord.gg/Dmm69peqjh)
|
||||
[](https://medium.com/@mcp_toolbox)
|
||||
[](https://goreportcard.com/report/github.com/googleapis/mcp-toolbox-sdk-go)
|
||||
[](https://img.shields.io/github/v/release/googleapis/mcp-toolbox-sdk-go)
|
||||
[](https://img.shields.io/github/go-mod/go-version/googleapis/mcp-toolbox-sdk-go)
|
||||
|
||||
This repository contains the Go SDK designed to seamlessly integrate the
|
||||
functionalities of the [MCP
|
||||
Toolbox](https://github.com/googleapis/genai-toolbox) into your Agentic
|
||||
applications. The SDK allow you to load tools defined in Toolbox and use them
|
||||
as standard Go tools within popular orchestration frameworks
|
||||
or your custom code.
|
||||
|
||||
This simplifies the process of incorporating external functionalities (like
|
||||
Databases or APIs) managed by Toolbox into your GenAI applications.
|
||||
|
||||
<!-- TOC -->
|
||||
|
||||
- [Overview](#overview)
|
||||
- [Which Package Should I Use?](#which-package-should-i-use)
|
||||
- [Available Packages](#available-packages)
|
||||
- [Getting Started](#getting-started)
|
||||
|
||||
<!-- /TOC -->
|
||||
|
||||
## Overview
|
||||
|
||||
The MCP Toolbox service provides a centralized way to manage and expose tools
|
||||
(like API connectors, database query tools, etc.) for use by GenAI applications.
|
||||
|
||||
The Go SDK act as clients for that service. They handle the communication needed to:
|
||||
|
||||
* Fetch tool definitions from your running Toolbox instance.
|
||||
* Provide convenient Go structs representing those tools.
|
||||
* Invoke the tools (calling the underlying APIs/services configured in Toolbox).
|
||||
* Handle authentication and parameter binding as needed.
|
||||
|
||||
By using the SDK, you can easily leverage your Toolbox-managed tools directly
|
||||
within your Go applications or AI orchestration frameworks.
|
||||
|
||||
## Which Package Should I Use?
|
||||
|
||||
Choosing the right package depends on how you are building your application:
|
||||
|
||||
- [**`core`**](core/):
|
||||
This is a framework-agnostic way to connect tools to popular frameworks
|
||||
like Google GenAI, LangChain, etc.
|
||||
|
||||
- [**`tbadk`**](tbadk/):
|
||||
This package provides a way to connect tools to ADK Go.
|
||||
|
||||
- [**`tbgenkit`**](tbgenkit/):
|
||||
This package provides functionality to convert the Tool fetched using the core package
|
||||
into a Genkit Go compatible tool.
|
||||
|
||||
## Available Packages
|
||||
|
||||
This repository hosts the following Go packages. See the package-specific
|
||||
README for detailed installation and usage instructions:
|
||||
|
||||
| Package | Target Use Case | Integration | Path | Details (README) |
|
||||
| :------ | :----------| :---------- | :---------------------- | :---------- |
|
||||
| [`core`](core/) | Framework-agnostic / Custom applications | Use directly / Custom | `core/` | 📄 [View README](https://github.com/googleapis/mcp-toolbox-sdk-go/blob/main/core/README.md) |
|
||||
| [`tbadk`](tbadk/) | ADK Go | Use directly | `tbadk/` | 📄 [View README](https://github.com/googleapis/mcp-toolbox-sdk-go/blob/main/tbadk/README.md) |
|
||||
| [`tbgenkit`](tbgenkit/) | Genkit Go | Along with core | `tbgenkit/` | 📄 [View README](https://github.com/googleapis/mcp-toolbox-sdk-go/blob/main/tbgenkit/README.md) |
|
||||
|
||||
## Getting Started
|
||||
|
||||
To get started using Toolbox tools with an application, follow these general steps:
|
||||
|
||||
1. **Set up and Run the Toolbox Service:**
|
||||
|
||||
Before using the SDKs, you need the MCP Toolbox server running. Follow
|
||||
the instructions here: [**Toolbox Getting Started
|
||||
Guide**](https://github.com/googleapis/genai-toolbox?tab=readme-ov-file#getting-started)
|
||||
|
||||
2. **Install the Appropriate SDK:**
|
||||
|
||||
Choose the package based on your needs (see "[Which Package Should I Use?](#which-package-should-i-use)" above)
|
||||
Use this command to install the SDK module
|
||||
|
||||
```bash
|
||||
# For the core, framework-agnostic SDK
|
||||
go get github.com/googleapis/mcp-toolbox-sdk-go
|
||||
```
|
||||
|
||||
3. **Use the SDK:**
|
||||
|
||||
Consult the `README` for your chosen package (linked in the "[Available
|
||||
Packages](#available-packages)" section above) for detailed instructions on
|
||||
how to connect the client, load tool definitions, invoke tools, configure
|
||||
authentication/binding, and integrate them into your application or
|
||||
framework.
|
||||
|
||||
[Github](https://github.com/googleapis/mcp-toolbox-sdk-go)
|
||||
@@ -1,932 +0,0 @@
|
||||
---
|
||||
title: "Core Package"
|
||||
linkTitle: "Core"
|
||||
type: docs
|
||||
weight: 1
|
||||
---
|
||||
|
||||

|
||||
|
||||
# MCP Toolbox For Go Core SDK
|
||||
|
||||
[](https://opensource.org/licenses/Apache-2.0)
|
||||
|
||||
This SDK allows you to seamlessly integrate the functionalities of
|
||||
[MCP Toolbox](https://github.com/googleapis/genai-toolbox) allowing you to load and
|
||||
use tools defined in the service as standard Go structs within your GenAI
|
||||
applications.
|
||||
|
||||
This simplifies integrating external functionalities (like APIs, databases, or
|
||||
custom logic) managed by the Toolbox into your workflows, especially those
|
||||
involving Large Language Models (LLMs).
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
go get github.com/googleapis/mcp-toolbox-sdk-go
|
||||
```
|
||||
This SDK is supported on Go version 1.24.4 and higher.
|
||||
|
||||
{{< notice note >}}
|
||||
While the SDK itself is synchronous, you can execute its functions within goroutines to achieve asynchronous behavior.
|
||||
{{< /notice >}}
|
||||
|
||||
|
||||
## Quickstart
|
||||
|
||||
Here's a minimal example to get you started. Ensure your Toolbox service is
|
||||
running and accessible.
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/googleapis/mcp-toolbox-sdk-go/core"
|
||||
)
|
||||
|
||||
func quickstart() string {
|
||||
ctx := context.Background()
|
||||
inputs := map[string]any{"location": "London"}
|
||||
client, err := core.NewToolboxClient("http://localhost:5000")
|
||||
if err != nil {
|
||||
return fmt.Sprintln("Could not start Toolbox Client", err)
|
||||
}
|
||||
tool, err := client.LoadTool("get_weather", ctx)
|
||||
if err != nil {
|
||||
return fmt.Sprintln("Could not load Toolbox Tool", err)
|
||||
}
|
||||
result, err := tool.Invoke(ctx, inputs)
|
||||
if err != nil {
|
||||
return fmt.Sprintln("Could not invoke tool", err)
|
||||
}
|
||||
return fmt.Sprintln(result)
|
||||
}
|
||||
|
||||
func main() {
|
||||
fmt.Println(quickstart())
|
||||
}
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
Import and initialize a Toolbox client, pointing it to the URL of your running
|
||||
Toolbox service.
|
||||
|
||||
```go
|
||||
import "github.com/googleapis/mcp-toolbox-sdk-go/core"
|
||||
|
||||
client, err := core.NewToolboxClient("http://localhost:5000")
|
||||
```
|
||||
|
||||
All interactions for loading and invoking tools happen through this client.
|
||||
|
||||
{{< notice note >}}
|
||||
For advanced use cases, you can provide an external custom `http.Client` during initialization (e.g., `core.NewToolboxClient(URL, core.WithHTTPClient(myClient)`).
|
||||
If you provide your own session, you are responsible for managing its lifecycle; `ToolboxClient` *will not* close it.
|
||||
{{< /notice >}}
|
||||
|
||||
{{< notice info >}}
|
||||
Closing the `ToolboxClient` also closes the underlying network session shared by all tools loaded from that client. As a result, any tool instances you have loaded will cease to function and will raise an error if you attempt to invoke them after the client is closed.
|
||||
{{< /notice >}}
|
||||
|
||||
## Transport Protocols
|
||||
|
||||
The SDK supports multiple transport protocols for communicating with the Toolbox server. By default, the client uses the latest supported version of the **Model Context Protocol (MCP)**.
|
||||
|
||||
You can explicitly select a protocol using the `core.WithProtocol` option during client initialization. This is useful if you need to use the native Toolbox HTTP protocol or pin the client to a specific legacy version of MCP.
|
||||
|
||||
{{< notice note >}}
|
||||
* **Native Toolbox Transport**: This uses the service's native **REST over HTTP** API.
|
||||
* **MCP Transports**: These options use the **Model Context Protocol over HTTP**.
|
||||
{{< /notice >}}
|
||||
|
||||
|
||||
### Supported Protocols
|
||||
|
||||
| Constant | Description |
|
||||
| :--- | :--- |
|
||||
| `core.MCP` | **(Default)** Alias for the latest supported MCP version (currently `v2025-06-18`). |
|
||||
| `core.Toolbox` | The native Toolbox HTTP protocol. |
|
||||
| `core.MCPv20250618` | MCP Protocol version 2025-06-18. |
|
||||
| `core.MCPv20250326` | MCP Protocol version 2025-03-26. |
|
||||
| `core.MCPv20241105` | MCP Protocol version 2024-11-05. |
|
||||
|
||||
### Example
|
||||
|
||||
If you wish to use the native Toolbox protocol:
|
||||
|
||||
```go
|
||||
import "github.com/googleapis/mcp-toolbox-sdk-go/core"
|
||||
|
||||
client, err := core.NewToolboxClient(
|
||||
"http://localhost:5000",
|
||||
core.WithProtocol(core.Toolbox),
|
||||
)
|
||||
```
|
||||
If you want to pin the MCP Version 2025-03-26:
|
||||
|
||||
```go
|
||||
import "github.com/googleapis/mcp-toolbox-sdk-go/core"
|
||||
|
||||
client, err := core.NewToolboxClient(
|
||||
"http://localhost:5000",
|
||||
core.WithProtocol(core.MCPv20250326),
|
||||
)
|
||||
```
|
||||
|
||||
## Loading Tools
|
||||
|
||||
You can load tools individually or in groups (toolsets) as defined in your
|
||||
Toolbox service configuration. Loading a toolset is convenient when working with
|
||||
multiple related functions, while loading a single tool offers more granular
|
||||
control.
|
||||
|
||||
### Load a toolset
|
||||
|
||||
A toolset is a collection of related tools. You can load all tools in a toolset
|
||||
or a specific one:
|
||||
|
||||
```go
|
||||
// Load default toolset by providing an empty string as the name
|
||||
tools, err := client.LoadToolset("", ctx)
|
||||
|
||||
// Load a specific toolset
|
||||
tools, err := client.LoadToolset("my-toolset", ctx)
|
||||
```
|
||||
|
||||
|
||||
### Load a single tool
|
||||
|
||||
Loads a specific tool by its unique name. This provides fine-grained control.
|
||||
|
||||
```go
|
||||
tool, err = client.LoadTool("my-tool", ctx)
|
||||
```
|
||||
|
||||
## Invoking Tools
|
||||
|
||||
Once loaded, tools behave like Go structs. You invoke them using `Invoke` method
|
||||
by passing arguments corresponding to the parameters defined in the tool's
|
||||
configuration within the Toolbox service.
|
||||
|
||||
```go
|
||||
tool, err = client.LoadTool("my-tool", ctx)
|
||||
inputs := map[string]any{"location": "London"}
|
||||
result, err := tool.Invoke(ctx, inputs)
|
||||
```
|
||||
|
||||
{{< notice tip >}}
|
||||
For a more comprehensive guide on setting up the Toolbox service itself, which you'll need running to use this SDK, please refer to the [Toolbox Quickstart Guide](https://googleapis.github.io/genai-toolbox/getting-started/local_quickstart).
|
||||
{{< /notice >}}
|
||||
|
||||
## Client to Server Authentication
|
||||
|
||||
This section describes how to authenticate the ToolboxClient itself when
|
||||
connecting to a Toolbox server instance that requires authentication. This is
|
||||
crucial for securing your Toolbox server endpoint, especially when deployed on
|
||||
platforms like Cloud Run, GKE, or any environment where unauthenticated access is restricted.
|
||||
|
||||
This client-to-server authentication ensures that the Toolbox server can verify
|
||||
the identity of the client making the request before any tool is loaded or
|
||||
called. It is different from [Authenticating Tools](#authenticating-tools),
|
||||
which deals with providing credentials for specific tools within an already
|
||||
connected Toolbox session.
|
||||
|
||||
### When is Client-to-Server Authentication Needed?
|
||||
|
||||
You'll need this type of authentication if your Toolbox server is configured to
|
||||
deny unauthenticated requests. For example:
|
||||
|
||||
- Your Toolbox server is deployed on Cloud Run and configured to "Require authentication."
|
||||
- Your server is behind an Identity-Aware Proxy (IAP) or a similar
|
||||
authentication layer.
|
||||
- You have custom authentication middleware on your self-hosted Toolbox server.
|
||||
|
||||
Without proper client authentication in these scenarios, attempts to connect or
|
||||
make calls (like `LoadTool`) will likely fail with `Unauthorized` errors.
|
||||
|
||||
### How it works
|
||||
|
||||
The `ToolboxClient` allows you to specify TokenSources that dynamically generate HTTP headers for
|
||||
every request sent to the Toolbox server. The most common use case is to add an
|
||||
Authorization header with a bearer token (e.g., a Google ID token).
|
||||
|
||||
These header-generating functions are called just before each request, ensuring
|
||||
that fresh credentials or header values can be used.
|
||||
|
||||
### Configuration
|
||||
|
||||
You can configure these dynamic headers as seen below:
|
||||
|
||||
|
||||
```go
|
||||
import "github.com/googleapis/mcp-toolbox-sdk-go/core"
|
||||
|
||||
tokenProvider := func() string {
|
||||
return "header3_value"
|
||||
}
|
||||
|
||||
staticTokenSource := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: "header2_value"})
|
||||
dynamicTokenSource := core.NewCustomTokenSource(tokenProvider)
|
||||
|
||||
client, err := core.NewToolboxClient(
|
||||
"toolbox-url",
|
||||
core.WithClientHeaderString("header1", "header1_value"),
|
||||
core.WithClientHeaderTokenSource("header2", staticTokenSource),
|
||||
core.WithClientHeaderTokenSource("header3", dynamicTokenSource),
|
||||
)
|
||||
```
|
||||
|
||||
### Authenticating with Google Cloud Servers
|
||||
|
||||
For Toolbox servers hosted on Google Cloud (e.g., Cloud Run) and requiring
|
||||
`Google ID token` authentication, the helper module
|
||||
[auth_methods](https://github.com/googleapis/mcp-toolbox-sdk-go/blob/main/core/auth.go) provides utility functions.
|
||||
|
||||
### Step by Step Guide for Cloud Run
|
||||
|
||||
1. **Configure Permissions**: [Grant](https://cloud.google.com/run/docs/securing/managing-access#service-add-principals) the `roles/run.invoker` IAM role on the Cloud
|
||||
Run service to the principal. This could be your `user account email` or a
|
||||
`service account`.
|
||||
2. **Configure Credentials**
|
||||
- Local Development: Set up
|
||||
[ADC](https://cloud.google.com/docs/authentication/set-up-adc-local-dev-environment).
|
||||
- Google Cloud Environments: When running within Google Cloud (e.g., Compute
|
||||
Engine, GKE, another Cloud Run service, Cloud Functions), ADC is typically
|
||||
configured automatically, using the environment's default service account.
|
||||
3. **Connect to the Toolbox Server**
|
||||
```go
|
||||
import "github.com/googleapis/mcp-toolbox-sdk-go/core"
|
||||
import "context"
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
token, err := core.GetGoogleIDToken(ctx, URL)
|
||||
|
||||
client, err := core.NewToolboxClient(
|
||||
URL,
|
||||
core.WithClientHeaderString("Authorization", token),
|
||||
)
|
||||
|
||||
// Now, you can use the client as usual.
|
||||
```
|
||||
|
||||
## Authenticating Tools
|
||||
|
||||
{{< notice warning >}}
|
||||
**Always use HTTPS** to connect your application with the Toolbox service, especially in **production environments** or whenever the communication involves **sensitive data** (including scenarios where tools requireauthentication tokens). Using plain HTTP lacks encryption and exposes your application and data to significant security risks, such as eavesdropping and tampering.
|
||||
{{< /notice >}}
|
||||
|
||||
Tools can be configured within the Toolbox service to require authentication,
|
||||
ensuring only authorized users or applications can invoke them, especially when
|
||||
accessing sensitive data.
|
||||
|
||||
### When is Authentication Needed?
|
||||
|
||||
Authentication is configured per-tool within the Toolbox service itself. If a
|
||||
tool you intend to use is marked as requiring authentication in the service, you
|
||||
must configure the SDK client to provide the necessary credentials (currently
|
||||
Oauth2 tokens) when invoking that specific tool.
|
||||
|
||||
### Supported Authentication Mechanisms
|
||||
|
||||
The Toolbox service enables secure tool usage through **Authenticated Parameters**.
|
||||
For detailed information on how these mechanisms work within the Toolbox service and how to configure them, please refer to [Toolbox Service Documentation - Authenticated Parameters](https://googleapis.github.io/genai-toolbox/resources/tools/#authenticated-parameters).
|
||||
|
||||
### Step 1: Configure Tools in Toolbox Service
|
||||
|
||||
First, ensure the target tool(s) are configured correctly in the Toolbox service
|
||||
to require authentication. Refer to the [Toolbox Service Documentation -
|
||||
Authenticated
|
||||
Parameters](https://googleapis.github.io/genai-toolbox/resources/tools/#authenticated-parameters)
|
||||
for instructions.
|
||||
|
||||
### Step 2: Configure SDK Client
|
||||
|
||||
Your application needs a way to obtain the required Oauth2 token for the
|
||||
authenticated user. The SDK requires you to provide a function capable of
|
||||
retrieving this token *when the tool is invoked*.
|
||||
|
||||
#### Provide an ID Token Retriever Function
|
||||
|
||||
You must provide the SDK with a function that returns the
|
||||
necessary token when called. The implementation depends on your application's
|
||||
authentication flow (e.g., retrieving a stored token, initiating an OAuth flow).
|
||||
|
||||
{{< notice info >}}
|
||||
The name used when registering the getter function with the SDK (e.g., `"my_api_token"`) must exactly match the `name` of the corresponding `authServices` defined in the tool's configuration within the Toolbox service.
|
||||
{{< /notice >}}
|
||||
|
||||
```go
|
||||
func getAuthToken() string {
|
||||
// ... Logic to retrieve ID token (e.g., from local storage, OAuth flow)
|
||||
// This example just returns a placeholder. Replace with your actual token retrieval.
|
||||
return "YOUR_ID_TOKEN" // Placeholder
|
||||
}
|
||||
```
|
||||
|
||||
{{< notice tip >}}
|
||||
Your token retriever function is invoked every time an authenticated parameter requires a token for a tool call. Consider implementing caching logic within this function to avoid redundant token fetching or generation, especially for tokens with longer validity periods or if the retrieval process is resource-intensive.
|
||||
{{< /notice >}}
|
||||
|
||||
#### Option A: Add Default Authentication to a Client
|
||||
|
||||
You can add default tool level authentication to a client.
|
||||
Every tool / toolset loaded by the client will contain the auth token.
|
||||
|
||||
```go
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
client, err := core.NewToolboxClient("http://127.0.0.1:5000",
|
||||
core.WithDefaultToolOptions(
|
||||
core.WithAuthTokenString("my-auth-1", "auth-value"),
|
||||
),
|
||||
)
|
||||
|
||||
AuthTool, err := client.LoadTool("my-tool", ctx)
|
||||
```
|
||||
|
||||
#### Option B: Add Authentication to a Loaded Tool
|
||||
|
||||
You can add the token retriever function to a tool object *after* it has been
|
||||
loaded. This modifies the specific tool instance.
|
||||
|
||||
```go
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
client, err := core.NewToolboxClient("http://127.0.0.1:5000")
|
||||
|
||||
tool, err := client.LoadTool("my-tool", ctx)
|
||||
|
||||
AuthTool, err := tool.ToolFrom(
|
||||
core.WithAuthTokenSource("my-auth", headerTokenSource),
|
||||
core.WithAuthTokenString("my-auth-1", "value"),
|
||||
)
|
||||
```
|
||||
|
||||
#### Option C: Add Authentication While Loading Tools
|
||||
|
||||
You can provide the token retriever(s) directly during the `LoadTool` or
|
||||
`LoadToolset` calls. This applies the authentication configuration only to the
|
||||
tools loaded in that specific call, without modifying the original tool objects
|
||||
if they were loaded previously.
|
||||
|
||||
```go
|
||||
AuthTool, err := client.LoadTool("my-tool", ctx, core.WithAuthTokenString("my-auth-1", "value"))
|
||||
|
||||
// or
|
||||
|
||||
AuthTools, err := client.LoadToolset(
|
||||
"my-toolset",
|
||||
ctx,
|
||||
core.WithAuthTokenString("my-auth-1", "value"),
|
||||
)
|
||||
```
|
||||
|
||||
{{< notice note >}}
|
||||
Adding auth tokens during loading only affect the tools loaded within that call.
|
||||
{{< /notice >}}
|
||||
|
||||
### Complete Authentication Example
|
||||
|
||||
```go
|
||||
import "github.com/googleapis/mcp-toolbox-sdk-go/core"
|
||||
import "fmt"
|
||||
|
||||
func getAuthToken() string {
|
||||
// ... Logic to retrieve ID token (e.g., from local storage, OAuth flow)
|
||||
// This example just returns a placeholder. Replace with your actual token retrieval.
|
||||
return "YOUR_ID_TOKEN" // Placeholder
|
||||
}
|
||||
|
||||
func main() {
|
||||
ctx := context.Background()
|
||||
inputs := map[string]any{"input": "some input"}
|
||||
|
||||
dynamicTokenSource := core.NewCustomTokenSource(getAuthToken)
|
||||
|
||||
client, err := core.NewToolboxClient("http://127.0.0.1:5000")
|
||||
tool, err := client.LoadTool("my-tool", ctx)
|
||||
AuthTool, err := tool.ToolFrom(core.WithAuthTokenSource("my_auth", dynamicTokenSource))
|
||||
|
||||
result, err := AuthTool.Invoke(ctx, inputs)
|
||||
|
||||
fmt.Println(result)
|
||||
}
|
||||
```
|
||||
|
||||
{{< notice note >}}
|
||||
An auth token getter for a specific name (e.g., "GOOGLE_ID") will replace any client header with the same name followed by "_token" (e.g., "GOOGLE_ID_token").
|
||||
{{< /notice >}}
|
||||
|
||||
## Binding Parameter Values
|
||||
|
||||
The SDK allows you to pre-set, or "bind", values for specific tool parameters
|
||||
before the tool is invoked or even passed to an LLM. These bound values are
|
||||
fixed and will not be requested or modified by the LLM during tool use.
|
||||
|
||||
### Why Bind Parameters?
|
||||
|
||||
- **Protecting sensitive information:** API keys, secrets, etc.
|
||||
- **Enforcing consistency:** Ensuring specific values for certain parameters.
|
||||
- **Pre-filling known data:** Providing defaults or context.
|
||||
|
||||
{{< notice info >}}
|
||||
The parameter names used for binding (e.g., `"api_key"`) must exactly match the parameter names defined in the tool's configuration within the Toolbox service.
|
||||
{{< /notice >}}
|
||||
|
||||
{{< notice note >}}
|
||||
You do not need to modify the tool's configuration in the Toolbox service to bind parameter values using the SDK.
|
||||
{{< /notice >}}
|
||||
|
||||
#### Option A: Add Default Bound Parameters to a Client
|
||||
|
||||
You can add default tool level bound parameters to a client. Every tool / toolset
|
||||
loaded by the client will have the bound parameter.
|
||||
|
||||
```go
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
client, err := core.NewToolboxClient("http://127.0.0.1:5000",
|
||||
core.WithDefaultToolOptions(
|
||||
core.WithBindParamString("param1", "value"),
|
||||
),
|
||||
)
|
||||
|
||||
boundTool, err := client.LoadTool("my-tool", ctx)
|
||||
```
|
||||
|
||||
### Option B: Binding Parameters to a Loaded Tool
|
||||
|
||||
Bind values to a tool object *after* it has been loaded. This modifies the
|
||||
specific tool instance.
|
||||
|
||||
```go
|
||||
client, err := core.NewToolboxClient("http://127.0.0.1:5000")
|
||||
|
||||
tool, err := client.LoadTool("my-tool", ctx)
|
||||
|
||||
boundTool, err := tool.ToolFrom(
|
||||
core.WithBindParamString("param1", "value"),
|
||||
core.WithBindParamString("param2", "value")
|
||||
)
|
||||
```
|
||||
|
||||
### Option C: Binding Parameters While Loading Tools
|
||||
|
||||
Specify bound parameters directly when loading tools. This applies the binding
|
||||
only to the tools loaded in that specific call.
|
||||
|
||||
```go
|
||||
boundTool, err := client.LoadTool("my-tool", ctx, core.WithBindParamString("param", "value"))
|
||||
|
||||
// OR
|
||||
|
||||
boundTool, err := client.LoadToolset("", ctx, core.WithBindParamString("param", "value"))
|
||||
```
|
||||
|
||||
{{< notice note >}} Bound values during loading only affect the tools loaded in that call. {{< /notice >}}
|
||||
|
||||
### Binding Dynamic Values
|
||||
|
||||
Instead of a static value, you can bind a parameter to a synchronous or
|
||||
asynchronous function. This function will be called *each time* the tool is
|
||||
invoked to dynamically determine the parameter's value at runtime.
|
||||
Functions with the return type (data_type, error) can be provided.
|
||||
|
||||
```go
|
||||
getDynamicValue := func() (string, error) { return "req-123", nil }
|
||||
|
||||
dynamicBoundTool, err := tool.ToolFrom(core.WithBindParamStringFunc("param", getDynamicValue))
|
||||
```
|
||||
|
||||
{{< notice info >}} You don't need to modify tool configurations to bind parameter values. {{< /notice >}}
|
||||
|
||||
|
||||
# Using with Orchestration Frameworks
|
||||
|
||||
To see how the MCP Toolbox Go SDK works with orchestration frameworks, check out these end-to-end examples given below.
|
||||
|
||||
<details>
|
||||
<summary>Google GenAI</summary>
|
||||
|
||||
```go
|
||||
// This sample demonstrates integration with the standard Google GenAI framework.
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/googleapis/mcp-toolbox-sdk-go/core"
|
||||
"google.golang.org/genai"
|
||||
)
|
||||
|
||||
// ConvertToGenaiTool translates a ToolboxTool into the genai.FunctionDeclaration format.
|
||||
func ConvertToGenaiTool(toolboxTool *core.ToolboxTool) *genai.Tool {
|
||||
|
||||
inputschema, err := toolboxTool.InputSchema()
|
||||
if err != nil {
|
||||
return &genai.Tool{}
|
||||
}
|
||||
|
||||
var schema *genai.Schema
|
||||
_ = json.Unmarshal(inputschema, &schema)
|
||||
// First, create the function declaration.
|
||||
funcDeclaration := &genai.FunctionDeclaration{
|
||||
Name: toolboxTool.Name(),
|
||||
Description: toolboxTool.Description(),
|
||||
Parameters: schema,
|
||||
}
|
||||
|
||||
// Then, wrap the function declaration in a genai.Tool struct.
|
||||
return &genai.Tool{
|
||||
FunctionDeclarations: []*genai.FunctionDeclaration{funcDeclaration},
|
||||
}
|
||||
}
|
||||
|
||||
// printResponse extracts and prints the relevant parts of the model's response.
|
||||
func printResponse(resp *genai.GenerateContentResponse) {
|
||||
for _, cand := range resp.Candidates {
|
||||
if cand.Content != nil {
|
||||
for _, part := range cand.Content.Parts {
|
||||
fmt.Println(part.Text)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Setup
|
||||
ctx := context.Background()
|
||||
apiKey := os.Getenv("GOOGLE_API_KEY")
|
||||
toolboxURL := "http://localhost:5000"
|
||||
|
||||
// Initialize the Google GenAI client using the explicit ClientConfig.
|
||||
client, err := genai.NewClient(ctx, &genai.ClientConfig{
|
||||
APIKey: apiKey,
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create Google GenAI client: %v", err)
|
||||
}
|
||||
|
||||
// Initialize the MCP Toolbox client.
|
||||
toolboxClient, err := core.NewToolboxClient(toolboxURL)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create Toolbox client: %v", err)
|
||||
}
|
||||
|
||||
// Load the tools using the MCP Toolbox SDK.
|
||||
tools, err := toolboxClient.LoadToolset("my-toolset", ctx)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to load tools: %v\nMake sure your Toolbox server is running and the tool is configured.", err)
|
||||
}
|
||||
|
||||
genAITools := make([]*genai.Tool, len(tools))
|
||||
toolsMap := make(map[string]*core.ToolboxTool, len(tools))
|
||||
|
||||
for i, tool := range tools {
|
||||
// Convert the tools into usable format
|
||||
genAITools[i] = ConvertToGenaiTool(tool)
|
||||
// Add tool to a map for lookup later
|
||||
toolsMap[tool.Name()] = tool
|
||||
}
|
||||
|
||||
// Set up the generative model with the available tool.
|
||||
modelName := "gemini-2.0-flash"
|
||||
|
||||
query := "Find hotels in Basel with Basel in it's name and share the names with me"
|
||||
|
||||
// Create the initial content prompt for the model.
|
||||
contents := []*genai.Content{
|
||||
genai.NewContentFromText(query, genai.RoleUser),
|
||||
}
|
||||
config := &genai.GenerateContentConfig{
|
||||
Tools: genAITools,
|
||||
ToolConfig: &genai.ToolConfig{
|
||||
FunctionCallingConfig: &genai.FunctionCallingConfig{
|
||||
Mode: genai.FunctionCallingConfigModeAny,
|
||||
},
|
||||
},
|
||||
}
|
||||
genContentResp, _ := client.Models.GenerateContent(ctx, modelName, contents, config)
|
||||
|
||||
printResponse(genContentResp)
|
||||
|
||||
functionCalls := genContentResp.FunctionCalls()
|
||||
if len(functionCalls) == 0 {
|
||||
log.Println("No function call returned by the AI. The model likely answered directly.")
|
||||
return
|
||||
}
|
||||
|
||||
// Process the first function call (the example assumes one for simplicity).
|
||||
fc := functionCalls[0]
|
||||
log.Printf("--- Gemini requested function call: %s ---\n", fc.Name)
|
||||
log.Printf("--- Arguments: %+v ---\n", fc.Args)
|
||||
|
||||
var toolResultString string
|
||||
|
||||
if fc.Name == "search-hotels-by-name" {
|
||||
tool := toolsMap["search-hotels-by-name"]
|
||||
toolResult, err := tool.Invoke(ctx, fc.Args)
|
||||
toolResultString = fmt.Sprintf("%v", toolResult)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to execute tool '%s': %v", fc.Name, err)
|
||||
}
|
||||
|
||||
} else {
|
||||
log.Println("LLM did not request our tool")
|
||||
}
|
||||
resultContents := []*genai.Content{
|
||||
genai.NewContentFromText("The tool returned this result, share it with the user based of their previous querys"+toolResultString, genai.RoleUser),
|
||||
}
|
||||
finalResponse, err := client.Models.GenerateContent(ctx, modelName, resultContents, &genai.GenerateContentConfig{})
|
||||
if err != nil {
|
||||
log.Fatalf("Error calling GenerateContent (with function result): %v", err)
|
||||
}
|
||||
log.Println("=== Final Response from Model (after processing function result) ===")
|
||||
printResponse(finalResponse)
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>LangChain</summary>
|
||||
|
||||
```go
|
||||
// This sample demonstrates how to use Toolbox tools as function definitions in LangChain Go.
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/googleapis/mcp-toolbox-sdk-go/core"
|
||||
"github.com/tmc/langchaingo/llms"
|
||||
"github.com/tmc/langchaingo/llms/googleai"
|
||||
)
|
||||
|
||||
// ConvertToLangchainTool converts a generic core.ToolboxTool into a LangChainGo llms.Tool.
|
||||
func ConvertToLangchainTool(toolboxTool *core.ToolboxTool) llms.Tool {
|
||||
|
||||
// Fetch the tool's input schema
|
||||
inputschema, err := toolboxTool.InputSchema()
|
||||
if err != nil {
|
||||
return llms.Tool{}
|
||||
}
|
||||
|
||||
var paramsSchema map[string]any
|
||||
_ = json.Unmarshal(inputschema, ¶msSchema)
|
||||
|
||||
// Convert into LangChain's llms.Tool
|
||||
return llms.Tool{
|
||||
Type: "function",
|
||||
Function: &llms.FunctionDefinition{
|
||||
Name: toolboxTool.Name(),
|
||||
Description: toolboxTool.Description(),
|
||||
Parameters: paramsSchema,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
genaiKey := os.Getenv("GOOGLE_API_KEY")
|
||||
toolboxURL := "http://localhost:5000"
|
||||
ctx := context.Background()
|
||||
|
||||
// Initialize the Google AI client (LLM).
|
||||
llm, err := googleai.New(ctx, googleai.WithAPIKey(genaiKey), googleai.WithDefaultModel("gemini-1.5-flash"))
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create Google AI client: %v", err)
|
||||
}
|
||||
|
||||
// Initialize the MCP Toolbox client.
|
||||
toolboxClient, err := core.NewToolboxClient(toolboxURL)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create Toolbox client: %v", err)
|
||||
}
|
||||
|
||||
// Load the tools using the MCP Toolbox SDK.
|
||||
tools, err := toolboxClient.LoadToolset("my-toolset", ctx)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to load tools: %v\nMake sure your Toolbox server is running and the tool is configured.", err)
|
||||
}
|
||||
|
||||
toolsMap := make(map[string]*core.ToolboxTool, len(tools))
|
||||
|
||||
langchainTools := make([]llms.Tool, len(tools))
|
||||
for i, tool := range tools {
|
||||
// Convert the loaded ToolboxTools into the format LangChainGo requires.
|
||||
langchainTools[i] = ConvertToLangchainTool(tool)
|
||||
// Add tool to a map for lookup later
|
||||
toolsMap[tool.Name()] = tool
|
||||
}
|
||||
|
||||
// Start the conversation history.
|
||||
messageHistory := []llms.MessageContent{
|
||||
llms.TextParts(llms.ChatMessageTypeHuman, "Find hotels in Basel with Basel in it's name."),
|
||||
}
|
||||
|
||||
// Make the first call to the LLM, making it aware of the tool.
|
||||
resp, err := llm.GenerateContent(ctx, messageHistory, llms.WithTools(langchainTools))
|
||||
if err != nil {
|
||||
log.Fatalf("LLM call failed: %v", err)
|
||||
}
|
||||
|
||||
// Add the model's response (which should be a tool call) to the history.
|
||||
respChoice := resp.Choices[0]
|
||||
assistantResponse := llms.TextParts(llms.ChatMessageTypeAI, respChoice.Content)
|
||||
for _, tc := range respChoice.ToolCalls {
|
||||
assistantResponse.Parts = append(assistantResponse.Parts, tc)
|
||||
}
|
||||
messageHistory = append(messageHistory, assistantResponse)
|
||||
|
||||
// Process each tool call requested by the model.
|
||||
for _, tc := range respChoice.ToolCalls {
|
||||
toolName := tc.FunctionCall.Name
|
||||
|
||||
switch tc.FunctionCall.Name {
|
||||
case "search-hotels-by-name":
|
||||
var args map[string]any
|
||||
if err := json.Unmarshal([]byte(tc.FunctionCall.Arguments), &args); err != nil {
|
||||
log.Fatalf("Failed to unmarshal arguments for tool '%s': %v", toolName, err)
|
||||
}
|
||||
tool := toolsMap["search-hotels-by-name"]
|
||||
toolResult, err := tool.Invoke(ctx, args)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to execute tool '%s': %v", toolName, err)
|
||||
}
|
||||
|
||||
// Create the tool call response message and add it to the history.
|
||||
toolResponse := llms.MessageContent{
|
||||
Role: llms.ChatMessageTypeTool,
|
||||
Parts: []llms.ContentPart{
|
||||
llms.ToolCallResponse{
|
||||
Name: toolName,
|
||||
Content: fmt.Sprintf("%v", toolResult),
|
||||
},
|
||||
},
|
||||
}
|
||||
messageHistory = append(messageHistory, toolResponse)
|
||||
default:
|
||||
log.Fatalf("got unexpected function call: %v", tc.FunctionCall.Name)
|
||||
}
|
||||
}
|
||||
|
||||
// Final LLM Call for Natural Language Response
|
||||
log.Println("Sending tool response back to LLM for a final answer...")
|
||||
|
||||
// Call the LLM again with the updated history, which now includes the tool's result.
|
||||
finalResp, err := llm.GenerateContent(ctx, messageHistory)
|
||||
if err != nil {
|
||||
log.Fatalf("Final LLM call failed: %v", err)
|
||||
}
|
||||
|
||||
// Display the Result
|
||||
fmt.Println("\n======================================")
|
||||
fmt.Println("Final Response from LLM:")
|
||||
fmt.Println(finalResp.Choices[0].Content)
|
||||
fmt.Println("======================================")
|
||||
}
|
||||
|
||||
```
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>OpenAI</summary>
|
||||
|
||||
```go
|
||||
// This sample demonstrates integration with the OpenAI Go client.
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/googleapis/mcp-toolbox-sdk-go/core"
|
||||
openai "github.com/openai/openai-go"
|
||||
)
|
||||
|
||||
// ConvertToOpenAITool converts a ToolboxTool into the go-openai library's Tool format.
|
||||
func ConvertToOpenAITool(toolboxTool *core.ToolboxTool) openai.ChatCompletionToolParam {
|
||||
// Get the input schema
|
||||
jsonSchemaBytes, err := toolboxTool.InputSchema()
|
||||
if err != nil {
|
||||
return openai.ChatCompletionToolParam{}
|
||||
}
|
||||
|
||||
// Unmarshal the JSON bytes into FunctionParameters
|
||||
var paramsSchema openai.FunctionParameters
|
||||
if err := json.Unmarshal(jsonSchemaBytes, ¶msSchema); err != nil {
|
||||
return openai.ChatCompletionToolParam{}
|
||||
}
|
||||
|
||||
// Create and return the final tool parameter struct.
|
||||
return openai.ChatCompletionToolParam{
|
||||
Function: openai.FunctionDefinitionParam{
|
||||
Name: toolboxTool.Name(),
|
||||
Description: openai.String(toolboxTool.Description()),
|
||||
Parameters: paramsSchema,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Setup
|
||||
ctx := context.Background()
|
||||
toolboxURL := "http://localhost:5000"
|
||||
openAIClient := openai.NewClient()
|
||||
|
||||
// Initialize the MCP Toolbox client.
|
||||
toolboxClient, err := core.NewToolboxClient(toolboxURL)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create Toolbox client: %v", err)
|
||||
}
|
||||
|
||||
// Load the tools using the MCP Toolbox SDK.
|
||||
tools, err := toolboxClient.LoadToolset("my-toolset", ctx)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to load tool : %v\nMake sure your Toolbox server is running and the tool is configured.", err)
|
||||
}
|
||||
|
||||
openAITools := make([]openai.ChatCompletionToolParam, len(tools))
|
||||
toolsMap := make(map[string]*core.ToolboxTool, len(tools))
|
||||
|
||||
for i, tool := range tools {
|
||||
// Convert the Toolbox tool into the openAI FunctionDeclaration format.
|
||||
openAITools[i] = ConvertToOpenAITool(tool)
|
||||
// Add tool to a map for lookup later
|
||||
toolsMap[tool.Name()] = tool
|
||||
|
||||
}
|
||||
question := "Find hotels in Basel with Basel in it's name "
|
||||
|
||||
params := openai.ChatCompletionNewParams{
|
||||
Messages: []openai.ChatCompletionMessageParamUnion{
|
||||
openai.UserMessage(question),
|
||||
},
|
||||
Tools: openAITools,
|
||||
Seed: openai.Int(0),
|
||||
Model: openai.ChatModelGPT4o,
|
||||
}
|
||||
|
||||
// Make initial chat completion request
|
||||
completion, err := openAIClient.Chat.Completions.New(ctx, params)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
toolCalls := completion.Choices[0].Message.ToolCalls
|
||||
|
||||
// Return early if there are no tool calls
|
||||
if len(toolCalls) == 0 {
|
||||
fmt.Printf("No function call")
|
||||
return
|
||||
}
|
||||
|
||||
// If there was a function call, continue the conversation
|
||||
params.Messages = append(params.Messages, completion.Choices[0].Message.ToParam())
|
||||
for _, toolCall := range toolCalls {
|
||||
if toolCall.Function.Name == "search-hotels-by-name" {
|
||||
// Extract the location from the function call arguments
|
||||
var args map[string]interface{}
|
||||
tool := toolsMap["search-hotels-by-name"]
|
||||
err := json.Unmarshal([]byte(toolCall.Function.Arguments), &args)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
result, err := tool.Invoke(ctx, args)
|
||||
if err != nil {
|
||||
log.Fatal("Could not invoke tool", err)
|
||||
}
|
||||
|
||||
params.Messages = append(params.Messages, openai.ToolMessage(result.(string), toolCall.ID))
|
||||
}
|
||||
}
|
||||
|
||||
completion, err = openAIClient.Chat.Completions.New(ctx, params)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Println(completion.Choices[0].Message.Content)
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
@@ -1,683 +0,0 @@
|
||||
---
|
||||
title: "ADK Package"
|
||||
linkTitle: "ADK"
|
||||
type: docs
|
||||
weight: 1
|
||||
---
|
||||
|
||||

|
||||
|
||||
# MCP Toolbox For Go ADK SDK
|
||||
|
||||
[](https://opensource.org/licenses/Apache-2.0)
|
||||
|
||||
This SDK allows you to seamlessly integrate the functionalities of
|
||||
[MCP Toolbox](https://github.com/googleapis/genai-toolbox) allowing you to load and
|
||||
use tools defined in the service as standard Go structs within your ADK Go
|
||||
applications.
|
||||
|
||||
This simplifies integrating external functionalities (like APIs, databases, or
|
||||
custom logic) managed by the Toolbox into your workflows, especially those
|
||||
involving Large Language Models (LLMs).
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
go get github.com/googleapis/mcp-toolbox-sdk-go
|
||||
```
|
||||
This SDK is supported on Go version 1.24.4 and higher.
|
||||
|
||||
{{< notice note >}}
|
||||
While the SDK itself is synchronous, you can execute its functions within goroutines to achieve asynchronous behavior.
|
||||
{{< /notice >}}
|
||||
|
||||
|
||||
## Quickstart
|
||||
|
||||
Here's a minimal example to get you started. Ensure your Toolbox service is
|
||||
running and accessible.
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/googleapis/mcp-toolbox-sdk-go/tbadk"
|
||||
)
|
||||
|
||||
func quickstart() string {
|
||||
inputs := map[string]any{"location": "London"}
|
||||
client, err := tbadk.NewToolboxClient("http://localhost:5000")
|
||||
if err != nil {
|
||||
return fmt.Sprintln("Could not start Toolbox Client", err)
|
||||
}
|
||||
tool, err := client.LoadTool("get_weather", ctx)
|
||||
if err != nil {
|
||||
return fmt.Sprintln("Could not load Toolbox Tool", err)
|
||||
}
|
||||
// pass the tool.Context as ctx into the Run() method
|
||||
result, err := tool.Run(ctx, inputs)
|
||||
if err != nil {
|
||||
return fmt.Sprintln("Could not invoke tool", err)
|
||||
}
|
||||
return fmt.Sprintln(result["output"])
|
||||
}
|
||||
|
||||
func main() {
|
||||
fmt.Println(quickstart())
|
||||
}
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
Import and initialize a Toolbox client, pointing it to the URL of your running
|
||||
Toolbox service.
|
||||
|
||||
```go
|
||||
import "github.com/googleapis/mcp-toolbox-sdk-go/tbadk"
|
||||
|
||||
client, err := tbadk.NewToolboxClient("http://localhost:5000")
|
||||
```
|
||||
|
||||
All interactions for loading and invoking tools happen through this client.
|
||||
|
||||
{{< notice note >}}
|
||||
For advanced use cases, you can provide an external custom `http.Client`
|
||||
during initialization (e.g., `tbadk.NewToolboxClient(URL, core.WithHTTPClient(myClient)`). If you provide your own session, you are responsible for managing its lifecycle;
|
||||
`ToolboxClient` *will not* close it.
|
||||
{{< /notice >}}
|
||||
|
||||
## Transport Protocols
|
||||
|
||||
The SDK supports multiple transport protocols. By default, the client uses the latest supported version of the **Model Context Protocol (MCP)**.
|
||||
|
||||
You can explicitly select a protocol using the `core.WithProtocol` option during client initialization.
|
||||
|
||||
{{< notice note >}}* **Native Toolbox Transport**: This uses the service's native **REST over HTTP** API.
|
||||
* **MCP Transports**: These options use the **Model Context Protocol over HTTP**.
|
||||
{{< /notice >}}
|
||||
|
||||
### Supported Protocols
|
||||
|
||||
| Constant | Description |
|
||||
| :--- | :--- |
|
||||
| `core.MCP` | **(Default)** Alias for the latest supported MCP version (currently `v2025-06-18`). |
|
||||
| `core.Toolbox` | The native Toolbox HTTP protocol. |
|
||||
| `core.MCPv20251125` | MCP Protocol version 2025-11-25. |
|
||||
| `core.MCPv20250618` | MCP Protocol version 2025-06-18. |
|
||||
| `core.MCPv20250326` | MCP Protocol version 2025-03-26. |
|
||||
| `core.MCPv20241105` | MCP Protocol version 2024-11-05. |
|
||||
|
||||
### Example
|
||||
|
||||
```go
|
||||
import (
|
||||
"github.com/googleapis/mcp-toolbox-sdk-go/core"
|
||||
"github.com/googleapis/mcp-toolbox-sdk-go/tbadk"
|
||||
)
|
||||
|
||||
// Initialize with the native Toolbox protocol
|
||||
client, err := tbadk.NewToolboxClient(
|
||||
"http://localhost:5000",
|
||||
core.WithProtocol(core.Toolbox),
|
||||
)
|
||||
|
||||
// Initialize with the MCP Protocol 2025-03-26
|
||||
client, err := tbadk.NewToolboxClient(
|
||||
"http://localhost:5000",
|
||||
core.WithProtocol(core.MCPv20250326),
|
||||
)
|
||||
|
||||
```
|
||||
|
||||
## Loading Tools
|
||||
|
||||
You can load tools individually or in groups (toolsets) as defined in your
|
||||
Toolbox service configuration. Loading a toolset is convenient when working with
|
||||
multiple related functions, while loading a single tool offers more granular
|
||||
control.
|
||||
|
||||
### Load a toolset
|
||||
|
||||
A toolset is a collection of related tools. You can load all tools in a toolset
|
||||
or a specific one:
|
||||
|
||||
```go
|
||||
// Load default toolset by providing an empty string as the name
|
||||
tools, err := client.LoadToolset("", ctx)
|
||||
|
||||
// Load a specific toolset
|
||||
tools, err := client.LoadToolset("my-toolset", ctx)
|
||||
```
|
||||
|
||||
`LoadToolset` returns a slice of the ToolboxTool structs (`[]ToolboxTool`).
|
||||
|
||||
|
||||
### Load a single tool
|
||||
|
||||
Loads a specific tool by its unique name. This provides fine-grained control.
|
||||
|
||||
```go
|
||||
tool, err = client.LoadTool("my-tool", ctx)
|
||||
```
|
||||
|
||||
## Invoking Tools
|
||||
|
||||
Once loaded, tools behave like Go structs. You invoke them using `Run` method
|
||||
by passing arguments corresponding to the parameters defined in the tool's
|
||||
configuration within the Toolbox service.
|
||||
|
||||
```go
|
||||
tool, err = client.LoadTool("my-tool", ctx)
|
||||
inputs := map[string]any{"location": "London"}
|
||||
// Pass the tool.Context as ctx to the Run() function
|
||||
result, err := tool.Run(ctx, inputs)
|
||||
```
|
||||
|
||||
{{< notice tip >}}For a more comprehensive guide on setting up the Toolbox service itself, which
|
||||
you'll need running to use this SDK, please refer to the [Toolbox Quickstart
|
||||
Guide](https://googleapis.github.io/genai-toolbox/getting-started/local_quickstart).
|
||||
{{< /notice >}}
|
||||
|
||||
## Client to Server Authentication
|
||||
|
||||
This section describes how to authenticate the ToolboxClient itself when
|
||||
connecting to a Toolbox server instance that requires authentication. This is
|
||||
crucial for securing your Toolbox server endpoint, especially when deployed on
|
||||
platforms like Cloud Run, GKE, or any environment where unauthenticated access is restricted.
|
||||
|
||||
This client-to-server authentication ensures that the Toolbox server can verify
|
||||
the identity of the client making the request before any tool is loaded or
|
||||
called. It is different from [Authenticating Tools](#authenticating-tools),
|
||||
which deals with providing credentials for specific tools within an already
|
||||
connected Toolbox session.
|
||||
|
||||
### When is Client-to-Server Authentication Needed?
|
||||
|
||||
You'll need this type of authentication if your Toolbox server is configured to
|
||||
deny unauthenticated requests. For example:
|
||||
|
||||
- Your Toolbox server is deployed on Cloud Run and configured to "Require authentication."
|
||||
- Your server is behind an Identity-Aware Proxy (IAP) or a similar
|
||||
authentication layer.
|
||||
- You have custom authentication middleware on your self-hosted Toolbox server.
|
||||
|
||||
Without proper client authentication in these scenarios, attempts to connect or
|
||||
make calls (like `LoadTool`) will likely fail with `Unauthorized` errors.
|
||||
|
||||
### How it works
|
||||
|
||||
The `ToolboxClient` allows you to specify TokenSources that dynamically generate HTTP headers for
|
||||
every request sent to the Toolbox server. The most common use case is to add an
|
||||
Authorization header with a bearer token (e.g., a Google ID token).
|
||||
|
||||
These header-generating functions are called just before each request, ensuring
|
||||
that fresh credentials or header values can be used.
|
||||
|
||||
### Configuration
|
||||
|
||||
You can configure these dynamic headers as seen below:
|
||||
|
||||
|
||||
```go
|
||||
import (
|
||||
"github.com/googleapis/mcp-toolbox-sdk-go/core"
|
||||
"github.com/googleapis/mcp-toolbox-sdk-go/tbadk"
|
||||
)
|
||||
|
||||
tokenProvider := func() string {
|
||||
return "header3_value"
|
||||
}
|
||||
|
||||
staticTokenSource := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: "header2_value"})
|
||||
dynamicTokenSource := core.NewCustomTokenSource(tokenProvider)
|
||||
|
||||
client, err := tbadk.NewToolboxClient(
|
||||
"toolbox-url",
|
||||
core.WithClientHeaderString("header1", "header1_value"),
|
||||
core.WithClientHeaderTokenSource("header2", staticTokenSource),
|
||||
core.WithClientHeaderTokenSource("header3", dynamicTokenSource),
|
||||
)
|
||||
```
|
||||
|
||||
### Authenticating with Google Cloud Servers
|
||||
|
||||
For Toolbox servers hosted on Google Cloud (e.g., Cloud Run) and requiring
|
||||
`Google ID token` authentication, the helper module
|
||||
[auth_methods](/core/auth.go) provides utility functions.
|
||||
|
||||
### Step by Step Guide for Cloud Run
|
||||
|
||||
1. **Configure Permissions**: [Grant](https://cloud.google.com/run/docs/securing/managing-access#service-add-principals) the `roles/run.Runr` IAM role on the Cloud
|
||||
Run service to the principal. This could be your `user account email` or a
|
||||
`service account`.
|
||||
2. **Configure Credentials**
|
||||
- Local Development: Set up
|
||||
[ADC](https://cloud.google.com/docs/authentication/set-up-adc-local-dev-environment).
|
||||
- Google Cloud Environments: When running within Google Cloud (e.g., Compute
|
||||
Engine, GKE, another Cloud Run service, Cloud Functions), ADC is typically
|
||||
configured automatically, using the environment's default service account.
|
||||
3. **Connect to the Toolbox Server**
|
||||
```go
|
||||
import (
|
||||
"github.com/googleapis/mcp-toolbox-sdk-go/core"
|
||||
"github.com/googleapis/mcp-toolbox-sdk-go/tbadk"
|
||||
"context"
|
||||
)
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
token, err := core.GetGoogleIDToken(ctx, URL)
|
||||
|
||||
client, err := tbadk.NewToolboxClient(
|
||||
URL,
|
||||
core.WithClientHeaderString("Authorization", token),
|
||||
)
|
||||
|
||||
// Now, you can use the client as usual.
|
||||
```
|
||||
|
||||
## Authenticating Tools
|
||||
|
||||
{{< notice warning >}} **Always use HTTPS** to connect your application with the Toolbox service,
|
||||
especially in **production environments** or whenever the communication
|
||||
involves **sensitive data** (including scenarios where tools require
|
||||
authentication tokens). Using plain HTTP lacks encryption and exposes your
|
||||
application and data to significant security risks, such as eavesdropping and tampering.
|
||||
{{< /notice >}}
|
||||
|
||||
Tools can be configured within the Toolbox service to require authentication,
|
||||
ensuring only authorized users or applications can invoke them, especially when
|
||||
accessing sensitive data.
|
||||
|
||||
### When is Authentication Needed?
|
||||
|
||||
Authentication is configured per-tool within the Toolbox service itself. If a
|
||||
tool you intend to use is marked as requiring authentication in the service, you
|
||||
must configure the SDK client to provide the necessary credentials (currently
|
||||
Oauth2 tokens) when invoking that specific tool.
|
||||
|
||||
### Supported Authentication Mechanisms
|
||||
|
||||
The Toolbox service enables secure tool usage through **Authenticated Parameters**.
|
||||
For detailed information on how these mechanisms work within the Toolbox service and how to configure them, please refer to [Toolbox Service Documentation - Authenticated Parameters](https://googleapis.github.io/genai-toolbox/resources/tools/#authenticated-parameters).
|
||||
|
||||
### Step 1: Configure Tools in Toolbox Service
|
||||
|
||||
First, ensure the target tool(s) are configured correctly in the Toolbox service
|
||||
to require authentication. Refer to the [Toolbox Service Documentation -
|
||||
Authenticated
|
||||
Parameters](https://googleapis.github.io/genai-toolbox/resources/tools/#authenticated-parameters)
|
||||
for instructions.
|
||||
|
||||
### Step 2: Configure SDK Client
|
||||
|
||||
Your application needs a way to obtain the required Oauth2 token for the
|
||||
authenticated user. The SDK requires you to provide a function capable of
|
||||
retrieving this token *when the tool is invoked*.
|
||||
|
||||
#### Provide an ID Token Retriever Function
|
||||
|
||||
You must provide the SDK with a function that returns the
|
||||
necessary token when called. The implementation depends on your application's
|
||||
authentication flow (e.g., retrieving a stored token, initiating an OAuth flow).
|
||||
|
||||
{{< notice info >}}
|
||||
The name used when registering the getter function with the SDK (e.g.,
|
||||
`"my_api_token"`) must exactly match the `name` of the corresponding
|
||||
`authServices` defined in the tool's configuration within the Toolbox service.
|
||||
{{< /notice >}}
|
||||
|
||||
```go
|
||||
func getAuthToken() string {
|
||||
// ... Logic to retrieve ID token (e.g., from local storage, OAuth flow)
|
||||
// This example just returns a placeholder. Replace with your actual token retrieval.
|
||||
return "YOUR_ID_TOKEN" // Placeholder
|
||||
}
|
||||
```
|
||||
|
||||
{{< notice tip >}} Your token retriever function is invoked every time an authenticated parameter
|
||||
requires a token for a tool call. Consider implementing caching logic within
|
||||
this function to avoid redundant token fetching or generation, especially for
|
||||
tokens with longer validity periods or if the retrieval process is resource-intensive.
|
||||
{{< /notice >}}
|
||||
|
||||
#### Option A: Add Default Authentication to a Client
|
||||
|
||||
You can add default tool level authentication to a client.
|
||||
Every tool / toolset loaded by the client will contain the auth token.
|
||||
|
||||
```go
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
client, err := tbadk.NewToolboxClient("http://127.0.0.1:5000",
|
||||
core.WithDefaultToolOptions(
|
||||
core.WithAuthTokenString("my-auth-1", "auth-value"),
|
||||
),
|
||||
)
|
||||
|
||||
AuthTool, err := client.LoadTool("my-tool", ctx)
|
||||
```
|
||||
|
||||
#### Option B: Add Authentication to a Loaded Tool
|
||||
|
||||
You can add the token retriever function to a tool object *after* it has been
|
||||
loaded. This modifies the specific tool instance.
|
||||
|
||||
```go
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
client, err := tbadk.NewToolboxClient("http://127.0.0.1:5000")
|
||||
|
||||
tool, err := client.LoadTool("my-tool", ctx)
|
||||
|
||||
AuthTool, err := tool.ToolFrom(
|
||||
core.WithAuthTokenSource("my-auth", headerTokenSource),
|
||||
core.WithAuthTokenString("my-auth-1", "value"),
|
||||
)
|
||||
```
|
||||
|
||||
#### Option C: Add Authentication While Loading Tools
|
||||
|
||||
You can provide the token retriever(s) directly during the `LoadTool` or
|
||||
`LoadToolset` calls. This applies the authentication configuration only to the
|
||||
tools loaded in that specific call, without modifying the original tool objects
|
||||
if they were loaded previously.
|
||||
|
||||
```go
|
||||
AuthTool, err := client.LoadTool("my-tool", ctx, core.WithAuthTokenString("my-auth-1", "value"))
|
||||
|
||||
// or
|
||||
|
||||
AuthTools, err := client.LoadToolset(
|
||||
"my-toolset",
|
||||
ctx,
|
||||
core.WithAuthTokenString("my-auth-1", "value"),
|
||||
)
|
||||
```
|
||||
|
||||
{{< notice note >}}
|
||||
Adding auth tokens during loading only affect the tools loaded within that call.
|
||||
{{< /notice >}}
|
||||
|
||||
### Complete Authentication Example
|
||||
|
||||
```go
|
||||
import "github.com/googleapis/mcp-toolbox-sdk-go/core"
|
||||
import "fmt"
|
||||
|
||||
func getAuthToken() string {
|
||||
// ... Logic to retrieve ID token (e.g., from local storage, OAuth flow)
|
||||
// This example just returns a placeholder. Replace with your actual token retrieval.
|
||||
return "YOUR_ID_TOKEN" // Placeholder
|
||||
}
|
||||
|
||||
func main() {
|
||||
ctx := context.Background()
|
||||
inputs := map[string]any{"input": "some input"}
|
||||
|
||||
dynamicTokenSource := core.NewCustomTokenSource(getAuthToken)
|
||||
|
||||
client, err := tbadk.NewToolboxClient("http://127.0.0.1:5000")
|
||||
tool, err := client.LoadTool("my-tool", ctx)
|
||||
AuthTool, err := tool.ToolFrom(core.WithAuthTokenSource("my_auth", dynamicTokenSource))
|
||||
|
||||
result, err := AuthTool.Run(ctx, inputs)
|
||||
|
||||
fmt.Println(result)
|
||||
}
|
||||
```
|
||||
|
||||
{{< notice note >}}An auth token getter for a specific name (e.g., "GOOGLE_ID") will replace any client header with the same name followed by "_token" (e.g.,"GOOGLE_ID_token").
|
||||
{{< /notice >}}
|
||||
|
||||
## Binding Parameter Values
|
||||
|
||||
The SDK allows you to pre-set, or "bind", values for specific tool parameters
|
||||
before the tool is invoked or even passed to an LLM. These bound values are
|
||||
fixed and will not be requested or modified by the LLM during tool use.
|
||||
|
||||
### Why Bind Parameters?
|
||||
|
||||
- **Protecting sensitive information:** API keys, secrets, etc.
|
||||
- **Enforcing consistency:** Ensuring specific values for certain parameters.
|
||||
- **Pre-filling known data:** Providing defaults or context.
|
||||
|
||||
{{< notice info >}}
|
||||
The parameter names used for binding (e.g., `"api_key"`) must exactly match the
|
||||
parameter names defined in the tool's configuration within the Toolbox service.
|
||||
{{< /notice >}}
|
||||
|
||||
{{< notice note >}}
|
||||
You do not need to modify the tool's configuration in the Toolbox service to bind parameter values using the SDK.
|
||||
{{< /notice >}}
|
||||
|
||||
#### Option A: Add Default Bound Parameters to a Client
|
||||
|
||||
You can add default tool level bound parameters to a client. Every tool / toolset
|
||||
loaded by the client will have the bound parameter.
|
||||
|
||||
```go
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
client, err := tbadk.NewToolboxClient("http://127.0.0.1:5000",
|
||||
core.WithDefaultToolOptions(
|
||||
core.WithBindParamString("param1", "value"),
|
||||
),
|
||||
)
|
||||
|
||||
boundTool, err := client.LoadTool("my-tool", ctx)
|
||||
```
|
||||
|
||||
### Option B: Binding Parameters to a Loaded Tool
|
||||
|
||||
Bind values to a tool object *after* it has been loaded. This modifies the
|
||||
specific tool instance.
|
||||
|
||||
```go
|
||||
client, err := tbadk.NewToolboxClient("http://127.0.0.1:5000")
|
||||
|
||||
tool, err := client.LoadTool("my-tool", ctx)
|
||||
|
||||
boundTool, err := tool.ToolFrom(
|
||||
core.WithBindParamString("param1", "value"),
|
||||
core.WithBindParamString("param2", "value")
|
||||
)
|
||||
```
|
||||
|
||||
### Option C: Binding Parameters While Loading Tools
|
||||
|
||||
Specify bound parameters directly when loading tools. This applies the binding
|
||||
only to the tools loaded in that specific call.
|
||||
|
||||
```go
|
||||
boundTool, err := client.LoadTool("my-tool", ctx, core.WithBindParamString("param", "value"))
|
||||
|
||||
// OR
|
||||
|
||||
boundTool, err := client.LoadToolset("", ctx, core.WithBindParamString("param", "value"))
|
||||
```
|
||||
|
||||
{{< notice note >}}
|
||||
Bound values during loading only affect the tools loaded in that call.
|
||||
{{< /notice >}}
|
||||
|
||||
### Binding Dynamic Values
|
||||
|
||||
Instead of a static value, you can bind a parameter to a synchronous or
|
||||
asynchronous function. This function will be called *each time* the tool is
|
||||
invoked to dynamically determine the parameter's value at runtime.
|
||||
Functions with the return type (data_type, error) can be provided.
|
||||
|
||||
```go
|
||||
getDynamicValue := func() (string, error) { return "req-123", nil }
|
||||
|
||||
dynamicBoundTool, err := tool.ToolFrom(core.WithBindParamStringFunc("param", getDynamicValue))
|
||||
```
|
||||
|
||||
{{< notice info >}}
|
||||
You don't need to modify tool configurations to bind parameter values.
|
||||
{{< /notice >}}
|
||||
|
||||
## Using with ADK Go
|
||||
|
||||
After altering the tool to your needs, type-assert the ToolboxTool and pass it to the LLM agent.
|
||||
|
||||
### For a single tool
|
||||
|
||||
```go
|
||||
|
||||
toolboxtool, err = client.LoadTool("my-tool", ctx)
|
||||
|
||||
// <Bind parameters & add authentication here>
|
||||
|
||||
llmagent, err := llmagent.New(llmagent.Config{
|
||||
Name: "assistant",
|
||||
Model: model,
|
||||
Description: "Agent to answer questions.",
|
||||
Tools: []tool.Tool{&toolboxtool},
|
||||
})
|
||||
```
|
||||
|
||||
### For a toolset
|
||||
|
||||
```go
|
||||
toolboxtools, err := client.LoadToolset("", ctx)
|
||||
|
||||
// <Bind parameters & add authentication here>
|
||||
|
||||
toolsList := make([]tool.Tool, len(toolboxtools))
|
||||
for i := range toolboxtools {
|
||||
toolsList[i] = &toolboxtools[i]
|
||||
}
|
||||
|
||||
llmagent, err := llmagent.New(llmagent.Config{
|
||||
Name: "assistant",
|
||||
Model: model,
|
||||
Description: "Agent to answer questions.",
|
||||
Tools: toolsList,
|
||||
})
|
||||
|
||||
```
|
||||
|
||||
The reason we have to type assert it before passing it to ADK Go, is because it requires a generic `tool.Tool` interface. You can always convert it back to `ToolboxTool` format to access the specialized methods.
|
||||
|
||||
# Using with Orchestration Frameworks
|
||||
|
||||
To see how the MCP Toolbox Go SDK works with orchestration frameworks, check out these end-to-end examples given below.
|
||||
|
||||
<details>
|
||||
<summary>ADK Go</summary>
|
||||
|
||||
```go
|
||||
//This sample contains a complete example on how to integrate MCP Toolbox Go SDK with ADK Go using the tbadk package.
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/googleapis/mcp-toolbox-sdk-go/tbadk"
|
||||
"google.golang.org/adk/agent"
|
||||
"google.golang.org/adk/agent/llmagent"
|
||||
"google.golang.org/adk/model/gemini"
|
||||
"google.golang.org/adk/runner"
|
||||
"google.golang.org/adk/session"
|
||||
"google.golang.org/adk/tool"
|
||||
"google.golang.org/genai"
|
||||
)
|
||||
|
||||
func main() {
|
||||
genaiKey := os.Getenv("GEMINI_API_KEY")
|
||||
toolboxURL := "http://localhost:5000"
|
||||
ctx := context.Background()
|
||||
|
||||
// Initialize MCP Toolbox client
|
||||
toolboxClient, err := tbadk.NewToolboxClient(toolboxURL)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create MCP Toolbox client: %v", err)
|
||||
}
|
||||
|
||||
toolsetName := "my-toolset"
|
||||
toolset, err := toolboxClient.LoadToolset(toolsetName, ctx)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to load MCP toolset '%s': %v\nMake sure your Toolbox server is running.", toolsetName, err)
|
||||
}
|
||||
|
||||
// Create Gemini model
|
||||
model, err := gemini.NewModel(ctx, "gemini-2.5-flash", &genai.ClientConfig{
|
||||
APIKey: genaiKey,
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create model: %v", err)
|
||||
}
|
||||
|
||||
tools := make([]tool.Tool, len(toolset))
|
||||
for i := range toolset {
|
||||
tools[i] = &toolset[i]
|
||||
}
|
||||
|
||||
llmagent, err := llmagent.New(llmagent.Config{
|
||||
Name: "hotel_assistant",
|
||||
Model: model,
|
||||
Description: "Agent to answer questions about hotels.",
|
||||
Tools: tools,
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create agent: %v", err)
|
||||
}
|
||||
|
||||
appName := "hotel_assistant"
|
||||
userID := "user-123"
|
||||
|
||||
sessionService := session.InMemoryService()
|
||||
resp, err := sessionService.Create(ctx, &session.CreateRequest{
|
||||
AppName: appName,
|
||||
UserID: userID,
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create the session service: %v", err)
|
||||
}
|
||||
session := resp.Session
|
||||
|
||||
r, err := runner.New(runner.Config{
|
||||
AppName: appName,
|
||||
Agent: llmagent,
|
||||
SessionService: sessionService,
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create runner: %v", err)
|
||||
}
|
||||
|
||||
query := "Find hotels with Basel in its name."
|
||||
|
||||
fmt.Println(query)
|
||||
userMsg := genai.NewContentFromText(query, genai.RoleUser)
|
||||
|
||||
streamingMode := agent.StreamingModeSSE
|
||||
for event, err := range r.Run(ctx, userID, session.ID(), userMsg, agent.RunConfig{
|
||||
StreamingMode: streamingMode,
|
||||
}) {
|
||||
if err != nil {
|
||||
fmt.Printf("\nAGENT_ERROR: %v\n", err)
|
||||
} else {
|
||||
if event.LLMResponse.Content != nil {
|
||||
for _, p := range event.LLMResponse.Content.Parts {
|
||||
if streamingMode != agent.StreamingModeSSE || event.LLMResponse.Partial {
|
||||
fmt.Print(p.Text)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
@@ -1,121 +0,0 @@
|
||||
---
|
||||
title: "Genkit Package"
|
||||
linkTitle: "Genkit"
|
||||
type: docs
|
||||
weight: 1
|
||||
---
|
||||
|
||||

|
||||
|
||||
# MCP Toolbox For Go Genkit SDK
|
||||
|
||||
[](https://opensource.org/licenses/Apache-2.0)
|
||||
|
||||
This package allows you to seamlessly integrate the functionalities of
|
||||
[MCP Toolbox](https://github.com/googleapis/genai-toolbox) allowing you to load and
|
||||
use tools defined in the service as standard Genkit Tools within your Genkit Go
|
||||
applications.
|
||||
|
||||
This simplifies integrating external functionalities (like APIs, databases, or
|
||||
custom logic) managed by the Toolbox into your workflows, especially those
|
||||
involving Large Language Models (LLMs).
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
go get github.com/googleapis/mcp-toolbox-sdk-go
|
||||
```
|
||||
This SDK is supported on Go version 1.24.4 and higher.
|
||||
|
||||
## Quickstart
|
||||
|
||||
For more information on how to load a `ToolboxTool`, see [the core package](https://github.com/googleapis/mcp-toolbox-sdk-go/tree/main/core)
|
||||
|
||||
## Convert Toolbox Tool to a Genkit Tool
|
||||
|
||||
```go
|
||||
"github.com/googleapis/mcp-toolbox-sdk-go/tbgenkit"
|
||||
|
||||
func main() {
|
||||
// Assuming the toolbox tool is loaded
|
||||
// Make sure to add error checks for debugging
|
||||
ctx := context.Background()
|
||||
g, err := genkit.Init(ctx)
|
||||
|
||||
genkitTool, err := tbgenkit.ToGenkitTool(toolboxTool, g)
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
# Using with Orchestration Frameworks
|
||||
|
||||
To see how the MCP Toolbox Go SDK works with orchestration frameworks, check out these end-to-end examples given below.
|
||||
|
||||
<details>
|
||||
<summary>Genkit Go</summary>
|
||||
|
||||
```go
|
||||
//This sample contains a complete example on how to integrate MCP Toolbox Go SDK with Genkit Go using the tbgenkit package.
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/googleapis/mcp-toolbox-sdk-go/core"
|
||||
"github.com/googleapis/mcp-toolbox-sdk-go/tbgenkit"
|
||||
|
||||
"github.com/firebase/genkit/go/ai"
|
||||
"github.com/firebase/genkit/go/genkit"
|
||||
"github.com/firebase/genkit/go/plugins/googlegenai"
|
||||
)
|
||||
|
||||
func main() {
|
||||
ctx := context.Background()
|
||||
toolboxClient, err := core.NewToolboxClient("http://127.0.0.1:5000")
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create Toolbox client: %v", err)
|
||||
}
|
||||
|
||||
// Load the tools using the MCP Toolbox SDK.
|
||||
tools, err := toolboxClient.LoadToolset("my-toolset", ctx)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to load tools: %v\nMake sure your Toolbox server is running and the tool is configured.", err)
|
||||
}
|
||||
|
||||
// Initialize genkit
|
||||
g := genkit.Init(ctx,
|
||||
genkit.WithPlugins(&googlegenai.GoogleAI{}),
|
||||
genkit.WithDefaultModel("googleai/gemini-1.5-flash"),
|
||||
)
|
||||
|
||||
// Convert your tool to a Genkit tool.
|
||||
genkitTools := make([]ai.Tool, len(tools))
|
||||
for i, tool := range tools {
|
||||
newTool, err := tbgenkit.ToGenkitTool(tool, g)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to convert tool: %v\n", err)
|
||||
}
|
||||
genkitTools[i] = newTool
|
||||
}
|
||||
|
||||
toolRefs := make([]ai.ToolRef, len(genkitTools))
|
||||
|
||||
for i, tool := range genkitTools {
|
||||
toolRefs[i] = tool
|
||||
}
|
||||
|
||||
// Generate llm response using prompts and tools.
|
||||
resp, err := genkit.Generate(ctx, g,
|
||||
ai.WithPrompt("Find hotels in Basel with Basel in it's name."),
|
||||
ai.WithTools(toolRefs...),
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatalf("%v\n", err)
|
||||
}
|
||||
fmt.Println(resp.Text())
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
15
docs/en/sdks/js-sdk.md
Normal file
15
docs/en/sdks/js-sdk.md
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
title: "JS SDK"
|
||||
weight: 2
|
||||
description: Javascript client SDK
|
||||
icon: fa-brands fa-node-js
|
||||
manualLink: "https://github.com/googleapis/mcp-toolbox-sdk-js"
|
||||
manualLinkTarget: _blank
|
||||
---
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<link rel="canonical" href="https://github.com/googleapis/mcp-toolbox-sdk-js"/>
|
||||
<meta http-equiv="refresh" content="0;url=https://github.com/googleapis/mcp-toolbox-sdk-js"/>
|
||||
</head>
|
||||
</html>
|
||||
15
docs/en/sdks/python-sdk.md
Normal file
15
docs/en/sdks/python-sdk.md
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
title: "Python SDK"
|
||||
weight: 2
|
||||
description: Python client SDK
|
||||
icon: fa-brands fa-python
|
||||
manualLink: "https://github.com/googleapis/mcp-toolbox-sdk-python"
|
||||
manualLinkTarget: _blank
|
||||
---
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<link rel="canonical" href="https://github.com/googleapis/mcp-toolbox-sdk-python"/>
|
||||
<meta http-equiv="refresh" content="0;url=https://github.com/googleapis/mcp-toolbox-sdk-python"/>
|
||||
</head>
|
||||
</html>
|
||||
@@ -1,98 +0,0 @@
|
||||
---
|
||||
title: "Python"
|
||||
type: docs
|
||||
weight: 1
|
||||
description: >
|
||||
Python SDKs to connect to the MCP Toolbox server.
|
||||
---
|
||||
|
||||
|
||||
## Overview
|
||||
|
||||
The MCP Toolbox service provides a centralized way to manage and expose tools
|
||||
(like API connectors, database query tools, etc.) for use by GenAI applications.
|
||||
|
||||
These Python SDKs act as clients for that service. They handle the communication needed to:
|
||||
|
||||
* Fetch tool definitions from your running Toolbox instance.
|
||||
* Provide convenient Python objects or functions representing those tools.
|
||||
* Invoke the tools (calling the underlying APIs/services configured in Toolbox).
|
||||
* Handle authentication and parameter binding as needed.
|
||||
|
||||
By using these SDKs, you can easily leverage your Toolbox-managed tools directly
|
||||
within your Python applications or AI orchestration frameworks.
|
||||
|
||||
## Which Package Should I Use?
|
||||
|
||||
Choosing the right package depends on how you are building your application:
|
||||
|
||||
* [`toolbox-langchain`](langchain):
|
||||
Use this package if you are building your application using the LangChain or
|
||||
LangGraph frameworks. It provides tools that are directly compatible with the
|
||||
LangChain ecosystem (`BaseTool` interface), simplifying integration.
|
||||
* [`toolbox-llamaindex`](llamaindex):
|
||||
Use this package if you are building your application using the LlamaIndex framework.
|
||||
It provides tools that are directly compatible with the
|
||||
LlamaIndex ecosystem (`BaseTool` interface), simplifying integration.
|
||||
* [`toolbox-core`](core):
|
||||
Use this package if you are not using LangChain/LangGraph or any other
|
||||
orchestration framework, or if you need a framework-agnostic way to interact
|
||||
with Toolbox tools (e.g., for custom orchestration logic or direct use in
|
||||
Python scripts).
|
||||
* [`toolbox-adk`](ADK):
|
||||
Use this package if you are building your application using Google ADK (Agent Development Kit).
|
||||
It provides tools that are directly compatible with the
|
||||
Google ADK ecosystem (`BaseTool` / `BaseToolset` interface) handling authentication propagation, header management, and tool wrapping automatically.
|
||||
|
||||
## Available Packages
|
||||
|
||||
This repository hosts the following Python packages. See the package-specific
|
||||
README for detailed installation and usage instructions:
|
||||
|
||||
| Package | Target Use Case | Integration | Path | Details (README) | PyPI Status |
|
||||
| :------ | :---------- | :---------- | :---------------------- | :---------- | :---------
|
||||
| `toolbox-core` | Framework-agnostic / Custom applications | Use directly / Custom | `packages/toolbox-core/` | 📄 [View README](https://github.com/googleapis/mcp-toolbox-sdk-python/blob/main/packages/toolbox-core/README.md) |  |
|
||||
| `toolbox-langchain` | LangChain / LangGraph applications | LangChain / LangGraph | `packages/toolbox-langchain/` | 📄 [View README](https://github.com/googleapis/mcp-toolbox-sdk-python/blob/main/packages/toolbox-langchain/README.md) |  |
|
||||
| `toolbox-llamaindex` | LlamaIndex applications | LlamaIndex | `packages/toolbox-llamaindex/` | 📄 [View README](https://github.com/googleapis/mcp-toolbox-sdk-python/blob/main/packages/toolbox-llamaindex/README.md) |  |
|
||||
| `toolbox-adk` | Google ADK applications | Google ADK | `packages/toolbox-adk/` | 📄 [View README](https://github.com/googleapis/mcp-toolbox-sdk-python/blob/main/packages/toolbox-adk/README.md) |  |
|
||||
|
||||
|
||||
## Getting Started
|
||||
|
||||
To get started using Toolbox tools with an application, follow these general steps:
|
||||
|
||||
1. **Set up and Run the Toolbox Service:**
|
||||
|
||||
Before using the SDKs, you need the main MCP Toolbox service running. Follow
|
||||
the instructions here: [**Toolbox Getting Started
|
||||
Guide**](https://github.com/googleapis/genai-toolbox?tab=readme-ov-file#getting-started)
|
||||
|
||||
2. **Install the Appropriate SDK:**
|
||||
|
||||
Choose the package based on your needs (see "[Which Package Should I Use?](#which-package-should-i-use)" above) and install it:
|
||||
|
||||
```bash
|
||||
# For the core, framework-agnostic SDK
|
||||
pip install toolbox-core
|
||||
|
||||
# OR
|
||||
|
||||
# For LangChain/LangGraph integration
|
||||
pip install toolbox-langchain
|
||||
|
||||
# OR
|
||||
|
||||
# For the LlamaIndex integration
|
||||
pip install toolbox-llamaindex
|
||||
|
||||
# OR
|
||||
|
||||
# For the Google ADK Integration
|
||||
pip install google-adk[toolbox]
|
||||
```
|
||||
|
||||
|
||||
|
||||
{{< notice note >}}
|
||||
Source code for [python-sdk](https://github.com/googleapis/mcp-toolbox-sdk-python)
|
||||
{{< /notice >}}
|
||||
2
go.mod
2
go.mod
@@ -94,7 +94,7 @@ require (
|
||||
cloud.google.com/go/monitoring v1.24.3 // indirect
|
||||
cloud.google.com/go/trace v1.11.7 // indirect
|
||||
dario.cat/mergo v1.0.2 // indirect
|
||||
filippo.io/edwards25519 v1.1.0 // indirect
|
||||
filippo.io/edwards25519 v1.1.1 // indirect
|
||||
github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect
|
||||
github.com/99designs/keyring v1.2.2 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 // indirect
|
||||
|
||||
3
go.sum
3
go.sum
@@ -639,8 +639,9 @@ cloud.google.com/go/workflows v1.10.0/go.mod h1:fZ8LmRmZQWacon9UCX1r/g/DfAXx5VcP
|
||||
dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8=
|
||||
dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
||||
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||
filippo.io/edwards25519 v1.1.1 h1:YpjwWWlNmGIDyXOn8zLzqiD+9TyIlPhGFG96P39uBpw=
|
||||
filippo.io/edwards25519 v1.1.1/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||
gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8=
|
||||
git.sr.ht/~sbinet/gg v0.3.1/go.mod h1:KGYtlADtqsqANL9ueOFkWymvzUvLMQllU5Ixo+8v3pc=
|
||||
github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs=
|
||||
|
||||
@@ -15,7 +15,6 @@ package redis
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
@@ -45,20 +44,14 @@ func newConfig(ctx context.Context, name string, decoder *yaml.Decoder) (sources
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
Name string `yaml:"name" validate:"required"`
|
||||
Type string `yaml:"type" validate:"required"`
|
||||
Address []string `yaml:"address" validate:"required"`
|
||||
Username string `yaml:"username"`
|
||||
Password string `yaml:"password"`
|
||||
Database int `yaml:"database"`
|
||||
UseGCPIAM bool `yaml:"useGCPIAM"`
|
||||
ClusterEnabled bool `yaml:"clusterEnabled"`
|
||||
TLS TLSConfig `yaml:"tls"`
|
||||
}
|
||||
|
||||
type TLSConfig struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
InsecureSkipVerify bool `yaml:"insecureSkipVerify"`
|
||||
Name string `yaml:"name" validate:"required"`
|
||||
Type string `yaml:"type" validate:"required"`
|
||||
Address []string `yaml:"address" validate:"required"`
|
||||
Username string `yaml:"username"`
|
||||
Password string `yaml:"password"`
|
||||
Database int `yaml:"database"`
|
||||
UseGCPIAM bool `yaml:"useGCPIAM"`
|
||||
ClusterEnabled bool `yaml:"clusterEnabled"`
|
||||
}
|
||||
|
||||
func (r Config) SourceConfigType() string {
|
||||
@@ -98,13 +91,6 @@ func initRedisClient(ctx context.Context, r Config) (RedisClient, error) {
|
||||
}
|
||||
}
|
||||
|
||||
var tlsConfig *tls.Config
|
||||
if r.TLS.Enabled {
|
||||
tlsConfig = &tls.Config{
|
||||
InsecureSkipVerify: r.TLS.InsecureSkipVerify,
|
||||
}
|
||||
}
|
||||
|
||||
var client RedisClient
|
||||
var err error
|
||||
if r.ClusterEnabled {
|
||||
@@ -118,7 +104,6 @@ func initRedisClient(ctx context.Context, r Config) (RedisClient, error) {
|
||||
CredentialsProviderContext: authFn,
|
||||
Username: r.Username,
|
||||
Password: r.Password,
|
||||
TLSConfig: tlsConfig,
|
||||
})
|
||||
err = clusterClient.ForEachShard(ctx, func(ctx context.Context, shard *redis.Client) error {
|
||||
return shard.Ping(ctx).Err()
|
||||
@@ -140,7 +125,6 @@ func initRedisClient(ctx context.Context, r Config) (RedisClient, error) {
|
||||
CredentialsProviderContext: authFn,
|
||||
Username: r.Username,
|
||||
Password: r.Password,
|
||||
TLSConfig: tlsConfig,
|
||||
})
|
||||
_, err = standaloneClient.Ping(ctx).Result()
|
||||
if err != nil {
|
||||
|
||||
@@ -63,9 +63,6 @@ func TestParseFromYamlRedis(t *testing.T) {
|
||||
database: 1
|
||||
useGCPIAM: true
|
||||
clusterEnabled: true
|
||||
tls:
|
||||
enabled: true
|
||||
insecureSkipVerify: true
|
||||
`,
|
||||
want: map[string]sources.SourceConfig{
|
||||
"my-redis-instance": redis.Config{
|
||||
@@ -76,10 +73,6 @@ func TestParseFromYamlRedis(t *testing.T) {
|
||||
Database: 1,
|
||||
ClusterEnabled: true,
|
||||
UseGCPIAM: true,
|
||||
TLS: redis.TLSConfig{
|
||||
Enabled: true,
|
||||
InsecureSkipVerify: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user