Deploy with a bootstrap server changedthird-party/claude-desktop/bootstrap
Nearest release: v2.1.239, published 2 hours before this site recorded the change. Shown because the two are within 24 hours of each other. Nothing here says the release caused the edit.
Recorded here
Lines+17added
Lines−17removed
From line
121
where the diff opens
First seen
14 Aug 2026
this site's first read of the page
Recorded edits24to this page, all time
The whole hunk
from line 121, old and new numbered
/
from line 121
121121
122122The bootstrap request is always authenticated: either each user signs in and the app sends their bearer token, or the device sends request headers you configure. The mode is chosen by which keys you set alongside `bootstrapUrl`:
123123
124| Mode | When to use it | MDM keys |
125| ---------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------- |
126| **Separate identity provider (PKCE)** | Users sign in through your existing OIDC provider (Microsoft Entra ID, Okta, Ping, or any compliant provider). The app runs an OAuth authorization-code grant with PKCE in the system browser. | `bootstrapUrl` and `bootstrapOidc` |
127| **Bootstrap server as authorization server (device code)** | Your bootstrap server (or the gateway it fronts) implements RFC 8414 discovery and the RFC 8628 device-code grant. One sign-in covers both the configuration fetch and inference when they share an origin. | `bootstrapUrl` only |
128| **Request headers (no per-user sign-in)** | The endpoint authenticates the device or a service account rather than the user: a static `Authorization: Basic …` or API-key header, or a short-lived token a script on the device fetches from your secrets manager. No browser step; the response cannot vary by signed-in user unless your headers identify one. | `bootstrapUrl` and `bootstrapHeaders` and/or `bootstrapHeadersHelper` |
124| Mode | When to use it | MDM keys |
125| ---------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ |
126| **Separate identity provider (PKCE)** | Users sign in through your existing OIDC provider (Microsoft Entra ID, Okta, Ping, or any compliant provider). The app runs an OAuth authorization-code grant with PKCE in the system browser. | `bootstrapUrl` and `bootstrapOidc` |
127| **Bootstrap server as authorization server (device code)** | Your bootstrap server (or the gateway it fronts) implements RFC 8414 discovery and the RFC 8628 device-code grant. One sign-in covers both the configuration fetch and inference when they share an origin. | `bootstrapUrl` only |
128| **Request headers (no per-user sign-in)** | The endpoint authenticates the device or a service account rather than the user: a static `Authorization: Basic …` or API-key header, or a short-lived token a script on the device fetches from your secrets manager. No browser step; the response cannot vary by signed-in user unless your headers identify one. | `bootstrapUrl` and `bootstrapHeaders` and/or `bootstrapHeadersHelper` (1.32885.1 or later) |
129129
130130### Separate identity provider (PKCE)
131131
from line 237
237237 { "access_token": "eyJhbGciOiJSUzI1NiIs...", "expires_in": 3600 }
238238 ```
239239
240 The polling interval is clamped between 1 and 30 seconds; the grant times out after 5 minutes; the token lifetime you return is clamped between 5 minutes and 30 days.
240 The polling interval is clamped between 1 and 30 seconds; the grant times out after 5 minutes; the token lifetime you return is clamped between 5 minutes and 30 days (24 hours before 1.17377.1).
241241
242 When `inferenceGatewayBaseUrl` shares the `bootstrapUrl` origin, so the same sign-in also serves inference, you may also return a `refresh_token` (optionally with `refresh_token_expires_in` in seconds): as the access token nears expiry during use, Claude Desktop renews it with an RFC 6749 `grant_type=refresh_token` POST to your `token_endpoint` rather than interrupting the user. The configuration fetch at launch still asks the user to sign in if the access token itself has already expired. Answer `400` with `{"error":"invalid_grant"}` to revoke the refresh token and require a fresh sign-in.
242 When `inferenceGatewayBaseUrl` shares the `bootstrapUrl` origin, so the same sign-in also serves inference, you may also return a `refresh_token` (optionally with `refresh_token_expires_in` in seconds): as the access token nears expiry during use, Claude Desktop 1.34493.0 and later renews it with an RFC 6749 `grant_type=refresh_token` POST to your `token_endpoint` rather than interrupting the user. The configuration fetch at launch still asks the user to sign in if the access token itself has already expired. Answer `400` with `{"error":"invalid_grant"}` to revoke the refresh token and require a fresh sign-in.
243243 </Step>
244244
245245 <Step title="Serve the configuration endpoint">
from line 249
249249
250250### Request headers (no per-user sign-in)
251251
252Set `bootstrapHeaders` to a JSON object of headers to send on every bootstrap fetch, or `bootstrapHeadersHelper` to the absolute path of an executable that prints such an object on stdout (run with no arguments; its output is cached for a few minutes and merged over the static headers, the helper winning on a conflict). When either key is set and `bootstrapOidc` is not, the app treats the headers as sufficient authentication and fetches the configuration without prompting the user to sign in. If your server answers `401` or `403`, the app discards the cached helper output so the next attempt re-runs the helper, and offers the user sign-in if your server also implements the [device-code grant](#bootstrap-server-as-authorization-server-device-code); a signed-in user's bearer token then replaces any `Authorization` header you configured. Both keys are read from device management or the local configuration file only, never from the bootstrap response, and header values are masked in the diagnostic report. [Origin pinning](#origin-pinning) applies in this mode exactly as in device-code mode. Use this instead of embedding `user:password@` in `bootstrapUrl`, which the app refuses.
252Requires Claude Desktop 1.32885.1 or later. Set `bootstrapHeaders` to a JSON object of headers to send on every bootstrap fetch, or `bootstrapHeadersHelper` to the absolute path of an executable that prints such an object on stdout (run with no arguments; its output is cached for a few minutes and merged over the static headers, the helper winning on a conflict). When either key is set and `bootstrapOidc` is not, the app treats the headers as sufficient authentication and fetches the configuration without prompting the user to sign in. If your server answers `401` or `403`, the app discards the cached helper output so the next fetch (the next background check, or a relaunch) re-runs the helper. At launch the app also shows a sign-in prompt; that sign-in succeeds only if your server implements the [device-code grant](#bootstrap-server-as-authorization-server-device-code), so a headers-only server should return `401`/`403` only for a genuinely unusable credential. A `401`/`403` on a background check keeps the running configuration and retries at the next check without prompting. A signed-in user's bearer token replaces any `Authorization` header you configured. Both keys are read from device management or the local configuration file only, never from the bootstrap response, and header values are masked in the diagnostic report. [Origin pinning](#origin-pinning) applies in this mode exactly as in device-code mode. Use this instead of embedding `user:password@` in `bootstrapUrl`, which the app refuses.
253253
254254## The HTTP contract
255255
from line 283
283283}
284284```
285285
286| Status | App behavior |
287| ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
288| `200` | Parse and apply. |
289| `304` | Re-serve the cached response (the app sends `If-None-Match` when it has one). |
290| `401`, `403` | Discard the cached token and prompt the user to sign in again. A `401` on a background refresh keeps the running session and retries without prompting. Return `401` when the token is missing, expired, or the wrong audience; return `403` when the token is valid but the caller is not entitled. |
291| Other non-2xx, or `3xx` | Fetch error. Falls back to the last good response from this session if one exists; otherwise the app stays in the degraded sign-in state. |
286| Status | App behavior |
287| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
288| `200` | Parse and apply. |
289| `304` | Re-serve the cached response (the app sends `If-None-Match` when it has one). |
290| `401`, `403` | Discard the cached token and prompt the user to sign in again. A `401` on a background refresh keeps the running configuration. When the same sign-in also serves inference, the app treats it as an ended session and asks the user to sign in again (1.34493.0 and later); otherwise it retries at the next check without prompting. Return `401` when the token is missing, expired, or the wrong audience; return `403` when the token is valid but the caller is not entitled. |
291| Other non-2xx, or `3xx` | Fetch error. Falls back to the last good response from this session if one exists; otherwise the app stays in the degraded sign-in state. |
292292
293293<Warning>
294294 A `200` that is not a JSON object (an empty body, an HTML page from a captive portal or load balancer, or a JSON array) is a parse error. Make sure intermediate proxies do not rewrite the response.
from line 306
306306The response can supply any key in that schema, including inference credentials, model allowlists, MCP servers, the egress allowlist, telemetry endpoints, and the organization banner.
307307
308308<Note>
309 Organization plugins and skills can be delivered over the network by returning `organizationPluginsUrl` in the bootstrap response when using [device-code mode](#bootstrap-server-as-authorization-server-device-code), or through the filesystem `org-plugins/` directory described in [Connectors and extensions](/docs/third-party/claude-desktop/extensions). Network delivery is not available in PKCE mode.
309 Organization plugins and skills can be delivered over the network by returning `allowedPluginMarketplaces` in the bootstrap response (see [Plugin marketplaces](/docs/third-party/claude-desktop/extensions#plugin-marketplaces-admin)), or through the filesystem `org-plugins/` directory described in [Connectors and extensions](/docs/third-party/claude-desktop/extensions).
310310</Note>
311311
312312A small set of keys are **structurally excluded** and ignored if returned:
from line 352
352352
353353### Origin pinning
354354
355When no `bootstrapOidc` is set (device-code or request-headers mode), the response is fenced: `inferenceGatewayBaseUrl`, `inferenceVertexBaseUrl`, `inferenceBedrockBaseUrl`, and `organizationPluginsUrl` must share the `bootstrapUrl` origin or the field is dropped. A compromised configuration response cannot redirect inference to an attacker-controlled host because the only host it can name is the one the user already authenticated to.
355When no `bootstrapOidc` is set (device-code or request-headers mode), the response is fenced: `inferenceGatewayBaseUrl`, `inferenceVertexBaseUrl`, and `inferenceBedrockBaseUrl` must share the `bootstrapUrl` origin or the field is dropped. A compromised configuration response cannot redirect inference to an attacker-controlled host because the only host it can name is your bootstrap server's own origin.
356356
357357When you supply `bootstrapOidc`, your configuration server and gateway are independent hosts you control, so origin pinning is disabled and the response can name any HTTPS host. In this mode the bootstrap server's integrity is the only control on where inference and MCP traffic are sent.
358358
No line in this hunk matches that.