Deciding Which Clients Can Connect: Registration and Client Identity for MCP

Most MCP authorization writing stops at the user. The user consents, the token carries their identity, the server enforces their scope. That leaves a second principal unaddressed, and it is the one an enterprise reviewer asks about early: which client application is holding the token?

In OAuth terms the agent host is the client. The MCP client could be a desktop assistant on an employee laptop, an IDE, a browser extension, a hosted agent platform, or something a developer wrote yesterday. Your server's authorization server has to decide which of those it will issue tokens to. That decision is client registration, and there are only a few defensible answers.

What the specification expects

The MCP authorization specification points at OAuth 2.1 and at the discovery chain: your server publishes protected resource metadata (RFC 9728), that names the authorization server, and the authorization server publishes its own metadata (RFC 8414). The specification states that authorization servers SHOULD support dynamic client registration (RFC 7591) so that clients can obtain a client ID without a human doing paperwork first.

The reason is practical. There is no fixed list of MCP clients. A user who installs a new agent and points it at your server cannot be expected to file a ticket with your identity team. Without dynamic registration, either you enumerate every client in advance or the connection fails.

RFC 7591 is a SHOULD, not a MUST. Clients are expected to cope when it is absent, usually by using a client ID your documentation gives them. So you have a genuine choice, and it should be made deliberately rather than inherited from whatever your identity provider does by default.

Open dynamic registration

An open registration endpoint accepts an unauthenticated POST with a client name, redirect URIs, and grant types, and returns a client ID. Any caller gets one.

What this actually grants is smaller than it sounds. A client ID is not access. Every token still comes from an authorization code flow with PKCE, and that flow still requires a real user to authenticate and consent. A registered client with no user is a registered client with nothing.

What it does grant is the ability to appear in front of your users. A registration record carries a display name, a logo URI, and a client URI, and those are what the consent screen shows. An attacker who registers "Acme Internal Assistant" with your logo has built a convincing phishing page hosted on your own domain. Registration records are also unbounded state: an open endpoint can be filled with garbage until the table is a liability.

If you run open registration, the controls that matter are:

  • Rate limit the endpoint per source, and cap the total number of live registrations.
  • Expire registrations that have never completed an authorization flow. A few days is usually enough.
  • Do not display attacker-controlled strings on the consent screen as if they were verified. Show the redirect host, mark the client as unverified, and treat client name and logo as untrusted data.
  • Reject redirect URIs that are not exact HTTPS URLs or documented loopback addresses, and refuse wildcards outright.
  • Issue registration access tokens (RFC 7592) so a registration can be read, updated, and deleted, and so you can revoke one.

That is a workable posture for a consumer-facing or self-serve product. It is a hard sell for a customer whose security team wants an inventory of every application that can reach their data.

Pre-registration and allowlists

The opposite posture: registration is closed, and client IDs are issued by you. Public clients you have reviewed get an entry; anything else fails at the authorization endpoint.

This is what most enterprise buyers are asking for when they raise the question. It gives them an answer to "which applications can connect" that is a list rather than a policy. It also gives you somewhere to attach per-client rules: this client may call read tools only, that one may call write tools, this one is restricted to a tenant.

The cost is real. Every new agent your customers adopt becomes an intake request. If your product is used by many small teams, that queue will not be staffed. Do not choose the allowlist because it sounds stricter; choose it because someone will operate it.

The middle position, and the one most servers should take

In practice the sustainable answer is both, split by tenant.

Run dynamic registration for the general case, with the hygiene above. Then let an administrator on each tenant decide what their organization accepts. Three settings cover most requirements:

  • Open: any registered client may be used by our users. Suitable for small teams and trials.
  • Approved clients only: an administrator maintains the list of client IDs their users may connect with, and a first connection from an unknown client raises an approval request instead of an error.
  • Managed clients only: only clients registered by us, typically the customer's own internal agent platform, connecting through their identity provider.

This moves the decision to the party that owns the risk, which is the same argument that makes per-tenant scope policy work. It also answers the questionnaire directly: the customer does not have to trust your judgement about which agents are acceptable, because they set it themselves.

A fourth option is emerging. Work is in progress at the IETF on client identifiers that are URLs resolving to a signed or hosted metadata document, so that a client proves what it is by publishing that document at a domain it controls, with no registration call at all. It is a draft. Read it, design so that adopting it later is a configuration change rather than a rewrite, and do not put it in a customer commitment yet.

Software statements

RFC 7591 includes a middle path that is often overlooked. A registration request may carry a software statement: a JWT, signed by an issuer you trust, asserting the client's name, redirect URIs, and other metadata. Registration stays dynamic, but the values that appear on your consent screen came from a signer rather than from the caller.

This is how a directory or platform can vouch for the clients it distributes. If the ecosystem your customers live in offers signed statements, accept them and mark those clients as verified. Accept unsigned registrations too, if you must, but keep the distinction visible in the consent screen and in the audit log.

Client identity in tokens and in the log

Whatever the registration policy, the client must remain identifiable after the token is issued. Two requirements follow.

First, the access token needs a client claim. Most authorization servers include one; check yours, and check that your server reads it rather than ignoring it. Without it your server cannot apply per-client policy and your audit events cannot say which application acted.

Second, every audit event carries user, tenant, and client. "Who did this" has two halves for an agent call, and reviewers ask for both. When a customer wants to remove an agent from their environment, the client ID is what they search for, and the client ID is what you revoke against.

Per-client policy is worth designing even if you start permissive. The rule that a newly registered, unverified client may call read tools only, and needs administrator approval before any state-changing tool, costs little to implement and removes an entire class of finding from the review.

Confidential clients are rarer than you think

One more distinction that reviewers check. A client that runs on a user's machine cannot keep a secret, so it is a public client, and PKCE is the protection. A hosted agent platform running server-side can hold credentials and should be registered as a confidential client with client authentication, ideally an assertion rather than a shared secret.

Issuing a client secret to a desktop application and treating it as authentication is a finding. If the same registration flow serves both kinds of client, record which kind each one is at registration and enforce the corresponding rules at the token endpoint.

What to write down

Before the build, one page: the registration mode you support, the per-tenant controls an administrator has, how redirect URIs are validated, what the consent screen shows and which parts of it are untrusted, how a registration is revoked, and what the audit event says about the client. That page answers most of the client-related questions in a vendor security review, and it is short enough that it stays true.

We treat client registration as a design decision in week one on every server build, and it is one of the areas an MCP security audit checks against the specification.