Skip to main content
يعمل MCP في اتجاهين. يستطيع وكيلك أن يستدعي أدوات خوادم MCP، أو يستطيع وكيلك أن يكون هو نفسه خادم MCP يستدعيه Claude Code وCursor وغيرهما من عملاء MCP. كلا الاتجاهين في المسار الفرعي @lousho/build-ai-agent/mcp، وحزمة @modelcontextprotocol/sdk اعتمادية نظيرة (peer dependency) اختيارية: ثبّتها لاستخدام أي من الاتجاهين.
الدوال connectMcp وloadMcpTools وserveMcp مُصدَّرة من @lousho/build-ai-agent/mcp؛ وتصدّرها كذلك جذر الحزمة و@lousho/build-ai-agent/tools. أما createAgent({ mcpServers }) فلا يحتاج إلى أي استيراد من المسار الفرعي.

استخدام خوادم MCP في وكيل

يقبل createAgent({ mcpServers }) الخريطة نفسها. تتصل الخوادم عند await agent.ready() أو تلقائيًا عند أول send() / stream()؛ وتُضاف أدوات كل خادم باسم <server>__<tool> (مثل docs__search). الخادم الذي يتعذر اتصاله يُفشل ذلك الاستدعاء، ويحاول الاستدعاء التالي مرة أخرى. يقطع agent.close() الاتصال بها (ويوقف عمليات stdio)؛ وأي استدعاء أداة لاحق يعيد الاتصال. وبلا mcpServers لا تفعل ready() ولا close() شيئًا. تختار بادئة النموذج vendor/ المزوّد؛ ومع OpenRouter استخدم openrouter/<vendor>/<model> (مثل openrouter/openai/gpt-4o-mini).
تُشغَّل مدخلات stdio بالقيمتين command وargs؛ وتُضاف env إلى البيئة الافتراضية (PATH وما شابهه)، فهي ليست بديلًا عنها. أما مدخلات HTTP فتستخدم نقل HTTP القابل للبث (streamable HTTP) وترسل الترويسات الثابتة headers مع كل طلب. ويمكن لمدخل HTTP أيضًا تسجيل الدخول بـ OAuth، كما تصفه مواصفات تفويض MCP: أضف oauth: { redirectUri } فيسجّل مشغّلٌ دخول الوكيل مرة واحدة؛ انظر خوادم MCP مع OAuth. الخريطة هي نفسها التي يعلنها ملف المواصفات؛ انظر الإعدادات (قسم mcpServers) لصيغة YAML.

مشاركة الخوادم عبر connectMcp()

لمشاركة الخوادم بين عدة وكلاء، أو لاختيار طريقة معالجة الإخفاقات، استدعِ connectMcp(servers, options?) ومرّر tools الناتجة عنها بنفسك. تتصل بكل خادم وتسرد أدواته قبل أن تكتمل، فتكون الأدوات معروفة سلفًا. الخيارات:
  • onError: القيمة 'throw' (الافتراضية) ترفض الوعد حين يتعذر اتصال خادم، بعد إغلاق الخوادم الأخرى؛ والقيمة 'skip' تستبعد ذلك الخادم وتحذّر عبر logger.
  • lazy (الافتراضية true): بعد close() أو انقطاع الاتصال، يعيد استدعاء الأداة التالي الاتصال. أما مع false فيفشل ذلك الاستدعاء. وسرد الأدوات يحتاج إلى اتصال، فلا تؤخّر lazy أول اتصال أبدًا.
  • logger: يتلقى تحذيرات الخوادم والأدوات المتخطّاة (الافتراضي: لا شيء).
  • tokens: مخزن الرموز (AgentStore.tokens) للخوادم التي لها oauth؛ وهو مطلوب حين يكون لأي خادم oauth.
تعيد { tools, close(), status() }؛ وتربط status() كل خادم بإحدى القيم 'idle' أو 'connected' أو 'failed' أو 'needs-auth' (خادم له oauth لم يسجّل التطبيق دخوله إليه). tools هي Record<string, ToolDescriptor> مفتاحها <server>__<tool> — خريطة، لا المصفوفة التي تصنعها نتائج defineTool(). وتقبل createAgent({ tools }) الصورتين معًا وتجمعهما: tools: [myTool, mcp.tools] تسجّل عناصر المصفوفة بأسمائها وعناصر الخريطة بمفاتيحها، فتجتمع أدواتك الخاصة وأدوات MCP في قائمة واحدة. (والنشر في خريطة واحدة، tools: { ...mcp.tools, my_tool: myTool }، يعمل أيضًا.)
mcp.tools خريطة، وtools تقبل المصفوفة أيضًا، فتختلط الصورتان: tools: [mcp.tools, weatherTool] أو tools: [...createFsTools(workspace), ...Object.values(mcp.tools)] (يحمل كل واصف MCP اسم <server>__<tool> الخاص به، فيعمل Object.values أيضًا).

الموافقة على أدوات MCP

