zuplo 7.4.4 → 7.4.6

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 (40) hide show
  1. package/docs/articles/ci-cd-azure/local-testing.mdx +22 -4
  2. package/docs/articles/ci-cd-bitbucket/local-testing.mdx +22 -4
  3. package/docs/articles/ci-cd-circleci/local-testing.mdx +21 -4
  4. package/docs/articles/ci-cd-github/deploy-and-test.mdx +28 -13
  5. package/docs/articles/ci-cd-github/local-testing.mdx +36 -16
  6. package/docs/articles/ci-cd-gitlab/local-testing.mdx +22 -4
  7. package/docs/articles/github-deployment-testing.mdx +118 -31
  8. package/docs/articles/testing-getting-started.mdx +220 -0
  9. package/docs/articles/testing-preview-environments.mdx +148 -0
  10. package/docs/articles/testing-recipes.mdx +429 -0
  11. package/docs/articles/testing.mdx +138 -408
  12. package/docs/mcp-gateway/auth/configuring-auth0.mdx +6 -5
  13. package/docs/mcp-gateway/auth/configuring-clerk.mdx +4 -4
  14. package/docs/mcp-gateway/auth/configuring-cognito.mdx +5 -4
  15. package/docs/mcp-gateway/auth/configuring-entra.mdx +5 -4
  16. package/docs/mcp-gateway/auth/configuring-generic-oidc.mdx +8 -8
  17. package/docs/mcp-gateway/auth/configuring-google.mdx +4 -4
  18. package/docs/mcp-gateway/auth/configuring-keycloak.mdx +4 -3
  19. package/docs/mcp-gateway/auth/configuring-logto.mdx +4 -4
  20. package/docs/mcp-gateway/auth/configuring-okta.mdx +3 -3
  21. package/docs/mcp-gateway/auth/configuring-onelogin.mdx +3 -3
  22. package/docs/mcp-gateway/auth/configuring-ping.mdx +3 -3
  23. package/docs/mcp-gateway/auth/configuring-workos.mdx +5 -4
  24. package/docs/mcp-gateway/auth/manual-oauth-testing.mdx +8 -8
  25. package/docs/mcp-gateway/auth/overview.mdx +17 -17
  26. package/docs/mcp-gateway/auth/upstream-oauth.mdx +5 -5
  27. package/docs/mcp-gateway/code-config/local-development.mdx +14 -12
  28. package/docs/mcp-gateway/code-config/overview.mdx +9 -4
  29. package/docs/mcp-gateway/connect-clients/chatgpt.mdx +114 -56
  30. package/docs/mcp-gateway/how-it-works.mdx +11 -9
  31. package/docs/mcp-gateway/introduction.mdx +3 -1
  32. package/docs/mcp-gateway/quickstart-local.mdx +7 -7
  33. package/docs/mcp-gateway/reference.mdx +58 -25
  34. package/docs/mcp-gateway/server-registry.mdx +179 -0
  35. package/docs/mcp-gateway/test-clients.mdx +2 -2
  36. package/docs/mcp-server/custom-tools.mdx +32 -0
  37. package/docs/programmable-api/mcp-gateway-plugin.mdx +137 -0
  38. package/docs/programmable-api/mcp-sdk.mdx +240 -0
  39. package/docs/self-hosted/overview.md +2 -0
  40. package/package.json +5 -5
@@ -56,13 +56,14 @@ tokens that bind to MCP routes. The Auth0 application you create represents the
56
56
  ### Configure callback and origin URLs
57
57
 
58
58
  The gateway completes browser login by redirecting back to its own
59
- `/oauth/callback` endpoint, so Auth0 needs that URL on its allow-list.
59
+ `/__zuplo/oauth/callback` endpoint, so Auth0 needs that URL on its allow-list.
60
60
 
61
61
  On the same **Settings** tab:
62
62
 
63
63
  1. Set **Allowed Callback URLs** to your gateway's
64
- `https://<gateway-host>/oauth/callback`. For local development against
65
- `zuplo dev`, add `http://localhost:9000/oauth/callback` as well.
64
+ `https://<gateway-host>/__zuplo/oauth/callback`. For local development
65
+ against `zuplo dev`, add `http://localhost:9000/__zuplo/oauth/callback` as
66
+ well.
66
67
  2. Set **Allowed Web Origins** to the gateway origin `https://<gateway-host>`
67
68
  (plus `http://localhost:9000` for local dev).
68
69
  3. Save changes.
@@ -194,8 +195,8 @@ endpoint with `curl` so you can see the raw responses.
194
195
  - **"Invalid Auth0 domain" at boot.** The `auth0Domain` value includes a scheme
195
196
  prefix or doesn't contain a dot. Use `my-tenant.us.auth0.com`.
196
197
  - **Browser login redirects but the callback fails.** The
