تست دسترسپذیری MCP Apps: چرا و چطور؟
خلاصهٔ کاملتر
MCP Apps یعنی سرور MCP (پروتکلی که ابزارها رو به ایجنتهای هوش مصنوعی وصل میکنه) به جای اینکه فقط نتیجه برگردونه، یه رابط کاربری واقعی مثل دکمه، فرم و کارت رو داخل خود کلاینت رندر کنه. نویسنده، Harris Schneiderman از Deque، میگه این خبر خوبیه ولی یه خطر داره: اگه این UI دسترسپذیر نباشه، یه نسل کامل از رابطها ساخته میشه که از روز اول یه عده رو بیرون نگه میداره. اینکه کلاینت کنار ویجت توضیح متنی هم بده یا نه کاملاً دست خودشه؛ Claude Desktop توضیح میداد، ولی بعضی کلاینتها متن رو کلاً حذف میکنن.
به گفته نویسنده، حتی توضیح متنی هم جایگزین نیست، چون متن فقط خلاصه میکنه ولی کارهایی مثل فیلتر، مرتبسازی و فرم فقط داخل ویجت هستن. از اون طرف، راهنمای رسمی تست MCP Apps فقط تست عملکردی رو پوشش میده و خود مشخصات MCP هم اسمی از کنتراست، کیبورد، صفحهخوان یا فوکوس نمیاره. این موضوع قبلاً تو یه issue در فوریه ۲۰۲۶ هم مطرح شده بود.
تست این اپها دو تا مشکل خاص داره. اول اینکه نمیشه یه ایجنت زنده رو مجبور کرد همه حالتها رو نشون بده؛ مثلاً حالتی که اپ لود شده ولی هنوز دادهای نرسیده، یا لغو و teardown. دوم اینکه اپ داخل یه iframe سندباکسشده و cross-origin رندر میشه، تو صفحهای که مال تو نیست. ابزاری مثل MCP Inspector و Axe DevTools میتونن داخل فریم رو ببینن، ولی مسیر فریم به هر کلاینت بستگی داره و با تغییر markup اون کلاینت میشکنه.
راهحل نویسنده یه سرور توسعه محلیه. همون HTMLی رو سرو میکنی که هندلر ui:// سرور MCPت سرو میکنه، نه یه کپی؛ به گفته نویسنده این مهمترین تصمیم کل کاره. بعد یه stub host (یعنی یه میزبان ساختگی که جای کلاینت واقعی پیام میفرسته) کمتر از ۱۰۰ خط مینویسی که به ui/initialize جواب بده، ورودی و نتیجه ابزار رو بفرسته و به ui/open-link جواب بده. این stub هیچ UIی نداره تا اسکنرها اونو جزو مشکلات اپ تو حساب نکنن.
هر حالت با یه پارامتر URL انتخاب میشه: اتصال، انتظار داده، استریم، موفق، خالی، خطا، لغو، teardown و تغییر context. اینا با داده کم، زیاد و داده عجیب (رشتههای خیلی بلند، متن راستبهچپ، فیلدهای اختیاری خالی) و بعد با تم روشن و تاریک ترکیب میشن. روی هر URL قوانین خودکار و پیشرفته Axe رو با عرض واقعی ستون چت اجرا میکنی و بعد Intelligent Guided Tests رو.
نویسنده چند تا اشتباه رایج رو هم گوشزد میکنه. تیترها رو از h1 شروع کن، چون اپ سند خودشه؛ title و h1 نباید یه چیز رو تکرار کنن. شورتکاتهای کیبورد ممکنه با کلاینت تداخل داشته باشن، پس طبق WCAG 2.1.4 قابل تغییر باشن. برای رنگ، یا هر دو طرف جفت رنگ رو از توکنهای میزبان بگیر یا هیچکدوم. env(safe-area-inset-*) داخل iframe صفر برمیگردونه، پس باید مقدارها رو از hostContext.safeAreaInsets بخونی و خودت ست کنی:
function applyInsets(insets = {}) {
const root = document.documentElement;
for (const side of ["top", "right", "bottom", "left"]) {
root.style.setProperty(`--safe-${side}`, `${insets[side] ?? 0}px`);
}
}نکات کلیدی:
- مشخصات MCP و راهنمای رسمی تست MCP Apps هیچ اشارهای به دسترسپذیری ندارن
- اینکه کلاینت کنار ویجت توضیح متنی بده یا نه به خود کلاینت بستگی داره
- یه stub host زیر ۱۰۰ خط کافیه تا همه حالتهای اپ رو بازپخش کنی
- dev server باید دقیقاً همون HTML هندلر ui:// رو سرو کنه، نه کپی اون
- تیترها از h1 شروع بشن و شورتکاتها طبق WCAG 2.1.4 قابل غیرفعال یا تغییر باشن
- env(safe-area-inset-*) داخل iframe بیفایدهست؛ از hostContext.safeAreaInsets استفاده کن
- media queryهایی مثل prefers-reduced-motion و forced-colors بدون تغییر کار میکنن




