curl --request POST 'https://api.voicecheap.ai/oauth/register' \
--header 'Content-Type: application/json' \
--data '{"client_name":"Acme assistant","redirect_uris":["https://assistant.example.com/oauth/callback"],"token_endpoint_auth_method":"none","grant_types":["authorization_code","refresh_token"],"response_types":["code"],"scope":"account:read projects:read offline_access"}'
const input = {
client_name: 'Acme assistant',
redirect_uris: ['https://assistant.example.com/oauth/callback'],
token_endpoint_auth_method: 'none',
grant_types: ['authorization_code', 'refresh_token'],
response_types: ['code'],
scope: 'account:read projects:read offline_access',
};
const response = await fetch('https://api.voicecheap.ai/oauth/register', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(input),
redirect: 'manual',
});
console.log(response.status, await response.text());
import os
import requests
response = requests.request(
"POST",
"https://api.voicecheap.ai/oauth/register",
headers={"Content-Type":"application/json"},
json={"client_name": "Acme assistant", "redirect_uris": ["https://assistant.example.com/oauth/callback"], "token_endpoint_auth_method": "none", "grant_types": ["authorization_code", "refresh_token"], "response_types": ["code"], "scope": "account:read projects:read offline_access"},
timeout=120,
allow_redirects=False,
)
print(response.status_code, response.text)
OAuth en het MCP-protocol
Een MCP OAuth-client registreren
Registreer een openbare client met exacte callback-URL’s en een begrensde set productrechten.
POST
/
oauth
/
register
curl --request POST 'https://api.voicecheap.ai/oauth/register' \
--header 'Content-Type: application/json' \
--data '{"client_name":"Acme assistant","redirect_uris":["https://assistant.example.com/oauth/callback"],"token_endpoint_auth_method":"none","grant_types":["authorization_code","refresh_token"],"response_types":["code"],"scope":"account:read projects:read offline_access"}'
const input = {
client_name: 'Acme assistant',
redirect_uris: ['https://assistant.example.com/oauth/callback'],
token_endpoint_auth_method: 'none',
grant_types: ['authorization_code', 'refresh_token'],
response_types: ['code'],
scope: 'account:read projects:read offline_access',
};
const response = await fetch('https://api.voicecheap.ai/oauth/register', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(input),
redirect: 'manual',
});
console.log(response.status, await response.text());
import os
import requests
response = requests.request(
"POST",
"https://api.voicecheap.ai/oauth/register",
headers={"Content-Type":"application/json"},
json={"client_name": "Acme assistant", "redirect_uris": ["https://assistant.example.com/oauth/callback"], "token_endpoint_auth_method": "none", "grant_types": ["authorization_code", "refresh_token"], "response_types": ["code"], "scope": "account:read projects:read offline_access"},
timeout=120,
allow_redirects=False,
)
print(response.status_code, response.text)
Registreer een openbare client met exacte callback-URL’s en een begrensde set productrechten.
POST https://api.voicecheap.ai/oauth/register
Authenticatie
Geen. Registratie meldt geen gebruiker aan en autoriseert geen accountverbinding.Aanvraagbody
array
vereist
Tussen 1 en 10 callbacks voordat duplicaten worden verwijderd.Minimaal aantal items: 1. Maximaal aantal items: 10.
string
Optioneel clientlabel; witruimte aan het begin en einde wordt vóór het opslaan verwijderd en het label moet niet-leeg blijven.Minimale lengte: 1. Maximale lengte: 120. Patroon:
^(?=.*\S)[^\u0000-\u001F\u007F]+$. Standaardwaarde: “MCP client”.field
Alleen publieke clients.Vereiste waarde: “none”. Standaardwaarde: “none”.
union
Moet authorization_code bevatten; refresh_token is optioneel. Weglaten of null selecteert beide. Dubbele waarden worden verwijderd.Standaardwaarde: [“authorization_code”,“refresh_token”].
array
Lijst met waarden. Zie het volledige invoerschema voor de structuur van de items.Minimaal aantal items: 1. Maximaal aantal items: 1. Standaardwaarde: [“code”].
string
Door spaties gescheiden machtigingen uit scopes_supported, eventueel inclusief offline_access. Niet-ondersteunde namen en waarden met alleen witruimte worden geweigerd; duplicaten worden verwijderd. Als scope wordt weggelaten of geen productmachtigingen bevat, bijvoorbeeld alleen openid of alleen offline_access, worden alle ondersteunde productscopes geregistreerd. email vereist openid; alleen email wordt geweigerd. Als OpenID Connect beschikbaar is, omvat de registratie openid en email als clientmogelijkheden, ook als scope ontbreekt. Registratie verleent geen toegang; identiteitsmachtigingen vereisen een expliciet autorisatieverzoek en toestemming van de gebruiker.Minimale lengte: 1. Maximale lengte: 2048. Patroon:
^ *(?:account:read|usage:read|settings:read|settings:write|team:read|team:write|projects:read|projects:write|projects:delete|translations:write|transcription:read|transcription:write|subtitles:read|subtitles:write|tts:read|tts:write|voices:read|voices:write|images:read|images:write|thumbnails:read|thumbnails:write|folders:read|folders:write|glossary:read|glossary:write|webhooks:read|webhooks:write|publishing:read|publishing:write|offline_access|openid|email)(?: +(?:account:read|usage:read|settings:read|settings:write|team:read|team:write|projects:read|projects:write|projects:delete|translations:write|transcription:read|transcription:write|subtitles:read|subtitles:write|tts:read|tts:write|voices:read|voices:write|images:read|images:write|thumbnails:read|thumbnails:write|folders:read|folders:write|glossary:read|glossary:write|webhooks:read|webhooks:write|publishing:read|publishing:write|offline_access|openid|email))* *$.Technisch schema
Technisch schema
{
"type": "object",
"properties": {
"redirect_uris": {
"type": "array",
"minItems": 1,
"maxItems": 10,
"items": {
"type": "string",
"minLength": 1,
"maxLength": 2048,
"pattern": "^[^\\s\\u0000-\\u001F\\u007F-\\u009F#\\\\]+$",
"format": "uri",
"anyOf": [
{
"pattern": "^[Hh][Tt][Tt][Pp][Ss]://"
},
{
"pattern": "^http://(?:localhost|127\\.0\\.0\\.1|\\[::1\\])(?::[0-9]{1,5})?(?:/|\\?|$)"
},
{
"const": "cursor://anysphere.cursor-mcp/oauth/callback"
}
],
"description": "An absolute HTTPS callback, an HTTP callback using the exact lowercase loopback spelling localhost, 127.0.0.1, or [::1], or exactly cursor://anysphere.cursor-mcp/oauth/callback. Must parse as a URL with no username/password, whitespace, control characters, backslashes, or fragment. A loopback port must be a valid URL port. The exact spelling is retained."
},
"description": "Between 1 and 10 callbacks before duplicates are removed."
},
"client_name": {
"type": "string",
"minLength": 1,
"maxLength": 120,
"pattern": "^(?=.*\\S)[^\\u0000-\\u001F\\u007F]+$",
"default": "MCP client",
"description": "Optional client label; trimmed before saving and must remain nonempty."
},
"token_endpoint_auth_method": {
"const": "none",
"default": "none",
"description": "Public clients only."
},
"grant_types": {
"anyOf": [
{
"type": "array",
"minItems": 1,
"items": {
"enum": [
"authorization_code",
"refresh_token"
]
},
"contains": {
"const": "authorization_code"
}
},
{
"type": "null"
}
],
"default": [
"authorization_code",
"refresh_token"
],
"description": "Must include authorization_code; refresh_token is optional. Omitted or null selects both. Duplicate values are removed."
},
"response_types": {
"type": "array",
"minItems": 1,
"maxItems": 1,
"items": {
"const": "code"
},
"default": [
"code"
]
},
"scope": {
"type": "string",
"minLength": 1,
"maxLength": 2048,
"pattern": "^ *(?:account:read|usage:read|settings:read|settings:write|team:read|team:write|projects:read|projects:write|projects:delete|translations:write|transcription:read|transcription:write|subtitles:read|subtitles:write|tts:read|tts:write|voices:read|voices:write|images:read|images:write|thumbnails:read|thumbnails:write|folders:read|folders:write|glossary:read|glossary:write|webhooks:read|webhooks:write|publishing:read|publishing:write|offline_access|openid|email)(?: +(?:account:read|usage:read|settings:read|settings:write|team:read|team:write|projects:read|projects:write|projects:delete|translations:write|transcription:read|transcription:write|subtitles:read|subtitles:write|tts:read|tts:write|voices:read|voices:write|images:read|images:write|thumbnails:read|thumbnails:write|folders:read|folders:write|glossary:read|glossary:write|webhooks:read|webhooks:write|publishing:read|publishing:write|offline_access|openid|email))* *$",
"description": "Space-delimited permissions from scopes_supported, optionally including offline_access. Unsupported names and whitespace-only values are rejected; duplicates are removed. Omitting scope or supplying no product scopes, such as openid alone or offline_access alone, registers all supported product scopes. email requires openid; email alone is rejected. When OpenID Connect is available, registration includes openid and email as client capabilities even when scope is omitted. Registration grants no access; identity permissions require an explicit authorization request and user consent.",
"examples": [
"account:read projects:read offline_access"
]
}
},
"required": [
"redirect_uris"
],
"additionalProperties": true
}
Voorbeeldaanvragen
Volg de gedocumenteerde codering en authenticatie voor deze route. De antwoordstructuur en idempotentieregels van de actie-API gelden alleen voor actieaanroepen.curl --request POST 'https://api.voicecheap.ai/oauth/register' \
--header 'Content-Type: application/json' \
--data '{"client_name":"Acme assistant","redirect_uris":["https://assistant.example.com/oauth/callback"],"token_endpoint_auth_method":"none","grant_types":["authorization_code","refresh_token"],"response_types":["code"],"scope":"account:read projects:read offline_access"}'
const input = {
client_name: 'Acme assistant',
redirect_uris: ['https://assistant.example.com/oauth/callback'],
token_endpoint_auth_method: 'none',
grant_types: ['authorization_code', 'refresh_token'],
response_types: ['code'],
scope: 'account:read projects:read offline_access',
};
const response = await fetch('https://api.voicecheap.ai/oauth/register', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(input),
redirect: 'manual',
});
console.log(response.status, await response.text());
import os
import requests
response = requests.request(
"POST",
"https://api.voicecheap.ai/oauth/register",
headers={"Content-Type":"application/json"},
json={"client_name": "Acme assistant", "redirect_uris": ["https://assistant.example.com/oauth/callback"], "token_endpoint_auth_method": "none", "grant_types": ["authorization_code", "refresh_token"], "response_types": ["code"], "scope": "account:read projects:read offline_access"},
timeout=120,
allow_redirects=False,
)
print(response.status_code, response.text)
Antwoord
Geregistreerde metadata van de openbare client. Bewaar client_id en gebruik deze met de exact geregistreerde redirect_uri. Er wordt geen client_secret uitgegeven.HTTP 201
{
"client_id": "mcp_client_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
"client_id_issued_at": 1792152000,
"client_name": "Acme assistant",
"redirect_uris": ["https://assistant.example.com/oauth/callback"],
"token_endpoint_auth_method": "none",
"grant_types": ["authorization_code", "refresh_token"],
"response_types": ["code"],
"scope": "account:read projects:read offline_access"
}
Antwoordheaders
{
"Cache-Control": "no-store",
"Pragma": "no-cache"
}
Opmerkingen bij de bewerking
- Herkende scalaire parameters moeten eenmaal worden opgegeven als niet-lege strings zonder ASCII-besturingstekens of DEL. Herhaalde query-/formuliervelden worden gedecodeerd als arrays en geweigerd wanneer ze als scalaire waarden worden gelezen.
- Gebruik Content-Type application/json. Een URL-gecodeerde registratiebody wordt geweigerd met het OAuth-antwoord invalid_request; niet-ondersteunde mediatypen kunnen eerder door de integratieparser worden geweigerd.
- Redirect-URI’s worden exact bewaard en vergeleken. Wijzigingen in hoofdletters, poortnotatie, pad, query of afsluitende slash vereisen registratie van die exacte URI.
- HTTP-callbacks accepteren alleen de onbewerkte loopbacknamen localhost, 127.0.0.1 en [::1]. Privénetwerkhosts, alternatieve IP-schrijfwijzen, *.localhost en LOCALHOST in hoofdletters voldoen niet.
- De enige geaccepteerde callback met een aangepast URI-schema is exact cursor://anysphere.cursor-mcp/oauth/callback.
- Elke callback moet de validatie doorstaan; één ongeldige callback zorgt ervoor dat de volledige registratie wordt geweigerd. Inloggegevens in URL’s, witruimte, besturingstekens, fragmenten en backslashes worden geweigerd.
- De client mag alle ondersteunde productscopes registreren, maar de gebruiker moet tijdens de autorisatie de gevraagde subset afzonderlijk goedkeuren. Registratie alleen geeft geen toegang.
- Alleen authorization_code en optionele refresh_token-grants worden ondersteund. Een client die zonder refresh_token is geregistreerd, ontvangt geen vernieuwingstoken.
- Onbekende metadatavelden op het hoogste niveau worden door de huidige implementatie genegeerd. Voor bekende velden blijven de beperkingen uit het schema gelden.
- De openbare registratielimiet is 10 aanvragen per 10 minuten per client-IP, gedeeld door alle workers. JSON-body’s zijn beperkt tot 1 MiB.
- Een geslaagde registratie retourneert HTTP 201.
- openid en email zijn identiteitsrechten, los van productrechten, en worden alleen geaccepteerd als ze worden vermeld. email vereist openid. Bij de eerste autorisatie gebruikt een verzoek met alleen identiteitsscopes de standaardproductrechten die op het toestemmingsscherm staan.
Fouten
| HTTP-status | Code | Betekenis of herstel |
|---|---|---|
| 400 | invalid_request | De body of een herkende parameter is ongeldig, ontbreekt, is dubbel opgegeven of heeft de verkeerde codering. |
| 400 | invalid_client_metadata | Ongeldig aantal callbacks, leeg clientlabel of niet-ondersteunde clientauthenticatie, granttypen of responstypen. |
| 400 | invalid_redirect_uri | Een callback-URL gebruikt een niet-ondersteunde of onveilige vorm. |
| 400 | invalid_scope | De scope-string bevat een niet-ondersteunde machtiging of geen aangevraagde machtigingen. |
| 413 | REQUEST_TOO_LARGE | De aanvraag overschrijdt de toegestane bodygrootte. JSON is beperkt tot 1 MiB en URL-gecodeerde formulieren tot 32 KiB. |
| 415 | UNSUPPORTED_CONTENT_TYPE | De bodyparser van de integratie accepteert alleen JSON of URL-gecodeerde formulieren. De route kan specifiek een van deze coderingen vereisen. |
| 429 | temporarily_unavailable | De openbare frequentielimiet voor OAuth-aanvragen is bereikt. Wacht tot het huidige tijdvenster voorbij is voordat je het opnieuw probeert. |
| 500 | server_error | Autorisatie is tijdelijk niet beschikbaar. Probeer het later opnieuw. |
Was deze pagina nuttig?

