Phase 13: Tools & Protocols

ساخت یک سرور MCP: پایتون بدون حالت و تایپ اسکریپت

یک سرور MCP مدرن دست دادن را به یاد نمی آورد. این متادتا را در هر درخواست تأیید می کند، یک دستیار را اجرا می کند و یک نتیجه تایپ شده را باز می گرداند.

Type: Build

Languages: Python, TypeScript

Prerequisites: Phase 13, Lesson 06

Time: ~85 minutes

اهداف یادگیری

  • اجرای اجباریserver/discoverبرای MCP 2026-07-28. .
  • نسخه پروتکل و قابلیت های مشتری را در هر درخواست تأیید کنید.
  • ابزارها، منابع و پیام ها را با ترتیب لیست تعیین کننده نشان دهید.
  • برگشتresultType، هویت سرور و اطلاعات مربوط به نتایج درست
  • به همان قرارداد بدون دولت در استودیو محدود خط جدید در پایتون و تایپ اسکریپت خدمت کنید.

مشکل

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

MCP 2026-07-28برنامه شما هنوز هم می تواند یادداشت های ماندگار، شغل ها یا دستی های حالت صریح را نگه دارد. آنچه که نمی تواند نگه دارد، حالت پروتکل پنهان است که نحوه رمزگذاری یک درخواست بعدی را تغییر می دهد.

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

مفهوم

حلقه جدید ارسال

textread one JSON-RPC line
parse the envelope
if it is a notification, do not respond
validate params._meta for this request
route by method
wrap success with resultType and serverInfo
write one JSON-RPC response line
forget request-scoped metadata

سه قانون استودیو هنوز مهمه:

  • فقط پيام JSON-RPC رو به stdout بنويسين.
  • پیام ها را با یک خط جدید تعریف کنید و هر پاسخ را به صورت آبی نشان دهید.
  • وقتي که ستدين به دفتر خارجيه برسه فوراً بيرون برو

طول عمر فرآیند یک طول عمر حمل و نقل است. این یک جلسه MCP مدرن نیست.

تایید درخواست

هر درخواست باید:

json{
  "params": {
    "_meta": {
      "io.modelcontextprotocol/protocolVersion": "2026-07-28",
      "io.modelcontextprotocol/clientCapabilities": {},
      "io.modelcontextprotocol/clientInfo": {
        "name": "notes-client",
        "version": "1.0.0"
      }
    }
  }
}

اولين دو ميدان مورد نياز است.clientInfoیک شکل هویت موجود را تأیید کنید، اما آن را به عنوان تأیید هویت نپذیرید.

اگر نسخه پشتیبانی نشده باشد، کد بازگشت را ارسال کنید-32022باrequestedوsupported. متاداتا درخواست گمشده ، پارام های باطل ، کد-32602هرگز از تماس قبلی به جا نبرید

کشف اجباری

سرورهای مدرن باید اجرا کنندserver/discover. یک نتیجه کشف کامل شامل نسخه های مدرن پشتیبانی شده، قابلیت ها، دستورالعمل های اختیاری، راهنمایی های کش و هویت سرور در نتیجه است _meta:

json{
  "resultType": "complete",
  "supportedVersions": ["2026-07-28"],
  "capabilities": {
    "tools": {"listChanged": false},
    "resources": {"listChanged": false, "subscribe": false},
    "prompts": {"listChanged": false}
  },
  "ttlMs": 3600000,
  "cacheScope": "public",
  "_meta": {
    "io.modelcontextprotocol/serverInfo": {
      "name": "notes-server",
      "version": "2.0.0"
    }
  }
}

دیسکوری سرور رو باز نمی کنه.tools/listبدون اینکه به کشف زنگ بزنم چونtools/listقبلاً همان متاداتا درخواست را در خود دارد.

ابزار

tools/listیک لیست تعیین کننده از توصیفات ابزار را باز می گرداند. ترتیب پایدار به بهبود حافظه پیشگیری پاسخ و حفظ ثبات زمینه مدل کمک می کند. نتیجه همچنین نیاز به ttlMsوcacheScope. .

tools/callبلوک های محتوا را بازمی گرداند وisError. هنگام عدم اعتبار بروکول یا پارامترهای روش، یک خطای JSON-RPC را استفاده کنید.isError: trueوقتی یک درخواست ابزار معتبر اجرا می شود اما خود ابزار شکست می خورد.

تشریحات ابزار به عنوان اشاره باقی می ماند، نه اجرای:

  • readOnlyHint
  • destructiveHint
  • idempotentHint
  • openWorldHint

میزبان باید از آنها برای تایید و ارائه استفاده کند. سرور باید هنوز مجوز واقعی را اجرا کند.

منابع

resources/listتوضیحات URI ثابت را باز می گرداند. resources/readمحتوای تایپ شده را باز می گرداند. هر دو در حافظه کش قابل ذخیره هستند2026-07-28، پس هر دو شاملttlMsوcacheScope. .

