3 min read

بناء خادم MCP لواجهة API وربطه مع Ollama وKimi

ابنِ محول MCP آمناً لواجهة API قائمة واحسب تكلفته، ثم اربط عقود الأدوات المختبرة بـCodex أو Ollama أو Kimi مفتوح الأوزان.

استمع إلى المقال

جارٍ تجهيز الصوت…

هندسة الذكاء الاصطناعي

تصبح واجهة API مفيدة لنظام ذكاء اصطناعي عندما يستطيع النموذج اكتشاف قدرة محددة، وتمرير معاملات صالحة، واستلام نتيجة منظمة يمكنه الاستدلال عليها. هذا لا يعني إعطاء النموذج ملف OpenAPI كاملاً ورمز وصول إداري. أفضل إنشاء محول MCP ضيق يحافظ على ضوابط التفويض وقواعد المجال الموجودة أصلاً في الواجهة.

يبني هذا الدليل ذلك المحول باستخدام حزمة TypeScript الرسمية لـMCP، ثم يربطه بـCodex أو أي مضيف MCP آخر، ويوضح حلقة الأدوات المطلوبة عندما يكون Ollama أو نموذج Kimi مفتوح الأوزان هو طبقة النموذج. واجهة المثال افتراضية، لكن حد الثقة عملي: النموذج يقترح، والتطبيق يتحقق ويقرر.

تسلسل من مضيف النموذج عبر خادم MCP وإضافة أداة إلى واجهة REST قائمة، مع التحقق من المخطط والسياسة وتنقية النتائج وتسجيل دليل التدقيق
الشكل 33. يوحد MCP اكتشاف الأدوات واستدعاءها، بينما تبقى بيانات الاعتماد والتفويض وآثار المجال وتقليل المخرجات والدليل مسؤوليات التطبيق.

ابدأ بحد الثقة لا بالحزمة البرمجية

يقدم خادم MCP ثلاث قدرات: الموارد والأدوات والقوالب الجاهزة للمحادثة. المورد سياق قابل للقراءة، والأداة تنفذ استعلاماً أو إجراءً، والقالب يحدد تفاعلاً قابلاً لإعادة الاستخدام. عند تغليف API قائمة أبدأ غالباً بالأدوات لأنها تمنح النموذج عملية مسماة ومخطط إدخال واضحاً.

السؤال الأول ليس: «كيف أحول كل endpoint؟» بل: «ما أسئلة العمل التي يجب أن يُسمح للنموذج بطرحها؟». قد تحتوي واجهة داخلية على 180 عملية، بينما تحتاج النسخة الأولى إلى ثلاث أدوات فقط:

  • orders.get_status لقراءة الحالة المرجعية لطلب واحد؛
  • orders.search للبحث داخل نطاق المستأجر وفترة زمنية ثابتة؛
  • orders.prepare_cancellation للتحقق من مقترح إلغاء من دون تنفيذه.

لا أعرض روابط حرة أو طرق HTTP عشوائية أو SQL أو رموز الوصول أو أداة عامة باسم call_api. العقد الضيق يقلل سطح التفويض ويحسن وصف القدرة للنموذج وينتج أحداث تدقيق ذات معنى.

أنشئ خادم MCP

تستخدم حزمة TypeScript الرسمية الحالية حزمتين منفصلتين للخادم والعميل. يحتاج خادم stdio محلي إلى Node.js 20 أو أحدث:

mkdir api-mcp && cd api-mcp
npm init -y
npm pkg set type=module
npm install @modelcontextprotocol/server zod tsx
mkdir -p src/plugins

أنشئ src/index.ts. يأتي رابط API ورمز الوصول من بيئة العملية، ولا يكونان معاملين يستطيع النموذج اختيارهما:

import { McpServer } from '@modelcontextprotocol/server';
import { serveStdio } from '@modelcontextprotocol/server/stdio';
import * as z from 'zod/v4';

const API_BASE = new URL(process.env.API_BASE ?? 'https://api.example.com');
const API_TOKEN = process.env.API_TOKEN;
if (!API_TOKEN) throw new Error('API_TOKEN is required');

const Order = z.object({
  id: z.string(),
  status: z.enum(['pending', 'confirmed', 'cancelled']),
  updatedAt: z.string()
});

