Docs

Administration

IdP-Managed MCP Access ​

Let your identity provider decide who can use Bumpkit from MCP clients like Claude and Codex, with no Bumpkit sign-in or consent screen, and setup guides for Okta, PingFederate, Descope, Janssen, ThunderID and Athenz.

Your identity provider decides who can use Bumpkit's MCP server from MCP clients like Claude and Codex. Employees sign in to the MCP client with corporate SSO and start using Bumpkit tools. They never see a Bumpkit sign-in or consent screen, and Bumpkit checks their membership on every request.

This is the MCP enterprise-managed authorization extension (io.modelcontextprotocol/enterprise-managed-authorization). Your identity provider issues a short-lived Identity Assertion JWT Authorization Grant (ID-JAG) for Bumpkit, the MCP client trades it at Bumpkit's token endpoint for an access token, and Bumpkit maps the person to a member of your workspace.

Beta, early access. Flag: idp_managed_mcp. It also needs single sign-on (flag sso) with an OIDC connection turned on. Until your workspace has access, the IdP-managed MCP access card doesn't appear on the Single sign-on page and /v1/identity/sso/managed-mcp answers 403 FEATURE_EARLY_ACCESS with a link to request it. Request access at https://dashboard.bumpkit.dev/early-access?feature=idp_managed_mcp.

When to use it ​

  • You want one place to grant and revoke access. Assign Bumpkit to people or groups in your identity provider; remove them there and their MCP access ends.
  • You don't want each employee to approve a consent screen. Admins approve Bumpkit once for the whole organization.
  • You want MCP access to follow corporate SSO policy. Sign-in, MFA and device rules stay in your identity provider.

Keep using per-person sign-in (the default in Connect Claude, Codex or Grok) if your identity provider can't issue ID-JAGs or your MCP client doesn't support enterprise-managed authorization yet. You can run both side by side until you require IdP-managed access.

How it works ​

  1. An employee signs in to the MCP client with corporate SSO.
  2. When the client needs Bumpkit, it asks your identity provider for an ID-JAG for Bumpkit. The identity provider checks that the person is assigned to Bumpkit.
  3. The client sends the ID-JAG, with the client ID and secret you registered in Bumpkit, to https://bumpkit.dev/oauth/token.
  4. Bumpkit checks the signature against your identity provider's published keys, checks the ID-JAG is for Bumpkit and hasn't been used before, finds the member, and returns an access token for https://bumpkit.dev/mcp. The token lasts up to 1 hour, and never more than 1 hour past the ID-JAG's own expiry. There's no refresh token: the client gets a new ID-JAG when it needs a new token.
  5. Every MCP request re-checks that the member is still active in the workspace, that IdP-managed access is still on, and that the identity provider is still your SSO provider. The member's current role applies.

Set it up ​

You need admin access to your identity provider and an owner or admin role in Bumpkit; the first single sign-on setup needs an owner. Only an owner can change the tenant or Athenz domain, turn this off, or stop requiring it.

1. Turn on single sign-on with OIDC ​

IdP-managed access trusts the same identity provider your workspace already uses for OIDC single sign-on. The issuer in every ID-JAG must match the OIDC issuer URL in Settings → Single sign-on exactly. Set up and verify your email domains too: Bumpkit uses them to match people the first time.

2. Turn on IdP-managed MCP access ​

In Settings → Single sign-on, find the IdP-managed MCP access card, check Accept ID-JAGs from this identity provider and click Save. The card shows the values your identity provider needs:

Value on the card Example Where it goes
Issuer https://acme.okta.com Your OIDC issuer; the iss of every ID-JAG
Audience https://bumpkit.dev The ID-JAG's aud: Bumpkit's authorization server
Resource https://bumpkit.dev/mcp The resource the ID-JAG is for
Token endpoint https://bumpkit.dev/oauth/token Where the MCP client trades the ID-JAG
Audience tenant (aud_tenant) Your workspace ID Optional; if the identity provider sends it, it must be this workspace ID or the Audience value
Scopes mcp, mcp:read See Roles and scopes

