API Reference · MCP · OAuth 2.1

توثيق المطورين — مدعوم

كل ما تحتاجه للاتصال بمنصة مدعوم برمجيًا: مفاتيح API، خادم MCP الموحّد (JSON-RPC)، وتدفق OAuth 2.1 الكامل مع Dynamic Client Registration. هذا التوثيق مبني مباشرة من كود الـ Edge Functions الفعلي على Supabase.

آخر تحديث: يوليو 2026 mcp function v21 تتبع الاستخدام تم إصلاحه
01

نظرة عامة على البنية

جدول api_tokens هو مصدر الهوية الوحيد لكل شيء — سواء تولّد يدويًا من لوحة "مفاتيح API"، أو صدر تلقائيًا عبر تدفق OAuth 2.1 لعميل مثل Claude أو ChatGPT.

توليد يدوي

من لوحة مفاتيح API
create-api-token

api_tokens

مصدر الهوية الموحّد
لكل طلب API/MCP

توليد تلقائي

عبر OAuth 2.1
oauth-token

كل طلب — سواء بمفتاح API ثابت أو Access Token صادر من OAuth — يصل في النهاية لنفس نقطة الدخول: POST /mcp، بروتوكول JSON-RPC 2.0 واحد يغطي كل الأدوات.

02

بداية سريعة

أسرع طريقة للاتصال: ولّد مفتاح API من لوحة المطورين، ثم استدعِ /mcp مباشرة.

ولّد مفتاح من لوحة "مفاتيح API"

اختر credential_type واحدة: api_key_secret أو bearer. السر يُعرض مرة واحدة فقط — احفظه فورًا.

نادِ initialize لبدء الجلسة

الرد يحمل هيدر Mcp-Session-Id ونسخة البروتوكول المتفق عليها.

اسحب قائمة الأدوات المتاحة لك

tools/list بترجع بس الأدوات اللي صلاحياتها (scopes) موجودة في مفتاحك، وغير معطّلة إداريًا.

نفّذ أي أداة عبر tools/call

مرّر name وarguments — النتيجة بترجع كـ JSON نصي داخل content.

curl — تدفق كامل
curl -X POST https://mad3oom.online/mcp \
  -H "Authorization: Bearer mad3oom_pk_XXXX.mad3oom_sk_YYYY" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize"}'

# tools/list
curl -X POST https://mad3oom.online/mcp \
  -H "Authorization: Bearer mad3oom_pk_XXXX.mad3oom_sk_YYYY" \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/list"}'

# tools/call
curl -X POST https://mad3oom.online/mcp \
  -H "Authorization: Bearer mad3oom_pk_XXXX.mad3oom_sk_YYYY" \
  -d '{
    "jsonrpc":"2.0","id":3,"method":"tools/call",
    "params":{"name":"list_tickets","arguments":{"status":"open","limit":10}}
  }'
03

مفاتيح API

جدول api_tokens يخزّن SHA-256 فقط لكل سر — لا يوجد أي استرجاع للسر الأصلي بعد الإنشاء، فقط تجديد كامل.

أنواع بيانات الاعتماد

credential_typeتنسيق المفتاحالرد عند الإنشاء
api_key_secretmad3oom_pk_... + mad3oom_sk_...{ token: {api_key}, secret }
bearermad3oom_bt_... (256-bit){ token, bearer_token }
bothصفّان مرتبطان بـ credential_group_id{ api_key_secret: {...}, bearer: {...} }

الاستخدام في هيدر Authorization

تمييز النوع من التوكن نفسه
// api_key_secret → فيه نقطة فاصلة بين الاثنين
Authorization: Bearer mad3oom_pk_XXXX.mad3oom_sk_YYYY

// bearer → توكن واحد بدون نقطة
Authorization: Bearer mad3oom_bt_ZZZZZZZZ

السر يُعرض مرة واحدة فقط. لو ضاع أو اتقفل المودال بالغلط، الحل الوحيد هو تجديد السر عبر regenerate-api-token-secret — مفيش استرجاع لنص السر الأصلي لأن القاعدة بتخزّن الهاش بس.

04

الصلاحيات (Scopes)

كل مفتاح له مصفوفة scopes — الأداة اللي محتاجة scope غير موجود عند المفتاح ببساطة مش هتظهر في tools/list، ومحاولة استدعائها في tools/call بترجع خطأ 403 (JSON-RPC code -32003).

الصلاحيات المستهلَكة فعليًا من أدوات MCP

tickets:readtickets:write whatsapp:send subscriptions:readsubscriptions:write subscriptions:renewsubscriptions:cancelsubscriptions:plans notifications:readnotifications:sendnotifications:manage

الصلاحيات الافتراضية (لو ماتحددتش صراحة)

tickets:readtickets:writewhatsapp:sendwhatsapp:readchatbot:read

الصلاحيات التالية معرّفة ومسموح بيها لكن لا توجد أي أداة MCP تستهلكها حاليًا: tickets:delete, knowledge_base:*, customers:write, whatsapp:read, analytics:read, settings:manage, oauth:manage, mcp:connect, chatbot:read, admin:full. جاهزة للاستخدام المستقبلي عند إضافة أدوات جديدة.

