Skip to content

Commit ad11f6b

Browse files
Document v1beta1 CRD graduation and redirectUri default for v0.23.1
Bump apiVersion to toolhive.stacklok.dev/v1beta1 across 39 docs (all manifest examples except the "before" blocks in migrate-to-v1beta1), add a v0.23.0 section to the migration guide covering the storage version promotion and zero-downtime upgrade path, and document the new {resourceUrl}/oauth/callback default applied when redirectUri is empty on upstream OIDC/OAuth2 providers. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1 parent d6c311c commit ad11f6b

41 files changed

Lines changed: 298 additions & 179 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

docs/toolhive/guides-cli/build-containers.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ thv build --tag mcp-servers/git-server:stable uvx://mcp-server-git
101101
Use the built image in your Kubernetes manifests:
102102

103103
```yaml
104-
apiVersion: toolhive.stacklok.dev/v1alpha1
104+
apiVersion: toolhive.stacklok.dev/v1beta1
105105
kind: MCPServer
106106
metadata:
107107
name: git-server
@@ -263,7 +263,7 @@ you need to pre-build containers before deploying them.
263263
3. **Deploy to Kubernetes** using the pre-built image:
264264

265265
```yaml
266-
apiVersion: toolhive.stacklok.dev/v1alpha1
266+
apiVersion: toolhive.stacklok.dev/v1beta1
267267
kind: MCPServer
268268
metadata:
269269
name: git-server

docs/toolhive/guides-k8s/auth-k8s.mdx

Lines changed: 60 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ isolation.
107107
<TabItem value="inline" label="External IdP" default>
108108

109109
```yaml title="shared-oidc-config.yaml"
110-
apiVersion: toolhive.stacklok.dev/v1alpha1
110+
apiVersion: toolhive.stacklok.dev/v1beta1
111111
kind: MCPOIDCConfig
112112
metadata:
113113
name: production-oidc
@@ -127,7 +127,7 @@ spec:
127127
<TabItem value="k8s" label="Kubernetes service account">
128128
129129
```yaml title="k8s-oidc-config.yaml"
130-
apiVersion: toolhive.stacklok.dev/v1alpha1
130+
apiVersion: toolhive.stacklok.dev/v1beta1
131131
kind: MCPOIDCConfig
132132
metadata:
133133
name: k8s-sa-oidc
@@ -154,7 +154,7 @@ Use `oidcConfigRef` instead of inline `oidcConfig`. Each server must set a
154154
unique `audience` to prevent token replay across servers:
155155

156156
```yaml title="mcp-server-shared-oidc.yaml"
157-
apiVersion: toolhive.stacklok.dev/v1alpha1
157+
apiVersion: toolhive.stacklok.dev/v1beta1
158158
kind: MCPServer
159159
metadata:
160160
name: weather-server
@@ -217,7 +217,7 @@ settings, and an `MCPServer` resource that references it. The ToolHive proxy
217217
handles authentication before forwarding requests to the MCP server.
218218

219219
```yaml title="mcp-server-external-auth.yaml"
220-
apiVersion: toolhive.stacklok.dev/v1alpha1
220+
apiVersion: toolhive.stacklok.dev/v1beta1
221221
kind: MCPOIDCConfig
222222
metadata:
223223
name: external-oidc
@@ -229,7 +229,7 @@ spec:
229229
clientId: 'your-client-id'
230230
jwksUrl: 'https://your-oidc-issuer.com/path/to/jwks'
231231
---
232-
apiVersion: toolhive.stacklok.dev/v1alpha1
232+
apiVersion: toolhive.stacklok.dev/v1beta1
233233
kind: MCPServer
234234
metadata:
235235
name: weather-server-external
@@ -310,7 +310,7 @@ Create an `MCPOIDCConfig` resource for Kubernetes service account authentication
310310
and an `MCPServer` that references it:
311311

312312
```yaml title="mcp-server-k8s-auth.yaml"
313-
apiVersion: toolhive.stacklok.dev/v1alpha1
313+
apiVersion: toolhive.stacklok.dev/v1beta1
314314
kind: MCPOIDCConfig
315315
metadata:
316316
name: k8s-sa-oidc
@@ -321,7 +321,7 @@ spec:
321321
serviceAccount: 'mcp-client'
322322
namespace: 'client-apps'
323323
---
324-
apiVersion: toolhive.stacklok.dev/v1alpha1
324+
apiVersion: toolhive.stacklok.dev/v1beta1
325325
kind: MCPServer
326326
metadata:
327327
name: weather-server-k8s
@@ -499,7 +499,7 @@ Create an `MCPExternalAuthConfig` resource with the `embeddedAuthServer` type.
499499
This example configures an OIDC upstream provider (the most common case):
500500

501501
```yaml title="embedded-auth-config.yaml"
502-
apiVersion: toolhive.stacklok.dev/v1alpha1
502+
apiVersion: toolhive.stacklok.dev/v1beta1
503503
kind: MCPExternalAuthConfig
504504
metadata:
505505
name: embedded-auth-server
@@ -562,7 +562,7 @@ authorization server itself. The MCPOIDCConfig issuer must match the `issuer` in
562562
your `MCPExternalAuthConfig`.
563563

