پرش به محتوای اصلی
پرش به محتوای مقاله

دیوارهای احرازی OAuth سرورهای MCP را در دایرکتوری‌ها نامرئی می‌کنند

·۳۱ مرداد ۱۴۰۵۵ دقیقه مطالعه
راهنما
اگر سرور MCP شما از OAuth استفاده می‌کند، هر پوشه فکر می‌کند هیچ ابزاری ندارد
اگر سرور MCP شما از OAuth استفاده می‌کند، هر پوشه فکر می‌کند هیچ ابزاری ندارد
اشتراک‌گذاری
واقعاً چه چیز جدید است؟

شناسایی یک تداخل ساختاری میان پروتکل OAuth و مکانیزم اکتشاف MCP که منجر به ایجاد «لیست‌های مرده» در دایرکتوری‌های ابزارهای هوش مصنوعی می‌شود.

تصور کنید سرور پروتکل زمینهٔ مدل (MCP) شما کاملاً درست کار می‌کند، اما در چشم دنیا مرده است. اگر توسعه‌دهندگان تمام هندلرهای خود را پشت دیواری از احراز هویت OAuth 2.1 قرار دهند، به‌طور ناخواسته باعث می‌شوند دایرکتوری‌های اکتشافی مانند Smithery و mcp.directory سرور آن‌ها را با لیست ابزارهای صفر ثبت کنند. این اتفاق عملاً سرویس را برای کاربران بالقوه نامرئی می‌کند.

این شکست به‌دلیل سازوکار اکوسیستم MCP در مدیریت اکتشاف رخ می‌دهد. برای فهرست کردن قابلیت‌های یک سرور، خزنده‌ی دایرکتوری متد tools/list را فراخوانی می‌کند. اگر این متد پشت یک دیوار احرازی باشد، خزنده با پاسخ ۴۰۱ (Unauthorized) مواجه می‌شود. از آنجا که خزنده حساب کاربری ندارد، نمی‌تواند درخواست را تایید کند و صرفاً یک لیست خالی از قابلیت‌ها را ثبت می‌کند.

به نقل از گزارش فنی منتشر شده توسط سازندگان FrameThrower، این یک شکست خاموش است. لاگ‌های سرور خطاهای ۴۰۱ را نشان می‌دهند، اما صفحه عمومی دایرکتوری صرفاً عبارت tools: [] را نمایش می‌دهد. در یک مورد، API شرکت glama خروجی را به‌صورت زیر برگرداند: { "name": "FrameThrower MCP Server", "attributes": ["author:official", "hosting:remote-capable"], "tools": [] }. این وضعیت باعث ایجاد «لیست‌های مرده» می‌شود که اغلب در سایر رجیستری‌ها نیز تکثیر شده و تضمین می‌کند که سرور، فارغ از اینکه در چند دایرکتوری ثبت شده باشد، ناشناخته باقی بماند.

سازوکار شکست

bسیاری از توسعه‌دهندگان از مستنداتی پیروی می‌کنند که آن‌ها را تشویق می‌کند برای محافظت از اعتبارها (Credits) و داده‌های کاربر، هندلرها را در لایه‌ی احراز هویت بپیچند. یک پیاده‌سازی اشتباه معمولاً به این شکل است:

  • رپِر withMcpAuth روی تمام درخواست‌های GET، POST و DELETE اعمال می‌شود.
  • هر درخواستی بدون userId معتبر (که از طریق session?.userId ?? session?.user?.id بررسی می‌شود)، پاسخ ۴۰۱ می‌گیرد.
  • متد tools/list که یک متد غیرممتاز (non-privileged) است، در این تله گرفتار می‌شود.

در مورد FrameThrower، لاگ اسکنر Smithery فاش کرد که خزنده به‌محض برخورد با نیاز به احراز هویت متوقف شده است. لاگ نشان می‌داد: [scan] Discovering server metadata... و سپس [scan] Server metadata discovered (OAuth required). و در نهایت [scan] Authentication required. Please authorize at: https://connect.smithery.ai/...

تنها زمانی که یک انسان به‌صورت دستی مراحل تعاملی OAuth را طی کرد، اسکنر توانست چهار ابزار موجود را شناسایی کند: [scan] Capabilities found: 4 tools. با این حال، این نتیجه‌ی انسانی در صفحه عمومی دایرکتوری منعکس نمی‌شود و بازدیدکنندگان همچنان تعداد ابزارها را صفر می‌بینند.

راهکار فنی: تفکیک متدها