05

مدعوم كخادم MCP

نقطة JSON-RPC 2.0 واحدة تخدم كل عملاء MCP الخارجيين (Claude, ChatGPT, Cursor...) عبر Streamable HTTP.

POST https://mad3oom.online/mcp functions/v1/mcp (Vercel rewrite)

دورة حياة الجلسة

initialize → tools/list → tools/call
// 1) initialize — يرجع Mcp-Session-Id في الهيدر
→ {"method":"initialize","params":{"protocolVersion":"2025-06-18"}}
← {"result":{"protocolVersion":"2025-06-18","serverInfo":{"name":"mad3oom-mcp","version":"1.1.0"}}}

// 2) tools/list — مفلترة حسب scopes التوكن + الأدوات المعطّلة إداريًا
→ {"method":"tools/list"}
← {"result":{"tools":[{"name":"list_tickets", ...}]}}

// 3) tools/call
→ {"method":"tools/call","params":{"name":"list_tickets","arguments":{"status":"open"}}}
← {"result":{"content":[{"type":"text","text":"[...]"}]}}

كتالوج الأدوات بقى Live من جدول mcp_tools_catalog بدل ما يكون ثابت في الكود — أي أداة جديدة أو تعديل وصف بيتحدّث من قاعدة البيانات مباشرة (Cache محلي 30 ثانية داخل الدالة).

06

الأدوات المتاحة

18 أداة موزّعة على 5 مجموعات — كل أداة مربوطة بـ scope واحد محدد.

الأداةScopeالوصف
create_tickettickets:writeإنشاء تذكرة نيابةً عن صاحب المفتاح
update_tickettickets:writeتعديل — الأدمن أي حقل عبر RPC، العميل أرشفة فقط
close_tickettickets:writeإغلاق (أدمن فقط حاليًا)
list_ticketstickets:readفلترة بالحالة + limit/offset (حد أقصى 100)
get_tickettickets:readتذكرة واحدة
get_dashboard_statstickets:readإحصائيات حسب الحالة
get_customer / list_customerstickets:readبيانات العملاء المرئيين لصاحب المفتاح
send_whatsappwhatsapp:sendنصي أو تمبلت عبر WhatsApp Graph API
list_subscriptions / get_subscriptionsubscriptions:readفلترة بالحالة/الخطة أو اشتراك واحد
create_subscriptionsubscriptions:writeطلب جديد (تذكرة + صف pending)
renew_subscriptionsubscriptions:renewطلب تجديد
cancel_subscriptionsubscriptions:cancelإلغاء طلب pending فقط
list_subscription_planssubscriptions:plansالخطط النشطة + مزاياها
list_notificationsnotifications:readإشعارات صاحب المفتاح نفسه فقط
send_notificationnotifications:sendلمستخدم ضمن حدود الرؤية
manage_notificationnotifications:manageتحديد كمقروء / حذف

نموذج الصلاحيات (Actor-based)

كل أداة تمر بـ getActor(userId) لتحديد: أدمن رئيسي (بريد ثابت)، أدمن (profiles.role='admin')، أو مستخدم فرعي. الأدمن يرى كل شيء في التذاكر والاشتراكات، العميل العادي يرى نفسه ومستخدميه الفرعيين فقط. الإشعارات استثناء — مقصورة على صاحب المفتاح نفسه حتى لو كان أدمن.

07

مدعوم كعميل MCP

عكس الاتجاه السابق — هنا مدعوم بيتصل بخوادم MCP خارجية (Supabase, GitHub, Notion...) نيابةً عن الأدمن، عبر جدولين منفصلين.

الجدولالغرض
mcp_serversتعريف الخادم — مشترك بين كل الأدمنز
mcp_server_connectionsاتصال كل أدمن — معزول بـ RLS على owner_id

التشفير

كل الأسرار (api_key_encrypted, bearer_token_encrypted, oauth_access_token_encrypted...) مشفّرة بـ AES-GCM حقيقي (IV عشوائي 12 بايت + ciphertext). لا يوجد أي مسار في الكود يعيد فك هذه القيم للواجهة — فقط تُستخدم داخليًا وقت الاستدعاء الفعلي.

أنواع المصادقة المدعومة

noneapi_keybearercustomoauth2

لكل نوع oauth2، الدالة ensureFreshAccessToken بتجدّد access_token تلقائيًا لو باقي أقل من 60 ثانية على انتهائه، قبل بناء الهيدر.

08

تدفق OAuth 2.1 الكامل

هذا المسار تستخدمه Claude/ChatGPT/أي عميل يدعم Dynamic Client Registration + PKCE، عوضًا عن مفتاح API ثابت.

الوظيفةPublic URL
Discovery (RFC 8414)GET /.well-known/oauth-authorization-server
Protected Resource (RFC 9728)GET /.well-known/oauth-protected-resource
تسجيل عميل تلقائيPOST /oauth/register
بدء التفويضGET /oauth/authorize
إصدار/تجديد TokenPOST /oauth/token
تسجيل العميل (DCR)

Claude يبعت client_name وredirect_uris → يرجع client_idclient_secret لو مطلوب).

