اتصال مدلهای هوش مصنوعی به ابزارهای بیرونی مثل پایگاه داده، تقویم و سیستمهای فایلی، همواره نیازمند نوشتن لایههای چسبندهی اختصاصی برای احراز هویت، اعتبارسنجی ورودی و بستر انتقال بوده است. پروتکل کانتکست مدل (Model Context Protocol یا به اختصار MCP) این آشفتگی را با ارائهی یک لایهی ارتباطی استاندارد بر بستر JSON-RPC حل میکند تا هر میزبان بتواند ابزارها و منابع سرورها را مستقل از زبان پیادهسازی کشف و اجرا کند.
در نسخههای مدرن این استاندارد، مفهوم نشستهای سنتی و فاز دستدادن (Handshake) جای خود را به معماری بیوضعیت (Stateless) داده است. این تغییر به این معناست که تمام زمینهها، قابلیتها و نسخهی پروتکل در هر درخواست از نو ارسال میشوند؛ بنابراین نگهداری مقیاسپذیر سرورها در محیطهای میکروسرویسی و ابری بهمراتب سادهتر و قابلاتکاتر شده است.
در این درس یاد میگیرید که چگونه بدون اتکا به کتابخانههای واسط و صرفاً با پایتون استاندارد، سازههای اصلی سرور شامل ابزارها (Tools)، منابع (Resources) و پرامپتها را پیادهسازی کنید و پیامها را روی بسترهای stdio یا Streamable HTTP منتقل نمایید.
پروتکل MCP یک پروتکل واحد در اختیار میزبان هوش مصنوعی (AI host) میگذارد تا ابزارها، منابع (Resources) و پرامپتها را کشف و فراخوانی کند. بازنگری 2026-07-28 این پروتکل را بیوضعیت (Stateless) میکند: اطلاعات قابلیتها و نسخه همراه تکتک درخواستها فرستاده میشود، نه در قالب دستدادنی (Handshake) وابسته به اتصال.
اهداف یادگیری
- تمایز قائل شدن میان میزبان (Host)، کلاینت، سرور، بستر انتقال (Transport) و سازههای پایهی سرور در MCP.
- ساخت درخواست JSON-RPC همراه با متادیتای الزامی نسخه 2026-07-28 پروتکل MCP.
- استفاده از
server/discoverبرای بررسی نسخهها، هویت و قابلیتها. - بازگرداندن نتایج نوعدار و سازگار با کش از ابزارها، منابع و پرامپتها.
- توضیح نحوهی تعامل متقابل MCP مدرن و بیوضعیت با سرورهای دورهی دستدادن.
- تعیین مرزهای امن برای وضعیت، بستر انتقال و سازوکار تأیید در سرور.
صورت مسئله
برنامهی شما به یک کوئری پایگاه داده، یک عملیات تقویم و یک فایلخوان نیاز دارد. بدون یک پروتکل مشترک، هر میزبان هوش مصنوعی باید برای همین قابلیتها کد اختصاصیِ کشف، فراخوانی، مدیریت خطا، بستر انتقال و احراز هویت بنویسد.
پروتکل MCP این ماتریس یکپارچهسازی را کوچکتر میکند. سرور یک رابط استاندارد بر پایهی JSON-RPC ارائه میدهد. کلاینتِ سازگار با استاندارد میتواند این رابط را کشف کند، آن را به مدل یا کاربر نشان دهد، فراخوانیاش کند و بدون نیاز به آداپتور اختصاصی، نتیجه را تفسیر کند.
اما مرز باریکی این وسط هست که نباید از آن غافل شد: MCP فقط ارتباطات را استاندارد میکند. این پروتکل تعیین نمیکند که مدل باید کدام ابزار را صدا بزند، محتوای غیرقابلاعتماد را امن نمیکند و درخواست بیوضعیت را هم به وضعیت پایدار برنامه تبدیل نمیکند. این تصمیمها همچنان بر عهدهی میزبان و سرور شماست.
مفاهیم پایه
سه سازهی پایهی سرور
- ابزارها (Tools): اکشنهای قابل فراخوانی هستند. هر ابزار یک نام، توضیحات، ورودی مبتنی بر JSON Schema و یک هندلر (Handler) دارد.
- منابع (Resources): محتواهای نامگذاریشده با آدرس URI هستند که کلاینت میتواند آنها را بخواند.
- پرامپتها (Prompts): قالبهای چندبارمصرفی هستند که میزبان میتواند به کاربر ارائه دهد.
میزبان همان برنامهی هوش مصنوعی است. کلاینت MCP درون آن میزبان قرار دارد و با یک سرور صحبت میکند. بستر انتقال هم پیامهای JSON-RPC را میان آنها جابهجا میکند.
جایگزینی دستدادن با درخواستهای بیوضعیت
نسخه 2026-07-28 پروتکل MCP متدهای initialize و notifications/initialized را حذف کرده است. نشستهای سطح پروتکل هم کنار رفتهاند. حالا هر درخواست، زمینهی لازم برای تفسیر خود را درون params._meta به همراه دارد:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list",
"params": {
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientCapabilities": {},
"io.modelcontextprotocol/clientInfo": {
"name": "lesson-client",
"version": "1.0.0"
}
}
}
}
نسخهی پروتکل و قابلیتهای کلاینت الزامی هستند؛ درج هویت کلاینت هم پیشنهاد میشود. اگر _meta یا یکی از فیلدهای الزامی وجود نداشته باشد، یا فیلد الزامی از نوع دادهی اشتباهی باشد، درخواست بدقواره (Malformed) به حساب میآید و خطای Invalid Params با کد -32602 برمیگرداند. اگر رشتهی نسخه ساختار درستی داشته باشد اما سرور از آن پشتیبانی نکند، خطای UnsupportedProtocolVersionError با کد -32022 برمیگردد. بنابراین سرور میتواند یک درخواست معتبر را بدون بازیابی سوابق مذاکرات پیشین پردازش کند.
بیوضعیت بودن به این معنا نیست که برنامه اصلاً نمیتواند وضعیتی نگه دارد؛ بلکه وضعیت دیگر پشت اتصال MCP یا Mcp-Session-Id پنهان نمیشود. اگر جریان کاری نیاز به تداوم دارد، سرور یک شناسهی مات (Opaque handle) تولید میکند و کلاینت در فراخوانیهای بعدی، آن را مثل یک آرگومان معمولیِ ابزار ارسال میکند. مجوزها هم باید در تکتک درخواستها بررسی شوند.
کشف و انتخاب نسخه
تمام سرورهای مدرن متد server/discover را پیادهسازی میکنند. خروجی این متد، نسخههای پشتیبانیشده، قابلیتها و هویت سرور را اعلان میکند:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"resultType": "complete",
"supportedVersions": ["2026-07-28"],
"capabilities": {
"tools": {},
"resources": {},
"prompts": {}
},
"ttlMs": 3600000,
"cacheScope": "public",
"_meta": {
"io.modelcontextprotocol/serverInfo": {
"name": "demo-server",
"version": "1.0.0"
}
}
}
}
کلاینت میتواند یک متد دیگر را مستقیماً فراخوانی کند و خطای نسخه را مدیریت کند، اما کشف اولیه باعث میشود نمایش قابلیتها و انتخاب نسخه صریح و شفاف باشد. اگر نسخه پشتیبانی نشود، خطای UnsupportedProtocolVersionError با کد -32022 برمیگردد. دادههای این خطا شامل آرایهای از نسخههای سرور در فیلد supported و نسخهی ردشده در فیلد requested است.
در ارتباط از طریق stdio، کلاینتِ سازگار با هر دو دوره ابتدا با server/discover وضعیت سرور را میسنجد. دریافت نتیجهی کشف یا یکی از خطاهای شناختهشدهی مدرن مثل UnsupportedProtocolVersionError نشان میدهد سرور مدرن است. هر خطای ناشناخته یا هرگونه تایماوت، امکان عقبگرد به روند initialize نسخهی 2025-11-25 را فراهم میکند. رفتارهای دورهی پیشین صرفاً کدهای سازگاری هستند، نه رفتار پیشفرضِ مدرن.
صریح بودن نتایج
تمام نتایج اصلی در نسخه 2026-07-28 فیلد resultType دارند:
- مقدار
completeیعنی عملیات به پایان رسیده است. - مقدار
input_requiredیعنی سرور طبق الگوی «درخواستهای چند دوررفت» (Multi Round-Trip Requests) به رفتوبرگشت دیگری نیاز دارد. سرورهای اصلی فقط در پاسخ بهtools/call،resources/readیاprompts/getمجاز به بازگرداندن این مقدار هستند.
کلاینتها باید پاسخهای قدیمیتر را که فاقد resultType هستند، کامل تلقی کنند.
سرورها باید مقدار io.modelcontextprotocol/serverInfo را در _metaی تمام نتایج قرار دهند. این هویت خوداظهاری است و فقط برای نمایش، لاگگیری و دیباگ کاربرد دارد، نه تصمیمگیریهای امنیتی.
نتایج فهرستگیری و خواندن، فیلدهای ttlMs و cacheScope را هم به همراه دارند. ترتیب قطعی در tools/list به همراه یک راهنمای تازگی داده، به کلاینتها اجازه میدهد نتایج کشف را با اطمینان کش کنند و پایداری پرامپتکش (Prompt cache) را بالا ببرند. مقدار cacheScope: public امکان کش مشترک را میدهد؛ مقدار private استفادهی مجدد را به همان دامنهی فراخوانی محدود میکند.
ساختار تبادل داده و بستر ارتباطی
پروتکل MCP از استاندارد JSON-RPC 2.0 روی stdio یا Streamable HTTP استفاده میکند.
- هر درخواست شامل
jsonrpc،id،methodوparamsاست. - هر پاسخ شامل همان
idمتناظر و یکی از دو فیلدresultیاerrorاست. - اعلانها (Notifications) فاقد
idهستند و پاسخی هم انتظار نمیکشند.
در Streamable HTTP مدرن، یک اندپوینت وجود دارد که فقط POST میپذیرد. هر پیام JSON-RPC با یک درخواست POST جداگانه فرستاده میشود. درخواست POST یا یک شیء تکیِ JSON دریافت میکند یا یک استریم Server-Sent Events در دامنهی همان درخواست، که با پاسخ نهایی به پایان میرسد. اعلانهای پذیرفتهشده کد HTTP 202 بدون بدنهی پاسخ میگیرند؛ در بازنگری اصلی این نسخه هیچ اعلانی از سمت کلاینت به سرور روی Streamable HTTP تعریف نشده است.
در نسخه 2026-07-28 چیزی به اسم استریم مستقلِ GET، اندپوینت DELETE برای نشست، Mcp-Session-Id یا بازپخش با Last-Event-ID وجود ندارد. اعلانهای تغییراتِ طولانیمدت با یک POST به subscriptions/listen فعال میشوند که پاسخ آن بهصورت یک استریم SSE باز میماند.
دریافت ورودی از کلاینت بدون درخواست از سمت سرور
در نسخههای پیشین، سرور میتوانست درخواستهایی مثل sampling/createMessage، roots/list یا elicitation/create را روی استریم ارسال کند. در پروتکل فعلی، بهجای این کار از الگوی Multi Round-Trip Requests استفاده میشود. فراخوانی ابزار، خواندن منبع یا دریافت پرامپتِ واجد شرایط، resultType: input_required را همراه با حداقل یکی از فیلدهای inputRequests یا requestState برمیگرداند. کلاینت ورودیهای خواستهشده را جمعآوری میکند، متد اصلی را با یک شناسه JSON-RPC جدید و پاسخهای متناظر در inputResponses مجدداً فرامیخواند و اگر مقدار requestState داده شده بود، دقیقاً همان را تکرار میکند. اگر فیلد inputRequests وجود نداشت، در فراخوانی مجدد نیازی به ارسال inputResponses نیست.
قابلیتهای Roots، Sampling و Logging هنوز کار میکنند اما منسوخ (Deprecated) شدهاند؛ بنابراین پیادهسازیهای جدید نباید سراغ آنها بروند. درخواستهای فعلی Roots یا Sampling داخل inputRequests در الگوی MRTR ردوبدل میشوند و هرگز بهصورت درخواست مستقلِ JSON-RPC از سرور به کلاینت فرستاده نمیشوند. بهتر است از پارامترهای صریح فایل یا دایرکتوری، URIهای منابع، پیکربندی سرور و اتصال مستقیم به ارائهدهندهی مدل استفاده کنید. برای خطایابی در stdio از stderr و برای تلهمتری محیط پروداکشن از OpenTelemetry استفاده کنید.
پیادهسازی گامبهگام
مرحلهی 1: ثبت رابط سرور
با وجود تغییر قرارداد درخواستها، ثبت متدها همچنان ساده است:
server = MCPServer("demo-server")
@server.tool(
"add",
"Add two integers.",
{
"type": "object",
"properties": {
"a": {"type": "integer"},
"b": {"type": "integer"}
},
"required": ["a", "b"]
}
)
def add(a: int, b: int) -> dict:
return {"sum": a + b}
پیادهسازی ارائهشده در code/main.py یک منبع و یک پرامپت را هم ثبت میکند. این کد عمداً با کتابخانهی استاندارد نوشته شده تا بستهبندی پیامها را مستقیم ببینید و متکی به SDK نباشید.
مرحلهی 2: الصاق متادیتا به تکتک درخواستها
def request(method, params=None):
body_params = dict(params or {})
body_params["_meta"] = {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientCapabilities": {},
"io.modelcontextprotocol/clientInfo": {
"name": "demo-client",
"version": "1.0.0"
}
}
return {
"jsonrpc": "2.0",
"id": 1,
"method": method,
"params": body_params
}
این متادیتا را فقط در آبجکت اتصال کش نکنید؛ سرور در هر درخواست آن را اعتبارسنجی میکند.
مرحلهی 3: کشف قابلیتها پیش از فهرستگیری (اختیاری)
متد server/discover را صدا بزنید، یکی از نسخههای پشتیبانیشده را انتخاب کنید و سپس سراغ tools/list بروید. اگر نسخه را از قبل میدانید و خطای -32022 را مدیریت کردهاید، فراخوانی مستقیم tools/list هم کاملاً درست است.
کد نمونه فهرست ابزارها را به ترتیب الفبا برمیگرداند و مقادیر ttlMs، cacheScope، resultType و هویت سرور را هم پیوست میکند. فراخوانی ابزار خروجی کامل و غیرقابلکشی برمیگرداند، چون نتیجه میتواند به وضعیت فعلی سیستم وابسته باشد.
مرحلهی 4: نگاشت همان درخواست روی پروتکل HTTP
درخواست POST به یک مخزن راهدور (Remote) برای tools/call شامل هدرهایی است که بدنهی JSON-RPC را منعکس میکنند:
POST /mcp HTTP/1.1
Content-Type: application/json
Accept: application/json, text/event-stream
MCP-Protocol-Version: 2026-07-28
Mcp-Method: tools/call
Mcp-Name: add
هدر MCP-Protocol-Version باید دقیقاً با نسخهی درون _meta یکی باشد. هدر Mcp-Method در تمام درخواستهای JSON-RPC الزامی است و باید با method مطابقت داشته باشد. هدر Mcp-Name فقط برای tools/call، resources/read و prompts/get الزامی است و مقدارش باید با نام ابزار، URI منبع یا نام پرامپت یکی باشد. اگر هدری جا بماند یا عدم تطابق وجود داشته باشد، پاسخ HTTP 400 با کد خطای HeaderMismatch یا همان -32020 برمیگردد.
مرحلهی 5: اعمال تمهیدات امنیتی فراتر از وضعیت پروتکل
- مجوزها و مخاطبان (Audience) را روی تکتک درخواستهای HTTP اعتبارسنجی کنید.
- سرورهای محلی را فقط به localhost متصل کنید و مقدار
Originرا روی Streamable HTTP بسنجید. - ابزارهای تغییردهندهی وضعیت را با
destructiveHint: trueمشخص کنید و از میزبان تأییدیه بخواهید. - بهجای اتکا به قابلیت منسوخشدهی Roots، دامنهی دسترسی به فایلها و دایرکتوریها را صریح ارسال کنید.
- محتوای منابع و خروجی ابزارها را دادهی غیرقابلاعتماد در نظر بگیرید.
- در stdio، خروجی stdout را منحصراً به پیامهای JSON-RPC اختصاص دهید و لاگهای دیباگ را به stderr بفرستید.
اجرای عملی
این درس را از دایرکتوری خودش اجرا کنید:
python3 code/main.py
cd code
python3 -m unittest discover tests -v
خط اول باید کشف demo-server روی پروتکل 2026-07-28 را گزارش کند. سپس متد MCPClient.request را بررسی کنید: این متد فیلد _meta را برای تکتک فراخوانیها بازسازی میکند. این متادیتا را از یکی از درخواستها بردارید و ببینید سرور چطور آن را رد میکند.
تحویل پروژه
فایل outputs/skill-mcp-server-designer.md هر دامنهی کاری را به یک طرح MCP بیوضعیت تبدیل میکند. معیارهای پذیرش آن شامل خروجی کشف سرور، سیاست متادیتای هر درخواست، فهرستهای قطعی و سازگار با کش، شناسههای صریح وضعیت، هدرهای بستر انتقال و قوانین احراز هویت و تأییدیه است.
ادامهی مسیر یادگیری عمیق MCP
این درس مدل کلی پروتکل را نشان داد. در بخش 13، چهار مرز آمادهسازی برای پروداکشن را در قالب درسهای مستقلِ پیادهسازی و ارزیابی بررسی میکنیم:
- قراردادهای ابزار و محتوا در MCP: به بررسی اسکیماهای ورودی بسته، محتوای ساختاریافته، متادیتای مسیریابی، صفحهبندی با شناسههای مات، مجوز تکمیل و تفاوت خطاهای سطح پروتکل با خطاهای دامنهی ابزار میپردازد.
- قابلیت اطمینان، لغو عملیات و کنترل جریان در MCP: موضوعاتی مثل لغو درخواست، لغو کارهای طولانیمدت، مهلتهای زمانی (Deadlines)، ویژگی چندباراجرایی (Idempotency)، پسزدگی (Backpressure)، بافرینگ پروکسی و رفتار در زمان اتصال مجدد را پوشش میدهد.
- زنجیرهی تأمین رجیستری MCP، پذیرش، انحراف و بازگردانی: شامل اثبات فضای نام، منشأ و سندیت مصنوعات، قفل کردن نسخههای تغییرناپذیر، انحراف در لحظه، وضعیت رجیستری، شواهد پذیرش و بازگردانی (Rollback) میشود.
- مهندسی انطباق در MCP: به بررسی رونوشتهای استاندارد و ناموفق شبکه، دورههای زمانی سختگیرانهی نسخهها، تفاوتهای SDKها، شواهد پروکسی، پنهانسازی دادههای حساس، معیارهای ارزیابی سلامت و بازگردانی نسخهها میپردازد.
وقتی قرار است سرور از مرز تیمها عبور کند یا به محیطهای غیرقابلاعتماد برود، این درسها را به ترتیب دنبال کنید. این مجموعه شما را از سطح «متد به درستی کار میکند» به سطح «قرارداد در تمام مراحل استقرار، امن و قابلردیابی باقی میماند» میرساند.
تمرینها
- ابزار
subtractرا اضافه کنید و مطمئن شوید خروجیtools/listهمچنان طبق حروف الفبا مرتب میماند. - کلید protocol-version را حذف کنید و مطمئن شوید خطای Invalid Params با کد
-32602برمیگردد. سپس نسخهی معتبر ولی پشتیبانینشدهی2025-11-25را بفرستید؛ خطای-32022را بررسی کنید و ببینید مقدارrequestedهمان نسخه را بازمیگرداند یا خیر، و یکی از مقادیرsupportedرا انتخاب کنید. - یک شناسهی
draftIdساختهشده توسط سرور به عملیات ساخت اضافه کنید و ارائهی آن را برای بهروزرسانی اجباری کنید. توضیح دهید چرا این شناسه، وضعیت برنامه محسوب میشود نه نشست پروتکل. - در ابزاری که نیاز به تأیید کاربر دارد، مقدار
input_requiredبرگردانید. بهجای ارسال یک درخواست جداگانهی JSON-RPC از سرور به کلاینت، فراخوانی اولیه را با یک ID جدید، ورودیinputResponsesو مقدار دقیقrequestStateتکرار کنید. - ساختار یک کلاینت stdio سازگار با هر دو دوره را طراحی کنید؛ طوری که نتیجه یا خطاهای شناختهشدهی مدرن را به عنوان سرور مدرن بشناسد و بازگشت به
initializeرا فقط برای خطاهای ناشناخته یا تایماوت مجاز بداند.
اصطلاحات کلیدی
| اصطلاح | معنای عامیانه | معنای دقیق فنی |
|---|---|---|
| MCP | «پروتکل ابزار برای مدلهای زبانی» | پروتکل JSON-RPC برای کشف سرور، ابزارها، منابع، پرامپتها و افزونهها |
| Host | «برنامهی هوش مصنوعی» | مالک مدل و رابط کاربری که یک یا چند کلاینت MCP را اجرا میکند |
| Client | «اتصالدهنده» | رابطی که از طرف میزبان با یک سرور MCP صحبت میکند |
| Stateless MCP | «بدون نشست» | هر درخواست، نسخه و قابلیتها را در بر دارد؛ هیچ وضعیتی در پروتکل بر پایهی یک اتصال ذخیره نمیشود |
server/discover |
«ارزیابی قابلیتها» | متد الزامی سرور برای اعلام نسخهها، قابلیتها و هویت |
resultType |
«وضعیت نتیجه» | وضعیت نتیجه را با complete یا input_required مشخص میکند |
| State handle | «شناسهی ورکفلو» | شناسهی تولیدشده توسط سرور برای برنامه که مثل یک آرگومان عادی فرستاده میشود |
| Streamable HTTP | «بستر انتقال راهدور» | یک اندپوینت POST منفرد با پاسخهای JSON یا استریم SSE متصل به همان درخواست |
| MRTR | «پرسش و تلاش مجدد» | درخواست دریافت ورودی تعبیهشده درون نتیجه، و به دنبال آن تکرار عملیات اصلی |