function createServer(): McpServer {
  const server = new McpServer({ name: 'orders-api', version: '1.0.0' });

  server.registerTool(
    'orders.get_status',
    {
      title: 'Get order status',
      description: 'Read the authoritative status of one order visible to the caller.',
      inputSchema: z.object({
        orderId: z.string().regex(/^ord_[a-zA-Z0-9]+$/)
      }),
      outputSchema: Order,
      annotations: { readOnlyHint: true, idempotentHint: true }
    },
    async ({ orderId }) => {
      const controller = new AbortController();
      const timeout = setTimeout(() => controller.abort(), 5000);
      try {
        const url = new URL(`/v1/orders/${encodeURIComponent(orderId)}`, API_BASE);
        const response = await fetch(url, {
          headers: { Authorization: `Bearer ${API_TOKEN}` },
          signal: controller.signal
        });
        if (response.status === 404) {
          return { content: [{ type: 'text', text: 'Order not found.' }], isError: true };
        }
        if (!response.ok) {
          return {
            content: [{ type: 'text', text: `Upstream API failed with HTTP ${response.status}.` }],
            isError: true
          };
        }
        const order = Order.parse(await response.json());
        return {
          content: [{ type: 'text', text: JSON.stringify(order) }],
          structuredContent: order
        };
      } finally {
        clearTimeout(timeout);
      }
    }
  );
  return server;
}

void serveStdio(createServer);
console.error('orders-api MCP server running on stdio');

ينتج مخطط Zod الواحد مخطط JSON الذي يراه العميل ويتحقق من المعاملات قبل تشغيل المعالج. كما يوفر مخطط الإخراج عقداً آلياً. ومع ذلك أتحقق من رد API أيضاً؛ فالبيانات المشوهة يجب أن تفشل عند حد المحول بدلاً من أن تتحول إلى سياق يثق به النموذج.

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

نظّم الأدوات كإضافات صريحة

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

// src/plugins/types.ts
import type { McpServer } from '@modelcontextprotocol/server';

export type ToolPlugin = {
  name: string;
  register(server: McpServer): void;
};
// src/plugins/index.ts
import { orderStatusPlugin } from './order-status.js';
import { customerSummaryPlugin } from './customer-summary.js';

export const plugins = [orderStatusPlugin, customerSummaryPlugin];
const server = new McpServer({ name: 'operations-api', version: '1.0.0' });
for (const plugin of plugins) plugin.register(server);

بهذا يملك كل مكون مالكاً واختبارات ومخططات وقائمة endpoints مسموحة وسياسة تفويض وإصداراً. أتجنب مسح مجلد غير موثوق واستيراد كل ملف يظهر داخله.

اختبر قبل ربط النموذج

تشغل أداة MCP Inspector الرسمية عبر npx وتسمح بعرض الأدوات والمخططات واستدعاء المعالجات مباشرة:

API_BASE=https://sandbox.example.com \
API_TOKEN=replace-locally \
npx @modelcontextprotocol/inspector npx tsx src/index.ts

اختبر الاستدعاءات الصحيحة والمعرفات المشوهة والسجلات غير المصرح بها والمهل وردود JSON غير المتوقعة والتزامن. تحقق من أن السجل يحتوي معرف تتبع وقراراً، لا رمز وصول خاماً أو بيانات شخصية زائدة.

في stdio تكون stdout قناة JSON-RPC. قد تفسد عبارة console.log واحدة البروتوكول، لذلك يذهب التسجيل التشغيلي إلى stderr أو وجهة مستقلة.

سجله في Codex أو مضيف آخر

يستطيع Codex تسجيل أمر التشغيل المحلي وتمرير متغيرات البيئة إلى العملية التابعة:

codex mcp add orders-api \
  --env API_BASE=https://sandbox.example.com \
  --env API_TOKEN=replace-locally \
  -- npx tsx /absolute/path/api-mcp/src/index.ts

لا تحفظ الرمز الحقيقي في المستودع أو المقالة أو سجل الصدفة أو prompt. في الإنتاج استخدم هوية عمل قصيرة العمر أو مدير أسرار واربط التفويض بالمستخدم المصادق بدلاً من رمز مشترك واسع الصلاحية.