Then register each MCP client your organization uses. Under MCP clients, type a name such as Claude and click Register client. Bumpkit shows the client ID (bkmcp_ema_...) and client secret (bkmcp_emas_...). If your identity provider always puts its own client ID in the ID-JAG, as ThunderID and Athenz do, enter that ID under Client ID from your IdP when you register: Bumpkit uses it as the client ID and still generates the secret. A client ID can be up to 255 letters, digits and . _ : / @ + ~ -, and each one can be registered once per workspace. Copy the secret now: it's shown once and Bumpkit stores only a hash. Put the client ID in your identity provider (step 3) and give the ID and secret to whoever configures the MCP client's enterprise-managed authorization settings. Remove a client to cut off every token issued to it.

From the CLI:

Terminal
bumpkit identity sso managed-mcp view
bumpkit identity sso managed-mcp clients add Claude
bumpkit identity sso managed-mcp clients add ThunderID --client-id thunder-app

and bumpkit identity sso managed-mcp set --enabled [--required] [--tenant TENANT] [--role-domain DOMAIN] --yes to turn it on. Identity provider tenant (--tenant) is only for issuers that serve several tenants from one issuer and put a tenant claim in ID-JAGs. Athenz domain (--role-domain) is only for Athenz. See CLI and MCP for every command.

3. Add Bumpkit as a resource app in your identity provider ​

In your identity provider, set Bumpkit up as the resource (the app the MCP client gets access to), point it at the audience and resource above, enter the client ID from step 2 for the MCP client, define the scopes mcp and mcp:read, and assign the people or groups who may use Bumpkit. Follow the guide for your identity provider.

Before you roll it out, check one ID-JAG. Paste it under Test an ID-JAG on the card and click Check, or pipe it to bumpkit identity sso managed-mcp test. Bumpkit says whether it would accept it, as which member and role and with which scope, or which error to fix. The test doesn't use the ID-JAG up, so the client can still trade it.

4. Optionally require it ​

Check Require it for verified domains and click Save (or add --required). For people whose email is on one of your verified domains, Bumpkit then turns off its own sign-in for MCP clients:

  • New sign-ins and consent through Bumpkit's sign-in page are refused with access_denied.
  • MCP connections they already approved stop working on their next request, and so do their refresh tokens.
  • Their personal API keys can't connect to https://bumpkit.dev/mcp; the 401 says access_denied. API keys still work with the CLI and the REST API.

This applies to everyone whose email is on a domain your workspace verified, whichever workspace they use. Requiring it needs IdP-managed access turned on and at least one verified domain.

What employees do ​

  1. Sign in to the MCP client with corporate SSO, the way your organization set it up.
  2. Ask the client to use a Bumpkit tool, like status or release_check.
  3. That's it: there's no Bumpkit sign-in, workspace picker or Allow button. The client connects as them, in your workspace, with their role.

The first time, Bumpkit matches the person to a member by the identity provider's account ID if they've signed in to Bumpkit with SSO before, or else by their email. Email matching needs the ID-JAG to carry email with email_verified: true, on one of your verified domains. If there's no member yet and Create accounts on first sign-in is on for your SSO connection, Bumpkit adds them with the Role for new members. After that, the identity provider account and the member stay linked, and Bumpkit never moves the link to another member. A linked member doesn't need a verified domain or an email in the ID-JAG, so removing a domain doesn't cut them off; deactivate them or clear their link to do that. A deactivated member is refused before anything else is checked. Single sign-on and IdP-managed access share one link and the same rule, so signing in once with either links both. Changing the OIDC issuer, client ID or Identity provider tenant clears every link, and people link again by verified email the next time they sign in. To clear one person's link, see single sign-on. Once you set a tenant, dashboard sign-in also needs a matching tenant claim in ID tokens. Bumpkit only matches by email on domains this workspace verified, and a domain can be verified by one workspace only.

Offboarding ​

  • With SCIM: when your identity provider deactivates someone, Bumpkit refuses their next MCP request.
  • Without SCIM: once you unassign or deactivate someone in your identity provider, it stops issuing them ID-JAGs, so they can't get new tokens. A token they already have works until it expires, up to 1 hour, unless you also remove them on the Team page, which stops their next request.
  • Turning off IdP-managed access, changing the OIDC issuer, or removing the client stops every token issued through it on the next request.
  • Removing a member in Bumpkit stops their tokens on the next request and keeps them out, even if Create accounts on first sign-in is on and your identity provider still grants them access. To bring them back, invite them again or provision them through SCIM. They join with the invited role, and a canceled or expired invitation doesn't bring them back.

