شرحexplainer · 2026-10-08

من الصفر إلى الإنتاج: نظام فواتير آلي كامل ونشره كخادم MCP — المشروع النهائي

المقال الأخير في سلسلة n8n يبني نظام فرز فواتير كاملاً طبقة فوق طبقة، من متغيّرات البيئة إلى بوابة موافقة بشرية تسبق أي أثر جانبي. ثم يعرضه على Claude وأي عميل MCP آخر كأدوات قابلة للاستدعاء، مع تحديد ما لن نبيه مسبقاً، وقائمة تحقّق من ثمانية أسئلة قبل النشر.

نُشر 8 أكتوبر 2026 · قبل 3 ساعاتconfidence 0.902 مصادرrecheck 2027-01-06
مخطط يعرض البنية الكاملة: طلب خارجي، ثم وكيل، ثم أدوات، ثم بوابة موافقة بشرية. عند الموافقة ينفذ الإجراء ثم يُسجَّل، وعند الرفض يتوقف المسار. مخرج آخر من الأدوات يذهب إلى مسار معالجة الخطأ الذي ينبّهك. الرموز ‎{ }‎ على السهم تبيّن تدفق البيانات.

هذا هو آخر مقالات سلسلة n8n، وهو الذي يجمع ما سبق في شيء واحد يعمل. مقال الوكلاء الثلاثة فرّق بين عقدة AI Agent والوكيل ككائن في المشروع. مقال الاستضافة الذاتية والأمان تناول مفتاح التشفير ووضع الطابور وما الذي يغادر شبكتك. مقال الترخيص والإصدارات قال ما لا يجوز فعله تجارياً. هنا نضعها كلها في مسار واحد: نظام فرز فواتير يومي، محميّ ببوابة موافقة بشرية، ثم معروض على Claude وأي عميل MCP آخر كأدوات قابلة للاستدعاء.

ما الذي لن بنينه؟ الجواب: ثلاثة أشياء، ونقولها قبل المشروع لا بعده

المقال الذي يبني «نظاماً كاملاً» ينتهي عادةً بلوحة تحكم ومراقبة أداء ومصادقة مركزية. لن نبني أياً منها.

أولاً: لن ننشره كمنتج. ترخيص n8n يسمح لك باستخدامه لأغراض أعمالك الداخلية، لا لإعادة توزيعه كخدمة لأشخاص آخرين. الفقرة الحرفية وشروط ملفات .ee. كاملةً في مقال الترخيص — وأي خطوة من هذا المشروع نحو عميل خارجي تخرج من الترخيص لا من الهندسة.

ثانياً: لن نضع لوحة تحكم. ما سنبنيه هنا سبع عقد في سير عمل واحد، وسير عمل أخطاء من عقدتين. لوحة تحكم حقيقية تحتاج جداول ومصادقة وتتبّع تنفيذ ونسخاً احتياطية — أي مشروع ثانٍ، لا طبقة أولى في الأول.

ثالثاً: لن نضع AI Agent داخل هذا المشروع. المخرجات هنا محدّدة سلفاً والمبلغ رقمي والمقارنة حتمية. الوكيل يضيف احتمالاً لا نحتاجه، ومشروع لو أُوقف نصفه لتوقّف عن كونه حتمياً. حين يصبح العمل مفتوح النهاية، ساعتها تستدعي ما بسطناه في مقال الوكلاء الثلاثة. ولمن قرأ مقال الوكلاء الثلاثة الفرق واضح: حين تضيف عقدة وكيل، فأنت داخل LangChain داخلياً — مقال إنشاء الوكيل والوسيط يشرح ما الذي يعنيه هذا عملياً.

الحدود الثلاثة مكتوبة هنا لأن الصدق في الحدود هو ما يجعل ما سنبنيه بعده قابلاً للتصديق.

ما الذي سنبنيه بالضبط؟ الجواب: مواصفة في نص عادي، قبل أول عقدة

اكتب هذه المواصفة قبل أن تفتح المحرّر، لا بعد أن تبنّي. المواصفة هي التي تخبرك أن عقدة الطلب وحدها لا تكفي، وأن هناك عقدة توحيد لازمة، وأن هناك إنساناً في المسار أصلاً.

