عکس از آدی گلدشتاین در Unsplash.
عکس از آدی گلدشتاین در Unsplash.

ساخت اولین سرور پروتکل زمینه مدل (MCP) شما

پروتکل زمینه مدل به عنوان یک واسطه عمل می‌کند که نحوه تعامل ابزارها و سرویس‌های مختلف با مدل‌های زبانی را استانداردسازی می‌کند.

مدل‌های زبانی بزرگ (LLM) نحوه تعامل ما با هوش مصنوعی را متحول کرده‌اند، اما محدودیت‌های ذاتی خود را دارند. در حالی که آن‌ها در پیش‌بینی و تولید متن بر اساس داده‌های آموزشی خود عالی هستند، در انجام مستقل وظایف معنادار دنیای واقعی مشکل دارند. این محدودیت اساسی منجر به توسعه LLMهای تقویت‌شده با ابزار شد که می‌توانند از طریق رابط‌های برنامه‌نویسی کاربردی (API) با سرویس‌های خارجی تعامل داشته باشند و قابلیت‌هایی مانند جستجوی وب و عملیات فایل را فعال کنند.

با این حال، رویکردهای مبتنی بر ابزار چالش‌های خاص خود را به همراه دارند. در حالی که آن‌ها به طور قابل توجهی قابلیت‌های یک LLM را افزایش می‌دهند و امکان اتوماسیون وظایف و بازیابی داده‌ها را فراهم می‌کنند، همچنان به دلیل ساختار سفت و سخت خود محدود هستند. هنگامی که APIها تکامل می‌یابند یا موارد استفاده جدید پدیدار می‌شوند، کل اکوسیستم ابزار باید تطبیق یابد که باعث ایجاد سربار نگهداری و نقاط بالقوه شکست می‌شود.

این ما را با مشکل زیر مواجه می‌کند: چگونه می‌توانیم سیستم‌های انعطاف‌پذیرتر و مقاوم‌تری ایجاد کنیم که بر این محدودیت‌ها غلبه کنند؟ یک پاسخ ممکن، رویکرد پروتکل زمینه مدل (MCP) است که در جامعه هوش مصنوعی مورد توجه زیادی قرار گرفته است.

چگونه MCP مشکل را حل می‌کند؟

پروتکل زمینه مدل (MCP) با فراهم کردن یک لایه ارتباطی یکپارچه بین LLMها و سرویس‌های خارجی، به این چالش‌ها رسیدگی می‌کند. در هسته خود، MCP یک واسطه است که نحوه تعامل ابزارها و سرویس‌های مختلف با مدل‌های زبانی را استانداردسازی می‌کند.

نوآوری کلیدی MCP توانایی آن در ترجمه بین مشخصات ابزار و APIهای مختلف است. به جای اینکه هر ابزار ملزم به تطبیق با الزامات یک LLM خاص باشد، MCP لایه ترجمه را مدیریت می‌کند و ارتباط روان بین همه مؤلفه‌ها را تضمین می‌کند. این استانداردسازی نیاز به ادغام‌های سفارشی را از بین می‌برد و پیچیدگی پیاده‌سازی را کاهش می‌دهد.

معماری MCP شامل سه مؤلفه اصلی است:

  1. کلاینت MCP: برنامه‌هایی مانند Cursor یا Windsurf، و همچنین ارائه‌دهندگان LLM که با پروتکل رابط دارند.
  2. سرور MCP: مؤلفه اصلی که ترجمه پروتکل و مدیریت قابلیت‌ها را انجام می‌دهد و توسط ارائه‌دهندگان خدمات (GitHub، Figma و دیگران) نگهداری می‌شود.
  3. سرویس‌ها: ابزارها و قابلیت‌های واقعی که سرور MCP به آن‌ها متصل می‌شود.

