本页面适用于 Apigee 和 Apigee Hybrid。
查看 Apigee Edge 文档。
本页面介绍了如何排查和解决 MCP 发现代理部署问题。您可以使用此页面了解 MCP 部署的异步预配生命周期、解决错误代码并验证运行时连接性。
了解 MCP 部署
MCP Discovery 代理的部署是一个异步的多步骤过程,可确保在代理部署完成之前,配置已在 Apigee 和 Google Cloud 基础架构中完全传播。
在执行这些下游预配步骤时,界面会显示代理处于预配状态。 流程完成后,状态会更改为已部署。此状态确认所有下游组件均已完全预配,并且代理已准备好处理流量。
问题排查
以下部分介绍了您在 Apigee 中使用 MCP 时可能会遇到的错误和已知问题。
后端未在预期位置收到工具实参
问题:后端从一个请求位置(查询字符串、标头或 Cookie)读取工具实参,但 OpenAPI 规范在另一个位置声明了形参 in,因此实参会到达后端请求中的其他位置。调用会失败或表现得就像参数不存在一样。
症状:tools/call 请求在 MCP 层成功,并且 MCP 客户端提供了参数,但后端响应就像缺少值一样,例如,缺少必需值时返回 400,或者应用默认值来代替发送的值。
原因:该参数在 OpenAPI 规范中声明为 in: header 或 in: cookie,因此 Apigee 会将其值作为请求标头或在 Cookie 标头中发送,而不是在查询字符串中发送。仅从查询字符串中读取值的后端不会看到该值。请参阅后端请求中的工具参数放置。
解决方法:确定值所属的位置,并使规范和后端保持一致:
- 如需在查询字符串中保留该值,请声明参数
in: query。 - 如需将其作为标头或 Cookie 发送,请保持声明不变,并从后端中的该位置读取值。
后端停止接收 MCP 客户端请求携带的 Cookie
问题:在某些工具调用中,MCP 客户端发出的 HTTP 请求中包含的 Cookie(例如基于浏览器的客户端发出的会话 Cookie)无法到达后端。
症状:后端表现得好像调用方未通过身份验证或未处于会话中,并且行为不一致:同一操作在某些调用中有效,而在其他调用中无效。
原因:该操作声明了一个或多个 in: cookie 参数,并且受影响的调用提供了其中至少一个参数。Cookie 标头会作为一个整体被重写,而不是被附加,因此在这些调用中,它仅携带声明的 Cookie 参数,而所有其他 Cookie 都会被丢弃。未提供任何 Cookie 参数的调用会原封不动地传递标头,因此只有部分调用会失败。请参阅发送到后端的请求中的 Cookie。
解决方法:在每个需要 Cookie 的操作中,将后端所需的每个 Cookie 声明为 in: cookie 参数,以便其值始终由工具调用提供,而不是从客户端请求继承。没有任何设置可以保留未声明的 Cookie。
工具调用和元数据的错误响应状态代码
Apigee MCP 端点会返回遵循 Model Context Protocol (MCP) 规范和相关 OAuth 标准的 HTTP 状态代码。了解此行为有助于您在 MCP 客户端或 AI 智能体中正确处理错误。
下表总结了 Apigee MCP 端点返回的状态代码:
| 场景 | HTTP 状态代码 | 响应正文 |
|---|---|---|
工具执行在 tools/call 上失败(例如,后端 API 返回 4xx 或 5xx 错误,例如验证错误或缺少必填字段)。 |
200 OK |
CallToolResult,其中 result.isError 设置为 true,错误详情位于 content 中。这样,MCP 客户端和 LLM 代理就可以读取错误并进行恢复(例如,通过重新提示输入缺失的内容并重试),而不是终止会话。 |
未配置 OAuth 受保护资源元数据 (PRM),或在 /.well-known/oauth-protected-resource/mcp 找不到该元数据。 |
404 Not Found |
表示在请求的位置没有可用的受保护资源元数据。 |
| 访问令牌缺失、无效或已过期。 | 401 Unauthorized |
包含用于驱动 OAuth 发现流程的 WWW-Authenticate 质询。 |
| 访问令牌的范围不足。 | 403 Forbidden |
包含 WWW-Authenticate 质询,用于驱动升级授权流程。 |
示例:工具执行错误响应正文
当工具调用失败时,Apigee MCP 会返回 HTTP 200 OK,并在 JSON-RPC result 对象中报告失败,其中 isError 设置为 true。后端返回的原始错误会保留:后端响应正文会逐字(作为字符串)放置在 result.content[].text 中。例如,如果后端返回 HTTP 404 且正文为 {"error":"User 42 not found"},则 MCP 响应为:
{ "jsonrpc": "2.0", "id": 1, "result": { "content": [ { "type": "text", "text": "{\"error\":\"User 42 not found\"}" } ], "isError": true } }
id 与 tools/call 请求的 id 匹配。
如果后端未返回响应正文,则 text 会包含生成的摘要,例如 Operation failed (HTTP 500).
您的 MCP 客户端应检查 result.isError(而非 HTTP 状态代码),以检测失败的工具调用。如果您的客户端代码专门预期 4xx 或 5xx HTTP 状态来指示工具执行错误,则它不会检测到错误,因为响应为 HTTP 200 OK。请更新此类客户端,使其读取 result.isError 和 content 数组。
协议级错误(例如,格式错误的 JSON-RPC 请求)与工具执行错误不同:它们会继续在 JSON-RPC error 对象(例如 {"jsonrpc": "2.0", "error": {"code": -32700, ...}})中返回,而不是在 result.isError 中返回。
建议:符合标准的 MCP 客户端会通过其默认逻辑处理这些状态代码,因此无需进行任何更改。如果您之前添加了客户端权宜解决方法来处理非标准状态代码(例如,解析非 2xx 响应正文以查找 tools/call 错误,或将来自 PRM 端点的 500 响应视为“元数据未配置”),我们建议您移除该权宜解决方法。否则,您的客户端可能会继续使用过时的处理逻辑,而不是正常处理更正后的状态代码。
针对基于浏览器的 MCP 调用的 CORS 政策
当直接从浏览器发出 Apigee MCP 调用时(例如,当 MCP 检查器使用“直接”设置而非“通过代理”时),需要使用跨域资源共享 (CORS) 政策。默认情况下,MCP 发现代理模板在代理包的代理端点请求 PreFlow 中包含 Apigee CORS 政策,以启用基于浏览器的调用。
如果您在直接从浏览器发出调用时遇到与 CORS 相关的问题,则可能需要调整 MCP Discovery 代理软件包的代理端点请求 PreFlow 中的 CORS 政策设置。
向 MCP 端点发送请求时发生 JSON 解析错误
向 MCP 端点发送请求时,您可能会收到类似于以下内容的出错提示(或具有不同的错误代码和消息):
{
"error": {
"code": -32700,
"message": "JSON parse error"
},
"id": null,
"jsonrpc": "2.0"
}在这种情况下,我们建议您确认以下信息:
- 您输入的 MCP 端点网址正确。
- 您的请求格式正确。
- 您正在访问受支持的方法。
- 您已在 受支持的国家/地区中启用并配置 MCP Discovery Proxy。如需查看可能存在容量限制的区域列表,请参阅部署失败。
部署失败
如果 MCP Discovery Proxy 部署失败,且界面中显示失败状态,请查看出错提示了解详情。常见的失败情况包括:
- 网络配置失败或 OAS 中的架构不受支持:这些错误通常表示 OpenAPI 规范存在问题。确保您的规范有效且使用受支持的版本。
- 区域容量限制(仅限 Apigee):如果您看到与负载均衡器预配失败相关的错误,或者预配状态从未更改为已部署,则可能是由于以下某个区域存在临时基础架构容量限制:
asia-east2asia-northeast3asia-southeast2australia-southeast1europe-central2europe-west12europe-west9me-central2us-central2
如需解决该错误,请尝试将代理部署到其他区域中的环境。此故障模式不适用于 Apigee Hybrid,其中运行时基础架构是您自己的集群。
- 集群中未启用 MCP(仅限 Apigee Hybrid):如果 MCP 代理部署无限期保持正在预配状态,并且从未达到已部署状态,请验证集群中是否已启用 MCP。请参阅下文的集群端诊断。
集群端诊断(仅限 Apigee Hybrid)
由于 Apigee Hybrid MCP 数据平面在您自己的 Kubernetes 集群中运行,因此集群内故障模式会通过针对集群运行 kubectl 来诊断。请按顺序完成以下诊断核对清单。
第 1 步:验证集群中是否已启用 MCP
MCP 部署为 ApigeeDeployment 自定义资源(由 Apigee Operator 管理),而不是普通 Kubernetes Deployment。检查 MCP ApigeeDeployment:
kubectl -n APIGEE_NAMESPACE get apigeedeployment -l app=apigee-mcp-server
预期输出(资源名称包含组织派生的后缀,此处显示为 ORG_CR_SUFFIX):
NAME STATE NESTEDSTATE AGE apigee-mcp-server-default-ORG_CR_SUFFIX running 1h
如果该命令返回 No resources found in APIGEE_NAMESPACE namespace.,则表示 MCP 未启用。返回到在 Apigee Hybrid 中启用 MCP,并验证 enableMcpServer: true 是否已设置为 overrides.yaml 中的顶级键,以及您是否在 apigee-org 版本之前升级了 apigee-operator Helm 版本。请参阅启用过程的第 3 步和第 4 步,了解正确的 helm 命令。
第 2 步:验证 MCP pod 是否正在运行
kubectl -n APIGEE_NAMESPACE get pods -l app=apigee-mcp-server
预期输出(Pod 后缀会有所不同):
NAME READY STATUS RESTARTS AGE apigee-mcp-server-default-ORG_CR_SUFFIX-1170-abcd1234 2/2 Running 0 1h apigee-mcp-server-default-ORG_CR_SUFFIX-1170-efgh5678 2/2 Running 0 1h
Pod 名称遵循模板 apigee-mcp-server-default-ORG_CR_SUFFIX-REV-POD_HASH,其中 REV 是四位数的 Hybrid 版本修订版本(例如,Hybrid 1.17.0 的 1170),POD_HASH 是一个八字符的字母数字后缀,每个 Pod 的后缀都不同。
每个 Pod 都必须在 READY 列中显示 2/2,在 STATUS 列中显示 Running。如果 Pod 不是 Running,kubectl -n APIGEE_NAMESPACE describe pod POD_NAME 会显示原因。常见原因包括映像拉取失败(验证从集群到 overrides.yaml 中配置的映像注册表的出站流量)以及 CPU 或内存余量不足(在 overrides.yaml 中提高 mcpServer.resources.requests)。
第 3 步:检查边车配置拉取状态
每个 MCP pod 中的 apigee-mcp-server-config 边车容器会定期从 Apigee 控制平面拉取 MCP 配置。每次拉取都会从 apigee.googleapis.com 检索当前配置引用,然后从 Cloud Storage 提取引用的配置软件包。当拉取操作成功完成并获得有效配置后,MCP 数据平面会开始在 https://mcp.apigee.internal/mcp 上处理 MCP 工具流量。
在首次使用有效配置成功拉取之前(因为尚未为您的组织部署 MCP Discovery Proxy,或者因为边车无法访问控制平面),MCP Pod 会保持 Ready 状态,但对 https://mcp.apigee.internal/mcp 的请求会失败,并显示连接被拒绝。
检查边车日志,确定您属于哪种情况:
kubectl -n APIGEE_NAMESPACE logs -l app=apigee-mcp-server -c apigee-mcp-server-config --tail=100
- 重复的
info行,表示控制平面没有 MCP 配置: Apigee 控制平面返回了成功响应,但尚未为您的组织部署 MCP 发现代理。这是在初始配置期间的预期稳定状态。如需将 MCP 数据平面转换为服务状态,请按照 MCP 快速入门部署 MCP Discovery Proxy。{"level":"info","ts":1787582542.68,"caller":"mcpsidecar/sidecar.go:397","msg":"mcpsidecar: no MCP config from CP yet; skipping tick, pod stays Ready via seed","org":"YOUR_ORG","mcp_server_id":"default"} error行,带有consecutive_failures计数器: 边车日志是结构化 JSON。如果您看到{"level":"error","ts":1787613247.74,"caller":"mcpsidecar/sidecar.go:...","msg":"mcpsidecar: ...","org":"YOUR_ORG","mcp_server_id":"default","consecutive_failures":185,"error":"<wrapped error text>"}"level":"error"且consecutive_failures计数器不断增加,则表示边车无法完成配置拉取。边车会自动重试并退避,并在下次成功拉取时将计数器重置为 0。当此计数器持续上升时,请检查以下常见根本原因:
apigee-watcherGoogle Cloud 服务账号不在 Apigee 组织的controlPlaneAccess资源的watcher_identities列表中。请参阅启用过程中的第 2 步:向观察者身份授予对控制平面上的 MCP 配置的访问权限,以添加授权并验证其是否已生效。- 从集群到
apigee.googleapis.com或storage.googleapis.com的出站流量会被屏蔽。两个端点都必须可从 MCP pod 访问(请参阅启用过程中的出站网络要求)。 apigee-watcher服务账号无法从此集群获取 Google Cloud 访问令牌。如果同一命名空间中的现有 Apigee Hybrid 组件也报告身份验证失败,请先解决共享身份验证问题。- 暂时性 Apigee 控制平面或 Cloud Storage 错误。如果在排除上述原因后,计数器在较长时间内持续上升,请与 Apigee 支持团队联系。
第 4 步:验证是否已注入消息处理器 hostAliases
启用 MCP 后,Apigee Operator 会将一个 hostAliases 条目注入消息处理器 (MP) Pod 规范中。该条目包含一个 IP(MCP Service ClusterIP)和两个主机名:mcp.apigee.internal 和小写的 ORG_NAME.mcp.apigee.internal。验证注入是否成功:
kubectl -n APIGEE_NAMESPACE get pods -l app=apigee-runtime \ -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.hostAliases}{"\n"}{end}'
每个列出的 MP pod 都必须有一个 hostAliases 条目,其中包含 mcp.apigee.internal 和小写的 ORG_NAME.mcp.apigee.internal,指向 MCP Service ClusterIP。任何显示空条目或缺失条目的 MP pod 都是在启用 MCP 之前创建的。删除受影响的 MP pod,以便 ApigeeDeployment 控制器根据当前 pod 规范(其中包含注入的 hostAliases 条目)重新创建该 pod:
kubectl -n APIGEE_NAMESPACE delete pod -l app=apigee-runtime
第 5 步:端到端验证
如需进行端到端测试,通过 MCP 数据平面发送实际 MCP initialize 请求,请部署 MCP Discovery Proxy 并按照 MCP 快速入门中的说明操作。
在为您的组织部署 MCP 发现代理之前,无论消息处理器是否可以访问 MCP pod,对 https://mcp.apigee.internal/mcp 的请求都会失败,并显示连接被拒绝(请参阅第 3 步)。
支持请求
如果您提交的支持请求涉及 Apigee Hybrid MCP 数据平面,请附上以下输出内容,以加快诊断速度:
kubectl -n APIGEE_NAMESPACE logs -l app=apigee-mcp-server --all-containers --tail=1000kubectl -n APIGEE_NAMESPACE describe pod -l app=apigee-mcp-serverkubectl -n APIGEE_NAMESPACE get pods -l app=apigee-mcp-server -o wide和kubectl -n APIGEE_NAMESPACE get svc -l app=apigee-mcp-server。- 最近的
overrides.yaml和helm history APIGEE_ORG_RELEASE_NAME -n APIGEE_NAMESPACE输出(其中APIGEE_ORG_RELEASE_NAME是apigee-org图表的 Helm 版本名称;使用helm list -n APIGEE_NAMESPACE | grep apigee-org查找)。在共享overrides.yaml之前,请隐去 Secret 材料,包括:gcp.workloadIdentity、envs[].serviceAccountPaths或mcpServer.serviceAccountPath下的任何内嵌服务账号密钥。virtualhosts下的所有 TLS 证书或私钥。cassandra.auth个密码字段。- 您的替换项传递给 Operator 的任何内嵌凭据。
- 重现问题的完整
curl命令和响应。
无法在 API Hub 中将 API 样式更改为 MCP
如果 Apigee API Hub 中已存在具有现有 API 操作的 API 资源,则无法将该资源的 API 样式属性更改为 MCP。如需在 Apigee API Hub 中将 API 注册为 MCP API,您必须在首次注册 API 时选择 MCP 样式,或在将样式更改为 MCP 之前确保 API 资源中不存在任何操作。
如果您遇到任何其他问题,请参阅使用调试,详细了解如何在 Google Cloud 控制台中使用调试工具来分析 MCP 发现代理的请求和响应。