الاسم        : فرز الفواتير
متى يعمل     : مرة كل يوم، عند ساعتين بعد منتصف الليل بتوقيت النسخة
المدخل       : واجهة الفواتير — طلب قراءة للفواتير المفتوحة، عبر بيانات اعتماد محفوظة
الإخراج      : عنصر لكل فاتورة، بحقول invoiceId وamount وroute وfetchedAt
عند الفشل    : سير عمل أخطاء واحد مشترك باسم «فرز-أخطاء»
هل يُنشر     : نعم، بعد تشغيل يدوي ثم تشغيل جزئي على بيانات حقيقية

لاحظ كم سؤالاً أجبتَ عنه بلغة بشرية قبل أن تكتب أي مفتاح. هذا هو الترتيب الصحيح: المواصفة، ثم البنية، ثم التعبير، ثم الإعداد. من يبدأ بالعقدة ثم يكتب المواصفة ينتهي بسير عمل يعمل ولا يعرف لماذا.

الطبقة صفر: الأساس الذي لن تراه على اللوحة

الجواب: متغيّرات البيئة تحسم أمرين قبل أن تفتح المحرّر — أين تُشغَّل النسخة، وأين تُخزَّن مفاتيحها.

# طبقة 0 — الأساس
EXECUTIONS_MODE=queue
N8N_ENCRYPTION_KEY=<سلسلة عشوائية طويلة تُولَّد مرة واحدة وتُحفظ خارج النسخة>
WEBHOOK_URL=https://n8n.example.com

ثلاثة أسطر فقط هنا تحمل ثلاث قرارات مختلفة تماماً. EXECUTIONS_MODE=queue يعني أن النسخة الرئيسية لن تنفّذ سيرَيات العمل بنفسها. N8N_ENCRYPTION_KEY يعني أن ما تكتبه في .env هنا هو ما يفتح بيانات الاعتماد المخزّنة في قاعدة البيانات — لا تكتب مفتاحاً مثل sk-... في نص سير العمل إطلاقاً، ضعه في بيانات اعتماد من واجهة المحرّر، وولا يقرأه إلا العقد التي لها صلاحية الوصول إليه. تفصيل التوليد والتخزين والمشاركة بين العمال في مقال الاستضافة الذاتية.

واختيار وضع الطابور هنا ليس مجانياً، وسيظهر ثمنه في الطبقة التالية.

الطبقة الأولى: متى يعمل؟ الجواب: مرة في اليوم، لا كل خمس دقائق

الجواب في العقدة الأولى: Schedule Trigger بمُحفّز يومي، لا أكثر. الفرق بين يومي وكل خمس دقائق ليس في إعدادات العقدة، بل في الجدول الذي تكتبه في حقله.

السبب ماليّ لا تقنيّ. من صفحة الأسعار نفسها: «For instance, a daily schedule would result in 30 or 31 executions per month, while one that runs every 5 minutes would result in about 8,600–8,900 executions monthly.» ومعنى الجملة أنّ «An execution is a single run of your entire workflow. It doesn't matter how many steps are in the workflow or how much data it processes. It's still a single execution.»

فجدول كل خمس دقائق لا يدفع ثمن خمس دقائق من العمل، بل يدفع ثمن رقم تشغيلات شهري كامل. اكتب في مواصفتك سطراً اسمه عدد التشغيلات المتوقّع شهرياً واحتفظ به — سنعود إليه في قائمة التحقق.

وقاعدة أخرى توفّر عليك صورة مفاجئة: المشغّلات الدورية تُحتسب كل مرة تنطلق فيها، لكن التشغيل اليدوي لا يُحتسب، ولا تُحتسب تنفيذات سيرَيات الأخطاء، ولا الجزء الداخلي من سير عمل يستدعي سير عمل آخر بحزمة Execute Sub-workflow. أي أن تجربتك المجانية لا تستهلك حصّتك — فصّلها مقال منطق المسار.

الطبقة الثانية: من أين تأتي البيانات؟ الجواب: عقدة HTTP Request واحدة ببيانات اعتماد

