Skip to content

Commit d9b0e51

Browse files
authored
Merge branch 'main' into prebuilt-and-banner
2 parents e7cd8ee + 68d5fac commit d9b0e51

File tree

24 files changed

+1204
-152
lines changed

24 files changed

+1204
-152
lines changed

UPGRADING.md

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
# Upgrading to MCP Toolbox for Databases v1.0.0
2+
3+
Welcome to the v1.0.0 release of the MCP Toolbox for Databases!
4+
5+
This release stabilizes our core APIs and standardizes our protocol alignments.
6+
As part of this milestone, we have introduced several breaking changes and
7+
deprecations that require updates to your configuration and code.
8+
9+
**📖 New Versioning Policy**
10+
We have officially published our [Versioning Policy](https://googleapis.github.io/genai-toolbox/dev/about/versioning/). Moving forward, we follow standard versioning conventions to classify updates:
11+
* **Major (vX.0.0):** Breaking changes requiring manual updates.
12+
* **Minor (v1.X.0):** New, backward-compatible features and deprecation notices.
13+
* **Patch (v1.0.X):** Backward-compatible bug fixes and security patches.
14+
15+
This guide outlines what has changed and the steps you need to take to upgrade.
16+
17+
## 🚨 Breaking Changes (Action Required)
18+
19+
### 1. Endpoint Transition: `/api` disabled by default
20+
The legacy `/api` endpoint for the native Toolbox protocol is now disabled by default. All official SDKs have been updated to use the `/mcp` endpoint, which aligns with the standard Model Context Protocol (MCP) specification.
21+
22+
If you still require the legacy `/api` endpoint, you must explicitly activate it using a new command-line flag.
23+
24+
* **Usage:** `./toolbox --enable-api`
25+
* **Migration:** You must update all custom implementations to use the `/mcp`
26+
endpoint exclusively, as the `/api` endpoint is now deprecated. If your workflow
27+
relied on a non-standard feature that is missing from the new implementation, please submit a
28+
feature request on our [GitHub Issues page](https://github.com/googleapis/genai-toolbox/issues).
29+
* **UI Dependency:** Until the UI is officially migrated, it still requires the API to function. You must run the toolbox with both flags: `./toolbox --ui --enable-api`.
30+
31+
### 2. Strict Tool Naming Validation (SEP986)
32+
Tool names are now strictly validated against [ModelContextProtocol SEP986 guidelines](https://github.com/alexhancock/modelcontextprotocol/blob/main/docs/specification/draft/server/tools.mdx#tool-names) prior to MCP initialization.
33+
* **Migration:** Ensure all your tool names **only** contain alphanumeric characters, hyphens (`-`), underscores (`_`), and periods (`.`). Any other special characters will cause initialization to fail.
34+
35+
### 3. Removed CLI Flags
36+
The legacy snake_case flag `--tools_file` has been completely removed.
37+
* **Migration:** Update your deployment scripts to use `--config` instead.
38+
39+
### 4. Singular `kind` Values in Configuration
40+
_(This step applies only if you are currently using the new flat format.)_
41+
42+
All primitive kind fields in configuration files have been updated to use singular nouns instead of plural. For example, `kind: sources` is now `kind: source`, and `kind: tools` is now `kind: tool`.
43+
44+
* **Migration:** Update your configuration files to use the singular form for all `kind`
45+
values. _(Note: If you transitioned to the flat format using the `./toolbox migrate` command, this step was handled automatically.)_
46+
47+
48+
### 5. Configuration Schema: `authSources` renamed
49+
The `authSources` field is no longer supported in configuration files.
50+
* **Migration:** Rename all instances of `authSources` to `authService` in your
51+
configuration files.
52+
53+
### 6. CloudSQL for SQL Server: `ipAddress` removed
54+
The `ipAddress` field for the CloudSQL for SQL Server source was redundant and has been removed.
55+
* **Migration:** Remove the `ipAddress` field from your CloudSQL for SQL Server configurations.
56+
57+
58+
## ⚠️ Deprecations & Modernization
59+
60+
### 1. Flat Configuration Format Introduced
61+
We have introduced a new, streamlined "flat" format for configuration files. While the older nested format is still supported for now, **all new features will only be added to the flat format.**
62+
63+
**Schema Restructuring (`kind` vs. `type`):**
64+
Along with the flat format, the configuration schema has been reorganized. The
65+
old `kind` field (which specified the specific primitive types, like
66+
`alloydb-postgres`) has been renamed to `type`. The `kind` field is now strictly
67+
used to declare the core primitive of the block (e.g., `source` or `tool`).
68+
69+
**Example of the new flat format:**
70+
71+
```yaml
72+
kind: source
73+
name: my-source
74+
type: alloydb-postgres
75+
project: my-project
76+
region: my-region
77+
instance: my-instance
78+
---
79+
kind: tool
80+
name: my-simple-tool
81+
type: postgres-execute-sql
82+
source: my-source
83+
description: this is a tool that executes the sql provided.
84+
```
85+
86+
**Migration:**
87+
88+
You can automatically migrate your existing nested configurations to the new flat format using the CLI. Run the following command:
89+
90+
```Bash
91+
./toolbox migrate --config <path-to-your-config>
92+
```
93+
_Note: You can also use the `--configs` or `--config-folder` flags with this command._
94+
95+
### 2. Deprecated CLI Flags
96+
The following CLI flags are deprecated and will be removed in a future release. Please update your scripts:
97+
98+
* `--tools-file` ➡️ Use `--config`
99+
* `--tools-files` ➡️ Use `--configs`
100+
* `--tools-folder` ➡️ Use `--config-folder`
101+
102+
## 💡 Other Notable Updates
103+
* **Enhanced Error Handling:** Errors are now strictly categorized between Agent Errors (allowing the LLM to self-correct) and Client/Server Errors (which signal a hard stop).
104+
105+
* **Telemetry Updates:** The /mcp endpoint telemetry has been revised to fully comply with the [OpenTelemetry semantic conventions for MCP](https://opentelemetry.io/docs/specs/semconv/gen-ai/mcp/).
106+
107+
* **MCP Authorization Support:** The Model Context Protocol's [authorization specification](https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization) is now fully supported.
108+
109+
* **Database Name Validation:** Removed the "required field" validation for the database name in CloudSQL for MySQL and generic MySQL sources.
110+
111+
* **Prebuilt Tools:** Toolsets have been resized for better performance.
112+
## 📚 Documentation Moved
113+
Our official documentation has a new home! Please update your bookmarks to [mcp-toolbox.dev](http://mcp-toolbox.dev).

cmd/internal/config.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727

2828
"github.com/goccy/go-yaml"
2929
"github.com/google/go-cmp/cmp"
30+
"github.com/googleapis/genai-toolbox/internal/auth/generic"
3031
"github.com/googleapis/genai-toolbox/internal/server"
3132
)
3233

@@ -309,6 +310,18 @@ func mergeConfigs(files ...Config) (Config, error) {
309310
return Config{}, fmt.Errorf("resource conflicts detected:\n - %s\n\nPlease ensure each source, authService, tool, toolset and prompt has a unique name across all files", strings.Join(conflicts, "\n - "))
310311
}
311312

313+
// Ensure only one authService has mcpEnabled = true
314+
var mcpEnabledAuthServers []string
315+
for name, authService := range merged.AuthServices {
316+
// Only generic type has McpEnabled right now
317+
if genericService, ok := authService.(generic.Config); ok && genericService.McpEnabled {
318+
mcpEnabledAuthServers = append(mcpEnabledAuthServers, name)
319+
}
320+
}
321+
if len(mcpEnabledAuthServers) > 1 {
322+
return Config{}, fmt.Errorf("multiple authServices with mcpEnabled=true detected: %s. Only one MCP authorization server is currently supported", strings.Join(mcpEnabledAuthServers, ", "))
323+
}
324+
312325
return merged, nil
313326
}
314327

cmd/internal/config_test.go

Lines changed: 68 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"testing"
2121

2222
"github.com/google/go-cmp/cmp"
23+
"github.com/googleapis/genai-toolbox/internal/auth/generic"
2324
"github.com/googleapis/genai-toolbox/internal/auth/google"
2425
"github.com/googleapis/genai-toolbox/internal/embeddingmodels/gemini"
2526
"github.com/googleapis/genai-toolbox/internal/prebuiltconfigs"
@@ -616,38 +617,48 @@ func TestParseConfig(t *testing.T) {
616617
type: google
617618
clientId: testing-id
618619
---
619-
kind: embeddingModel
620-
name: gemini-model
621-
type: gemini
622-
model: gemini-embedding-001
623-
apiKey: some-key
624-
dimension: 768
620+
kind: authService
621+
name: my-generic-auth
622+
type: generic
623+
audience: testings
624+
authorizationServer: https://testings
625+
mcpEnabled: true
626+
scopesRequired:
627+
- read:files
628+
- write:files
625629
---
626-
kind: tool
627-
name: example_tool
628-
type: postgres-sql
629-
source: my-pg-instance
630-
description: some description
631-
statement: |
632-
SELECT * FROM SQL_STATEMENT;
633-
parameters:
634-
- name: country
635-
type: string
636-
description: some description
630+
kind: embeddingModel
631+
name: gemini-model
632+
type: gemini
633+
model: gemini-embedding-001
634+
apiKey: some-key
635+
dimension: 768
637636
---
638-
kind: toolset
639-
name: example_toolset
640-
tools:
641-
- example_tool
637+
kind: tool
638+
name: example_tool
639+
type: postgres-sql
640+
source: my-pg-instance
641+
description: some description
642+
statement: |
643+
SELECT * FROM SQL_STATEMENT;
644+
parameters:
645+
- name: country
646+
type: string
647+
description: some description
642648
---
643-
kind: prompt
644-
name: code_review
645-
description: ask llm to analyze code quality
646-
messages:
647-
- content: "please review the following code for quality: {{.code}}"
648-
arguments:
649-
- name: code
650-
description: the code to review
649+
kind: toolset
650+
name: example_toolset
651+
tools:
652+
- example_tool
653+
---
654+
kind: prompt
655+
name: code_review
656+
description: ask llm to analyze code quality
657+
messages:
658+
- content: "please review the following code for quality: {{.code}}"
659+
arguments:
660+
- name: code
661+
description: the code to review
651662
`,
652663
wantConfig: Config{
653664
Sources: server.SourceConfigs{
@@ -669,6 +680,14 @@ func TestParseConfig(t *testing.T) {
669680
Type: google.AuthServiceType,
670681
ClientID: "testing-id",
671682
},
683+
"my-generic-auth": generic.Config{
684+
Name: "my-generic-auth",
685+
Type: generic.AuthServiceType,
686+
Audience: "testings",
687+
McpEnabled: true,
688+
AuthorizationServer: "https://testings",
689+
ScopesRequired: []string{"read:files", "write:files"},
690+
},
672691
},
673692
EmbeddingModels: server.EmbeddingModelConfigs{
674693
"gemini-model": gemini.Config{
@@ -2029,12 +2048,19 @@ func TestMergeConfigs(t *testing.T) {
20292048
Sources: server.SourceConfigs{"source1": httpsrc.Config{Name: "source1"}},
20302049
Tools: server.ToolConfigs{"tool2": http.Config{Name: "tool2"}},
20312050
}
2051+
fileMcp1 := Config{
2052+
AuthServices: server.AuthServiceConfigs{"generic1": generic.Config{Name: "generic1", McpEnabled: true}},
2053+
}
2054+
fileMcp2 := Config{
2055+
AuthServices: server.AuthServiceConfigs{"generic2": generic.Config{Name: "generic2", McpEnabled: true}},
2056+
}
20322057

20332058
testCases := []struct {
2034-
name string
2035-
files []Config
2036-
want Config
2037-
wantErr bool
2059+
name string
2060+
files []Config
2061+
want Config
2062+
wantErr bool
2063+
errString string
20382064
}{
20392065
{
20402066
name: "merge two distinct files",
@@ -2054,6 +2080,12 @@ func TestMergeConfigs(t *testing.T) {
20542080
files: []Config{file1, file2, fileWithConflicts},
20552081
wantErr: true,
20562082
},
2083+
{
2084+
name: "merge multiple mcp enabled generic",
2085+
files: []Config{fileMcp1, fileMcp2},
2086+
wantErr: true,
2087+
errString: "multiple authServices with mcpEnabled=true detected",
2088+
},
20572089
{
20582090
name: "merge single file",
20592091
files: []Config{file1},
@@ -2094,7 +2126,9 @@ func TestMergeConfigs(t *testing.T) {
20942126
if err == nil {
20952127
t.Fatal("expected an error for conflicting files but got none")
20962128
}
2097-
if !strings.Contains(err.Error(), "resource conflicts detected") {
2129+
if tc.errString != "" && !strings.Contains(err.Error(), tc.errString) {
2130+
t.Errorf("expected error %q, but got: %v", tc.errString, err)
2131+
} else if tc.errString == "" && !strings.Contains(err.Error(), "resource conflicts detected") {
20982132
t.Errorf("expected conflict error, but got: %v", err)
20992133
}
21002134
}

docs/en/documentation/configuration/authentication/_index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -304,4 +304,4 @@ func main() {
304304
}
305305
```
306306

307-
## Kinds of Auth Services
307+
## Types of Auth Services

docs/en/documentation/configuration/embedding-models/_index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,4 +103,4 @@ parameters:
103103
embeddedBy: gemini-model # refers to the name of a defined embedding model
104104
```
105105

106-
## Kinds of Embedding Models
106+
## Types of Embedding Models

docs/en/documentation/configuration/prompts/_index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,4 +78,4 @@ The workflow is as follows:
7878
5. **Response:** This completed prompt is then sent to the Gemini model, and the
7979
model's response is displayed back to you in the CLI.
8080

81-
## Kinds of prompts
81+
## Types of prompts

docs/en/documentation/configuration/sources/_index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,4 @@ to connect to the database and execute the tool.
3333
3434
## Available Sources
3535
36-
To see all supported sources and the specific tools they unlock, explore the full list of our [Integrations](../../../integrations/_index.md).
36+
To see all supported sources and the specific tools they unlock, explore the full list of our [Integrations](../../../integrations/_index.md).
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
---
2+
title: "Generic OIDC Auth"
3+
type: docs
4+
weight: 2
5+
description: >
6+
Use a Generic OpenID Connect (OIDC) provider for OAuth 2.0 flow and token
7+
lifecycle.
8+
---
9+
10+
## Getting Started
11+
12+
The Generic Auth Service allows you to integrate with any OpenID Connect (OIDC)
13+
compliant identity provider (IDP). It discovers the JWKS (JSON Web Key Set) URL
14+
either through the provider's `/.well-known/openid-configuration` endpoint or
15+
directly via the provided `authorizationServer`.
16+
17+
To configure this auth service, you need to provide the `audience` (typically
18+
your client ID or the intended audience for the token), the
19+
`authorizationServer` of your identity provider, and optionally a list of
20+
`scopesRequired` that must be present in the token's claims.
21+
22+
## Behavior
23+
24+
### Token Validation
25+
26+
When a request is received, the service will:
27+
28+
1. Extract the token from the `<name>_token` header (e.g.,
29+
`my-generic-auth_token`).
30+
2. Fetch the JWKS from the configured `authorizationServer` (caching it in the
31+
background) to verify the token's signature.
32+
3. Validate that the token is not expired and its signature is valid.
33+
4. Verify that the `aud` (audience) claim matches the configured `audience`.
34+
claim contains all required scopes.
35+
5. Return the validated claims to be used for [Authenticated
36+
Parameters][auth-params] or [Authorized Invocations][auth-invoke].
37+
38+
[auth-invoke]: ../tools/#authorized-invocations
39+
[auth-params]: ../tools/#authenticated-parameters
40+
41+
## Example
42+
43+
```yaml
44+
kind: authServices
45+
name: my-generic-auth
46+
type: generic
47+
audience: ${YOUR_OIDC_AUDIENCE}
48+
authorizationServer: https://your-idp.example.com
49+
mcpEnabled: false
50+
scopesRequired:
51+
- read
52+
- write
53+
```
54+
55+
{{< notice tip >}} Use environment variable replacement with the format
56+
${ENV_NAME} instead of hardcoding your secrets into the configuration file.
57+
{{< /notice >}}
58+
59+
## Reference
60+
61+
| **field** | **type** | **required** | **description** |
62+
| ------------------- | :------: | :----------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
63+
| type | string | true | Must be "generic". |
64+
| audience | string | true | The expected audience (`aud` claim) in the JWT token. This ensures the token was minted specifically for your application. |
65+
| 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. |
66+
| mcpEnabled | bool | false | Indicates if MCP endpoint authentication should be applied. Defaults to false. |
67+
| scopesRequired | []string | false | A list of required scopes that must be present in the token's `scope` claim to be considered valid. |

0 commit comments

Comments
 (0)