تصف خوادم MCP كل أداة بتوصيفات (annotations): readOnlyHint و destructiveHint وidempotentHint وopenWorldHint وtitle. وهي تلميحات، لكن SDK تستخدمها قاعدةً افتراضية لـالموافقات: الأداة ذات readOnlyHint: true تعمل؛ والأداة ذات destructiveHint: true، أو التي لا ترسل destructiveHint (الافتراضي في مواصفة MCP أنها مدمِّرة)، توقف التشغيل حتى يوافق إنسان؛ وذات destructiveHint: false تعمل. وعليه فالأداة بلا توصيفات تطلب الموافقة. تبقى التوصيفات الخام في descriptor.metadata.mcp.annotations، ويصير title هو displayName. اضبط approval في مدخل الخادم (mcpServers أو createAgent أو connectMcp()) أو في loadMcpTools(client, name, { approval }):
  • 'annotations' (الافتراضية): كما سبق.
  • 'always' / 'never': اطلب الموافقة لكل الأدوات / لا تطلبها لأي منها.
  • دالة ({ name, annotations }) => boolean تقرر لكل أداة (name هو اسم الأداة المجرّد؛ وannotations هي {} حين لا يرسل الخادم شيئًا). في الشيفرة فقط؛ أما ملف المواصفات فيقبل السلاسل الثلاث.
قواعد الصلاحيات تعمل أولًا، ويظل بوسعها allow أو deny أو ask.

أدوات من عميل اتصلتَ به بنفسك

اتصل بنفسك بـClient من @modelcontextprotocol/sdk ثم حمّل أدواته بـloadMcpTools()، ومرّر النتيجة إلى createAgent() (أو سجّلها في ToolRegistry):
تتوفر loadMcpTools أيضًا من جذر الحزمة ومن @lousho/build-ai-agent/tools.

تقديم وكيل عبر MCP

تعكس serveMcp() عمل loadMcpTools(): فهي تعرض وكيلًا (واختياريًا بعض أدواته) على أنه خادم MCP، فيستطيع Claude Code وCursor وغيرهما من عملاء MCP استدعاءه.
  • بلا حالة. كل استدعاء لأداة الوكيل محادثة جديدة.
  • الإلغاء. إلغاء طلب MCP يُجهض تشغيل الوكيل (agent.send(message, { signal })).
  • الأخطاء. يعود إخفاق الوكيل نتيجةَ MCP فيها isError: true.
  • الموافقات. لا يمكن الموافقة على الأدوات المشروطة بموافقة عبر MCP. التشغيل الذي يتوقف للموافقة يعيد isError: true مع رسالة تقول ذلك. والأدوات المعلَّمة بـneedsApproval لا تُعرض مباشرة ما لم تمرّر allowApprovalTools: true؛ وإن فعلت، شغّلها العملاء دون أي بوابة بشرية.
  • stdio. لا يُكتب إلى stdout غير بروتوكول MCP؛ وتذهب التحذيرات إلى stderr.
  • HTTP. يرتبط افتراضيًا بالعنوان 127.0.0.1. أضف auth: { type: 'bearer', token } لاشتراط ترويسة Authorization: Bearer؛ والارتباط بمضيف غير loopback دون auth يسجّل تحذيرًا.

التوصيفات

تحمل tools/list توصيفات MCP ليعرف العملاء ما تفعله الأداة. الأداة التي تحتاج إلى موافقة تُعلَن بـreadOnlyHint: false, destructiveHint: true؛ وحدّد التلميحات بنفسك عبر annotations (تُرسَل كما هي). والأداة التي بلا تلميحات لا ترسل شيئًا، فيظل وكيل Lousho الذي يستهلك هذا الخادم يسأل قبل تشغيلها (انظر approval في connectMcp())؛ أما readOnlyHint: true فتعمل دون سؤال. والأداة التي تحتاج إلى موافقة لا تُعلَن أبدًا للقراءة فقط. الأدوات المضمّنة read_file وlist_dir و glob وgrep وtodo_read وcurrent_date وday_name للقراءة فقط.

من سطر الأوامر

يقدّم lousho mcp ملف مواصفات وكيل (عبر stdio افتراضيًا):
لاستخدامه من عميل MCP، أضفه إلى إعدادات MCP الخاصة بالعميل (مثل .mcp.json في Claude Code):

الحدود

  • لا يمكن الموافقة على الأدوات المشروطة بموافقة عبر MCP حين تقدّم وكيلًا: التشغيل الذي يتوقف للموافقة يعيد isError: true، والأدوات المعلَّمة بـneedsApproval لا تُعرض ما لم تُضبط allowApprovalTools.
  • يرسل عملاء HTTP الترويسات الثابتة headers مع كل طلب. أما OAuth (oauth) فيملكه التطبيق: منحة واحدة لكل خادم للوكيل كله، يسجّل دخولها مشغّل؛ ولا توجد منح MCP لكل مستخدم بعد.
  • استدعاءات serveMcp() بلا حالة: كل استدعاء لأداة الوكيل محادثة جديدة، ولا يقبل نقل HTTP غير POST.