الجواب: عقدة واحدة، طريقة GET، حقل المصادقة من بيانات اعتماد لا نص مفتاح في الرابط.

ثلاثة أشياء تُضبط فيها قبل التشغيل:

أ. حقول Add Option > Batching داخل نفس العقدة: عدد العناصر في الطلب الواحد، والفاصل الزمني بين الطلبات. هذا هو الحارس من ضربة حدّ المعدّل، والخطوات الرسمية مشروحة خطوة بخطوة في مقال منطق المسار.

ب. On Error لا يبقى على Stop Workflow في طلب خارجي، بل ينتقل إلى Continue (using error output)، لأن فشل خدمة خارجية يجب أن يصطدم بمسار معالجة لا أن يوقف الفاتورة كلها.

ج. لا شيء في هذا الطلب يكتب في أي نظام. القراءة فقط.

⚠️ قبل أن تضيف Convert to File أو تُلحق PDF بالفاتورة أنت في الطبقة صفر اخترت EXECUTIONS_MODE=queue. والتوثيق يقول حرفياً: «n8n doesn't support queue mode with binary data storage in filesystem. If your workflows need to persist binary data in queue mode, you can use S3 external storage.» ومن الصفحة نفسها: «Running a distributed system with this setup over SQLite isn't supported.» و«Running n8n with execution mode set to queue with an SQLite database isn't recommended.»

ما يعنيه هذا عملياً: لو بدأت اليوم بلا وعي بملفات PDF، وقررت غداً أن تشغّل مجموعة عمال خلف موازن، ستكتشف أن الملفات التي كانت تُكتب على القرص لم تعد قابلة للاعتماد. أمامك طريقان لا ثالث لهما: إمّا تكمل بلا بيانات ثنائية دائمة في سير العمل، وإمّا تفعّل تخزيناً خارجياً مثل S3 قبل أن تحتاجه. والاختيار الثالث — «سأجربه على نسخة واحدة» — هو بالضبط ما يكلّفك بعد شهر.

ولاحظ أن التخزين الخارجي للبيانات الثنائية ليس من Community edition أصلاً، فإذا كنت على الإصدار المجاني فالخيار الوحيد هو المسار الأول. مقال الترخيص يحصر ما تحصل عليه وما لا تحصل عليه.

الطبقة الثالثة: توحيد البيانات قبل أي قرار — عقدة Code

الجواب: قبل أن تقارن أي مبلغ، اجعل كل عنصر شكلاً واحداً. واجهة الفواتير ترجع الحقول بأسماء مختلفة حسب حالة الفاتورة، وأسماء الحقول تختلف بين حسابك التجريبي وحسابك الإنتاجي. المقارنة على بيانات غير موحّدة هي أكثر أسباب «لماذا رفض هذا؟» في أنظمة الفوترة.

ضع Code node في وضع Run Once for All Items — وضع Run Once for Each Item سيشغّل النص على كل عنصر على حدة، وهو بطيء ومضلّ.

const seen = new Set();
const out = [];

for (const item of $input.all()) {
  const raw = item.json.invoice ?? item.json;
  const invoiceId = `${raw.customer}:${raw.id}`;

  if (seen.has(invoiceId)) continue;   // تكرار ناتج عن تقسيم الصفحات
  seen.add(invoiceId);

  out.push({
    json: {
      invoiceId,
      amount: Number(raw.total),       // نفترض أن المبالغ بالوحدة الكبرى
      currency: raw.currency ?? 'EUR',
      route: 'pending',                 // لكل عنصر مسار افتراضي
      fetchedAt: $now.toISO(),
    },
  });
}

return out;

ثلاثة قرارات في هذا النص الصغير:

seen تمنع تكرار الفاتورة نفسها إن رجعت في صفحة نتائج تالية. عنصر واحد لكل فاتورة هو أصلاً ما تحتاجه، لا تحسين. أسماء حقول الفاتورة تتغيّر مع الوقت، ومواصفتك تحتاج أسماء ثابتة لا أسماء الواجهة الخارجية. وroute: 'pending' تعني أن لكل عنصر تصنيفاً افتراضياً — لو توقفت الأتيجة في منتصف الدفعة، لا يبقى عنصر بلا مسار.