ويستخدم VS Code الأمر نفسه في .vscode/mcp.json:

{
  "servers": {
    "orders-api": {
      "type": "stdio",
      "command": "npx",
      "args": ["tsx", "src/index.ts"]
    }
  }
}

ينفذ المضيف tools/list ويقدم الأسماء والأوصاف والمخططات للنموذج، ثم يرسل tools/call المختار إلى خادم MCP. لا يستدعي النموذج REST API مباشرة.

موقع Ollama في المعمارية

يوفر Ollama واجهة محادثة محلية على http://localhost:11434/api/chat ويدعم تعريف الأدوات واستجابات استدعائها. Ollama هو مشغل النموذج وليس خادم MCP. يجب على المضيف أو جسر صغير تحويل أدوات MCP إلى مخطط الدوال المرسل إلى Ollama، وتنفيذ الاستدعاء عبر عميل MCP، وإضافة النتيجة إلى المحادثة، ثم طلب المتابعة من النموذج.

import { Client } from '@modelcontextprotocol/client';
import { StdioClientTransport } from '@modelcontextprotocol/client/stdio';

const mcp = new Client({ name: 'ollama-host', version: '1.0.0' });
await mcp.connect(new StdioClientTransport({
  command: 'npx', args: ['tsx', 'src/index.ts']
}));

const { tools } = await mcp.listTools();
const ollamaTools = tools.map(tool => ({
  type: 'function',
  function: {
    name: tool.name,
    description: tool.description,
    parameters: tool.inputSchema
  }
}));

const response = await fetch('http://localhost:11434/api/chat', {
  method: 'POST',
  headers: { 'content-type': 'application/json' },
  body: JSON.stringify({
    model: process.env.OLLAMA_MODEL ?? 'qwen3:8b',
    messages: [{ role: 'user', content: 'What is the status of ord_1042?' }],
    tools: ollamaTools,
    stream: false
  })
});

const turn = await response.json();
for (const call of turn.message.tool_calls ?? []) {
  const result = await mcp.callTool({
    name: call.function.name,
    arguments: call.function.arguments
  });
  // أضف دور المساعد ونتيجة الأداة ثم استدع Ollama مجدداً.
}

يضيف المضيف الإنتاجي حلقة الرسائل الكاملة والإلغاء وحداً أقصى لعمق الاستدعاء وموافقة بحسب الأداة وحدوداً لحجم النتائج وقياسات تشغيلية وقائمة سماح ثابتة. لا تمرر اسم الأداة إلى eval أو shell أو import ديناميكي.

موقع Kimi مفتوح الأوزان

تنشر Moonshot AI كود Kimi وأوزانه وفق ترخيص Modified MIT. صُمم Kimi K2 لاستخدام الأدوات، لكن معماريته المنشورة تحتوي تريليون معامل إجمالي و32 مليار معامل نشط. الأوزان المفتوحة لا تعني أن النموذج مناسب لحاسوب محمول؛ يحتاج تشغيل النموذج الكامل إلى بنية استدلال كبيرة، وتوثق Moonshot محركات مثل vLLM وSGLang.

إذا عرض Ollama نموذج Kimi يدعم الأدوات، يتغير فقط OLLAMA_MODEL في الجسر السابق. وإذا خُدّم Kimi عبر endpoint متوافق مع OpenAI، يمكن وضع عميل MCP نفسه خلف حلقة مضيف متوافقة. لا يتغير خادم MCP لأن اختيار النموذج يقع فوق حد الأدوات.

لبيئة تطوير محلية فعلية ابدأ بنموذج Ollama أصغر وموسوم بدعم الأدوات. استخدم Kimi عندما يناسب حجم التشغيل والبيئة. لا تصف نموذجاً يمر عبر السحابة بأنه محلي لمجرد أن الأمر يبدأ بكلمة ollama.

ما التكلفة الفعلية لهذه المعمارية؟

لا يضيف MCP بحد ذاته رسم ترخيص. الحزمة الرسمية مفتوحة المصدر، والمحول في هذا الدليل عملية صغيرة. تتركز التكلفة حوله: الحوسبة البعيدة، واستدلال النموذج، والسجلات، والأسرار، والهوية، والاختبارات، ووقت الهندسة اللازم لإبقاء عقود الأدوات متوافقة مع API.

