Skip to main content
Requires Claude Desktop 1.10628.0 or later. Earlier builds ignore the bootstrapUrl keys.
A bootstrap server is an HTTPS endpoint you host that authenticates each user against your identity provider and returns that user’s configuration as JSON. Use it when your organization doesn’t have MDM, or when configuration varies too widely for per-group profiles: per-user gateway credentials, per-team model allowlists, or per-user OpenTelemetry attribution. When one configuration or a few group-scoped profiles cover your fleet, deploying with MDM is simpler; most MDMs support role-based distribution. When a bootstrap response is available, it is the effective configuration. The MDM profile supplies the trust anchor (bootstrapUrl, optional bootstrapOidc, and the bootstrapEnabled opt-out), and Claude Desktop does not consult MDM for any key the bootstrap server is permitted to set. A bootstrap-settable key that your response omits is treated as unset, not inherited from MDM, so return every key you want applied.
Your bootstrap server is fully trusted. Its response can set inference credentials, the egress allowlist, MCP servers, and every other key in the published schema. Treat compromise of this endpoint as credential compromise: restrict who can deploy it, log every response, and harden it as you would any secrets-issuing service.
Before the server can take over, each device needs the bootstrap keys that point at it. There are two ways to get them onto a device:
  • With MDM: deploy a profile that sets bootstrapUrl (and bootstrapOidc if you use one).
  • Without MDM: give each user a small JSON file containing those keys, which they load from Developer → Configure Third-Party Inference… → Import configuration.
Either way, the bootstrap server supplies everything else after the user signs in. See Installation and setup for the surrounding workflow. If you set deploymentOrganizationUuid, include it in the MDM profile or imported configuration file, and return the same value in your bootstrap response, as a plain UUID without braces in both places. Claude Desktop uses the device-side value at startup to locate sessions, skills, and plugins stored on the device.

How it works

  1. Your managed configuration (MDM or imported) sets bootstrapUrl (and bootstrapOidc if you use a separate identity provider).
  2. At launch, the app authenticates the user via one of two modes and sends GET <bootstrapUrl> with Authorization: Bearer <token>.
  3. Your server validates the token, authorizes the caller against your directory or entitlement source, and returns a JSON object whose keys are the same managed-configuration key names documented in the configuration reference.
  4. The app validates each key against the response schema, drops anything it doesn’t recognize or that fails validation, and applies the result as the effective configuration.
  5. The response is cached in memory (until your expiresAt, or 1 hour by default). The app also re-polls in the background every 30 minutes with a conditional request, so an unchanged configuration costs your server a 304 (see Caching and expiresAt).
If the user has not yet signed in, or the fetch fails with no cached response from this session, the app starts in a degraded state with no inference provider configured and prompts the user to sign in.

Availability

The cached response is held in memory only; there is no on-disk fallback to a previous session’s response. If your bootstrap server is unreachable when Claude Desktop launches, the user stays in the degraded sign-in state until the server recovers. A failed refetch during a running session keeps the in-memory response and retries, so an outage that starts mid-session does not disrupt active users until they relaunch. Run the endpoint across multiple replicas or regions behind a load balancer. Do not rely on response caching for availability: responses are per-user and carry credentials (see the Cache-Control: no-store guidance under Server responsibilities). If your configuration data lives in a database, a read replica of that store improves availability without caching responses. A refetch that returns different values does not change the running session. The app keeps the configuration it launched with (inference credentials, egress allowlist, MCP servers, and renderer state such as the model picker all stay on the boot-time values) and applies the new response at the next app launch. Plan changes accordingly: when rotating an inference credential, keep the previous credential valid until your fleet has relaunched rather than expecting propagation within a refetch interval.

Server responsibilities

