أخطاء خادم MCP
أخطاء خادم MCP
كيفية التعامل مع الأخطاء التي يرجعها خادم foura-mcp.
كل استجابة خطأ من أي من الأدوات الأربع (foura_auto، foura_single، foura_proxy، foura_browser) تأتي بصيغة مهيكلة. يمكن لوكلاء LLM قراءة حقل code لمنطق إعادة المحاولة دون الحاجة إلى تحليل النصوص النثرية.
بنية غلاف الاستجابة
يحمل كل خطأ (isError: true) كتلة structuredContent. الحقول الدنيا في كل خطأ:
{
"service": "auto | single | proxy | browser",
"code": "rate_limited",
"error": "Rate limit exceeded"
}
عند حدوث أخطاء من المصدر الأساسي (upstream) مع حالة HTTP، يتوفر status أيضاً. عندما يرفض الحد المشترك للمنصة إجراء استدعاء، يضيف الغلاف retryAfter وcurrent.{concurrency, rpm} وlimits.{maxConcurrency, maxRpm}، بنفس بنية أخطاء REST API الأساسية.
عندما يرفض أحد حدود خطتك الخاصة إجراء استدعاء، فإن الكود يمثل ذلك الحد تحديداً: plan_limit_ متبوعاً بـ credits أو bandwidth أو rate أو concurrency أو browser_daily أو premium أو feature. يتضمن retryAfter فترة الانتظار عندما يكون الانتظار كفيلاً بإلغاء التقييد، ويكون غائباً في حال وجود حد لا يمكن للانتظار حله، مثل ميزة لا تتضمنها الخطة. لا يتضمن plan_limit_browser_daily أيضاً أي retryAfter: حيث يُعاد ضبطه عند منتصف الليل بتوقيت UTC.
في foura_auto، يتم إرجاع حد الخطة الذي تم الوصول إليه داخل التدرج الخاص بها كـ rate_limited أو forbidden، مع تضمين كود الخطة في reason.
قيم code الثابتة
| الكود | HTTP | المعنى | هل إعادة المحاولة آمنة؟ |
|---|---|---|---|
ssrf_blocked |
لا ينطبق | الهدف هو عنوان خاص أو محجوز (RFC 5735، RFC 6598، IPv6 reserved)، أو أن URL ليس http(s)، أو لم يتم حل اسم المضيف الخاص به | لا، تحقق من URL. يمكن إعادة محاولة البحث الذي فشل مؤقتا |
upstream_non_json |
يختلف | أرجع المصدر الأساسي محتوى غير صالح بتنسيق JSON | ربما، تحقق من الأمر |
output_validation_failed |
لا ينطبق | رفض outputSchema الخاص بخادم MCP استجابة المصدر، أو تعذر على الأداة إكمال الاستدعاء بالكامل (لم يتم تكوين مفتاح API، أو تعذر الوصول إلى API) |
ربما: تحقق من الإعداد، ثم أبلغ عن المشكلة |
bad_request |
400 | بنية الإدخال مرفوضة من قبل FourA API | لا، قم بتصحيح المعاملات |
auth_failed |
401 | مفتاح FourA API مفقود، أو غير صالح، أو معطل؛ لا يتعلق هذا ببيانات اعتماد الموقع المستهدف | لا، قم بتصحيح مفتاح FourA |
forbidden |
403 | رفض الهدف الطلب (فحص الموقع، قيود متعلقة بالبلد) | لا، أو انتقل إلى foura_proxy |
not_found |
404 | عنوان URL أو endpoint الهدف غير موجود | لا |
rate_limited |
429 | الحصة المشتركة لكل دقيقة للمنصة، أو استجابة 429 من الهدف رفضها validate الخاص بك. في foura_auto قد يكون أيضا بسبب رصيد خطتك، أو حركة المرور، أو rate limit (انظر reason) |
نعم، انتظر retryAfter عند توفره، وإلا فاستخدم backoff |
at_capacity |
503 | تم الوصول إلى الحد الأقصى للتزامن (current.concurrency > limits.maxConcurrency) |
نعم، انتظر retryAfter ثوان |
service_disabled |
503 | الخدمة متوقفة للصيانة. الأداة غير المضمنة في خطتك تعود كـ plan_limit_feature |
تواصل مع الدعم |
service_unavailable |
503 | خطأ 503 عام من المصدر | نعم، backoff قصير |
upstream_error |
+500 أو 0 | استجاب الهدف بخطأ في الخادم، أو في foura_proxy، لم يستجب كل من foura_browser و foura_auto مطلقا |
نعم، exponential backoff |
upstream_client_error |
4xx | أخطاء 4xx أخرى غير مذكورة أعلاه | لا في العادة |
upstream_unknown |
غير ذلك | تم تنفيذ الطلب ولكنه لم ينتج استجابة مقبولة: في foura_single لم يستجب الهدف مطلقا (مهلة، رفض الاتصال)، وفي أي أداة رفض validate الخاص بك استجابة 2xx أو 3xx. راجع status و error |
تحقق من الأمر |
no_eligible_proxy |
لا ينطبق | لا يوجد proxy يطابق القائمة المسموح بها exitCountries الصارمة؛ يحتوي details.exitCountries على النطاق القياسي |
أعد المحاولة لاحقا؛ لا تغير النطاق إلا بشكل صريح |
plan_limit_credits |
429 | استنفد الرصيد الشهري في خطتك | نعم، بعد retryAfter، أو قم بتغيير الخطة |
plan_limit_bandwidth |
429 | استنفدت حصة حركة المرور في خطتك لفترة الفوترة الحالية | نعم، بعد retryAfter، أو قم بتغيير الخطة |
plan_limit_rate |
429 | عدد الطلبات في الدقيقة لخطتك لهذا الـ endpoint | نعم، بعد retryAfter |
plan_limit_concurrency |
429 | عدد الطلبات المتزامنة لخطتك لهذا الـ endpoint | نعم، بعد retryAfter |
plan_limit_browser_daily |
429 | استنفدت حصة Browser اليومية في خطتك | نعم، غدا، أو استخدم foura_single / foura_proxy |
plan_limit_premium |
403 | أرسلت exitClass: "premium" في خطة لا تتضمن منافذ خروج مدفوعة |
لا، احذف المعامل أو قم بتغيير الخطة |
plan_limit_feature |
403 | الخطة لا تدعم هذا الـ endpoint أو هذه الإمكانية | لا، قم بتغيير الخطة |
أخطاء مستوى HTTP من خادم MCP
تحدث بعض حالات الفشل في طبقة نقل MCP، قبل استدعاء أي أداة. تُرجع هذه الحالات أخطاء JSON-RPC خام (بدون structuredContent):
| HTTP | متى | ما تراه |
|---|---|---|
| 400 | ترويسة MCP-Protocol-Version غير مدعومة |
Unsupported MCP-Protocol-Version: <value>. Supported: 2025-11-25, 2025-06-18, 2025-03-26, 2024-11-05, 2024-10-07. |
| 401 | استدعاء أداة أو قراءة مورد بدون مفتاح API. يعمل سرد الأدوات والـ prompts بدون مفتاح | خطأ JSON-RPC + WWW-Authenticate: Bearer realm="foura-mcp" |
| 403 | ترويسة Origin أو Host غير مسموح بها (دفاع ضد DNS-rebinding، CVE-2025-66414) |
Origin <value> is not in the allowlist أو Host <value> is not in the allowlist |
| 405 | GET أو DELETE على /mcp (وضع stateless) |
Method not allowed in stateless mode. Use POST /mcp. |
| 413 | جسم الطلب > 256 كيلوبايت | خطأ 413 الافتراضي من Express |
قوائم السماح لرمز 403 قابلة للتهيئة عبر متغيرات البيئة للاستضافة الذاتية بواسطة FOURA_MCP_ALLOWED_HOSTS و FOURA_MCP_ALLOWED_ORIGINS.
الملفات التعريفية للمتصفح المرفوضة
الملف التعريفي للمتصفح الذي لا يستطيع الكتالوج تقديمه، أو الملف التعريفي المرسل مع ضبط unblocker على false، يعود كفشل من المصدر (upstream) مع ذكر السبب في error ولا يغادر الطلب خوادم FourA أبدًا. تحدد الرسالة ما هو متاح، لذا أعد المحاولة باستخدام أحد التوليفات المدرجة بدلاً من نفس التوليفة.
هذه الحالات هي حالات رفض وليست انقطاعات: إعادة محاولة نفس الطلب تمامًا لا يمكن أن تنجح، ولم يتم استخدام أي متصفح آخر بدلاً منه.
استراتيجية إعادة المحاولة
خمس فئات:
- خطتك هي التي رفضت الطلب، وليس الهدف: أي رمز
plan_limit_*. سيتم رفض نفس العملية عبر أداة أخرى أيضًا، لذا فإن تبديل الـ endpoints لا يستهلك سوى الوقت. انتظر حتى ينتهيretryAfterعند وجوده؛ وإلا فيجب تغيير الخطة. خطأplan_limit_premiumهو الخطأ الذي يمكنك معالجته بنفسك عن طريق إزالةexitClass. - الانتظار وإعادة المحاولة:
rate_limited،at_capacity،service_unavailable،upstream_error. التزم بقيمةretryAfterعند توفرها. استخدم التراجع الأسي (exponential backoff) مع تذبذب عشوائي (jitter) عند عدم توفرها. لا تستجب لها بإعادة إرسال كل استدعاء أداة في قائمة الانتظار دفعة واحدة: بل قلل عدد الاستدعاءات المشغلة بالتوازي بدلاً من ذلك. - الحفاظ على النطاق وإعادة المحاولة لاحقًا:
no_eligible_proxy. لا تقم بإزالةexitCountriesأو استبدال بلد آخر بدون تصريح. قم بتغيير قائمة السماح أو توسيعها فقط عندما يغير المستخدم المتطلبات صراحة. - عدم إعادة المحاولة حتى يتم تصحيح المدخلات أو بيانات الاعتماد:
bad_request،auth_failed،not_found،ssrf_blocked. بالنسبة لـauth_failed، تحقق من مفتاح API الخاص بـ FourA، وليس بيانات اعتماد الموقع الهدف. - تبديل الأداة عندما يتطلب المحتوى ذلك: يمكن أن يبرر ظهور
forbiddenعلىfoura_singleإجراء محاولة محدودة لـfoura_proxy. استخدمfoura_browserعندما يتطلب المحتوى المطلوب JavaScript. بعد نجاح اختيار الـ proxy، مرر معرفproxyالذي تم إرجاعه إلىfoura_browser.proxyبدلاً من بدء اختيار جديد.
مثال على إعادة المحاولة (TypeScript، من جانب 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");
}
مواضيع ذات صلة
- MCP Server، الأدوات الأربع ومخططاتها (schemas)
- MCP Recipes، موجهات سير العمل المضمنة مع الخادم
- API Errors، نفس هيكل الاستجابة (envelope) في طبقة REST API الأساسية
- Rate Limits، حدود الحساب والمنصة خلف
rate_limitedوat_capacity