تم التحقق من الأسعار التالية في 21 يوليو 2026. هي نقاط مرجعية وليست عروض أسعار، ولا تشمل الضريبة أو التخزين أو المراقبة أو الهوية المدارة أو الشبكة أو الدعم أو وقت الفريق.

خيار النشر سعر البداية المنشور ما الذي يشمله ما الذي لا يشمله
MCP محلي عبر stdio مع Ollama محلي تكلفة برمجية إضافية 0 دولار عملية MCP وخطة Ollama المجانية على جهاز موجود شراء العتاد والكهرباء والنسخ الاحتياطية ووقت المطور وسعة RAM/GPU الكافية
استخدام Ollama بمساعدة السحابة المجاني 0؛ Pro بسعر 20 دولاراً شهرياً؛ Max بسعر 100 دولار شهرياً تختلف حصة الاستخدام والتزامن بحسب الخطة استضافة MCP ومنصة API والسجلات ودعم الإنتاج
آلة افتراضية صغيرة لخادم MCP بعيد تبدأ Droplets من DigitalOcean عند 4 دولارات شهرياً آلة عامة أساسية تمثل الحد الأدنى للتكلفة التكرار وقاعدة البيانات وموازن الحمل والنسخ الاحتياطية والمراقبة واستدلال النموذج
محول بعيد دون خادم دائم Cloudflare Workers مجاني، أو 5 دولارات شهرياً كحد أدنى للخطة المدفوعة تنفيذ Worker والاستخدام المشمول في الخطة رموز النموذج ورسوم API الخارجية والخدمات الدائمة والضوابط الهندسية
Kimi مفتوح الأوزان مستضاف ذاتياً قد يكون ترخيص النموذج 0؛ البنية ليست مجانية التحكم في خدمة النموذج ومسار البيانات GPU والسعة الاحتياطية والنسخ المتعددة وتحميل النموذج والطاقة والتشغيل والاستجابة للحوادث

إذن القرار ليس «مجاني أم مدفوع»، بل أين تستقر التكلفة والمسؤولية التشغيلية. قد لا ينتج نموذج Ollama محلي فاتورة جديدة لكنه يستهلك محطة عمل. وقد تشغل آلة بقيمة 4 دولارات محولاً خفيفاً، لكنها لا تشغل نموذجاً كبيراً مفتوح الأوزان. كما يحتاج endpoint بعيد لـMCP إلى TLS وهوية عمل وتدوير أسرار وحدود معدل وقياسات تشغيلية وتحديثات وتصميم توافر.

نموذج تكلفة يمكن الدفاع عنه

أفصل في تقدير الإنتاج بين تكلفة المنصة الثابتة وتكلفة النموذج المرتبطة بالاستخدام:

التكلفة الشهرية = حوسبة المحول
                 + الهوية والأسرار والسجلات والتخزين
                 + (رموز الإدخال / 1,000,000 × سعر الإدخال)
                 + (رموز الإخراج / 1,000,000 × سعر الإخراج)
                 + الملكية التشغيلية

لنفترض حملاً توضيحياً قدره 50,000 تفاعل مدعوم بالأدوات شهرياً، بمتوسط 2,000 رمز إدخال و500 رمز إخراج لكل تفاعل. الناتج 100 مليون رمز إدخال و25 مليون رمز إخراج. وعند سعر افتراضي قدره 0.60 دولار لكل مليون رمز إدخال و2.50 دولار لكل مليون رمز إخراج تكون تكلفة الاستدلال:

عنصر التكلفة العملية الحسابية التكلفة الشهرية التوضيحية
رموز الإدخال 100 × 0.60 دولار 60.00 دولاراً
رموز الإخراج 25 × 2.50 دولار 62.50 دولاراً
مجموع النموذج 60.00 + 62.50 122.50 دولاراً
المحول والضوابط أضف الاستضافة والقياسات والأسرار والدعم متغير

