Lỗi MCP Server
Cách xử lý các lỗi do foura-mcp server trả về.
Mỗi response lỗi từ bất kỳ công cụ nào trong ba công cụ (foura_single, foura_proxy, foura_browser) đều được cấu trúc. Các LLM agent có thể đọc trường code để thực hiện logic thử lại (retry) mà không cần phân tích cú pháp văn bản.
Cấu trúc envelope
Mỗi lỗi (isError: true) đều đi kèm một block structuredContent. Các trường tối thiểu trên mỗi lỗi:
{
"service": "single | proxy | browser",
"code": "rate_limited",
"error": "Rate limit exceeded"
}
Đối với các lỗi upstream có HTTP status, trường status cũng sẽ xuất hiện. Đối với các lỗi rate-limit và dung lượng (capacity), envelope sẽ bổ sung retryAfter, current.{concurrency, rpm}, và limits.{maxConcurrency, maxRpm}, cùng cấu trúc với các REST API errors bên dưới.
Các giá trị code ổn định
| Code | HTTP | Ý nghĩa | Thử lại an toàn? |
|---|---|---|---|
ssrf_blocked |
n/a | IP đích nằm trong dải riêng tư hoặc được bảo lưu (RFC 5735, RFC 6598, IPv6 bảo lưu) | Không, hãy thay đổi URL |
upstream_non_json |
thay đổi | Upstream trả về body không phải là JSON hợp lệ | Có thể, hãy kiểm tra |
output_validation_failed |
n/a | outputSchema của MCP server đã từ chối response từ upstream (lỗi server hoặc cấu trúc upstream không mong muốn) |
Có thể, hãy báo cáo |
bad_request |
400 | Cấu trúc đầu vào bị từ chối bởi FourA API | Không, hãy sửa các đối số |
auth_failed |
401 | Key bị thiếu, không hợp lệ hoặc đã bị vô hiệu hóa | Không, hãy sửa key |
forbidden |
403 | Đích từ chối request (chống bot, chặn địa lý) | Không, hoặc chuyển sang foura_proxy |
not_found |
404 | URL hoặc endpoint đích không tồn tại | Không |
rate_limited |
429 | Đạt giới hạn RPM của mỗi key | Có, đợi retryAfter giây |
at_capacity |
503 | Đạt giới hạn concurrency (current.concurrency > limits.maxConcurrency) |
Có, đợi retryAfter giây |
service_disabled |
503 | Dịch vụ bị vô hiệu hóa cho tài khoản của bạn (gói dịch vụ hoặc bảo trì) | Liên hệ hỗ trợ |
service_unavailable |
503 | Lỗi 503 chung từ upstream | Có, backoff ngắn |
upstream_error |
500+ | Lỗi 5xx từ upstream | Có, exponential backoff |
upstream_client_error |
4xx | Lỗi 4xx khác không được đề cập ở trên | Thường là không |
upstream_unknown |
khác | Phòng thủ, không nên xảy ra trong thực tế | Kiểm tra |
Các lỗi cấp độ HTTP từ MCP server
Một số lỗi xảy ra ở tầng transport của MCP, trước khi bất kỳ công cụ nào được gọi. Những lỗi này trả về lỗi JSON-RPC thô (không có structuredContent):
| HTTP | Khi nào | Những gì bạn thấy |
|---|---|---|
| 400 | Header MCP-Protocol-Version không được hỗ trợ |
Unsupported MCP-Protocol-Version: <value>. Supported: 2025-11-25, 2025-06-18, 2025-03-26, 2024-11-05, 2024-10-07. |
| 401 | Header Authorization bị thiếu hoặc sai định dạng |
JSON-RPC error + WWW-Authenticate: Bearer realm="foura-mcp", resource_metadata="https://foura.ai/docs/mcp/server#auth" |
| 403 | Header Origin hoặc Host không được phép (phòng thủ DNS-rebinding, CVE-2025-66414) |
Origin <value> is not in the allowlist hoặc Host <value> is not in the allowlist |
| 405 | GET hoặc DELETE trên /mcp (chế độ stateless) |
Method not allowed in stateless mode. Use POST /mcp. |
| 413 | Request body > 256 KB | Lỗi 413 mặc định của Express |
Các allowlist cho lỗi 403 có thể cấu hình qua biến môi trường cho những người tự host (self-host) thông qua FOURA_MCP_ALLOWED_HOSTS và FOURA_MCP_ALLOWED_ORIGINS.
Chiến lược thử lại (retry)
Ba nhóm chính:
- Chờ + thử lại:
rate_limited,at_capacity,service_unavailable,upstream_error. Tuân thủretryAfterkhi có sẵn (gợi ý từ server, tính bằng giây). Sử dụng exponential backoff kèm jitter khi không có. - Không thử lại, sửa đầu vào:
bad_request,auth_failed,not_found,ssrf_blocked. - Chuyển đổi công cụ:
forbiddentrênfoura_single→ chuyển tiếp lênfoura_proxy. Nếu trang cũng cần JavaScript, sử dụngfoura_browser. Nếufoura_browserbáo lỗiforbidden, hãy kết hợp vớifoura_proxytrước và truyền IDproxynhận được vàofoura_browser.proxy.
Ví dụ thử lại (TypeScript, phía MCP)
async function callWithRetry(call: () => Promise<any>, maxAttempts = 3) {
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
const r = await call();
if (!r.isError) return r;
const code = r.structuredContent?.code;
const wait = r.structuredContent?.retryAfter ?? Math.min(2 ** attempt, 30);
if (["rate_limited", "at_capacity", "service_unavailable", "upstream_error"].includes(code)) {
await new Promise((res) => setTimeout(res, wait * 1000));
continue;
}
// Non-retryable, surface to caller
throw new Error(`${code}: ${r.structuredContent?.error}`);
}
throw new Error("max retries exceeded");
}
Tài liệu liên quan
- MCP Server, ba công cụ và schema của chúng
- MCP Recipes, các workflow prompt đi kèm với server
- API Errors, cùng cấu trúc envelope ở tầng REST API bên dưới