ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Cline MCP OAuth 本地测试服务器:完整复现 MCP 授权流程与各类故障模式

Cline MCP OAuth 本地测试服务器:完整复现 MCP 授权流程与各类故障模式 Cline MCP OAuth 本地测试服务器完整复现 MCP 授权流程与各类故障模式【免费下载链接】clineAutonomous coding agent as an SDK, IDE extension, or CLI assistant.项目地址: https://gitcode.com/GitHub_Trending/cl/clineCline 在接入需要 OAuth 授权的远程 MCP 服务器时会经历资源元数据发现、动态客户端注册DCR、浏览器授权确认、PKCE 换票、回调 state 校验等一系列环节。本文基于仓库中的 mcp-oauth-test-server 文档讲解如何用这个零依赖仅 Nodehttp的本地测试服务器一键复现完整的 MCP OAuth 流程及其典型故障模式state 过期、用户拒绝授权并结合 server.ts 源码剖析其端点设计、故障注入参数与调试挂具debug harness集成方式。一、它是什么一台服务器扮演两个角色真实的 MCP OAuth 链路涉及两个独立的远端角色OAuth 2.0 授权服务器签发 token 的 IdP和MCP StreamableHTTP 资源服务器提供工具调用端点、返回 401 触发授权。要调试 Cline 的 OAuth 行为通常需要同时部署两者而这台测试服务器把它们合二为一OAuth 2.0 Authorization Server遵循 RFC 8414 / RFC 7591 DCR / RFC 7636 PKCEGET /.well-known/oauth-protected-resource— 受保护资源元数据RFC 9728GET /.well-known/oauth-authorization-server— 授权服务器元数据POST /register— 动态客户端注册Dynamic Client RegistrationGET /authorize— 交互式Approve / Deny同意页POST /token—authorization_coderefresh_token两种授权类型MCP StreamableHTTP 资源服务器POST /mcp— 未认证时返回401 WWW-Authenticate: Bearer resource_metadata...这正是触发 Cline 启动 OAuth 流程的信号认证后返回最小化的initialize响应。从源码可以确认端点形态刻意对齐modelcontextprotocol/sdkv1.25.x 的发现逻辑server.ts 的路由同时匹配/.well-known/oauth-protected-resource和/.well-known/oauth-authorization-server的带路径后缀变体SDK 会探测两种形式并且兼容/.well-known/openid-configuration作为授权服务器元数据的别名。服务端返回的元数据内容在 server.ts 中定义核心字段包括{ issuer: http://127.0.0.1:7777, authorization_endpoint: .../authorize, token_endpoint: .../token, registration_endpoint: .../register, response_types_supported: [code], grant_types_supported: [authorization_code, refresh_token], code_challenge_methods_supported: [S256], token_endpoint_auth_methods_supported: [none, client_secret_post], scopes_supported: [mcp] }注意一个源码中特意处理的细节当使用随机端口时所有输出发现元数据、重定向目标、/mcp资源 id都必须使用实际绑定后的端口见 server.ts 中boundPort的注释否则 SDK 侧的redirect_uri/resource校验会失败——这也是很多自研 OAuth 测试桩容易踩的坑。二、快速上手启动并接入 Cline在apps/vscode目录下启动package.json 中注册了对应的 dev 脚本cd apps/vscode bun run dev:mcp-oauth-test-server -- --verbose # 或直接运行源码 bun src/dev/mcp-oauth-test-server/server.ts --verbose启动后除了横幅服务器还会打印一段可直接粘贴的mcpServersJSON 片段采用cline_mcp_settings.json使用的嵌套transport形态。将其合并到~/.cline/data/settings/cline_mcp_settings.json的mcpServers下即可。该片段由 server.ts 的buildSettingsFragment生成单实例时服务器名为oauth-test多实例时自动加序号后缀oauth-test-1…{ mcpServers: { oauth-test: { transport: { type: streamableHttp, url: http://127.0.0.1:7777/mcp } } } }也可以不写配置直接在 Cline 中手动添加一个 StreamableHTTP 类型的 MCP 服务器指向http://127.0.0.1:7777/mcp。随后点击Authenticate浏览器会打开/authorize同意页你可以在上面点击Approve或Deny见 server.ts 中渲染的深色风格同意页页面上会展示client_id与redirect_uri供核对。三、故障注入参数全解服务器通过 CLI 参数控制故障注入参数解析逻辑见 server.ts 的parseArgsFlag说明--port n监听端口默认7777环境变量MCP_OAUTH_TEST_PORT可覆盖。0表示请求 OS 分配的随机端口--random-port直接绑定 OS 分配的随机空闲端口忽略--port--instances n启动 N 个相互独立的服务器实例各自使用随机端口隐含--random-port用于一次向 Cline 添加多个 MCP 服务器--auto-approve跳过同意页始终批准授权--auto-deny跳过同意页始终拒绝等效于点 Deny--code-ttl ms授权码authorization code有效期默认60000010 分钟。设小如1000可强制触发过期竞争--slow-authorize ms延迟/authorize的响应模拟在同意页停留很久的用户--verbose,-v记录每一个请求前缀[mcp-oauth-test]--help,-h显示帮助参数之间存在约束源码中做了显式校验--auto-approve与--auto-deny互斥同时指定会直接报错退出--instances必须是正整数--instances 1时强制转为随机端口多个实例无法共享同一固定端口。四、复现两类典型的 OAuth 故障README 的核心价值在于无真实远端也能复现 MCP OAuth 的失败模式两类最值得关注的场景4.1 State 过期竞争Cline 的McpOAuthManagerMcpOAuthManager.ts对交互式 OAuth 流程施加了一个时间窗口——从当前源码看MCP_OAUTH_FLOW_TIMEOUT_MS被定义为 10 分钟即浏览器回调若在此窗口内未返回流程会被判为超时。测试服务器文档中将该窗口称为 state 生命周期MCP_OAUTH_STATE_EXPIRY_MS两者语义一致回调回来时 state 已失效即被拒绝。要复现只需让/authorize的响应慢于这个窗口bun src/dev/mcp-oauth-test-server/server.ts --slow-authorize 605000 --verbose源码中--slow-authorize的实现就是在响应前await delay(ms)server.ts精确模拟用户在同意页磨蹭了 10 分 05 秒。4.2 用户拒绝授权同意页的 Deny 按钮或--auto-deny会让重定向带上erroraccess_denied符合 RFC 6749 §4.1.2.1从而观察 Cline 对拒绝的处理路径bun src/dev/mcp-oauth-test-server/server.ts --auto-deny --verbose对应源码见 server.ts拒绝时向redirect_uri回传erroraccess_denied、error_description及原样带回的state。4.3 授权码层面的过期与防重放除 state 之外/token端点还内建了完整的授权码安全校验server.ts一次性使用code 在兑换后立即从内存删除二次兑换返回invalid_grantTTL 校验Date.now() - issuedAt codeTtlMs时返回Authorization code expired配合--code-ttl 1000可以演练过期竞争redirect_uri 一致性换票时提交的redirect_uri必须与授权时注册的完全一致否则invalid_grantPKCE S256 校验对code_verifier做base64url(sha256)后与授权阶段捕获的code_challenge比对不匹配即拒绝。此外授权阶段还会拒绝未注册的 redirect_uriserver.ts并在错误信息中直接列出该 client 已注册的 redirect 列表——这正是真实环境中loopback 端口变化导致注册失配的复现手段。五、多实例并发 OAuth 流程演练bun src/dev/mcp-oauth-test-server/server.ts --instances 3 --verbose每个实例绑定自己的随机端口并各自打印/mcp端点把它们分别加为 Cline 中独立的 StreamableHTTP 服务器即可演练并发 OAuth 流程与多个已认证服务器并存的情形。这里有一个关键设计Cline 的 OAuth state 以服务器名为键存储于cline_mcp_settings.json因此每个 Cline 服务器条目拥有独立的 token——即使两个条目的 URL 完全相同也会各自走一遍注册与授权这也是多实例命名加序号后缀的原因。六、frozzle 工具用不可幻觉的结果证明链路真的通了一个容易被忽略但设计精妙的点/mcp端点认证后不仅响应initialize还暴露了一个名为frozzle的 MCP 工具server.ts。其描述刻意不透露变换规则因此模型无法凭空算出结果——只有真正通过OAuth 认证后的MCP 连接调用了工具才能得到正确答案。这使让 agent frozzle 一段文本并核对输出成为评估场景中验证OAuth 后的 MCP 往返确实发生、而非幻觉的可靠端到端信号。变换本身确定且可逆反转字符串、逐字符交换大小写、用« »包裹例如frozzle(Hello) «OLLEh»。实现见 server.ts并有独立单测 frozzle.test.ts。tools/list、tools/call、initialize之外的其他 JSON-RPC 方法则统一返回空结果result: {}避免让 SDK 误判出错。七、与 debug harness 的集成无浏览器驱动全流程该服务器同时是 Cline 调试挂具的配套设施模块只在被直接执行时才自动启动server.ts 中的isMain判断导出的TestServer、TestServerOptions和parseArgs允许挂具在进程内import后直接拉起一个实例。无浏览器驱动链路的要点详见 debug-harness/README.md 的 Testing MCP OAuth 章节设置CLINE_CAPTURE_BROWSER1定义见 env.tsCline 原本要打开的授权 URL 会被捕获而不是真实启动浏览器挂具curl该被捕获的/authorizeURL追加decisionapprove或decisiondeny即可跳过 HTML 同意页直接拿到重定向从重定向的Location头中提取vscode://回调再通过globalThis.__clineHandleUri(...)投递给扩展完成整条链路。这正是/authorize支持decision查询参数server.ts存在的原因该参数既是同意页按钮的回跳方式也是脚本化驱动的入口。八、纯脚本方式手工走一遍协议不依赖浏览器与 Cline也可以用curl完成发现、注册、授权README Manual flow 一节PORT7777 # 1. 发现授权服务器元数据 curl -s localhost:$PORT/.well-known/oauth-authorization-server # 2. 动态注册一个 client CID$(curl -s -X POST localhost:$PORT/register -H Content-Type: application/json \ -d {redirect_uris:[http://127.0.0.1:48801/cb]} \ | node -e process.stdin.on(data,dconsole.log(JSON.parse(d).client_id))) # 3. Approve 并捕获重定向 Location 头中的 code # 追加 decisionapprove 可跳过 HTML 同意页第 3 步拿到code后还需携带grant_typeauthorization_code、redirect_uri和 PKCEcode_verifier向POST /token换票。作为对照/register的实现要求请求体必须包含非空的redirect_uris数组client_id形如client_24位hex并回显grant_types、response_typesserver.ts。九、延伸阅读Cline 侧的 OAuth 状态管理测试服务器只是链路的一半Cline 扩展侧的实现集中在McpOAuthManager.ts负责按服务器名读写~/.cline/data/settings/cline_mcp_settings.json中每个服务器的oauth状态与cline/coreCLI/JetBrains 共用同一格式通过跨进程锁做范围化写入以避免并发覆盖从源码结构看扩展侧还定义了本地回调端口池MCP_OAUTH_CALLBACK_PORTS1456–1461并默认优先复用已存储的redirectUrlMcpHub.ts 与 mcpAuth.tsMCP 服务器管理与授权状态的协作层debug-harness/README.md挂具驱动的 MCP OAuth 自动化测试说明。适用前提与小结运行前提是 Bun 环境脚本在apps/vscode包内执行服务器绑定127.0.0.1仅用于本机调试内存态设计client、code、refresh token 全部存于Map意味着进程重启即清空正好符合每次从零注册的调试心智它模拟的是modelcontextprotocol/sdkv1.25.x 的发现行为若 Cline 依赖的 SDK 版本升级改变了发现端点形态需同步核对 server.ts 的元数据与路由。掌握这台测试服务器后开发者可以在不依赖任何真实远端 IdP 的情况下端到端验证 Cline 的 MCP OAuth 全链路并把 state 过期、用户拒绝、redirect_uri 失配、PKCE 校验失败、code 过期/重放等边界情况逐一复现和回归验证。【免费下载链接】clineAutonomous coding agent as an SDK, IDE extension, or CLI assistant.项目地址: https://gitcode.com/GitHub_Trending/cl/cline创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表