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.
Files changed (160) hide show
  1. package/docs/mcp-gateway/auth/configuring-auth0.mdx +216 -0
  2. package/docs/mcp-gateway/auth/configuring-clerk.mdx +153 -0
  3. package/docs/mcp-gateway/auth/configuring-cognito.mdx +128 -0
  4. package/docs/mcp-gateway/auth/configuring-entra.mdx +134 -0
  5. package/docs/mcp-gateway/auth/configuring-generic-oidc.mdx +242 -0
  6. package/docs/mcp-gateway/auth/configuring-google.mdx +117 -0
  7. package/docs/mcp-gateway/auth/configuring-keycloak.mdx +125 -0
  8. package/docs/mcp-gateway/auth/configuring-logto.mdx +116 -0
  9. package/docs/mcp-gateway/auth/configuring-okta.mdx +199 -0
  10. package/docs/mcp-gateway/auth/configuring-onelogin.mdx +122 -0
  11. package/docs/mcp-gateway/auth/configuring-ping.mdx +157 -0
  12. package/docs/mcp-gateway/auth/configuring-workos.mdx +117 -0
  13. package/docs/mcp-gateway/auth/manual-oauth-testing.mdx +528 -0
  14. package/docs/mcp-gateway/auth/overview.mdx +314 -0
  15. package/docs/mcp-gateway/auth/upstream-oauth.mdx +221 -0
  16. package/docs/mcp-gateway/capability-filtering.mdx +162 -0
  17. package/docs/mcp-gateway/code-config/compatibility-dates.mdx +33 -0
  18. package/docs/mcp-gateway/code-config/local-development.mdx +198 -0
  19. package/docs/mcp-gateway/code-config/mcp-proxy-handler.mdx +186 -0
  20. package/docs/mcp-gateway/code-config/multi-upstream.mdx +293 -0
  21. package/docs/mcp-gateway/code-config/overview.mdx +210 -0
  22. package/docs/mcp-gateway/connect-clients/chatgpt.mdx +127 -0
  23. package/docs/mcp-gateway/connect-clients/claude-code.mdx +184 -0
  24. package/docs/mcp-gateway/connect-clients/claude-desktop.mdx +160 -0
  25. package/docs/mcp-gateway/connect-clients/cursor.mdx +100 -0
  26. package/docs/mcp-gateway/connect-clients/other-clients.mdx +207 -0
  27. package/docs/mcp-gateway/connect-clients/overview.mdx +137 -0
  28. package/docs/mcp-gateway/connect-clients/vs-code.mdx +128 -0
  29. package/docs/mcp-gateway/how-it-works.mdx +266 -0
  30. package/docs/mcp-gateway/how-to/connect-upstream-oauth.mdx +268 -0
  31. package/docs/mcp-gateway/how-to/curate-tools.mdx +278 -0
  32. package/docs/mcp-gateway/introduction.mdx +151 -0
  33. package/docs/mcp-gateway/observability/analytics.mdx +191 -0
  34. package/docs/mcp-gateway/observability/logging.mdx +191 -0
  35. package/docs/mcp-gateway/quickstart.mdx +266 -0
  36. package/docs/mcp-gateway/reference.mdx +148 -0
  37. package/docs/mcp-gateway/test-clients.mdx +130 -0
  38. package/docs/mcp-gateway/troubleshooting.mdx +228 -0
  39. package/docs/mcp-server/introduction.mdx +10 -0
  40. package/docs/mcp-server/openai-apps-sdk.mdx +12 -0
  41. package/docs/policies/_index.md +14 -0
  42. package/docs/policies/akamai-ai-firewall/schema.json +1 -0
  43. package/docs/policies/akamai-firewall-for-ai-inbound/schema.json +1 -0
  44. package/docs/policies/akamai-firewall-for-ai-outbound/schema.json +1 -0
  45. package/docs/policies/amberflo-metering-inbound/schema.json +1 -0
  46. package/docs/policies/api-key-inbound/schema.json +1 -0
  47. package/docs/policies/audit-log-inbound/schema.json +1 -0
  48. package/docs/policies/auth0-jwt-auth-inbound/schema.json +1 -0
  49. package/docs/policies/authzen-inbound/schema.json +1 -0
  50. package/docs/policies/axiomatics-authz-inbound/schema.json +1 -0
  51. package/docs/policies/basic-auth-inbound/schema.json +1 -0
  52. package/docs/policies/bot-detection-inbound/schema.json +1 -0
  53. package/docs/policies/brownout-inbound/schema.json +1 -0
  54. package/docs/policies/caching-inbound/schema.json +1 -0
  55. package/docs/policies/change-method-inbound/schema.json +1 -0
  56. package/docs/policies/clear-headers-inbound/schema.json +1 -0
  57. package/docs/policies/clear-headers-outbound/schema.json +1 -0
  58. package/docs/policies/clerk-jwt-auth-inbound/schema.json +1 -0
  59. package/docs/policies/cognito-jwt-auth-inbound/schema.json +1 -0
  60. package/docs/policies/comet-opik-tracing-inbound/schema.json +1 -0
  61. package/docs/policies/complex-rate-limit-inbound/schema.json +1 -0
  62. package/docs/policies/composite-inbound/schema.json +1 -0
  63. package/docs/policies/composite-outbound/schema.json +1 -0
  64. package/docs/policies/curity-phantom-token-inbound/schema.json +1 -0
  65. package/docs/policies/firebase-jwt-inbound/schema.json +1 -0
  66. package/docs/policies/formdata-to-json-inbound/schema.json +1 -0
  67. package/docs/policies/galileo-tracing-inbound/schema.json +1 -0
  68. package/docs/policies/geo-filter-inbound/schema.json +1 -0
  69. package/docs/policies/graphql-complexity-limit-inbound/schema.json +1 -0
  70. package/docs/policies/graphql-disable-introspection-inbound/schema.json +1 -0
  71. package/docs/policies/graphql-introspection-filter-outbound/schema.json +1 -0
  72. package/docs/policies/http-deprecation-outbound/schema.json +1 -0
  73. package/docs/policies/jwt-scopes-inbound/schema.json +1 -0
  74. package/docs/policies/ldap-auth-inbound/schema.json +1 -0
  75. package/docs/policies/mcp-auth0-oauth-inbound/doc.md +54 -0
  76. package/docs/policies/mcp-auth0-oauth-inbound/intro.md +7 -0
  77. package/docs/policies/mcp-auth0-oauth-inbound/schema.json +135 -0
  78. package/docs/policies/mcp-capability-filter-inbound/doc.md +58 -0
  79. package/docs/policies/mcp-capability-filter-inbound/intro.md +9 -0
  80. package/docs/policies/mcp-capability-filter-inbound/schema.json +212 -0
  81. package/docs/policies/mcp-clerk-oauth-inbound/doc.md +34 -0
  82. package/docs/policies/mcp-clerk-oauth-inbound/intro.md +1 -0
  83. package/docs/policies/mcp-clerk-oauth-inbound/schema.json +134 -0
  84. package/docs/policies/mcp-cognito-oauth-inbound/doc.md +52 -0
  85. package/docs/policies/mcp-cognito-oauth-inbound/intro.md +7 -0
  86. package/docs/policies/mcp-cognito-oauth-inbound/schema.json +152 -0
  87. package/docs/policies/mcp-entra-oauth-inbound/doc.md +51 -0
  88. package/docs/policies/mcp-entra-oauth-inbound/intro.md +6 -0
  89. package/docs/policies/mcp-entra-oauth-inbound/schema.json +131 -0
  90. package/docs/policies/mcp-google-oauth-inbound/doc.md +52 -0
  91. package/docs/policies/mcp-google-oauth-inbound/intro.md +6 -0
  92. package/docs/policies/mcp-google-oauth-inbound/schema.json +125 -0
  93. package/docs/policies/mcp-keycloak-oauth-inbound/doc.md +43 -0
  94. package/docs/policies/mcp-keycloak-oauth-inbound/intro.md +2 -0
  95. package/docs/policies/mcp-keycloak-oauth-inbound/schema.json +140 -0
  96. package/docs/policies/mcp-logto-oauth-inbound/doc.md +52 -0
  97. package/docs/policies/mcp-logto-oauth-inbound/intro.md +6 -0
  98. package/docs/policies/mcp-logto-oauth-inbound/schema.json +131 -0
  99. package/docs/policies/mcp-oauth-inbound/doc.md +70 -0
  100. package/docs/policies/mcp-oauth-inbound/intro.md +11 -0
  101. package/docs/policies/mcp-oauth-inbound/schema.json +177 -0
  102. package/docs/policies/mcp-okta-oauth-inbound/doc.md +61 -0
  103. package/docs/policies/mcp-okta-oauth-inbound/intro.md +7 -0
  104. package/docs/policies/mcp-okta-oauth-inbound/schema.json +137 -0
  105. package/docs/policies/mcp-onelogin-oauth-inbound/doc.md +50 -0
  106. package/docs/policies/mcp-onelogin-oauth-inbound/intro.md +6 -0
  107. package/docs/policies/mcp-onelogin-oauth-inbound/schema.json +131 -0
  108. package/docs/policies/mcp-ping-oauth-inbound/doc.md +80 -0
  109. package/docs/policies/mcp-ping-oauth-inbound/intro.md +7 -0
  110. package/docs/policies/mcp-ping-oauth-inbound/schema.json +151 -0
  111. package/docs/policies/mcp-token-exchange-inbound/doc.md +135 -0
  112. package/docs/policies/mcp-token-exchange-inbound/intro.md +6 -0
  113. package/docs/policies/mcp-token-exchange-inbound/schema.json +134 -0
  114. package/docs/policies/mcp-workos-oauth-inbound/doc.md +50 -0
  115. package/docs/policies/mcp-workos-oauth-inbound/intro.md +6 -0
  116. package/docs/policies/mcp-workos-oauth-inbound/schema.json +125 -0
  117. package/docs/policies/mock-api-inbound/schema.json +1 -0
  118. package/docs/policies/moesif-inbound/schema.json +1 -0
  119. package/docs/policies/monetization-inbound/schema.json +1 -0
  120. package/docs/policies/mtls-auth-inbound/schema.json +1 -0
  121. package/docs/policies/okta-fga-authz-inbound/schema.json +1 -0
  122. package/docs/policies/okta-jwt-auth-inbound/schema.json +1 -0
  123. package/docs/policies/open-id-jwt-auth-inbound/schema.json +1 -0
  124. package/docs/policies/openfga-authz-inbound/schema.json +1 -0
  125. package/docs/policies/openmeter-inbound/schema.json +1 -0
  126. package/docs/policies/prompt-injection-outbound/schema.json +1 -0
  127. package/docs/policies/propel-auth-jwt-inbound/schema.json +1 -0
  128. package/docs/policies/query-param-to-header-inbound/schema.json +1 -0
  129. package/docs/policies/quota-inbound/schema.json +1 -0
  130. package/docs/policies/rate-limit-inbound/schema.json +1 -0
  131. package/docs/policies/readme-metrics-inbound/schema.json +1 -0
  132. package/docs/policies/remove-headers-inbound/schema.json +1 -0
  133. package/docs/policies/remove-headers-outbound/schema.json +1 -0
  134. package/docs/policies/remove-query-params-inbound/schema.json +1 -0
  135. package/docs/policies/replace-string-outbound/schema.json +1 -0
  136. package/docs/policies/request-size-limit-inbound/schema.json +1 -0
  137. package/docs/policies/request-validation-inbound/schema.json +1 -0
  138. package/docs/policies/require-origin-inbound/schema.json +1 -0
  139. package/docs/policies/secret-masking-outbound/schema.json +1 -0
  140. package/docs/policies/semantic-cache-inbound/schema.json +1 -0
  141. package/docs/policies/set-body-inbound/schema.json +1 -0
  142. package/docs/policies/set-headers-inbound/schema.json +1 -0
  143. package/docs/policies/set-headers-outbound/schema.json +1 -0
  144. package/docs/policies/set-query-params-inbound/schema.json +1 -0
  145. package/docs/policies/set-status-outbound/schema.json +1 -0
  146. package/docs/policies/set-upstream-api-key-inbound/schema.json +1 -0
  147. package/docs/policies/sleep-inbound/schema.json +1 -0
  148. package/docs/policies/stripe-webhook-verification-inbound/schema.json +1 -0
  149. package/docs/policies/supabase-jwt-auth-inbound/schema.json +1 -0
  150. package/docs/policies/upstream-azure-ad-service-auth-inbound/schema.json +1 -0
  151. package/docs/policies/upstream-firebase-admin-auth-inbound/schema.json +1 -0
  152. package/docs/policies/upstream-firebase-user-auth-inbound/schema.json +1 -0
  153. package/docs/policies/upstream-gcp-federated-auth-inbound/schema.json +1 -0
  154. package/docs/policies/upstream-gcp-jwt-inbound/schema.json +1 -0
  155. package/docs/policies/upstream-gcp-service-auth-inbound/schema.json +1 -0
  156. package/docs/policies/upstream-zuplo-jwt-auth-inbound/schema.json +1 -0
  157. package/docs/policies/validate-json-schema-inbound/schema.json +1 -0
  158. package/docs/policies/web-bot-auth-inbound/schema.json +1 -0
  159. package/docs/policies/xml-to-json-outbound/schema.json +1 -0
  160. package/package.json +4 -4