وأخيراً $now: تجده من متغيّرات $، وهو أدقّ رقم في المواصفة كلها. مقال التعبيرات يشرح لماذا $now في نسخة بلا منطقة زمنية مضبوطة يكتب تاريخاً بتوقيت نيويورك، بينما لا يرفع n8n أي تحذير.

الطبقة الرابعة: أين يتّخذ القرار؟ عقدة If واحدة تقسم العالم إلى نصفين

الجواب: عقدة If واحدة تقارن amount بحدّ تكتبه بنفسك. أكبر من الحدّ يحتاج موافقة بشرية، وأصغر منه مُفوَّض مسبقاً بقرار مكتوب.

شرط 1 : {{ $json.amount }}  is greater than  →  المسار الأول (يحتاج موافقة)
شرط 2 : وإلا                                    →  المسار الثاني (مُفوَّض)

اكتب الحدّ رقماً داخل العقدة، ولا تحاول جعله متغيّر بيئة: متغيّرات المشروع ليست ضمن Community edition. حدّ مكتوب داخل العقدة أفضل من حدّ مركزي لا تستطيع فتحه ولا تعديله.

وفي هذا المقام انتبه لقاعدة واحدة: كل عقدة تُغيّر شيئاً في العالم يجب أن تأتي بعد هذه العقدة، لا قبلها. إن بنيت عقدة الدفع قبل الشرط تكون قد دفعت فاتورة ثم اكتشفت أنها كانت خارج حدود ما فوّضك به أحد.

الطبقة الخامسة: بوابة الموافقة — هنا بالذات، لا في أي مكان آخر

الجواب: المسار الذي يحتاج موافقة يذهب إلى عقدة Ask Human، ومخرجها وحده هو الذي يصل إلى عقدة الأثر الجانبي Settle.

ضع Ask Human كعقدة Slack بخيار «send and wait» أو أي عقدة الانتظار، بحيث يتوقف التنفيذ ولا يتجاوز إلى ما بعدها حتى يصل الرد. المخرج الذي يعود منها يحمل route: 'approved'.

⚠️ ترتيب البوابة ليس تفصيلاً أخلاقياً بل هندسياً التنفيذ الذي يتوقف عند بانتظار إنسان ثم يستأنف قد يعيد تشغيل ما قبل التوقف — وهذه قراءة تشغيلية تعلّمناها من سلوك الاستئناف، لا جملة مقتبسة من التوثيق، فخذها كقاعدة تشغيل لا كضمانة موثّقة. القاعدة التي تتبنّاها: كل عقدة تكتب في نظام خارجي ولا تحتمل التكرار تأتي بعد البوابة، ولا تسبقها أبداً. اكتب هذا في المواصفة كقاعدة، لا كنصيحة. ووقّعها بمفتاح تفرّد: أرسل invoiceId كترويسة idempotency مع كل طلب دفع. حين يعيد n8n تشغيل ما قبل التوقف، الترويسة هي التي تحفظ الفاتورة من الخصم مرتين — لا المنطق في شرطك.

لو أحببت أن تتعلّم أكثر عن كم ثانية يصمد الاستئناف دون تكرار، فمقال منطق المسار ومعالجة الأخطاء يشرح الفرق بين «يحفظ التنفيذ مكان توقفه» و«يعيد من البداية»، ومتى يختار كل واحد.

الطبقة السادسة: الأثر الجانبي — عقدة واحدة تغذّيها المساران

الجواب: عقدة Settle واحدة تستقبل من المسارين معاً، وهي كل ما يملك حق الكتابة في النظام المالي.

{
  "parameters": {
    "method": "POST",
    "url": "={{ $env.INVOICE_URL }}",
    "sendBody": true
  },
  "id": "settle-node",
  "name": "Settle",
  "type": "n8n-nodes-base.httpRequest",
  "typeVersion": 4
}

ثلاثة أشياء في هذه العقدة تحديداً تستحق التوقف:

