浏览 MCP与Skills教程与资源
MCP 401 与 403 排查:先识别拒绝请求的是哪一层
分别检查 MCP 端点认证、下游服务授权和网关策略,用响应位置、WWW-Authenticate 与同身份对照请求决定下一步,避免一报错就扩权。
同一个‘403’,可能根本还没进入 MCP Server
| 位置 | 常见证据 | 该找谁修 |
|---|---|---|
| 代理、WAF 或访问网关 | 响应是网关 HTML/品牌错误页,Server 没有相应请求记录 | 网络或网关策略;换 API Key 未必有用 |
| MCP HTTP 端点 | 请求本身返回 401/403,可能带 WWW-Authenticate | MCP 连接所用身份、凭证、作用域或 Origin 校验 |
| 工具内部的 GitHub/Notion 等下游 | 外层 MCP 调用已完成,工具错误里包含下游 401/403 | 该 Server 访问下游使用的凭证与资源权限 |
| 客户端预先拒绝 | 没有真正发出的网络请求,界面显示权限或工具被禁用 | 客户端工具过滤/审批;不等于服务端鉴权失败 |
先记录请求时间、目标主机、HTTP 状态、错误正文类型和脱敏 request ID。不要把完整 Authorization、Cookie 或授权码复制进问题报告。
401 是认证分支,403 仍要看具体错误
下面是为了说明字段而构造的 HTTP 片段,不是某台服务器的运行日志。采用 MCP OAuth 的服务应使用为该资源签发的令牌;一个别处可用的 API Key 不会自动成为此 MCP 的令牌。
无效令牌与缺少 scope
HTTP/1.1 401 Unauthorized WWW-Authenticate: Bearer error="invalid_token" HTTP/1.1 403 Forbidden WWW-Authenticate: Bearer error="insufficient_scope", scope="documents:read"
documents:read 是用于解释机制的虚构 scope,不是 Notion、GitHub 或 Codex 的配置参数。真实 scope 必须取自该服务的挑战和官方说明,不能照抄这个字符串。
先证明确实发送了正确来源的凭证
- 01
辨认服务要求的认证类型
公开只读服务可能不需要认证;OAuth 服务需走客户端授权;PAT 服务使用对应提供方的令牌。不要把 OpenAI API Key 填入 GitHub MCP,也不要向未知重定向域名发送 Token。
证据:官方端点与认证说明,而不是工具名称里含有哪个品牌。 - 02
核对客户端实际使用的凭证来源
若配置引用环境变量,确认启动客户端的进程拥有该变量;GUI 重启后才会继承新的环境。若使用 OAuth,确认当前连接和当前用户对应的授权,避免只在另一个浏览器账号登录。
只记录变量是否存在、凭证标签和到期信息,不输出令牌值。 - 03
按提供方机制续期或重新授权
对已过期/已撤销的凭证重新登录或生成新令牌,再更新真实使用位置。JWT 的本地解码只能读声明,不能证明签名有效;opaque token 甚至不能这样查看。
由服务端对原请求的响应验证,不把本地解码当验证。 - 04
重复同一个最小请求
身份、资源、动作和参数保持不变。若已从 401 变为工具级无权读取,说明来到下一层,需要继续查资源授权,不能说整个问题已解决。
保存脱敏的前后响应,不同时换仓库或改业务对象。
用同身份的成功/失败对象找出差异
| 对照结果 | 优先检查 | 不该直接做 |
|---|---|---|
| 同一连接能读测试仓库 A,仓库 B 失败 | 资源所有者、PAT 所选仓库、组织审批和实际资源 ACL | 生成全仓库管理员 Token 来掩盖差异 |
| 同一页面能读,更新失败 | 本次任务是否需要写、Server 是否只读、凭证是否有写权限 | 为一个读取任务打开全部写能力 |
| 所有调用突然 403,并有速率限制说明 | Retry-After、速率响应头、近期并发和服务状态 | 把限流误判成少一个 scope |
| 本地 HTTP Server 返回 Origin 拒绝 | 客户端 Origin 与 Server 允许来源是否匹配 | 关闭所有 Origin 校验;这不是 OAuth scope 问题 |
| 权限申请仍在 pending | 组织审批状态和管理员策略 | 重建相同令牌期望绕过审批 |
GitHub:公开资源成功,不证明私有仓库已获授权
假设同一 github_issues 连接能读取公开 Issue,却读不到你选定的私有 acme/demo-app #42。先确认 owner/repo/#42 的 URL 正确,再检查 fine-grained PAT 的资源所有者、所选仓库、Issues 只读权限和组织批准状态。GitHub 对某些无权私有对象会返回 404,以避免泄露对象是否存在,所以 404 也要放进这个对照。
如果 MCP 外层响应正常,而 issue_read 的工具结果说 GitHub 拒绝了请求,调试重点在下游 GitHub 授权。如果 MCP 地址本身立即 401,先查 Codex 的 bearer_token_env_var。两者使用的错误位置不同,不能仅凭用户界面的一行‘unauthorized’猜根因。
权限缺口不是靠重复请求补出来的
明确的 scope/角色/组织策略拒绝,应先确定任务确实需要对应权限,再走授权流程;同一个无变化请求不停重试既不能扩大权限,还可能触发限流。若客户端在授权后仍用旧令牌,先定位凭证读取位置和缓存,不要留下多份不知谁在使用的 Token。
修复记录只需说明:哪层拒绝、已确认的身份与对象、最小变更、原请求的新结果。没有服务端证据时可写‘疑似网关策略,尚未定位’,不能把 403 一律翻译成‘身份有效但 scope 不够’。
