MCP Registry: كيف تُدرج خادمك عبر GitHub وملف server.json

MCP Registry هو المكان الذي يجد فيه العملاء والأسواق خادمك، والإدراج يتطلب ملف server.json واحدًا ونطاقًا مُتحقَّقًا منه واحدًا وأمرًا واحدًا. يتتبّع هذا المقال تسجيل الدخول عبر GitHub، وفحوص ملكية الحزم، والخوادم البعيدة، وسير عمل الإصدارات الموسومة.

MCP Registry: كيف تُدرج خادمك عبر GitHub وملف server.json
Cristian Da Conceicao
مؤسس Picasso IA

خادم MCP جيد لا يجده أحد كأنه غير موجود. يحلّ MCP Registry الرسمي هذه المشكلة بملف JSON واحد، واسم مُتحقَّق منه واحد، وأمر واحد، ويظهر GitHub في ثلاث نقاط منفصلة على الطريق: تسجيل الدخول، والنطاق، وأتمتة الإصدار. يتبع هذا المقال الملفات والأوامر الدقيقة من وثائق السجل، حتى يُدرج خادمك في السجل من المحاولة الأولى بدلًا من الخامسة.

💡 الإجابة السريعة: اكتب server.json، وأثبت أنك تملك الحزمة التي يشير إليها، ثم شغّل mcp-publisher login github، ثم شغّل mcp-publisher publish. يشرح كل ما يلي سبب وجود كل خطوة وما الذي ينكسر إذا تخطيتها.

ما هو MCP Registry فعليًا؟

سجلّ MCP Registry هو مستودع البيانات الوصفية الرسمي والمركزي لخوادم MCP المتاحة للعموم، وتدعمه Anthropic وGitHub وPulseMCP وMicrosoft. فُتح في نسخة معاينة في سبتمبر 2025، وبقي API مجمّدًا عند الإصدار v0.1 منذ أواخر أكتوبر 2025، وما تزال الوثائق تحمل شريط المعاينة، لذا توقّع تغييرات صغيرة. تقع الخدمة الحية على registry.modelcontextprotocol.io.

البيانات الوصفية لا الكود

منظر جوي لميناء حاويات تقف فيه حاويات الشحن المكدّسة في شبكات منتظمة عند الساعة الذهبية

لا يخزّن السجل كودك أبدًا. بل يخزّن سجلًا يشير إلى حزمة على npm أو PyPI أو NuGet أو crates.io أو سجل حاويات أو إصدار GitHub. فكّر في ميناء الحاويات: البيان يوضّح ما في كل صندوق ومن أين جاء، بينما البضاعة نفسها موجودة في مكان آخر. لذلك يهمّ الترتيب. تنشر الحزمة أولًا، وبعد ذلك فقط تنشر مدخل السجل.

دور GitHub في العملية

يلمس GitHub العملية في ثلاثة مواضع:

  • الهوية. سجّل الدخول عبر GitHub، ويجب أن يبدأ اسم خادمك بالبادئة io.github.username/، أو باسم مؤسستك بدلًا من اسم المستخدم.
  • البيانات الوصفية. يحمل server.json كائن repository يضم "source": "github" وعنوان URL للمستودع.
  • الأتمتة. تستطيع GitHub Actions المصادقة على السجل عبر OIDC، دون أي سر مخزّن.

هناك أيضًا واجهة عرض منفصلة. يشغّل GitHub سجل MCP الخاص به على github.com/mcp، وأعلن أن الخوادم المنشورة ذاتيًا في سجل المجتمع مفتوح المصدر "ستظهر تلقائيًا" هناك. اعتبر ذلك مكسبًا إضافيًا لا وعدًا: بعد النشر، تحقّق من ظهور خادمك على GitHub بنفسك.

من يستطيع إدراج خادم

الخوادم مفتوحة المصدر ومغلقة المصدر مرحّب بهما، بشرط واحد: أن يكون الخادم متاحًا للوصول العام. أي حزمة عامة (حزمة npm أو صورة Docker على سجل عام) أو نقطة نهاية بعيدة غير محبوسة داخل شبكة خاصة. الخوادم على مضيف داخلي مثل mcp.acme-corp.internal، أو خلف سجل حزم خاص، خارج النطاق. لهذه الحالات، شغّل سجلًا خاصًا بك.

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

اختر النطاق أولًا

حقل name في server.json هو هوية خادمك الدائمة، وطريقة تسجيل الدخول تحدد الأسماء التي يحق لك استخدامها.