بناء رابط PKCE والتحويل

code_challenge_method=S256 إجباري. يتحقق من rate limit ومطابقة redirect_uri المسجّل، ثم يحوّل لصفحة موافقة المستخدم.

موافقة المستخدم

بعد تسجيل الدخول، ينشئ authorization_code صالح لـ 60 ثانية فقط.

تبادل الكود بـ Access Token

Claude يتحقق من code_verifier مقابل code_challenge المخزّن، وينشئ صف api_tokens جديد (credential_type=bearer) + oauth_refresh_tokens مرتبط به.

الاستخدام والتجديد

Access token يُستخدم كـ Bearer عادي على /mcp. Refresh token يُدوَّر بالكامل (rotation) عند كل استخدام.

09

التفاصيل الأمنية لـ OAuth

أعمار التوكنات

Access token: ساعة واحدة (3600s)
Refresh token: 30 يوم، يُدوَّر بالكامل عند كل استخدام

PKCE إجباري

S256 فقط — لا يوجد مسار بدون code_challenge

Rate Limiting مستقل

authorize: 60/د لكل IP، 20/د لكل client
token: 40/د لكل IP، 15/د لكل client
register: 5/ساعة لكل IP

تسجيل شامل

كل محاولة تسجيل عميل (ناجحة أو فاشلة) تُسجَّل في oauth_client_registrations_log مع IP وUser-Agent

10

تتبع الاستخدام

تم الإصلاح — mcp function v21

تسجيل كل طلب موثّق في api_token_usage_logs + عدّاد usage_count على api_tokens. كانت فيه 3 فجوات حقيقية في الكود، اتصلحت الثلاثة في نفس الإصدار.

الفجوةقبلبعد
endpointثابت دايمًا: "/mcp:unknown"ديناميكي: /mcp:tools/call:list_tickets مثلاً
status_codeNULL في كل الصفوفالـ status الفعلي للرد (200 / 400 / 403 / 500...)
usage_countصفر دائمًا — مفيش كود بيزوّدهيتزود أتوميك عبر RPC increment_api_token_usage

كيف اتصلحت

التسجيل انتقل من بداية الطلب (داخل verifyApiToken) لنهايته، بعد معرفة الـ method واسم الأداة والـ Response النهائي فعليًا — عبر دالة withLogging() بتلف كل مسارات الرد في index.ts.

index.ts — منطق التسجيل الجديد
function withLogging(response) {
  logApiUsage({
    tokenId: auth.token.id,
    endpoint: endpointLabel, // ديناميكي حسب method/الأداة
    statusCode: response.status, // من الـ Response الفعلي
    ip, userAgent,
  });
  return response;
}
// كل return في الملف بقى: return withLogging(httpJson(...))

تريد-أوف واعي: حد الـ rate limit (60 طلب/دقيقة) لسه بيتحسب بعدّ سجلات آخر 60 ثانية قبل معالجة الطلب — زي الأول بالظبط. لكن بما إن الإدراج الفعلي بقى في النهاية مش البداية، هامش الـ race بين عدد كبير من الطلبات المتزامنة جدًا لنفس التوكن في نفس اللحظة بقى أوسع شوية من قبل. تريد-أوف مقبول مقابل تسجيل status_code وendpoint صحيحين.

11

توجيه Vercel

كل الروابط العامة rewrites (مش redirects) — العميل يرى دومين mad3oom.online فقط طول الوقت، وهو مطلوب لتطابق issuer في RFC 8414/9728.

/.well-known/oauth-authorization-serveroauth-discovery
/.well-known/oauth-protected-resourceoauth-protected-resource
/oauth/registeroauth-register
/oauth/authorizeoauth-authorize
/oauth/tokenoauth-token
/mcpmcp
12

مرجع الوظائف

verify_jwt: false على mcp وoauth-* إجباري — المصادقة عندهم مخصّصة (api_tokens / client credentials)، مش JWT قياسي.

mcp
نقطة JSON-RPC الرئيسية — كل أدوات MCP
verify_jwt: false
mcp-server-info
حالة الخادم + تفعيل/تعطيل الأدوات عالميًا
verify_jwt: true
create-api-token
توليد مفتاح API جديد
verify_jwt: true
regenerate-api-token-secret
تجديد سر/Bearer لمفتاح موجود
verify_jwt: true
oauth-discovery
RFC 8414 metadata
verify_jwt: false
oauth-protected-resource
RFC 9728 metadata
verify_jwt: false
oauth-register
Dynamic Client Registration
verify_jwt: false
oauth-authorize
بداية تدفق PKCE
verify_jwt: false
oauth-authorize-approve
تنفيذ موافقة/رفض المستخدم
verify_jwt: true
oauth-token
تبادل code/refresh_token بـ access_token
verify_jwt: false
save-mcp-credentials
تشفير وحفظ بيانات اعتماد خادم MCP خارجي
verify_jwt: true
mcp-invoke-tool
تنفيذ أداة على خادم MCP خارجي متصل
verify_jwt: true
test-mcp-server
اختبار اتصال + مزامنة أدوات خادم خارجي
verify_jwt: true