197
- `https://<gateway-host>/oauth/callback` URL isn't on the **Allowed Callback
198
- URLs** list for the Auth0 application.
198
+ `https://<gateway-host>/__zuplo/oauth/callback` URL isn't on the **Allowed
199
+ Callback URLs** list for the Auth0 application.
199
200
  - **Token endpoint returns `invalid_audience`.** The MCP client is reusing a
200
201
  token bound to a different route. Each gateway-issued token binds to one
201
202
  `operationId`; the client must obtain a separate token per route.
@@ -29,8 +29,8 @@ to MCP routes.
29
29
  then open **Configure → OAuth Applications**.
30
30
  2. Click **Add OAuth application**.
31
31
  3. Give the application a name (for example, `Zuplo MCP Gateway`).
32
- 4. Set **Redirect URIs** to `https://<gateway-host>/oauth/callback`. Add
33
- `http://localhost:9000/oauth/callback` for local development with
32
+ 4. Set **Redirect URIs** to `https://<gateway-host>/__zuplo/oauth/callback`. Add
33
+ `http://localhost:9000/__zuplo/oauth/callback` for local development with
34
34
  `zuplo dev`.
35
35
  5. Select the OIDC scopes the gateway needs — `openid`, `profile`, and `email`
36
36
  are enough.
@@ -143,8 +143,8 @@ endpoint with `curl` so you can see the raw responses.
143
143
  - **The policy rejects `frontendApiUrl` at boot.** The value includes a path,
144
144
  query string, or fragment. Use only the origin (`https://clerk.example.com`).
145
145
  - **Browser login redirects but the callback fails.** The
146
- `https://<gateway-host>/oauth/callback` URL isn't on the OAuth application's
147
- redirect URIs allow-list in Clerk.
146
+ `https://<gateway-host>/__zuplo/oauth/callback` URL isn't on the OAuth
147
+ application's redirect URIs allow-list in Clerk.
148
148
 
149
149
  ## Related
150
150
 
@@ -44,8 +44,9 @@ wrapper handles both.
44
44
  1. Under **App integration → App clients**, click **Create app client**.
45
45
  2. Choose **Confidential client**. The client must have a client secret — the
46
46
  gateway needs it for the federated token exchange.
47
- 3. Set **Allowed callback URLs** to `https://<gateway-host>/oauth/callback`. Add
48
- `http://localhost:9000/oauth/callback` for local development.
47
+ 3. Set **Allowed callback URLs** to
48
+ `https://<gateway-host>/__zuplo/oauth/callback`. Add
49
+ `http://localhost:9000/__zuplo/oauth/callback` for local development.
49
50
  4. Enable **Authorization code grant** under allowed OAuth flows.
50
51
  5. Enable the OIDC scopes the gateway needs — `openid`, `profile`, and `email`.
51
52
  6. Click **Create app client**.
@@ -115,8 +116,8 @@ endpoint with `curl` so you can see the raw responses.
115
116
  `https://`, a trailing slash, or an OAuth path. Strip those — use only
116
117
  `auth.example.com` or `my-pool.auth.us-east-1.amazoncognito.com`.
117
118
  - **Browser login lands on a Cognito error page.** The callback URL on the app
118
- client doesn't match. Set it to `https://<gateway-host>/oauth/callback`
119
- exactly.
119
+ client doesn't match. Set it to
120
+ `https://<gateway-host>/__zuplo/oauth/callback` exactly.
120
121
  - **`invalid_client` from Cognito's token endpoint.** The app client doesn't
121
122
  have a client secret, or the secret value doesn't match. Cognito confidential
122
123
  clients require both ID and secret.
@@ -41,7 +41,7 @@ to MCP routes.
41
41
  directory only (single tenant)**. The wrapper does not support multi-tenant
42
42
  modes.
43
43
  4. Under **Redirect URI**, choose **Web** and set the value to
44
- `https://<gateway-host>/oauth/callback`. Click **Register**.
44
+ `https://<gateway-host>/__zuplo/oauth/callback`. Click **Register**.
45
45
  5. On the application's **Overview** page, note the **Application (client) ID**
46
46
  and the **Directory (tenant) ID**. Both are UUIDs.
47
47
 
@@ -55,7 +55,8 @@ to MCP routes.
55
55
  ### Add the local development redirect URI
56
56
 
57
57
  1. Open **Authentication** on the application.
58
- 2. Add `http://localhost:9000/oauth/callback` under **Web → Redirect URIs**.
58
+ 2. Add `http://localhost:9000/__zuplo/oauth/callback` under **Web → Redirect
59
+ URIs**.
59
60
  3. Save.
60
61
 
61
62
  ### Optional: restrict access
@@ -121,8 +122,8 @@ endpoint with `curl` so you can see the raw responses.
121
122
  verified domain, `common`, `organizations`, or `consumers`. Look up the tenant
122
123
  ID under **Overview** in the Entra admin center.
