MCP و OAuth 2.1

ما الذي يقدّمه خادم MCP

يُشغّل Institflow خادم Model Context Protocol على المسار /mcp (بروتوكول Streamable HTTP، بلا حالة — كل استدعاء مستقلّ، فيتوسّع تمامًا كأي طلب واجهة آخر). يعرض نفس خدمات النطاق التي تستدعيها كل نقطة نهاية REST، عبر 74 أداة موجَّهة بالمهام، وعددًا من الموارد للقراءة فقط، وبضعة مطالبات (prompts) بأسلوب التقارير — بحيث يستطيع وكيل ذكاء اصطناعي (Claude، أو أي عميل MCP) البحث عن طلاب، أو الاطّلاع على جدول، أو تسجيل حضور، أو صياغة تقرير تقدّم، مستخدِمًا صلاحيات المستدعي نفسه بدقّة، لا أكثر أبدًا.

ربط عميل (Client)

Institflow خادم تفويض OAuth 2.1 خاص به لهذا الغرض — لا حاجة إلى مفتاح API منفصل أو رمز يدوي. عميل MCP متوافق يكتشف كل ما يحتاجه تلقائيًا:

  1. يجلب GET /.well-known/oauth-protected-resource (وفق RFC 9728) من تحدّي WWW-Authenticate الذي تُعيده /mcp، ثم GET /.well-known/oauth-authorization-server (وفق RFC 8414) لمعرفة نقاط الرمز والتسجيل والتفويض.
  2. إن لم يكن لديه client_id مسبقًا، يسجّل واحدًا ديناميكيًا: POST /oauth/register (وفق RFC 7591 — عميل عام، بلا سرّ؛ يمكنك تعطيل هذه النقطة على مستوى المستأجر بالكامل عبر إعداد OAUTH_DYNAMIC_REGISTRATION إن فضّلت تسجيل العملاء بنفسك مسبقًا).
  3. يفتح GET /oauth/authorize مع PKCE (بخوارزمية S256 — مطلوبة لا اختيارية، وفق OAuth 2.1) في متصفّحك. تسجّل الدخول (إن لزم) وتصل إلى شاشة موافقة تُظهر بالضبط أيّ مستأجر/عضوية تربطه وما الذي يستطيع العميل فعله.
  4. بعد موافقتك، يستبدل العميل رمز التفويض — POST /oauth/token مع code_verifier الخاص بـPKCE — برمز وصول (JWT عادي من Institflow، بقيمة typ: "mcp" فقط) ورمز تحديث صالح لمدّة 30 يومًا.
mcp request
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6ImF0K2p3dCJ9...

رمز MCP لا يُصادِق أبدًا طلب REST

