Managing MCP Servers with the API

Every MCP server in Descope is a Resource of type MCP server. The Resources Management API lets you create, load, update, and delete those Resources from code, with the same settings you see on the MCP server settings page in the Console.

This page is for teams that register MCP servers programmatically. If you create MCP servers by hand, see Managing Resources for the Console steps instead.

Why Automate MCP Server Registration

An MCP server needs its own Resource before Descope can issue tokens for it. The Resource holds the server's audience, its scope catalog, and the rules for clients that register through Dynamic Client Registration (DCR) or Client ID Metadata Documents (CIMD).

Creating that Resource by hand works when you have a handful of servers. The approach breaks down when you run an internal or external MCP gateway whose registry onboards new downstream services on a regular basis. Each new service needs a Resource on the day it joins the registry, and each retired service needs its Resource deleted.

With the Management API, your registry owns that lifecycle. When a service joins, the registry creates its Resource. When a service changes its tools, the registry updates the scopes. When a service leaves, the registry deletes the Resource, and Descope stops issuing tokens for it.

Authentication

Every endpoint on this page needs a Management Key. You send your Project ID and the key together as a bearer token:

Authorization: Bearer __ProjectID__:<MANAGEMENT_KEY>

Resource Endpoints

The Resources Management API covers both API Resources and MCP Server Resources. You use the same endpoints for each kind. The type field on the Resource tells Descope which kind it is: mcp for an MCP Server Resource or api for an API Resource. Every request on this page sets type to mcp. To create API Resources from code, see Creating a Resource with the Management API.

TaskEndpoint
Create a ResourcePOST /v1/mgmt/resource/create
Load a Resource by IDGET /v1/mgmt/resource/load?id=<id>
Load a Resource by URIGET /v1/mgmt/resource/load/uri?uri=<uri>
Load all ResourcesGET /v1/mgmt/resources/load
Update a ResourcePOST /v1/mgmt/resource/update
Delete a ResourcePOST /v1/mgmt/resource/delete
Delete several ResourcesPOST /v1/mgmt/resource/delete/batch

Creating an MCP Server Resource

The create request body groups into a few kinds of settings. Each group matches a section of the MCP server settings in the Console.

  • Identity: name and description label the server in the Console. Set type to mcp on every create request. If you leave out type, Descope creates an API Resource, which does not appear as an MCP server.
  • Audience: uri is the MCP Server URL field in the Console, and every create request needs it. Descope includes the URL in the aud claim of the tokens it issues for this Resource. Each uri must be unique in the project.
  • Scopes: scopes holds the scope catalog. See Scopes below.
  • Access: userAccess and clientAccess control whether clients can receive tokens for this Resource. See User and Client Access below.
  • Registration and consent: dynamicRegistrationSettings controls how DCR and CIMD clients register, which consent flow they run, and their session settings. See Dynamic Registration Settings below.

Descope does not let you change type or uri after it creates the Resource. If a service moves to a new URL, create a new Resource for the new URL and delete the old one.

The example below creates a Resource for a calendar MCP server. The server allows DCR and CIMD from any domain, takes its client defaults from a dynamic registration template, and has one required scope.

curl -X POST "__BaseURL__/v1/mgmt/resource/create" \
  -H "Authorization: Bearer __ProjectID__:<MANAGEMENT_KEY>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Calendar MCP Server",
    "description": "Calendar tools for agents",
    "type": "mcp",
    "uri": "https://calendar.mcp.example.com/mcp",
    "scopes": {
      "permissionsScopes": [
        { "name": "mcp:tools:read", "description": "Read tools", "optional": false }
      ]
    },
    "dynamicRegistrationSettings": {
      "useTemplate": true,
      "dynamicRegistrationTemplateId": "<TEMPLATE_ID>",
      "dynamicRegistration": { "enabled": true },
      "cimdSettings": {
        "enabled": true,
        "domainPolicies": { "policies": [{ "domainPattern": "*", "enabled": true }] }
      }
    }
  }'

The response returns the created resource object. Store its id, because the update, load, and delete endpoints all take that ID.

Scopes

scopes holds the scope catalog of the MCP server in two lists. Every scope in a list has a name, a description that the consent screen shows, an optional flag that lets the user decline the scope, and an optional values array.

  • permissionsScopes: These scopes cover what the client can do on the MCP server, such as mcp:tools:write.
  • connectionsScopes: These scopes grant access to Connections, so the MCP server can retrieve the user's third-party credentials. In this list, values holds the Connection scopes that the MCP scope grants.