Your bootstrap endpoint is a security boundary. The response can carry inference credentials, so an unauthenticated or under-authorized endpoint leaks those credentials to anyone who can reach the URL. Host it on your private network (VPC, corporate intranet, or behind your zero-trust access proxy) rather than the public internet; reachability from managed devices is sufficient. Authenticate. Verify the bearer token’s signature against your identity provider’s JWKS, and check iss, aud, and exp. Reject anything else with 401. Authorize. Verifying the token proves who the caller is, not that they’re entitled to a configuration. Check the caller’s identity claim against your directory before returning a response: Return 403 when the token is valid but the caller is not entitled. Do not authorize on email or preferred_username alone; those claims are mutable and may be absent for guest or external-identity users. Key the response on the caller when configuration needs to differ. A single default profile returned to every entitled user is valid; vary by user or group only where you need per-user credentials, model allowlists, or telemetry attribution.

Mapping groups to profiles

The common pattern is one profile per directory group or app role. For Entra, define an app role on the registration (for example cowork-power-user), assign it to a group via Enterprise applications → Users and groups, and select the profile from the token’s roles claim. For Okta, the equivalent is a groups claim on your custom authorization server; match on payload.groups. Moving a user between groups in your directory is picked up at the next refetch with no profile re-push to devices; the new configuration takes effect when the user’s app next launches. A reference Node.js handler showing token validation, role-based authorization, and profile selection:
Set Cache-Control: no-store on the response. Without it, a reverse proxy or CDN between the app and your endpoint may cache one user’s credentials and serve them to the next.

Authentication

The bootstrap request always carries a bearer token; there is no unauthenticated mode. There are two ways to obtain that token, chosen by whether you set bootstrapOidc in MDM:

Separate identity provider (PKCE)

1

Register a public client in your identity provider