الرأس Idempotency-Key هو ما يجعل الطبقة 5 فعّالة لا شكلية. حقل route يجعل أثر كل مسار قابلاً للتدقيق لاحقاً: بعض الفواتير مرّت بموافقة بشرية وبعضها مُفوَّض سلفاً. و$env للوصول إلى عنوان الخدمة، مفتاحك في البيئة لا في نص سير العمل — وهذا يبقى صحيحاً حتى لو نشرتَ نصّ سير العمل على Git.

وملاحظة عن Settle: هي تتلقّى من Ask Human ومن فرع If المباشر في آن واحد. هذه ليست مخالفة لقاعدة «البوابة قبل الأثر» — القاعدة تخصّ الأثر الذي يحتاج موافقة. والأثر المُفوَّض بقرار مكتوب في If يمشي مساره المباشر — وأي أثر يحتاج موافقة لا يلتصق بـ Settle إلا من مخرج Ask Human.

الطبقة السابعة: تشكيل المخرجات في عقدة واحدة

الجواب: Edit Fields واحدة في النهاية تبني شكل المخرج النهائي وتختم المشروع.

ضع كل التعبيرات في هذه العقدة أو في عقدة Code، ولا في عقد الأعمال نفسها. سبب ذلك ليس ذوقاً: تعديل شرط في عقدة HTTP أثناء تصحيح حقل ناتج يجعل كل علة سببين، وتضيع ساعاتك في قراءة السجل. المواصفة تقف في مكان واحد، والحقول تُبنى في مكان واحد.

الطبقة الثامنة: ماذا يحدث حين يفشل كل هذا؟

الجواب: سير عمل أخطاء واحد مشترك، لا تنبيه في كل سير عمل.

{
  "name": "فرز-أخطاء",
  "nodes": [
    { "name": "Error Trigger", "type": "n8n-nodes-base.errorTrigger", "typeVersion": 1 },
    { "name": "Log Failure", "type": "n8n-nodes-base.noOp", "typeVersion": 1 }
  ]
}

والربط في إعدادات سير العمل نفسه: «For each workflow, you can set an error workflow in Workflow Settings. It runs if an execution fails.» ثم يضيف: «The error workflow must start with the [Error Trigger]» — لذلك لا تنسخ عقدة Schedule Trigger من سير العمل الأول وتظنّ أنها تعمل. ومن النص نفسه: «You can use the same error workflow for multiple workflows.»

نقطتان قبل أن تنتقل:

أضف عقدة Stop And Error في مسار تجريبي واحد لتتأكد أن سير العمل الأخطاء يصل فعلاً. أسوأ ما في الأمر أن نسيان استدعائه لا يظهر إلا بعد أول عطل حقيقي، لا في نومك.

وثقّق نقطة أخيرة: تنفيذات سير العمل الأخطاء لم تعد تُحتسب ضمن حصّتك على كل الخطط. رقم الإصدار الذي حدث فيه ذلك وشرحه الكامل موثّقان في مقال منطق المسار، ولا نكرّره هنا.

ثم نضع المشروع على السطح: MCP في الاتجاهين

الجواب: نظامك صار ينفع في اتجاهين معاً، وهما مختلفان تماماً حتى لو كانا نفس الملف.

الاتجاه الأول: عميل MCP ينادي n8n — فيصل Claude أو غيره إلى نسختك، فيبني سير عمل أو يعدّله أو يشغّله، وتستخدم أنت Claude كواجهة بناء لأتمتك. منذ n8n 2.13.0 هذه القدرة موجودة: «building or editing workflows (available from n8n 2.13.0)».

الاتجاه الثاني: n8n ينادي العالم — تعرّض عقد الأدوات في سير عملك كخادم MCP، فيستدعي أي عميل MCP «فرّز هذه الفواتير» كأداة قابلة للاستدعاء، لا تحتاج أن يكون ذلك العميل Claude تحديداً.

نفس سير العمل، غرضان مختلفان تماماً، وملف واحد. من يظنّ أن «MCP في n8n» شيء واحد يخلط بين ما يفعله n8n كأداة وما يفعله كخادم.

الاتجاه الأول عملياً: أوامر الاتصال الحقيقية

هذه الأوامر كما هي في التوثيق، لا تقريبية:

