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 i protokół MCP
Zarejestruj klienta OAuth MCP
Zarejestruj klienta publicznego z dokładnymi adresami URL wywołania zwrotnego i ograniczonym zestawem uprawnień produktu.
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)
Zarejestruj klienta publicznego z dokładnymi adresami URL wywołania zwrotnego i ograniczonym zestawem uprawnień produktu.
POST https://api.voicecheap.ai/oauth/register
Uwierzytelnianie
Brak. Rejestracja nie loguje użytkownika ani nie autoryzuje połączenia konta.Treść żądania
array
wymagane
Od 1 do 10 adresów wywołań zwrotnych przed usunięciem duplikatów.Minimalna liczba elementów: 1. Maksymalna liczba elementów: 10.
string
Opcjonalna etykieta klienta; przed zapisaniem usuwane są z niej skrajne białe znaki i musi pozostać niepusta.Minimalna długość: 1. Maksymalna długość: 120. Wzorzec:
^(?=.*\S)[^\u0000-\u001F\u007F]+$. Wartość domyślna: “MCP client”.field
Wyłącznie klienci publiczni.Wymagana wartość: “none”. Wartość domyślna: “none”.
union
Musi zawierać authorization_code; refresh_token jest opcjonalne. Pominięcie pola lub podanie null powoduje wybranie obu. Powtórzone wartości są usuwane.Wartość domyślna: [“authorization_code”,“refresh_token”].
array
Lista wartości. Strukturę elementów opisuje pełny schemat danych wejściowych.Minimalna liczba elementów: 1. Maksymalna liczba elementów: 1. Wartość domyślna: [“code”].
string
Uprawnienia z scopes_supported rozdzielone spacjami, opcjonalnie z offline_access. Nieobsługiwane nazwy i wartości zawierające wyłącznie białe znaki są odrzucane; duplikaty są usuwane. Pominięcie scope lub brak uprawnień produktu, na przykład samo openid lub samo offline_access, rejestruje wszystkie obsługiwane zakresy produktu. email wymaga openid; samo email jest odrzucane. Gdy OpenID Connect jest dostępny, rejestracja obejmuje openid i email jako możliwości klienta, nawet jeśli scope pominięto. Rejestracja nie przyznaje dostępu; uprawnienia tożsamości wymagają jawnego żądania autoryzacji i zgody użytkownika.Minimalna długość: 1. Maksymalna długość: 2048. Wzorzec:
^ *(?: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))* *$.Schemat techniczny
Schemat techniczny
{
"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
}
Przykłady żądań
Stosuj udokumentowany sposób kodowania i uwierzytelniania dla tej ścieżki. Struktura odpowiedzi i reguły idempotencji API akcji dotyczą wyłącznie wywołań akcji.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)
Odpowiedź
Zarejestrowane metadane klienta publicznego. Zapisz client_id i używaj go z dokładnie zarejestrowanym redirect_uri. client_secret nie jest wydawany.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"
}
Nagłówki odpowiedzi
{
"Cache-Control": "no-store",
"Pragma": "no-cache"
}
Uwagi do operacji
- Rozpoznawane parametry skalarne muszą być podane jednokrotnie jako niepuste ciągi znaków bez znaków sterujących ASCII ani DEL. Powtórzone pola zapytania lub formularza są dekodowane jako tablice i odrzucane przy odczycie jako wartości skalarne.
- Użyj Content-Type application/json. Treść rejestracji zakodowana jako URL-encoded jest odrzucana odpowiedzią OAuth invalid_request; nieobsługiwane typy mediów mogą zostać odrzucone wcześniej przez parser integracji.
- Adresy URI przekierowania są zachowywane i porównywane dokładnie. Zmiany wielkości liter, zapisu portu, ścieżki, zapytania lub końcowego ukośnika wymagają rejestracji dokładnie takiego adresu URI.
- Wywołania zwrotne HTTP akceptują wyłącznie dosłowne nazwy pętli zwrotnej localhost, 127.0.0.1 i [::1]. Hosty sieci prywatnych, alternatywne zapisy adresów IP, *.localhost i pisane wielkimi literami LOCALHOST nie spełniają tego warunku.
- Jedynym akceptowanym adresem wywołania zwrotnego z niestandardowym schematem URI jest dokładnie cursor://anysphere.cursor-mcp/oauth/callback.
- Każdy adres wywołania zwrotnego musi przejść walidację; jeden nieprawidłowy adres powoduje odrzucenie całej rejestracji. Dane uwierzytelniające w adresie URL, białe znaki, znaki sterujące, fragmenty i ukośniki odwrotne są odrzucane.
- Klient może zarejestrować dowolne obsługiwane zakresy uprawnień produktu, ale użytkownik musi osobno zatwierdzić żądany podzbiór podczas autoryzacji. Sama rejestracja nie przyznaje dostępu.
- Obsługiwane są wyłącznie typy grantów authorization_code i opcjonalnie refresh_token. Klient zarejestrowany bez refresh_token nie otrzymuje tokenu odświeżania.
- Nieznane pola metadanych najwyższego poziomu są ignorowane przez bieżącą implementację. Znane pola zachowują ograniczenia przedstawione w schemacie.
- Publiczny limit rejestracji wynosi 10 żądań na 10 minut na adres IP klienta i jest współdzielony przez procesy robocze. Treści JSON są ograniczone do 1 MiB.
- Pomyślna rejestracja zwraca HTTP 201.
- openid i email to uprawnienia tożsamości, niezależne od uprawnień produktu, akceptowane tylko wtedy, gdy są ogłaszane. email wymaga openid. Podczas pierwszej autoryzacji żądanie zawierające wyłącznie zakresy tożsamości używa domyślnych uprawnień produktu pokazanych na ekranie zgody.
Błędy
| Status HTTP | Kod | Znaczenie lub sposób rozwiązania |
|---|---|---|
| 400 | invalid_request | Treść żądania lub rozpoznany parametr są nieprawidłowe, nieobecne, zduplikowane lub mają niewłaściwe kodowanie. |
| 400 | invalid_client_metadata | Nieprawidłowa liczba adresów wywołań zwrotnych, pusta etykieta klienta, nieobsługiwane uwierzytelnianie klienta, typy przyznania uprawnień lub typy odpowiedzi. |
| 400 | invalid_redirect_uri | Adres URL wywołania zwrotnego ma nieobsługiwaną lub niebezpieczną postać. |
| 400 | invalid_scope | Ciąg scope zawiera nieobsługiwane uprawnienie lub nie zawiera żądanych zakresów. |
| 413 | REQUEST_TOO_LARGE | Żądanie przekracza dozwolony rozmiar treści. Limit dla JSON wynosi 1 MiB, a dla formularzy zakodowanych w URL — 32 KiB. |
| 415 | UNSUPPORTED_CONTENT_TYPE | Parser treści integracji przyjmuje wyłącznie JSON lub formularze URL-encoded. Dana trasa może wymagać konkretnego z tych kodowań. |
| 429 | temporarily_unavailable | Osiągnięto publiczny limit częstotliwości żądań OAuth. Przed ponowieniem poczekaj na zakończenie bieżącego okna. |
| 500 | server_error | Autoryzacja jest tymczasowo niedostępna. Spróbuj ponownie później. |
Czy ta strona była pomocna?

