Phase 13: Tools & Protocols

حمل و نقل MCP: stdio و بدون دولت قابل پخش HTTP

حمل و نقل پیام های MCP را حمل می کند.2026-07-28، استودیو محلی و HTTP از راه دور Streamable هر دو درخواست های خود توصیف دارند.

Type: Learn

Languages: Python

Prerequisites: Phase 13, Lessons 07 and 08

Time: ~65 minutes

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

  • برای فرآیندهای محلی کودک استودیو و برای خدمات شبکه HTTP Streamable را انتخاب کنید.
  • اجرای قرارداد HTTP Streamable مدرن یک نقطه پایان، فقط POST.
  • آینه و اعتبار ورژن، روش و عنوان نام MCP را با بدن JSON-RPC تأیید کنید.
  • ارائه ی SSE به اندازه ی درخواست و عمر طولانیsubscriptions/listenبه طور درست جریان می دهد.
  • مهاجرت به پیاده سازی های HTTP+SSE مبتنی بر جلسه و قدیمی بدون ارائه رفتار قدیمی به عنوان مدرن.

مشکل

نسخه های قبلی Streamable HTTP مذاکره پروتکل را با رفتار اتصال و جلسه ترکیب می کردند. یک سرور می تواند mint Mcp-Session-Id, یک جریان GET مستقل را نشان می دهد, DELETE را برای پایان دادن به جلسه پذیرفته و SSE را با Last-Event-ID. .

MCP 2026-07-28هر درخواست می تواند بر روی هر کارگر سالم فرود آید زیرا نسخه پروتکل و قابلیت های مشتری آن در بدن درخواست حرکت می کنند. سرپرستی های HTTP زمینه های انتخاب شده را برای مسیریابی و سیاست منعکس می کنند، اما سرور قبل از اجرای آن آن سرپرستی ها را در برابر بدن تأیید می کند.

نتیجه آسان تر است که مقیاس پذیر شود و استدلال شود. این همچنین به این معنی است که یک سرور که حمل و نقل 2025 را به عنوان فعلی آموزش می دهد، مدل شکست و امنیت اشتباه را آموزش می دهد.

مفهوم

استودیو

اتصال استودیو برای یک فرعی که توسط مشتری راه اندازی می شود:

  • مشتری یک پیام UTF-8 JSON-RPC را در هر خط به stdin می نویسد.
  • سرور یک پیام UTF-8 JSON-RPC را در هر خط به stdout می نویسد.
  • سرور تشخیص رو به STDARR می نويسه
  • سرور فوراً از سیستم خارج می شه
  • هر درخواست مدرن دارای نسخه و قابلیت های مشتری در params._meta. .

این فرآیند ممکن است برای بسیاری از تماس ها زنده باشد، اما این یک جلسه پروتکل مدرن نیست. اگر غیر منتظره خارج شود، درخواست های در پرواز از دست می روند. فرآیند را دوباره شروع کنید، دوباره کشف کنید، لیست مجدد کنید، اشتراک ها را باز کنید و عملیات ایمن را با شناسه های درخواست جدید دوباره امتحان کنید.

HTTP قابل پخش در 2026-07-28

یک سرور مدرن یک نقطه پایان MCP را نشان می دهد، مانند /mcp، که پست رو قبول ميکنه

هر درخواست یا اطلاعیه JSON-RPC یک HTTP POST جدید است. بدن حاوی یک پیام JSON-RPC است. مشتریان پاسخ های JSON-RPC را به سرور ارسال نمی کنند.

برای یک درخواست، سرور یا به شما می گوید:

  • Content-Type: application/jsonبا یک پاسخ JSON-RPC؛ یا
  • Content-Type: text/event-streamبا اطلاعیه های مربوط به این درخواست، و سپس پاسخ نهایی JSON-RPC.

برای اطلاعیه قبول شده، سرور باز می گردد 202 Acceptedبدون جسد

مشتریان هر دو نوع پاسخ را تبلیغ می کنند:

httpAccept: application/json, text/event-stream

فقط POST به معنای فقط POST است

HTTP Streamable مدرن هیچ جریان GET مستقل و نقطه پایان جلسه DELETE ندارد.

  • GET /mcpبازپرداخت405 Method Not Allowed. .
  • DELETE /mcpبازپرداخت405 Method Not Allowed. .
  • Mcp-Session-Idکه هرگز به یاد نمی آید و هرگز به یاد نمی آید.
  • Last-Event-IDبه خاطر اینکه جریان های مدرن قابل تجدید نیستند نادیده گرفته می شود.

اگر یک جریان درخواست قبل از پاسخ نهایی از بین برود، مشتری درخواست در پرواز را از دست داده است. می تواند یک درخواست جدید را با یک شناسه JSON-RPC جدید صادر کند وقتی دوباره تلاش ایمن است. نباید تلاش برای بازخورد جریان کند.

اعتبار اعتبار اصل