@@ -0,0 +1,242 @@
1
+ ---
2
+ title: "Configuring a generic OIDC provider"
3
+ sidebar_label: "Generic OIDC"
4
+ description:
5
+ Configure any OIDC-compatible identity provider — Ory Hydra, Authentik,
6
+ ZITADEL, FusionAuth, PingFederate, or a custom OIDC server — to back the MCP
7
+ Gateway's downstream OAuth using the mcp-oauth-inbound policy.
8
+ ---
9
+
10
+ The `mcp-oauth-inbound` policy is the catch-all for OIDC identity providers that
11
+ don't yet have a first-class wrapper. It accepts the OIDC URLs explicitly and
12
+ otherwise behaves the same as every per-provider wrapper.
13
+
14
+ Use this policy when your IdP doesn't appear in the
15
+ [provider catalog](./overview.mdx#identity-providers). Common cases:
16
+
17
+ - **Ory Hydra** — self-hosted OAuth 2.0/OIDC.
18
+ - **Authentik** — open-source IdP.
19
+ - **ZITADEL** — open-source IdP.
20
+ - **FusionAuth** — self-hosted IdP.
21
+ - **PingFederate** — enterprise IdP (use this policy, not
22
+ `mcp-ping-oauth-inbound`, which is for PingOne cloud).
23
+ - **A custom OIDC server** you operate yourself.
24
+
25
+ If your IdP is on the [catalog](./overview.mdx#identity-providers), use the
26
+ dedicated wrapper instead — it validates provider-specific inputs at boot.
27
+
28
+ Read the [authentication overview](./overview.mdx) first for the two-layer
29
+ model.
30
+
31
+ ## What the gateway needs from your IdP
32
+
33
+ The gateway needs three pieces of information about your IdP:
34
+
35
+ 1. The **OIDC issuer URL** — the value of `iss` in ID tokens.
36
+ 2. The **JWKS URL** — where the gateway fetches the IdP's public keys to verify
37
+ ID tokens.
38
+ 3. The **authorize URL** — where the gateway redirects the user's browser to log
39
+ in.
40
+
41
+ For the federated authorization-code exchange you also need a token URL, a
42
+ client ID, and a client secret. The [options reference](#full-options-reference)
43
+ below lists every field.
44
+
45
+ Most OIDC providers publish all four URLs in a discovery document at
46
+ `{issuer}/.well-known/openid-configuration`. Fetch that document in a browser to
47
+ copy the values.
48
+
49
+ ## Set up the OIDC application
50
+
51
+ Each IdP exposes its application registration differently, but every flow lands
52
+ at the same place:
53
+
54
+ 1. Create a new OIDC web application (or "regular web application", "OIDC
55
+ client", "confidential client" — terminology varies).
56
+ 2. Set the **redirect URI** to `https://<gateway-host>/oauth/callback`. Add
57
+ `http://localhost:9000/oauth/callback` for local development with
58
+ `zuplo dev`.
59
+ 3. Note the **client ID** and **client secret**.
60
+ 4. Restrict the application to the users or groups who should be able to
61
+ authenticate against the gateway.
62
+
63
+ ## Wire the policy into the gateway
64
+
65
+ Add the policy to `config/policies.json`:
66
+
67
+ ```json
68
+ {
69
+ "name": "oidc-managed-oauth",
70
+ "policyType": "mcp-oauth-inbound",
71
+ "handler": {
72
+ "module": "$import(@zuplo/runtime/mcp-gateway)",
73
+ "export": "McpOAuthInboundPolicy",
74
+ "options": {
75
+ "oidc": {
76
+ "issuer": "https://idp.example.com",
77
+ "jwksUrl": "https://idp.example.com/.well-known/jwks.json"
78
+ },
79
+ "browserLogin": {
80
+ "url": "https://idp.example.com/oauth2/authorize",
81
+ "tokenUrl": "https://idp.example.com/oauth2/token",
82
+ "clientId": "$env(OIDC_CLIENT_ID)",
83
+ "clientSecret": "$env(OIDC_CLIENT_SECRET)"
84
+ }
85
+ }
86
+ }
87
+ }
88
+ ```
89
+
90
+ Set `OIDC_CLIENT_ID` and `OIDC_CLIENT_SECRET` in your project's environment
91
+ configuration (the secret goes in the secret store).
92
+
93
+ Attach the policy to each MCP route in `config/routes.oas.json`:
94
+
95
+ ```jsonc
96
+ {
97
+ "paths": {
98
+ "/mcp/linear-v1": {
99
+ "get,post": {
100
+ "operationId": "linear-mcp-server",
101
+ "x-zuplo-route": {
102
+ "corsPolicy": "none",
103
+ "handler": {
104
+ "module": "$import(@zuplo/runtime/mcp-gateway)",
105
+ "export": "McpProxyHandler",
106
+ "options": {
107
+ "rewritePattern": "https://mcp.linear.app/mcp",
108
+ },
109
+ },
110
+ "policies": {
111
+ "inbound": ["oidc-managed-oauth", "mcp-token-exchange-linear"],
112
+ },
113
+ },
114
+ },
115
+ },
116
+ },
117
+ }
118
+ ```
119
+
120
+ Register the gateway plugin in `modules/zuplo.runtime.ts`:
121
+
122
+ ```ts
123
+ import { RuntimeExtensions } from "@zuplo/runtime";
124
+ import { McpGatewayPlugin } from "@zuplo/runtime/mcp-gateway";
125
+
126
+ export function runtimeInit(runtime: RuntimeExtensions) {
127
+ runtime.addPlugin(new McpGatewayPlugin());
128
+ }
129
+ ```
130
+
131
+ One MCP OAuth policy serves every MCP route in the project. The gateway rejects
132
+ projects that declare more than one MCP OAuth policy.
133
+
134
+ ## Local development shortcut
135
+
136
+ For local development without round-tripping a real IdP, set `browserLogin.url`
137
+ to the loopback dev-login endpoint:
138
+
139
+ ```json
140
+ {
141
+ "options": {
142
+ "oidc": {
143
+ "issuer": "http://localhost:9000/",
144
+ "jwksUrl": "http://localhost:9000/dev/jwks"
145
+ },
146
+ "browserLogin": {
147
+ "url": "http://127.0.0.1:9000/oauth/dev-login"
148
+ }
149
+ }
150
+ }
151
+ ```
152
+
153
+ When `browserLogin.url` points at `/oauth/dev-login`, you don't need `tokenUrl`,
154
+ `clientId`, or `clientSecret`. The endpoint is only served on loopback origins;
155
+ production deployments cannot reach it.
156
+
157
+ See the [local development guide](../code-config/local-development.mdx) for the
158
+ rest of the local setup.
159
+
160
+ ## Full options reference
161
+
162
+ `mcp-oauth-inbound` has two required option groups: `oidc` and `browserLogin`.
163
+
164
+ | Option | Required | Default | Notes |
165
+ | -------------------------------- | ------------------ | ---------------------- | ----------------------------------------------------------------------------------------------------------- |
166
+ | `oidc.issuer` | yes | — | The OIDC issuer URL. Must include the scheme. |
167
+ | `oidc.jwksUrl` | yes | — | JWKS endpoint that publishes the IdP's signing keys. |
168
+ | `oidc.audience` | no | unset | Optional ID-token audience override. Leave unset when ID tokens use the OIDC `client_id` as their audience. |
169
+ | `browserLogin.url` | yes | — | The IdP's `/authorize` endpoint. The loopback `/oauth/dev-login` shortcut works for local dev. |
170
+ | `browserLogin.tokenUrl` | for federated OIDC | — | The IdP's token endpoint. Required for the federated authorization-code exchange. |
171
+ | `browserLogin.clientId` | for federated OIDC | — | OIDC client_id registered with the IdP. |
172
+ | `browserLogin.clientSecret` | for federated OIDC | — | OIDC client_secret. Use `$env(...)`. |
173
+ | `browserLogin.scope` | no | `openid profile email` | OIDC scopes requested during browser login. |
174
+ | `browserLogin.audience` | no | unset | Optional `audience` parameter for Auth0-style API audiences. |
175
+ | `browserLogin.remoteTimeoutMs` | no | `10000` | Outbound timeout for IdP calls. |
176
+ | `browserLogin.stateTtlSeconds` | no | `900` | Browser-login state record lifetime. |
177
+ | `browserLogin.sessionTtlSeconds` | no | `28800` | Browser session cookie lifetime (8 hours). |
178
+ | `gateway.accessTokenTtlSeconds` | no | `900` | Gateway-issued access token lifetime. |
179
+ | `gateway.refreshTokenTtlSeconds` | no | long-lived | Gateway-issued refresh token lifetime. |
180
+ | `gateway.cimdEnabled` | no | `true` | Advertise CIMD support in AS metadata. |
181
+
182
+ ## Notes for specific providers
183
+
184
+ - **Ory Hydra.** Discovery lives at `{issuer}/.well-known/openid-configuration`;
185
+ set the issuer to the public-facing Hydra URL.
186
+ - **Authentik.** The issuer is `https://<authentik-host>/application/o/<slug>/`
187
+ (note the trailing slash). The metadata document is at that issuer plus
188
+ `.well-known/openid-configuration`.
189
+ - **ZITADEL.** The issuer is your ZITADEL custom domain; metadata is at
190
+ `{issuer}/.well-known/openid-configuration`.
191
+ - **FusionAuth.** The issuer is your FusionAuth host; metadata is at
192
+ `{issuer}/.well-known/openid-configuration`.
193
+ - **PingFederate.** Use this generic policy (not the PingOne wrapper).
194
+ PingFederate deployments can customize issuer hosts, issuer paths, and
195
+ endpoint paths; copy the four URLs from your federation metadata.
196
+ - **Google Workspace.** Google has a first-class wrapper —
197
+ [Configuring Google](./configuring-google.mdx).
198
+ - **Microsoft Entra ID.** Entra has a first-class wrapper —
199
+ [Configuring Microsoft Entra](./configuring-entra.mdx).
200
+ - **Keycloak.** Keycloak has a first-class wrapper —
201
+ [Configuring Keycloak](./configuring-keycloak.mdx).
202
+
203
+ In every case, the gateway only needs the four URL fields (issuer, JWKS,
204
+ authorize, token) plus a client ID and secret.
205
+
206
+ ## Test the configuration
207
+
208
+ The fastest sanity check is to connect an MCP client:
209
+
210
+ 1. Open Claude Desktop, Cursor, Claude Code, or another OAuth-aware MCP client.
211
+ 2. Add a remote MCP server pointing at one of your `/mcp/{slug}` routes.
212
+ 3. The client should redirect you to your IdP's login page. After login, the
213
+ gateway's consent screen renders. Approve it.
214
+ 4. The client receives an access token and can call `tools/list`.
215
+
216
+ If something fails partway through, walk the flow manually using the
217
+ [manual OAuth testing guide](./manual-oauth-testing.mdx) — it exercises every
218
+ endpoint with `curl` so you can see the raw responses.
219
+
220
+ ## Common issues
221
+
222
+ - **The gateway returns 500 at boot.** A required option is missing or invalid.
223
+ Check the runtime logs for the configuration error.
224
+ - **ID token verification fails.** The `oidc.jwksUrl` doesn't match the IdP's
225
+ actual JWKS endpoint, or the IdP rotated keys. Restart the gateway to clear
226
+ the JWKS cache.
227
+ - **`invalid_audience` from the gateway's token endpoint.** The MCP client is
228
+ reusing a token bound to a different route. Each gateway-issued token is
229
+ scoped to one MCP route.
230
+ - **MCP client can't discover the AS.** Confirm the `mcp-oauth-inbound` policy
231
+ is attached to the route in `routes.oas.json` and the `McpGatewayPlugin` is
232
+ registered in `modules/zuplo.runtime.ts`.
233
+ - **Browser login redirects but the callback fails.** The
234
+ `https://<gateway-host>/oauth/callback` URL isn't on the application's
235
+ redirect URI allow-list at the IdP.
236
+
237
+ ## Related
238
+
239
+ - [Authentication overview](./overview.mdx) — the provider catalog and the
240
+ two-layer OAuth model.
241
+ - [Per-user OAuth to upstream MCP servers](./upstream-oauth.mdx)
242
+ - [Manual OAuth testing](./manual-oauth-testing.mdx)
@@ -0,0 +1,117 @@
1
+ ---
2
+ title: "Configuring Google"
3
+ sidebar_label: "Google"
4
+ description:
5
+ Configure Google as the identity provider behind the MCP Gateway's downstream
6
+ OAuth using the mcp-google-oauth-inbound policy. Covers OAuth client setup in
7
+ Google Cloud and wiring the policy in your gateway project.
8
+ ---
9
+
10
+ The MCP Gateway can use Google as the identity provider behind its downstream
11
+ OAuth flow. The `mcp-google-oauth-inbound` policy is a Google-friendly wrapper
12
+ around the generic `mcp-oauth-inbound` policy: provide a Google OAuth client ID
13
+ and client secret, and the policy uses Google's fixed OIDC issuer
14
+ (`https://accounts.google.com`) and discovery document automatically.
15
+
16
+ This guide walks through the Google Cloud 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
+ ## Set up Google
21
+
22
+ The MCP Gateway acts as an OAuth 2.1 authorization server in front of Google.
23
+ Google handles browser login; the gateway issues its own access tokens that bind
24
+ to MCP routes.
25
+
26
+ ### Create an OAuth client
27
+
28
+ 1. In the Google Cloud Console, switch to the project that should own the OAuth
29
+ client, then open **APIs & Services → Credentials**.
30
+ 2. Click **Create credentials → OAuth client ID**. (If prompted, configure the
31
+ **OAuth consent screen** first — pick **Internal** for Google Workspace
32
+ tenants or **External** for general use, then add the user types you want to
33
+ allow.)
34
+ 3. Choose **Web application** as the application type.
35
+ 4. Give the client a name (for example, `Zuplo MCP Gateway`).
36
+ 5. Under **Authorized redirect URIs**, add
37
+ `https://<gateway-host>/oauth/callback`. Add
38
+ `http://localhost:9000/oauth/callback` for local development with
39
+ `zuplo dev`.
40
+ 6. Click **Create**.
41
+
42
+ Note the **Client ID** (looks like
43
+ `123456789012-abc123def456.apps.googleusercontent.com`) and the **Client
44
+ secret** from the dialog. The wrapper rejects values that aren't in Google's
45
+ OAuth client ID shape.
46
+
47
+ ## Wire the policy into the gateway
48
+
49
+ Add the policy to `config/policies.json`:
50
+
51
+ ```json
52
+ {
53
+ "name": "google-managed-oauth",
54
+ "policyType": "mcp-google-oauth-inbound",
55
+ "handler": {
56
+ "module": "$import(@zuplo/runtime/mcp-gateway)",
57
+ "export": "McpGoogleOAuthInboundPolicy",
58
+ "options": {
59
+ "clientId": "$env(GOOGLE_CLIENT_ID)",
60
+ "clientSecret": "$env(GOOGLE_CLIENT_SECRET)"
61
+ }
62
+ }
63
+ }
64
+ ```
65
+
66
+ Set the two environment variables in your project's environment configuration.
67
+ The secret values belong in the project secret store.
68
+
69
+ Attach the policy to each MCP route in `config/routes.oas.json` and register the
70
+ gateway plugin in `modules/zuplo.runtime.ts` (see
71
+ [Configuring Auth0](./configuring-auth0.mdx#wire-the-policy-into-the-gateway)
72
+ for the route and plugin patterns — they're identical across all wrappers).
73
+
74
+ ## What the wrapper derives
75
+
76
+ Google publishes a fixed OIDC discovery document at
77
+ `https://accounts.google.com/.well-known/openid-configuration`. The wrapper
78
+ hard-codes the corresponding endpoints:
79
+
80
+ | Generic field | Derived value |
81
+ | ----------------------- | ---------------------------------------------- |
82
+ | `oidc.issuer` | `https://accounts.google.com` |
83
+ | `oidc.jwksUrl` | `https://www.googleapis.com/oauth2/v3/certs` |
84
+ | `browserLogin.url` | `https://accounts.google.com/o/oauth2/v2/auth` |
85
+ | `browserLogin.tokenUrl` | `https://oauth2.googleapis.com/token` |
86
+
87
+ ## Test the configuration
88
+
89
+ The fastest sanity check is to connect an MCP client:
90
+
91
+ 1. Open Claude Desktop, Cursor, Claude Code, or another OAuth-aware MCP client.
92
+ 2. Add a remote MCP server pointing at one of your `/mcp/{slug}` routes.
93
+ 3. The client should redirect you to the Google sign-in page. After login, the
94
+ gateway's consent screen renders. Approve it.
95
+ 4. The client receives an access token and can call `tools/list`.
96
+
97
+ If something fails partway through, walk the flow manually using the
98
+ [manual OAuth testing guide](./manual-oauth-testing.mdx) — it exercises every
99
+ endpoint with `curl` so you can see the raw responses.
100
+
101
+ ## Common issues
102
+
103
+ - **`clientId` rejected at boot.** The wrapper rejects values that don't use
104
+ Google's OAuth client ID shape — issuer URLs, API hostnames, project numbers.
105
+ Use the full `123456789012-abc123def456.apps.googleusercontent.com` form.
106
+ - **`redirect_uri_mismatch` from Google.** The redirect URI on the OAuth client
107
+ doesn't match `https://<gateway-host>/oauth/callback` exactly. Match scheme,
108
+ host, and path.
109
+ - **`access_denied` for Google Workspace users.** The OAuth consent screen is
110
+ set to **Internal** but the user belongs to a different workspace, or the user
111
+ isn't on the **Test users** list during pre-verification.
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)
@@ -0,0 +1,125 @@
1
+ ---
2
+ title: "Configuring Keycloak"
3
+ sidebar_label: "Keycloak"
4
+ description:
5
+ Configure Keycloak to back the MCP Gateway's downstream OAuth using the
6
+ mcp-keycloak-oauth-inbound policy. Covers realm client setup and wiring the
7
+ policy in your gateway project.
8
+ ---
9
+
10
+ The MCP Gateway can use Keycloak as the identity provider behind its downstream
11
+ OAuth flow. The `mcp-keycloak-oauth-inbound` policy is a Keycloak-friendly
12
+ wrapper around the generic `mcp-oauth-inbound` policy: provide your Keycloak
13
+ base URL, a realm name, a client ID, and a client secret, and the policy derives
14
+ the realm-issuer URL, JWKS URL, and authorize and token URLs from Keycloak's
15
+ standard OpenID Connect endpoint layout.
16
+
17
+ This guide walks through the Keycloak admin console setup, then wires the policy
18
+ into a gateway project. Read the [authentication overview](./overview.mdx) first
19
+ for the two-layer OAuth model.
20
+
21
+ ## Set up Keycloak
22
+
23
+ The MCP Gateway acts as an OAuth 2.1 authorization server in front of Keycloak.
24
+ Keycloak handles browser login; the gateway issues its own access tokens that
25
+ bind to MCP routes.
26
+
27
+ ### Create a client in the realm
28
+
29
+ 1. In the Keycloak admin console, switch to the realm you want the gateway to
30
+ use.
31
+ 2. Open **Clients** and click **Create client**.
32
+ 3. Give the client a Client ID (for example, `zuplo-mcp-gateway`) and click
33
+ **Next**.
34
+ 4. Enable **Client authentication** (so the client requires a secret) and leave
35
+ **Standard flow** (authorization code) enabled. Disable **Service accounts
36
+ roles** and **Direct access grants** — the gateway only needs the browser
37
+ code flow.
38
+ 5. Click **Next**.
39
+ 6. Set **Valid redirect URIs** to `https://<gateway-host>/oauth/callback`. Add
40
+ `http://localhost:9000/oauth/callback` for local development.
41
+ 7. Set **Web origins** to `https://<gateway-host>` (and `http://localhost:9000`
42
+ for local dev).
43
+ 8. Click **Save**.
44
+
45
+ ### Note the client credentials
46
+
47
+ Open the client's **Credentials** tab. Copy the **Client secret**. The **Client
48
+ ID** is the value you set above.
49
+
50
+ ## Wire the policy into the gateway
51
+
52
+ Add the policy to `config/policies.json`:
53
+
54
+ ```json
55
+ {
56
+ "name": "keycloak-managed-oauth",
57
+ "policyType": "mcp-keycloak-oauth-inbound",
58
+ "handler": {
59
+ "module": "$import(@zuplo/runtime/mcp-gateway)",
60
+ "export": "McpKeycloakOAuthInboundPolicy",
61
+ "options": {
62
+ "keycloakBaseUrl": "$env(KEYCLOAK_BASE_URL)",
63
+ "realm": "$env(KEYCLOAK_REALM)",
64
+ "clientId": "$env(KEYCLOAK_CLIENT_ID)",
65
+ "clientSecret": "$env(KEYCLOAK_CLIENT_SECRET)"
66
+ }
67
+ }
68
+ }
69
+ ```
70
+
71
+ :::caution
72
+
73
+ `keycloakBaseUrl` is the Keycloak server root, without `/realms/{realm}` — set
74
+ the realm separately on the `realm` option. If your deployment uses a path
75
+ prefix (legacy `/auth`), include that in `keycloakBaseUrl`
76
+ (`https://sso.example.com/auth`).
77
+
78
+ :::
79
+
80
+ Attach the policy to each MCP route in `config/routes.oas.json` and register the
81
+ gateway plugin in `modules/zuplo.runtime.ts` (see
82
+ [Configuring Auth0](./configuring-auth0.mdx#wire-the-policy-into-the-gateway)
83
+ for the route and plugin patterns — they're identical across all wrappers).
84
+
85
+ ## What the wrapper derives
86
+
87
+ Given `keycloakBaseUrl: "https://sso.example.com"` and
88
+ `realm: "customer-portal"`:
89
+
90
+ | Generic field | Derived value |
91
+ | ----------------------- | ------------------------------------------------------------------------------ |
92
+ | `oidc.issuer` | `https://sso.example.com/realms/customer-portal` |
93
+ | `oidc.jwksUrl` | `https://sso.example.com/realms/customer-portal/protocol/openid-connect/certs` |
94
+ | `browserLogin.url` | `https://sso.example.com/realms/customer-portal/protocol/openid-connect/auth` |
95
+ | `browserLogin.tokenUrl` | `https://sso.example.com/realms/customer-portal/protocol/openid-connect/token` |
96
+
97
+ ## Test the configuration
98
+
99
+ The fastest sanity check is to connect an MCP client:
100
+
101
+ 1. Open Claude Desktop, Cursor, Claude Code, or another OAuth-aware MCP client.
102
+ 2. Add a remote MCP server pointing at one of your `/mcp/{slug}` routes.
103
+ 3. The client should redirect you to the Keycloak sign-in page. After login, the
104
+ gateway's consent screen renders. Approve it.
105
+ 4. The client receives an access token and can call `tools/list`.
106
+
107
+ If something fails partway through, walk the flow manually using the
108
+ [manual OAuth testing guide](./manual-oauth-testing.mdx) — it exercises every
109
+ endpoint with `curl` so you can see the raw responses.
110
+
111
+ ## Common issues
112
+
113
+ - **`keycloakBaseUrl` rejected at boot.** The value includes `/realms/...`.
114
+ Strip the realm path; pass the realm name on the `realm` option instead.
115
+ - **`Invalid redirect_uri` from Keycloak.** The callback URL on the client
116
+ doesn't match `https://<gateway-host>/oauth/callback`.
117
+ - **`Invalid client credentials`.** The client isn't a confidential client
118
+ (Client authentication off), or the secret value doesn't match. Re-copy the
119
+ secret from the **Credentials** tab.
120
+
121
+ ## Related
122
+
123
+ - [Authentication overview](./overview.mdx)
124
+ - [Configuring a generic OIDC provider](./configuring-generic-oidc.mdx)
125
+ - [Per-user OAuth to upstream MCP servers](./upstream-oauth.mdx)
@@ -0,0 +1,116 @@
1
+ ---
2
+ title: "Configuring Logto"
3
+ sidebar_label: "Logto"
4
+ description:
5
+ Configure Logto to back the MCP Gateway's downstream OAuth using the
6
+ mcp-logto-oauth-inbound policy. Covers application setup and wiring the policy
7
+ in your gateway project.
8
+ ---
9
+
10
+ The MCP Gateway can use [Logto](https://logto.io/) as the identity provider
11
+ behind its downstream OAuth flow. The `mcp-logto-oauth-inbound` policy is a
12
+ Logto-friendly wrapper around the generic `mcp-oauth-inbound` policy: provide
13
+ your Logto tenant endpoint, a client ID, and a client secret, and the policy
14
+ derives the OIDC issuer, JWKS URL, and authorize and token URLs from Logto's
15
+ `/oidc` mount point.
16
+
17
+ This guide walks through the Logto console setup, then wires the policy into a
18
+ gateway project. Read the [authentication overview](./overview.mdx) first for
19
+ the two-layer OAuth model.
20
+
21
+ ## Set up Logto
22
+
23
+ The MCP Gateway acts as an OAuth 2.1 authorization server in front of Logto.
24
+ Logto handles browser login; the gateway issues its own access tokens that bind
25
+ to MCP routes.
26
+
27
+ ### Create a Traditional Web application
28
+
29
+ 1. In the Logto Console, open **Applications** and click **Create application**.
30
+ 2. Pick **Traditional Web** as the application type. (Not SPA, not Native — the
31
+ gateway needs a confidential client with a secret.)
32
+ 3. Give the application a name (for example, `Zuplo MCP Gateway`) and click
33
+ **Create application**.
34
+ 4. On the application's **Settings** tab, set **Redirect URIs** to
35
+ `https://<gateway-host>/oauth/callback`. Add
36
+ `http://localhost:9000/oauth/callback` for local development.
37
+ 5. Save.
38
+
39
+ Note the **App ID** (= client ID) and **App secret** (= client secret) from the
40
+ application's detail page.
41
+
42
+ ### Find your tenant endpoint
43
+
44
+ Open **Settings → Domains** in the Logto Console. Your default tenant endpoint
45
+ looks like `https://your-tenant.logto.app`. If you've configured a custom
46
+ domain, use that instead. The wrapper takes the origin only — no `/oidc`, no
47
+ `.well-known/...`, no trailing slash.
48
+
49
+ ## Wire the policy into the gateway
50
+
51
+ Add the policy to `config/policies.json`:
52
+
53
+ ```json
54
+ {
55
+ "name": "logto-managed-oauth",
56
+ "policyType": "mcp-logto-oauth-inbound",
57
+ "handler": {
58
+ "module": "$import(@zuplo/runtime/mcp-gateway)",
59
+ "export": "McpLogtoOAuthInboundPolicy",
60
+ "options": {
61
+ "logtoEndpoint": "$env(LOGTO_ENDPOINT)",
62
+ "clientId": "$env(LOGTO_CLIENT_ID)",
63
+ "clientSecret": "$env(LOGTO_CLIENT_SECRET)"
64
+ }
65
+ }
66
+ }
67
+ ```
68
+
69
+ Attach the policy to each MCP route in `config/routes.oas.json` and register the
70
+ gateway plugin in `modules/zuplo.runtime.ts` (see
71
+ [Configuring Auth0](./configuring-auth0.mdx#wire-the-policy-into-the-gateway)
72
+ for the route and plugin patterns — they're identical across all wrappers).
73
+
74
+ ## What the wrapper derives
75
+
76
+ Given `logtoEndpoint: "https://acme.logto.app"`:
77
+
78
+ | Generic field | Derived value |
79
+ | ----------------------- | ----------------------------------- |
80
+ | `oidc.issuer` | `https://acme.logto.app/oidc` |
81
+ | `oidc.jwksUrl` | `https://acme.logto.app/oidc/jwks` |
82
+ | `browserLogin.url` | `https://acme.logto.app/oidc/auth` |
83
+ | `browserLogin.tokenUrl` | `https://acme.logto.app/oidc/token` |
84
+
85
+ These endpoint shapes come from Logto's OIDC provider mounted at `/oidc` and its
86
+ discovery document at
87
+ `https://<your-logto-endpoint>/oidc/.well-known/openid-configuration`.
88
+
89
+ ## Test the configuration
90
+
91
+ The fastest sanity check is to connect an MCP client:
92
+
93
+ 1. Open Claude Desktop, Cursor, Claude Code, or another OAuth-aware MCP client.
94
+ 2. Add a remote MCP server pointing at one of your `/mcp/{slug}` routes.
95
+ 3. The client should redirect you to the Logto sign-in page. After login, the
96
+ gateway's consent screen renders. Approve it.
97
+ 4. The client receives an access token and can call `tools/list`.
98
+
99
+ If something fails partway through, walk the flow manually using the
100
+ [manual OAuth testing guide](./manual-oauth-testing.mdx) — it exercises every
101
+ endpoint with `curl` so you can see the raw responses.
102
+
103
+ ## Common issues
104
+
105
+ - **`logtoEndpoint` rejected at boot.** The value includes `/oidc`,
106
+ `/.well-known/openid-configuration`, or another path. Use the bare tenant
107
+ endpoint origin.
108
+ - **`redirect_uri` rejected by Logto.** The redirect URI on the application
109
+ doesn't match `https://<gateway-host>/oauth/callback`. Match scheme, host, and
110
+ path.
111
+
112
+ ## Related
113
+
114
+ - [Authentication overview](./overview.mdx)
115
+ - [Configuring a generic OIDC provider](./configuring-generic-oidc.mdx)
116
+ - [Per-user OAuth to upstream MCP servers](./upstream-oauth.mdx)