564564
```yaml title="mcp-server-embedded-auth.yaml"
565-
apiVersion: toolhive.stacklok.dev/v1alpha1
565+
apiVersion: toolhive.stacklok.dev/v1beta1
566566
kind: MCPOIDCConfig
567567
metadata:
568568
name: embedded-auth-oidc
@@ -573,7 +573,7 @@ spec:
573573
# This must match the embedded authorization server issuer url
574574
issuer: 'https://mcp.example.com'
575575
---
576-
apiVersion: toolhive.stacklok.dev/v1alpha1
576+
apiVersion: toolhive.stacklok.dev/v1beta1
577577
kind: MCPServer
578578
metadata:
579579
name: weather-server-embedded
@@ -690,7 +690,7 @@ for providers like GitHub that use OAuth 2.0 but don't implement the full OIDC
690690
specification.
691691

692692
```yaml title="embedded-auth-oauth2-config.yaml"
693-
apiVersion: toolhive.stacklok.dev/v1alpha1
693+
apiVersion: toolhive.stacklok.dev/v1beta1
694694
kind: MCPExternalAuthConfig
695695
metadata:
696696
name: embedded-auth-oauth2
@@ -788,6 +788,53 @@ refresh-token state), add `prompt: 'consent'` alongside `access_type: 'offline'`
788788
- Google then shows the consent screen on every login and re-issues a refresh
789789
token each time.
790790

791+
### Default callback URL for upstream providers
792+
793+
Starting in v0.23.0, the `redirectUri` field on an upstream provider's
794+
`oidcConfig` or `oauth2Config` is optional. When you omit it, the operator
795+
defaults it to `{resourceUrl}/oauth/callback`, where `resourceUrl` is the value
796+
from the MCPServer's `oidcConfigRef.resourceUrl` (the same URL the embedded
797+
authorization server advertises as its protected resource).
798+
799+
```yaml title="Upstream provider with defaulted redirect URI"
800+
# Assumes the MCPServer references this config with:
801+
# oidcConfigRef:
802+
# resourceUrl: https://mcp.example.com/mcp
803+
#
804+
# With no redirectUri set, the operator uses
805+
# https://mcp.example.com/mcp/oauth/callback
806+
upstreamProviders:
807+
- name: google
808+
type: oidc
809+
oidcConfig:
810+
issuerUrl: 'https://accounts.google.com'
811+
clientId: '<YOUR_GOOGLE_CLIENT_ID>'
812+
clientSecretRef:
813+
name: upstream-idp-secret
814+
key: client-secret
815+
```
816+
817+
Set `redirectUri` explicitly if your upstream provider is registered with a
818+
different callback path, or if your MCPServer does not set `resourceUrl` (in
819+
which case no default is applied):
820+
821+
```yaml title="Upstream provider with explicit redirect URI"
822+
upstreamProviders:
823+
- name: google
824+
type: oidc
825+
oidcConfig:
826+
issuerUrl: 'https://accounts.google.com'
827+
clientId: '<YOUR_GOOGLE_CLIENT_ID>'
828+
# highlight-next-line
829+
redirectUri: 'https://mcp.example.com/custom/callback'
830+
clientSecretRef:
831+
name: upstream-idp-secret
832+
key: client-secret
833+
```
834+
835+
Whichever value ends up in effect - defaulted or explicit - must exactly match
836+
the redirect URI registered with the upstream identity provider.
837+
791838
## Set up authorization
792839

793840
All authentication approaches can use the same authorization configuration using
@@ -836,7 +883,7 @@ kubectl apply -f authz-configmap.yaml
836883
Add the authorization configuration to your `MCPServer` resources:
837884

838885
```yaml title="mcp-server-with-authz.yaml"
839-
apiVersion: toolhive.stacklok.dev/v1alpha1
886+
apiVersion: toolhive.stacklok.dev/v1beta1
840887
kind: MCPOIDCConfig
841888
metadata:
842889
name: k8s-sa-authz-oidc
@@ -847,7 +894,7 @@ spec:
847894
serviceAccount: 'mcp-client'
848895
namespace: 'client-apps'
849896
---
850-
apiVersion: toolhive.stacklok.dev/v1alpha1
897+
apiVersion: toolhive.stacklok.dev/v1beta1
851898
kind: MCPServer
852899
metadata:
853900
name: weather-server-with-authz

docs/toolhive/guides-k8s/connect-clients.mdx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ First, ensure you have an MCP server deployed. This example uses the `fetch`
105105
server:
106106

107107
```yaml title="fetch-server.yaml"
108-
apiVersion: toolhive.stacklok.dev/v1alpha1
108+
apiVersion: toolhive.stacklok.dev/v1beta1
109109
kind: MCPServer
110110
metadata:
111111
name: fetch
@@ -235,7 +235,7 @@ First, in the MCPServer spec for each server, ensure the `resourceUrl` property
235235
is set to the full client-facing URL via `oidcConfigRef`:
236236

