MCP 和 Web 集成
AI 服务通过两个集成点扩展模型功能:用于工具调用的 Model Context Protocol (MCP),以及用于页面获取和搜索的可插拔 Web 端点。这两项功能仅在 AI 对话中运行。Web 搜索和抓取允许 AI 在对话期间引用实时互联网内容,对于大多数部署而言,启用至少一种 Web 搜索功能可以提高响应质量。
这些功能完全通过 AI 服务容器上的环境变量进行配置。除了一个搜索端点和一个抓取端点外,不需要额外的基础设施。
先决条件
本页假设以下内容已配置:
- 带有数据库和 Redis 的运行中的 AI 服务容器(参见 Database and Redis)。
- 在
PROVIDERS和MODELS中配置的至少一个 LLM 提供商(参见 LLM providers)。 - 已部署并使用正确的 API Secret 对令牌进行签名的 JWT 令牌端点(参见 JWT authentication)。
Model Context Protocol (MCP)
MCP 允许 AI 服务在对话期间调用外部工具(内部 wiki、API 规范、运维手册、合同数据库和合规检查器)。该服务通过 Streamable HTTP transport 连接到 MCP 服务器。
仅支持 Streamable HTTP transport。基于 Stdio 的 MCP 服务器无法直接连接到 AI 服务。使用前请使用 SDK 的 HTTP transport 适配器对其进行封装(例如 TypeScript SDK 中的 StreamableHTTPServerTransport 或 Python SDK 中的 StreamableHTTPServer)。
MCP 工具仅在 AI conversations 中可用。Reviews 和 quick actions 不会调用 MCP 工具。对于启用 OAuth 的 MCP 服务器,每个用户必须在服务器工具变得可用之前完成授权流程。
配置
将 MCP_SERVERS 环境变量设置为 JSON 对象。每个键是一个服务器标识符;每个值描述连接情况。对于启用 OAuth 的服务器,还需设置 MCP_OAUTH_CALLBACK_URL(参见 OAuth 2.0 authentication)。
-e MCP_SERVERS='{
"knowledge-hub": {
"url": "http://host.docker.internal:3001/mcp",
"options": { "callToolTimeout": 30 }
}
}'| 字段 | 描述 |
|---|---|
url | MCP 服务器的 HTTP 端点(Streamable HTTP transport)。对于启用 OAuth 的服务器,这必须是支持 OAuth protected resource discovery (RFC 9728) 的端点。参见 MCP server URL for OAuth。 |
headers | 随每个请求发送的 HTTP 头部的 JSON 对象(例如 {"Authorization": "Bearer token"})。参见 Static-token authentication。 |
oauth | OAuth 2.0 配置块。为需要它的 MCP 服务器启用按用户授权。参见 OAuth 2.0 authentication。 |
tools.disabled | 要从 LLM 访问中排除的工具名称数组。 |
options.callToolTimeout | 每次工具调用的超时时间(秒)(默认 60)。 |
MCP_SERVERS 支持多个服务器条目。向同一 JSON 对象添加其他键:
-e MCP_SERVERS='{
"knowledge-hub": {
"url": "http://host.docker.internal:3001/mcp"
},
"compliance-checker": {
"url": "http://host.docker.internal:3002/mcp"
}
}'每个服务器的工具都独立命名空间化(例如 knowledge-hub-search_docs 和 compliance-checker-run_check)。
Docker 网络
在 Linux Docker 上,向 AI 服务的 compose 条目中添加 extra_hosts: ["host.docker.internal:host-gateway"],以访问在主机机器上运行的 MCP 服务器。
警告: host-gateway 解析为 Docker 桥接 IP,而不是 127.0.0.1。仅绑定到 127.0.0.1 的主机服务(常见于 Python MCP SDK 示例和 CLI 风格的服务器)在容器内部不可访问(ECONNREFUSED)。请将 MCP 服务器绑定到 0.0.0.0,或将其作为同一 Docker 网络中的同级容器运行。
静态令牌认证
headers 字段会在每次向 MCP 服务器发送请求时附带一组固定的 HTTP 标头。无论哪个最终用户触发了对话,每次工具调用都使用相同的凭据。
-e MCP_SERVERS='{
"knowledge-hub": {
"url": "http://host.docker.internal:3001/mcp",
"headers": {
"Authorization": "Bearer QUkgc2VydmljZQ==",
"X-Custom-Header": "custom-value"
}
}
}'如果 MCP 服务器需要每用户上下文但不使用 OAuth,请在对话提示中或在 MCP 服务器自行解析为每用户身份的标头中编码身份信息。
OAuth 2.0 认证
对于需要 OAuth 2.0 授权而不是在 headers 字段中使用静态访问令牌的 MCP 服务器,AI 服务可以作为 OAuth 客户端。该服务实现了带有 PKCE 的 OAuth 2.0 授权码流程,并支持允许此功能的服务器的动态客户端注册 (RFC 7591)。
最终用户通过其浏览器授权连接。每个用户独立进行授权,生成的访问令牌将在后续请求中重复使用。当访问令牌过期时,AI 服务会自动刷新它。
用于 OAuth 的 MCP 服务器 URL
启用 OAuth 后,AI 服务通过向 MCP 服务器 url 发送未认证的请求,并从 401 响应的 WWW-Authenticate 标头中读取 resource_metadata 链接来发现授权服务器(依据 RFC 9728)。
某些 MCP 服务器为未认证访问和 OAuth 保护访问暴露了单独的端点。url 必须指向返回此元数据的端点。使用错误的端点会导致 initialize 调用无限期挂起(请参阅故障排除)。
提示: 要验证正确的端点,请发送未认证的请求并检查 WWW-Authenticate 标头。它应包含一个 resource_metadata URL:curl -sI -X POST https://mcp.example.com/v1/mcp/auth -H "Content-Type: application/json" | grep -i www-authenticate
配置
为 MCP 服务器启用 OAuth 需要两个步骤:
- 将
MCP_OAUTH_CALLBACK_URL设置为集成 Web 应用程序托管的 OAuth 回调页面的 URL。AI 服务将此 URL 用作所有启用 OAuth 的 MCP 服务器的 OAuthredirect_uri参数(除非通过oauth.callbackUrl针对特定服务器进行覆盖)。 - 在
MCP_SERVERS中的目标服务器条目内添加一个oauth块。
-e MCP_OAUTH_CALLBACK_URL='https://your-app.example.com/oauth/callback' \
-e MCP_SERVERS='{
"knowledge-hub": {
"url": "http://host.docker.internal:3001/mcp",
"headers": { "Authorization": "Bearer static-token" }
},
"external-tools": {
"url": "https://mcp.example.com/v1/mcp",
"oauth": {
"clientId": "",
"clientSecret": "",
"scopes": ["read", "write"]
}
}
}'内部 MCP 服务器可以使用静态令牌认证(通过 headers),同时与需要 OAuth 的外部服务器共存。每个服务器都在同一个 MCP_SERVERS 对象内独立配置。MCP_OAUTH_CALLBACK_URL 仅适用于具有 oauth 块的服务器。
| 字段 | 描述 |
|---|---|
oauth.clientId | 由 MCP 服务器颁发的 OAuth 2.0 客户端标识符。省略此项以执行动态客户端注册。 |
oauth.clientSecret | OAuth 2.0 客户端密钥。与 clientId 一起用于机密客户端。 |
oauth.scopes | 要从授权服务器请求的 OAuth 范围数组。省略此项以使用默认服务器范围。 |
oauth.callbackUrl | 对 MCP_OAUTH_CALLBACK_URL 的每服务器覆盖。当不同的 MCP 服务器重定向到 Web 应用程序中的不同页面时使用。 |
动态客户端注册
如果 MCP 服务器支持 RFC 7591 动态客户端注册,则可以在 oauth 块中省略 clientId 和 clientSecret。AI 服务会在首次授权尝试时自动向 MCP 服务器注册自身,并在后续流程中复用生成的注册信息。
授权流程
OAuth 流程由集成 Web 应用程序驱动。AI 服务提供 REST 端点(参见 REST 端点);应用程序负责协调重定向并转发授权码。
- 初始化。 应用程序为已登录用户调用
POST /v1/mcp/oauth/{serverName}/initialize。响应包含以下内容之一:{ "connected": true }— 用户已拥有有效的访问令牌;无需进一步操作。{ "connected": false, "authorizationUrl": "…" }— 将用户的浏览器重定向到authorizationUrl。
- 用户同意。 MCP 服务器的授权页面在用户的浏览器中打开。批准后,服务器会将用户重定向回
MCP_OAUTH_CALLBACK_URL(或oauth.callbackUrl),并附加code和state查询参数。 - 完成。 回调页面从查询字符串中提取
code和state,并将它们转发到POST /v1/mcp/oauth/{serverName}/complete,请求体为{ "code": "…", "state": "…" }。成功后,用户的连接变为活动状态,后续的 AI 对话可以使用 MCP 服务器的工具。
注意: AI 服务不托管回调页面。请将 MCP_OAUTH_CALLBACK_URL(或每个服务器的 oauth.callbackUrl)作为已授权的重定向 URI 注册到 MCP 服务器——可以通过服务器的开发者控制台进行注册,或者在使用动态客户端注册时自动完成。
重要: 授权会话在 initialize 后十分钟内有效。如果用户花费超过十分钟来完成授权页面,complete 调用将返回 mcp-oauth-invalid-state 错误,并且必须从 initialize 重新开始流程。
回调页面实现
AI 服务不托管回调页面。集成 Web 应用程序必须在 MCP_OAUTH_CALLBACK_URL 处提供一个页面,该页面从重定向 URL 中提取 code 和 state 查询参数,并将它们转发到 AI 服务的 complete 端点。
最小化回调页面:
<script>
const params = new URLSearchParams(window.location.search);
fetch('/api/mcp/oauth/my-server/complete', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ code: params.get('code'), state: params.get('state') })
})
.then(r => r.json())
.then(data => document.body.textContent = data.connected ? 'Connected.' : 'Failed: ' + JSON.stringify(data));
</script>将 my-server 替换为来自 MCP_SERVERS 的键。在生产环境中,请添加错误处理、加载指示器以及对缺失 code 或 state 参数的验证。
在上面的示例中,回调页面调用的是集成应用程序自身服务器上的 /api/mcp/oauth/{serverName}/complete,而不是直接调用 AI 服务。这就是下面描述的代理模式。
浏览器集成与代理端点
AI 服务上的 OAuth REST 端点需要 JWT 身份验证,由于 CORS 限制,可能无法直接从浏览器调用。在基于浏览器的集成中,通过应用程序自己的后端代理 OAuth 调用。
后端生成一个 JWT(用于对话的同一令牌),将其附加到请求中,并将调用转发给 AI 服务。这样可以将 JWT 生成保留在服务端,并避免在 AI 服务上进行 CORS 配置。
典型的集成需要四个代理路由:
GET /api/mcp/oauth/status→GET {AI_SERVICE_URL}/v1/mcp/oauth/statusPOST /api/mcp/oauth/{serverName}/initialize→POST {AI_SERVICE_URL}/v1/mcp/oauth/{serverName}/initializePOST /api/mcp/oauth/{serverName}/complete→POST {AI_SERVICE_URL}/v1/mcp/oauth/{serverName}/completeDELETE /api/mcp/oauth/{serverName}→DELETE {AI_SERVICE_URL}/v1/mcp/oauth/{serverName}
REST 端点
所有端点均使用与其他 AI 服务端点相同的 JWT 进行身份验证。操作者用户由令牌标识;每个用户在每个 MCP 服务器上拥有独立的连接状态。
| 方法 | 路径 | 描述 |
|---|---|---|
GET | /v1/mcp/oauth/status | 返回每个启用 OAuth 的 MCP 服务器的连接状态,包含调用用户的 connected 状态以及可选的 expiresAt 时间戳。 |
POST | /v1/mcp/oauth/{serverName}/initialize | 启动 OAuth 流程。返回 { "connected": true } 或 { "connected": false, "authorizationUrl": "…" }。 |
POST | /v1/mcp/oauth/{serverName}/complete | 完成 OAuth 流程。请求体:{ "code": "…", "state": "…" }。成功时返回 { "connected": true }。 |
DELETE | /v1/mcp/oauth/{serverName} | 移除存储的令牌以及调用用户任何正在进行的授权状态。 |
一旦至少为一个 MCP 服务器配置了 OAuth,这些端点即可用。
连接范围与撤销
OAuth 连接是按用户建立的,不会在不同用户或环境之间共享。
要撤销用户的连接,请发送 DELETE /v1/mcp/oauth/{serverName}。
对于启用 OAuth 的 MCP 服务器,只有在每个用户完成授权流程后才会建立连接。在此之前,该服务器的工具不会暴露给该用户。
工具命名空间
MCP 工具以带命名空间的标识符暴露给 LLM:<server_id>-<tool_name>(例如,knowledge-hub-search_knowledge_base)。tools.disabled 数组仅接受裸工具名称(例如,"search_knowledge_base",而不是带命名空间的形式)。
MCP 服务器示例
以下示例使用官方 MCP TypeScript SDK (@modelcontextprotocol/sdk) 配合 StreamableHTTPServerTransport,后者处理会话管理、SSE 封装以及完整的 Streamable HTTP 传输规范。
知识库 MCP 服务器
创建 package.json:
{
"name": "knowledge-mcp-server",
"type": "module",
"private": true,
"dependencies": {
"@modelcontextprotocol/sdk": "^1.29.0",
"express": "^4.18.0",
"zod": "^3.23.0"
}
}安装依赖项:
npm install创建 knowledge-mcp-server.js:
// knowledge-mcp-server.js
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
import express from 'express';
import { z } from 'zod';
const KNOWLEDGE_BASE = {
'api-guidelines': 'All REST APIs must use JSON, include pagination through Link headers, and return 4xx for client errors with a machine-readable error code.',
'deployment-process': 'Deployments require: 1) PR approval, 2) passing CI, 3) staging verification, 4) production canary (5% traffic for 30min), 5) full rollout.',
'security-policy': 'All user data must be encrypted at rest (AES-256) and in transit (TLS 1.3). PII requires additional field-level encryption.',
};
function createServer() {
const server = new McpServer({
name: 'knowledge-hub',
version: '1.0.0'
});
server.tool(
'search_knowledge_base',
'Search the company knowledge base for policies, guidelines, and procedures',
{ query: z.string().describe('Search query') },
async ({ query }) => {
const q = query.toLowerCase();
const results = Object.entries(KNOWLEDGE_BASE)
.filter(([key]) => key.includes(q) || q.includes(key.split('-')[0]))
.map(([key, value]) => `## ${key}\n${value}`)
.join('\n\n');
return {
content: [{ type: 'text', text: results || 'No results found.' }]
};
}
);
server.tool(
'get_api_spec',
'Get the OpenAPI spec for an internal service',
{ service: z.string().describe('Service name (for example user-service, billing-api)') },
async ({ service }) => {
return {
content: [{ type: 'text', text: `Spec not found for: ${service}` }]
};
}
);
return server;
}
const app = express();
app.use(express.json());
app.all('/mcp', async (req, res) => {
const server = createServer();
const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: undefined });
await server.connect(transport);
await transport.handleRequest(req, res, req.body);
await server.close();
});
app.listen(3001, () => console.log('Knowledge MCP server on http://0.0.0.0:3001/mcp'));示例服务器绑定到 0.0.0.0,因此可以从 Docker 容器内部访问。当 MCP 服务器在主机上运行时,AI 服务通过 http://host.docker.internal:3001/mcp 连接到它(参见 Docker 网络配置)。
Web search
AI 服务可以将搜索查询转发到外部端点,从而使 AI 对话能够引用实时的 Web 内容。
启用 web search
Web search 需要同时配置以下三个组件:
| 组件 | 配置 |
|---|---|
| 环境变量 | 在 AI 服务容器中设置 WEBSEARCH_ENABLED='true' 和 WEBSEARCH_ENDPOINT。可选地,为经过身份验证的搜索后端设置 WEBSEARCH_REQUEST_TIMEOUT(默认 10000ms)和 WEBSEARCH_HEADERS。 |
| MODELS 条目 | 模型的 MODELS 条目必须包含 capabilities.webSearch: true(布尔值),以便在编辑器中显示 web search 切换开关。参见 MODELS 配置。 |
| JWT 权限 | JWT 必须在 auth.ai.permissions 数组中包含 ai:conversations:webSearch。参见 JWT 权限。如果没有此权限,即使环境变量和 MODELS 条目正确,切换开关仍会保持灰色不可用状态。 |
-e WEBSEARCH_ENABLED='true' \
-e WEBSEARCH_ENDPOINT='http://host.docker.internal:4001/search' \
-e WEBSEARCH_REQUEST_TIMEOUT='10000' \
-e WEBSEARCH_HEADERS='Authorization: Bearer search-api-key, X-Source: tinymce'重要: WEBSEARCH_HEADERS 使用冒号分隔的 CSV 格式(Header-Name: value, Another: value),而不是 JSON。传递 JSON 对象会导致 ERR_INVALID_HTTP_TOKEN 并静默阻止所有出站搜索请求。
按消息激活(自定义集成)
当用户开启 web search 时,TinyMCE 编辑器会发送 web search 激活标志。直接调用 AI 服务 API 的自定义集成必须在每个应启用 web search 的消息请求体中包含以下内容:
{
"capabilities": { "webSearch": {} }
}该值必须是一个空对象({})。这是文档规定的 API 契约(参见 Capability configuration)。服务会拒绝其他格式:
"webSearch": true: 被拒绝(schema 期望一个对象,而不是布尔值)。"webSearch": {"enabled": true}: 被拒绝(无法识别的键)。- 完全省略:即使所有服务器端配置正确,也不会向模型提供 web search 功能。
如果没有此字段,环境变量、JWT 权限和 MODELS 配置将不足以启用该功能。模型永远不会接收到 web search 工具。
Endpoint contract
| 方向 | Payload |
|---|---|
| Request | 包含 query 字段(搜索字符串)的 JSON 对象。 |
| Response | 包含 results 数组的 JSON 对象;每个项包括 url、text、title,以及可选的 author、publishedAt 和 favicon。 |
请求体:
{ "query": "search string" }响应体:
{
"results": [
{
"url": "https://example.com/article",
"text": "Content snippet",
"title": "Article Title",
"author": "Author",
"publishedAt": "2026-04-30T10:00:00Z",
"favicon": "https://example.com/favicon.ico"
}
]
}实现示例 (SerpAPI)
// search-service.js
const express = require('express');
const app = express();
app.use(express.json());
app.post('/search', async (req, res) => {
const response = await fetch(
`https://serpapi.com/search.json?q=${encodeURIComponent(req.body.query)}&api_key=${process.env.SERP_API_KEY}`
);
const data = await response.json();
const results = (data.organic_results || []).slice(0, 5).map(r => ({
url: r.link,
title: r.title,
text: r.snippet
}));
res.json({ results });
});
app.listen(4001);Web scraping
AI 服务可以将网页获取请求转发到外部 endpoint,从而使 AI 对话能够引用特定页面。
启用 Web scraping
在 AI 服务容器上设置 WEBRESOURCES_ENABLED='true' 和 WEBRESOURCES_ENDPOINT。可选地,设置 WEBRESOURCES_REQUEST_TIMEOUT(默认为 10000ms)。
-e WEBRESOURCES_ENABLED='true' \
-e WEBRESOURCES_ENDPOINT='http://host.docker.internal:4000/scrape' \
-e WEBRESOURCES_REQUEST_TIMEOUT='10000'触发机制
当 AI 服务收到以下请求时,会调用 scrape endpoint (WEBRESOURCES_ENDPOINT):
POST /v1/conversations/{id}/web-resources
Content-Type: application/json
{ "url": "https://example.com/page-to-fetch" }当用户在 Chat sidebar 中添加链接作为源(点击 Add context source 按钮,然后选择 Link),或者选择一个解析为 URL 的集成方提供的源(参见 tinymceai_chat_fetch_sources)时,TinyMCE 编辑器会发送此请求。直接在聊天消息中输入 URL 不会触发获取操作。自定义集成必须显式调用此 endpoint 以触发页面获取。
响应会存储在对应对话中。scrape 响应中的 type 字段必须是 text/html 或 text/markdown,且 data 不能为空。其他 MIME 类型(例如 application/pdf)和空的 data 字段会被拒绝,并返回 422 web-resource-download-error。
Endpoint contract
| 方向 | Payload |
|---|---|
| Request | 包含 url 字段(要获取的页面)的 JSON 对象。 |
| Response | 包含 type(text/html 或 text/markdown)和 data(正文内容)的 JSON 对象。 |
请求体:
{ "url": "https://example.com/article" }响应体:
{ "type": "text/html", "data": "<html><body><p>Example page body</p></body></html>" }实现示例 (Playwright)
// scraper-service.js
const { chromium } = require('playwright');
const express = require('express');
const app = express();
app.use(express.json());
app.post('/scrape', async (req, res) => {
const browser = await chromium.launch();
const page = await browser.newPage();
await page.goto(req.body.url, { waitUntil: 'networkidle' });
const content = await page.content();
await browser.close();
res.json({ type: 'text/html', data: content });
});
app.listen(4000);SSE 事件
自定义流式 UI 集成可以使用以下 Server-Sent Events (SSE) 来渲染工具调用进度和搜索结果。AI 服务在对话期间发出这些事件:
| 事件名称 | 描述 |
|---|---|
mcp-tool-result | 当 MCP 工具调用完成时发出。包含工具结果。没有预调用事件;客户端在工具调用结束之前不会收到任何信号。 |
web-search | 当执行网络搜索时发送。载荷是一个空对象,并且当搜索后端失败时也会发送此事件(参见故障排除)。 |
source | 随模型响应中的源引用一起发出。 |
有关每个事件及其载荷的详细信息,请参阅 API 参考文档。
Kubernetes 部署
在 Kubernetes 中,extra_hosts: host-gateway Docker 模式不适用。请将 MCP 服务器和网络集成端点作为同级 Deployment 部署在同一命名空间中,并使用 ClusterIP Services。通过集群 DNS 引用它们:
-e MCP_SERVERS='{
"knowledge-hub": {
"url": "http://mcp-knowledge.tinymce-ai.svc.cluster.local:3001/mcp",
"options": { "callToolTimeout": 30 }
}
}'
-e WEBRESOURCES_ENDPOINT='http://web-scrape.tinymce-ai.svc.cluster.local:4000/scrape'
-e WEBSEARCH_ENDPOINT='http://web-search.tinymce-ai.svc.cluster.local:4001/search'将 MCP_SERVERS 和 WEBSEARCH_HEADERS 存储在 Kubernetes Secret 中,并将其作为环境变量挂载到 AI 服务的 Deployment 中。这避免了在 Deployment 清单中暴露凭据,并允许在不重新部署的情况下进行轮换。
对于生产集群,MCP 服务器 Deployment 应具有独立的资源请求、存活探针和副本数,不依赖于 AI 服务。有关通用的 Kubernetes 模式,请参阅生产环境部署。
故障排除
| 症状 | 解决方法 |
|---|---|
| Web 搜索或 Web 抓取功能完全未显示 | WEBSEARCH_ENABLED 和 WEBRESOURCES_ENABLED 默认值均为 false。请在 AI 服务环境中将它们设置为 true,并提供相应的 _ENDPOINT 值。如果未启用这些标志,无论 JWT 权限或 MODELS 配置如何,AI 服务都会禁用所有 Web 集成功能。 |
| 编辑器中的 Web 搜索开关呈灰色(不可用) | JWT 中缺少 ai:conversations:webSearch 权限。请将其添加到 token 的 auth.ai.permissions 数组中(或使用通配符 ai:conversations:*)。请参阅 JWT 权限部分。 |
| 已开启 Web 搜索但模型从未使用它 | 每条消息的请求体中缺少 "capabilities": {"webSearch": {}}。当开关激活时,TinyMCE 编辑器会发送此字段。自定义集成必须在每个请求体中包含它。请参阅按消息激活(自定义集成)部分。 |
与 Web 搜索相关的 AI 服务日志中出现 ERR_INVALID_HTTP_TOKEN | WEBSEARCH_HEADERS 被设置为 JSON 对象。该服务期望的是冒号分隔的 CSV 格式:Header-Name: value, Another: value。 |
连接 MCP 服务器时出现 ECONNREFUSED | MCP 服务器绑定到了 127.0.0.1。请改为绑定到 0.0.0.0,或将 MCP 服务器作为同级容器运行在同一个 Docker 网络(或 Kubernetes namespace)上。 |
大约每 60 秒出现一次 [WARN] MCP client health check ping failed, evicting | 非功能性问题。AI 服务在每次驱逐后会重新与 MCP 服务器进行握手。工具调用继续正常工作。这种日志量在稳态下是预期的,并不表示存在问题。 |
| Web 搜索返回“无结果”,但搜索后端正在运行 | 检查 AI 服务容器日志中是否有 [WARN] Web search request failed。当 WEBSEARCH_ENDPOINT 返回 5xx 错误时,服务会记录警告,但向客户端发出空的 event: web-search,且不包含错误载荷。模型会继续执行,就像返回了零个结果一样。 |
来自 web-resources 端点的 422 web-resource-download-error | 这个单一的错误代码涵盖了多种失败模式:scrape 端点返回 5xx、返回非 JSON、返回空的 data 字段,或返回不支持的 type(除 text/html 或 text/markdown 以外的任何类型)。请检查 AI 服务容器日志以查找根本原因。 |
来自 complete 端点的 mcp-oauth-invalid-state 错误 | 授权会话已过期。调用 initialize 后,会话有效期为十分钟。请从 POST /v1/mcp/oauth/{serverName}/initialize 重新开始流程。 |
| 配置 OAuth 后,用户看不到 MCP 工具 | 用户尚未完成授权流程。OAuth 连接是针对每个用户的——每个用户必须通过 initialize 和 complete 独立进行授权。请使用 GET /v1/mcp/oauth/status 检查连接状态。 |
initializeMcpOAuth 挂起超过 60 秒且无响应 | MCP_SERVERS 中的 MCP 服务器 url 未返回 OAuth 资源发现元数据 (RFC 9728)。AI 服务向该 URL 发送未经身份验证的请求,并期望收到一个带有 resource_metadata 链接的 WWW-Authenticate 头的 401 响应。如果缺少该头,服务将无限期挂起。请使用以下命令验证正确的端点:curl -sI -X POST https://mcp.example.com/endpoint -H "Content-Type: application/json",并检查 WWW-Authenticate 头中是否包含 resource_metadata。某些 MCP 服务器为经过身份验证的访问和受 OAuth 保护的访问暴露了单独的 URL。请参阅用于 OAuth 的 MCP 服务器 URL 部分。 |
另请参阅
- LLM 提供商:提供商配置和
MODELS目录 - 参考:完整的环境变量参考,包括
MCP_SERVERS、WEBRESOURCES_*和WEBSEARCH_* - 故障排除:一般故障排除