برای حل این مشکل، توسعه‌دهندگان باید «دست‌دادن» (Handshake) را از «اجرا» (Execution) جدا کنند. توصیف آنچه سرور ارائه می‌دهد یک عملیات عمومی است، اما فراخوانی آن ابزارها یک عملیات ممتاز و نیازمند سطح دسترسی است. راهکار پیشنهادی، ایجاد مجموعه‌ای از متدهای عمومی (PUBLIC_METHODS) است که از گیت احرازی عبور کنند:

  • initialize
  • notifications/initialized
  • ping
  • tools/list

برای جلوگیری از تبدیل این مسیر به یک حفره امنیتی (Authentication Bypass)، پیاده‌سازی باید از سه قانون سخت‌گیرانه پیروی کند. اول، اگر هدر Authorization در درخواست وجود داشت، درخواست حتماً باید از مسیر احراز هویت عبور کند. بدون این قانون، کلاینتی که توکنی منقضی‌شده دارد، به‌جای دریافت خطای ۴۰۱ (که باعث تمدید توکن می‌شود)، به‌طور خاموش به دسترسی ناشناس سقوط می‌کند. شکست خاموش بدتر از شکست آشکار است.

دوم، در مسیر عمومی فقط درخواست‌های POST مجاز هستند. در پروتکل HTTP Streamable، درخواست‌های GET برای باز کردن جریان SSE و DELETE برای پایان دادن به نشست استفاده می‌شوند. هیچ‌کدام از این‌ها متد JSON-RPC را حمل نمی‌کنند که بتوان آن را بازرسی کرد، بنابراین هیچ‌کدام نمی‌توانند «عمومی» طبقه‌بندی شوند و باید احراز هویت شوند.

سوم، سیستم باید هنگام بررسی درخواست‌های دسته‌ای (Batch)، از متد .every() به‌جای .some() استفاده کند. پروتکل JSON-RPC اجازه دسته‌بندی درخواست‌ها را می‌دهد. اگر یک دسته درخواست، متد tools/list را با tools/call ترکیب کند، کل درخواست باید به‌عنوان یک درخواست نیازمند احراز هویت تلقی شود.

به عنوان خط دفاعی دوم، مسیر عمومی بدون هیچ فراخواننده‌ای (Caller) در زمینه (Context) اجرا می‌شود. اگر متد tools/call هرگز به این مسیر برسد، تابع محاسبه هزینه (Charging function) هیچ کاربری را پیدا نمی‌کند و درخواست را رد می‌کند. بدین ترتیب، گیت از هر دو جهت بسته می‌ماند. این رویکرد در کنار ابزارهای نظارتی مانند سیستم mcp-fabric-toolmesh که برای جلوگیری از دسترسی‌های غیرکنترل‌شده عامل‌ها طراحی شده، امنیت سرور را دوچندان می‌کند.

تایید پیاده‌سازی

توسعه‌دهندگان باید با تست کدهای پاسخ خاص، صحت تنظیمات را بررسی کنند تا مطمئن شوند اکتشاف OAuth را از دست نداده‌اند. یک تنظیم موفق باید این نتایج را بدهد:

  • initialize (بدون احراز) $\rightarrow$ ۲۰۰
  • tools/list (بدون احراز) $\rightarrow$ ۲۰۰ (لیست کامل ابزارها)
  • tools/call (بدون احراز) $\rightarrow$ ۴۰۱
  • tools/list (توکن نامعتبر) $\rightarrow$ ۴۰۱
  • ترکیب دسته‌ای tools/list + tools/call $\rightarrow$ ۴۰۱
  • GET (جریان SSE، بدون احراز) $\rightarrow$ ۴۰۱

نکته حیاتی این است که هر پاسخ ۴۰۱ باید شامل هدر WWW-Authenticate به همراه resource_metadata باشد تا کلاینت‌های سازگار بدانند کجا باید احراز هویت کنند. می‌توان این مورد را با دستور curl زیر تایید کرد:

curl -s -D - -o /dev/null -X POST https://your-server/api/mcp \ -H 'Content-Type: application/json' \ -H 'Accept: application/json, text/event-stream' \ -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"x","arguments":{}}}' \ | grep -i 'www-authenticate'

خروجی مورد انتظار عبارت است از: www-authenticate: Bearer resource_metadata="https://your-server/api/auth/.well-known/oauth-protected-resource"

باگ پنهان در هویت سرور

تیم FrameThrower هنگام رفع مشکل احراز هویت، متوجه خطای رایج دومی در مورد هویت سرور شد. تابع createMcpHandler در کتابخانه mcp-handler، اگر مقدار serverInfo به‌طور صریح تنظیم نشود، آن را به‌صورت پیش‌فرض روی "mcp-typescript server on vercel" نسخه 0.1.0 قرار می‌دهد.

