zuplo 6.70.53 → 6.70.55
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/mcp-gateway/auth/configuring-auth0.mdx +216 -0
- package/docs/mcp-gateway/auth/configuring-clerk.mdx +153 -0
- package/docs/mcp-gateway/auth/configuring-cognito.mdx +128 -0
- package/docs/mcp-gateway/auth/configuring-entra.mdx +134 -0
- package/docs/mcp-gateway/auth/configuring-generic-oidc.mdx +242 -0
- package/docs/mcp-gateway/auth/configuring-google.mdx +117 -0
- package/docs/mcp-gateway/auth/configuring-keycloak.mdx +125 -0
- package/docs/mcp-gateway/auth/configuring-logto.mdx +116 -0
- package/docs/mcp-gateway/auth/configuring-okta.mdx +199 -0
- package/docs/mcp-gateway/auth/configuring-onelogin.mdx +122 -0
- package/docs/mcp-gateway/auth/configuring-ping.mdx +157 -0
- package/docs/mcp-gateway/auth/configuring-workos.mdx +117 -0
- package/docs/mcp-gateway/auth/manual-oauth-testing.mdx +528 -0
- package/docs/mcp-gateway/auth/overview.mdx +314 -0
- package/docs/mcp-gateway/auth/upstream-oauth.mdx +221 -0
- package/docs/mcp-gateway/capability-filtering.mdx +162 -0
- package/docs/mcp-gateway/code-config/compatibility-dates.mdx +33 -0
- package/docs/mcp-gateway/code-config/local-development.mdx +198 -0
- package/docs/mcp-gateway/code-config/mcp-proxy-handler.mdx +186 -0
- package/docs/mcp-gateway/code-config/multi-upstream.mdx +293 -0
- package/docs/mcp-gateway/code-config/overview.mdx +210 -0
- package/docs/mcp-gateway/connect-clients/chatgpt.mdx +127 -0
- package/docs/mcp-gateway/connect-clients/claude-code.mdx +184 -0
- package/docs/mcp-gateway/connect-clients/claude-desktop.mdx +160 -0
- package/docs/mcp-gateway/connect-clients/cursor.mdx +100 -0
- package/docs/mcp-gateway/connect-clients/other-clients.mdx +207 -0
- package/docs/mcp-gateway/connect-clients/overview.mdx +137 -0
- package/docs/mcp-gateway/connect-clients/vs-code.mdx +128 -0
- package/docs/mcp-gateway/how-it-works.mdx +266 -0
- package/docs/mcp-gateway/how-to/connect-upstream-oauth.mdx +268 -0
- package/docs/mcp-gateway/how-to/curate-tools.mdx +278 -0
- package/docs/mcp-gateway/introduction.mdx +151 -0
- package/docs/mcp-gateway/observability/analytics.mdx +191 -0
- package/docs/mcp-gateway/observability/logging.mdx +191 -0
- package/docs/mcp-gateway/quickstart.mdx +266 -0
- package/docs/mcp-gateway/reference.mdx +148 -0
- package/docs/mcp-gateway/test-clients.mdx +130 -0
- package/docs/mcp-gateway/troubleshooting.mdx +228 -0
- package/docs/mcp-server/introduction.mdx +10 -0
- package/docs/mcp-server/openai-apps-sdk.mdx +12 -0
- package/docs/policies/_index.md +14 -0
- package/docs/policies/akamai-ai-firewall/schema.json +1 -0
- package/docs/policies/akamai-firewall-for-ai-inbound/schema.json +1 -0
- package/docs/policies/akamai-firewall-for-ai-outbound/schema.json +1 -0
- package/docs/policies/amberflo-metering-inbound/schema.json +1 -0
- package/docs/policies/api-key-inbound/schema.json +1 -0
- package/docs/policies/audit-log-inbound/schema.json +1 -0
- package/docs/policies/auth0-jwt-auth-inbound/schema.json +1 -0
- package/docs/policies/authzen-inbound/schema.json +1 -0
- package/docs/policies/axiomatics-authz-inbound/schema.json +1 -0
- package/docs/policies/basic-auth-inbound/schema.json +1 -0
- package/docs/policies/bot-detection-inbound/schema.json +1 -0
- package/docs/policies/brownout-inbound/schema.json +1 -0
- package/docs/policies/caching-inbound/schema.json +1 -0
- package/docs/policies/change-method-inbound/schema.json +1 -0
- package/docs/policies/clear-headers-inbound/schema.json +1 -0
- package/docs/policies/clear-headers-outbound/schema.json +1 -0
- package/docs/policies/clerk-jwt-auth-inbound/schema.json +1 -0
- package/docs/policies/cognito-jwt-auth-inbound/schema.json +1 -0
- package/docs/policies/comet-opik-tracing-inbound/schema.json +1 -0
- package/docs/policies/complex-rate-limit-inbound/schema.json +1 -0
- package/docs/policies/composite-inbound/schema.json +1 -0
- package/docs/policies/composite-outbound/schema.json +1 -0
- package/docs/policies/curity-phantom-token-inbound/schema.json +1 -0
- package/docs/policies/firebase-jwt-inbound/schema.json +1 -0
- package/docs/policies/formdata-to-json-inbound/schema.json +1 -0
- package/docs/policies/galileo-tracing-inbound/schema.json +1 -0
- package/docs/policies/geo-filter-inbound/schema.json +1 -0
- package/docs/policies/graphql-complexity-limit-inbound/schema.json +1 -0
- package/docs/policies/graphql-disable-introspection-inbound/schema.json +1 -0
- package/docs/policies/graphql-introspection-filter-outbound/schema.json +1 -0
- package/docs/policies/http-deprecation-outbound/schema.json +1 -0
- package/docs/policies/jwt-scopes-inbound/schema.json +1 -0
- package/docs/policies/ldap-auth-inbound/schema.json +1 -0
- package/docs/policies/mcp-auth0-oauth-inbound/doc.md +54 -0
- package/docs/policies/mcp-auth0-oauth-inbound/intro.md +7 -0
- package/docs/policies/mcp-auth0-oauth-inbound/schema.json +135 -0
- package/docs/policies/mcp-capability-filter-inbound/doc.md +58 -0
- package/docs/policies/mcp-capability-filter-inbound/intro.md +9 -0
- package/docs/policies/mcp-capability-filter-inbound/schema.json +212 -0
- package/docs/policies/mcp-clerk-oauth-inbound/doc.md +34 -0
- package/docs/policies/mcp-clerk-oauth-inbound/intro.md +1 -0
- package/docs/policies/mcp-clerk-oauth-inbound/schema.json +134 -0
- package/docs/policies/mcp-cognito-oauth-inbound/doc.md +52 -0
- package/docs/policies/mcp-cognito-oauth-inbound/intro.md +7 -0
- package/docs/policies/mcp-cognito-oauth-inbound/schema.json +152 -0
- package/docs/policies/mcp-entra-oauth-inbound/doc.md +51 -0
- package/docs/policies/mcp-entra-oauth-inbound/intro.md +6 -0
- package/docs/policies/mcp-entra-oauth-inbound/schema.json +131 -0
- package/docs/policies/mcp-google-oauth-inbound/doc.md +52 -0
- package/docs/policies/mcp-google-oauth-inbound/intro.md +6 -0
- package/docs/policies/mcp-google-oauth-inbound/schema.json +125 -0
- package/docs/policies/mcp-keycloak-oauth-inbound/doc.md +43 -0
- package/docs/policies/mcp-keycloak-oauth-inbound/intro.md +2 -0
- package/docs/policies/mcp-keycloak-oauth-inbound/schema.json +140 -0
- package/docs/policies/mcp-logto-oauth-inbound/doc.md +52 -0
- package/docs/policies/mcp-logto-oauth-inbound/intro.md +6 -0
- package/docs/policies/mcp-logto-oauth-inbound/schema.json +131 -0
- package/docs/policies/mcp-oauth-inbound/doc.md +70 -0
- package/docs/policies/mcp-oauth-inbound/intro.md +11 -0
- package/docs/policies/mcp-oauth-inbound/schema.json +177 -0
- package/docs/policies/mcp-okta-oauth-inbound/doc.md +61 -0
- package/docs/policies/mcp-okta-oauth-inbound/intro.md +7 -0
- package/docs/policies/mcp-okta-oauth-inbound/schema.json +137 -0
- package/docs/policies/mcp-onelogin-oauth-inbound/doc.md +50 -0
- package/docs/policies/mcp-onelogin-oauth-inbound/intro.md +6 -0
- package/docs/policies/mcp-onelogin-oauth-inbound/schema.json +131 -0
- package/docs/policies/mcp-ping-oauth-inbound/doc.md +80 -0
- package/docs/policies/mcp-ping-oauth-inbound/intro.md +7 -0
- package/docs/policies/mcp-ping-oauth-inbound/schema.json +151 -0
- package/docs/policies/mcp-token-exchange-inbound/doc.md +135 -0
- package/docs/policies/mcp-token-exchange-inbound/intro.md +6 -0
- package/docs/policies/mcp-token-exchange-inbound/schema.json +134 -0
- package/docs/policies/mcp-workos-oauth-inbound/doc.md +50 -0
- package/docs/policies/mcp-workos-oauth-inbound/intro.md +6 -0
- package/docs/policies/mcp-workos-oauth-inbound/schema.json +125 -0
- package/docs/policies/mock-api-inbound/schema.json +1 -0
- package/docs/policies/moesif-inbound/schema.json +1 -0
- package/docs/policies/monetization-inbound/schema.json +1 -0
- package/docs/policies/mtls-auth-inbound/schema.json +1 -0
- package/docs/policies/okta-fga-authz-inbound/schema.json +1 -0
- package/docs/policies/okta-jwt-auth-inbound/schema.json +1 -0
- package/docs/policies/open-id-jwt-auth-inbound/schema.json +1 -0
- package/docs/policies/openfga-authz-inbound/schema.json +1 -0
- package/docs/policies/openmeter-inbound/schema.json +1 -0
- package/docs/policies/prompt-injection-outbound/schema.json +1 -0
- package/docs/policies/propel-auth-jwt-inbound/schema.json +1 -0
- package/docs/policies/query-param-to-header-inbound/schema.json +1 -0
- package/docs/policies/quota-inbound/schema.json +1 -0
- package/docs/policies/rate-limit-inbound/schema.json +1 -0
- package/docs/policies/readme-metrics-inbound/schema.json +1 -0
- package/docs/policies/remove-headers-inbound/schema.json +1 -0
- package/docs/policies/remove-headers-outbound/schema.json +1 -0
- package/docs/policies/remove-query-params-inbound/schema.json +1 -0
- package/docs/policies/replace-string-outbound/schema.json +1 -0
- package/docs/policies/request-size-limit-inbound/schema.json +1 -0
- package/docs/policies/request-validation-inbound/schema.json +1 -0
- package/docs/policies/require-origin-inbound/schema.json +1 -0
- package/docs/policies/secret-masking-outbound/schema.json +1 -0
- package/docs/policies/semantic-cache-inbound/schema.json +1 -0
- package/docs/policies/set-body-inbound/schema.json +1 -0
- package/docs/policies/set-headers-inbound/schema.json +1 -0
- package/docs/policies/set-headers-outbound/schema.json +1 -0
- package/docs/policies/set-query-params-inbound/schema.json +1 -0
- package/docs/policies/set-status-outbound/schema.json +1 -0
- package/docs/policies/set-upstream-api-key-inbound/schema.json +1 -0
- package/docs/policies/sleep-inbound/schema.json +1 -0
- package/docs/policies/stripe-webhook-verification-inbound/schema.json +1 -0
- package/docs/policies/supabase-jwt-auth-inbound/schema.json +1 -0
- package/docs/policies/upstream-azure-ad-service-auth-inbound/schema.json +1 -0
- package/docs/policies/upstream-firebase-admin-auth-inbound/schema.json +1 -0
- package/docs/policies/upstream-firebase-user-auth-inbound/schema.json +1 -0
- package/docs/policies/upstream-gcp-federated-auth-inbound/schema.json +1 -0
- package/docs/policies/upstream-gcp-jwt-inbound/schema.json +1 -0
- package/docs/policies/upstream-gcp-service-auth-inbound/schema.json +1 -0
- package/docs/policies/upstream-zuplo-jwt-auth-inbound/schema.json +1 -0
- package/docs/policies/validate-json-schema-inbound/schema.json +1 -0
- package/docs/policies/web-bot-auth-inbound/schema.json +1 -0
- package/docs/policies/xml-to-json-outbound/schema.json +1 -0
- package/package.json +4 -4
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Configuring Okta"
|
|
3
|
+
sidebar_label: "Okta"
|
|
4
|
+
description:
|
|
5
|
+
Configure Okta to back the MCP Gateway's downstream OAuth using the
|
|
6
|
+
mcp-okta-oauth-inbound policy. Covers Okta application setup and wiring the
|
|
7
|
+
policy in your gateway project.
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
The MCP Gateway can use Okta as the identity provider behind its downstream
|
|
11
|
+
OAuth flow. The `mcp-okta-oauth-inbound` policy is an Okta-friendly wrapper
|
|
12
|
+
around the generic `mcp-oauth-inbound` policy: provide your Okta domain, a
|
|
13
|
+
client ID, and a client secret, and the policy derives the OIDC issuer, JWKS
|
|
14
|
+
URL, and authorize and token URLs for you.
|
|
15
|
+
|
|
16
|
+
This guide walks through the Okta admin console setup, then wires the policy
|
|
17
|
+
into a gateway project. Read the [authentication overview](./overview.mdx) first
|
|
18
|
+
for the two-layer model and the role each policy plays.
|
|
19
|
+
|
|
20
|
+
The wrapper supports both Okta's **org authorization server** (the default) and
|
|
21
|
+
**custom authorization servers**. Custom authorization servers give you control
|
|
22
|
+
over scopes and audiences; the org server is fine for the gateway's
|
|
23
|
+
identity-only use of Okta.
|
|
24
|
+
|
|
25
|
+
## Set up Okta
|
|
26
|
+
|
|
27
|
+
The MCP Gateway acts as an OAuth 2.1 authorization server in front of Okta. Okta
|
|
28
|
+
handles browser login and identity; the gateway issues its own access tokens
|
|
29
|
+
that bind to MCP routes. The Okta application you create represents the
|
|
30
|
+
**gateway's identity** against Okta, not the MCP client.
|
|
31
|
+
|
|
32
|
+
### Create an OIDC application
|
|
33
|
+
|
|
34
|
+
1. In the Okta Admin Console, open **Applications → Applications** and click
|
|
35
|
+
**Create App Integration**.
|
|
36
|
+
2. Choose **OIDC - OpenID Connect** as the sign-in method and **Web
|
|
37
|
+
Application** as the application type. Click **Next**.
|
|
38
|
+
3. Give the integration a name (for example, `Zuplo MCP Gateway`).
|
|
39
|
+
4. Under **Grant types**, leave **Authorization Code** checked. The gateway does
|
|
40
|
+
not need refresh tokens from Okta — it uses Okta only for browser identity,
|
|
41
|
+
not as a long-running token source.
|
|
42
|
+
5. Set **Sign-in redirect URIs** to your gateway's
|
|
43
|
+
`https://<gateway-host>/oauth/callback`. Add
|
|
44
|
+
`http://localhost:9000/oauth/callback` for local development with
|
|
45
|
+
`zuplo dev`.
|
|
46
|
+
6. Under **Assignments**, restrict access to the groups or users who should be
|
|
47
|
+
able to authenticate against the gateway.
|
|
48
|
+
7. Click **Save**.
|
|
49
|
+
|
|
50
|
+
Note the **Client ID** and **Client Secret** from the application's **General**
|
|
51
|
+
tab. You'll wire these into the policy in the next section.
|
|
52
|
+
|
|
53
|
+
### Optional: pick a custom authorization server
|
|
54
|
+
|
|
55
|
+
By default the policy uses the Okta org authorization server, which is enough
|
|
56
|
+
for gateway browser identity. If you already operate a custom authorization
|
|
57
|
+
server, open **Security → API → Authorization Servers** in the Okta admin
|
|
58
|
+
console and note the server's **name** (such as `default` or `customer-portal`).
|
|
59
|
+
You'll pass that name as the `authorizationServerId` option.
|
|
60
|
+
|
|
61
|
+
## Wire the policy into the gateway
|
|
62
|
+
|
|
63
|
+
Add the policy to `config/policies.json`:
|
|
64
|
+
|
|
65
|
+
```json
|
|
66
|
+
{
|
|
67
|
+
"name": "okta-managed-oauth",
|
|
68
|
+
"policyType": "mcp-okta-oauth-inbound",
|
|
69
|
+
"handler": {
|
|
70
|
+
"module": "$import(@zuplo/runtime/mcp-gateway)",
|
|
71
|
+
"export": "McpOktaOAuthInboundPolicy",
|
|
72
|
+
"options": {
|
|
73
|
+
"oktaDomain": "$env(OKTA_DOMAIN)",
|
|
74
|
+
"clientId": "$env(OKTA_CLIENT_ID)",
|
|
75
|
+
"clientSecret": "$env(OKTA_CLIENT_SECRET)"
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
:::caution
|
|
82
|
+
|
|
83
|
+
`oktaDomain` is a **bare hostname** like `acme.okta.com` or
|
|
84
|
+
`acme.oktapreview.com`. Don't include `https://`, a trailing slash, or an
|
|
85
|
+
`/oauth2/...` path.
|
|
86
|
+
|
|
87
|
+
:::
|
|
88
|
+
|
|
89
|
+
Set the three environment variables in your project's environment configuration.
|
|
90
|
+
`OKTA_DOMAIN` goes in plain config; the secret values belong in the project
|
|
91
|
+
secret store.
|
|
92
|
+
|
|
93
|
+
To use a custom authorization server, add `authorizationServerId`:
|
|
94
|
+
|
|
95
|
+
```json
|
|
96
|
+
{
|
|
97
|
+
"options": {
|
|
98
|
+
"oktaDomain": "$env(OKTA_DOMAIN)",
|
|
99
|
+
"authorizationServerId": "default",
|
|
100
|
+
"clientId": "$env(OKTA_CLIENT_ID)",
|
|
101
|
+
"clientSecret": "$env(OKTA_CLIENT_SECRET)"
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Attach the policy to each MCP route in `config/routes.oas.json`:
|
|
107
|
+
|
|
108
|
+
```jsonc
|
|
109
|
+
{
|
|
110
|
+
"paths": {
|
|
111
|
+
"/mcp/linear-v1": {
|
|
112
|
+
"get,post": {
|
|
113
|
+
"operationId": "linear-mcp-server",
|
|
114
|
+
"x-zuplo-route": {
|
|
115
|
+
"corsPolicy": "none",
|
|
116
|
+
"handler": {
|
|
117
|
+
"module": "$import(@zuplo/runtime/mcp-gateway)",
|
|
118
|
+
"export": "McpProxyHandler",
|
|
119
|
+
"options": {
|
|
120
|
+
"rewritePattern": "https://mcp.linear.app/mcp",
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
"policies": {
|
|
124
|
+
"inbound": ["okta-managed-oauth", "mcp-token-exchange-linear"],
|
|
125
|
+
},
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
},
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Register the gateway plugin in `modules/zuplo.runtime.ts`:
|
|
134
|
+
|
|
135
|
+
```ts
|
|
136
|
+
import { RuntimeExtensions } from "@zuplo/runtime";
|
|
137
|
+
import { McpGatewayPlugin } from "@zuplo/runtime/mcp-gateway";
|
|
138
|
+
|
|
139
|
+
export function runtimeInit(runtime: RuntimeExtensions) {
|
|
140
|
+
runtime.addPlugin(new McpGatewayPlugin());
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
One MCP OAuth policy serves every MCP route in the project — attach the same
|
|
145
|
+
policy by name to each route.
|
|
146
|
+
|
|
147
|
+
## Full options reference
|
|
148
|
+
|
|
149
|
+
| Option | Required | Default | Notes |
|
|
150
|
+
| ----------------------------------------- | -------- | ---------------------- | ------------------------------------------------------------------------------------- |
|
|
151
|
+
| `oktaDomain` | yes | — | Bare hostname (`acme.okta.com`). No scheme. |
|
|
152
|
+
| `authorizationServerId` | no | unset (org server) | Name of an Okta custom authorization server, e.g. `default`. |
|
|
153
|
+
| `clientId` | yes | — | Okta application client ID. |
|
|
154
|
+
| `clientSecret` | yes | — | Okta application client secret. Use `$env(...)`. |
|
|
155
|
+
| `scope` | no | `openid profile email` | OIDC scopes requested during browser login. |
|
|
156
|
+
| `gateway.accessTokenTtlSeconds` | no | `900` | Gateway-issued access token lifetime. |
|
|
157
|
+
| `gateway.refreshTokenTtlSeconds` | no | long-lived | Gateway-issued refresh token lifetime. Override only if you need to shorten sessions. |
|
|
158
|
+
| `gateway.cimdEnabled` | no | `true` | Advertise CIMD support in AS metadata. |
|
|
159
|
+
| `browserLoginOverrides.sessionTtlSeconds` | no | `28800` | Browser session cookie lifetime (8 hours). |
|
|
160
|
+
| `browserLoginOverrides.stateTtlSeconds` | no | `900` | Browser-login state record lifetime. |
|
|
161
|
+
| `browserLoginOverrides.remoteTimeoutMs` | no | `10000` | Outbound timeout to Okta (token exchange, JWKS fetch). |
|
|
162
|
+
|
|
163
|
+
## Test the configuration
|
|
164
|
+
|
|
165
|
+
The fastest sanity check is to connect an MCP client:
|
|
166
|
+
|
|
167
|
+
1. Open Claude Desktop, Cursor, Claude Code, or another OAuth-aware MCP client.
|
|
168
|
+
2. Add a remote MCP server pointing at one of your `/mcp/{slug}` routes on the
|
|
169
|
+
gateway.
|
|
170
|
+
3. The client should redirect you to Okta's login page. After login, the
|
|
171
|
+
gateway's consent screen renders. Approve it.
|
|
172
|
+
4. The client receives an access token and can call `tools/list`.
|
|
173
|
+
|
|
174
|
+
If something fails partway through, walk the flow manually using the
|
|
175
|
+
[manual OAuth testing guide](./manual-oauth-testing.mdx) — it exercises every
|
|
176
|
+
endpoint with `curl` so you can see the raw responses.
|
|
177
|
+
|
|
178
|
+
## Common issues
|
|
179
|
+
|
|
180
|
+
- **"Invalid Okta domain" at boot.** `oktaDomain` includes a scheme prefix,
|
|
181
|
+
trailing slash, or path. Use `acme.okta.com`.
|
|
182
|
+
- **Browser login redirects but the callback fails.** The
|
|
183
|
+
`https://<gateway-host>/oauth/callback` URL isn't on the application's
|
|
184
|
+
**Sign-in redirect URIs** allow-list in Okta.
|
|
185
|
+
- **`invalid_audience` from the gateway's token endpoint.** The MCP client is
|
|
186
|
+
reusing a token bound to a different route. Each gateway-issued token binds to
|
|
187
|
+
one MCP route.
|
|
188
|
+
- **MCP client can't discover the AS.** Confirm the `mcp-okta-oauth-inbound`
|
|
189
|
+
policy is attached to the route in `routes.oas.json` and the
|
|
190
|
+
`McpGatewayPlugin` is registered in `modules/zuplo.runtime.ts`. The internal
|
|
191
|
+
OAuth endpoints register only when both are present.
|
|
192
|
+
|
|
193
|
+
## Related
|
|
194
|
+
|
|
195
|
+
- [Authentication overview](./overview.mdx)
|
|
196
|
+
- [Configuring Auth0](./configuring-auth0.mdx) — the most-used wrapper
|
|
197
|
+
- [Configuring a generic OIDC provider](./configuring-generic-oidc.mdx) — for
|
|
198
|
+
IdPs without a first-class wrapper.
|
|
199
|
+
- [Per-user OAuth to upstream MCP servers](./upstream-oauth.mdx)
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Configuring OneLogin"
|
|
3
|
+
sidebar_label: "OneLogin"
|
|
4
|
+
description:
|
|
5
|
+
Configure OneLogin to back the MCP Gateway's downstream OAuth using the
|
|
6
|
+
mcp-onelogin-oauth-inbound policy. Covers OIDC app setup and wiring the policy
|
|
7
|
+
in your gateway project.
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
The MCP Gateway can use OneLogin as the identity provider behind its downstream
|
|
11
|
+
OAuth flow. The `mcp-onelogin-oauth-inbound` policy is a OneLogin-friendly
|
|
12
|
+
wrapper around the generic `mcp-oauth-inbound` policy: provide your OneLogin
|
|
13
|
+
account subdomain, a client ID, and a client secret, and the policy derives the
|
|
14
|
+
OIDC v2 issuer, JWKS URL, and authorize and token URLs for you.
|
|
15
|
+
|
|
16
|
+
This guide walks through the OneLogin admin portal setup, then wires the policy
|
|
17
|
+
into a gateway project. Read the [authentication overview](./overview.mdx) first
|
|
18
|
+
for the two-layer OAuth model.
|
|
19
|
+
|
|
20
|
+
## Set up OneLogin
|
|
21
|
+
|
|
22
|
+
The MCP Gateway acts as an OAuth 2.1 authorization server in front of OneLogin.
|
|
23
|
+
OneLogin handles browser login; the gateway issues its own access tokens that
|
|
24
|
+
bind to MCP routes.
|
|
25
|
+
|
|
26
|
+
### Create an OIDC application
|
|
27
|
+
|
|
28
|
+
1. In the OneLogin admin portal, open **Applications → Applications** and click
|
|
29
|
+
**Add App**.
|
|
30
|
+
2. Search for **OpenID Connect (OIDC)** and pick the matching app.
|
|
31
|
+
3. Give the application a display name (for example, `Zuplo MCP Gateway`) and
|
|
32
|
+
click **Save**.
|
|
33
|
+
4. Open the application's **Configuration** tab.
|
|
34
|
+
5. Set **Redirect URIs** to `https://<gateway-host>/oauth/callback`. Add
|
|
35
|
+
`http://localhost:9000/oauth/callback` for local development.
|
|
36
|
+
6. Set **Login Url** to your gateway origin (`https://<gateway-host>`).
|
|
37
|
+
7. Save.
|
|
38
|
+
|
|
39
|
+
### Configure SSO settings
|
|
40
|
+
|
|
41
|
+
1. Open the application's **SSO** tab.
|
|
42
|
+
2. Set **Token Endpoint Authentication Method** to **POST**.
|
|
43
|
+
3. Note the **Client ID** and **Client Secret** shown on the page.
|
|
44
|
+
|
|
45
|
+
### Assign users
|
|
46
|
+
|
|
47
|
+
Under the application's **Access** tab, assign the roles or users that should be
|
|
48
|
+
able to authenticate through the gateway.
|
|
49
|
+
|
|
50
|
+
### Find your OneLogin subdomain
|
|
51
|
+
|
|
52
|
+
Your OneLogin subdomain is the prefix of your admin portal URL. If the portal is
|
|
53
|
+
at `https://acme.onelogin.com`, the subdomain is `acme`. The wrapper takes only
|
|
54
|
+
the subdomain — no `https://`, no `.onelogin.com`, no path.
|
|
55
|
+
|
|
56
|
+
## Wire the policy into the gateway
|
|
57
|
+
|
|
58
|
+
Add the policy to `config/policies.json`:
|
|
59
|
+
|
|
60
|
+
```json
|
|
61
|
+
{
|
|
62
|
+
"name": "onelogin-managed-oauth",
|
|
63
|
+
"policyType": "mcp-onelogin-oauth-inbound",
|
|
64
|
+
"handler": {
|
|
65
|
+
"module": "$import(@zuplo/runtime/mcp-gateway)",
|
|
66
|
+
"export": "McpOneLoginOAuthInboundPolicy",
|
|
67
|
+
"options": {
|
|
68
|
+
"oneLoginSubdomain": "$env(ONELOGIN_SUBDOMAIN)",
|
|
69
|
+
"clientId": "$env(ONELOGIN_CLIENT_ID)",
|
|
70
|
+
"clientSecret": "$env(ONELOGIN_CLIENT_SECRET)"
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Attach the policy to each MCP route in `config/routes.oas.json` and register the
|
|
77
|
+
gateway plugin in `modules/zuplo.runtime.ts` (see
|
|
78
|
+
[Configuring Auth0](./configuring-auth0.mdx#wire-the-policy-into-the-gateway)
|
|
79
|
+
for the route and plugin patterns — they're identical across all wrappers).
|
|
80
|
+
|
|
81
|
+
## What the wrapper derives
|
|
82
|
+
|
|
83
|
+
Given `oneLoginSubdomain: "acme"`:
|
|
84
|
+
|
|
85
|
+
| Generic field | Derived value |
|
|
86
|
+
| ----------------------- | ---------------------------------------- |
|
|
87
|
+
| `oidc.issuer` | `https://acme.onelogin.com/oidc/2` |
|
|
88
|
+
| `oidc.jwksUrl` | `https://acme.onelogin.com/oidc/2/certs` |
|
|
89
|
+
| `browserLogin.url` | `https://acme.onelogin.com/oidc/2/auth` |
|
|
90
|
+
| `browserLogin.tokenUrl` | `https://acme.onelogin.com/oidc/2/token` |
|
|
91
|
+
|
|
92
|
+
These endpoint shapes follow OneLogin's OIDC provider configuration document at
|
|
93
|
+
`https://{oneLoginSubdomain}.onelogin.com/oidc/2/.well-known/openid-configuration`.
|
|
94
|
+
|
|
95
|
+
## Test the configuration
|
|
96
|
+
|
|
97
|
+
The fastest sanity check is to connect an MCP client:
|
|
98
|
+
|
|
99
|
+
1. Open Claude Desktop, Cursor, Claude Code, or another OAuth-aware MCP client.
|
|
100
|
+
2. Add a remote MCP server pointing at one of your `/mcp/{slug}` routes.
|
|
101
|
+
3. The client should redirect you to the OneLogin sign-in page. After login, the
|
|
102
|
+
gateway's consent screen renders. Approve it.
|
|
103
|
+
4. The client receives an access token and can call `tools/list`.
|
|
104
|
+
|
|
105
|
+
If something fails partway through, walk the flow manually using the
|
|
106
|
+
[manual OAuth testing guide](./manual-oauth-testing.mdx) — it exercises every
|
|
107
|
+
endpoint with `curl` so you can see the raw responses.
|
|
108
|
+
|
|
109
|
+
## Common issues
|
|
110
|
+
|
|
111
|
+
- **`oneLoginSubdomain` rejected at boot.** The value includes `https://`,
|
|
112
|
+
`.onelogin.com`, or a trailing path. Pass only the subdomain (`acme`).
|
|
113
|
+
- **`invalid_request: redirect_uri`.** The redirect URI on the OIDC application
|
|
114
|
+
doesn't match `https://<gateway-host>/oauth/callback`.
|
|
115
|
+
- **`invalid_client` from the token endpoint.** **Token Endpoint Authentication
|
|
116
|
+
Method** isn't set to **POST** on the application's SSO tab.
|
|
117
|
+
|
|
118
|
+
## Related
|
|
119
|
+
|
|
120
|
+
- [Authentication overview](./overview.mdx)
|
|
121
|
+
- [Configuring a generic OIDC provider](./configuring-generic-oidc.mdx)
|
|
122
|
+
- [Per-user OAuth to upstream MCP servers](./upstream-oauth.mdx)
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Configuring PingOne"
|
|
3
|
+
sidebar_label: "PingOne"
|
|
4
|
+
description:
|
|
5
|
+
Configure PingOne to back the MCP Gateway's downstream OAuth using the
|
|
6
|
+
mcp-ping-oauth-inbound policy. Covers application setup and wiring the policy
|
|
7
|
+
in your gateway project.
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
The MCP Gateway can use PingOne as the identity provider behind its downstream
|
|
11
|
+
OAuth flow. The `mcp-ping-oauth-inbound` policy is a PingOne-friendly wrapper
|
|
12
|
+
around the generic `mcp-oauth-inbound` policy: provide a PingOne environment ID
|
|
13
|
+
(or a custom domain), a client ID, and a client secret, and the policy derives
|
|
14
|
+
the OIDC issuer, JWKS URL, and authorize and token URLs for you.
|
|
15
|
+
|
|
16
|
+
This guide walks through the PingOne admin console setup, then wires the policy
|
|
17
|
+
into a gateway project. Read the [authentication overview](./overview.mdx) first
|
|
18
|
+
for the two-layer OAuth model.
|
|
19
|
+
|
|
20
|
+
:::note
|
|
21
|
+
|
|
22
|
+
This policy is for **PingOne cloud**. For **PingFederate** deployments — which
|
|
23
|
+
can customize issuer hosts, issuer paths, and endpoint paths — use the generic
|
|
24
|
+
[`mcp-oauth-inbound` policy](./configuring-generic-oidc.mdx) instead.
|
|
25
|
+
|
|
26
|
+
:::
|
|
27
|
+
|
|
28
|
+
## Set up PingOne
|
|
29
|
+
|
|
30
|
+
The MCP Gateway acts as an OAuth 2.1 authorization server in front of PingOne.
|
|
31
|
+
PingOne handles browser login; the gateway issues its own access tokens that
|
|
32
|
+
bind to MCP routes.
|
|
33
|
+
|
|
34
|
+
### Create an OIDC application
|
|
35
|
+
|
|
36
|
+
1. In the PingOne admin console, switch to the environment the gateway should
|
|
37
|
+
use, then open **Applications → Applications**.
|
|
38
|
+
2. Click **+ Add Application**, name it (for example, `Zuplo MCP Gateway`),
|
|
39
|
+
choose **OIDC Web App** as the application type, and click **Save**.
|
|
40
|
+
3. Open the application's **Configuration** tab.
|
|
41
|
+
4. Set **Redirect URIs** to `https://<gateway-host>/oauth/callback`. Add
|
|
42
|
+
`http://localhost:9000/oauth/callback` for local development.
|
|
43
|
+
5. Set **Grant Types** to **Authorization Code**.
|
|
44
|
+
6. Save.
|
|
45
|
+
|
|
46
|
+
### Note the credentials
|
|
47
|
+
|
|
48
|
+
Open the application's **Profile** tab. Copy the **Client ID** and **Client
|
|
49
|
+
Secret**.
|
|
50
|
+
|
|
51
|
+
### Find your environment ID and region
|
|
52
|
+
|
|
53
|
+
Open **Settings → Environment** in the PingOne admin console. Copy the
|
|
54
|
+
**Environment ID** (a UUID like `11111111-1111-4111-8111-111111111111`). Note
|
|
55
|
+
the **Geography** of the environment — North America, Canada, Europe, Singapore,
|
|
56
|
+
Australia, or Asia-Pacific. You'll pass these to the policy.
|
|
57
|
+
|
|
58
|
+
### Optional: custom domain
|
|
59
|
+
|
|
60
|
+
If your PingOne environment uses a custom domain (configured under **Settings →
|
|
61
|
+
Domains**), copy the bare host (such as `login.example.com`) and use it instead
|
|
62
|
+
of `environmentId` + `region`. The wrapper switches to the custom-domain
|
|
63
|
+
endpoint shape when `customDomain` is set.
|
|
64
|
+
|
|
65
|
+
## Wire the policy into the gateway
|
|
66
|
+
|
|
67
|
+
Add the policy to `config/policies.json`:
|
|
68
|
+
|
|
69
|
+
```json
|
|
70
|
+
{
|
|
71
|
+
"name": "ping-managed-oauth",
|
|
72
|
+
"policyType": "mcp-ping-oauth-inbound",
|
|
73
|
+
"handler": {
|
|
74
|
+
"module": "$import(@zuplo/runtime/mcp-gateway)",
|
|
75
|
+
"export": "McpPingOAuthInboundPolicy",
|
|
76
|
+
"options": {
|
|
77
|
+
"environmentId": "$env(PING_ENVIRONMENT_ID)",
|
|
78
|
+
"region": "north-america",
|
|
79
|
+
"clientId": "$env(PING_CLIENT_ID)",
|
|
80
|
+
"clientSecret": "$env(PING_CLIENT_SECRET)"
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
For a custom domain:
|
|
87
|
+
|
|
88
|
+
```json
|
|
89
|
+
{
|
|
90
|
+
"options": {
|
|
91
|
+
"customDomain": "$env(PING_CUSTOM_DOMAIN)",
|
|
92
|
+
"clientId": "$env(PING_CLIENT_ID)",
|
|
93
|
+
"clientSecret": "$env(PING_CLIENT_SECRET)"
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Attach the policy to each MCP route in `config/routes.oas.json` and register the
|
|
99
|
+
gateway plugin in `modules/zuplo.runtime.ts` (see
|
|
100
|
+
[Configuring Auth0](./configuring-auth0.mdx#wire-the-policy-into-the-gateway)
|
|
101
|
+
for the route and plugin patterns — they're identical across all wrappers).
|
|
102
|
+
|
|
103
|
+
## Available regions
|
|
104
|
+
|
|
105
|
+
| `region` value | PingOne auth host |
|
|
106
|
+
| --------------- | ---------------------------- |
|
|
107
|
+
| `north-america` | `auth.pingone.com` (default) |
|
|
108
|
+
| `canada` | `auth.pingone.ca` |
|
|
109
|
+
| `europe` | `auth.pingone.eu` |
|
|
110
|
+
| `singapore` | `auth.pingone.sg` |
|
|
111
|
+
| `australia` | `auth.pingone.com.au` |
|
|
112
|
+
| `asia-pacific` | `auth.pingone.asia` |
|
|
113
|
+
|
|
114
|
+
## What the wrapper derives
|
|
115
|
+
|
|
116
|
+
For the default region (`north-america`) and environment ID `ENV_ID`:
|
|
117
|
+
|
|
118
|
+
| Generic field | Derived value |
|
|
119
|
+
| ----------------------- | ------------------------------------------------ |
|
|
120
|
+
| `oidc.issuer` | `https://auth.pingone.com/{ENV_ID}/as` |
|
|
121
|
+
| `oidc.jwksUrl` | `https://auth.pingone.com/{ENV_ID}/as/jwks` |
|
|
122
|
+
| `browserLogin.url` | `https://auth.pingone.com/{ENV_ID}/as/authorize` |
|
|
123
|
+
| `browserLogin.tokenUrl` | `https://auth.pingone.com/{ENV_ID}/as/token` |
|
|
124
|
+
|
|
125
|
+
With `customDomain` set, the host changes to your custom domain and the
|
|
126
|
+
`{environmentId}` segment is removed.
|
|
127
|
+
|
|
128
|
+
## Test the configuration
|
|
129
|
+
|
|
130
|
+
The fastest sanity check is to connect an MCP client:
|
|
131
|
+
|
|
132
|
+
1. Open Claude Desktop, Cursor, Claude Code, or another OAuth-aware MCP client.
|
|
133
|
+
2. Add a remote MCP server pointing at one of your `/mcp/{slug}` routes.
|
|
134
|
+
3. The client should redirect you to the PingOne sign-in page. After login, the
|
|
135
|
+
gateway's consent screen renders. Approve it.
|
|
136
|
+
4. The client receives an access token and can call `tools/list`.
|
|
137
|
+
|
|
138
|
+
If something fails partway through, walk the flow manually using the
|
|
139
|
+
[manual OAuth testing guide](./manual-oauth-testing.mdx) — it exercises every
|
|
140
|
+
endpoint with `curl` so you can see the raw responses.
|
|
141
|
+
|
|
142
|
+
## Common issues
|
|
143
|
+
|
|
144
|
+
- **`environmentId` rejected at boot.** The wrapper expects a UUID. Don't pass
|
|
145
|
+
the issuer URL, the auth domain, or the client ID.
|
|
146
|
+
- **Browser login lands on a PingOne error page.** The redirect URI on the
|
|
147
|
+
application doesn't match `https://<gateway-host>/oauth/callback`.
|
|
148
|
+
- **`invalid_client`.** The application is set to **Public** instead of
|
|
149
|
+
**Confidential**. Confidential is required so the gateway can authenticate
|
|
150
|
+
with the client secret.
|
|
151
|
+
|
|
152
|
+
## Related
|
|
153
|
+
|
|
154
|
+
- [Authentication overview](./overview.mdx)
|
|
155
|
+
- [Configuring a generic OIDC provider](./configuring-generic-oidc.mdx) — use
|
|
156
|
+
this for PingFederate.
|
|
157
|
+
- [Per-user OAuth to upstream MCP servers](./upstream-oauth.mdx)
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Configuring WorkOS"
|
|
3
|
+
sidebar_label: "WorkOS"
|
|
4
|
+
description:
|
|
5
|
+
Configure WorkOS to back the MCP Gateway's downstream OAuth using the
|
|
6
|
+
mcp-workos-oauth-inbound policy. Covers AuthKit setup and wiring the policy in
|
|
7
|
+
your gateway project.
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
The MCP Gateway can use [WorkOS](https://workos.com/) as the identity provider
|
|
11
|
+
behind its downstream OAuth flow. The `mcp-workos-oauth-inbound` policy is a
|
|
12
|
+
WorkOS-friendly wrapper around the generic `mcp-oauth-inbound` policy: provide a
|
|
13
|
+
WorkOS client ID and client secret and the policy derives the OIDC issuer, JWKS
|
|
14
|
+
URL, and authorize and token URLs from the client ID.
|
|
15
|
+
|
|
16
|
+
This guide walks through the WorkOS dashboard setup, then wires the policy into
|
|
17
|
+
a gateway project. Read the [authentication overview](./overview.mdx) first for
|
|
18
|
+
the two-layer OAuth model.
|
|
19
|
+
|
|
20
|
+
## Set up WorkOS
|
|
21
|
+
|
|
22
|
+
The MCP Gateway acts as an OAuth 2.1 authorization server in front of WorkOS
|
|
23
|
+
AuthKit. WorkOS handles browser login; the gateway issues its own access tokens
|
|
24
|
+
that bind to MCP routes.
|
|
25
|
+
|
|
26
|
+
### Configure AuthKit
|
|
27
|
+
|
|
28
|
+
1. In the WorkOS Dashboard, switch to the environment you want the gateway to
|
|
29
|
+
use, then open **Authentication → AuthKit**.
|
|
30
|
+
2. If AuthKit isn't enabled yet, complete the AuthKit setup flow first — enable
|
|
31
|
+
email and password sign-in or any social connections your users need.
|
|
32
|
+
|
|
33
|
+
### Add the redirect URI
|
|
34
|
+
|
|
35
|
+
1. Open **Redirects** in the WorkOS Dashboard.
|
|
36
|
+
2. Add `https://<gateway-host>/oauth/callback` as an allowed redirect URI. Add
|
|
37
|
+
`http://localhost:9000/oauth/callback` for local development with
|
|
38
|
+
`zuplo dev`.
|
|
39
|
+
3. Save.
|
|
40
|
+
|
|
41
|
+
### Note the API credentials
|
|
42
|
+
|
|
43
|
+
Open **API Keys** in the WorkOS Dashboard. Copy the **Client ID** and the **API
|
|
44
|
+
Key** (= client secret) for the environment you're using.
|
|
45
|
+
|
|
46
|
+
## Wire the policy into the gateway
|
|
47
|
+
|
|
48
|
+
Add the policy to `config/policies.json`:
|
|
49
|
+
|
|
50
|
+
```json
|
|
51
|
+
{
|
|
52
|
+
"name": "workos-managed-oauth",
|
|
53
|
+
"policyType": "mcp-workos-oauth-inbound",
|
|
54
|
+
"handler": {
|
|
55
|
+
"module": "$import(@zuplo/runtime/mcp-gateway)",
|
|
56
|
+
"export": "McpWorkosOAuthInboundPolicy",
|
|
57
|
+
"options": {
|
|
58
|
+
"clientId": "$env(WORKOS_CLIENT_ID)",
|
|
59
|
+
"clientSecret": "$env(WORKOS_CLIENT_SECRET)"
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Set the two environment variables in your project's environment configuration.
|
|
66
|
+
The secret values belong in the project secret store.
|
|
67
|
+
|
|
68
|
+
Attach the policy to each MCP route in `config/routes.oas.json` and register the
|
|
69
|
+
gateway plugin in `modules/zuplo.runtime.ts` (see
|
|
70
|
+
[Configuring Auth0](./configuring-auth0.mdx#wire-the-policy-into-the-gateway)
|
|
71
|
+
for the route and plugin patterns — they're identical across all wrappers).
|
|
72
|
+
|
|
73
|
+
## What the wrapper derives
|
|
74
|
+
|
|
75
|
+
WorkOS keys its OIDC issuer by the client ID. Given a `clientId` like
|
|
76
|
+
`client_01KC6057N3C66XJAXZ65YHAC72`, the wrapper derives:
|
|
77
|
+
|
|
78
|
+
| Generic field | Derived value |
|
|
79
|
+
| ----------------------- | ----------------------------------------------------- |
|
|
80
|
+
| `oidc.issuer` | `https://api.workos.com/user_management/{clientId}` |
|
|
81
|
+
| `oidc.jwksUrl` | `https://api.workos.com/sso/jwks/{clientId}` |
|
|
82
|
+
| `browserLogin.url` | `https://api.workos.com/user_management/authorize` |
|
|
83
|
+
| `browserLogin.tokenUrl` | `https://api.workos.com/user_management/authenticate` |
|
|
84
|
+
|
|
85
|
+
These endpoint shapes come from WorkOS OIDC discovery at
|
|
86
|
+
`https://api.workos.com/user_management/{clientId}/.well-known/openid-configuration`.
|
|
87
|
+
|
|
88
|
+
## Test the configuration
|
|
89
|
+
|
|
90
|
+
The fastest sanity check is to connect an MCP client:
|
|
91
|
+
|
|
92
|
+
1. Open Claude Desktop, Cursor, Claude Code, or another OAuth-aware MCP client.
|
|
93
|
+
2. Add a remote MCP server pointing at one of your `/mcp/{slug}` routes.
|
|
94
|
+
3. The client should redirect you to the WorkOS AuthKit sign-in page. After
|
|
95
|
+
login, the gateway's consent screen renders. Approve it.
|
|
96
|
+
4. The client receives an access token and can call `tools/list`.
|
|
97
|
+
|
|
98
|
+
If something fails partway through, walk the flow manually using the
|
|
99
|
+
[manual OAuth testing guide](./manual-oauth-testing.mdx) — it exercises every
|
|
100
|
+
endpoint with `curl` so you can see the raw responses.
|
|
101
|
+
|
|
102
|
+
## Common issues
|
|
103
|
+
|
|
104
|
+
- **`Invalid redirect URI`.** The redirect URI on **Redirects** in the WorkOS
|
|
105
|
+
Dashboard doesn't match `https://<gateway-host>/oauth/callback` exactly.
|
|
106
|
+
- **`invalid_client`.** The client secret value doesn't match. WorkOS shows the
|
|
107
|
+
secret only once after creation — regenerate it from **API Keys** if you've
|
|
108
|
+
lost it.
|
|
109
|
+
- **JWKS fetch fails.** The client ID doesn't match the API key's environment.
|
|
110
|
+
Make sure both `clientId` and `clientSecret` come from the same WorkOS
|
|
111
|
+
environment.
|
|
112
|
+
|
|
113
|
+
## Related
|
|
114
|
+
|
|
115
|
+
- [Authentication overview](./overview.mdx)
|
|
116
|
+
- [Configuring a generic OIDC provider](./configuring-generic-oidc.mdx)
|
|
117
|
+
- [Per-user OAuth to upstream MCP servers](./upstream-oauth.mdx)
|