237237
```yaml title="fetch-server-oauth.yaml"
238-
apiVersion: toolhive.stacklok.dev/v1alpha1
238+
apiVersion: toolhive.stacklok.dev/v1beta1
239239
kind: MCPServer
240240
# ...
241241
spec:
@@ -493,7 +493,7 @@ First, in the MCPServer spec for each server, ensure the `resourceUrl` property
493493
is set to the full client-facing URL via `oidcConfigRef`:
494494

495495
```yaml title="fetch-server-oauth.yaml"
496-
apiVersion: toolhive.stacklok.dev/v1alpha1
496+
apiVersion: toolhive.stacklok.dev/v1beta1
497497
kind: MCPServer
498498
# ...
499499
spec:

docs/toolhive/guides-k8s/customize-tools.mdx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ descriptions. You reference the configuration from an MCPServer using the
2323
This example exposes only three tools on a server:
2424

2525
```yaml title="toolconfig-basic.yaml"
26-
apiVersion: toolhive.stacklok.dev/v1alpha1
26+
apiVersion: toolhive.stacklok.dev/v1beta1
2727
kind: MCPToolConfig
2828
metadata:
2929
name: basic-tool-filter
@@ -51,7 +51,7 @@ scopes (for example, separate GitHub orgs, repos, or environments). Renaming
5151
tools makes intent obvious and helps prevent mistakes.
5252

5353
```yaml title="toolconfig-with-overrides.yaml"
54-
apiVersion: toolhive.stacklok.dev/v1alpha1
54+
apiVersion: toolhive.stacklok.dev/v1beta1
5555
kind: MCPToolConfig
5656
metadata:
5757
name: github-tools-config
@@ -112,7 +112,7 @@ resource.
112112
<TabItem value="mcpserver" label="MCPServer" default>
113113

114114
```yaml {10-11} title="mcpserver-with-toolconfig.yaml"
115-
apiVersion: toolhive.stacklok.dev/v1alpha1
115+
apiVersion: toolhive.stacklok.dev/v1beta1
116116
kind: MCPServer
117117
metadata:
118118
name: github
@@ -130,7 +130,7 @@ spec:
130130
<TabItem value="mcpremoteproxy" label="MCPRemoteProxy">
131131

132132
```yaml {10-11} title="mcpremoteproxy-with-toolconfig.yaml"
133-
apiVersion: toolhive.stacklok.dev/v1alpha1
133+
apiVersion: toolhive.stacklok.dev/v1beta1
134134
kind: MCPRemoteProxy
135135
metadata:
136136
name: github
@@ -161,7 +161,7 @@ Run the GitHub MCP twice, once per organization, and rename tools so intent is
161161
clear to clients.
162162

163163
```yaml title="github-org-scoped-tools.yaml"
164-
apiVersion: toolhive.stacklok.dev/v1alpha1
164+
apiVersion: toolhive.stacklok.dev/v1beta1
165165
kind: MCPToolConfig
166166
metadata:
167167
name: github-acme-tools
@@ -176,7 +176,7 @@ spec:
176176
get_pull_request:
177177
name: github_acme_get_pr
178178
---
179-
apiVersion: toolhive.stacklok.dev/v1alpha1
179+
apiVersion: toolhive.stacklok.dev/v1beta1
180180
kind: MCPToolConfig
181181
metadata:
182182
name: github-foocorp-tools
@@ -191,7 +191,7 @@ spec:
191191
get_pull_request:
192192
name: github_foocorp_get_pr
193193
---
194-
apiVersion: toolhive.stacklok.dev/v1alpha1
194+
apiVersion: toolhive.stacklok.dev/v1beta1
195195
kind: MCPServer
196196
metadata:
197197
name: github-acme
@@ -204,7 +204,7 @@ spec:
204204
toolConfigRef:
205205
name: github-acme-tools
206206
---
207-
apiVersion: toolhive.stacklok.dev/v1alpha1
207+
apiVersion: toolhive.stacklok.dev/v1beta1
208208
kind: MCPServer
209209
metadata:
210210
name: github-foocorp

docs/toolhive/guides-k8s/logging.mdx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ your MCP server manifest:
8484
<TabItem value="mcpserver" label="MCPServer" default>
8585

8686
```yaml {11-12}
87-
apiVersion: toolhive.stacklok.dev/v1alpha1
87+
apiVersion: toolhive.stacklok.dev/v1beta1
8888
kind: MCPServer
8989
metadata:
9090
name: <SERVER_NAME>
@@ -102,7 +102,7 @@ spec:
102102
<TabItem value="mcpremoteproxy" label="MCPRemoteProxy">
103103
104104
```yaml {11-12}
105-
apiVersion: toolhive.stacklok.dev/v1alpha1
105+
apiVersion: toolhive.stacklok.dev/v1beta1
106106
kind: MCPRemoteProxy
107107
metadata:
108108
name: <SERVER_NAME>
@@ -120,7 +120,7 @@ spec:
120120
<TabItem value="virtualmcpserver" label="VirtualMCPServer">
121121
122122
```yaml {11-14}
123-
apiVersion: toolhive.stacklok.dev/v1alpha1
123+
apiVersion: toolhive.stacklok.dev/v1beta1
124124
kind: VirtualMCPServer
125125
metadata:
126126
name: <SERVER_NAME>