قبل از اصلاح، لاگ Smithery نشان می‌داد: [scan] Server info retrieved. name: mcp-typescript server on vercel, version: 0.1.0. این بدان معناست که بسیاری از سرورها خود را به کلاینت‌هایی مانند Claude Desktop و Cursor با یک نام پیش‌فرض و کلی معرفی می‌کنند، نه با نام برند واقعی خود. این نقص در شناسایی، مستقیماً بر معیارهای ارزیابی کیفیت اثر می‌گذارد؛ برای مثال ابزار mcpscore می‌تواند چنین نقصاتی در استانداردهای پیاده‌سازی سرور را شناسایی و نمره‌گذاری کند.

این یک اصلاح تک‌خطی در شیء تنظیمات است: serverInfo: { name: 'FrameThrower', version: '1.0.0' }. این رشته متنی همان چیزی است که هر کلاینتی نمایش می‌دهد و عدم تنظیم آن منجر به تجربه کاربری ضعیف می‌شود. پس از اعمال هر دو اصلاح، اسکنر بدون نیاز به هیچ مرحله‌ای در مرورگر، به‌طور تمیز اجرا شد: [scan] Server info retrieved. name: FrameThrower, version: 1.0.0 و [scan] Capabilities found: 4 tools.

برای توسعه‌دهندگان، این بدان معناست که لایه‌ی اکتشاف تنها به کیفیت «دست‌دادن» وابسته است. اگر یک سرور MCP راه دور اجرا می‌کنید، باید صفحات دایرکتوری را چک کنید — نه لاگ‌های خود را — تا مطمئن شوید ابزارهایتان واقعاً برای عموم قابل مشاهده است. چه در حال ساخت یک کتابخانه سینماتوگرافی مانند FrameThrower (موجود در github.com/framethrower-ai/framethrower-mcp) باشید و چه یک ابزار داده سازمانی، قانون یکسان است: توصیف یک منبع عمومی است، اما استفاده از آن خیر.

گام بعدی شما

  • اگر سرور MCP راه دور دارید، همین حالا صفحه دایرکتوری خود را چک کنید تا مطمئن شوید ابزارهایتان برای عموم قابل مشاهده است.
  • متدهای initialize و tools/list را از لایه‌ی احراز هویت OAuth خارج کنید.
  • مقدار serverInfo را در تنظیمات هندلر از حالت پیش‌فرض خارج کرده و نام برند خود را جایگزین کنید.

اما داستان سخت‌افزاری این تحول حتی شگفت‌انگیزتر است — به تحلیل ما درباره‌ی تراشه‌های Blackwell مراجعه کنید.

چرا این موضوع مهم است؟

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

تأثیر برای ایران

برای توسعه‌دهندگان ایرانی که سرورهای MCP را روی زیرساخت‌های ابری خارجی مستقر می‌کنند، رعایت این تفکیک در متدها برای دیده شدن در دایرکتوری‌های جهانی ضروری است.

·نگاه ما
تحریریه دات‌هوش

این مسئله نشان می‌دهد که در اکوسیستم‌های نوظهور مثل MCP، استانداردهای امنیتی رایج (مانند بستن کامل API پشت OAuth) می‌توانند به‌طور ناخواسته باعث شکست در توزیع و اکتشاف شوند. توسعه‌دهندگان باید از مدل «دسترسی سطح‌بندی شده» استفاده کنند تا قابلیت‌های سیستم برای خزنده‌ها باز و عملیات حساس برای کاربران احراز شده باقی بماند.

منابع

این گزارش با خط‌لولهٔ خودکار دات‌هوش از منابع معتبر جهانی تدوین و زیر نظر تحریریه منتشر شده است. روش کار ما

گفتگو

پنج‌شنبه‌های هوش‌محور

بسته‌ی هفتگی دات‌هوش

۵ خبر، ۲ ابزار، ۱ پرامپت در هر شماره. به‌زودی راه‌اندازی می‌شود — هر پنج‌شنبه صبح.

خبر کلیدی
ابزار کاربردی
پرامپت حرفه‌ای
تحلیل پژوهش
به‌زودی
زاویه‌ی ایرانی
به‌زودی
تمرین این هفته
به‌زودی

راهنماهای دات‌هوش

راهنماهای کاربردیِ دات‌هوش برای کار با هوش مصنوعی — از همین‌جا شروع کنید:

دات‌هوش

راهنمای فارسی هوش مصنوعی — با نگاه به ایران

اخبار روزانه، معرفی ابزارها و مدل‌ها، و آموزشِ کار با هوش مصنوعی؛ همیشه با این پرسش که از ایران چه چیزی کار می‌کند و چه چیزی نه.