Skip to main content
Clink MCP 让服务端 Agent 以已授权用户的身份调用 Clink 工具。
同一个服务端应用、部署、租户或安装实例复用一个 OAuth client_id。每位用户分别完成 OAuth 授权,服务端为该用户单独保存 Token。不要为每次请求或每个用户注册新的 Client。

先选方案和环境

本文使用 UAT 沙盒和 Production 环境。两套环境的 MCP resource、OAuth resource、Token audience 和元数据地址必须一一对应,不能混用。MCP 配置只填地址,不要填 Access Token、Refresh Token 或 API Key。 先声明两个环境的 base_url,后面的地址都只在其后拼接路径:

环境地址

OAuth Endpoint

下面的路径在两个环境相同,只需和所选环境的 base_url 拼接。授权地址和 Token 地址在可用时应以 Authorization Server Metadata 的返回值为准。
只有 Authorization Server Metadata 返回 registration_endpoint 时才调用 DCR 注册接口;Protected Resource Metadata 不提供 DCR 地址。没有返回时使用 CIMD 或 Pre-registration。

注册和授权的频率

服务端集成

一次性准备 OAuth Client

无论用哪种方案,Client 注册的 Scope 都是之后每次授权请求的上限。申请超出这个范围的 Scope 会返回 invalid_scope,后续补充权限时也一样。所以注册时要写全 Agent 可能用到的 Scope。Clink MCP 使用下面这些 Scope,offline_access 用于签发 Refresh Token:
每次授权请求仍然可以只申请其中一部分。

CIMD

CIMD 适合能维护公开 HTTPS 元数据的服务端 Agent。在自己的 HTTPS 域名下托管公开 JSON 文件,并把文件 URL 作为 client_id:
Clink 会拉取这个文件来校验授权请求,文件需要满足:
  • URL 使用 HTTPS,带路径,不带 query 和 fragment。
  • 文件中的 client_id 与文件 URL 完全一致。
  • 直接返回 HTTP 200,Content-Type 为 application/json;Clink 不会跟随跳转。
  • 文件不超过 5 KB。
CIMD URL 是公开的 Client 标识,文件里不要放 Client Secret。

Pre-registration

Pre-registration 适合固定企业或合作方。接入前把 client_name、固定 HTTPS redirect_uri、当前环境的 resource 和 Agent 可能用到的全部 Scope 提供给 Clink,由 Clink 完成配置并返回固定的 client_id。服务端不调用注册接口,也不需要托管 CIMD 文件;把这个 client_id 放在服务端配置中。 当前 Clink 的预注册 MCP Client 使用 public client,不需要 Client Secret,但仍必须使用 Authorization Code + PKCE(S256)。用户点击“连接 Clink”时,授权请求里的 client_id 使用这个固定值,每位用户的 Token 仍要单独保存。

DCR

DCR 适合需要动态 Client ID、按租户或实例隔离 Client,或目标 Authorization Server 只支持动态注册的场景。先读取 Authorization Server Metadata;只有返回 registration_endpoint 时才调用注册。服务端应在部署、租户开通或首次安装时注册一次,保存返回的 client_id,后续所有用户复用它。
DCR 返回的 client_id 要持久化保存。它只代表 Client 注册成功,后续每位用户仍要单独登录和授权。当前 Clink 示例使用 public client(token_endpoint_auth_method=none),不需要 Client Secret。 Clink 不支持修改已注册的 Client。需要调整 redirect URI 或 Scope 时,要重新注册一个 Client,用户也要用新的 client_id 重新授权。 三种方案的区别在于 client_id 怎么取得,以及 redirect URI 和 Scope 在哪里登记。取得 client_id 后,用户授权、回调换 Token、调用 MCP、刷新 Token 的流程都按下面步骤执行。

用户点击“连接 Clink”时

1

读取 Protected Resource Metadata

请求当前环境的 Protected Resource Metadata,从 authorization_servers 取得 issuer。UAT 地址是 ${UAT_BASE_URL}/.well-known/oauth-protected-resource/mcp。
2

读取 Authorization Server Metadata

请求 {issuer}/.well-known/oauth-authorization-server,读取 authorization_endpoint 和 token_endpoint。不要把端点写死在代码里。
3

生成 state 和 PKCE 参数

服务端为当前用户生成随机 state 和 PKCE code_verifier,临时保存它们与内部用户 ID 的绑定,用 S256 计算 code_challenge。
4