سرورهای MCP می‌توانند سه نوع سرویس را به کلاینت‌ها ارائه دهند:

  • منابع (Resources): این‌ها ساختارهای داده‌ای شبیه فایل هستند که کلاینت‌ها می‌توانند به آن‌ها دسترسی داشته باشند، مانند محتویات فایل یا پاسخ‌های API.
  • ابزارها (Tools): فراخوانی‌های تابعی که LLMها می‌توانند (با تأیید کاربر) اجرا کنند و امکان تعامل با سرویس‌های خارجی را فراهم می‌کنند.
  • پرامپت‌ها (Prompts): الگوهای از پیش نوشته شده که کاربران یا LLMها را در انجام وظایف خاص راهنمایی می‌کنند.

این رویکرد ساختاریافته تضمین می‌کند که سرویس‌ها می‌توانند عملکرد خود را به طور مداوم و ایمن ارائه دهند، در حالی که انعطاف‌پذیری را برای توسعه‌ها و تغییرات آینده حفظ می‌کنند.

بیایید یک سرور MCP ساده بسازیم

برای نشان دادن پیاده‌سازی عملی یک سرور MCP، یک مثال پایه با استفاده از نود.جی‌اس (Node.js) با تایپ‌اسکریپت (TypeScript) ایجاد خواهیم کرد. در حالی که کیت‌های توسعه نرم‌افزار (SDK) رسمی برای پایتون، جاوا، کاتلین و سی‌شارپ موجود است، ما نود.جی‌اس را به دلیل پذیرش گسترده و پشتیبانی عالی از تایپ‌اسکریپت انتخاب کرده‌ایم.

ما برای این آموزش سروری خواهیم ساخت که با سرویس‌های Stream ادغام می‌شود. اگرچه با فراخوانی‌های API خاص Stream کار خواهیم کرد، اصول و الگوهای اصلی که پوشش خواهیم داد برای هر پیاده‌سازی سرور MCP اعمال می‌شود. سرور ما دو ابزار ضروری را ارائه خواهد داد:

  • create-user: ابزاری برای ایجاد کاربر
  • get-token: ابزاری برای تولید توکن وب جیسون (JWT)

این ابزارها پایه یک پروژه اساسی را تشکیل می‌دهند و به شما در درک مفاهیم بنیادی پیاده‌سازی سرور MCP کمک می‌کنند.

قبل از شروع، اطمینان حاصل کنید که نود.جی‌اس نسخه ۱۶ یا بالاتر روی سیستم شما نصب شده باشد. برای این آموزش، از نود.جی‌اس نسخه ۲۰ استفاده خواهیم کرد.

راه‌اندازی پروژه

بیایید با راه‌اندازی محیط توسعه خود شروع کنیم. یک پروژه جدید نود.جی‌اس با پشتیبانی تایپ‌اسکریپت ایجاد می‌کنیم و تمام وابستگی‌های لازم برای ساخت سرور MCP خود را نصب می‌کنیم.

ابتدا، یک دایرکتوری جدید برای پروژه خود ایجاد کرده و آن را با npm مقداردهی اولیه کنید:


mkdir sample-server && cd sample-server
npm init -y
npm install @modelcontextprotocol/sdk zod getstream
npm install -D @types/node typescript

سپس، ساختار پایه پروژه را با افزودن یک دایرکتوری منبع (source) و فایل اصلی تایپ‌اسکریپت خود ایجاد خواهیم کرد:


mkdir src
touch src/index.ts

از آنجایی که ما در حال ساخت یک ماژول هستیم نه یک برنامه وب، باید فایل package.json خود را به درستی پیکربندی کنیم. پیکربندی زیر را برای تعیین نوع ماژول و اسکریپت ساخت اضافه کنید:


{
  "type": "module",
  "bin": {
    "sample-server": "./build/index.js"
  },
  "scripts": {
    "build": "tsc && chmod 755 build/index.js"
  },
  "files": [
    "build"
  ]
}