طريقة تسجيل الدخولصيغة الاسممثال
GitHubio.github.username/* أو io.github.orgname/*io.github.alice/weather-server
النطاق (DNS أو HTTP)الصيغة المعكوسة لنطاقكcom.example/acme-analytics

أسماء GitHub لتحقيق مكاسب سريعة

لقطة مقرّبة لصناديق بريد نحاسية عتيقة مع بطاقات أسماء ورقية صغيرة في ردهة شقة قديمة

اختر مسار GitHub عندما تكون مطوّرًا فرديًا أو مشروعًا مفتوح المصدر. تُشغّل CLI تدفق OAuth للجهاز، فتوافق عليه في المتصفح، وتنتهي خلال دقيقتين تقريبًا. لا لوحة DNS، ولا ملفات تحتاج إلى استضافة. التنازل يكون في الاسم: io.github.alice/weather-server يبدو جيدًا لمشروع جانبي، لكن العلامة التجارية للشركة عادةً تريد نطاقها الخاص.

أسماء النطاقات عبر DNS أو HTTP

تستخدم الأسماء المبنية على النطاق الصيغة المعكوسة لنطاق تملكه، مثل com.example/acme-analytics. تثبت التحكم به بإحدى طريقتين:

  1. DNS. أنشئ زوج مفاتيح Ed25519 (أو ECDSA P-384) باستخدام openssl، ثم انشر النصف العام منه كسجل TXT بالصيغة example.com. IN TXT "v=MCPv1; k=ed25519; p=<base64>". اسمح بعدة دقائق حتى ينتشر السجل.
  2. HTTP. استضف السطر نفسه v=MCPv1; ... كملف على https://example.com/.well-known/mcp-registry-auth.

ثم سجّل الدخول باستخدام mcp-publisher login dns --domain example.com أو mcp-publisher login http --domain example.com، مع إضافة النصف الخاص من زوجك كما هو موضح في وثائق المصادقة. الفرق التي تفضّل عدم الاحتفاظ بملف خاص على الحاسوب المحمول يمكنها التوقيع عبر خدمات التوقيع السحابي من Google أو Azure بدلًا من ذلك.

اكتب server.json خطوة بخطوة

أنشئ الهيكل الأساسي

ثبّت الناشر عبر Homebrew (brew install mcp-publisher) أو نزّل ملفًا ثنائيًا من إصدارات GitHub الخاصة بالسجل. ثم، داخل مجلد مشروع الخادم:

mcp-publisher --help
mcp-publisher init

يكتب الأمر init قالب server.json ويملأ منه ما يستطيع من مشروعك.

ملف عامل بالحد الأدنى

مطوّر يرتدي هودي رمادي يكتب على مكتب واقف بجانب قائمة مراجعة في دفتر ونبتة عصارية صغيرة

هذا هو الشكل الذي تستخدمه الوثائق لخادم npm محلي:

{
  "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
  "name": "io.github.my-username/weather",
  "description": "An MCP server for weather information.",
  "repository": {
    "url": "https://github.com/my-username/mcp-weather-server",
    "source": "github"
  },
  "version": "1.0.1",
  "packages": [
    {
      "registryType": "npm",
      "identifier": "@my-username/mcp-weather-server",
      "version": "1.0.1",
      "transport": {
        "type": "stdio"
      }
    }
  ]
}

أبقِ سطر $schema الذي يولّده init، لأن تاريخ المخطط يتغيّر مع الوقت. ثلاثة حقول تسبب معظم المشاكل. يجب أن يطابق name إثبات الملكية داخل حزمتك (المزيد أدناه). ويجب أن يشير packages[].identifier إلى شيء منشور بالفعل. أما transport.type فيُخبر العملاء بكيفية التخاطب مع الخادم، حيث يعني stdio عملية محلية.

هل تحتاج إلى متغيرات بيئة؟ أضفها إلى مدخل الحزمة بعلامتي isRequired وisSecret، فيطلب العملاء منك قيمها ويخفون الإدخال.

قواعد الإصدارات التي تسبب المشاكل

يحتاج كل نشر إلى version فريد، وبمجرد نشره، لا يمكن تغيير ذلك الإصدار وبياناته الوصفية. يُوصى بالإصدار الدلالي (Semantic Versioning)، رغم أن أي نص يُقبل. نطاقات الإصدارات مرفوضة عن قصد.

سلسلة الإصدارالحالة
1.0.0، 1.0.0-beta.1، 3.0.0-rc.2موصى به
2025-06-18، v1.0مسموح
^1.2.3، ~1.2.3، >=1.2.3، 1.xممنوع

عادتان تبعدانك عن المشاكل. أولًا، اجعل إصدار الخادم يطابق إصدار الحزمة، بحيث يطابق 1.2.3 في server.json الإصدار 1.2.3 على npm. ثانيًا، إذا كنت تحتاج فقط إلى إصلاح البيانات الوصفية في السجل دون لمس الحزمة، فانشر إصدارًا تجريبيًا (prerelease) مثل 1.2.3-1. لاحظ الفخ: يرتّب semver الإصدار التجريبي قبل إصداره العادي، لذا نشر 1.2.3-1 بعد 1.2.3 لن يُعلَّم كأحدث إصدار.

الخوادم البعيدة عبر remotes

منظور من زاوية منخفضة لممر هادئ في مركز بيانات تصطف على جانبيه رفوف خوادم سوداء طويلة

تستخدم الخوادم المستضافة مصفوفة remotes بدلًا من packages أو إلى جانبه:

{
  "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
  "name": "com.example/acme-analytics",
  "description": "Real-time business intelligence and reporting platform",
  "version": "2.0.0",
  "remotes": [
    {
      "type": "streamable-http",
      "url": "https://analytics.example.com/mcp",
      "headers": [
        {
          "name": "Authorization",
          "description": "Bearer token for your account",
          "isRequired": true,
          "isSecret": true
        }
      ]
    }
  ]
}

يجب أن يكون الخادم البعيد متاحًا للعامة عبر عنوانه. فضّل Streamable HTTP؛ فنقل SSE مهجور، لذا أضف خادمًا بعيدًا من نوع "sse" فقط للعملاء الحاليين. يمكن لإعدادات تعدد المستأجرين استخدام متغيرات في عنوان URL مثل https://{tenant_id}.analytics.example.com/mcp، يُوصف كل منها بواسطة isRequired أو default أو choices. وإذا نشرت حزمة وخادمًا بعيدًا معًا، فاذكرهما كليهما: يختار تطبيق المضيف طريقة التثبيت التي يفضّلها.

أثبت ملكيتك للحزمة

يتحقق السجل من أن الحزمة تنتمي فعلًا إلى الاسم الذي تطالب به. إذا تخطّيت هذا، سيفشل النشر برسالة "Registry validation failed for package". لكل نوع حزمة إثبات خاص به.

فحص واحد لكل نوع حزمة

لقطة ماكرو لختم توثيق نحاسي يضغط بصمة حبر طازجة على ورق كريمي سميك

نوع الحزمةregistryTypeإثبات الملكية
npmnpmmcpName في package.json يساوي اسم الخادم
PyPIpypimcp-name: <server name> في README، ويُسمح بالتعليق المخفي
NuGetnugetmcp-name: <server name> في README، ويُسمح بالتعليق المخفي
Cargo (crates.io)cargomcp-name: <server name> كنص مرئي في README
صورة Docker أو OCIociLABEL io.modelcontextprotocol.server.name="<server name>"
ملف MCPBmcpbيحتوي عنوان URL على "mcp"، إضافة إلى تجزئة fileSha256 في server.json

بالنسبة إلى npm، يبدو ذلك هكذا في package.json:

{
  "name": "@my-username/mcp-weather-server",
  "version": "1.0.1",
  "mcpName": "io.github.my-username/weather"
}

هناك تفاصيل قليلة توقع الناس في الخطأ. فحص npm يستخدم سجل npm العام فقط، وPyPI و NuGet مقيّدان بالمثل بسجلاتهما الرسمية. يحذف crates.io تعليقات HTML، لذا يجب أن يكون رمز Cargo نصًا مرئيًا لا تعليقًا مخفيًا. بالنسبة إلى صور الحاويات، يأتي identifier بعد registry/namespace/repository:tag، والمضيفون المدعومون هم Docker Hub و GitHub Container Registry (ghcr.io) و Google Artifact Registry و Azure Container Registry و Microsoft Container Registry. أما ملفات MCPB المستضافة على إصدارات GitHub أو GitLab، فاحسب التجزئة باستخدام openssl dgst -sha256 your-file.mcpb. لا يتحقق السجل من هذه التجزئة، لكن العملاء يتحققون منها قبل التثبيت.

💡 نصيحة: يجب أن يتطابق اسم الخادم في server.json مع الإثبات داخل الحزمة حرفًا بحرف. يكفي حرف كبير واحد زائد لإفشال التحقق.

انشر من الطرفية

سجّل الدخول عبر GitHub

امرأة ترتدي سترة جينز على طاولة قرب نافذة مقهى في يوم ممطر تمسك هاتفًا بجانب حاسوب محمول مفتوح

شغّل تسجيل الدخول من مجلد مشروعك:

mcp-publisher login github

تطبع CLI رمزًا لمرة واحدة ورابطًا:

To authenticate, please:
1. Go to: https://github.com/login/device
2. Enter code: ABCD-1234
3. Authorize this application
Waiting for authorization...

افتح الرابط، والصق الرمز، ووافق، وستؤكد الطرفية تسجيل الدخول. إذا ظهرت لاحقًا رسالة "Invalid or expired Registry JWT token"، فهذا يعني أن الجلسة انتهت. أعد تسجيل الدخول.

انشر وتحقّق

منظور بمستوى العين لواجهة مكتبة عند الساعة الذهبية، عليها كتاب مجلد جديد واحد على حامل عرض خشبي

مع وجود الحزمة منشورة على npm وحفظ server.json، انشر:

mcp-publisher publish

يطبع التشغيل السليم عنوان URL الخاص بالسجلّ واسم خادمك مع إصداره. تحقّق من ذلك عبر API العام:

curl "https://registry.modelcontextprotocol.io/v0.1/servers?search=io.github.my-username/weather"

يجب أن تظهر البيانات الوصفية لخادمك في JSON المُعاد. تُحدَّث الأسواق اللاحقة وفق جدولها الخاص، فامنحها بعض الوقت قبل أن تتوقع ظهور الإدراج هناك، وابحث عنه في github.com/mcp أيضًا.

تتبع التحديثات المسار نفسه. ارفع إصدار الحزمة، وانشرها على npm، ثم ارفع server.json ليطابقها، وشغّل mcp-publisher publish مرة أخرى. كل نشر إصدار غير قابل للتغيير بذاته، ويعلّم السجل أحدث إصدار دلالي بأنه الأحدث، لذلك يحصل العملاء الذين يطلبون الإصدار الحالي على الإصدار الصحيح.

أطلق الإصدارات عبر GitHub Actions

سير عمل إصدار موسوم

منظور من زاوية مرتفعة لطرود كرتونية تسير على سير ناقل عبر قاعة فرز

بمجرد أن يعمل التشغيل اليدوي، انقله إلى CI بحيث ينشر كل وسم إصدار الحزمة ومدخل السجل معًا. يستخدم سير العمل هذا OIDC من GitHub، وهي الطريقة التي توصي بها الوثائق:

name: Publish to MCP Registry

on:
  push:
    tags: ["v*"]

jobs:
  publish:
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: read

    steps:
      - name: Checkout code
        uses: actions/checkout@v5

      - name: Set up Node.js
        uses: actions/setup-node@v5
        with:
          node-version: "lts/*"

      - name: Install dependencies
        run: npm ci

      - name: Build package
        run: npm run build --if-present

      - name: Publish package to npm
        run: npm publish
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

      - name: Install mcp-publisher
        run: |
          curl -L "https://github.com/modelcontextprotocol/registry/releases/latest/download/mcp-publisher_$(uname -s | tr '[:upper:]' '[:lower:]')_$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/').tar.gz" | tar xz mcp-publisher

      - name: Authenticate to MCP Registry
        run: ./mcp-publisher login github-oidc

      - name: Publish server to MCP Registry
        run: ./mcp-publisher publish

تُطلق الإصدار بأمرين هما git tag v1.0.0 ثم git push origin v1.0.0. شيء واحد يتركه القالب اختياريًا هو تحديث الإصدار. إذا احتوى server.json على إصدار مكتوب يدويًا، فسيرفض السجل النشر المكرر، لذا عيّنه من الوسم قبل خطوة النشر. بالنسبة إلى خادم بحزمة واحدة، يحدّث هذا السطر jq كلا حقلي الإصدار:

VERSION=${GITHUB_REF#refs/tags/v}
jq --arg v "$VERSION" '.version = $v | .packages[0].version = $v' server.json > server.tmp && mv server.tmp server.json

الأسرار التي تحتاجها

  • GitHub OIDC: لا يحتاج إلى سرّ للسجل. تحتاج فقط إلى صلاحية id-token: write.
  • رمز الوصول الشخصي من GitHub: خزّنه كسرّ وشغّل mcp-publisher login github --token، مع النطاقين read:org و read:user.
  • تسجيل الدخول عبر DNS: خزّن النصف الخاص من زوج Ed25519 كسرّ، ومرّره إلى mcp-publisher login dns.
  • سجل الحزم: يحتاج سير العمل أعلاه أيضًا إلى سرّ NPM_TOKEN من أجل npm publish.

أصلح الأخطاء قبل أن يراها المستخدمون

منظور علوي لمكتب عليه صفحة مطبوعة مُعلَّم عليها بقلم أحمر، وعدسة مكبّرة، وأوراق ملاحظات لاصقة

معظم عمليات النشر الفاشلة تعود إلى خمس رسائل:

رسالة الخطأالإصلاح المحتمل
"Registry validation failed for package"تفتقر الحزمة إلى إثبات ملكيتها، مثل mcpName في package.json.
"Invalid or expired Registry JWT token"سجّل الدخول مرة أخرى باستخدام mcp-publisher login github.
"You do not have permission to publish this server"طريقة تسجيل الدخول لا تطابق بادئة الاسم. يحتاج تسجيل الدخول عبر GitHub إلى io.github.your-username/.
"Authentication failed"في Actions، تأكد من ضبط id-token: write، أو راجع أسرارك.
"Package validation failed"الحزمة غير منشورة على سجلها بعد، أو تفتقر إلى إثبات الملكية.

قبل كل إصدار، راجع هذه القائمة القصيرة:

  • name في server.json يساوي mcpName (أو رمز README، أو تسمية الصورة).
  • إصدار الحزمة في server.json موجود بالفعل على npm أو PyPI أو مضيف الحاويات لديك.
  • version الخاص بالخادم لم يُنشر من قبل، وليس نطاقًا.
  • أي عنوان URL بعيد يستجيب من الإنترنت العام، لا من شبكة مكتبك فقط.
  • الخادم مُعدّ للعامة. الخوادم الخاصة تنتمي إلى سجل خاص.

صغ وصوّر مع PicassoIA

نموذج لغوي كبير (LLM) آلة سريعة لإعداد المسودة الأولى من أجل server.json، ما دام السجل هو من يتولى الحكم. تستضيف PicassoIA نماذج لغوية كبيرة يمكنك استخدامها مباشرة من المتصفح، بما فيها Claude Sonnet 5 وGPT 5.6 Sol وGemini 3.5 Flash.

كيفية استخدام Sonnet 5 على PicassoIA

  1. افتح صفحة Claude Sonnet 5 على PicassoIA وابدأ محادثة جديدة.
  2. الصق حقول package.json (الاسم، والإصدار، والوصف، والمستودع) مع سطر $schema الذي أنتجه mcp-publisher init.
  3. اطلب JSON فقط، وأخبر النموذج أن يترك $schema دون تغيير، واحظر الحقول المختلَقة.
  4. انسخ النتيجة إلى server.json، ثم تحقّق بعينك من أن name يساوي mcpName.
  5. شغّل mcp-publisher publish. إذا اعترض التحقق، فالصق الخطأ نفسه كما ظهر في المحادثة.

الأوامر القصيرة مع مصدر ملصوق تتفوق على الأوامر الطويلة المكتوبة بالوصف، لأن النماذج تختلق حقولًا معقولة عندما لا يُعرض عليها الملف الحقيقي. هل تريد تهيئة سير عمل Actions أيضًا؟ GPT 5.6 Sol رأي ثانٍ جيد لذلك.

تشغّل PicassoIA كذلك API للمطوّرين، وهو مثال مناسب لتوضيح الغرض من environmentVariables. يقع API على https://api.picassoia.com/v1 ويعمل مثل واجهات التنبؤ الأخرى: أنشئ تنبؤًا، ثم استعلم عن حالته، ثم اجلب النتيجة، مع حدّ أقصاه 5 تنبؤات متزامنة لكل حساب (اعتبارًا من أوائل أكتوبر 2026). سيطلب خادم تغليف مُتخيَّل من كل مستخدم بيانات اعتماده الخاصة مرة واحدة، عبر إدخال كهذا داخل حزمته:

"environmentVariables": [
  {
    "name": "PICASSOIA_TOKEN",
    "description": "Bearer credential for api.picassoia.com/v1",
    "isRequired": true,
    "isSecret": true,
    "format": "string"
  }
]

مدخل السجل مجرد نص، لكن README وبطاقة المشاركة والمنشور الإطلاقي كلها تحتاج إلى صور. افتح PicassoIA، واختر نموذجًا لتوليد الصور أو الفيديو، واصنع صورة رئيسية أو مقطع عرض قصيرًا لخادمك. كتالوج النماذج الكامل موجود على picassoia.com/en/all-models. جرّب ثلاثة أوامر نصية، واحتفظ بأفضلها، وانشره مع أول mcp-publisher publish لك.

شارك هذا المقال

اختر لغتك

مقالات ذات صلة