claude mcp add --transport http n8n https://<your-n8n-domain>/mcp-server/http
codex mcp add n8n --url "https://<your-n8n-domain>/mcp-server/http"
gemini mcp add --transport http n8n https://<your-n8n-domain>/mcp-server/http

وإن كان عميلك لا يقبل HTTP مباشراً، فمفتاح bearer يدخل من جسر:

{ "mcpServers": {
    "n8n-mcp": {
      "command": "npx",
      "args": ["-y", "supergateway", "--streamableHttp",
               "https://<your-n8n-domain>/mcp-server/http",
               "--header", "Authorization:Bearer <YOUR_N8N_MCP_TOKEN>"]
    }
  }
}

⚠️ هذا ليس عنوان محرّرك — فخّ يقع فيه الجميع التوثيق ينبّه حرفياً: «It ends in /mcp-server/http, so it looks like https://<your-n8n-domain>/mcp-server/http. This isn't the address of your n8n editor. Don't paste the URL from your browser's address bar.»

إن لصقتَ العنوان الذي في متصفحك ستظنّ أن الاتصال فشل، بينما أنت لا تكلّم خادم MCP أصلاً. تحقّق أولاً من ذيل العنوان: يجب أن ينتهي بـ /mcp-server/http.

وقبل أن تفعّل الاتصال، فعّل الالتقاط لكل سير عمل على حدة، لا للجميع دفعة واحدة: «It doesn't provide blanket exposure to all workflows in your instance. You must enable MCP at your instance level and then enable each workflow individually.»

ولإطفاء الوصول كلياً عند الانتهاء من التجربة، يكفي متغيّر واحد: N8N_DISABLED_MODULES=mcp.

الاتجاه الثاني عملياً: سير عمل آخر يعرض أدواتك

الجواب: أضف MCP Server Trigger في سير عمل جديد، ثم اربطه بعقد Tool فقط.

هذه العقدة مختلفة عن كل مُحفّز رأيته في السلسلة. حرفياً: «Unlike conventional trigger nodes, which respond to events and pass their output to the next connected node, the MCP Server Trigger node only connects to and executes tool nodes.» لا يمرّر بياناته إلى العقدة التالية، بل يستقبل نداءً من عميل MCP ويُنفّذ الأدوات المتصلة به.

ثلاثة أشياء تُضبط فيه فوراً:

خيارات المصادقة ثلاثة: None أو Bearer auth أو Header auth. اختر الثاني أو الثالث في أي شبكة لا تثق بها، وNone تعني أن أي من يصل إلى العنوان ينادي أدواتك بلا هوية.

العنوان يتغيّر بين الاختبار والإنتاج: «Production: n8n registers a production MCP URL when you publish the workflow.» فلا تُعطِ عنوان اختبار لأحد في الإنتاج.

ولا يدعم البثّ القياسي على الإدخال والإخراج: «It currently doesn't support standard input/output (stdio) transport.»

⚠️ مع نسخ الـ webhook المتعددة، وكّل /mcp* إلى نسخة واحدة «If you run multiple webhook replicas, you need to route all /mcp* requests to a single, dedicated webhook replica.» هذا معنى أن موازن الحمل الذي وزّعته على بقية الـ webhooks في مقال الاستضافة الذاتية يجب أن يستثني مسار MCP، وإلا انكسر البثّ في منتصف جلسة. والبلوك الذي يجعله يعمل:

location /mcp/ {
    proxy_http_version 1.1;
    proxy_buffering    off;
    gzip               off;
    chunked_transfer_encoding off;
    proxy_set_header   Connection '';
}

كل سطر هنا ليس تحسيناً اختيارياً — أوّلها يبقي الاتصال، وثانيها يمنع تخزين الاستجابات، ورابعها يمنع قطع البثّ.

ماذا يرى كل عميل MCP ممّا فعّلته؟ الجواب: نفس القائمة للجميع، بلا استثناء

هنا يجب أن تتوقّف، لأن العبارة أدناه تقلب ترتيب أولوياتك: ما يبنيه Claude وما ينفّذه Claude ليسا شيئاً واحداً، وأنت كنت تظنّ أنهما كذلك.