docs/toolhive/guides-k8s/mcp-server-entry.mdx

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ MCPServerEntry resources must be part of an MCPGroup. Create the group first if
7979
it doesn't exist:
8080

8181
```yaml title="my-group.yaml"
82-
apiVersion: toolhive.stacklok.dev/v1alpha1
82+
apiVersion: toolhive.stacklok.dev/v1beta1
8383
kind: MCPGroup
8484
metadata:
8585
name: my-group
@@ -91,7 +91,7 @@ spec:
9191
Then create a basic MCPServerEntry:
9292
9393
```yaml title="my-entry.yaml"
94-
apiVersion: toolhive.stacklok.dev/v1alpha1
94+
apiVersion: toolhive.stacklok.dev/v1beta1
9595
kind: MCPServerEntry
9696
metadata:
9797
name: my-remote-tool
@@ -142,7 +142,7 @@ exchange. The MCPExternalAuthConfig must exist in the same namespace as the
142142
MCPServerEntry.
143143

144144
```yaml title="auth-entry.yaml"
145-
apiVersion: toolhive.stacklok.dev/v1alpha1
145+
apiVersion: toolhive.stacklok.dev/v1beta1
146146
kind: MCPExternalAuthConfig
147147
metadata:
148148
name: my-auth-config
@@ -157,7 +157,7 @@ spec:
157157
key: client-secret
158158
audience: https://mcp.example.com
159159
---
160-
apiVersion: toolhive.stacklok.dev/v1alpha1
160+
apiVersion: toolhive.stacklok.dev/v1beta1
161161
kind: MCPServerEntry
162162
metadata:
163163
name: internal-tool
@@ -191,7 +191,7 @@ kubectl create configmap internal-ca-bundle \
191191
Then reference it in the MCPServerEntry:
192192

193193
```yaml title="tls-entry.yaml"
194-
apiVersion: toolhive.stacklok.dev/v1alpha1
194+
apiVersion: toolhive.stacklok.dev/v1beta1
195195
kind: MCPServerEntry
196196
metadata:
197197
name: internal-tool
@@ -216,7 +216,7 @@ keys, or other purposes. Use the `headerForward` field to inject headers into
216216
requests forwarded to the remote server.
217217

218218
```yaml title="header-entry.yaml"
219-
apiVersion: toolhive.stacklok.dev/v1alpha1
219+
apiVersion: toolhive.stacklok.dev/v1beta1
220220
kind: MCPServerEntry
221221
metadata:
222222
name: my-remote-tool
@@ -246,7 +246,7 @@ it must already exist or be created separately:
246246
```yaml title="complete-entry.yaml"
247247
---
248248
# 1. Create the MCPGroup
249-
apiVersion: toolhive.stacklok.dev/v1alpha1
249+
apiVersion: toolhive.stacklok.dev/v1beta1
250250
kind: MCPGroup
251251
metadata:
252252
name: engineering-tools
@@ -256,7 +256,7 @@ spec:
256256

257257
---
258258
# 2. Create authentication config for token exchange
259-
apiVersion: toolhive.stacklok.dev/v1alpha1
259+
apiVersion: toolhive.stacklok.dev/v1beta1
260260
kind: MCPExternalAuthConfig
261261
metadata:
262262
name: remote-auth
@@ -273,7 +273,7 @@ spec:
273273

274274
---
275275
# 3. Create the MCPServerEntry
276-
apiVersion: toolhive.stacklok.dev/v1alpha1
276+
apiVersion: toolhive.stacklok.dev/v1beta1
277277
kind: MCPServerEntry
278278
metadata:
279279
name: partner-tools

0 commit comments

Comments
 (0)