Roles and scopes ​

A member's role comes from Bumpkit: from their SCIM group mapping, from the role you gave them on the Team page, or from the connection's Role for new members for people added on first use. The identity provider can only narrow access, never widen it.

Scope in the ID-JAG Access
mcp The member's role
mcp:read Read-only: members who can make changes, admins included, act as viewer, and the client lists only read tools
No scope claim Same as mcp
Scopes, none of them Bumpkit's Refused with invalid_scope

If both scopes are present, mcp wins. Athenz role scopes map the same way, only for the Athenz domain set on the card: <domain>:role.mcp is mcp and <domain>:role.mcp-read is mcp:read. Roles from any other domain are ignored. A client may ask for a narrower scope on the token request, for example scope=mcp:read; asking for more than the ID-JAG grants is refused.

What Bumpkit accepts ​

Most identity providers set these for you. Use this table when an ID-JAG is refused.

Part Requirement
typ header oauth-id-jag+jwt
Signature RS256, RS384, RS512, PS256, PS384, PS512, ES256, ES384, ES512 or EdDSA, with a key from the issuer's published keys. RSA keys need at least 2048 bits
iss Exactly your workspace's OIDC issuer URL. Bumpkit finds the keys at <iss>/.well-known/openid-configuration, or <iss>/.well-known/oauth-authorization-server
aud Exactly https://bumpkit.dev (a one-element array is fine)
client_id A client ID you registered in this workspace, and the same one the MCP client sends
resource Optional; if present, every value must be https://bumpkit.dev/mcp
cnf Not accepted: sender-constrained ID-JAGs are refused
tenant Only for identity providers that serve several tenants from one issuer: it must equal the Identity provider tenant you set on the card, and an ID-JAG without it is refused once you set one
sub, jti, exp, iat Required. Each jti is accepted once
Lifetime exp at most 1 hour after iat; clocks may differ by up to 60 seconds
scope Optional; see Roles and scopes
aud_tenant Optional; if present it must be your workspace ID or https://bumpkit.dev. The workspace always comes from the registered client
email, email_verified Optional; used to match a member the first time

Identity provider guides ​

These identity providers document how to issue ID-JAGs. Their consoles change, so each guide links the provider's own steps and lists the Bumpkit values to enter. Whatever the provider, check the result with Test an ID-JAG.

Okta (Cross App Access) ​

Okta calls this Cross App Access (XAA). Okta's Cross App Access overview says it's available to orgs subscribed to its Single Sign-On product.

  1. Use your Okta org URL as the issuer. Okta's org authorization server issues ID-JAGs, so the OIDC issuer URL in Bumpkit must be your org URL, like https://acme.okta.com, not a custom authorization server such as https://acme.okta.com/oauth2/default. If your Bumpkit SSO uses a custom authorization server, switch it to the org URL first.
  2. Turn on Cross App Access for Bumpkit's app. Following Configure the resource app, open the OIDC app you use for Bumpkit sign-in under Applications and Resources → Applications, go to Machine Assignments → Callers, click Edit next to Cross App Access (XAA) and select Enable. Enter the Audience value from Bumpkit (https://bumpkit.dev) as the Issuer URL. Leave Audience/tenant ID empty, or enter the workspace ID shown as Audience tenant on the card; confirm with Test an ID-JAG. Add the scopes mcp and mcp:read, and click Save.
  3. Connect the MCP client. Following Configure the Cross App Access connection, go to Directory → AI Agents, select the agent for your MCP client, open Resource connections and click Add resource connection. Select the Bumpkit app and Enable, set Resource indicator to https://bumpkit.dev/mcp, set AI agent's client ID registered in this app to the bkmcp_ema_... client ID from Bumpkit, choose which scopes it may request, and click Add. To register the agent itself, see Manage Cross App Access connections.
  4. Assign people. Assign the people or groups who may use Bumpkit to the app, as you do for sign-in.

