Resources و Prompts در MCP

قسمت ۴ ۱۵ دقیقه

خلاصه قسمت قبل

در قسمت ۳ یه MCP Server حرفه‌ای ساختیم که فایل‌سیستم رو مدیریت می‌کرد. با ساختار سرور، شماهای ورودی دقیق و مدیریت خطا آشنا شدیم. حالا وقتشه با دو قابلیت دیگه MCP آشنا بشیم: Resources و Prompts.

چرا فقط Tools کافی نیست؟

تا اینجا همه‌چیز درباره Tools بود — ابزارهایی که AI صداشون می‌زنه و یه کاری انجام می‌دن. ولی MCP فقط Tools نیست. دو قابلیت دیگه هم داره که خیلی وقت‌ها مهم‌تر از Tools هستن.

فرض کن یه سرور داری که به دیتابیس شرکتت وصله. یه‌بار AI می‌خواد لیست مشتری‌ها رو ببینه (خوندن داده) و یه‌بار دیگه می‌خواد یه مشتری جدید اضافه کنه (انجام کار). اینا دو نوع متفاوت از تعامل هستن و MCP هم اونا رو جدا می‌کنه.

تشبیه
فکر کن MCP یه آشپزخونه حرفه‌ایه. Tools مثل آشپزن — یه سفارش می‌گیرن و یه غذا درست می‌کنن. Resources مثل ویترین مواد اولیه‌ست — AI می‌تونه ببینه چه موادی موجوده. Prompts هم مثل منوی پیشنهادی شف هستن — ترکیب‌های آماده‌ای که AI می‌تونه ازشون استفاده کنه.

Resources: داده‌ها رو در اختیار AI بذار

Resource به AI اجازه می‌ده داده‌ها رو بخونه — بدون اینکه کاری انجام بده. فرقش با Tool اینه که Resource فقط‌خواندنی (read-only) هست. Tool یه عملیات اجرا می‌کنه ولی Resource صرفاً اطلاعات برمی‌گردونه.

چرا این تفکیک مهمه؟ چون:

  • امنیت: خوندن داده خطرناک نیست، ولی نوشتن می‌تونه خطرناک باشه. وقتی چیزی Resource تعریف بشه، AI می‌دونه که ایمنه و می‌تونه آزادتر ازش استفاده کنه
  • عملکرد: Client می‌تونه Resourceها رو cache کنه. اگه همون داده رو دوبار بخواد، لازم نیست دوبار از سرور بگیره
  • وضوح: وقتی AI لیست ابزارها رو می‌بینه، فوری می‌فهمه کدوم‌ها فقط‌خواندنی و کدوم‌ها عملیاتی هستن

تعریف Resource

بیا یه Resource ساده بسازیم. فرض کن سرور فایل‌سیستممون می‌خوایم اطلاعات کلی درباره پوشه مجاز رو هم نشون بده:

server.resource(
  "workspace-info",
  "workspace://info",
  async (uri) => {
    const stats = await fs.stat(ALLOWED_DIR);
    const entries = await fs.readdir(ALLOWED_DIR);

    return {
      contents: [{
        uri: uri.href,
        mimeType: "text/plain",
        text: [
          `Workspace: ${ALLOWED_DIR}`,
          `Total items: ${entries.length}`,
          `Last modified: ${stats.mtime.toISOString()}`
        ].join("\n")
      }]
    };
  }
);

ببین تفاوت‌ها رو با Tool:

تابع server.resource(): به جای server.tool(). سه آرگومان می‌گیره: اسم resource، URI (آدرس یکتا)، و تابعی که داده رو برمی‌گردونه.

URI: هر Resource یه آدرس یکتا داره. اینجا workspace://info هست. Client با این آدرس از سرور می‌خواد اطلاعات رو بفرسته. فرمت URI دلخواهه ولی باید منحصربه‌فرد باشه.

بدون شمای ورودی: Resource شمای ورودی نداره. آدرسش مشخصه و AI فقط اون آدرس رو صدا می‌زنه.

mimeType: نوع محتوا رو مشخص می‌کنه. اینجا متن ساده‌ست ولی می‌تونه application/json یا حتی image/png هم باشه.

Resource با الگو (Template)

Resources می‌تونن پویا هم باشن. مثلاً یه Resource که محتوای هر فایلی رو بر اساس مسیرش برمی‌گردونه:

server.resource(
  "file-content",
  new ResourceTemplate("file:///{path}", { list: undefined }),
  async (uri, { path: filePath }) => {
    const fullPath = path.resolve(ALLOWED_DIR, filePath);

    if (!fullPath.startsWith(ALLOWED_DIR)) {
      throw new Error("Access denied");
    }

    const content = await fs.readFile(fullPath, "utf-8");

    return {
      contents: [{
        uri: uri.href,
        mimeType: "text/plain",
        text: content
      }]
    };
  }
);