重定向到授权地址

将下面参数全部 URL 编码后带上。CIMD 使用公开 JSON 文件 URL;Pre-registration 使用 Clink 提供的固定 Client ID;DCR 使用注册接口返回并持久化的 Client ID。
scope 按当前需要申请,且不能超出 Client 注册的 Scope。MCP Server 首次返回的 401 会要求 wallet:read events:read events:consume;提前申请这两个 events Scope,可以避免 Operation 进行中再弹一次授权。需要 Refresh Token 时要包含 offline_access。UAT 和 Production 必须使用各自对应的 resource。

回调换 Token

用户完成登录和授权后,回调会收到 code、state 和 iss;授权失败时会收到错误参数。如果 state 与保存的值不一致,或 iss 缺失、与 Authorization Server Metadata 中的 issuer 不一致,直接拒绝这次回调。 然后向 token_endpoint 发送 POST 请求,Content-Type 为 application/x-www-form-urlencoded。使用同一个回调地址和保存的 PKCE verifier,每个参数值都要 URL 编码:
这是 public client,不需要 client_secret 或 device_id。按内部用户 ID、环境和 client_id 加密保存 access_token、refresh_token、过期时间和 Scope。授权码只能兑换一次。

用 Token 调 MCP

后端用当前用户的 Access Token 请求对应环境的 /mcp。Clink MCP 支持 2026-07-28 和 2025-06-18 两个协议版本。建议使用官方 MCP Client SDK:它会协商版本、发送必需的请求头并解析流式响应。让 SDK 指向 MCP 地址,并在运行时为当前用户带上 Authorization: Bearer 请求头。 如果直接发送 HTTP 请求,请使用 2025-06-18 流程。2026-07-28 没有 initialize 握手,并且每个请求都要附带协议元数据,建议交给 SDK 处理。
  1. 发送 initialize,protocolVersion 设为 2025-06-18。
  2. 发送 notifications/initialized。
  3. 调用 tools/list 获取工具。
  4. 调用 tools/call 执行业务。
每个请求都要带上面的 Accept 请求头,否则服务端返回 406。响应可能是 text/event-stream 流,其中每个 data: 行是一条 JSON-RPC 消息。initialize 之后的每个请求,都要在 MCP-Protocol-Version 请求头里带上协商出的版本:

处理需要用户打开的链接

部分工具结果会带 next_action,其 type 为 REDIRECT_USER,例如绑卡、完成 3DS 或为 Agent Pay 注册卡片。通过你自己的渠道把 params.redirect_url 发给用户。params.actor 为 USER_DEVICE_ONLY 时,必须由用户在自己的设备上打开,不要在 Agent 控制的浏览器里打开。用户从页面返回不代表这一步已经成功,要调用 get_operation 读取结果。

刷新和恢复

Access Token 过期时,向同一个 token_endpoint 提交 grant_type=refresh_token、原 client_id、当前 Refresh Token 和同一个 resource。 每次刷新都会返回新的 Refresh Token,旧的随即失效。先保存新的 Refresh Token,再使用新的 Access Token。如果再次提交已失效的 Refresh Token,Clink 会判定为重复使用,并撤销这次授权下的全部 Refresh Token,用户必须重新授权。刷新操作要按用户、环境和 client_id 串行,多实例部署时也要保证。
  • 遇到 401 时刷新 Token;刷新失败则让用户重新授权。
  • 遇到 403 且错误为 insufficient_scope 时,从 WWW-Authenticate 响应头的 scope 参数读取所需 Scope,与已授予的 Scope 合并后让用户重新授权。合并后的 Scope 不能超出 Client 注册的 Scope。
  • 支付、退款或指令超时时调用 get_operation 查询,不能直接重复执行。

上线检查

  • Client 注册只在初始化、部署、租户开通或首次安装时执行。
  • Client 注册时写全 Agent 可能用到的 Scope,授权时只申请当前需要的 Scope。
  • 每个用户的 Token、会话和 Operation 隔离保存。
  • 回调地址与 Client 配置逐字符一致。
  • Token、Client Secret 不放进配置、CIMD 文件或日志。
  • UAT 和 Production 地址不混用。
  • Refresh Token 按用户、环境和 client_id 串行使用。
  • REDIRECT_USER 链接发给用户打开,不要在 Agent 控制的浏览器里打开。