والعكس أيضًا غير ممكن — رمز بقيمة typ: "mcp" يُرفَض بـ 401 على كل مسار /api/v1/* عادي، ورمز وصول عادي لا يستطيع استدعاء /mcp. الفصل بينهما مقصود.

الصلاحيات والنطاقات

الحصول على رمز أصلًا يتطلّب صلاحية mcp.access على العضوية التي تربط بها — عضو بلا هذه الصلاحية (معظم أدوار secretary/teacher افتراضيًا) يُرفَض عند خطوة الموافقة، قبل إصدار أي رمز. كل أداة تتحقّق أيضًا من صلاحيتها الخاصة المُعلَنة عند كل استدعاء — مطابقة تمامًا لما تتطلّبه نقطة نهاية REST المكافئة.

الأدوات المُعلَّمة كإجراء حسّاس أدناه تحتاج أيضًا إلى mcp.destructive. استدعاء إحداها بلا confirm: true لا يُعدّل شيئًا أبدًا — يُعيد معاينة لما سيحدث (مثل: "سيغيّر الحالة من نشط إلى منسحب") مع requiresConfirmation: true. الوكيل (أو الشخص الذي يقوده) يعيد استدعاء نفس الأداة بـconfirm: true لتنفيذها فعليًا. كل استدعاء — معاينة أو تنفيذ — يُسجَّل في سجلّ التدقيق بقناة channel: "mcp"، واسم الأداة، وقيمة تجزئة لمعطياتها (لا المعطيات الخام أبدًا، فقد تحمل بيانات شخصية).

فهرس الأدوات

كل أداة، مُولَّدة مباشرة من apps/api/src/modules/mcp/tools/*.ts — المصدر نفسه الذي يسجّله خادم MCP عند الإقلاع.

Academics

الأداةالوصفالصلاحيةإجراء حسّاس
cancel_sessionCancel a scheduled class session, with a reason. Destructive: previews unless confirm: true is passed.groups.writeنعم
create_groupCreate a new teaching group (class section) for a course, with an optional weekly schedule.groups.writeلا
drop_enrollmentDrop a student's enrollment from a group. Destructive: previews unless confirm: true is passed.enrollments.writeنعم
enroll_studentEnroll a student into a teaching group.enrollments.writeلا
get_groupGet full details for one teaching group by id.groups.readلا
get_scheduleGet scheduled class sessions for a group, teacher, or student within an optional date range. Exactly one of groupId/teacherStaffId/studentId is required.groups.readلا
list_coursesList the course catalogue (subjects/programs offered), optionally filtered by category or active status.courses.readلا
list_groupsList teaching groups (class sections), optionally filtered by branch, course, status, or teacher.groups.readلا
transfer_studentTransfer a student's enrollment from their current group to another group (drop + enroll in one operation). Destructive: previews unless confirm: true is passed.enrollments.writeنعم

Admin

الأداةالوصفالصلاحيةإجراء حسّاس
dashboard_summaryOwner/manager dashboard summary — currently the tenant-wide billing summary (outstanding balance, collections, overdue).invoices.readلا
get_settingsGet the tenant's effective settings (general, attendance, grading, billing, notifications, curriculum, reminders).settings.manageلا
invite_memberInvite a new member to the tenant by email, with a role. Destructive: previews unless confirm: true is passed.members.manageنعم
list_membersList members of the current tenant, with their assigned roles.members.manageلا
list_rolesList every role (system and custom) in the tenant, with its permissions.roles.manageلا
set_member_rolesSet a member's complete role assignment (within one branch scope, or tenant-wide) to exactly the given list of role ids. Destructive: previews the add/remove diff unless confirm: true is passed.members.manageنعم
update_settingsUpdate one or more tenant settings keys. Destructive: previews the before/after values unless confirm: true is passed.settings.manageنعم

Assessment

الأداةالوصفالصلاحيةإجراء حسّاس
create_examCreate a new exam/quiz/homework/project for a group.assessment.writeلا
generate_progress_reportQueue generation of a progress report for a student or an entire group over a period. Asynchronous — returns immediately once queued.assessment.writeلا
get_student_gradesGet a student's grades (per-group weighted average and per-exam breakdown), optionally scoped to one group.assessment.readلا
publish_examPublish an exam so its results become visible to students/guardians. Destructive: previews unless confirm: true is passed.assessment.writeنعم
record_resultsBulk-record (or update) student scores for an exam.assessment.writeلا
send_progress_reportsSend every published (not-yet-sent) progress report for a student or group to guardians. Destructive: previews the list unless confirm: true is passed.assessment.writeنعم

assignments

الأداةالوصفالصلاحيةإجراء حسّاس
curriculum.assignments.createCreate an assignment unit in a course: a lesson of kind "assignment" plus its instructions, due date, max score, late policy and allowed submission kinds, in one transaction.curriculum.writeلا
curriculum.assignments.grade_submissionGrade a submission (score at most the assignment’s max score, optional feedback). Emits assignment.graded.curriculum.assignments.gradeلا
curriculum.assignments.list_submissionsList an assignment’s submissions (cursor-paginated), optionally filtered by status. lessonId is the assignment unit’s id, or the id of the video lesson that carries the task.curriculum.assignments.gradeلا
curriculum.assignments.publish_to_gradebookPublish every currently-graded submission into the gradebook as a "homework" exam per group — upserts on repeat. Destructive: the first publish for a group creates and publishes a real exam, notifying students/guardians, so it previews unless confirm: true is passed.curriculum.assignments.gradeنعم
curriculum.assignments.return_submissionSend a submission back to the student for revision (clears any earlier grade).curriculum.assignments.gradeلا
curriculum.assignments.updateUpdate an assignment’s own fields (instructions, due date, max score, late policy, allowed submission kinds). Lesson-shared fields (title, section, drip gate) go through update_lesson.curriculum.writeلا
curriculum.lesson_tasks.removeRemove the task under a video lesson. Destructive: previews (with the number of submissions that would be deleted with it) unless confirm: true is passed, which also confirms deleting those submissions.curriculum.writeنعم
curriculum.lesson_tasks.setCreate or replace «مهمة هذا الدرس», the task under a video lesson (instructions, due date, max score, late policy, accepted submission kinds). Submissions, grading and the gradebook publish then use the curriculum.assignments.* tools with the same lessonId.curriculum.writeلا

Attendance

الأداةالوصفالصلاحيةإجراء حسّاس
attendance_reportAttendance report for a group (per-student rates) or a single student (full history), within an optional date range.attendance.readلا
get_session_rosterGet the attendance roster for a scheduled session — every enrolled student and their current attendance mark, if any.attendance.readلا
record_attendanceBulk-record (or update) attendance marks for every student on a session's roster.attendance.markلا

Billing

الأداةالوصفالصلاحيةإجراء حسّاس
billing_summaryTenant-wide billing summary — outstanding balance, this month's collections, and overdue counts/totals.invoices.readلا
create_invoiceCreate a new draft invoice for a student, with one or more line items.invoices.writeلا
get_invoiceGet full details for one invoice, including its lines and payments.invoices.readلا
list_invoicesList invoices, filterable by status (including an "overdue" shorthand), student, guardian, or due-date range.invoices.readلا
record_paymentRecord a payment against an invoice.payments.recordلا
student_statementGet a student's full billing statement — every invoice/payment entry and the running balance.invoices.readلا
void_invoiceVoid an invoice, with a reason. Destructive: previews unless confirm: true is passed.invoices.writeنعم

curriculum

الأداةالوصفالصلاحيةإجراء حسّاس
create_lessonCreate a lesson in a course. Omit sectionId to use (or auto-create) the course’s default section. audienceGroupIds restricts it to those groups of the course; omit or null for every group.curriculum.writeلا
delete_lessonDelete a lesson and its video and progress rows. Destructive: previews (with how many students have progress on it) unless confirm: true is passed.curriculum.writeنعم
get_lessonGet one lesson by id, including its markdown body and video source.curriculum.readلا
grant_course_accessGrant a student access to a self-paced (video) course. Idempotent — granting twice returns the existing enrollment.enrollments.writeلا
list_course_curriculumList a course’s curriculum: its sections, each with the lessons inside it. Published lessons only unless includeDrafts is true.curriculum.readلا
publish_lessonPublish a lesson so enrolled students can see it. Destructive: notifies real people, so it previews unless confirm: true is passed.curriculum.publishنعم
revoke_course_accessRevoke a student’s self-paced course access. Destructive: previews unless confirm: true is passed.enrollments.writeنعم
set_lesson_videoAttach a video to a lesson from a YouTube URL. The URL is validated and normalized exactly as the web editor does.curriculum.writeلا
student_course_progressOne student’s progress through their video courses — lessons completed vs. available, and the last lesson they opened.curriculum.readلا
update_lessonUpdate a lesson’s title, summary, markdown body, estimate, release rules or audience (audienceGroupIds: a list of the course’s group ids to restrict the lesson to those groups, null for every group).curriculum.writeلا

Notifications

الأداةالوصفالصلاحيةإجراء حسّاس
get_notification_ruleOne notification type: the effective rule, the override the institute made, what the type allows and locks, and per channel whether it can deliver, who bills it and the price per message.notifications.readلا
get_notification_spendNotification usage this month per channel and, when the install is on the Institflow messaging relay, the credit balance.notifications.manageلا
list_notification_rulesThe notification rules of the institute: for every kind of notice the system sends — absence, invoices, payments, grades, lessons, assignments, quizzes, class and deadline reminders, subscription alerts — who receives it, on which channels, and whether the institute changed it from the Institflow default.notifications.readلا
notification_usageNotification channel usage/cost for a billing period (defaults to the current month, format YYYY-MM).notifications.readلا
preview_notification_ruleChanges nothing: the estimated monthly cost (a range, in credit units — 10 000 units per credit), how many people a proposed rule would reach, whether saving it needs cost confirmation, and warnings. Omit `rule` to describe the current rule.notifications.readلا
reset_notification_ruleDeletes the override the institute made for one notification type: it goes back to the Institflow default. Destructive: previews the change unless confirm: true is passed. Going back to the default can switch the type or a paid channel on again; that additionally needs confirmCost: true, exactly like update_notification_rule.notifications.manageنعم
send_messageSend a message to a student/guardian/group/branch audience via the notification channel ladder (email/SMS/WhatsApp/push, falling back down the ladder). SMS/WhatsApp are platform/licence-approved per tenant — naming one explicitly in `channels` when it is not approved is rejected; leaving `channels` unset falls through the ladder to an approved channel (in-app always reachable) instead. Destructive: previews recipient count and quota impact unless confirm: true is passed.notifications.sendنعم
update_notification_ruleReplaces the override the institute made for one notification type (a field left out goes back to the Institflow default). Destructive: previews before/after AND the estimated cost unless confirm: true is passed. A change that raises what the institute pays for — a paid channel switched on, recipients, lead times or scope added — additionally needs confirmCost: true, so an assistant cannot spend credit by accident even with confirm.notifications.manageنعم

quizzes

الأداةالوصفالصلاحيةإجراء حسّاس
curriculum.quizzes.add_questionAdd a question to a quiz. Returns the whole quiz (questions included).curriculum.quizzes.manageلا
curriculum.quizzes.createCreate a quiz unit in a course: a lesson of kind "quiz" plus its settings, in one transaction. No questions yet.curriculum.quizzes.manageلا
curriculum.quizzes.delete_questionDelete a quiz question. Returns the whole quiz (questions included).curriculum.quizzes.manageلا
curriculum.quizzes.grade_answerGrade a short-answer (short_text) answer (points at most the question’s own points). Finalises the attempt’s score/passed once nothing is left ungraded. Emits quiz.graded on finalisation.curriculum.assignments.gradeلا
curriculum.quizzes.list_attemptsList a quiz’s attempts (cursor-paginated), optionally filtered by student or status.curriculum.assignments.gradeلا
curriculum.quizzes.publish_to_gradebookPublish each student’s best fully-graded attempt into the gradebook as a "quiz" exam per group — upserts on repeat. Destructive: the first publish for a group creates and publishes a real exam, notifying students/guardians, so it previews unless confirm: true is passed.curriculum.assignments.gradeنعم
curriculum.quizzes.reorder_questionsWhole-list reorder of a quiz’s questions. Returns the whole quiz (questions included).curriculum.quizzes.manageلا
curriculum.quizzes.updateUpdate a quiz’s own settings (time limit, attempts allowed, shuffle, show-answers-after, pass score, due date). Lesson-shared fields go through update_lesson.curriculum.quizzes.manageلا
curriculum.quizzes.update_questionUpdate a quiz question. Returns the whole quiz (questions included).curriculum.quizzes.manageلا

Students

الأداةالوصفالصلاحيةإجراء حسّاس
add_guardianAttach a guardian to a student — either link an existing guardian by id, or create a new one and link it.guardians.writeلا
create_studentCreate a new student record in the current tenant.students.writeلا
get_studentGet full details for one student by id, including guardians and status.students.readلا
search_studentsSearch/list students in the current tenant, filtered by free-text query, status, branch, group, or tag. Cursor-paginated.students.readلا
set_student_statusChange a student's lifecycle status (lead/active/inactive/graduated/withdrawn). Destructive: previews the transition unless confirm: true is passed.students.writeنعم
update_studentUpdate a student's profile fields (name, contact info, tags, ...). Does not change status — use set_student_status for that.students.writeلا

الموارد والمطالبات (Prompts)

موارد للقراءة فقط، تُعنوَن بمعرّف URI، لعميل يريد تحميل سياق دون استدعاء أداة:

URIتُعيد
institflow://student/{id}ملف طالب: بياناته وأولياء أمره وحالته.
institflow://group/{id}جدول مجموعة تدريسية وقائمة طلابها.
institflow://invoice/{id}فاتورة مع بنودها ومدفوعاتها.
institflow://schedule/todayحصص اليوم عبر المستأجر (بحدّ أقصى 100).

مطالبات — قوالب تعليمات جاهزة لإعادة الاستخدام يمكن لعميل عرضها كأمر سريع أو زرّ:

  • monthly_report (المعطيات: groupId أو studentId، وmonth)
  • overdue_followup — صياغة خطّة متابعة للفواتير المتأخّرة.
  • daily_briefing — ملخّص جدول اليوم والغياب وأي تأخّر في السداد.