ابنِ جسر خادم Ollama MCP في الاتجاهين: عميل Python يتيح للنماذج المحلية استدعاء أدوات MCP، وخادم يعرض Ollama على Claude Desktop وClaude Code. يشمل تحديد متطلبات العتاد، وشيفرة تعمل، وملفات إعداد، وحلولًا لثلاثة أخطاء تُفشل معظم المحاولات الأولى.
يمكن لحاسوبك المحمول أن يشغّل بالفعل نموذجًا لغويًا قويًا، لكن معظم أدواتك لا تعرف بوجوده. يحل إعداد خادم Ollama MCP هذه المشكلة. يقع جسر صغير بين Ollama، الذي يقدّم النماذج عبر localhost:11434، وبروتوكول سياق النموذج (MCP)، وهو المعيار الذي تستخدمه تطبيقات الذكاء الاصطناعي للعثور على الأدوات واستدعائها. ابنِه مرة واحدة، وسيتمكن نموذج محلي من قراءة ملفاتك، أو الاستعلام من قاعدة بيانات، أو البحث في ملاحظاتك. وإذا عكست الاتجاه، يستطيع Claude Desktop أو Claude Code تسليم المهام الرخيصة والخاصة إلى GPU الموجودة على مكتبك.
يبني هذا المقال الاتجاهين معًا بشيفرة Python تعمل: عميل جسر يتيح لنماذج Ollama استخدام أي خادم MCP، وخادم جسر يعرض Ollama كمجموعة أدوات لأي عميل MCP. كما ستحصل على أرقام الذاكرة، وملفات الإعداد، والأخطاء الثلاثة التي تستهلك معظم وقت التصحيح.
ماذا يفعل جسر Ollama MCP؟
يحل Ollama وMCP نصفين مختلفين من مشكلة واحدة. يقوم Ollama بتنزيل النماذج مفتوحة الأوزان وتقديمها عبر HTTP API بسيطة. أما MCP، الذي نشرته Anthropic في أواخر 2024، فيوحّد الطريقة التي يتحدث بها تطبيق الذكاء الاصطناعي مع الأدوات والملفات والبيانات عبر برامج صغيرة تسمى الخوادم. تتعامل API الخاصة بـ Ollama مع رسائل الدردشة وتعريفات الأدوات. لكنها لا تتعامل مع MCP، كما أن عملاء MCP لا يعرفون أين توجد نماذجك. ويقوم الجسر بالترجمة بين الطرفين.
طريقتان لبناء الجسر
تعني كلمة "Bridge" برنامجين مختلفين بحسب ما يحتاجه كل طرف، لذا اختر الاتجاه قبل أن تكتب أي شيفرة.
الاتجاه
عميل MCP
خادم MCP
الاستخدام المعتاد
يستخدم Ollama الأدوات
نص الجسر البرمجي الخاص بك، الذي يغلّف نموذج Ollama
خادم نظام الملفات أو قاعدة البيانات أو البحث
مساعد محلي يقرأ ملاحظاتك
Ollama كأداة
Claude Desktop وClaude Code وCursor
نص الجسر البرمجي الخاص بك، الذي يغلّف Ollama
نقل المهام الخاصة أو الرخيصة إلى نموذج محلي
يمنح الاتجاه الأول النموذج المحلي أيادي تعمل. ويمنح الثاني المساعد السحابي زميلًا محليًا. يبني معظم الناس الاتجاهين في النهاية، لأن الثاني يحتاج إلى نحو 30 سطرًا فقط.
ملاحظة سريعة حول النقل. تستخدم الأمثلة هنا stdio، حيث يشغّل العميل الخادم كعملية فرعية ويتواصل معه عبر الإدخال والإخراج القياسيين. وهذا أبسط خيار لجهاز شخصي. إذا أردت جسرًا واحدًا تشترك فيه عدة تطبيقات أو عدة حواسيب على شبكتك، فشغّله عبر نقل Streamable HTTP بدلًا من ذلك، وأبقه خلف جدار الحماية الخاص بك. تبقى شيفرة الأدوات كما هي، ولا يتغير إلا السطر الأخير في الخادم.
كيف ينتقل استدعاء الأداة
أيًّا كان الاتجاه الذي تختاره، يتبع استدعاء الأداة الحلقة نفسها:
يتصل الجسر بخادم MCP ويطلب قائمة أدواته باستخدام tools/list.
يعيد كتابة مخطط كل أداة بالصيغة التي يتوقعها Ollama.
يرسل سؤال المستخدم وتعريفات الأدوات تلك إلى نموذج محلي.
يجيب النموذج بإدخال tool_calls بدلًا من النص.
يشغّل الجسر هذا الاستدعاء على خادم MCP باستخدام tools/call.
تعود النتيجة إلى النموذج كرسالة tool.
تتكرر الخطوات من 3 إلى 6 حتى يرد النموذج بنص عادي.
💡 لا يلمس النموذج قرصك أبدًا. هو يطلب فقط تنفيذ إجراء. جسرك هو من يقرر ما إذا كان سينفّذه، ولهذا فهو المكان المناسب لقوائم السماح، ومطالبات التأكيد، والتسجيل.
ما الذي تحتاجه أولًا؟
عتاد يعمل
يجب أن تتسع أوزان النموذج في ذاكرة GPU (أو الذاكرة الموحدة على أجهزة Mac) مع ترك مساحة للسياق. هذه الأرقام تقريبية، وتخص الإصدارات المكمّاة بـ4 بت:
حجم النموذج
الذاكرة اللازمة للأوزان
الإعداد المريح
3B إلى 4B
من 2 إلى 3 GB
أي حاسوب محمول حديث
7B إلى 8B
من 5 إلى 6 GB
GPU بذاكرة 8 GB أو ذاكرة موحدة بسعة 16 GB
14B
من 9 إلى 10 GB
GPU بذاكرة 12 GB
20B
من 13 إلى 15 GB
GPU بذاكرة 16 GB أو ذاكرة موحدة بسعة 24 GB
32B
من 19 إلى 21 GB
GPU بذاكرة 24 GB
تعمل النماذج التي تفيض إلى ذاكرة النظام الرئيسية، لكن سرعة توكناتها تنخفض بشدة. ويجري الجسر عدة استدعاءات للنموذج في كل سؤال، لذلك تهم السرعة أكثر من الحجم. غالبًا ما يتفوق نموذج 8B يتسع بالكامل في GPU على نموذج 32B لا يتسع فيها.
نماذج تدعم استدعاء الأدوات
ليس كل نموذج قادرًا على طلب أداة. يتحقق Ollama من قالب المحادثة الخاص بالنموذج، والنموذج الذي لا يدعم الأدوات يعيد خطأ عند تمرير tools. صفِّ مكتبة Ollama بوسم tools، أو ابدأ من هذه القائمة المختصرة:
وسم Ollama
الحجم على القرص
سبب الاستخدام
llama3.1:8b
نحو 4.9 غيغابايت
خيار افتراضي موثوق للاختبارات الأولى
qwen3:8b
نحو 5.2 غيغابايت
قوي في استخدام الأدوات متعدد الخطوات، لكنه أبطأ عند تفعيل التفكير
mistral-nemo
نحو 7.1 غيغابايت
سياق طويل، ويتعامل مع أدوات كثيرة
gpt-oss:20b
نحو 14 غيغابايت
نموذج GPT OSS 20B مفتوح الأوزان، وقد بُني مع وضع استخدام الأدوات في الحسبان
ثبّت المكونات
فعّل بيئة افتراضية أولًا (source .venv/bin/activate على macOS وLinux، و.venv\Scripts\activate على Windows)، ثم شغّل:
# 1. Pull a tool-capable model and confirm Ollama is serving
ollama pull llama3.1:8b
curl http://localhost:11434/api/tags
# 2. Install the two Python packages the bridge needs
pip install ollama mcp
# 3. Check Node, because the example MCP server runs through npx
node --version
إذا أعاد curl قائمة JSON بنماذجك، فإن Ollama جاهز. وإذا رُفض الاتصال، فشغّله باستخدام ollama serve.
ابنِ عميل الجسر بلغة Python
العميل ملف واحد. يشغّل خادم MCP كعملية فرعية عبر stdio transport، ويقرأ أدواته، ويشغّل الحلقة الواردة في القسم السابق. والخادم المثال هو خادم الملفات الرسمي، موجَّه إلى مجلد ملاحظات.
تحويل أدوات MCP إلى صيغة Ollama
تحمل أداة MCP name، وdescription، وinputSchema مكتوبًا بصيغة JSON Schema. وتتطلب صيغة استدعاء الدوال في Ollama العناصر الثلاثة نفسها، ملفوفة داخل كائن function. والتحويل في معظمه إعادة تسمية:
تمر معظم المخططات دون تغيير. وإذا استخدم خادم تراكيب غريبة مثل anyOf أو $ref، فسطِّحها قبل الإرسال. النماذج الصغيرة تتعامل مع المخططات المسطحة بشكل أفضل بكثير.
اكتب حلقة استدعاء الأدوات
import asyncio
import ollama
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
MODEL = "llama3.1:8b"
NOTES_DIR = "/home/me/notes"
MAX_TURNS = 8
server_params = StdioServerParameters(
command="npx",
args=["-y", "@modelcontextprotocol/server-filesystem", NOTES_DIR],
)
def to_ollama_tool(tool):
return {
"type": "function",
"function": {
"name": tool.name,
"description": tool.description or "",
"parameters": tool.inputSchema,
},
}
async def ask(question: str) -> str:
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()
listed = await session.list_tools()
tools = [to_ollama_tool(t) for t in listed.tools]
client = ollama.AsyncClient()
messages = [{"role": "user", "content": question}]
for _ in range(MAX_TURNS):
response = await client.chat(model=MODEL, messages=messages, tools=tools)
message = response.message
messages.append(message)
if not message.tool_calls:
return message.content
for call in message.tool_calls:
result = await session.call_tool(
call.function.name, dict(call.function.arguments)
)
text = "\n".join(
block.text for block in result.content if block.type == "text"
)
messages.append(
{"role": "tool", "tool_name": call.function.name, "content": text}
)
return "Stopped: the model kept calling tools."
if __name__ == "__main__":
print(asyncio.run(ask("Which markdown files in my notes folder mention invoices?")))
أربعة تفاصيل تستحق الانتباه:
MAX_TURNS حاجز أمان. فالنموذج المرتبك قد يستدعي الأداة نفسها بلا نهاية، والعدّاد يحوّل ذلك إلى فشل واضح.
dict(call.function.arguments) مهم لأن Ollama يعيد الوسائط ككائن تعيين تتوقعه جلسة MCP كقاموس عادي.
كتل النص فقط. قد تتضمن نتائج MCP صورًا وموارد مضمّنة. هذه النسخة تحتفظ بالنص وتتجاهل الباقي.
tool_name في رسالة الأداة يخبر النموذج بالمكالمة التي تنتمي إليها النتيجة، مما يمنع اختلاط المكالمات المتوازية.
شغّله على ملفات حقيقية
احفظ الملف باسم bridge_client.py، وغيّر NOTES_DIR إلى مجلد حقيقي، ثم شغّل python bridge_client.py. يُجري التشغيل السليم أولًا استدعاء لعرض قائمة المجلد أو البحث، ثم قراءة ملف أو اثنين، ثم يجيب بنص عادي. ولمراقبة اختيار النموذج للأدوات، أضف print(call.function.name, call.function.arguments) في أعلى الحلقة الداخلية.
💡 نصيحة لنظام Windows: إذا لم تستطع Python تشغيل npx، فاستخدم npx.cmd كأمر تشغيل. ويتيح العلم -y لـ npx تثبيت خادم الملفات عند أول تشغيل دون أن يسألك.
قبل أن توجّه الجسر إلى أي شيء حساس، قرر ما الذي يُسمح للنموذج بفعله. لا يصل خادم الملفات إلا إلى المجلدات التي تمررها في سطر أوامره، لذا أعطه مجلد ملاحظات لا مجلدك الرئيسي. وبالنسبة للأدوات التي تكتب أو تحذف أو ترسل بيانات، أضف خطوة تأكيد داخل الحلقة: اطبع المكالمة واطلب الموافقة قبل أن يُنفَّذ session.call_tool. ثلاثون ثانية من الإزعاج أفضل من نموذج 8B يقرر أن التنظيف فكرة جيدة.
اعرض Ollama كخادم MCP
والآن اعكس الاتجاه. بدلًا من أن يستخدم النموذج المحلي أدوات الآخرين، تنشر النموذج المحلي كأداة. ويمكن لأي عميل MCP عندئذٍ استدعاؤه لصياغة النصوص أو تلخيصها أو تصنيفها، وهي نصوص لا ينبغي أن تغادر جهازك أبدًا.
خادم صغير بلغة Python
تتضمن حزمة Python الرسمية FastMCP، التي تبني مخطط الأداة من تلميحات الأنواع في شيفرتك، والوصف من docstring الخاصة بالدالة:
import sys
import ollama
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("ollama-bridge")
client = ollama.AsyncClient()
DEFAULT_MODEL = "llama3.1:8b"
@mcp.tool()
async def list_local_models() -> list[str]:
"""List the models installed in the local Ollama instance."""
listed = await client.list()
return [m.model for m in listed.models]
@mcp.tool()
async def ask_local_model(
prompt: str, model: str = DEFAULT_MODEL, temperature: float = 0.2
) -> str:
"""Send a prompt to a local Ollama model and return its reply.
Use it for private text or cheap drafts that should stay on this machine."""
print(f"ask_local_model: {model}", file=sys.stderr)
response = await client.chat(
model=model,
messages=[{"role": "user", "content": prompt}],
options={"temperature": temperature},
)
return response.message.content
if __name__ == "__main__":
mcp.run(transport="stdio")
اكتب docstring موجّهة إلى المستدعي، لا إليك أنت. فالنموذج العميل يقرأها ليقرر متى تستحق أداتك الاستدعاء، لذلك فإن عبارة "استخدمها للنصوص الخاصة" تؤدي دورًا حقيقيًا.
اربطه بتطبيق Claude Desktop
افتح claude_desktop_config.json. على Windows يقع في %APPDATA%\Claude، وعلى macOS في ~/Library/Application Support/Claude. أضف الخادم تحت mcpServers:
وجّه command إلى Python الخاص بالبيئة الافتراضية، لا إلى Python الخاص بالنظام. ذلك أن Claude Desktop لا يفعّل بيئتك، ومفسّر النظام من دون حزمة mcp يفشل بصمت. أغلق التطبيق وأعد فتحه، وستظهر الأداتان في قائمة الأدوات.
اربطه بـ Claude Code
يسجّل Claude Code الخوادم من الطرفية:
claude mcp add ollama-bridge -- /path/to/.venv/bin/python /path/to/ollama_bridge.py
claude mcp list
كل ما يأتي بعد الشرطتين المزدوجتين هو أمر التشغيل. وبمجرد أن يعرض claude mcp list الخادم كمتصل، اطلب من Claude Code أن "يلخّص هذا السجل باستخدام النموذج المحلي"، وراقب استدعاءه لـ ask_local_model.
أصلح المشكلات التي ستواجهها
ثلاث مشكلات تفسر معظم المحاولات الأولى الفاشلة. ولكل منها حل قصير.
مخرج stdout يكسر خوادم stdio
يرسل خادم MCP من نوع stdio رسائل JSON-RPC عبر stdout. وأي print() عابر يحقن نصًا في هذا التدفق، فيُسقط العميل الاتصال أو يُبلغ عن خطأ في التحليل. والعَرَض هو خادم يتصل ثم ينقطع خلال ثانية.
الحل عادة بسيطة: سجّل الرسائل إلى stderr (print(..., file=sys.stderr)) أو إلى ملف، ولا تكتب أي شيء آخر إلى stdout. ويشمل ذلك أشرطة التقدم والتحذيرات التي تطبعها المكتبات المستوردة.
النماذج الصغيرة تتجاهل الأدوات
نموذج 8B يُعطى 25 أداة كثيرًا ما يجيب من الذاكرة أو يستدعي الأداة الخطأ. أربعة تغييرات تساعد، مرتبة تقريبًا حسب الأثر:
أرسل أدوات أقل. صفِّ القائمة إلى الثلاث أو الست التي تناسب السؤال.
أعد كتابة الأوصاف. "اقرأ محتوى ملف واحد بمساره المطلق" أفضل من "قارئ الملفات".
خفّض درجة الحرارة إلى 0.1 أو 0.2 لاختيار الأدوات.
انتقل إلى حجم أكبر. الانتقال من 3B إلى 8B يصلح إخفاقات استدعاء الأدوات أكثر من أي حيلة في الأوامر النصية.
نوافذ السياق تمتلئ بسرعة
تستهلك تعريفات الأدوات ونتائجها السياق معًا، وقراءة ملف كبير واحدة قد تدفع السؤال خارج النافذة. وسياق Ollama الافتراضي صغير، لذا ارفعه صراحةً وقلّص النتائج قبل أن تصل إلى النموذج:
response = await client.chat(
model=MODEL,
messages=messages,
tools=tools,
options={"num_ctx": 8192},
)
text = text[:4000] # trim large tool results before appending them
تستهلك قيم num_ctx الأعلى ذاكرة أكبر لذاكرة الانتباه المؤقتة، لذا ارفعها تدريجيًا. واضبط أيضًا OLLAMA_KEEP_ALIVE على قيمة أطول مثل 30m. ذلك أن Ollama يفرّغ النماذج الخاملة بعد خمس دقائق افتراضيًا، وكل إعادة تحميل تضيف ثوانٍ إلى الرد الأول.
نماذج محلية أم نماذج مستضافة
لا يفرض عليك الجسر خيارًا. إنه يتيح لك توجيه كل مهمة إلى أرخص مكان يستطيع إنجازها بجودة جيدة.
تفوز النماذج المحلية عندما:
النص خاص، مثل العقود أو الملاحظات الصحية أو الشيفرة المصدرية الخاضعة لاتفاقية عدم إفشاء
تتكرر المهمة آلاف المرات، فتتراكم تكلفة الدفع لكل توكن
تعمل دون إنترنت أو على شبكة لا تتحكم فيها
تفوز النماذج المستضافة عندما:
تملك GPU لديك ذاكرة أقل من 8 GB
تتطلب المهمة نموذجًا يتجاوز 30 مليار معامل
تحتاج إلى إجابة خلال ثوانٍ عند البدء البارد
عمليًا، يعمل الهجين بأفضل شكل. دع النموذج المحلي يتولى المسودات الأولى والتصنيف وأي شيء يمس الملفات الخاصة، ثم صعّد المهام الصعبة التي تمثل نحو 10 في المئة إلى نموذج مستضاف أكبر. ولأن الاثنين يقعان خلف واجهة MCP نفسها، يمكن لمساعدك أن يختار بين ask_local_model وبديل مستضاف بمجرد وصف أوضح للأداة.
النماذج المستضافة على PicassoIA مقاييس مفيدة. شغّل الأمر النصي نفسه على نموذج 8B محلي وعلى أحد هذه النماذج، وسترى بالضبط ما يضيفه الحجم الإضافي:
اكتب أمرك النصي في حقل Prompt. ومن الاختبارات الجيدة استخدام docstring التي تنوي إعطاءها لـ ask_local_model، مع السؤال "هل ستعرف متى تستدعي هذه الأداة؟"
اترك Temperature على قيمته الافتراضية 0.1 للحصول على مخرجات دقيقة وقابلة للتكرار. وارفعها للعصف الذهني.
أبقِ Max Tokens على 2048 للإجابات الطويلة، أو خفّضها للردود القصيرة.
عدّل Top P وPresence Penalty وFrequency Penalty فقط إذا كانت المخرجات تكرر نفسها أو بدت متكررة.
شغّل، ثم عدّل، ثم شغّل مجددًا. تسرد صفحة النموذج توليدات غير محدودة، لذا فالتكرار لا يكلّفك شيئًا.
💡 قارن الإجابة المستضافة بتشغيلك المحلي. إن تطابقتا تقريبًا، فإعدادك المحلي يؤدي دوره وتستطيع التوقف عن دفع تكلفة الاستدعاء المستضاف.
ادمج الجسر مع توليد الصور
بمجرد أن يصبح ask_local_model موجودًا، يمكنه أن يفعل أكثر من تلخيص السجلات. النموذج المحلي وسيلة رخيصة وخاصة لصياغة أوامر الصور، وهنا يلتقي الجسر بالعمل البصري.
أضف أداة ثالثة تأخذ موضوعًا وتعيد أمرًا تصويريًا من 60 كلمة: الشخص، والمكان، واتجاه الضوء، والعدسة، ومظهر الفيلم. يستدعيها مساعدك، وتلصق النتيجة في نموذج تحويل النص إلى صورة. P-Image خيار سريع للمسودات. وFLUX 2 Pro مناسب لمرور ثانٍ عندما يحتاج الأمر إلى تفاصيل أكثر.
يعمل روتين بسيط بشكل جيد:
اطلب من النموذج المحلي ثلاث صيغ مختلفة للأمر الواحد عن موضوع واحد.
يعمل النمط نفسه مع الصور المصغرة ولقطات المنتجات وصور رؤوس المدونات. يُبقي الجسر خطوة الصياغة مجانية وخاصة، وتتولى النماذج المستضافة التصيير الثقيل.
أنشئ صورك الخاصة على PicassoIA
أصبح لديك الآن جسر يعمل في الاتجاهين: نموذج محلي يستطيع استخدام الأدوات، ونموذج محلي تستطيع التطبيقات الأخرى استدعاءه. الخطوة التالية هي وضعه للعمل على شيء تراه بعينك.
خذ فكرة صياغة الأوامر وجرّبها اليوم. اطلب من نموذجك المحلي أمرًا نصيًا تصويريًا، وافتح Picasso IA، وولّد أول صورة لك باستخدام P-Image أو FLUX 2 Pro. غيّر العدسة أو اتجاه الضوء أو المكان، وأعد التشغيل. وعندما تنجح لقطة، حوّلها إلى فيديو قصير. تصفّح كل النماذج المتاحة في كتالوج PicassoIA الكامل وابدأ التجربة على Picasso IA.