اینجا از ResourceTemplate استفاده کردیم. {path} یه پارامتر پویاست — AI می‌تونه هر مسیری رو بذاره. مثلاً file:///src/index.js محتوای فایل src/index.js رو برمی‌گردونه.

نکته
وقتی شک داری چیزی Resource باشه یا Tool، این قاعده رو یادت باشه: اگه فقط داده برمی‌گردونه و هیچ چیزی تغییر نمی‌ده → Resource. اگه یه عملیاتی انجام می‌ده (نوشتن، حذف، ارسال) → Tool.

Prompts: الگوهای آماده تعامل

Prompt سومین قابلیت MCP Server هست و شاید کمتر شناخته‌شده ولی خیلی قدرتمنده. Prompt یه الگوی از پیش تعریف‌شده برای تعامل با AI هست — مثل یه دستورالعمل آماده که AI می‌تونه ازش استفاده کنه.

چرا Prompts مفیدن؟

  • استانداردسازی: به جای اینکه هر بار یه درخواست پیچیده بنویسی، یه الگوی آماده داری
  • تخصص: می‌تونی الگوهایی بسازی که خاص حوزه کارت هستن — مثلاً «تحلیل کد» یا «خلاصه گزارش»
  • قابلیت اشتراک: الگوها رو می‌شه بین تیم به اشتراک گذاشت

تعریف Prompt

بیا یه Prompt بسازیم که کد رو بررسی می‌کنه:

server.prompt(
  "review-code",
  "Review code for bugs, style issues, and improvements",
  {
    filePath: {
      type: "string",
      description: "Path to the file to review"
    },
    focus: {
      type: "string",
      description: "What to focus on: 'bugs', 'style', 'performance', or 'all'",
      enum: ["bugs", "style", "performance", "all"]
    }
  },
  async ({ filePath, focus = "all" }) => {
    const fullPath = path.resolve(ALLOWED_DIR, filePath);
    const content = await fs.readFile(fullPath, "utf-8");

    const focusInstructions = {
      bugs: "Focus specifically on potential bugs, edge cases, and error handling issues.",
      style: "Focus on code style, naming conventions, and readability.",
      performance: "Focus on performance bottlenecks and optimization opportunities.",
      all: "Review for bugs, style issues, and performance improvements."
    };

    return {
      messages: [
        {
          role: "user",
          content: {
            type: "text",
            text: `Please review this code:\n\n\`\`\`\n${content}\n\`\`\`\n\n${focusInstructions[focus]}\n\nProvide specific, actionable feedback with line references where applicable.`
          }
        }
      ]
    };
  }
);

ببین چه اتفاقی می‌افته:

تابع server.prompt(): مثل tool ولی به جای content یه آرایه messages برمی‌گردونه. این پیام‌ها مستقیم وارد مکالمه AI می‌شن.

الگوی هوشمند: بر اساس focus انتخاب‌شده، دستورالعمل متفاوتی به AI داده می‌شه. اگه بگی «فقط باگ‌ها رو بررسی کن»، AI فقط روی باگ‌ها تمرکز می‌کنه.

خوندن فایل + پرامپت: Prompt اول محتوای فایل رو می‌خونه و بعد با دستورالعمل مناسب وارد مکالمه می‌شه. ترکیب Resource و Prompt!

تشبیه
فکر کن Prompt مثل یه چک‌لیست بازرسی هواپیماست. خلبان هر بار نباید از صفر فکر کنه چی چک کنه — یه لیست استاندارد داره که قدم‌به‌قدم جلو می‌ره. Prompt هم همینه — یه الگوی استاندارد که AI رو هدایت می‌کنه.

Prompt با چند پیام

Prompts می‌تونن چند پیام داشته باشن — حتی پیام‌های system:

server.prompt(
  "explain-simply",
  "Explain a technical concept in simple terms",
  {
    concept: {
      type: "string",
      description: "The technical concept to explain"
    }
  },
  async ({ concept }) => {
    return {
      messages: [
        {
          role: "user",
          content: {
            type: "text",
            text: `Explain "${concept}" as if I'm a complete beginner. Use everyday analogies, avoid jargon, and keep it under 200 words. If the concept has practical applications, mention one real-world example.`
          }
        }
      ]
    };
  }
);

این یه Prompt ساده‌تره — فقط یه مفهوم می‌گیره و از AI می‌خواد ساده توضیحش بده. ولی توجه کن چقدر دستورالعمل دقیقه: «مثل یه مبتدی توضیح بده، تشبیه روزمره استفاده کن، اصطلاحات فنی نذار، زیر ۲۰۰ کلمه.» هرچی Prompt دقیق‌تر باشه، خروجی AI بهتره.

Tools vs Resources vs Prompts — کی از کدوم استفاده کنیم؟