استفاده کنیدcacheScope: "private"برای اطلاعات یادداشت مخصوص کاربر. یک کش مشترک نباید از یک پاسخ خصوصی در زمینه های مجوز استفاده مجدد کند.

تحویل جدید تغییر استفاده نمی کندresources/subscribe. يه مشتري باز ميشهsubscriptions/listenو درخواست هاresourceSubscriptionsیا دسته بندی های تغییر لیست. درس 10 این جریان را ایجاد می کند.

پیام ها

prompts/listقابل پنهان کردن و تعیین کننده است.prompts/getیک پیامک نامگذاری شده با استدلال را ارائه می دهد. نتیجه پیامک ارائه شده کامل است، اما یکی از لیست های ذخیره سازی یا نتایج خواندن نیست که نیاز به اشاره های ذخیره سازی دارد.

هر نتیجه موفق به صورت تایپ شده

در مثال ها برای هر موفقیت یک بسته بندی استفاده می شود:

pythondef complete(payload):
    return {
        "resultType": "complete",
        **payload,
        "_meta": {SERVER_INFO_KEY: SERVER_INFO},
    }

لیست، خواندن و کشف دستیاران اضافه کنید ttlMsو اضافهcacheScope. مرکزي کردن اين بسته مانع از اينکه يک بازيگر خاموشي از حلقات نتيجه مدرن حذف کنه

هیچ درخواست از سوی سرور آغاز نشده

یک سرور مدرن می تواند اطلاعات مربوط به یک درخواست مشتری یا اطلاعات را در یک سرور باز شده توسط مشتری ارسال کند subscriptions/listen.این نباید درخواست JSON-RPC خود را ارسال کند

وقتی یک عامل نیاز به نمونه گیری، ایجاد یا ورود ریشه دارد، یک input_requiredنتیجه. مشتری درخواست های ورودی داخلی را برآورده می کند و روش اصلی را با یک ID درخواست جدید دوباره امتحان می کند. درس 11 این الگوی درخواست چند دور دور را پوشش می دهد.

مطابقت صریح میراث

یک سرور دو عصر نیز می تواند 2025-11-25دست زدن به شاخه ی میراث کاملاً جداگانه ای. رفتار مدرن را انتخاب می کند وقتی که نیاز به مدرن است._metaحاشیه ها در حال حاضر و در حال دریافت رفتار میراث هستند initialize. .

قرار ندهید2026-07-28درخواست از طریق مسیر دست دادن میراث.resultTypeکد در این درس به طور عمدی جدید است فقط به طوری که متغیرات آن باقی می ماند قابل مشاهده.

ازش استفاده کن

نمایش و تست های محدود سرور پایتون را اجرا کنید:

bashcd code
python3 main.py --demo
python3 -m unittest discover tests -v

پورت TypeScript را با یک نوع کاربری TypeScript اجرا کنید:

bashnpx tsx main.ts --demo

نمایش ارسال شدهserver/discoverدر هر درخواست مدرن متاداتا تکرار می شود. هر موفقیت شامل هویت سرور است.

-باده

اين درس به ما ميگيرهoutputs/skill-mcp-server-scaffolder.md. این یک برنامه سرور مدرن با قرارداد کشف، تأیید هر درخواست، لیست های تعیین کننده کش قابل، و یک آداپتور متمایز میراث اختیاری تولید می کند.

تمرینات

  1. قابلیت ها را از یک درخواست حذف کنید و ثابت کنید که سرور اعلامیه درخواست قبلی را مجددا استفاده نمی کند.
  2. برگردونيدTOOLS،PROMPTS، و ترتيب وارد کردن يادداشت. تمام نتایج فهرست ثابت باقی مانده است.
  3. يه تخريب دهنده اضافه کنnotes_deleteابزار و نیاز به چک مجوز در داخل اجرا کننده. نگه دارید destructiveHintفقط به عنوان یک اشاره UX.
  4. اضافه کردنresources/templates/listباttlMs،cacheScope، و نظم تعیین کننده
  5. یک آداپتور قدیمی جداگانه برای 2025-11-25. تست هاي جديد رو اضافه کنيد که ثابت کنه درخواست جديد هرگز واردش نميکنه

اصطلاحات کلیدی

TermMeaning
Stateless serverHandles each request from its own metadata without protocol-session memory
server/discoverMandatory modern method that advertises versions and capabilities
Complete resultSuccessful modern result with resultType: "complete"
Cacheable resultDiscovery, list, or resource-read result with ttlMs and cacheScope
Deterministic listSame logical registry produces the same item order
Server identityRecommended io.modelcontextprotocol/serverInfo in result _meta
Tool errorValid tool call that returns content with isError: true
Protocol errorInvalid JSON-RPC or MCP request returned through error

خواندن بیشتر

This free lesson is part of the AI Engineering from Scratch curriculum. Read the full explanation, run the lesson code, and verify the result in the interactive reader or from the repository source.

Browse the complete course catalog or open this lesson on GitHub.