Okta documents a limit of 250 ID-JAGs per user, per resource app, per month, and says each XAA user must be a licensed, active SSO user. Bumpkit's access tokens last up to 1 hour, so a client needing access all day asks for about one ID-JAG an hour: plan for that against the cap, or ask Okta about higher volumes.

PingFederate 13.1 and later ​

PingFederate 13.1 issues ID-JAGs through OAuth token exchange. Follow Ping's Configuring a refresh token to ID-JAG exchange, with these Bumpkit values:

  • SP connection: on General Info, set Partner's Entity ID to https://bumpkit.dev. PingFederate uses it as the ID-JAG's aud when the client sends no audience.
  • Protocol Settings: add https://bumpkit.dev/mcp as a resource URI and, under Allowed Requested Token Types, select Identity Assertion JWT (ID-JAG).
  • Token Lifetime: keep it at 1 hour or less.
  • Client ID: the ID-JAG's client_id must be a client ID registered in Bumpkit. Ping's guide doesn't say how the claim is set: if Ping sends its own client ID, register a client with that ID under Client ID from your IdP. Check it with Test an ID-JAG.

Ping's guide covers the token processor, the processor policy and enabling token exchange on the OAuth client. Its 13.1 release notes list the ID-JAG changes.

Descope ​

Descope issues ID-JAGs for third-party MCP servers. Follow Descope's Issue ID-JAGs for your agents, with these Bumpkit values:

  • Issuer: your Descope issuer, https://api.descope.com/v1/apps/<ProjectID> or your custom domain, must be the OIDC issuer URL in Bumpkit.
  • Resource: create a Resource of type API with the Resource identifier https://bumpkit.dev/mcp, exactly, and add the scopes mcp and mcp:read.
  • Cross App Access: turn on Enable and set Authorization server URL to https://bumpkit.dev (Discover finds it). Set Tenant ID in target to your Bumpkit workspace ID, the Audience tenant on the card. If it's left empty, Descope may send its own tenant ID, which Bumpkit refuses: confirm with Test an ID-JAG.
  • Client ID: under the client's Cross App Access Targets, map the Bumpkit Resource and enter the bkmcp_ema_... client ID from Bumpkit.
  • Policy: add a Delegated access (token exchange) policy that lets your users or agents reach the Bumpkit Resource with the scopes you choose. Without one, the exchange fails.

Janssen ​

The Janssen Server documents its ID-JAG settings in the Janssen Auth Server configuration properties, including idJagLifetime, the lifetime of the ID-JAGs it issues (300 seconds by default). Its docs don't have a step-by-step guide for issuing ID-JAGs to another authorization server yet, so configure the client with these Bumpkit values and check the result with Test an ID-JAG:

  • Issuer: the Janssen issuer must be the OIDC issuer URL in Bumpkit.
  • Audience: https://bumpkit.dev. Resource: https://bumpkit.dev/mcp.
  • Client ID: the bkmcp_ema_... client ID from Bumpkit. Scopes: mcp or mcp:read.
  • Lifetime: keep idJagLifetime at 3600 seconds or less.

ThunderID ​

ThunderID issues ID-JAGs through token exchange. Its guide, Issue identity assertions, is published with its documentation source. Follow it with these Bumpkit values:

  • Application or agent: on the Advanced tab, turn on Identity assertions (ID-JAG) and add https://bumpkit.dev under Allowed audiences. Keep Assertion validity at 3600 seconds or less (300 by default). The client must be confidential.
  • Token exchange request: the client sends audience=https://bumpkit.dev, resource=https://bumpkit.dev/mcp and scope=mcp or scope=mcp:read.
  • Client ID: ThunderID puts the requesting app's own client ID in the ID-JAG's client_id. Register a client in Bumpkit with that ID under Client ID from your IdP (--client-id), and give the MCP client that ID with the secret Bumpkit generates. Check with Test an ID-JAG before rolling out.
  • Issuer: the ThunderID issuer must be the OIDC issuer URL in Bumpkit.

Athenz ​