The schema for scopes also lists an attributesScopes field, but you can leave it out. The Console does not manage attribute scopes, such as profile and email, on a Resource. Descope defines them once for the project, and you add them to each client or Inbound App that needs them.

See Scopes on Resources for how Descope evaluates these scopes at token issuance.

User and Client Access

userAccess and clientAccess decide whether Descope issues tokens for the Resource at all, before it looks at scopes. userAccess applies when a client requests a token on behalf of a user. clientAccess applies when a client requests a token for itself, as in the client credentials flow.

Each field takes one of three values:

  • allow: Descope can issue tokens for the Resource. The Console sets both fields to allow when it creates an API Resource.
  • deny: Descope refuses every token request for the Resource in that mode.
  • allowViaPolicy: Descope can issue tokens for the Resource, and you control which clients and scopes with Policies.

Dynamic Registration Settings

dynamicRegistrationSettings applies only when type is mcp. The object has two modes, and useTemplate selects between them.

When useTemplate is true, the Resource takes its client defaults from the dynamic registration template named in dynamicRegistrationTemplateId. The template then supplies the login page URL, session settings, consent screen behavior, tags, approved callback URLs, and logo. Shared templates suit a gateway well, because every downstream service receives the same consent flow and token lifetimes without the registry repeating them.

When useTemplate is false, Descope uses the inline fields on the object instead. These fields are loginPageURL, sessionSettings, skipConsentScreen, forceAddAllAuthorizationInfo, tags, and fallbackClientLogo. In this mode, a Resource with DCR or CIMD turned on also needs a loginPageURL, or the create request fails.

In both modes, dynamicRegistration turns DCR on or off, and its optional flowId sets the Client Registration Flow, a management flow that runs after each DCR registration. cimdSettings turns CIMD on or off and limits which client domains can register. See Client Registration Methods for how each method works.

flowId has to be the ID of a management flow. A login flow such as sign-up-or-in is accepted when you create the Resource, but every DCR registration then fails with 403 and error E102005 ("The flow type is invalid for this operation"). If you don't need a Client Registration Flow, you can leave flowId out.

These registration settings apply in full to a server on the MCP Server Issuer. A server on the project issuer takes DCR and the Client Registration Flow from the project, and takes CIMD from the project unless the server overrides the project settings. See Enabling CIMD and DCR for more information.

Syncing Resources from a Gateway Registry

A registry usually knows each downstream service by its URL, not by a Descope ID. The Load a Resource by URI endpoint lets the registry look up a Resource by the same URL that it uses as the uri. With that lookup, the registry can run the same sync step every time it sees a service, and the step stays safe to repeat.

Look up the service

Call the load-by-URI endpoint with the exact MCP server URL that you store as uri.

Create a missing Resource

If the lookup fails with Resource not found (E074805), call the create endpoint.

Update an existing Resource

If the lookup returns a Resource, change the fields that differ and send the full object back.

Delete retired services

When a service leaves the registry, delete its Resource by ID.

Send the full Resource on update

The update endpoint replaces the whole Resource, so Descope clears any field that the request leaves out. Load the Resource first, change the fields you need, and send it back with its id and its version unchanged.

The version field protects against two writers that change the same Resource at once. If the Resource changed after your registry loaded it, the update fails with Resource not found (E074805). Your registry can then load the Resource again and retry the update.

For many services at once, the Load all Resources endpoint returns every Resource in the project. Your registry can compare that list with its own list of services and delete the leftovers with the batch delete endpoint.

Granting Pre-Registered Clients Access

Clients that register through DCR or CIMD receive access to the MCP server Resource that they registered with automatically. A pre-registered client, such as an Agentic Client or an Inbound App that you created in advance, receives no access by itself.

The Resource Policies API links a pre-registered client to a Resource. Each resource policy names the client in thirdPartyApplicationId, the Resource in resourceId, and the scopes the client can receive in userAccessScopes and clientAccessScopes. You can set allUserScopes or allClientScopes to true to allow every scope on the Resource instead of listing them.

When your gateway onboards a service and several known agents need it on day one, the batch create endpoint links those clients in one request.

A resource policy decides which scopes a client can receive, but Descope also evaluates the rules on the Policies page for each request. Descope can deny a request that no rule permits, even with a resource policy in place. To make sure a pre-registered client reaches the Resource, also add a rule whose subject is the client and whose target is the Resource.

Next Steps

You can review every field and response in the Resources Management API reference. To control which users and agents receive scopes on the Resources you create, set up Policies. To see how a gateway sits in front of many MCP servers, read MCP Gateways.

Was this helpful?

On this page