1. Project Overview & Quickstart (googleapis/mcp-toolbox)
File: docs/en/documentation/configuration/authentication/_index.md
title: "Authentication" type: docs weight: 1 AuthServices represent services that handle authentication and authorization.
AuthServices represent services that handle authentication and authorization. They support two distinct modes of operation:
1. Toolbox Native Authorization
Used for specific tools to enforce authorization or resolve parameters:
- Authorized Invocation: A tool is validated by the auth service before it can be invoked. Toolbox will reject any calls that fail to validate or have an invalid token.
- Authenticated Parameters: Replaces the value of a parameter with a field from an OIDC claim. Toolbox will automatically resolve the ID token provided by the client and replace the parameter in the tool call.
2. MCP Authorization
Used to secure the entire MCP server. The Model Context Protocol supports MCP Authorization to secure interactions between clients and servers. When enabled, all MCP endpoints require a valid token, and you can enforce granular tool-level scope authorization. Note that this mode is currently only supported when using the generic auth service type.
Example
The following configurations are placed at the top level of a tools.yaml file.
{{< notice tip >}}
If you are accessing Toolbox with multiple applications, each
application should register their own Client ID even if they use the same
"type" of auth provider.
{{< /notice >}}
kind: authService
name: my_auth_app_1
type: google
clientId: ${YOUR_CLIENT_ID_1}
---
kind: authService
name: my_auth_app_2
type: google
clientId: ${YOUR_CLIENT_ID_2}{{< notice tip >}}
Use environment variable replacement with the format ${ENV_NAME}
instead of hardcoding your secrets into the configuration file.
{{< /notice >}}
After you've configured an authService, you can use it:
- For Toolbox Native Authorization by referencing it in your tool configuration (using
authRequiredorauthServicein parameters). - For MCP Authorization by setting
mcpEnabled: truein the auth service configuration to secure the entire server.
Specifying ID Tokens from Clients
After configuring your authService, use a Toolbox SDK to
add your ID tokens to the header of a Tool invocation request. When specifying a
token you will provide a function (that returns an id). This function is called
when the tool is invoked. This allows you to cache and refresh the ID token as
needed.
The primary method for providing these getters is via the auth_token_getters
parameter when loading tools, or the add_auth_token_getter() /add_auth_token_getters() methods on a loaded tool object.
Specifying tokens during load
Python
Use the Python SDK.
{{< tabpane persist=header >}}
{{< tab header="Core" lang="Python" >}}
import asyncio
from toolbox_core import ToolboxClient
async def get_auth_token():
# ... 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
async def main():
async with ToolboxClient("http://127.0.0.1:5000") as toolbox:
auth_tool = await toolbox.load_tool(
"get_sensitive_data",
auth_token_getters={"my_auth_app_1": get_auth_token}
)
result = await auth_tool(param="value")
print(result)
if name == "main":
asyncio.run(main())
{{< /tab >}}
{{< tab header="LangChain" lang="Python" >}}
import asyncio
from toolbox_langchain import ToolboxClient
async def get_auth_token():
# ... 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
async def main():
toolbox = ToolboxClient("http://127.0.0.1:5000")
auth_tool = await toolbox.aload_tool(
"get_sensitive_data",
auth_token_getters={"my_auth_app_1": get_auth_token}
)
result = await auth_tool.ainvoke({"param": "value"})
print(result)if name == "main":
asyncio.run(main())
{{< /tab >}}
{{< tab header="Llamaindex" lang="Python" >}}
import asyncio
from toolbox_llamaindex import ToolboxClient
async def get_auth_token():
# ... 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
async def main():
toolbox = ToolboxClient("http://127.0.0.1:5000")
auth_tool = await toolbox.aload_tool(
"get_sensitive_data",
auth_token_getters={"my_auth_app_1": get_auth_token}
)
# result = await auth_tool.acall(param="value")
# print(result.content)if name == "main":
asyncio.run(main()){{< /tab >}}
{{< /tabpane >}}
Javascript/Typescript
Use the JS SDK.
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 authTool = await client.loadTool("my-tool", {"my_auth_app_1": getAuthToken});
const result = await authTool({param:"value"});
console.log(result);
print(result)Go
Use the Go SDK.
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() {
URL := "http://127.0.0.1:5000"
client, err := core.NewToolboxClient(URL)
if err != nil {
log.Fatalf("Failed to create Toolbox client: %v", err)
}
dynamicTokenSource := core.NewCustomTokenSource(getAuthToken)
authTool, err := client.LoadTool(
"my-tool",
ctx,
core.WithAuthTokenSource("my_auth_app_1", dynamicTokenSource))
if err != nil {
log.Fatalf("Failed to load tool: %v", err)
}
inputs := map[string]any{"param": "value"}
result, err := authTool.Invoke(ctx, inputs)
if err != nil {
log.Fatalf("Failed to invoke tool: %v", err)
}
fmt.Println(result)
}Specifying tokens for existing tools
Python
Use the Python
SDK.
{{< tabpane persist=header >}}
{{< tab header="Core" lang="Python" >}}
tools = await toolbox.load_toolset()
for a single token
authorized_tool = tools[0].add_auth_token_getter("my_auth", get_auth_token)
OR, if multiple tokens are needed
authorized_tool = tools[0].add_auth_token_getters({
"my_auth1": get_auth1_token,
"my_auth2": get_auth2_token,
})
{{< /tab >}}
{{< tab header="LangChain" lang="Python" >}}
tools = toolbox.load_toolset()
for a single token
authorized_tool = tools[0].add_auth_token_getter("my_auth", get_auth_token)
OR, if multiple tokens are needed
authorized_tool = tools[0].add_auth_token_getters({
"my_auth1": get_auth1_token,
"my_auth2": get_auth2_token,
})
{{< /tab >}}
{{< tab header="Llamaindex" lang="Python" >}}
tools = toolbox.load_toolset()
for a single token
authorized_tool = tools[0].add_auth_token_getter("my_auth", get_auth_token)
OR, if multiple tokens are needed
authorized_tool = tools[0].add_auth_token_getters({
"my_auth1": get_auth1_token,
"my_auth2": get_auth2_token,
})
{{< /tab >}}
{{< /tabpane >}}
Javascript/Typescript
Use the JS SDK.
const URL = 'http://127.0.0.1:5000';
let client = new ToolboxClient(URL);
let tool = await client.loadTool("my-tool")
// for a single token
const authorizedTool = tool.addAuthTokenGetter("my_auth", get_auth_token)
// OR, if multiple tokens are needed
const multiAuthTool = tool.addAuthTokenGetters({
"my_auth_1": getAuthToken1,
"my_auth_2": getAuthToken2,
})Go
Use the Go SDK.
import "github.com/googleapis/mcp-toolbox-sdk-go/core"
func main() {
URL := "http://127.0.0.1:5000"
client, err := core.NewToolboxClient(URL)
if err != nil {
log.Fatalf("Failed to create Toolbox client: %v", err)
}
tool, err := client.LoadTool("my-tool", ctx)
if err != nil {
log.Fatalf("Failed to load tool: %v", err)
}
dynamicTokenSource1 := core.NewCustomTokenSource(getAuthToken1)
dynamicTokenSource2 := core.NewCustomTokenSource(getAuthToken1)
// For a single token
authTool, err := tool.ToolFrom(
core.WithAuthTokenSource("my-auth", dynamicTokenSource1),
)
// OR, if multiple tokens are needed
authTool, err := tool.ToolFrom(
core.WithAuthTokenSource("my-auth_1", dynamicTokenSource1),
core.WithAuthTokenSource("my-auth_2", dynamicTokenSource2),
)
}Types of Auth Services
File: docs/en/documentation/configuration/authentication/generic.md
title: "Generic OIDC Auth" type: docs weight: 2 Use a Generic OpenID Connect (OIDC) provider for OAuth 2.0 flow and token lifecycle.
Getting Started
The Generic Auth Service allows you to integrate with any OpenID Connect (OIDC)
compliant identity provider (IDP). It discovers the JWKS (JSON Web Key Set) URL
either through the provider's /.well-known/openid-configuration endpoint or
directly via the provided authorizationServer.
To configure this auth service, you need to provide the audience (the expected aud claim in the token), the authorizationServer of your identity provider, and optionally a list of scopesRequired that must be present in the token's claims.
[!NOTE]
The only time theaudclaim matches theclient_idis inside an ID Token (a concept from OpenID Connect used to verify a user's identity). Because an ID token is intended to be consumed by the client application itself, the client is the audience.
Usage Modes
The Generic Auth Service supports two distinct modes of operation:
1. Toolbox Auth
This mode is used for Toolbox's native authentication/authorization features. It
is active when you reference the auth service in a tool's configuration andmcpEnabled is set to false.
- Header: Expects the token in a custom header matching
<name>_token
(e.g.,my-generic-auth_token). - Token Type: Only supports JWT (OIDC) tokens.
- Usage: Used for Authenticated Parameters and Authorized
Invocations.
Token Validation
When a request is received in this mode, the service will:
- Extract the token from the
<name>_tokenheader. - Treat it as a JWT (opaque tokens are not supported in this mode).
- Validates signature using JWKS fetched from
authorizationServer. - Verifies expiration (
exp) and audience (aud). - Verifies required scopes in
scopeclaim.
Example
kind: authService
name: my-generic-auth
type: generic
audience: ${YOUR_OIDC_AUDIENCE}
authorizationServer: https://your-idp.example.com
# mcpEnabled: false
scopesRequired:
- read
- writeTool Usage Example
To use this auth service for Authenticated Parameters or Authorized
Invocations, reference it in your tool configuration:
kind: tool
name: secure_query
type: postgres-sql
source: my-pg-instance
statement: |
SELECT * FROM data WHERE user_id = $1
parameters:
- name: user_id
type: strings
description: Auto-populated from token
authServices:
- name: my-generic-auth
field: sub # Extract 'sub' claim from JWT
authRequired:
- my-generic-auth # Require valid token for invocation2. MCP Authorization
This mode enforces global authentication for all MCP endpoints. It is active
when mcpEnabled is set to true in the auth service configuration.
- Header: Expects the token in the standard
Authorization: Bearer <token>
header. - Token Type: Supports both JWT and Opaque tokens.
- Usage: Used to secure the entire MCP server.
Token Validation
When a request is received in this mode, the service will:
- Extract the token from the
Authorizationheader afterBearerprefix. - Determine if the token is a JWT or an opaque token based on format (JWTs
contain exactly two dots). - For JWTs:
- Validates signature using JWKS fetched from
authorizationServer. - Verifies expiration (
exp) and audience (aud). - Verifies required scopes in
scopeclaim.
- Validates signature using JWKS fetched from
- For Opaque Tokens:
- Calls the introspection endpoint (either configured via
introspectionEndpoint
or discovered from theauthorizationServer's OIDC configuration). - Verifies expiration (
exp) and audience (audor"audience"fallback). - Verifies required scopes in
scopefield.
- Calls the introspection endpoint (either configured via
Example
kind: authService
name: my-generic-auth
type: generic
audience: ${YOUR_TOKEN_AUDIENCE}
authorizationServer: https://your-idp.example.com
mcpEnabled: true
scopesRequired:
- read
- writeGoogle Authentication Note
[!WARNING]
Do not configure Google's tokeninfo endpoint (https://oauth2.googleapis.com/tokeninfo) usingtype: generic. Because the generic OIDC service strictly enforces the presence and validity of theactiveclaim (RFC 7662), and Google's tokeninfo endpoint does not return this claim, validation will fail.To authenticate with Google tokens, use the native Google Sign-In auth service (
type: google) instead, which natively handles Google's endpoints and token formats.
Okta OIDC Configuration Example
To secure your MCP server or tools using Okta as the identity provider:
kind: authService
name: okta-auth
type: generic
audience: api://default # Or your custom Okta audience
authorizationServer: https://your-subdomain.okta.com/oauth2/default
mcpEnabled: true
scopesRequired:
- openid
- profile[!NOTE]
If you are using Okta's Org Authorization Server (instead of a Custom Authorization Server), yourauthorizationServerURL will behttps://your-subdomain.okta.com.
Tool-Level Scopes
When using MCP Authorization (with mcpEnabled: true in the auth service), you can enforce granular tool-level scope authorization by specifying the scopesRequired field in the tool configuration.
This ensures that a client can only invoke the tool if their authorization token contains all the specified scopes.
kind: tool
name: update_flight_status
type: postgres-sql
source: my-pg-instance
statement: |
UPDATE flights SET status = $1 WHERE flight_number = $2
description: Update flight status
authRequired:
- my-generic-auth
scopesRequired:
- execute:sql
- write:flightsIf a client attempts to invoke this tool without the required scopes, the server will return an HTTP 403 Forbidden response with a WWW-Authenticate header challenge indicating the missing scopes, as per the MCP Auth specification.
{{< notice tip >}} Use environment variable replacement with the format
${ENV_NAME} instead of hardcoding your secrets into the configuration file.
{{< /notice >}}
Reference
| field | type | required | description |
|---|---|---|---|
| type | string | true | Must be "generic". |
| audience | string | true | The expected audience (aud claim) in the token. This ensures the token was minted specifically for your application. See Getting Started for details on OIDC audience matching. |
| authorizationServer | string | true | The base URL of your OIDC provider. The service will append /.well-known/openid-configuration to discover the JWKS URI. HTTP is allowed but logs a warning. |
| mcpEnabled | bool | false | Indicates if MCP endpoint authentication should be applied. Defaults to false. |
| scopesRequired | []string | false | A list of required scopes that must be present in the token's scope claim to be considered valid. Disallowed if mcpEnabled is false. |
| introspectionEndpoint | string | false | Optional override for the token introspection URL. Useful if the provider does not list it in OIDC discovery (e.g., Google). Disallowed if mcpEnabled is false. |
| introspectionMethod | string | false | HTTP method to use for introspection. Defaults to "POST". Set to "GET" for providers like Google. Disallowed if mcpEnabled is false. |
| introspectionParamName | string | false | Parameter name for the token in the introspection request. Defaults to "token". Set to "access_token" for Google. Disallowed if mcpEnabled is false. |
File: docs/en/documentation/configuration/authentication/google.md
title: "Google Sign-In" type: docs weight: 1 Use Google Sign-In for OAuth 2.0 flow and token lifecycle.
Getting Started
Google Sign-In manages the OAuth 2.0 flow and token lifecycle. To integrate the Google Sign-In workflow to your web app, follow this guide.
After setting up Google Sign-In, configure your auth service in the toolbox. The Google auth provider supports two distinct validation modes:
- Web App Claims (OIDC): Used to authenticate user requests in web applications.
- MCP Authorization: Used to secure the entire MCP server transport (SSE or Stdio).
Configuration Modes
1. Web App OIDC Authentication
If you are developing a web application using the Toolbox and need to retrieve user claims from Google ID tokens sent in custom request headers, configure the clientId field.
- Header: Expects the token in the
<name>_tokenheader (e.g.my-google-auth_token). - Token Type: Google OIDC ID tokens (JWT).
Example
kind: authService
name: my-google-auth
type: google
clientId: ${YOUR_GOOGLE_CLIENT_ID}2. MCP Authorization
To secure all endpoints on your MCP server using Google OAuth tokens, enable mcpEnabled and specify the audience field.
- Header: Expects the token in the standard
Authorization: Bearer <token>header. - Token Type: Supports both Google ID tokens (JWT) and Google opaque access tokens.
Example
kind: authService
name: my-google-auth
type: google
audience: ${YOUR_GOOGLE_CLIENT_ID}
mcpEnabled: true
scopesRequired:
- https://www.googleapis.com/auth/userinfo.email[!IMPORTANT]
- For ID tokens (JWT): Local cryptographic signature verification is performed, which requires
audienceto be configured. Ifaudienceis not set, the provider will fall back to usingclientId. If neither is configured, validation will fail.- For Opaque tokens: The provider automatically queries Google's secure tokeninfo endpoint (
https://oauth2.googleapis.com/tokeninfo) and validates the resulting audience against the configuredaudiencefield (falling back toclientIdifaudienceis not set).
Behavior
Authorized Invocations
When using Authorized Invocations, a tool will be considered authorized if it has a valid OAuth 2.0 token that matches the Client ID or Audience.
Authenticated Parameters
When using Authenticated Parameters, any claim provided by the id-token can be used for the parameter.
Reference
| field | type | required | description |
|---|---|---|---|
| type | string | true | Must be "google". |
| clientId | string | false | Client ID of your application. Required for validating ID tokens in non-MCP web apps (GetClaimsFromHeader), and acts as a fallback for audience in MCP auth mode if audience is not configured. |
| audience | string | false | Expected audience. Required for validating ID tokens in MCP Auth mode (unless clientId is configured as a fallback). If specified, also validates opaque token audiences. Disallowed if mcpEnabled is false. |
| mcpEnabled | bool | false | Enforces global MCP transport authentication using the Authorization: Bearer header. Defaults to false. |
| scopesRequired | []string | false | A list of required scopes that must be present in the token's claims/metadata to be considered valid. Disallowed if mcpEnabled is false. |
File: docs/en/documentation/configuration/embedding-models/_index.md
title: "EmbeddingModels" type: docs weight: 7 EmbeddingModels represent services that transform text into vector embeddings for semantic search.
EmbeddingModels represent services that generate vector representations of text
data. In the MCP Toolbox, these models enable Semantic Queries, allowing
Tools to automatically convert human-readable text into numerical
vectors before using them in a query.
This is primarily used in two scenarios:
Vector Ingestion: Converting a text parameter into a vector string during
anINSERToperation.Semantic Search: Converting a natural language query into a vector to
perform similarity searches.
Hidden Parameter Duplication (valueFromParam)
When building tools for vector ingestion, you often need the same input string
twice:
- To store the original text in a TEXT column.
- To generate the vector embedding for a VECTOR column.
Requesting an Agent (LLM) to output the exact same string twice is inefficient
and error-prone. The valueFromParam field solves this by allowing a parameter
to inherit its value from another parameter in the same tool.
Key Behaviors
- Hidden from Manifest: Parameters with valueFromParam set are excluded from
the tool definition sent to the Agent. The Agent does not know this parameter
exists. - Auto-Filled: When the tool is executed, the Toolbox automatically copies the
value from the referenced parameter before processing embeddings.
Example
The following configuration defines an embedding model and applies it to
specific tool parameters.
{{< notice tip >}} Use environment variable replacement with the format
${ENV_NAME} instead of hardcoding your API keys into the configuration file.
{{< /notice >}}
Step 1 - Define an Embedding Model
Define an embedding model with the embeddingModel kind:
kind: embeddingModel
name: gemini-model # Name of the embedding model
type: gemini
model: gemini-embedding-001
apiKey: ${GOOGLE_API_KEY}
dimension: 768Step 2 - Embed Tool Parameters
Use the defined embedding model, embed your query parameters using theembeddedBy field. Only string-typed parameters can be embedded:
# Vector ingestion tool
kind: tool
name: insert_embedding
type: postgres-sql
source: my-pg-instance
description: Insert a new document into the database.
statement: |
INSERT INTO documents (content, embedding)
VALUES ($1, $2);
parameters:
- name: content
type: string
description: The raw text content to be stored in the database.
- name: vector_string
type: string
description: A hidden parameter holding a copy of 'content' to be embedded as a vector.
# This parameter is hidden from the LLM.
# It automatically copies the value from 'content' and embeds it.
valueFromParam: content
embeddedBy: gemini-model
---
# Semantic search tool
kind: tool
name: search_embedding
type: postgres-sql
source: my-pg-instance
description: Search for documents in the database.
statement: |
SELECT id, content, embedding <-> $1 AS distance
FROM documents
ORDER BY distance LIMIT 1
parameters:
- name: semantic_search_string
type: string
description: The search query that will be converted to a vector.
embeddedBy: gemini-model # refers to the name of a defined embedding modelTypes of Embedding Models
File: docs/en/documentation/configuration/embedding-models/gemini.md
title: "Gemini Embedding" type: docs weight: 1 Use Google's Gemini models to generate high-performance text embeddings for vector databases.
About
Google Gemini provides state-of-the-art embedding models that convert text into
high-dimensional vectors.
Authentication
Toolbox supports two authentication modes:
- Google AI (API Key): Used if you
provideapiKey(or setGOOGLE_API_KEY/GEMINI_API_KEYenvironment
variables). This uses the Google AI Studio backend. - Vertex AI (ADC): Used if provided
projectandlocation(or setGOOGLE_CLOUD_PROJECT/GOOGLE_CLOUD_LOCATIONenvironment variables). This uses Application
Default Credentials (ADC).
We recommend using an API key for quick testing and using Vertex AI with ADC for
production environments.
Behavior
Automatic Vectorization
When a tool parameter is configured with embeddedBy: <your-gemini-model-name>,
the Toolbox intercepts the raw text input from the client and sends it to the
Gemini API. The resulting numerical array is then formatted before being passed
to your database source.
Dimension Matching
The dimension field must match the expected size of your database column
(e.g., a vector(768) column in PostgreSQL). This setting is supported by newer
models since 2024 only. You cannot set this value if using the earlier model
(models/embedding-001). Check out available Gemini models for
more information.
Example
Using Google AI
Google AI uses API Key for authentication. You can get an API key from Google
AI Studio.
kind: embeddingModel
name: gemini-model
type: gemini
model: gemini-embedding-001
apiKey: ${GOOGLE_API_KEY}
dimension: 768Using Vertex AI
Vertex AI uses Application Default Credentials (ADC) for authentication. Learn
how to set up ADC here.
kind: embeddingModel
name: gemini-model
type: gemini
model: gemini-embedding-001
project: ${GOOGLE_CLOUD_PROJECT}
location: us-central1
dimension: 768{{< notice tip >}} Use environment variable replacement with the format
${ENV_NAME} instead of hardcoding your secrets into the configuration file.
{{< /notice >}}
Reference
| field | type | required | description |
|---|---|---|---|
| type | string | true | Must be gemini. |
| model | string | true | The Gemini model ID to use (e.g., gemini-embedding-001). |
| dimension | integer | false | The number of dimensions in the output vector (e.g., 768). |
File: docs/en/documentation/configuration/groups/_index.md
title: "Groups" type: docs weight: 6 Groups let you scope MCP primitives such as tools, prompts, resources, and resource templates together under a single name, with a description used as group metadata.
A Group is a single named collection that scopes MCP primitives together โ including tools, prompts, resources, and resource templates. Where a Toolset groups only tools, a group bundles these primitives under one name and one MCP endpoint, and carries a description that describes the collection.
Connecting to a group's endpoint (/mcp/{name}) scopes the corresponding MCP list methods (such as tools/list, prompts/list, resources/list, resources/templates/list, and resources/read) to that group. Groups are also introspectable over MCP through methods which are available on the com.google.cloud/toolbox.v1 extension.
Defining Groups
Declare a group as a kind: group document in your configuration file. A group has the following fields:
| Field | Required | Description |
|---|---|---|
name |
Yes* | Unique name for the group. Used as the endpoint path (/mcp/{name}). |
description |
No | Human-readable description of the group, surfaced via groups/list. |
tools |
No | List of tool names to include in the group. |
prompts |
No | List of prompt names to include in the group. |
resources |
No | List of resource names to include in the group. |
resourceTemplates |
No | List of resource template names to include in the group. |
ttlMs |
No | Time-to-live in milliseconds for cached group list responses. (MCP TTL Spec). Defaults to 300000 (5 minutes). |
cacheScope |
No | Cache visibility for group list responses (either public or private). (MCP Cache Scope Spec). Defaults to public. |
* name is required for every named group. The single default group omits it.
kind: group
name: data_analyst
description: Tools, prompts, and resources for exploratory data analysis.
tools:
- list_tables
- execute_sql
prompts:
- summarize_results
resources:
- database_schema
resourceTemplates:
- query_logs
---
kind: group
name: admin
description: Administrative operations.
tools:
- create_user
- list_users
resources:
- admin_guide
ttlMs: 3600000
cacheScope: privateThe default group
A single default (nameless) group always exists and contains all configured primitives (every tool, prompt, resource, and resource template). Connecting to the default MCP endpoint (/mcp) returns everything.
You may declare a kind: group document with no name to set a description for the default group. Because the default group always contains everything, it cannot declare tools, prompts, resources, resourceTemplates, or any other primitive list:
kind: group
description: All tools, prompts, and resources available on this server.Validation rules
At startup, Toolbox validates groups:
- Unique names. A named group must have a unique name that satisfies the standard name rules (alphanumeric characters, underscores, and hyphens).
- One default group. Declaring more than one nameless group is an error.
- Default group restrictions. The default group may set only a
description; declaringtools,prompts,resources,resourceTemplates, or any other primitive list on it is an error. - No duplicate names across toolsets and groups. A
kind: toolsetis parsed as a group, so defining the same name as both akind: toolsetand akind: groupis a duplicate-name error. - Valid parameters. If specified,
ttlMsmust be non-negative (>=0), andcacheScopemust be eitherpublicorprivate. - No UI resources in groups. UI resources and UI resource templates (
ui: true) are strictly global and cannot be included inresourcesorresourceTemplatesof any group. Attempting to add a UI resource to a group fails startup validation. (See MCP Apps for details on linking tools to UI resources.)
Relationship to toolsets
Groups are a superset of toolsets: a toolset is equivalent to a tools-only group. Existing kind: toolset configurations still load โ Toolbox parses every toolset as a group โ but that parity is not exact, so review the differences below before assuming a toolset behaves as it did:
- A toolset has no
descriptionof its own, so one written on akind: toolsetis dropped rather than promoted, and Toolbox logs a warning. To give a collection a description, declare it as akind: group. - Unrecognized fields on a toolset are rejected at startup instead of being silently ignored.
- Declaring the same name as both a
kind: toolsetand akind: groupis a duplicate-name error; previously the group silently took precedence.
We recommend migrating to a kind: group even for tools-only collections, so the configuration matches what Toolbox actually loads and can grow to scope prompts, resources, and resource templates alongside tools. See Toolsets for more.
To convert existing toolsets to groups automatically, run the migrate command. It rewrites both nested toolsets: blocks and already-flat kind: toolset documents to kind: group:
toolbox migrate --config tools.yamlUse --dry-run to preview the changes without writing them.
File: docs/en/documentation/configuration/pre-post-processing/go/_index.md
title: "Go: Pre & Post Processing" type: docs weight: 3 How to add pre- and post- processing to your Agents using Go. sample_filters: ["Pre & Post Processing", "Go", "ADK"] is_sample: true
Prerequisites
This tutorial assumes that you have set up MCP Toolbox with a basic agent as described in the local quickstart.
This guide demonstrates how to implement these patterns in your Toolbox applications.
Implementation
{{< tabpane persist=header >}}
{{% tab header="ADK" text=true %}}
The following example demonstrates how to use the beforeToolCallback and afterToolCallback hooks in the ADK LlmAgent to implement pre and post processing logic.
{{< include "adk/agent.go" "go" >}}
You can also add model-level (beforeModelCallback, afterModelCallback) and agent-level (beforeAgentCallback, afterAgentCallback) hooks to intercept messages at different stages of the execution loop.
For more information, see the ADK Callbacks documentation.{{% /tab %}}
{{< /tabpane >}}
Results
The output should look similar to the following.
{{< notice note >}}
The exact responses may vary due to the non-deterministic nature of LLMs and differences between orchestration frameworks.
{{< /notice >}}
AI: Booking Confirmed! You earned 500 Loyalty Points with this stay.
AI: Error: Maximum stay duration is 14 days.File: docs/en/documentation/configuration/pre-post-processing/js/_index.md
title: "Javascript: Pre & Post Processing" type: docs weight: 2 How to add pre- and post- processing to your Agents using JS. sample_filters: ["Pre & Post Processing", "JavaScript", "ADK", "LangChain"] is_sample: true
Prerequisites
This tutorial assumes that you have set up MCP Toolbox with a basic agent as described in the local quickstart.
This guide demonstrates how to implement these patterns in your Toolbox applications.
Implementation
{{< tabpane persist=header >}}
{{% tab header="ADK" text=true %}}
The following example demonstrates how to use the beforeToolCallback and afterToolCallback hooks in the ADK LlmAgent to implement pre and post processing logic.
{{< include "adk/agent.js" "js" >}}
You can also add model-level (beforeModelCallback, afterModelCallback) and agent-level (beforeAgentCallback, afterAgentCallback) hooks to intercept messages at different stages of the execution loop.
For more information, see the ADK Callbacks documentation.
{{% /tab %}}
{{% tab header="Langchain" text=true %}}
The following example demonstrates how to use ToolboxClient with LangChain's middleware to implement pre and post processing for tool calls.
{{< include "langchain/agent.js" "js" >}}
You can also use the wrapModelCall hook to intercept messages before and after model calls.
You can also use node-style hooks to intercept messages at the agent and model level.
See the LangChain Middleware documentation for details on these additional hook types.
{{% /tab %}}
{{< /tabpane >}}
Results
The output should look similar to the following.
{{< notice note >}}
The exact responses may vary due to the non-deterministic nature of LLMs and differences between orchestration frameworks.
{{< /notice >}}
AI: Booking Confirmed! You earned 500 Loyalty Points with this stay.
AI: Error: Maximum stay duration is 14 days.File: docs/en/documentation/configuration/pre-post-processing/python/_index.md
title: "Python: Pre & Post Processing" type: docs weight: 1 How to add pre- and post- processing to your Agents using Python. sample_filters: ["Pre & Post Processing", "Python", "ADK", "LangChain"] is_sample: true
Prerequisites
This tutorial assumes that you have set up MCP Toolbox with a basic agent as described in the local quickstart.
This guide demonstrates how to implement these patterns in your Toolbox applications.
Implementation
{{< tabpane persist=header >}}
{{% tab header="ADK" text=true %}}
The following example demonstrates how to use ToolboxToolset with ADK's pre and post processing hooks to implement pre and post processing for tool calls.
{{< include "adk/agent.py" "python">}}
You can also add model-level (before_model_callback, after_model_callback) and agent-level (before_agent_callback, after_agent_callback) hooks to intercept messages at different stages of the execution loop.
For more information, see the ADK Callbacks documentation.
{{% /tab %}}
{{% tab header="Langchain" text=true %}}
The following example demonstrates how to use ToolboxClient with LangChain's middleware to implement pre- and post- processing for tool calls.
{{< include "langchain/agent.py" "python" >}}
You can also add model-level (wrap_model) and agent-level (before_agent, after_agent) hooks to intercept messages at different stages of the execution loop. See the LangChain Middleware documentation for details on these additional hook types.
{{% /tab %}}
{{< /tabpane >}}
Results
The output should look similar to the following.
{{< notice note >}}
The exact responses may vary due to the non-deterministic nature of LLMs and differences between orchestration frameworks.
{{< /notice >}}
AI: Booking Confirmed! You earned 500 Loyalty Points with this stay.
AI: Error: Maximum stay duration is 14 days.File: docs/en/documentation/configuration/pre-post-processing/_index.md
title: "Pre- and Post- Processing" type: docs weight: 13 Intercept and modify interactions between the agent and its tools either before or after a tool is executed.
Pre- and post- processing allow developers to intercept and modify interactions between the agent and its tools or the user.
{{< notice note >}}
These capabilities are typically features of orchestration frameworks (like LangChain, LangGraph, or Agent Builder) rather than the Toolbox SDK itself. However, Toolbox tools are designed to fully leverage these framework capabilities to support robust, secure, and compliant agent architectures.
{{< /notice >}}
Types of Processing
Pre-processing
Pre-processing occurs before a tool is executed or an agent processes a message. Key types include:
- Input Sanitization & Redaction: Detecting and masking sensitive information (like PII) in user queries or tool arguments to prevent it from being logged or sent to unauthorized systems.
- Business Logic Validation: Verifying that the proposed action complies with business rules (e.g., ensuring a requested hotel stay does not exceed 14 days, or checking if a user has sufficient permission).
- Security Guardrails: Analyzing inputs for potential prompt injection attacks or malicious payloads.
Post-processing
Post-processing occurs after a tool has executed or the model has generated a response. Key types include:
- Response Enrichment: Injecting additional data into the tool output that wasn't part of the raw API response (e.g., calculating loyalty points earned based on the booking value).
- Output Formatting: Transforming raw data (like JSON or XML) into a more human-readable or model-friendly format to improve the agent's understanding.
- Compliance Auditing: Logging the final outcome of transactions, including the original request and the result, to a secure audit trail.
Processing Scopes
While processing logic can be applied at various levels (Agent, Model, Tool), this guide primarily focuses on Tool Level processing, which is most relevant for granular control over tool execution.
Tool Level (Primary Focus)
Wraps individual tool executions. This is best for logic specific to a single tool or a set of tools.
- Scope: Intercepts the raw inputs (arguments) to a tool and its outputs.
- Use Cases: Argument validation, output formatting, specific privacy rules for sensitive tools.
Other Levels
It is helpful to understand how tool-level processing differs from other scopes:
- Model Level: Intercepts individual calls to the LLM (prompts and responses). Unlike tool-level, this applies globally to all text sent/received, making it better for global PII redaction or token tracking.
- Agent Level: Wraps the high-level execution loop (e.g., a "turn" in the conversation). Unlike tool-level, this envelopes the entire turn (user input to final response), making it suitable for session management or end-to-end auditing.
Best Practices
Security & Guardrails
- Principle of Least Privilege: Ensure that tools run with the minimum necessary permissions. Middleware is an excellent place to enforce "read-only" modes or verify user identity before executing sensitive actions.
- Input Sanitization: Actively strip potential PII (like credit card numbers or raw emails) from tool arguments before logging them.
- Prompt Injection Defense: Use pre-processing hooks to scan user inputs for known jailbreak patterns or malicious directives before they reach the model or tools.
Observability & Debugging
- Structured Logging: Instead of simple print statements, use structured JSON logging with correlation IDs. This allows you to trace a single user request through multiple agent turns and tool calls.
- Logging for Testability: LLM responses are non-deterministic and may summarize away key details.
- Pattern: Add explicit logging markers in your post-processing middleware (e.g.,
logger.info("ACTION_SUCCESS: ")). - Benefit: Your integration tests can grep logs for these stable markers to verify tool success, rather than painfully parsing variable natural language responses.
- Pattern: Add explicit logging markers in your post-processing middleware (e.g.,
Performance & Cost Optimization
- Token Economy: Tools often return verbose JSON. Use post-processing to strip unnecessary fields or summarize large datasets before returning the result to the LLM's context window. This saves tokens and reduces latency.
- Caching: For read-heavy tools (like "search_knowledge_base"), implement caching middleware to return previous results for identical queries, saving both time and API costs.
Error Handling
- Graceful Degradation: If a tool fails (e.g., API timeout), catch the exception in middleware and return a structured error message to the LLM (e.g.,
Error: Database timeout, please try again). - Self-Correction: Well-formatted error messages often allow the LLM to understand why a call failed and retry it with corrected parameters automatically.
Samples
2. Official Technical Reference & Guides (googleapis/googleapis.github.io)
GAPIC Generators
Generated API Clients (GAPICs) are produced from declarative descriptions
of APIs. These API descriptions are written in the
Protocol Buffer language and
build on nearly 20 years of experience describing APIs within Google.
Our GAPIC generators are open source and are published in
github.com/googleapis. The original
gapic-generator produced API
clients in seven languages and continues to be the preferred generator for Java
and PHP.
Microgenerators
In 2018, we began developing a new set of generators, each written in the
language that it generates. Some of our language-specific GAPIC generators are
listed below:
- gapic-generator-python
- gapic-generator-go
- gapic-generator-java
- gapic-generator-ruby
- gapic-generator-kotlin
- gapic-generator-csharp
- gapic-generator-cpp
- gapic-generator-typescript
Testing GAPIC Generators
To verify GAPIC generator implementations, we test them with a common
gapic-showcase API that
"showcases" important GAPIC features.
Issues
For questions on a specific GAPIC generator, please file an issue on the
corresponding repository.