در نهایت، تایپ‌اسکریپت را با یک پیکربندی قوی راه‌اندازی می‌کنیم که ایمنی نوع (type safety) و ویژگی‌های مدرن جاوا اسکریپت را تضمین می‌کند. یک فایل tsconfig.json با این تنظیمات ایجاد کنید:


{
  "compilerOptions": {
    "target": "ES2022",
    "module": "Node16",
    "moduleResolution": "Node16",
    "outDir": "./build",
    "rootDir": "./src",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules"]
}

با این پیکربندی‌ها، ما یک پایه محکم برای ساخت سرور MCP خود داریم. پروژه اکنون دارای پشتیبانی تایپ‌اسکریپت، وابستگی‌های لازم و پیکربندی مناسب ماژول است.

راه‌اندازی سرور پایه

اکنون که ساختار پروژه خود را داریم، بیایید پایه سرور MCP خود را ایجاد کنیم. از SDK رسمی MCP استفاده خواهیم کرد که تمام بلوک‌های ساختمانی لازم برای پیاده‌سازی ما را فراهم می‌کند.

ابتدا، به راه‌اندازی اولیه سرور نگاهی بیندازیم. وابستگی‌های مورد نیاز را وارد کرده و نمونه سرور خود را ایجاد می‌کنیم:


import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
import { StreamChat } from 'stream-chat';

// Create server instance
const server = new McpServer({
  name: "sample-server",
  version: "1.0.0",
  capabilities: {
    resources: {},
    tools: {},
  },
});

این یک سرور MCP بسیار ساده با یک شیء قابلیت‌های خالی ایجاد می‌کند. سرور با نام و نسخه خود شناسایی می‌شود که به کلاینت‌ها کمک می‌کند بفهمند به چه چیزی متصل می‌شوند. در بخش‌های بعدی، به تدریج این پیکربندی را با افزودن ابزارها و منابع گسترش خواهیم داد.

هنگامی که نمونه سرور خود را راه‌اندازی کردیم، باید آن را به یک لایه انتقال متصل کنیم که ارتباط با کلاینت را مدیریت می‌کند. در این مورد، ما از stdio (ورودی/خروجی استاندارد) به عنوان مکانیزم انتقال خود استفاده می‌کنیم:


async function main() {
  const transport = new StdioServerTransport();
  await server.connect(transport);
  console.error('Sample MCP Server running on stdio');
}

main().catch((error) => {
  console.error('Fatal error in main():', error);
  process.exit(1);
});

افزودن ابزارها به سرور

با آماده بودن پایه سرور، زمان آن رسیده است که ابزارهایی را اضافه کنیم که به سرور MCP ما عملکرد می‌دهند. در MCP، ابزارها توابعی هستند که کلاینت‌ها می‌توانند برای انجام اقدامات خاص فراخوانی کنند. بیایید بررسی کنیم که چگونه این ابزارها را با سرور خود ثبت کنیم.

SDK MCP روشی ساده برای ثبت ابزارها با استفاده از متد server.tool ارائه می‌دهد. این متد به چهار مؤلفه کلیدی نیاز دارد:

  1. نام ابزار — یک شناسه منحصر به فرد برای ابزار.
  2. توضیحات — مستندات واضح در مورد کاری که ابزار انجام می‌دهد.
  3. اسکیمای ورودی — استفاده از Zod برای اعتبارسنجی ورودی با ایمنی نوع (type-safe).
  4. تابع اجرا — پیاده‌سازی واقعی که درخواست را پردازش می‌کند.

بیایید با پیاده‌سازی اولین ابزار خود به یک مثال عملی نگاه کنیم: قابلیت ایجاد کاربر.


server.tool(
  'create-user',
  'Create a new user on the Stream backend',
  {
    id: z.string().describe('The id of the user to create'),
    username: z.string().describe('The username of the user to create'),
    email: z
      .string()
      .email()
      .optional()
      .describe('The email of the user to create'),
  },
  async ({ id, username, email }) => {
    const serverClient = StreamChat.getInstance(
      STREAM_API_KEY,
      STREAM_API_SECRET
    );
    const user = await serverClient.upsertUser({
      id,
      username,
      email,
    });
    return {
      content: [
        {
          type: 'text',
          text: `User ${username} created successfully`,
        },
      ],
    };
  }
);

همچنین می‌توانیم ابزار دومی برای تولید توکن اضافه کنیم که از همان الگو پیروی می‌کند اما هدف متفاوتی را دنبال می‌کند:


server.tool(
  'generate-token',
  'Generate a token for a user',
  {
    userId: z.string().describe('The id of the user to generate a token for'),
  },
  async ({ userId }) => {
    const serverClient = StreamChat.getInstance(
      process.env.STREAM_API_KEY!,
      process.env.STREAM_API_SECRET!
    );

    const token = serverClient.createToken(userId);

    return {
      content: [{ type: 'text', text: `Token: ${token}` }],
    };
  }
);

هر دو ابزار قدرت سیستم ثبت ابزار MCP را نشان می‌دهند. آن‌ها الزامات ورودی خود را با استفاده از اسکیماهای Zod تعریف می‌کنند، توضیحات دقیقی ارائه می‌دهند و عملکرد خاصی را پیاده‌سازی می‌کنند که کلاینت‌ها می‌توانند فراخوانی کنند. ماهیت ایمن از نظر نوع (type-safe) این تنظیمات به جلوگیری از خطاهای زمان اجرا کمک می‌کند و تجربه توسعه‌دهنده عالی را از طریق تکمیل خودکار و اعتبارسنجی فراهم می‌کند.

افزودن سرور خود به یک کلاینت

حالا که پیاده‌سازی سرور MCP ما آماده است، بیایید آن را با یک برنامه کلاینت ادغام کنیم. ما از Cursor به عنوان کلاینت مثال خود استفاده خواهیم کرد، اگرچه این فرآیند برای سایر کلاینت‌های سازگار با MCP مشابه است.

ابتدا، باید سرور خود را بسازیم. به لطف پیکربندی قبلی دستور ساخت، این کار به سادگی اجرای دستور زیر است:

npm run build

پس از اتمام ساخت، مراحل زیر را برای ادغام سرور خود با Cursor دنبال کنید:

  1. تنظیمات Cursor را باز کرده و به بخش MCP در منو بروید.
  2. گزینه «Add new global MCP server» را پیدا کرده و روی آن کلیک کنید (توجه: در صورت تمایل می‌توانید این را به صورت هر پروژه نیز پیکربندی کنید).
  3. فایل سرور ساخته شده خود را پیدا کرده و مسیر مطلق آن را کپی کنید.

اکنون، باید یک پیکربندی سرور در قالب جی‌سون (JSON) ایجاد کنید. موارد زیر را به فایل پیکربندی خود اضافه کنید و جای‌نمای مسیر را با مسیر واقعی سرور خود جایگزین کنید:


{
  "mcpServers": {
    "stream-server": {
      "command": "node",
      "args": [
        "</path/to/server>/build/index.js"
      ]
    }
  }
}

با پیکربندی در جای خود، اکنون می‌توانید سرور خود را با درخواست ایجاد یک کاربر جدید آزمایش کنید. مشاهده کنید که چگونه سرور درخواست شما را پردازش کرده و نتایج را از طریق پروتکل MCP برمی‌گرداند.

خلاصه

این مثال عملی نشان داد که چگونه MCP فرآیند ساخت برنامه‌های هوش مصنوعی تقویت‌شده با ابزار را ساده می‌کند، در حالی که ایمنی نوع (type safety) را حفظ کرده و تجربه توسعه‌دهنده عالی را فراهم می‌کند. ما از SDK بک‌اند Stream استفاده کردیم، اما منطق را می‌توان به هر کد دیگری که می‌خواهید ارائه دهید، تطبیق داد. به ما اطلاع دهید که چه سرور MCPای خواهید ساخت!