Register a native or public application with a loopback redirect URI and no client secret. The registration is identical to the one used for gateway single sign-on; if you already have that, reuse it. See the provider notes below for redirect-URI specifics.For Microsoft Entra ID, also set an Application ID URI on the registration (App registration → Expose an APISet; accept the default api://CLIENT_ID). The CLIENT_ID/.default scope in the next step does not resolve without it.
2

Choose the scope your server will validate

The app sends the OAuth access token as the bearer. Your server validates that token’s aud, so the scope you request must produce a token whose audience your server accepts. This is provider-specific:Include offline_access so the app receives a refresh token and can renew silently between launches.
For Entra, use the bare-GUID form CLIENT_ID/.default, not api://CLIENT_ID/.default. The api:// form works on the initial authorize but fails on the refresh grant with AADSTS90009 when the client and resource are the same application.
3

Validate the token in your server

See Server responsibilities. What the token’s iss and aud look like depends on your provider:Entra token version. A new Entra app registration emits v1-format access tokens by default, with iss = https://sts.windows.net/TENANT/ and aud = api://CLIENT_ID. Set the accepted-token-version field in the registration’s Manifest to 2 so tokens match the table above. The portal shows this field as either accessTokenAcceptedVersion or api.requestedAccessTokenVersion depending on the manifest view; set whichever you see. If you cannot change it, your server must accept both the v1 and v2 forms.Group and role claims. Entra does not emit groups or roles in access tokens by default. Enable the groups claim under App registration → Token configuration, or define App roles and assign users via Enterprise applications. The oid claim is always present. For Okta, add a groups claim on your custom authorization server with a group filter.
4

Configure and export from Claude Desktop

Install Claude Desktop on an admin workstation (see Installation). From the menu bar, open Developer → Configure Third-Party Inference…. In the Source section, fill in the Bootstrap config URL card:Click Sign in to test against your typed values. Once authenticated, the card shows the keys your server supplied. Click Export and choose the template format your MDM expects (.mobileconfig, ADMX, Intune OMA-URI JSON, or .reg). See Deploy the configuration for per-platform instructions.

Provider notes

Use 127.0.0.1, not localhost. This page covers only the bootstrap sign-in. Authentication for inference is independent of bootstrap and depends on what your response provisions; see the relevant provider page (gateway SSO, Google Cloud’s Agent Platform, Amazon Bedrock, Microsoft Foundry).

Bootstrap server as authorization server (device code)

Set only bootstrapUrl in MDM. The app discovers your authorization endpoints via RFC 8414 and runs an RFC 8628 device-code grant. The bearer is reused for inference when inferenceGatewayBaseUrl shares the bootstrapUrl origin and inferenceCredentialKind is interactive, so the user signs in once for both.
1

Publish RFC 8414 discovery metadata

Serve a metadata document under the bootstrapUrl path. If bootstrapUrl ends in /bootstrap or /user/bootstrap, that suffix is stripped to form the issuer base.
Every endpoint URL must share the bootstrapUrl origin. Metadata that points off-origin is rejected.
2

Implement the device-code grant

POST to device_authorization_endpoint returns:
verification_uri and verification_uri_complete must share the bootstrapUrl origin; federate behind your own pages rather than returning an upstream provider’s URL directly. The app opens the verification URL in the user’s browser and shows the user code.The app polls token_endpoint with grant_type=urn:ietf:params:oauth:grant-type:device_code and the device_code. Return {"error":"authorization_pending"} until the user approves, then:
The polling interval is clamped between 1 and 30 seconds; the grant times out after 5 minutes; token TTL is clamped between 5 minutes and 24 hours.
3

Serve the configuration endpoint

On GET <bootstrapUrl> with a valid bearer, look up the user from the token claims and return their configuration (see the HTTP contract).

The HTTP contract

Request

The path is whatever you set in bootstrapUrl; there is no required path. Redirects are not followed: a 3xx is treated as an error so a same-origin open redirect cannot exfiltrate the bearer. The request times out after 30 seconds.

Response

Return 200 OK with Content-Type: application/json and a JSON object whose keys are a subset of the published response schema. Keys use the exact managed-configuration key names. Unknown keys, keys that fail validation, and keys outside that schema are silently dropped; one bad key never invalidates the rest.
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.

Response schema

The full set of bootstrap-settable keys is published as a machine-readable JSON Schema, generated from the same source as the configuration reference and updated with each release: Reference the schema with "$schema" in your response template, or with # yaml-language-server: $schema=… in YAML, for autocomplete and validation. The response can supply any key in that schema, including inference credentials, model allowlists, MCP servers, the egress allowlist, telemetry endpoints, and the organization banner.
Organization plugins and skills can be delivered over the network by returning organizationPluginsUrl in the bootstrap response when using device-code mode, or through the filesystem org-plugins/ directory described in Connectors and extensions. Network delivery is not available in PKCE mode.
A small set of keys are structurally excluded and ignored if returned:
  • bootstrapUrl, bootstrapOidc, bootstrapEnabled: the trust anchor cannot redirect itself.
  • inferenceCredentialHelper and its related settings: every key whose Availability column reads MDM only in the configuration reference is ignored in a bootstrap response.
  • Loopback hosts (127.0.0.1, localhost, [::1]) in any URL-valued key, regardless of scheme.
managedMcpServers entries are not restricted by transport in version 1.19367.0 and later: remote (http/sse) servers, local stdio commands, and the built-in microsoft365 and websearch connectors can all be delivered in the bootstrap response. Earlier versions accept only remote entries and drop the rest. Because a stdio entry names a command that runs on the device, a bootstrap response can start local processes — part of why the warning at the top of this page says to treat this endpoint as fully trusted. Entries whose server URL or OAuth authorization-server URL is loopback or non-HTTPS are still dropped, and the desktop log (see Troubleshooting) records which keys were dropped and why.

Caching and expiresAt

Omitted → cache for 1 hour. A number ≥ 10¹² is read as Unix epoch milliseconds; below that, seconds.A failed re-fetch keeps the last good response from the current session and retries; the app only enters the degraded state when there has never been a usable response this session.

Origin pinning

When the bootstrap server is its own authorization server (no bootstrapOidc), 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. When 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.

MDM configuration keys

Set this to use a separate identity provider (Microsoft Entra ID, Okta, Ping, or any compliant OIDC provider) for the bootstrap sign-in. The app runs an authorization-code-with-PKCE flow in the system browser. Omit to use device-code mode against the bootstrap server’s own origin.This is an object-typed key — in an MDM profile it is a single JSON-string value, not separate keys with dotted names like bootstrapOidc.clientId. Writing the sub-fields as separate registry values causes the app to silently fall through to device-code mode.
No inferenceProvider is needed in the MDM profile when using bootstrap; the response supplies it.

Troubleshooting