حالا بذار یه مقایسه واضح داشته باشیم. این سه قابلیت هر کدوم جای خودشون رو دارن:

Tools وقتی استفاده می‌شن که:

  • AI باید یه عملیات انجام بده (نوشتن، حذف، ارسال، محاسبه)
  • نتیجه به ورودی‌های مختلف بستگی داره
  • ممکنه side effect داشته باشه (تغییر فایل، ارسال پیام)
  • AI خودش تصمیم می‌گیره کِی صداشون بزنه

Resources وقتی استفاده می‌شن که:

  • AI باید داده‌ای رو بخونه (اطلاعات، فایل، وضعیت سیستم)
  • خوندن بی‌خطره و هیچ چیزی تغییر نمی‌کنه
  • داده قابل cache شدنه
  • کاربر یا اپلیکیشن تصمیم می‌گیره کِی لودشون کنه

Prompts وقتی استفاده می‌شن که:

  • یه الگوی تعامل تکراری داری
  • می‌خوای کیفیت خروجی AI رو استاندارد کنی
  • نیاز به دستورالعمل‌های پیچیده داری که هر بار تکرارشون سخته
  • کاربر انتخاب می‌کنه کدوم الگو استفاده بشه
مهم
یه اشتباه رایج اینه که همه‌چیز رو Tool تعریف کنی. اگه چیزی فقط داده می‌خونه، Resource تعریفش کن. اگه یه الگوی تکراری داری، Prompt بسازش. استفاده درست از هر سه قابلیت باعث می‌شه سرورت هم ایمن‌تر باشه و هم بهتر کار کنه.

یه مثال عملی — همه با هم

بذار ببینیم یه سرور واقعی چطور هر سه قابلیت رو ترکیب می‌کنه. فرض کن یه MCP Server برای مدیریت نوت‌ها داری:

Resources:

  • notes://list — لیست همه نوت‌ها (فقط‌خواندنی)
  • notes:///{id} — محتوای یه نوت خاص (فقط‌خواندنی)

Tools:

  • create_note — ساخت نوت جدید (عملیات نوشتن)
  • update_note — ویرایش نوت (عملیات نوشتن)
  • delete_note — حذف نوت (عملیات خطرناک)
  • search_notes — جستجو در نوت‌ها (عملیات محاسباتی)

Prompts:

  • summarize-notes — خلاصه همه نوت‌های امروز
  • brainstorm — ایده‌پردازی بر اساس نوت‌های موجود

ببین چطور هر قابلیت جای درستش رو داره. خوندن لیست نوت‌ها Resource هست چون ایمنه و قابل cache. ساخت و حذف نوت Tool هست چون عملیاته. خلاصه‌سازی Prompt هست چون یه الگوی تعامل تکراریه.

نکات پیشرفته

Subscription روی Resources

یه قابلیت جالب MCP اینه که Client می‌تونه روی Resource ها subscribe کنه — یعنی وقتی داده تغییر کرد، خودکار مطلع بشه. این برای داده‌هایی که مرتب عوض می‌شن (مثل وضعیت سیستم یا لاگ‌ها) خیلی مفیده.

Prompt ترکیبی

Prompts می‌تونن از Resources و Tools داخل خودشون استفاده کنن. مثلاً Prompt «تحلیل هفتگی» اول Resource لیست نوت‌ها رو می‌خونه، بعد با دستورالعمل مناسب از AI می‌خواد تحلیلش کنه.

توضیحات واضح

برای هر سه قابلیت، توضیحات واضح و دقیق بنویس. AI از این توضیحات استفاده می‌کنه تا بفهمه کِی و چطور از هر قابلیت استفاده کنه. یه توضیح خوب باید بگه «چی‌کار می‌کنه» و «چه موقع استفاده بشه.»

چی یاد گرفتیم؟

این قسمت مفهومی‌ترین قسمت تا اینجا بود:

  • Resources: داده‌های فقط‌خواندنی که AI می‌تونه بخونه — ایمن و قابل cache
  • Prompts: الگوهای آماده تعامل — کیفیت خروجی AI رو استاندارد می‌کنن
  • تفکیک سه‌گانه: Tools برای عملیات، Resources برای خوندن، Prompts برای الگوها
  • URI: هر Resource یه آدرس یکتا داره
  • ResourceTemplate: برای Resourceهای پویا با پارامتر
  • Messages: Prompts آرایه‌ای از پیام‌ها برمی‌گردونن
قسمت بعدی
توی قسمت ۵: اتصال MCP به Claude و مدل‌های دیگه یاد می‌گیری چطور سرورت رو به مدل‌ها و اپلیکیشن‌های مختلف وصل کنی. از Claude Desktop تا VS Code، از API مستقیم تا Agent frameworkها. دنیای واقعی MCP اونجا شروع می‌شه!

نظرات

هنوز نظری ثبت نشده. اولین نفر باشید!

نظر خود را بنویسید