Athenz ZTS issues ID-JAGs in exchange for an ID token. Its token exchange requirements describe the request and the policy it needs. With Bumpkit:

  • Roles: in your Athenz domain, create the roles mcp (full access) and mcp-read (read-only) and add the people who may use Bumpkit. Request them as scope=<domain>:role.mcp or <domain>:role.mcp-read; Set the domain as Athenz domain on the card (--role-domain); Bumpkit maps that domain's roles to mcp and mcp:read and ignores other domains.
  • Policy: grant the requesting principal the action zts.jag_exchange on <domain>:role.mcp and <domain>:role.mcp-read.
  • Audience: send audience=https://bumpkit.dev.
  • Issuer and client ID: the ZTS issuer must be the OIDC issuer URL in Bumpkit, and the ID-JAG's client_id, which Athenz sets to the requesting service's client ID, must be registered in Bumpkit under Client ID from your IdP. Check both with Test an ID-JAG.

For MCP client developers ​

Bumpkit advertises enterprise-managed authorization in its OAuth metadata. https://bumpkit.dev/.well-known/oauth-authorization-server lists urn:ietf:params:oauth:grant-type:jwt-bearer in grant_types_supported, urn:ietf:params:oauth:grant-profile:id-jag in authorization_grant_profiles_supported, client_secret_basic and client_secret_post in token_endpoint_auth_methods_supported, the scopes mcp and mcp:read, and the extension under extensions. https://bumpkit.dev/.well-known/oauth-protected-resource lists the same scopes and extension.

Trade the ID-JAG at the token endpoint:

Terminal
curl -X POST https://bumpkit.dev/oauth/token \
  -u "$BUMPKIT_MCP_CLIENT_ID:$BUMPKIT_MCP_CLIENT_SECRET" \
  -d grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer \
  --data-urlencode "assertion=$ID_JAG" \
  -d resource=https://bumpkit.dev/mcp

The client authenticates with HTTP Basic or with client_id and client_secret in the form. resource and scope are optional; resource, if sent, must be https://bumpkit.dev/mcp. The response has access_token, token_type Bearer, expires_in of at most 3600 and the granted scope, with no refresh_token. Send the token to https://bumpkit.dev/mcp as Authorization: Bearer .... Errors use the standard OAuth error and error_description; see Troubleshooting.

A client that declares the extension in its MCP request's _meta client capabilities and calls /mcp without a token gets a 401 whose message names the token endpoint and grant to use.

CLI and MCP ​

CLI MCP tool What it does
bumpkit identity sso managed-mcp view identity_sso_managed_mcp_view Whether it's on or required, the issuer, audience, resource, token endpoint, audience tenant, scopes and registered clients, without secrets
bumpkit identity sso managed-mcp set --enabled [--required] [--tenant TENANT] [--role-domain DOMAIN] --yes identity_sso_managed_mcp_set Only what you pass changes. Turn it on or off, require it, and set the identity provider tenant and Athenz domain; the tool takes enabled, required, tenant, role_domain and confirm
bumpkit identity sso managed-mcp clients add NAME [--client-id ID] identity_sso_managed_mcp_clients_add Register a client, with the client ID your identity provider uses if it chooses its own; prints its client_id and client_secret once
bumpkit identity sso managed-mcp clients remove CLIENT_ID --yes identity_sso_managed_mcp_clients_remove Remove a client and stop every token issued to it; the tool takes client_id and confirm
bumpkit identity sso managed-mcp test --file FILE identity_sso_managed_mcp_test Check an ID-JAG without using it up

set with no flags turns IdP-managed access off. test reads the ID-JAG from --file or, with --file - (the default), from standard input: bumpkit identity sso managed-mcp test < id-jag.txt. It never takes the token as a flag. The identity_sso_managed_mcp_test tool reads it from an environment variable in the server's environment (assertion_env) or a private file (assertion_file, mode 600), so it runs on the local MCP server. identity_sso_managed_mcp_clients_add is also local-only, because the result holds a secret; the hosted connector has the other three tools.

The API is GET and PUT /v1/identity/sso/managed-mcp, POST /v1/identity/sso/managed-mcp/clients, DELETE /v1/identity/sso/managed-mcp/clients/{id} and POST /v1/identity/sso/managed-mcp/test. See the Admin API.

Audit log ​

Every change and every token exchange is in the audit log:

Event When
sso.managed_mcp IdP-managed access turned on, off or required
sso.managed_mcp_client_create, sso.managed_mcp_client_delete A client registered or removed
sso.managed_mcp_test An admin tested an ID-JAG, with the verdict
mcp.managed.exchange An ID-JAG was traded for a token, with the client, role and issuer
sso.removed_refused, sso.relink_refused A dashboard sign-in was refused because the person was removed or their link belongs to a different identity provider account
mcp.managed.refused An ID-JAG was refused, with the error and why
mcp.auth.failed A token stopped working, for example because the member was deactivated or IdP-managed access is required

Troubleshooting ​

Each refusal comes back as an OAuth error with a description that says what to fix. Test an ID-JAG returns the same error and description.

invalid_client ​

The client_id or client_secret is wrong or missing, or the client was removed. Copy the client ID and secret from Settings → Single sign-on. Bumpkit finds the workspace from the client, so register a client in each workspace whose members use it. In a test, it means the ID-JAG's client_id isn't a client of this workspace: register one and set it as the client ID in your identity provider.

invalid_grant ​

The ID-JAG itself was refused. The description says which check failed:

Description says Fix
Bumpkit doesn't accept ID-JAGs from this issuer Set it as the OIDC issuer URL in Settings → Single sign-on and turn on IdP-managed access. For Okta, use the org URL
isn't a JWT signed with an asymmetric algorithm Sign with one of the accepted algorithms
typ header must be oauth-id-jag+jwt Send the ID-JAG, not an ID token or access token
couldn't read the OpenID configuration or signing keys Make sure <issuer>/.well-known/openid-configuration and its keys are reachable over HTTPS, then try again in a minute
keys have no signing key If the identity provider just rotated keys, try again in a minute: Bumpkit refetches keys at most once a minute, and remembers a failed fetch for a minute
signature doesn't match Get a new ID-JAG from the identity provider; it was changed or signed with another key
missing a required claim The identity provider must set iss, sub, aud, client_id, jti, exp and iat
aud must be exactly https://bumpkit.dev Set the audience or issuer URL for Bumpkit in your identity provider to the Audience value
resource must be https://bumpkit.dev/mcp Fix the resource or resource indicator in your identity provider
issued to a different client The ID-JAG's client_id must match the client ID the MCP client sends
lives longer than 1 hour Shorten the ID-JAG lifetime in your identity provider
expired, isn't valid yet, or issued in the future Get a new ID-JAG; if it keeps happening, check the identity provider's clock
already used Each ID-JAG works once; get a new one
bound to a key (cnf) Have the identity provider issue the ID-JAG without proof-of-possession binding
names tenant ..., so its issuer serves more than one tenant Set Identity provider tenant on the card to that tenant
tenant ... isn't the tenant set for this workspace The ID-JAG names another tenant, or none while you set one; fix the tenant in your identity provider or on the card

invalid_target ​

  • The ID-JAG's aud_tenant isn't the client's workspace or Bumpkit's audience. Set it to the workspace ID on the card, or leave it out. With Descope, set Tenant ID in target.
  • The token request's resource isn't https://bumpkit.dev/mcp. Send that value or leave resource out.

invalid_scope ​

The ID-JAG has scopes, but none of them is Bumpkit's, or the client asked for more than the ID-JAG grants. In your identity provider, grant mcp for full access or mcp:read for read-only access.

access_denied ​

The ID-JAG is valid, but the person can't use Bumpkit, or your organization requires IdP-managed access:

Description says Fix
No Bumpkit member matches Have the person sign in to Bumpkit with SSO once, make sure the ID-JAG carries a verified email on a domain this workspace verified, add them on the Team page, or turn on Create accounts on first sign-in
already linked to a different identity provider account The member is linked to another account at your identity provider; check the person's account in your identity provider and on the Team page
account ... is deactivated Restore the member on the Team page or through SCIM
manages MCP access through its identity provider Your organization requires IdP-managed MCP access, so Bumpkit sign-in and API keys for MCP clients are off for people on your verified domains. Connect through the MCP client your admin set up with your identity provider. An existing connection or API key that stops working with 401 after the requirement is turned on has the same cause

unsupported_grant_type ​

The token request used a grant other than authorization_code, refresh_token or urn:ietf:params:oauth:grant-type:jwt-bearer, or IdP-managed access isn't available on this server.

↑↓ to move, Enter to open