一个消失的密钥字段,堵住了公开插件提交
配置一个预定义的 OAuth 客户端,理论上应该让插件提交流程变得非常简单。你只需要把客户端 ID 和密钥的生成逻辑交给平台,用户在授权时连输入凭证的步骤都能跳过。然而,当 Tapify 团队试图通过 OpenAI 平台的公开插件提交门户发布他们的 MCP 服务时,这个本该丝滑的流程却在最后一步被一个自相矛盾的错误卡住了。
门户的界面上,导入的客户端配置信息清晰可见:认证模式是 provided,客户端 ID 明确写着 tapify-mcp-chatgpt,端点认证方式也是标准的 client_secret_basic。但诡异的事情发生了,那个用于填写 OAuth 客户端密钥的输入框,在页面加载的瞬间闪现了一下,随后便消失无踪。当他们点击 Connect 按钮试图完成连接时,等来的却是一条冰冷的提示:“MCP 详情保存失败:使用预定义 OAuth 客户端凭证时,OAuth 客户端 ID 是必需的。”
这个错误提示让人一时有些困惑。客户端 ID 不是就显示在刚刚保存的配置里吗?为什么平台却认为它缺失了?更奇怪的是,整个 OAuth 登录流程根本没有启动的迹象,仿佛在点击按钮的那一刻,某个校验环节就已经提前判了死刑。
为了弄清楚问题出在哪里,我们不妨先深入看看他们的配置文件。在插件 ZIP 包里的 mcp.json 中,认证相关的关键配置长这样:模式被设置为 provided,客户端 ID 指定了 tapify-mcp-chatgpt,并且使用了 client_secret_basic 作为令牌端点的认证方式。这套配置本身是符合规范的,意图也非常明确——告诉平台,客户端凭证已经由我们这些发布者预置好了,直接拿去用就行。
事实上,他们尝试过另一种模式。最初,他们将模式配置为 cimd,也就是客户端发起的动态注册,期望由平台来引导整个 OAuth 客户端的注册流程。但结果是,同样的错误提示如期而至,平台依然坚持要求一个预定义的客户端 ID。这说明问题的根源似乎并不在于 provided 和 cimd 这两种模式的选择上。随后他们尝试刷新页面,希望这只是一个暂时的界面显示故障,但刷新并没有带来任何改变。
一个值得注意的细节是,同一个开发者账号下,通过个人自定义 MCP 进行连接却是可以正常工作的。这仿佛将问题的范围精确地圈了出来:底层的 MCP 协议交互和 OAuth 授权流程本身没有问题,故障特定地发生在“公开插件提交”这个更为复杂、涉及后台审核与发布的工作流中。
在问题发生时,他们的 OAuth 客户端在后台其实是完全健康的状态。这个已注册的客户端要求 PKCE 和用户同意,使用 client_secret_basic 方式认证,并且正确配置了 https://chatgpt.com/connector_platform_oauth_redirect 作为重定向地址。甚至,实时的服务发现信息也表明,后端服务是支持 CIMD 和 S256 PKCE 的。所有这些信息都指向同一个结论:服务端和配置本身都是坚固的,问题更可能发生在平台门户的前端逻辑,或者其保存配置的后台校验服务上。
他们尝试通过浏览器的开发者工具寻找线索,记录了点击 Connect 时的网络请求。然而,结果令人沮丧,在网络层并没有观察到任何明确失败的 API 请求。观察到的只有成功的应用读取和配置刷新请求。这意味着,那个导致保存失败的校验,很可能是在浏览器端、在请求发送之前就发生了。也许是 JavaScript 在处理表单状态时出现了某种竞态条件,导致那个本应随配置一起被提交的 client_secret 字段,在校验的瞬间被判定为空值,尽管它在界面上显示过。
这种“显示”与“校验”之间的断层,是分布式系统和复杂前端应用中一类比较典型的隐蔽缺陷。平台的前端成功地获取并渲染了后端返回的配置数据,但在将这些数据打包成最终请求前的某个环节,状态的同步出现了偏差。对于开发者而言,这种问题的排查手段往往非常有限,因为错误信息是平台给出的,而真正的故障点却隐藏在平台的代码逻辑深处。
目前,这个公开提交的流程仍然处于阻塞状态。对于遇到类似问题的其他开发者,或许可以先绕道,通过个人自定义 MCP 的连接方式来验证服务的核心功能是否正常,再将主要精力放在向平台方提交详尽的故障报告上。报告中需要包含具体的插件 ID、出问题的 mcp.json 配置片段、错误提示的截图,以及尽可能详细的复现步骤。只有当平台的工程师能够深入检查导入的配置数据与 Connect 表单在提交瞬间的解析状态时,这个堵在半路上的密钥字段才有可能重新出现。

客户端 ID 显示在页面上,但表单提交的时候又“看不见”了 —— 这么典型的前端/后端字段名对不上的问题,作者怎么没查 network 面板一把?