123
124
  - **`AADSTS50011` redirect URI mismatch.** The redirect URI on the app
124
- registration doesn't match `https://<gateway-host>/oauth/callback` exactly.
125
- Match scheme, host, and path.
125
+ registration doesn't match `https://<gateway-host>/__zuplo/oauth/callback`
126
+ exactly. Match scheme, host, and path.
126
127
  - **`AADSTS700016` application not found.** The client ID doesn't belong to the
127
128
  tenant the wrapper is configured with. Make sure `tenantId` and `clientId`
128
129
  come from the same app registration.
@@ -53,8 +53,8 @@ at the same place:
53
53
 
54
54
  1. Create a new OIDC web application (or "regular web application", "OIDC
55
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
56
+ 2. Set the **redirect URI** to `https://<gateway-host>/__zuplo/oauth/callback`.
57
+ Add `http://localhost:9000/__zuplo/oauth/callback` for local development with
58
58
  `zuplo dev`.
59
59
  3. Note the **client ID** and **client secret**.
60
60
  4. Restrict the application to the users or groups who should be able to
@@ -144,15 +144,15 @@ to the loopback dev-login endpoint:
144
144
  "jwksUrl": "http://localhost:9000/dev/jwks"
145
145
  },
146
146
  "browserLogin": {
147
- "url": "http://127.0.0.1:9000/oauth/dev-login"
147
+ "url": "http://127.0.0.1:9000/__zuplo/oauth/dev-login"
148
148
  }
149
149
  }
150
150
  }
151
151
  ```
152
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.
153
+ When `browserLogin.url` points at `/__zuplo/oauth/dev-login`, you don't need
154
+ `tokenUrl`, `clientId`, or `clientSecret`. The endpoint is only served on
155
+ loopback origins; production deployments cannot reach it.
156
156
 
157
157
  See the [local development guide](../code-config/local-development.mdx) for the
158
158
  rest of the local setup.
@@ -166,7 +166,7 @@ rest of the local setup.
166
166
  | `oidc.issuer` | yes | — | The OIDC issuer URL. Must include the scheme. |
167
167
  | `oidc.jwksUrl` | yes | — | JWKS endpoint that publishes the IdP's signing keys. |
168
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. |
169
+ | `browserLogin.url` | yes | — | The IdP's `/authorize` endpoint. The loopback `/__zuplo/oauth/dev-login` shortcut works for local dev. |
170
170
  | `browserLogin.tokenUrl` | for federated OIDC | — | The IdP's token endpoint. Required for the federated authorization-code exchange. |
171
171
  | `browserLogin.clientId` | for federated OIDC | — | OIDC client_id registered with the IdP. |
172
172
  | `browserLogin.clientSecret` | for federated OIDC | — | OIDC client_secret. Use `$env(...)`. |
@@ -231,7 +231,7 @@ endpoint with `curl` so you can see the raw responses.
231
231
  is attached to the route in `routes.oas.json` and the `McpGatewayPlugin` is
232
232
  registered in `modules/zuplo.runtime.ts`.
233
233
  - **Browser login redirects but the callback fails.** The
234
- `https://<gateway-host>/oauth/callback` URL isn't on the application's
234
+ `https://<gateway-host>/__zuplo/oauth/callback` URL isn't on the application's
235
235
  redirect URI allow-list at the IdP.
236
236
 
237
237
  ## Related
@@ -34,8 +34,8 @@ to MCP routes.
34
34
  3. Choose **Web application** as the application type.
35
35
  4. Give the client a name (for example, `Zuplo MCP Gateway`).
36
36
  5. Under **Authorized redirect URIs**, add
37
- `https://<gateway-host>/oauth/callback`. Add
38
- `http://localhost:9000/oauth/callback` for local development with
37
+ `https://<gateway-host>/__zuplo/oauth/callback`. Add
38
+ `http://localhost:9000/__zuplo/oauth/callback` for local development with
39
39
  `zuplo dev`.
40
40
  6. Click **Create**.
41
41
 
@@ -104,8 +104,8 @@ endpoint with `curl` so you can see the raw responses.
104
104
  Google's OAuth client ID shape — issuer URLs, API hostnames, project numbers.
105
105
  Use the full `123456789012-abc123def456.apps.googleusercontent.com` form.
106
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.
107
+ doesn't match `https://<gateway-host>/__zuplo/oauth/callback` exactly. Match
108
+ scheme, host, and path.
109
109
  - **`access_denied` for Google Workspace users.** The OAuth consent screen is
110
110
  set to **Internal** but the user belongs to a different workspace, or the user
111
111
  isn't on the **Test users** list during pre-verification.
@@ -36,8 +36,9 @@ bind to MCP routes.
36
36
  roles** and **Direct access grants** — the gateway only needs the browser
37
37
  code flow.
