OAuth
يقبل خادم MCP نوعين من بيانات الاعتماد.
| مفتاح API | OAuth 2.1 | |
|---|---|---|
| من ينشئه | التاجر، من لوحة التحكم | العميل، تلقائيًا |
| ما يفعله التاجر | ينسخ المفتاح إلى العميل | يضغط موافقة في صفحة الموافقة |
| من يحمل السر | كل من ألصقتَ المفتاح عنده | لا أحد — يحمل العميل رمزًا دوّارًا |
| الإلغاء | احذف المفتاح | الإعدادات ← MCP ← فصل |
| الأنسب لـ | الوكلاء الذين تبنيهم، وأدوات الطرفية، والسكربتات، وخطوط CI | المساعدين الجاهزين: ChatGPT وClaude وكل ما فيه زر «اربط تطبيقًا» |
إن كنت تبني وكيلك بنفسك، فـمفتاح API أبسط وهذه الصفحة اختيارية. أما إن كنت تربط منتجًا يتوقع تشغيل مسار تفويض، فهذا هو الطريق الذي سيسلكه من تلقاء نفسه.
ما الذي يدعمه الخ ادم
| نوع المنح | Authorization code لعميل عام (token_endpoint_auth_method: none) |
| PKCE | إلزامي، بطريقة S256 حصرًا — وplain مرفوضة |
| تسجيل العملاء | ديناميكي (RFC 7591) — يسجّل العملاء أنفسهم بلا إعداد يدوي |
| الاكتشاف | بيانات المورد المحمي (RFC 9728) وبيانات خادم التفويض (RFC 8414) |
| رموز التجديد | دوّارة عند كل استخدام، مع كشف إعادة الاستخدام |
| الإلغاء | RFC 7009، إضافةً إلى فصل الاتصال من لوحة تحكم التاجر |
| النطاقات | mcp:read وmcp:write |
الوسيط resource | مقبول ومتجاهَل (RFC 8707) — فجمهور هذا الخادم ثابت |
العميل الذي يتقن تفويض MCP لا يحتاج أيًّا من العناوين أدناه: فهو يقرأ ترويسة WWW-Authenticate في استجابة 401 من /mcp ثم يكتشف الباقي بنفسه.
العناوين
| الغرض | الطريقة والمسار |
|---|---|
| بيانات المورد المحمي | GET https://api.taketheme.com/.well-known/oauth-protected-resource |
| بيانات خادم التفويض | GET https://api.taketheme.com/.well-known/oauth-authorization-server |
| تسجيل العميل | POST https://api.taketheme.com/api/v1/oauth/register |
| التفويض (صفحة متصفح) | GET https://dashboard.taketheme.com/oauth/authorize |
| الرموز | POST https://api.taketheme.com/api/v1/oauth/token |
| الإلغاء | POST https://api.taketheme.com/api/v1/oauth/revoke |
وتُقدَّم وثيقة المورد المحمي أيضًا على /.well-known/oauth-protected-resource/mcp، من أجل العملاء الذين يضعون مسار المورد بعد مقطع well-known.
المسار
-
يرسل العميل
POSTإلى/mcpبلا بيانات اعتماد فيتلقى401مع:WWW-Authenticate: Bearer resource_metadata="https://api.taketheme.com/.well-known/oauth-protected-resource" -
يجلب تلك الوثيقة، ويتبع
authorization_serversإلى بيانات خادم التفويض، ثم يسجّل نفسه علىregistration_endpoint. ويُرجع التسجيلclient_idبلا أي سر للعميل. -
يفتح
authorization_endpointفي متصفح التاجر ومعهclient_idوredirect_uriوcode_challengeوcode_challenge_method=S256وscopeوstate. -
يصل التاجر إلى صفحة الموافقة. وإن لم يكن مسجّل الدخول سجّل أولًا ثم عاد إليها. تعرض الصفحة اسم العميل والمتجر والنطاقات المطلوبة، ولا تفعل شيئًا حتى يختار. والرفض يُرجع
error=access_deniedإلى العميل. -
عند الموافقة يعود المتصفح إلى
redirect_uriالخاص بالعميل ومعهcodeصالح لاستخدام واحد وعمره عشر دقائق. -
يبادل العميل الرمز على عنوان الرموز مع
code_verifier، فيتلقى رمز وصول ورمز تجديد.
ولا يُوجَّه المتصفح إلى أي مكان قبل التأكد من أن redirect_uri يخص العميل المسجَّل، فطلب تفويض متلاعَب به يسقط على صفحة الموافقة بدل أن يُقذف بالتاجر إلى عنوان مهاجم.
النطاقات
يوجد نطاقان فقط، وطلب أي شيء غيرهما يُفشل طلب التفويض.
| النطاق | ما يمنحه |
|---|---|
mcp:read | READ على PRODUCTS وORDERS وCATEGORIES وCUSTOMERS وSTORE_SETTINGS وTHEME وBLOGS وANALYTICS |
mcp:write | ما سبق إضافةً إلى WRITE وUPDATE وDELETE على الموارد نفسها |
وإغفال scope في طلب التفويض يمنح mcp:read. والاتصال بصلاحية القراءة وحدها لا يستطيع استخدام أدوات منشئ المتجر — فكل واحدة منها ترحّل تغييرًا وتحتاج mcp:write. فإن اتصل مساعد ثم أبلغ أنه يقرأ متجرك ولا يستطيع تعديله، فهذا هو السبب: أعد الربط ووافق على صلاحية الكتابة.
وتنعكس النطاقات على نموذج المورد والإجراء نفسه المستخدم في صلاحيات مفاتيح API، وتُفحص عند كل استدعاء أداة لا عند العنوان.
get_review_summary غير متاحة عبر OAuthتحتاج هذه الأداة صلاحية REVIEWS، ولا يمنحها mcp:read ولا mcp:write. فاستدعاؤها على اتصال OAuth يُرجع permission_denied. استخدم مفتاح API لبيانات التقييمات ريثما يُصحَّح ذلك.
الرموز
رمز الوصول — رمز JWT صالح ساعة واحدة، جمهوره /mcp. يُقبل على عنوان MCP دون سواه: وتقديمه لأي مسار REST يُرجع 403، فالرمز المسرَّب لا يمكن نقله إلى بقية الـ API.
رمز التجديد — رمز مبهم يبدأ بـ tt_rt_، ويدور عند كل استخدام. وتقديم رمز سبق أن دار يُعامَل كسرقة: يُلغى عندها كامل عائلة الرموز فورًا ويضطر العميل إلى إعادة التفويض. فاحتفظ بأ حدث رمز تسلّمته فقط.
وتحمل الرموز المتجر الذي كان نشطًا لدى التاجر لحظة الموافقة. وكما هو الحال مع مفاتيح API، فـstoreId ليس وسيطًا لأي أداة — فلا يستطيع أي توجيه نصي أن يوجّه اتصالًا نحو بيانات تاجر آخر.
إلغاء الوصول
يستطيع التاجر فصل أي عميل من الإعدادات ← MCP، وهو ما يقتل عائلة الرموز كاملة دفعة واحدة.
وعلى العملاء الإلغاء عند تسجيل الخروج (RFC 7009):
curl -X POST https://api.taketheme.com/api/v1/oauth/revoke \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "token=tt_rt_YOUR_REFRESH_TOKEN" \
-d "token_type_hint=refresh_token" \
-d "client_id=YOUR_CLIENT_ID"
إلغاء رمز تجديد يُسقط عائلته. وإلغاء رمز وصول يضعه في قائمة منع لما تبقّى من ساعته. وكما يوجب المعيار، يجيب العنوان بـ 200 حتى للرمز الذي لم يجده.
حدود المعدل
عناوين OAuth محدودة بحسب عنوان IP، بمعزل عن حدود الـ API:
| العنوان | الحد |
|---|---|
/oauth/register | 5 في الساعة |
/oauth/authorize | 10 في الدقيقة |
/oauth/token | 30 في الدقيقة |
/oauth/revoke | 20 في الدقيقة |
والتسجيل هو الأضيق، والمساعدون المستضافون يسجّلون من عناوين خروج مشتركة. فإن أخفق موصّل في إعداد نفسه بالخطأ 429، انتظر ساعة ثم أعد المحاولة.
تنفيذه يدويًا
مفيد لاختبار عميل، أو لتطبيق أصيل يريد المسار دون مكتبة.
التسجيل:
curl -X POST https://api.taketheme.com/api/v1/oauth/register \
-H "Content-Type: application/json" \
-d '{
"client_name": "My Agent",
"redirect_uris": ["http://127.0.0.1:8976/callback"],
"grant_types": ["authorization_code", "refresh_token"],
"response_types": ["code"],
"token_endpoint_auth_method": "none"
}'
يجب أن تكون عناوين إعادة التوجيه بروتوكول https:، أو مخططًا مخصصًا (myapp://callback)، أو http: على الحلقة المحلية (localhost أو 127.0.0.1 أو [::1]). وبحد أقصى عشرة عناوين لكل عميل.
توليد زوج PKCE وإرسال التاجر إلى صفحة الموافقة:
VERIFIER=$(openssl rand -base64 60 | tr -d '\n=+/' | cut -c1-64)
CHALLENGE=$(printf '%s' "$VERIFIER" | openssl dgst -sha256 -binary | openssl base64 | tr '+/' '-_' | tr -d '=')
echo "https://dashboard.taketheme.com/oauth/authorize?client_id=$CLIENT_ID\
&redirect_uri=http://127.0.0.1:8976/callback\
&code_challenge=$CHALLENGE&code_challenge_method=S256\
&scope=mcp:read%20mcp:write&state=$(openssl rand -hex 16)"
مبادلة الرمز:
curl -X POST https://api.taketheme.com/api/v1/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=authorization_code" \
-d "client_id=$CLIENT_ID" \
-d "code=$CODE" \
-d "redirect_uri=http://127.0.0.1:8976/callback" \
-d "code_verifier=$VERIFIER"
{
"access_token": "eyJhbGciOi...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "tt_rt_...",
"scope": "mcp:read mcp:write"
}
ثم استدعِ عنوان MCP بترويسة Authorization: Bearer <access_token> تمامًا كما تفعل مع مفتاح API.
التجديد:
curl -X POST https://api.taketheme.com/api/v1/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=refresh_token" \
-d "client_id=$CLIENT_ID" \
-d "refresh_token=$REFRESH_TOKEN"
الأخطاء
| الرمز | المعنى |
|---|---|
UNAUTHORIZED_CLIENT | client_id غير مسجَّل أصلًا |
INVALID_GRANT | الرمز أُعيد استخدامه أو انتهى أو صدر لعميل آخر؛ أو redirect_uri غير مطابق؛ أو فشل تحقق PKCE؛ أو رمز التجديد غير صالح أو أُعيد استخدامه |
INVALID_REQUEST | code_challenge مفقود، أو code_challenge_method ليس S256 |
INVALID_SCOPE | طُلب نطاق غير mcp:read / mcp:write |
STORE_REQUIRED | التاجر الموافِق ليس لديه متجر نشط محدد |
INVALID_AUDIENCE | قُدِّم رمز OAuth في مكان غير /mcp |
TOKEN_REVOKED | أُلغي الرمز قبل انتهائه |
JWT_EXPIRED | تجاوز رمز الوصول ساعته — جدّده |
التالي
- خادم MCP — العنوان ووسيلة النقل وربط كل عميل
- مرجع الأدوات — كل أداة والصلاحية التي تحتاجها
- مرجع الصلاحيات — نموذج المورد والإجراء الذي تنعكس عليه هذه النطاقات