⚠️ قائمة واحدة يراها الجميع — ولا يوجد جدار بينها «It's not scoped to each MCP client. All clients you connect (for example, Claude Desktop and ChatGPT) can see all workflows you've enabled for MCP access. You can't restrict specific workflows to specific clients.»

ما معناه عملياً؟ أنّ ما فعّلته لـ Claude هو نفسه تماماً ما يراه ChatGPT، وما يراه أي عميل آخر تربطه لاحقاً. لا يوجد «حساب Claude» و«حساب ChatGPT» لكل منهما قائمته. جدار مصادقة خارجي، أو نسخة n8n منفصلة لكل عميل، أو تقسيم حقيقي — هذه الخيارات الثلاثة وحدها تعطيك عزلاً فعلياً.

وقاعدة تشغيل قصيرة: راجع قائمة ما هو مفعّل مرة كل أسبوع، وأطفئ ما انتهى غرضه بـ N8N_DISABLED_MODULES=mcp بدل تركه مفتوحاً.

وثاني مفاجأة في نفس الباب: «Most MCP tools work on unpublished workflows. The exception is execute_workflow, which defaults to production mode and runs the published version of a workflow.» أي أن المسودة آمنة للتجربة، وأن النشر يجعلها قابلة للتشغيل من عميل خارجي. انشر ما تريد تشغيله، ولا تنشر الباقي — وتذكّر أن الموافقة على النشر يجب أن تمرّ بالبوابة نفسها التي بنيتها في الطبقة 5، لا بمحادثة جانبية.

المواصفات النهائية: العقد في مواضعها

{
  "connections": {
    "Schedule Trigger":       { "main": [[{ "node": "Fetch Open Invoices", "type": "main", "index": 0 }]] },
    "Fetch Open Invoices":    { "main": [[{ "node": "Normalise Invoices", "type": "main", "index": 0 }]] },
    "Normalise Invoices":     { "main": [[{ "node": "Over Threshold?",  "type": "main", "index": 0 }]] },
    "Over Threshold?": {
      "main": [
        [{ "node": "Ask Human", "type": "main", "index": 0 }],
        [{ "node": "Settle",    "type": "main", "index": 0 }]
      ]
    },
    "Ask Human":  { "main": [[{ "node": "Settle", "type": "main", "index": 0 }]] },
    "Settle":     { "main": [[{ "node": "Shape Output", "type": "main", "index": 0 }]] },
    "Shape Output": { "main": [[]] }
  }
}

وهذه قراءة المخطط بترتيب الطبقات: Schedule Trigger يُطلق، Fetch Open Invoices يقرأ، Normalise Invoices يوحّد، Over Threshold? يقرّر، Ask Human ينتظر، Settle يكتب، Shape Output يسلّم. عقدة Settle وحيدة تحتمل الكتابة، ومخرج Ask Human هو الطريق الوحيد إليها حين يلزم موافقة.

ثم سير عمل ثانٍ من عقدتين: MCP Server Trigger وعقد Tool تقرأ من نفس منطق المواصفة.

قائمة تحقّق بعد البناء: ثمانية أسئلة يجب أن تجيب عنها

  1. كم عقدة في سير العمل الأول، وأيّها لا يمكن حذفها دون كسر منطق المشروع كله؟
  2. ما أول عقدة تكتب شيئاً في نظام خارجي، وأين تقع نسبةً إلى Ask Human؟
  3. إذا استأنف التنفيذ من وسط الطريق، هل الفاتورة تُدفع مرتين؟ وأين بالضبط مفتاح التفرّد الذي يمنع ذلك؟
  4. كم تشغيلاً شهرياً يكلّفك هذا الجدول، وهل الرقم مكتوب في مواصفتك أم محفوظ في ذاكرتك؟ (تذكّر: اليومي = «30 or 31 executions per month».)
  5. أين يوجد N8N_ENCRYPTION_KEY الآن، ومن غيره يستطيع قراءته، وهل هو خارج النسخة أم داخلها؟
  6. مع EXECUTIONS_MODE=queue، هل يُنتج نظامك بيانات ثنائية دائمة؟ وإن لم يكن، فهل سبب ذلك قرارٌ مكتوب أم صدفة؟
  7. ما سيرَيات العمل المفعّلة لـ MCP اليوم، وما القائمة التي يراها كل عميل مربوط بلا استثناء؟
  8. ما الذي يتغيّر في سلوك execute_workflow بمجرد نشر مسودتك، وما الذي يفعله سؤالك هذا لو لم تنشر بعد؟