38
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.
39
+ 6. Set **Valid redirect URIs** to
40
+ `https://<gateway-host>/__zuplo/oauth/callback`. Add
41
+ `http://localhost:9000/__zuplo/oauth/callback` for local development.
41
42
  7. Set **Web origins** to `https://<gateway-host>` (and `http://localhost:9000`
42
43
  for local dev).
43
44
  8. Click **Save**.
@@ -113,7 +114,7 @@ endpoint with `curl` so you can see the raw responses.
113
114
  - **`keycloakBaseUrl` rejected at boot.** The value includes `/realms/...`.
114
115
  Strip the realm path; pass the realm name on the `realm` option instead.
115
116
  - **`Invalid redirect_uri` from Keycloak.** The callback URL on the client
116
- doesn't match `https://<gateway-host>/oauth/callback`.
117
+ doesn't match `https://<gateway-host>/__zuplo/oauth/callback`.
117
118
  - **`Invalid client credentials`.** The client isn't a confidential client
118
119
  (Client authentication off), or the secret value doesn't match. Re-copy the
119
120
  secret from the **Credentials** tab.
@@ -32,8 +32,8 @@ to MCP routes.
32
32
  3. Give the application a name (for example, `Zuplo MCP Gateway`) and click
33
33
  **Create application**.
34
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.
35
+ `https://<gateway-host>/__zuplo/oauth/callback`. Add
36
+ `http://localhost:9000/__zuplo/oauth/callback` for local development.
37
37
  5. Save.
38
38
 
39
39
  Note the **App ID** (= client ID) and **App secret** (= client secret) from the
@@ -106,8 +106,8 @@ endpoint with `curl` so you can see the raw responses.
106
106
  `/.well-known/openid-configuration`, or another path. Use the bare tenant
107
107
  endpoint origin.
108
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.
109
+ doesn't match `https://<gateway-host>/__zuplo/oauth/callback`. Match scheme,
110
+ host, and path.
111
111
 
112
112
  ## Related
113
113
 
@@ -40,8 +40,8 @@ that bind to MCP routes. The Okta application you create represents the
40
40
  not need refresh tokens from Okta — it uses Okta only for browser identity,
41
41
  not as a long-running token source.
42
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
43
+ `https://<gateway-host>/__zuplo/oauth/callback`. Add
44
+ `http://localhost:9000/__zuplo/oauth/callback` for local development with
45
45
  `zuplo dev`.
46
46
  6. Under **Assignments**, restrict access to the groups or users who should be
47
47
  able to authenticate against the gateway.
@@ -180,7 +180,7 @@ endpoint with `curl` so you can see the raw responses.
180
180
  - **"Invalid Okta domain" at boot.** `oktaDomain` includes a scheme prefix,
181
181
  trailing slash, or path. Use `acme.okta.com`.
182
182
  - **Browser login redirects but the callback fails.** The
183
- `https://<gateway-host>/oauth/callback` URL isn't on the application's
183
+ `https://<gateway-host>/__zuplo/oauth/callback` URL isn't on the application's
184
184
  **Sign-in redirect URIs** allow-list in Okta.
185
185
  - **`invalid_audience` from the gateway's token endpoint.** The MCP client is
186
186
  reusing a token bound to a different route. Each gateway-issued token binds to
@@ -31,8 +31,8 @@ bind to MCP routes.
31
31
  3. Give the application a display name (for example, `Zuplo MCP Gateway`) and
32
32
  click **Save**.
33
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.
34
+ 5. Set **Redirect URIs** to `https://<gateway-host>/__zuplo/oauth/callback`. Add
35
+ `http://localhost:9000/__zuplo/oauth/callback` for local development.
36
36
  6. Set **Login Url** to your gateway origin (`https://<gateway-host>`).
37
37
  7. Save.
38
38
 
@@ -111,7 +111,7 @@ endpoint with `curl` so you can see the raw responses.
111
111
  - **`oneLoginSubdomain` rejected at boot.** The value includes `https://`,
112
112
  `.onelogin.com`, or a trailing path. Pass only the subdomain (`acme`).
113
113
  - **`invalid_request: redirect_uri`.** The redirect URI on the OIDC application
114
- doesn't match `https://<gateway-host>/oauth/callback`.
114
+ doesn't match `https://<gateway-host>/__zuplo/oauth/callback`.
115
115
  - **`invalid_client` from the token endpoint.** **Token Endpoint Authentication
116
116
  Method** isn't set to **POST** on the application's SSO tab.
117
117
 
@@ -38,8 +38,8 @@ bind to MCP routes.
38
38
  2. Click **+ Add Application**, name it (for example, `Zuplo MCP Gateway`),
39
39
  choose **OIDC Web App** as the application type, and click **Save**.
