منابع و پیام های MCP: زمینه قابل آدرس برای سرورهای بی تابعیت
Type: Build
Languages: Python
Prerequisites: Phase 13, Lesson 07 (Building an MCP Server), Phase 13, Lesson 09 (MCP Transports)
Time: ~60 minutes
اهداف یادگیری
- از میان ابزارها، منابع و خواسته های مصرف کننده انتخاب کنید.
- تبلیغات منابع و سطح فوری از طریق اجباری
server/discover. . - ساخت دترمنست
resources/listوprompts/listنتایج - درخواست کنید
ttlMsوcacheScopeبدون اینکه اطلاعات مربوط به کاربر به دست آید. - خطا JSON-RPC را بازگردانید
-32602برای یک URI منبع ناشناخته یا ناشناخته. - یه رو باز کن
subscriptions/listenجریان پاسخ POST و ارتباط هر رویداد با شناسه اشتراک. - محتوای منابع و قالب های فوری را به عنوان خروجی سرور غیرقابل اعتماد در نظر بگیرید.
از مصرف کننده شروع کنید
ساده ترین راه برای سوء استفاده از MCP شروع با کد پیاده سازی است. یک سوال پایگاه داده به یک ابزار تبدیل می شود زیرا عملکردها آشنا هستند. یک جریان کار قابل استفاده مجدد به یک منبع تبدیل می شود زیرا در یک فایل ذخیره می شود. یک پرامپت تبدیل به سیاست پنهان می شود زیرا میزبان می تواند آن را تزریق کند.
با انتخاب چه کسی و انتظار چه چیزی شروع کنید.
| Primitive | Primary intent | Selection owner | Typical result |
|---|---|---|---|
| Tool | Perform an operation | Model or application | Structured action result |
| Resource | Read content at a URI | Host, application, or user | Text or binary content |
| Prompt | Start a reusable message workflow | User through host UI | One or more prompt messages |
يه يادداشت درnotes://note-1یک منبع است زیرا محتوای قابل ادریس است. delete_noteاین ابزار است چون وضعیت را تغییر می دهد.review_noteیک پیامک است زیرا کاربر یک جریان کار بررسی آماده را انتخاب می کند.
هر سطح اضافی نیاز به کشف، مجوز، ذخیره سازی، مدیریت خطا، آزمایش و اسناد دارد.
پاکت بی شهروند 2026-07-28
این درس به بررسی پروتکل MCP هدفمند است2026-07-28. هیچ دست دادن اولیه یا جلسه پروتکل در این پروفایل وجود ندارد. هر درخواست نسخه پروتکل و قابلیت های مشتری خود را در زیر محفوظ دارد _metaکليدها
json{
"jsonrpc": "2.0",
"id": 1,
"method": "resources/list",
"params": {
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientInfo": {
"name": "course-client",
"version": "1.0.0"
},
"io.modelcontextprotocol/clientCapabilities": {}
}
}
}یک سرور باید اجرا کندserver/discover. نتایجش اعلامیه حمایت شده
نسخه ها، قابلیت های منابع و پرامپ، هویت پیاده سازی و
یک مشتری ممکن است به طور مستقیم به روش دیگری زنگ بزند، اما کشف به آن می دهد
یک عکس ثابت قبل از اینکه یک UI بسازد.
json{
"resultType": "complete",
"supportedVersions": ["2026-07-28"],
"capabilities": {
"resources": {"listChanged": true, "subscribe": true},
"prompts": {"listChanged": true}
},
"ttlMs": 3600000,
"cacheScope": "public"
}نتیجه ی عادی اعلام می شود"resultType": "complete". پاسخ_metaاجرای خدمت را با io.modelcontextprotocol/serverInfoاین اطلاعات برای تشخیص مفید است. این یک هویت معتبر نیست. یک درخواست که دارای یک بررسی غیر پشتیبانی شده است، باز می گردد.-32022با هم تجدید نظر مورد نیاز و هم تجدید نظر های پشتیبانی شده سرور.
قرارداد بی تابعیت غریزه های طراحی شما را تغییر می دهد. یک لیست نمی تواند به تماس قبلی در یک اتصال بستگی داشته باشد. مجوز ممکن است مجموعه قابل مشاهده را تغییر دهد زیرا اعتبارها ورودی درخواست هستند، اما تاریخچه اتصال نباید باشد.
منابع قراردادهای ثابت URI هستند
یک منبع محتوا است که توسط یک URI شناسایی می شود. URI را قبل از دستیار طراحی کنید.
خواص URI خوب:
- به اندازه کافی ثابت برای نشان دادن کتاب یا عبور بین درخواست ها
- نامي به دامنه سرور منتقل شده
- مستقل از یک شناسه فرآیند یا اتصال.
- قبل از دسترسی به ذخیره سازی تایید شده است.
- هر بار که بخونم مجوز دارم
notes://note-1بهتره ازnote-1چون فضای نامش صریحه. یک سرور فایل ممکن است از file://URI ها، اما هنوز باید بعد از حل لینک های متمایز و بخش های نسبی، مرز های دایرکتوری های پیکربندی شده را بررسی کند.
resources/listدر حال حاضر به کالر قابل مشاهده است. با یک کلید ثابت مانند URI مرتب می شود. ترتیب تعیین کننده از از دست دادن کش های سر و صدا، تغییر عکس ها و UI های میزبان که بین بروزرسانی ها پر می شوند جلوگیری می کند.
json{
"resultType": "complete",
"resources": [
{
"uri": "notes: TOK0
"name": "Architecture decision",
"description": "Why the service uses a stateless boundary",
"mimeType": "text/markdown"
}
],
"ttlMs": 300000,
"cacheScope": "public",
"_meta": {
"io.modelcontextprotocol/serverInfo": {
"name": "notes-server",
"version": "2.0.0"
}
}
}resources/readیک یا چند عنصر محتوا را باز می گرداند. یک URI ناشناخته یک خواندن خالی موفق نیست. مشخصات فعلی منابع، URI های ناشناخته یا ناشناخته را به پارامترهای ناشناخته JSON-RPC اختصاص می دهد.-32602. .
json{
"jsonrpc": "2.0",
"id": 2,
"error": {
"code": -32602,
"message": "Unknown or invalid resource URI",
"data": {
"uri": "notes://missing"
}
}
}این تفاوت به یک مشتری اجازه می دهد که غیبت را از یک سند خالی معتبر جدا کند. همچنین از سقوط تصادفی به جستجوی گسترده تر جلوگیری می کند.
قالب منابع
یک قالب منابع یک خانواده از URI های پارامتر شده را توصیف می کند. هنگام فهرست کردن هر قطعه مشخصی با هزینه یا محدودیت استفاده کنید. به عنوان مثال، notes://projects/{project}/decisions/{decision}به مشتری میگه چطور آدرس معتبر را بدون بازگشت هر تصمیم درست کند.
یک قالب اعتبارسنجی را ضعیف نمی کند. متغیرات را تجزیه و تحلیل کنید، مجوز را اعمال کنید، محدودیت های طول و کاراکتر را اجرا کنید و سوالات ذخیره سازی را با پارامترهای تایپ شده بسازید. هرگز یک دم URI تعسفی را به یک مسیر فایل سیستم یا بیانیه پایگاه داده متصل نکنید.
محتوا دستورالعمل قابل اعتماد نیست
متن منابع ممکن است شامل تزریق فوری، اسرار، دستورات گمراه کننده یا مارکاپ اشتباه باشد. میزبان باید منبع منبع را حفظ کند و محتوای منابع را به عنوان داده ها در نظر بگیرد. سرور باید اندازه محتوای را محدود کند، یک نوع MIME دقیق را بازگرداند، زمینه هایی را که تماس گیرنده نمی تواند به آنها دسترسی داشته باشد، و از بازگردانیدن سوابق مرتبط اجتناب کند.
پیام ها قالب های کنترل شده توسط کاربر هستند
پیام های MCP برای انتخاب صریح کاربر طراحی شده اند. یک میزبان می تواند آنها را به عنوان دستورات برش، عناصر مینو یا دکمه های جریان کار ارائه دهد. پروتکل نیازی به یک UI ندارد.
prompts/listهر پرامپت نیاز به یک نام ثابت، یک توصیف مفید و اظهارات استدلال دارد که اجازه می دهد میزبان واردات را قبل از جمع آوری کند.prompts/get. .
json{
"resultType": "complete",
"prompts": [
{
"name": "review_note",
"title": "Review a note",
"description": "Review one note for a named concern",
"arguments": [
{
"name": "uri",
"description": "The note resource URI",
"required": true
}
]
}
],
"ttlMs": 600000,
"cacheScope": "public"
}prompts/getاین برنامه جایگزین دستورالعمل های سیستم میزبان نمی شود. میزبان تصمیم می گیرد که چگونه پیام های بازگردانده شده به زمینه مدل وارد می شوند و سیاست های مورد اعتماد خود را اولویت بیشتری می دهد.
استدلال های پرامپت را در مرز سرور تأیید کنید. یک URI پرامپت باید همان چک مجوز را مانند خواندن منابع مستقیم عبور دهد. یک پرامپت را یک کانال جانبی در اطراف دسترسی به منابع قرار ندهید.
نشانه های ذخیره سازی بخشی از درستی هستند
ttlMsبه مشتری می گوید که چه مدت می تواند نتیجه را دوباره استفاده کند. cacheScopeشرح می دهد که چه کسی می تواند این ارزش ذخیره شده را به اشتراک بگذارد.
| Scope | Meaning | Typical use |
|---|---|---|
public | May be reused across users when authorization permits | Public prompt catalog |
private | Bound to the requesting user or credential context | User-owned note content |
از نرخ تغییر داده ها و آسیب تاخیر یک TTL را انتخاب کنید. پنج دقیقه ممکن است برای یک کاتالوگ عمومی مناسب باشد. یک یادداشت خصوصی ممکن است یک دقیقه را مصرف کند.
MCP فقط تعریف می کندpublicوprivateمثلcacheScopeبرای یک نتیجه مخفی یا تغییر سریع، بازگشتcacheScope: "private"باttlMs: 0، سپس هر قاعده سخت تر از فروشگاه در سيستم حافظه ي مهمان را اعمال کنید.no-storeخودش یک MCP نیستcacheScopeارزش
اشاره های کیش هرگز جایگزین مجوز نمی شوند. کلید کیش باید شامل هر ابعاد درخواست ای باشد که بینایی را تغییر دهد، از جمله مستاجر، کاربر، دامنه، محل و کرسر صفحه بندی. اگر یک کیش مشترک نمی تواند این ابعاد را به طور ایمن بیان کند، از privateبا صفر TTL و سیاست بدون فروشگاه در سطح میزبان.
اشتراک ها از یک جریان پاسخ مشتری باز استفاده کنید
مدل جدید اشتراک جایگزین مدل قبلی می شودresources/subscribeRPC و نقطه پایان رویداد HTTP GET قدیمی
مشتری ارسال کردsubscriptions/listenدر HTTP Streamable این یک POST است که پاسخ آن به عنوان یک جریان SSE باز باقی می ماند.notificationsیک سرور نباید انواع اطلاعیه هایی را که درخواست نشده اند ارسال کند.
json{
"jsonrpc": "2.0",
"id": 17,
"method": "subscriptions/listen",
"params": {
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientCapabilities": {},
"io.modelcontextprotocol/clientInfo": {
"name": "course-client",
"version": "1.0.0"
}
},
"notifications": {
"resourcesListChanged": true,
"promptsListChanged": true,
"resourceSubscriptions": [
"notes://note-1"
]
}
}
}ID درخواست، ID اشتراک است. قبل از هر رویداد درخواست شده، سرور ارسال می کند notifications/subscriptions/acknowledgedفیلترش فقط زیر مجموعه ای را که سرور قبول کرده است، دارد.
json{
"jsonrpc": "2.0",
"method": "notifications/subscriptions/acknowledged",
"params": {
"_meta": {
"io.modelcontextprotocol/subscriptionId": 17
},
"notifications": {
"resourcesListChanged": true,
"resourceSubscriptions": [
"notes://note-1"
]
}
}
}هر اتفاق بعد در آن جریان همان متادتا را دارد.
json{
"jsonrpc": "2.0",
"method": "notifications/resources/updated",
"params": {
"_meta": {
"io.modelcontextprotocol/subscriptionId": 17
},
"uri": "notes://note-1"
}
}اطلاعیه میگه که منبع تغییر کرده است.resources/readاین موضوع به این معنا نیست که این رویداد حاوی سند جدید است.
چندین اشتراک می تواند یک کانال استودیو را به اشتراک بگذارد. شناسه اشتراک اجازه می دهد تا مشتری آنها را از هم جدا کند. در HTTP، بسته شدن جریان پاسخ اشتراک را لغو می کند. سرور که جریان را با زیبایی به پایان می رساند، یک نهایی را باز می گرداند.resultType: "complete"پاسخ مربوط به درخواست اصلی.
از یک جریان اشتراک به عنوان یک جلسه پروتکل استفاده نکنید. خواندن بعد هنوز یک درخواست کامل است که می تواند به هر نمونه سرور سالم برسد.
آزمایشگاه تعاملی
با استفاده از این شکل برای طبقه بندی پنج قابلیت از یک ردیاب پروژه: جزئیات مسئله، ایجاد مسئله، قالب بررسی اسپرنت، سیاست پروژه و مشکل بسته. سپس تصمیم بگیرید که کدام لیست ها می توانند به صورت عمومی ذخیره شوند، کدام لیست باید خصوصی بماند و کدام منابع شایسته اطلاعیه های به روزرسانی هستند.
برای هر طبقه بندی، نام انتخاب کننده را نام دهید. اگر مدل یک عمل انجام دهد، از یک ابزار استفاده کنید. اگر میزبان محتوای URI را می خواند، از یک منبع استفاده کنید. اگر کاربر یک جریان کار پیام آماده را شروع کند، از یک پرامپت استفاده کنید.
آزمایشگاه تمرین
شبیه ساز را از ریشه مخزن اجرا کنید:
bashcd phases/13-tools-and-protocols/10-mcp-resources-and-prompts/code
python3 main.py
python3 -m unittest discover tests -vاز نقل نامه به اين ترتيب بررسي کنيد:
- تایید کن
server/discoverبه نظر می رسد که این برنامه به طور کامل به نظر می رسد. - تایید کنید که هر دو لیست مرتب شده و استفاده شده است
resultType: "complete". . - فهرست را تایید کنید و نتایج خواندن شامل اشاره های هدفمند حافظه کش است.
- URI خواندن را به تغییر دهید
notes://missingو مراقب باش-32602. . - تایید تایید اشتراک قبل از رویداد منابع.
- مراسم رو تایید کن و با خوشبختی ببند هر دو کارت ثبت نام رو نگه دار
5. .
مدل پایتون یک اتصال HTTP واقعی را باز نمی کند. این پیام هایی را که یک SDK باید در جریان پاسخ درخواست قرار دهد، نشان می دهد. از یک SDK رسمی برای چارچوب سازی و حمل و نقل در تولید استفاده کنید.
آثار هنری ارسال شده
outputs/skill-primitive-splitter.mdاین یک بررسی طراحی قابل استفاده مجدد برای انتخاب اولیه MCP است. اکنون کشف تعیین کننده، دامنه کش، رفتار نامطابق URI و فیلترهای جدید اشتراک را بررسی می کند.
درس هم کشتی هاassets/primitive-split.svg، یک نسخه ای از مرز اولیه و اشتراک برای مطالعه آفلاین.
بررسی کنید
bashcd phases/13-tools-and-protocols/10-mcp-resources-and-prompts/code
python3 main.py
python3 -m unittest discover tests -vنتیجه انتظار می رود: برنامه اصلی یک نسخه JSON را چاپ می کند و دستور آزمون حداقل 12 آزمون را گزارش می دهد.
اتصال Capstone
از این قرارداد استفاده کنید وقتی سرور پای سنگ شما اطلاعات قابل آدرس را در کنار اقدامات نشان می دهد. شامل یک عکس قطعات تعیین کننده، یک منبع مجاز خوانده شده، یک قطعنامه فوری، یک پرونده URI غیرفعال و یک نسخه اشتراک.
شواهد شما باید نشان دهد که هیچ لیست وابسته به تاریخچه اتصال نیست و یک رویداد اشتراک هرگز دسترسی به منبع اصلی را نمی دهد.
تمرینات
- اضافه کنید
notes://projects/{project}/notes/{id}قالب منابع و تایید هر دو متغیر. - صفحه بندی را به اضافه کنید
resources/listدر حالی که نظم تعیین کننده را حفظ می کند. - یک منبع را به تغییر دهید
cacheScope: "private"باttlMs: 0، یک سیاست بدون فروشگاه در سطح میزبان اضافه کنید و تهدیدی را که هر دو کنترل را توجیه می کند توضیح دهید. - یک اشتراک تغییر در لیست فوری اضافه کنید و ثابت کنید که هیچ رویداد زمانی که فیلتر حذف شود ارسال نمی شود
promptsListChanged. . - دو اشتراک همزمان ایجاد کنید و ثابت کنید که هر رویداد دارای شناسه درخواست درست است.
- یک مجوز متضمن را به دستیار خواندن اضافه کنید و ثابت کنید که یک ورودی حافظه پیشگیری نمی تواند متضمن را عبور کند.
اصطلاحات کلیدی
- Resource:محتوای آدرس URI که توسط یک سرور MCP قرار داده شده است.
- Prompt:یک قالب پیام کنترل شده توسط کاربر که توسط یک سرور MCP نمایش داده شده است.
- Deterministic list:یک نتیجه کشف با عضویت پایدار و سفارش برای ورودی های درخواست مشابه.
ttlMs:مدت تازه بودن در میلی ثانیه ذخیره کنید.cacheScope:مرز اشتراک گذاری برای یک نتیجه ذخیره شدهsubscriptions/listen:درخواست طولانی مدت که جریان پاسخ به طور صریح اطلاعیه های فیلتر شده را ارائه می دهد.- Subscription ID:شناسه اصلی درخواست گوش دادن، که در متاداتا اطلاعیه تکرار می شود.
- Invalid parameters:خطای JSON-RPC
-32602, برای یک URI منبع ناشناخته یا ناشناخته استفاده می شود. - Unsupported protocol version:خطای JSON-RPC
-32022، از جملهsupportedوrequestedاصلاحات server/discover:روش سرور اجباری که تغییرات پشتیبانی شده، قابلیت ها، هویت و اشاره های پیشگیری از گزینه ای را باز می گرداند.
خواندن بیشتر
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.