Lỗi MCP Server
Lỗi MCP Server
Cách xử lý các lỗi do foura-mcp server trả về.
Mọi error response từ bất kỳ công cụ nào trong bốn công cụ (foura_auto, 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 retry mà không cần phân tích văn bản tự nhiên.
Cấu trúc envelope
Mọi lỗi (isError: true) đều chứa một khối structuredContent. Các trường tối thiểu trên mọi lỗi:
{
"service": "auto | single | proxy | browser",
"code": "rate_limited",
"error": "Rate limit exceeded"
}
Đối với các lỗi upstream kèm HTTP status, status cũng sẽ xuất hiện. Khi hạn mức chia sẻ của nền tảng từ chối một lệnh gọi, envelope sẽ bổ sung retryAfter, current.{concurrency, rpm} và limits.{maxConcurrency, maxRpm}, có cấu trúc tương tự như lỗi REST API cơ bản.
Khi một trong các giới hạn riêng thuộc gói của bạn từ chối lệnh gọi, mã lỗi CHÍNH LÀ giới hạn đó: plan_limit_ theo sau bởi credits, bandwidth, rate, concurrency, browser_daily, premium hoặc feature. retryAfter chứa thời gian chờ trong trường hợp việc chờ đợi có thể giải phóng giới hạn, và sẽ không xuất hiện đối với giới hạn mà việc chờ đợi không thể xử lý, chẳng hạn như tính năng không nằm trong gói đăng ký. plan_limit_browser_daily cũng không chứa retryAfter: giới hạn này sẽ được làm mới vào lúc nửa đêm UTC.
Trên foura_auto, giới hạn gói đạt đến trong ladder của nó sẽ trả về dưới dạng rate_limited hoặc forbidden, cùng với mã lỗi của gói trong reason.
Các giá trị code ổn định
| Mã | HTTP | Ý nghĩa | Có thể thử lại an toàn? |
|---|---|---|---|
ssrf_blocked |
n/a | Mục tiêu là địa chỉ riêng tư hoặc dành riêng (RFC 5735, RFC 6598, IPv6 dành riêng), URL không phải http(s), hoặc tên máy chủ không phân giải được | Không, hãy kiểm tra URL. Quá trình tra cứu tạm thời thất bại có thể thử lại |
upstream_non_json |
thay đổi | Upstream trả về phần thân không phải là JSON hợp lệ | Có thể, hãy điều tra |
output_validation_failed |
n/a | outputSchema của MCP server đã từ chối response từ upstream, hoặc công cụ không thể hoàn tất lệnh gọi (chưa cấu hình API key, API không thể truy cập) |
Có thể: kiểm tra thiết lập, sau đó báo cáo |
bad_request |
400 | Định dạng đầu vào bị FourA API từ chối | Không, hãy sửa các đối số |
auth_failed |
401 | FourA API key bị thiếu, không hợp lệ hoặc đã bị vô hiệu hóa; điều này không liên quan đến thông tin xác thực của trang đích | Không, hãy sửa khóa FourA |
forbidden |
403 | Mục tiêu đã từ chối request (kiểm tra trang web, giới hạn quốc gia) | Không, hoặc chuyển sang foura_proxy |
not_found |
404 | URL hoặc endpoint mục tiêu không tồn tại | Không |
rate_limited |
429 | Hạn mức chia sẻ mỗi phút của nền tảng, hoặc lỗi 429 từ mục tiêu mà validate của bạn đã từ chối. Trên foura_auto, lỗi này cũng có thể do credit, lưu lượng truy cập hoặc rate limit của gói (xem reason) |
Có, đợi retryAfter nếu có, nếu không hãy giãn cách thử lại |
at_capacity |
503 | Đã đạt giới hạn đồng thời (current.concurrency > limits.maxConcurrency) |
Có, đợi retryAfter giây |
service_disabled |
503 | Dịch vụ tạm tắt để bảo trì. Công cụ không có trong gói của bạn sẽ trả về plan_limit_feature |
Liên hệ hỗ trợ |
service_unavailable |
503 | Lỗi 503 chung từ upstream | Có, giãn cách ngắn |
upstream_error |
500+ hoặc 0 | Mục tiêu phản hồi bằng lỗi máy chủ, hoặc trên foura_proxy, foura_browser và foura_auto không bao giờ phản hồi |
Có, giãn cách hàm mũ |
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 | Request đã chạy nhưng không tạo ra phản hồi được chấp nhận: trên foura_single mục tiêu không bao giờ phản hồi (hết thời gian chờ, từ chối kết nối), và trên bất kỳ công cụ nào thì validate của bạn đã từ chối response 2xx hoặc 3xx. Đọc status và error |
Điều tra |
no_eligible_proxy |
n/a | Không có proxy nào khớp với allowlist exitCountries nghiêm ngặt; details.exitCountries chứa phạm vi đã chuẩn hóa |
Thử lại sau; chỉ thay đổi phạm vi một cách rõ ràng |
plan_limit_credits |
429 | Credit hàng tháng trong gói của bạn đã hết | Có, sau retryAfter, hoặc thay đổi gói |
plan_limit_bandwidth |
429 | Hạn mức lưu lượng trong gói của bạn đã hết cho chu kỳ thanh toán này | Có, sau retryAfter, hoặc thay đổi gói |
plan_limit_rate |
429 | Số request mỗi phút trong gói của bạn cho endpoint đó | Có, sau retryAfter |
plan_limit_concurrency |
429 | Số request đồng thời trong gói của bạn cho endpoint đó | Có, sau retryAfter |
plan_limit_browser_daily |
429 | Hạn mức Browser hàng ngày trong gói của bạn đã hết | Có, vào ngày mai, hoặc sử dụng foura_single / foura_proxy |
plan_limit_premium |
403 | Bạn đã gửi exitClass: "premium" trên gói không bao gồm proxy đầu ra cao cấp |
Không, hãy bỏ tham số hoặc thay đổi gói |
plan_limit_feature |
403 | Gói không hỗ trợ endpoint hoặc khả năng đó | Không, hãy thay đổi gói |
Lỗi cấp HTTP từ MCP server
Một số lỗi xảy ra tại tầng transport của MCP, trước khi bất kỳ tool nào được gọi. Những trường hợp 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 | Gọi tool hoặc đọc resource mà không có API key. Việc liệt kê tool và prompt vẫn hoạt động mà không cần key | Lỗi JSON-RPC + WWW-Authenticate: Bearer realm="foura-mcp" |
| 403 | Header Origin hoặc Host không được phép (phòng chống 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 | Body của request > 256 KB | 413 mặc định của Express |
Allowlist cho lỗi 403 có thể cấu hình qua biến môi trường cho người tự host qua FOURA_MCP_ALLOWED_HOSTS và FOURA_MCP_ALLOWED_ORIGINS.
Profile trình duyệt bị từ chối
Một profile trình duyệt mà danh mục không thể cung cấp, hoặc profile được gửi với unblocker đặt thành false, sẽ trả về lỗi upstream với lý do nằm trong error và request sẽ không bao giờ rời khỏi FourA. Thông báo sẽ nêu rõ các lựa chọn hiện có, vì vậy hãy thử lại với một trong các tổ hợp được liệt kê thay vì gửi lại chính tổ hợp đó.
Đây là sự từ chối, không phải sự cố gián đoạn dịch vụ: việc thử lại một request y hệt không thể thành công, và không có trình duyệt nào khác được dùng để thay thế.
Chiến lược retry
Năm nhóm:
- Gói dịch vụ của chính bạn đã từ chối, không phải máy chủ đích: bất kỳ mã
plan_limit_*nào. Thao tác tương tự thông qua một tool khác cũng sẽ bị từ chối, vì vậy việc đổi endpoint chỉ làm mất thời gian. Hãy chờ hếtretryAfternếu có; nếu không thì cần phải thay đổi gói dịch vụ.plan_limit_premiumlà lỗi bạn có thể tự xử lý bằng cách bỏexitClass. - Chờ và thử lại:
rate_limited,at_capacity,service_unavailable,upstream_error. Tuân thủretryAfterkhi có. Sử dụng exponential backoff kèm jitter khi không có header này. Đừng xử lý bằng cách gửi lại đồng loạt mọi lệnh gọi tool đang chờ: thay vào đó hãy giảm số lượng lệnh chạy song song. - Giữ nguyên phạm vi và thử lại sau:
no_eligible_proxy. Không tự ý xóaexitCountrieshoặc âm thầm thay thế bằng quốc gia khác. Chỉ thay đổi hoặc mở rộng allowlist khi người dùng yêu cầu thay đổi rõ ràng. - Không thử lại cho đến khi input hoặc thông tin xác thực được khắc phục:
bad_request,auth_failed,not_found,ssrf_blocked. Đối vớiauth_failed, hãy kiểm tra API key của FourA, không phải thông tin xác thực của trang đích. - Đổi tool khi nội dung yêu cầu:
forbiddentrênfoura_singlecó thể là lý do hợp lý để thửfoura_proxyvới giới hạn. Dùngfoura_browserkhi nội dung cần lấy yêu cầu JavaScript. Sau khi chọn proxy thành công, hãy truyềnproxyID nhận được vàofoura_browser.proxythay vì bắt đầu một lượt chọn mới.
Ví dụ retry (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");
}
Liên quan
- MCP Server, bốn công cụ và schema của chúng
- MCP Recipes, các prompt quy trình làm việc đi kèm với server
- API Errors, cùng định dạng envelope ở tầng REST API cơ bản
- Rate Limits, giới hạn tài khoản và nền tảng đằng sau
rate_limitedvàat_capacity