الأسعار هنا توضيحية عمداً كي تبقى الطريقة صالحة عندما يغير المزودون أسعارهم. استبدلها بالسعر الحالي للنموذج والمنطقة المحددين، ثم قس prompts الحقيقية بدلاً من الاعتماد على متوسط العرض التجريبي. أوصاف الأدوات والمخططات وسجل المحادثة وإعادة المحاولة وحلقات الوكيل كلها تستهلك رموزاً. ويجب حساب خصومات التخزين المؤقت وأسعار الدفعات بصورة منفصلة لا افتراضها.

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

قِس القيمة والفشل معاً

تحتاج التجربة المنضبطة إلى خط أساس ومجموعة مقارنة. أقارن التدفق المدعوم بـMCP مع API أو التدفق اليدوي الحالي على مجموعة المهام نفسها وأسجل:

المقياس سبب أهميته
المهام الناجحة / المهام المحاولة يمنع نموذجاً رخيصاً وغير موثوق من الظهور كخيار كفء
التكلفة / المهمة الناجحة يربط تكلفة النموذج والمحول والإعادة بنتيجة فعلية
زمن الإكمال p50 وp95 يكشف إن كان الذيل يجعل التدفق غير عملي
استدعاءات الأدوات والإعادات / المهمة يكشف الحلقات وضعف الوصف وعدم توافق المخطط
المحاولات غير المصرح بها أو الواسعة يختبر حد القدرة لا جودة الإجابة فقط
التصحيحات البشرية / المهمة يقيس العبء التشغيلي الذي يخفيه العرض المصقول
اكتمال التتبع يثبت إمكانية إعادة بناء النتيجة ومراجعتها

لا أعتمد إطلاق الإنتاج على درجات جودة الإجابة وحدها. يجب أن تتضمن حزمة الدليل مجموعة المهام وإصدارات النموذج وprompt ومخططات الأدوات وفئات النتائج الخام وافتراضات التكلفة والتكاليف المستبعدة وأمثلة الفشل وتاريخ استرجاع أسعار المزودين.

ضوابط إنتاج لا أتجاوزها

قبل ربط واجهة حقيقية أطلب:

  1. قائمة قدرات مسموحة. لا أداة لرابط حر أو طريقة HTTP عامة أو SQL أو shell.
  2. طبقتي تحقق. مخطط MCP في المحول وقواعد المجال في API.
  3. تفويض مرتبط بالمتصل. المستأجر والدور والكيان والسجل والغرض واضحة.
  4. فصل القراءة عن الكتابة. لا تتحول أداة قراءة إلى كتابة عبر معامل خفي.
  5. إعداد قبل الأثر المادي. ينتج التغيير الحساس مقترحاً قابلاً للمراجعة قبل التنفيذ.
  6. منع التكرار وفحص الحالة. لا تنشئ الإعادة أثراً مكرراً ويفشل المقترح القديم بأمان.
  7. تقليل المخرجات. لا يرجع إلا ما يحتاجه النموذج مع حجب الأسرار والبيانات الزائدة.
  8. تنفيذ محدود. مهل وحدود تزامن وحجم استجابة وعمق استدعاء.
  9. دليل. تسجيل الشخص والأداة وإصدار المخطط والقرار ومعرف التتبع وفئة النتيجة والوقت.
  10. عقود ذات إصدارات. التغيير غير المتوافق ينشئ أداة أو إصدار عقد جديداً.

تظل الأنماط في وكلاء الذكاء الاصطناعي في التقنية المالية المنظمة وحوكمة الذكاء الاصطناعي المسؤول كنظام هندسي وواجهات الدفع المرنة صالحة حتى إن لم يكن المثال مالياً. يمنح MCP النموذج واجهة نظيفة، لكنه لا يلغي الانضباط الهندسي.

اختبار التصميم

أعد المحول جاهزاً عندما أستطيع استبدال Ollama بـKimi، أو استبدال كليهما بمضيف آخر، من دون تغيير التفويض وربط endpoints وقواعد المجال ودليل التدقيق. هذه قيمة MCP العملية: تتطور طبقة النموذج بينما يبقى حد القدرة مقصوداً وقابلاً للاختبار.

المراجع

نقاش هندسي

ما القرار الذي كنت ستتخذه؟

شارك سؤالاً أو تجربة أو رأياً مخالفاً. التعليقات متاحة للأعضاء المسجلين للحفاظ على نقاش مهني ومفيد.