> ## Documentation Index
> Fetch the complete documentation index at: https://api-docs.voicecheap.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# 注册 MCP OAuth 客户端

> 使用完全匹配的回调 URL 和一组受限的产品权限注册公开客户端。

使用完全匹配的回调 URL 和一组受限的产品权限注册公开客户端。

```http theme={null}
POST https://api.voicecheap.ai/oauth/register
```

## 身份验证

无需身份验证。注册不会使用户登录，也不会授权账户连接。

## 请求体

<ParamField body="redirect_uris" type="array" required>
  去重前须有 1 到 10 个回调地址。

  最少项目数: 1. 最多项目数: 10.
</ParamField>

<ParamField body="client_name" type="string">
  可选的客户端标签；保存前会去除首尾空白，处理后必须非空。

  最小长度: 1. 最大长度: 120. 匹配模式: `^(?=.*\S)[^\u0000-\u001F\u007F]+$`. 默认值: "MCP client".
</ParamField>

<ParamField body="token_endpoint_auth_method" type="field">
  仅限公共客户端。

  指定值: "none". 默认值: "none".
</ParamField>

<ParamField body="grant_types" type="union">
  必须包含 authorization\_code；refresh\_token 可选。省略或设为 null 时选择两者。重复值会被移除。

  默认值: \["authorization\_code","refresh\_token"].
</ParamField>

<ParamField body="response_types" type="array">
  值列表。项目结构请参阅完整输入架构。

  最少项目数: 1. 最多项目数: 1. 默认值: \["code"].
</ParamField>

<ParamField body="scope" type="string">
  以空格分隔、选自 scopes\_supported 的权限，可包含 offline\_access。不支持的名称和仅含空白字符的值会被拒绝；重复项会被移除。省略 scope 或不提供任何产品权限（例如仅提供 openid 或 offline\_access）时，会注册所有受支持的产品范围。email 必须与 openid 一起使用；仅提供 email 会被拒绝。OpenID Connect 可用时，即使省略 scope，注册也会将 openid 和 email 纳入客户端能力。注册本身不授予访问权；身份权限需要显式授权请求及用户同意。

  最小长度: 1. 最大长度: 2048. 匹配模式: `^ *(?: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))* *$`.
</ParamField>

<Accordion title="技术架构">
  ```json theme={null}
  {
    "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
  }
  ```
</Accordion>

## 请求示例

请遵循此路由文档规定的编码和身份验证方式。操作 API 的封装格式和幂等性规则仅适用于操作调用。

<RequestExample>
  ```bash cURL theme={null}
  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"}'
  ```

  ```javascript JavaScript theme={null}
  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());
  ```

  ```python Python theme={null}
  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)
  ```
</RequestExample>

## 响应

已注册的公开客户端元数据。请保存 client\_id，并将其与完全匹配的已注册 redirect\_uri 一起使用。不签发 client\_secret。

```json HTTP 201 theme={null}
{
  "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"
}
```

## 响应头

```json theme={null}
{
  "Cache-Control": "no-store",
  "Pragma": "no-cache"
}
```

## 操作说明

* 受支持的标量参数必须仅提供一次，值须为不含 ASCII 控制字符或 DEL 的非空字符串。重复的查询或表单字段会解码为数组，在按标量读取时会被拒绝。
* 使用 Content-Type application/json。URL 编码的注册请求体会被拒绝，并返回 OAuth invalid\_request 响应；不受支持的媒体类型可能先被集成解析器拒绝。
* 重定向 URI 会原样保留并进行精确比较。更改大小写、端口写法、路径、查询或末尾斜杠时，必须注册该确切 URI。
* HTTP 回调仅接受原样的回环名称 localhost、127.0.0.1 和 \[::1]。私有网络主机、其他 IP 拼写形式、\*.localhost 和大写的 LOCALHOST 均不符合要求。
* 唯一接受的自定义 URI 协议回调必须完全为 cursor://anysphere.cursor-mcp/oauth/callback。
* 每个回调都必须通过验证；只要一个回调无效，整个注册请求就会被拒绝。URL 中的凭据、空白字符、控制字符、片段标识符和反斜杠均不允许使用。
* 客户端可注册任意受支持的产品权限范围，但用户须在授权时另行批准所请求的子集。仅完成注册不会授予任何访问权限。
* 仅支持 authorization\_code 和可选的 refresh\_token 授权类型。注册时未包含 refresh\_token 的客户端不会收到刷新令牌。
* 当前实现会忽略未知的顶层 metadata 字段。已知字段仍须遵守架构中显示的约束。
* 公开注册限制为每个客户端 IP 每 10 分钟 10 次请求，由所有工作进程共用。JSON 请求体上限为 1 MiB。
* 注册成功时返回 HTTP 201。
* openid 和 email 是独立于产品权限的身份权限，仅在公布支持时接受。email 需要 openid。在首次授权时，仅包含身份权限的请求会使用同意页面显示的默认产品权限。

## 错误

| HTTP 状态 | 代码 | 含义或恢复方式 |
| - | - | - |
| 400 | `invalid_request` | 请求体或已识别的参数无效、缺失、重复或编码错误。 |
| 400 | `invalid_client_metadata` | 回调地址数量无效、客户端标签为空，或客户端身份验证、授权类型、响应类型不受支持。 |
| 400 | `invalid_redirect_uri` | 某个回调 URL 使用了不受支持或不安全的形式。 |
| 400 | `invalid_scope` | scope 字符串包含不支持的权限，或未请求任何范围。 |
| 413 | `REQUEST_TOO_LARGE` | 请求超出允许的请求体大小。JSON 上限为 1 MiB，URL 编码表单上限为 32 KiB。 |
| 415 | `UNSUPPORTED_CONTENT_TYPE` | 集成请求体解析器仅接受 JSON 或 URL 编码表单。具体路由可能要求使用其中一种编码。 |
| 429 | `temporarily_unavailable` | 已达到公开 OAuth 请求速率上限。请等待当前时间窗口结束后重试。 |
| 500 | `server_error` | 授权暂时不可用。请稍后重试。 |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.