40
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.
41
+ 4. Set **Redirect URIs** to `https://<gateway-host>/__zuplo/oauth/callback`. Add
42
+ `http://localhost:9000/__zuplo/oauth/callback` for local development.
43
43
  5. Set **Grant Types** to **Authorization Code**.
44
44
  6. Save.
45
45
 
@@ -144,7 +144,7 @@ endpoint with `curl` so you can see the raw responses.
144
144
  - **`environmentId` rejected at boot.** The wrapper expects a UUID. Don't pass
145
145
  the issuer URL, the auth domain, or the client ID.
146
146
  - **Browser login lands on a PingOne error page.** The redirect URI on the
147
- application doesn't match `https://<gateway-host>/oauth/callback`.
147
+ application doesn't match `https://<gateway-host>/__zuplo/oauth/callback`.
148
148
  - **`invalid_client`.** The application is set to **Public** instead of
149
149
  **Confidential**. Confidential is required so the gateway can authenticate
150
150
  with the client secret.
@@ -33,9 +33,9 @@ that bind to MCP routes.
33
33
  ### Add the redirect URI
34
34
 
35
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`.
36
+ 2. Add `https://<gateway-host>/__zuplo/oauth/callback` as an allowed redirect
37
+ URI. Add `http://localhost:9000/__zuplo/oauth/callback` for local development
38
+ with `zuplo dev`.
39
39
  3. Save.
40
40
 
41
41
  ### Note the API credentials
@@ -102,7 +102,8 @@ endpoint with `curl` so you can see the raw responses.
102
102
  ## Common issues
103
103
 
104
104
  - **`Invalid redirect URI`.** The redirect URI on **Redirects** in the WorkOS
105
- Dashboard doesn't match `https://<gateway-host>/oauth/callback` exactly.
105
+ Dashboard doesn't match `https://<gateway-host>/__zuplo/oauth/callback`
106
+ exactly.
106
107
  - **`invalid_client`.** The client secret value doesn't match. WorkOS shows the
107
108
  secret only once after creation — regenerate it from **API Keys** if you've
108
109
  lost it.
@@ -108,10 +108,10 @@ REDIRECT_URI="http://localhost:8765/callback"
108
108
  ```json
109
109
  {
110
110
  "issuer": "https://gateway.example.com/mcp/linear-v1",
111
- "authorization_endpoint": "https://gateway.example.com/oauth/authorize/mcp/linear-v1",
112
- "token_endpoint": "https://gateway.example.com/oauth/token",
113
- "registration_endpoint": "https://gateway.example.com/oauth/register",
114
- "revocation_endpoint": "https://gateway.example.com/oauth/revoke",
111
+ "authorization_endpoint": "https://gateway.example.com/__zuplo/oauth/authorize/mcp/linear-v1",
112
+ "token_endpoint": "https://gateway.example.com/__zuplo/oauth/token",
113
+ "registration_endpoint": "https://gateway.example.com/__zuplo/oauth/register",
114
+ "revocation_endpoint": "https://gateway.example.com/__zuplo/oauth/revoke",
115
115
  "scopes_supported": ["mcp:tools"],
116
116
  "response_types_supported": ["code"],
117
117
  "grant_types_supported": ["authorization_code", "refresh_token"],
@@ -209,7 +209,7 @@ REDIRECT_URI="http://localhost:8765/callback"
209
209
  Open the URL in a browser. The flow is:
210
210
  1. The gateway redirects you to your IdP's login page.
211
211
  2. You authenticate at the IdP.
212
- 3. The IdP redirects back to the gateway's `/oauth/callback`.
212
+ 3. The IdP redirects back to the gateway's `/__zuplo/oauth/callback`.
213
213
  4. The gateway renders the consent setup page.
214
214
  5. You click **Authorize**.
215
215
  6. The gateway redirects to your `redirect_uri` with `?code=...&state=...`.
@@ -231,8 +231,8 @@ REDIRECT_URI="http://localhost:8765/callback"
231
231
 
232
232
  1. **Exchange the code for tokens.**
233
233
 
234
- `POST /oauth/token` with the authorization-code grant. Public clients send
235
- `client_id` in the form body; confidential clients use HTTP Basic.
234
+ `POST /__zuplo/oauth/token` with the authorization-code grant. Public clients
235
+ send `client_id` in the form body; confidential clients use HTTP Basic.
236
236
 
237
237
  ```bash