سرورها تایید می کنندOriginدر ارتباط های ورودی برای جلوگیری از اتصال مجدد DNS. اگر سر و سر موجود باشد و به طور صریح اجازه داده نشده باشد، برگردید 403 Forbidden. یک مشتری غیر مرورگر ممکن است حذف کندOrigin، که قوانین رسمی حمل و نقل اجازه می دهد.

سرورهای محلی باید به 127.0.0.1. نه هر رابط . خدمات شبکه هنوز هم نیاز به تأیید و مجوز در هر درخواست . اعتبار اصل تایید نیست

با استفاده از مطابقت دقیق اصل پس از پیکربندی کانونیکی.origin.startswith("https://trusted.example")از اونجایی که می تونن ضمیر های کنترل شده توسط مهاجم رو قبول کنن

سرنخ های متادای HTTP مورد نیاز

هر درخواست جدید POST شامل:

httpMCP-Protocol-Version: 2026-07-28
Mcp-Method: tools/call
Mcp-Name: notes_search

قوانین عنوان:

  • MCP-Protocol-Versionلازم است و باید برابر باشدparams._meta.io.modelcontextprotocol/protocolVersion. .
  • Mcp-Methodمورد نیاز است و باید برابر JSON-RPC باشد method. .
  • Mcp-Nameبرای tools/call،resources/readوprompts/get. .
  • Mcp-Nameبرابر استparams.name، یاparams.uriبرایresources/read. .
  • ارزش های سر و کله ها نسبت به پرونده حساس هستند حتی اگر نام های سر و کله ها نسبت به پرونده حساس نباشند.

غیر امن یا غیر ASCII Mcp-Nameاز ارزش ها استفاده کنید UTF-8 Base64 Sentinel دقیق:

text=?base64?{Base64EncodedValue}?=

سرور قبل از مقایسه با بدن، این مقدار رو رمزنگاري ميکنه.

سرنخ های بازتاب شده گم شده، اشکال یافته یا نامتناسب HTTP را بازگردانید 400با کد JSON-RPC -32020اگر عنوان و بدن در یک نسخه که سرور پشتیبانی نمی کند موافق باشند، HTTP را برگردانید 400با-32022و اطلاعات اشتباه دقیق مانند {"supported":["2026-07-28"],"requested":"2027-01-01"}. .

یک روش مدرن ناشناخته HTTP را باز می گرداند 404با JSON-RPC -32601. جسم JSON-RPC مهم است زیرا یک مشتری دو دوره از آن برای تشخیص یک خطا مدرن از یک خطا پایانی قدیمی استفاده می کند.

SSE در مقیاس درخواست

یک سرور می تواند برای یک درخواست طولانی مدت SSE را انتخاب کند:

textPOST tools/call id=41
  <- notifications/progress related to id=41
  <- notifications/progress related to id=41
  <- JSON-RPC response id=41
stream closes

سرور نباید درخواست های JSON-RPC مستقل را در این جریان ارسال کند. نمونه گیری، جلب و جذب و تعاملات ریشه از نتایج درخواست چند دور استفاده می کنند. بسته شدن جریان پاسخ این درخواست را لغو می کند.

برای تکرار، شناسه های رویداد SSE را اضافه نکنید. Last-Event-IDبازپديد به نظر نمی رسد بخشی از تجدید نظر مدرن باشد.

تغییرات طولانی مدت استفاده از اشتراک / گوش دادن

اطلاعات تغییر از درخواست باز شده توسط مشتری استفاده می شود، نه GET مستقل:

json{
  "jsonrpc": "2.0",
  "id": "listen-1",
  "method": "subscriptions/listen",
  "params": {
    "notifications": {
      "toolsListChanged": true,
      "resourceSubscriptions": ["notes:TOK0
    },
    "_meta": {
      "io.modelcontextprotocol/protocolVersion": "2026-07-28",
      "io.modelcontextprotocol/clientCapabilities": {},
      "io.modelcontextprotocol/clientInfo": {
        "name": "course-client",
        "version": "1.0.0"
      }
    }
  }
}

پاسخ POST یک جریان SSE طولانی مدت است. اولین پیام پروتکل آنnotifications/subscriptions/acknowledged. تایید، هر اطلاعیه تغییر و نتیجه نهاییio.modelcontextprotocol/subscriptionIdدر_metaسرور ممکن است نظرات SSE را به عنوان نگهدارنده ارسال کند. وقتی جریان کاهش می یابد، مشتری دوباره ارسال می کند subscriptions/listenبا یک شناسه درخواست جدید و تغییر داده های تحت تاثیر قرار می گیرد.

resources/subscribeوresources/unsubscribeاز دوران میراث تعلق دارند. از آنها در ارتباط مدرن استفاده نکنید.

وضعیت درخواست صریح

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

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

شکست ناشی از حالت مخفي نقل مکانیک است:

  1. درخواست A به نسخه 1 می رسد و یک مسودۀ در حافظه آن فرآیند ایجاد می کند.
  2. پاسخ به یک مسودۀ دستی را باز نمی گرداند زیرا اجرای آن فرض می کند که ارتباط مسودۀ را شناسایی می کند.
  3. درخواست B یک POST تازه است و به نسخه 2 می رسد.
  4. نسخه 2 دارای متاداتا پروتکل معتبر است اما هیچ راهی برای نامگذاری یا بارگذاری طرح وجود ندارد، بنابراین جریان کار شکست می خورد یا شی محلی را اشتباه می خواند.
  5. به نظر می رسد مسیر چپکی علائم را حل می کند تا زمانی که یک بار دیگر شروع، راه اندازی، برنامه ریزی مجدد یا شکست مجدد درخواست بعدی را منتقل کند.

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

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

مطابقت دو عصر HTTP

یک مشتری که از سرورهای مدرن و قدیمی پشتیبانی می کند ابتدا یک POST مدرن را امتحان می کند. اگر HTTP دریافت کند 400،404، یا405، بدن رو بازرسي ميکنه:

  • یک خطا JSON-RPC مدرن شناخته شده ثابت می کند که سرور مدرن است. درخواست را اصلاح کنید یا نسخه تبلیغاتی را دوباره امتحان کنید. درجه بندی را کاهش ندهید.
  • یک جسم خالی یا پاسخ ناشناخته ممکن است یک سرور HTTP + SSE قدیمی را نشان دهد. فقط بعد از آن، نقطه پایان GET قدیمی را امتحان کنید و انتظار میراث آن را داشته باشید endpointرویداد

یک سرور می تواند از هر دو دوره در طول مهاجرت با هدایت متاداتا مدرن به پیاده سازی مدرن POST و حفظ نقاط پایان میراث جداگانه برای مشتریان قدیمی پشتیبانی کند. هرگز میراث GET، DELETE، session id یا رفتار بازیابی را به عنوان بخشی از 2026-07-28. .

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

code/main.pyیک سرور HTTP Streamable مدرن و محدود با کتابخانه استاندارد پایتون را اجرا می کند. این عنوان های اصلی و آینه ای را تأیید می کند، عنوان های جلسه حذف شده را نادیده می گیرد، JSON را برای تماس های عادی باز می کند و یک نامحدود را نشان می دهد subscriptions/listenجریان SSE

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

بررسی های سوند:

  • اصل باطل رد می شود؛
  • کشف بدون یک شناسه جلسه موفق می شود؛
  • Mcp-Session-IdوLast-Event-IDنادیده گرفته می شوند؛
  • بازده هاي نامناسب سر-32020؛
  • نسخه های غیر پشتیبانی شده بازمی گردد -32022با دقتsupportedوrequestedداده ها
  • یک اطلاعیه بدون هویت پذیرفته شده HTTP را بازمی گرداند 202بدون بدن
  • برگردان و حذف405؛
  • subscriptions/listenیک جریان پاسخ POST است که تایید، اطلاعیه ها و نتیجه نهایی آن دارای شناسه اشتراک است.

-باده

اين درس به ما ميگيرهoutputs/skill-mcp-transport-migrator.md. این جلسات پروتکل مدرن را حذف می کند، اعتبارسنجی های بدن سر را اضافه می کند، GET مستقل را با subscriptions/listen، و هر پل قدیمی را به طور قابل مشاهده جدا نگه می دارد

تمرینات

  1. حذف کنMcp-Methodاز یک POST. HTTP را تایید کنید 400و اشتباه-32020. .
  2. نسخه ي همبايد و همبايد ارسال کنيد 2027-01-01. HTTP رو تایید کن400، خطا-32022، و اطلاعات دقیق{"supported":["2026-07-28"],"requested":"2027-01-01"}. .
  3. يه نگهبان Base64 رو بفرستMcp-Nameبرای یک URI منابع غیر ASCII. تایید کنید که مقدار رمزگذاری شده با params.uri. .
  4. جریان گوش دادن محدود را قبل از پاسخ نهایی شکستن، با یک شناسه JSON-RPC جدید دوباره منتشر کنید و ابزار های بازنویسی را انجام دهید.
  5. یک دستی جریان کار صریح را به ابزار پینگ اضافه کنید. آن را به یک موضوع مجوز بدون استفاده از ارتباط ارتباط.

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

TermMeaning
stdioNewline-delimited JSON-RPC over a client-launched subprocess
Streamable HTTPSingle endpoint where each modern message is a new POST
Request-scoped SSEPOST response stream containing related notifications and final response
subscriptions/listenLong-lived POST request for opted-in change notifications
Header mismatchHTTP 400 and JSON-RPC -32020 when mirrored headers disagree with body
Origin validationDNS-rebinding defense for incoming connections, not authentication
Explicit state handleApplication token passed as an ordinary argument instead of hidden session state
Legacy bridgeSeparate earlier-era behavior kept only for compatibility

خواندن بیشتر

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.