MCP dynamic client registration at Sume: 10 redirect URIs, no secret

Sume's /oauth/register takes at most 10 redirect_uris, requires auth method none and returns invalid_redirect_uri for a bad entry. See what each error means.

5 min readSume
All posts

A client that registers itself with Sume's hosted MCP server at POST /oauth/register must send a non-empty redirect_uris array of at most 10 strings, each an allowed redirect, and use the token auth method none. Break one of those rules and the server answers with a specific OAuth error: invalid_redirect_uri for the list or an entry, invalid_client_metadata for too many entries, and an error for any auth method other than none.

This is the page for developers who build or debug a connector that registers on its own, rather than people who just add the URL to Claude or Cursor.

The reason to read the rules before you write a registration client is that the errors are specific, and each one tells you which field to fix. The same parser also runs the redirect check that the authorize step uses, so a callback that registers cleanly is also accepted at authorize time.

Treat the registration response as the contract for the rest of the flow. It carries the client_id that you will send to the authorize and token endpoints, and the redirect list that the server accepted. If the two differ from what you intended, stop and fix the request before you send a user to a browser, because a failed consent page is much harder to debug than a 400 from a JSON endpoint.

The rules and the errors

Each rule comes from the registration parser in the Sume source.

The checks run in this order: the redirect list first, then the auth method, then grant types. Fix the first error and resend, because a later one will not show until the earlier one is gone.

Teams that run a connector in several environments, such as a laptop callback and a staging callback, can register both in one request as long as the total stays within the limit of 10.

Registration checks and error codes in the Sume MCP source (read 2026-10-05)
Request problemError codeFix
redirect_uris missing, not an array or emptyinvalid_redirect_uriSend a non-empty array
More than 10 redirect_urisinvalid_client_metadataRegister 10 or fewer
An entry that is not a stringinvalid_redirect_uriSend strings only
An entry that fails the redirect allow-rulesinvalid_redirect_uriUse an allowed redirect
token_endpoint_auth_method other than noneRejected: must be none for public MCP clientsOmit it or send none

Defaults that save you a field

Duplicates in the list collapse to one entry. A missing or empty auth method defaults to none, so the shortest valid body is the client name and the redirect list. The grant type defaults to authorization_code; a refresh_token entry is dropped, as covered in the refresh-token post.

The normalization step turns each entry into its canonical URL string, so two spellings of the same address count as one. Compare the list in the response with the list you sent when you debug a callback that the browser refuses.

The redirect must match later

Registration is also bound to later steps. At authorize time, the redirect_uri has to be one that the client registered; a mismatch fails with "OAuth redirect_uri is not registered for this client." Register every callback your client can use, including a port that changes, up to the limit of 10.

If a user reports that the browser stops on an error page after consent, check this match first: the value in the registration and the value in the authorize request must be the same string, not just the same host.

This request creates a client with one callback, using only the standard library:

Keep the returned client_id and reuse it. A client that registers again on every start creates a new record each time and loses any consent state the user already gave, so store the id next to the redirect list.

import json, urllib.request

body = {
    "client_name": "My MCP bridge",
    "redirect_uris": ["http://127.0.0.1:8123/callback"],
    "token_endpoint_auth_method": "none",
    "grant_types": ["authorization_code"],
}
req = urllib.request.Request(
    "https://mcp.sume.com/oauth/register",
    data=json.dumps(body).encode(),
    headers={"Content-Type": "application/json"},
)
with urllib.request.urlopen(req) as res:
    print(json.load(res))

Next step

After registration, run the code flow with S256 as described in the MCP OAuth and API keys page, and request mcp:read, or mcp:read mcp:write if the user will turn Write on. An unsupported scope returns invalid_scope.

Last, remember that a registered client is not a login. The user still has to sign in on the consent page of the MCP host, and the Write toggle is off by default, so a connector that needs tools that change data must ask for the write scope and the user must switch it on.

Sources

Related posts

More in Integrations

All Integrations posts

Written by Sume