238
238
  TOKEN_RESPONSE=$(curl -s -X POST "${TOKEN_ENDPOINT}" \
@@ -360,7 +360,7 @@ REDIRECT_URI="http://localhost:8765/callback"
360
360
  When you're done testing, revoke the grant.
361
361
 
362
362
  ```bash
363
- curl -s -i -X POST "${GATEWAY}/oauth/revoke" \
363
+ curl -s -i -X POST "${GATEWAY}/__zuplo/oauth/revoke" \
364
364
  -H "content-type: application/x-www-form-urlencoded" \
365
365
  --data-urlencode "token=${NEW_REFRESH_TOKEN}" \
366
366
  --data-urlencode "token_type_hint=refresh_token" \
@@ -45,8 +45,8 @@ OAuth flow:
45
45
  route.
46
46
  - An RFC 7591 Dynamic Client Registration endpoint.
47
47
  - An OAuth Client ID Metadata Document (CIMD) acceptor.
48
- - `/oauth/authorize`, `/oauth/token`, `/oauth/revoke`, and `/oauth/callback`
49
- endpoints.
48
+ - `/__zuplo/oauth/authorize`, `/__zuplo/oauth/token`, `/__zuplo/oauth/revoke`,
49
+ and `/__zuplo/oauth/callback` endpoints.
50
50
 
51
51
  Browser identity is delegated to an OIDC identity provider you configure —
52
52
  Auth0, Okta, or any OIDC discovery-compatible IdP. The IdP authenticates the
@@ -89,16 +89,16 @@ The gateway implements the following standards in their MCP-mandated subsets.
89
89
  | [RFC 8414 — Authorization Server Metadata](https://datatracker.ietf.org/doc/html/rfc8414) | Published at `/.well-known/oauth-authorization-server[/{routePath}]`. |
90
90
  | [OpenID Connect Discovery 1.0](https://openid.net/specs/openid-connect-discovery-1_0.html) | Accepted alongside RFC 8414 as authorization-server discovery (added in the `2025-11-25` MCP revision). |
91
91
  | [RFC 9728 — Protected Resource Metadata](https://datatracker.ietf.org/doc/html/rfc9728) | Published at `/.well-known/oauth-protected-resource/{routePath}` per MCP route. |
92
- | [RFC 7591 — Dynamic Client Registration](https://datatracker.ietf.org/doc/html/rfc7591) | Accepted at `/oauth/register`. |
92
+ | [RFC 7591 — Dynamic Client Registration](https://datatracker.ietf.org/doc/html/rfc7591) | Accepted at `/__zuplo/oauth/register`. |
93
93
  | [OAuth Client ID Metadata Documents (CIMD)](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-client-id-metadata-document-00) | Recommended client identification path per the `2025-11-25` MCP revision. The gateway advertises `client_id_metadata_document_supported: true` and accepts URLs as `client_id` values when CIMD is enabled. |
94
94
  | [RFC 8707 — Resource Indicators](https://datatracker.ietf.org/doc/html/rfc8707) | MCP clients **MUST** include the `resource` parameter on every authorization and token request. The gateway validates that incoming bearer tokens were minted for the route's canonical resource URI. |
95
95
  | [RFC 6750 — Bearer tokens](https://datatracker.ietf.org/doc/html/rfc6750) | `Authorization: Bearer ...` only, header position only — tokens in query strings are rejected. |
96
- | [RFC 7009 — Token Revocation](https://datatracker.ietf.org/doc/html/rfc7009) | Published at `/oauth/revoke`. |
96
+ | [RFC 7009 — Token Revocation](https://datatracker.ietf.org/doc/html/rfc7009) | Published at `/__zuplo/oauth/revoke`. |
97
97
 
98
98
  CIMD is the recommended client identification path going forward; DCR is
99
99
  retained for backwards compatibility with older MCP clients. Both work against
100
- the same `/oauth/register` and AS metadata surface — clients that support either
101
- are accommodated.
100
+ the same `/__zuplo/oauth/register` and AS metadata surface — clients that
101
+ support either are accommodated.
102
102
 
103
103
  ## Downstream flow
104
104
 
@@ -123,7 +123,7 @@ plus the MCP `resource` parameter binding.
123
123
 
124
124
  The flow is the standard MCP authorization handshake. The
125
125
  [`McpGatewayPlugin`](../code-config/overview.mdx) registers the
126
- `/.well-known/...` and `/oauth/...` endpoints automatically.
126
+ `/.well-known/...` and `/__zuplo/oauth/...` endpoints automatically.
127
127
 
128
128
  ## Upstream flow
129
129
 
@@ -282,16 +282,16 @@ full URL catalog.
282
282
  | `/.well-known/oauth-authorization-server` | GET | RFC 8414 AS metadata (gateway-wide). |
283
283
  | `/.well-known/oauth-authorization-server/{routePath}` | GET | RFC 8414 AS metadata (per route, rebinds `issuer`). |
284
284
  | `/.well-known/oauth-protected-resource/{routePath}` | GET | RFC 9728 PRM (per route). |
285
- | `/oauth/register` | POST | RFC 7591 Dynamic Client Registration. |
286
- | `/oauth/authorize` | GET | Gateway-wide authorize endpoint. Requires the `resource` parameter. |
287
- | `/oauth/authorize/{routePath}` | GET | Per-route authorize endpoint. |
288
- | `/oauth/callback` | GET | Browser-login callback from the IdP. |
289
- | `/oauth/setup` | GET, POST | Consent and multi-upstream connect page. |
290
- | `/oauth/token` | POST | Token endpoint. Accepts `authorization_code` and `refresh_token` grants. |
291
- | `/oauth/revoke` | POST | RFC 7009 revocation. |
292
- | `/.well-known/oauth-client/{connection}` | GET | OIDC Client ID Metadata Document for the upstream OAuth client (per upstream). |
293
- | `/auth/connections/{connection}/connect` | GET | Start the upstream OAuth flow. |
294
- | `/auth/connections/{connection}/callback` | GET | Upstream OAuth callback. |
285
+ | `/__zuplo/oauth/register` | POST | RFC 7591 Dynamic Client Registration. |
286
+ | `/__zuplo/oauth/authorize` | GET | Gateway-wide authorize endpoint. Requires the `resource` parameter. |
287
+ | `/__zuplo/oauth/authorize/{routePath}` | GET | Per-route authorize endpoint. |
288
+ | `/__zuplo/oauth/callback` | GET | Browser-login callback from the IdP. |
289
+ | `/__zuplo/oauth/setup` | GET, POST | Consent and multi-upstream connect page. |
290
+ | `/__zuplo/oauth/token` | POST | Token endpoint. Accepts `authorization_code` and `refresh_token` grants. |
291
+ | `/__zuplo/oauth/revoke` | POST | RFC 7009 revocation. |
292
+ | `/__zuplo/.well-known/oauth-client/{connection}` | GET | OIDC Client ID Metadata Document for the upstream OAuth client (per upstream). |
293
+ | `/__zuplo/auth/connections/{connection}/connect` | GET | Start the upstream OAuth flow. |
294
+ | `/__zuplo/auth/connections/{connection}/callback` | GET | Upstream OAuth callback. |
295
295
 
296
296
  The well-known metadata endpoints serve CORS-permissive responses
297
297
  (`Access-Control-Allow-Origin: *`) because browser-resident MCP clients fetch
@@ -77,9 +77,9 @@ can request tokens. The `clientRegistration` option controls how:
77
77
  - **CIMD with DCR fallback (`{ "mode": "auto" }`)** — the default. The gateway
78
78
  publishes a per-upstream
79
79
  [OAuth Client ID Metadata Document](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-client-id-metadata-document-00)
80
- at `/.well-known/oauth-client/{connection}?authProfileId=...` and tells the
81
- upstream that URL is the client ID. If the upstream doesn't accept CIMD, the
82
- gateway falls back to
80
+ at `/__zuplo/.well-known/oauth-client/{connection}?authProfileId=...` and
81
+ tells the upstream that URL is the client ID. If the upstream doesn't accept
82
+ CIMD, the gateway falls back to
83
83
  [RFC 7591 Dynamic Client Registration](https://datatracker.ietf.org/doc/html/rfc7591).
84
84
  Auto mode requires nothing from the upstream provider beyond standard MCP
85
85
  authorization spec support and has no client secrets to rotate.
@@ -139,7 +139,7 @@ message; the user copies it into a browser.
139
139
 
140
140
  Each MCP route proxies to exactly one upstream, so the consent page typically
141
141
  shows one upstream to connect. The consent page is part of the gateway and
142
- renders automatically whenever a user lands at `/oauth/setup` mid-flow.
142
+ renders automatically whenever a user lands at `/__zuplo/oauth/setup` mid-flow.
143
143
 
144
144
  ## Connect-required states
145
145
 
@@ -165,7 +165,7 @@ The full JSON-RPC error payload looks like:
165
165
  "state": "authenticating",
166
166
  "upstreamServerId": "linear",
167
167
  "operationId": "linear-mcp-server",
168
- "authUrl": "https://gateway.example.com/auth/connections/linear/connect?browserTicket=eyJ...&operationId=linear-mcp-server",
168
+ "authUrl": "https://gateway.example.com/__zuplo/auth/connections/linear/connect?browserTicket=eyJ...&operationId=linear-mcp-server",
169
169
  "nextAction": "redirect",
170
170
  "authProfileId": "linear:user-oauth",
171
171
  },
@@ -3,8 +3,9 @@ title: "Local development"
3
3
  sidebar_label: "Local development"
4
4
  description:
5
5
  Run the Zuplo MCP Gateway locally with zuplo dev, bypass your identity
6
- provider with the loopback /oauth/dev-login shortcut, wire up an MCP client
7
- against 127.0.0.1, and recover cleanly from the known workerd restart quirk.
6
+ provider with the loopback /__zuplo/oauth/dev-login shortcut, wire up an MCP
7
+ client against 127.0.0.1, and recover cleanly from the known workerd restart
8
+ quirk.
8
9
  ---
9
10
 
10
11
  The MCP Gateway runs the same way locally as any Zuplo project — `zuplo dev`,
@@ -44,7 +45,7 @@ When configuring an MCP client locally, use `127.0.0.1`:
44
45
  The same applies to any callback or redirect URI you configure with an identity
45
46
  provider for local testing.
46
47
 
47
- ## Bypass your IdP with `/oauth/dev-login`
48
+ ## Bypass your IdP with `/__zuplo/oauth/dev-login`
48
49
 
49
50
  Setting up a real OIDC provider for local development is friction — you'd have
50
51
  to register a localhost callback, manage test users, and so on. The gateway
@@ -68,24 +69,24 @@ OAuth policy:
68
69
  "jwksUrl": "http://127.0.0.1:9000/.well-known/jwks.json",
69
70
  },
70
71
  "browserLogin": {
71
- "url": "http://127.0.0.1:9000/oauth/dev-login",
72
+ "url": "http://127.0.0.1:9000/__zuplo/oauth/dev-login",
72
73
  },
73
74
  },
74
75
  },
75
76
  }
76
77
  ```
77
78
 
78
- When `browserLogin.url` points at `/oauth/dev-login`, the
79
+ When `browserLogin.url` points at `/__zuplo/oauth/dev-login`, the
79
80
  `browserLogin.tokenUrl`, `browserLogin.clientId`, and
80
81
  `browserLogin.clientSecret` options aren't required. The consent page renders
81
82
  normally.
82
83
 
83
84
  :::caution
84
85
 
85
- The `/oauth/dev-login` route returns `403 Forbidden` for any request that
86
- doesn't arrive over loopback. It's not a security risk to leave configured for
87
- production, but it's also not useful — production deployments should use a real
88
- OIDC provider through one of the
86
+ The `/__zuplo/oauth/dev-login` route returns `403 Forbidden` for any request
87
+ that doesn't arrive over loopback. It's not a security risk to leave configured
88
+ for production, but it's also not useful — production deployments should use a
89
+ real OIDC provider through one of the
89
90
  [IdP-specific wrappers](../auth/overview.mdx#identity-providers).
90
91
 
91
92
  :::
@@ -136,9 +137,10 @@ example, with Claude Desktop:
136
137
  ```
137
138
 
138
139
  The client triggers the gateway's OAuth flow on first connect. With
139
- `/oauth/dev-login` configured, the browser tab opens, lands on the consent page
140
- without any IdP login, and you connect each upstream through its normal browser
141
- OAuth flow. Subsequent calls reuse the issued tokens until they expire.
140
+ `/__zuplo/oauth/dev-login` configured, the browser tab opens, lands on the
141
+ consent page without any IdP login, and you connect each upstream through its
142
+ normal browser OAuth flow. Subsequent calls reuse the issued tokens until they
143
+ expire.
142
144
 
143
145
  See [Connect MCP clients](../connect-clients/overview.mdx) for client-specific
144
146
  snippets and the connect URL format.
@@ -31,9 +31,12 @@ export function runtimeInit(runtime: RuntimeExtensions) {
31
31
  ```
32
32
 
33
33
  The plugin registers the OAuth metadata, authorization endpoints, consent page,
34
- and upstream connect callbacks the gateway needs. It's a no-op when no
35
- MCP-related policy is present, so adding it to projects that don't yet use the
36
- gateway has zero runtime cost.
34
+ and upstream connect callbacks the gateway needs. It also serves the read-only
35
+ [MCP Server Registry](../server-registry.mdx) by default. See the
36
+ [`McpGatewayPlugin` reference](../../programmable-api/mcp-gateway-plugin.mdx)
37
+ for all configuration options. The plugin is a no-op when no MCP-related policy
38
+ is present, so adding it to projects that don't yet use the gateway has zero
39
+ runtime cost.
37
40
 
38
41
  ## 2. Define one OAuth policy
39
42
 
@@ -185,10 +188,12 @@ For a worked example with two upstreams and the full file layout, see
185
188
 
186
189
  - [`McpProxyHandler` reference](./mcp-proxy-handler.mdx) — every option and
187
190
  every behavior of the route handler.
191
+ - [ZuploMcpSdk](../../programmable-api/mcp-sdk.mdx) — programmatically control
192
+ MCP tool results from custom handler modules.
188
193
  - [Compatibility dates](./compatibility-dates.mdx) — why `2026-03-01` is
189
194
  required and what older dates break.
190
195
  - [Local development](./local-development.mdx) — dev-loop, loopback URLs, the
191
- `/oauth/dev-login` shortcut, and the `workerd` restart quirk.
196
+ `/__zuplo/oauth/dev-login` shortcut, and the `workerd` restart quirk.
192
197
  - [Add multiple upstream MCP servers](./multi-upstream.mdx) — one project, many
193
198
  upstream MCP servers.
194
199
  - [Curate the tools an upstream exposes](../how-to/curate-tools.mdx) — restrict