إن عجزت عن الإجابة عن أي واحد منها، فالطبقة الناقصة هي الطبقة التي ستكتشفها في أول عطل حقيقي — لا في يوم النشر.


تحتاج أتمتة تعمل فعلاً؟

نصمّم ونبني أنظمة أتمتة للشركات والأفراد على n8n — من أول سير عمل يعمل خلال يوم، إلى وكيل يوثّق خطواته ويطلب موافقة بشرية قبل أي إجراء حسّاس. اكتب لنا وضعك من صفحة التواصل.


أُراجع في n8n 2.42.5 (2026-10-08). n8n يُصدر نسخاً جديدة أسبوعياً تقريباً، فراجع التوثيق إن كان عمرك يتجاوز بضعة أشهر.

المصادر

كل ادعاء في المقال مرتبط بمصدره. الروابط تفتح في نافذة جديدة.

  1. 01
    Connect to an n8n MCP server — instance-level MCP access ↗

    docs.n8n.io

    أداة execute_workflow استثناء على بقية أدوات MCP: تعمل في وضع الإنتاج على النسخة المنشورة من سير العمل.

  2. 02
    MCP client examples — connection commands and the URL rule ↗

    docs.n8n.io

    أوامر الاتصال الفعلية بـ Claude وCodex وGemini تنتهي كلها بـ /mcp-server/http، وهذا العنوان ليس عنوان محرّرك.

  3. 03
    n8n Pricing — الخطط والأسعار، وتوفّر Business، ونبض الترخيص اليومي ↗

    n8n.io

    جدول يومي يعني 30 or 31 executions per month، وجدول كل خمس دقائق يعني نحو 8,600–8,900 executions monthly، والتنفيذ الواحد هو تشغيل كامل لسير العمل مهما كثرت خطواته.

  4. 04
    MCP Server Trigger node — behaviour, auth, transports, and proxying ↗

    docs.n8n.io

    خيارات مصادقة MCP Server Trigger ثلاثة هي None وBearer auth وHeader auth، والعنوان الإنتاجي يُسجَّل عند نشر سير العمل.

  5. 05
    MCP Server Trigger node — behaviour, auth, transports, and proxying ↗

    docs.n8n.io

    عقدة MCP Server Trigger لا تتصل إلا بعقد الأدوات، ولا تنقل مخرجاتها إلى عقدة تالية.

  6. 06
    Connect to an n8n MCP server — instance-level MCP access ↗

    docs.n8n.io

    قائمة سيرات العمل المفعّلة لـ MCP واحدة لكل العملاء ولا يمكن تقييد سير عمل بعميل بعينه.

  7. 07
    Connect to an n8n MCP server — instance-level MCP access ↗

    docs.n8n.io

    قدرة عميل MCP على بناء سيرَيات العمل وتحريرها متاحة منذ n8n 2.13.0.

  8. 08
    MCP Server Trigger node — behaviour, auth, transports, and proxying ↗

    docs.n8n.io

    مع نسخ webhook المتعددة يجب توجيه كل طلبات /mcp* إلى نسخة واحدة مخصّصة، وإلا انكسر البثّ.

  9. 09
    Connect to an n8n MCP server — instance-level MCP access ↗

    docs.n8n.io

    وصول MCP على مستوى النسخة لا يعرّض كل سيرات العمل تلقائياً: يجب تفعيله على مستوى النسخة ثم تفعيل كل سير عمل على حدة.

  10. 10
    Enable queue mode — environment variables and hard limitations ↗

    docs.n8n.io

    وضع الطابور لا يدعم تخزين البيانات الثنائية على نظام الملفات، والبديل الموثّق هو تخزين خارجي مثل S3، كما أنه غير مدعوم فوق SQLite.

شروح أخرى

الكل ←