دليل المطوّر لـ NextPDF Connect
لمحة سريعة
قسم بعنوان «لمحة سريعة»يُغلّف NextPDF Connect (nextpdf/server) محرك NextPDF المستقل عن أُطُر العمل لـ PDF 2.0 بوصفه خدمة. وهو لا يُعيد تنفيذ توليد PDF. بل يعرِض كل قدرة من قدرات المحرك بوصفها أداة مُسمّاة ذات مخطط، ثم يقدّم هذا الفهرس عبر ثلاثة نواقل: Model Context Protocol (MCP) عبر الإدخال والإخراج القياسيَّين، وواجهة برمجة التطبيقات (API) القائمة على نقل الحالة التمثيلي (REST)، وgRPC. استخدم هذا الدليل عند تطوير تكامل فوق الخادم، أو توسيع مجموعة أدواته، أو تشغيله في الإنتاج.
يقوم هذا التصميم على ثلاثة مفاهيم: سجلّ الأدوات، والنواقل الثلاثة المستقلة، وبوابة التأكيد بمشاركة عنصر بشري في الحلقة (HITL). تشرح هذه الصفحة كيف تتكامل هذه المفاهيم، وكيف تتعامل معها دون إضعاف نموذج الأمان. للاطّلاع على رموز الأدوات الدقيقة واستدعاءات الإجراءات البعيدة (RPC) والرسائل، راجع مرجع API.
المتطلّبات المسبقة: PHP 8.4، وComposer 2، وبالنسبة إلى النواقل الشبكية ثنائيّة RoadRunner ومفتاح API واحد على الأقل. ثبّت الحزمة بـ composer require nextpdf/server.
حدود البنية المعمارية
قسم بعنوان «حدود البنية المعمارية»أبقِ كل مسؤولية في موضعها الصحيح ضمن الحدود. فالأداة غلاف رفيع حول استدعاء المحرك؛ ويجب ألّا تتضمّن تفسيرًا للتخطيط، ولا دلالات المستند، ولا منطق التحويل.
| الطبقة | المالك | المسؤولية | لا تضع هنا |
|---|---|---|---|
| العميل أو الوكيل | تكاملك | اختيار الأداة المراد استدعاؤها؛ وتمرير تحدّيات التأكيد إلى عنصر بشري. | منطق المحرك أو كشف الطبقة. |
| الناقل | nextpdf/server | صياغة الطلبات بصيغة JSON-RPC أو HTTP أو Protocol Buffers؛ والمصادقة؛ وتوجيهها إلى مُنفِّذ الأداة. | دلالات المستند. |
| سجلّ الأدوات | nextpdf/server | اكتشاف الطبقات، وتسجيل الأدوات وفق قائمة السماح الأمنية، والبحث عن أداة بالاسم. | توليد PDF. |
| الأداة | nextpdf/server | التحقّق من الوسائط مقابل مخطط الإدخال واستدعاء المحرك. | تفسير التخطيط أو التنسيق متعدّد الخطوات. |
| بوابة التأكيد | nextpdf/server | تعليق عملية ApprovalRequired إلى أن يوافق عليها عنصر بشري. | مصادقة المُستدعِي. |
| المحرك | nextpdf/core (وnextpdf/premium) | توليد محتوى PDF وفحصه وتحويله. | مسؤوليات الناقل أو المصادقة. |
دورة حياة وقت التشغيل
قسم بعنوان «دورة حياة وقت التشغيل»لكل ناقل نقطة دخول ومصنع إقلاع خاصان به. وينشئ كلٌّ منها مخطّط كائناته صراحةً. ولا توجد حاوية حقن تبعيّات يلزم تسجيلها.
- تحميل التهيئة. يحلّ خادم MCP التهيئة من متغيّرات البيئة (
NEXTPDF_MCP_*)، ثم قسمnextpdf_mcpمن ملف YAML، ثم القيم الافتراضية المُدمجة، وينتج عنهاreadonlyMcpConfig. ويقرأ خادما REST وgRPC القيمةHttpConfigمن متغيّرات البيئةNEXTPDF_*. راجع التهيئة. - بناء سياسة الأمان. تُبنى قائمة السماح
enabled_toolsقبل السجلّ، بحيث تُقيّد الاكتشاف منذ أول تسجيل. - إنشاء السجلّ واكتشاف الأدوات. يسجّل
ToolRegistry::registerDefaults()الطبقة الأساسية، ثم مزوّدي Pro وEnterprise عند إمكان حلّ أصنافهما، ثم مزوّدي AST والطفرات المُدمجَين وفق بوّابات البيئة الخاصة بهما. - بناء المخازن المشتركة والبوابة. يُبنى مخزن المستندات في الذاكرة من قيمة TTL والسعة المُهيّأتين؛ ويُجمَّع
ConfirmationGateمع مخزن رموز الاستخدام الواحد الخاص به. - ربط الناقل. يدخل MCP في حلقة قراءة ومعالجة وكتابة عبر stdio حتى نهاية الملف. ويبني خادما REST وgRPC جدول المسارات أو الخدمات لديهما من الطبقات المُكتشفة، ثم يُسلِّمان حلقة الطلبات إلى RoadRunner.
يمرّ الطلب بعد ذلك بهذا المسار: المصادقة (REST وgRPC)، وحلّ الأداة أو العملية، وتشغيل بوابة التأكيد لأعمال ApprovalRequired، والتنفيذ على المحرك، وإرجاع النتيجة. راجع الإقلاع والاكتشاف.
نموذج النواقل
قسم بعنوان «نموذج النواقل»تتشارك النواقل الثلاثة مفاهيم السجلّ والتهيئة والبوابة، لكنها تعمل بوصفها عمليات مستقلة. وبدء أحدها لا يبدأ البقية.
| الناقل | نقطة الدخول | متى تختاره |
|---|---|---|
| MCP | bin/nextpdf-mcp | عميل ذكاء اصطناعي (AI) محلي يُشغّل الخادم بوصفه عمليةً فرعيةً موثوقة. |
| REST | bin/nextpdf-server | عملاء HTTP عبر الشبكة؛ موصوفون بمستند OpenAPI 3.1. |
| gRPC | bin/nextpdf-grpc | عملاء ذوو أنواع محدّدة وتدفّق؛ خدمة nextpdf.connect.v1.NextPDFConnect. |
اختر النواقل بحسب ملف تعريف RoadRunner الذي تُشغّله: .rr.yaml (REST فقط)، أو .rr.grpc.yaml (gRPC فقط)، أو .rr.full.yaml (كليهما). وناقل MCP عملية فرعية بسيطة ولا يحتاج إلى مُشرف. للاطّلاع على تفاصيل الاتصال، راجع ناقل MCP، وناقل REST، وناقل gRPC.
بنية النشر المُوصى بها
قسم بعنوان «بنية النشر المُوصى بها»شغّل النواقل الشبكية تحت RoadRunner مع مخازن مشتركة ومفاتيح مُركّبة من ملفات سرّية. ويتيح ملف التعريف المُدمج لـ REST وgRPC مشاركة مُشرف واحد.
| المسار أو الإعداد | الغرض |
|---|---|
.rr.full.yaml | ملف تعريف مُدمج لـ REST وgRPC تحت مُشرف واحد. |
NEXTPDF_API_KEYS_FILE | مسار إلى ملف مفاتيح API مُركّب من ملف سرّي وقابل لإعادة التحميل السّاخن. |
NEXTPDF_REDIS_HOST | يُمكّن مخازن تحديد المعدّل وثبات الأثر والمستندات المدعومة بـ Redis لتجمّعات العمّال المتعدّدة. |
NEXTPDF_WORKER_COUNT / NEXTPDF_GRPC_WORKER_COUNT | تحديد حجم تجمّع العمّال لتجمّعَي HTTP وgRPC. |
| الدليل الأساس للإخراج | وحدة تخزين مُخصّصة بأذونات نظام ملفات أقل امتياز لأدوات إخراج الملفات. |
يُقلِع نموذج الصدفة التالي ملف التعريف المُدمج بمفاتيح مُركّبة من ملف سرّي ومخزن Redis مشترك. وهو لا يحتوي على أي أسرار؛ إذ تُركّب المفاتيح في /run/secrets/api-keys.
export NEXTPDF_API_KEYS_FILE=/run/secrets/api-keysexport NEXTPDF_WORKER_COUNT=8export NEXTPDF_GRPC_WORKER_COUNT=4export NEXTPDF_REDIS_HOST=redis./vendor/bin/rr serve -c .rr.full.yamlعند استخدام تجمّع عمّال متعدّد، هيّئ Redis وتأكّد من وجود ext-redis في صورة التشغيل. وبدونه تكون مخازن تحديد المعدّل وثبات الأثر والمستندات لكل عامل على حدة. راجع النشر.
سجلّ الأدوات وحلّ الطبقات
قسم بعنوان «سجلّ الأدوات وحلّ الطبقات»يبني NextPDF\Server\ToolRegistry (src/ToolRegistry.php) الفهرس عند الإقلاع. وطبقة كل أداة ثابتة ومُعلَنة: إذ تُرجِع كل أداة tier() وriskLevel() الخاصتَين بها. ولا يستنتج السجلّ الطبقة قط من فضاء الأسماء أو التحزيم.
- الطبقة الأساسية تُسجَّل دون شروط: أدوات المستندات والتشخيص، إضافةً إلى
generate_barcodeعند وجود سجلّ مُرمِّز الباركود الأساسي، وإلىparse_pdfفقط عندما تكون قيمةNEXTPDF_MCP_TOOL_PARSE_PDF_ENABLEDهيtrueأو1. - مزوّدو Pro وEnterprise يُسجَّلون عند إمكان حلّ أصناف مزوّديهم، مع الاستكشاف بـ
class_exists(). وتُتجاوَز أي طبقة غائبة بصمت. - مزوّدو AST والطفرات المُدمجون يُسجَّلون تحت طبقة Pro، مُقيَّدين بـ
NEXTPDF_AST_TOOLS_ENABLEDوNEXTPDF_MUTATION_TOOLS_ENABLED(كلاهما مُمكَّن افتراضيًا). - مُرشِّح سياسة الأمان يتقاطع مع كل تسجيل عبر قائمة السماح
enabled_tools. فقائمة السماح تطرح فقط؛ ولا تضيف قط. ولا تحسب عدّادات كل طبقة إلا الأدوات التي تسمح بها السياسة.
تُبلّغ استجابة initialize في MCP ونقطة النهاية GET /api/v1/capabilities في REST عن الأعداد الناتجة لكل طبقة وعن الإجمالي. عامِل أي إجمالي ثابت في النص بوصفه قديمًا؛ واستعلم الخادم قيد التشغيل. راجع فهرس الأدوات.
طبقات المخاطر وبوابة التأكيد
قسم بعنوان «طبقات المخاطر وبوابة التأكيد»تُعلِن كل أداة عن أحد أربعة مستويات للمخاطر من التعداد RiskLevel (src/Config/RiskLevel.php): Safe (0)، وCaution (1)، وReview (2)، وApprovalRequired (3). ويُطبَّق تسجيل التدقيق عند Caution فما فوق. وقد يرفع تجاوزٌ في التهيئة مخاطر أداة؛ لكنه لا يجوز أن يخفض أداةً هي ApprovalRequired بحكم التصميم. لذلك يرمي مُحمِّل التهيئة استثناءً عند وقت التحميل، ويرفض الخادم الإقلاع بدلًا من العمل ببوابة مُضعَفة.
عند استدعاء أداة ApprovalRequired دون رمز صالح، تُرجِع ConfirmationGate (src/Mcp/ConfirmationGate.php) رمز تحدٍّ ذا استخدام واحد. يربط الرمز اسم الأداة، وقيمة عشوائية لمرة واحدة، ومدة بقاء (TTL) قدرها 300 ثانية، لكنه لا يربط الوسائط، لأن العملاء قد يُعيدون تسلسل الوسائط بترتيب مفاتيح مختلف عند إعادة المحاولة. ينقل الوكيل التحدّي إلى عنصر بشري، ثم يُعيد استدعاء الأداة نفسها مع الرمز في الوسيط _confirmation_token. ويُستهلك الرمز عند الاستخدام، فلا يتيح إلا استدعاءً مُبوَّبًا واحدًا بالضبط.
يوضّح نموذج PHP التالي مُساعِدًا مستقلًا عن الناقل. وهو ينفّذ استدعاء أداة MCP، وعند ورود تحدّي تأكيد يعرض التحدّي على مُوافِق بشري قبل إعادة المحاولة بالرمز الصادر. وهو يُعلِن أنواعًا صارمة، ومُحدَّد الأنواع بالكامل، ويلتقط أكثر الاستثناءات تحديدًا بدلًا من ابتلاع كل خطأ.
<?php
declare(strict_types=1);
namespace App\Connect;
use JsonException;
/** * Drives one tool call and resolves an ApprovalRequired confirmation * challenge through a human approver before retrying. */final readonly class ConfirmingToolCaller{ public function __construct( private McpClientInterface $client, private HumanApproverInterface $approver, ) {}
/** * @param non-empty-string $toolName * @param array<string, mixed> $arguments * * @return array<string, mixed> The tool result content * * @throws JsonException When a response cannot be decoded * @throws ApprovalDeniedException When the human declines the challenge */ public function call(string $toolName, array $arguments): array { $response = $this->client->callTool($toolName, $arguments);
if (!isset($response['challenge'], $response['token'])) { return $response; }
$challenge = (string) $response['challenge']; $token = (string) $response['token'];
if (!$this->approver->approve($toolName, $challenge)) { throw new ApprovalDeniedException($toolName); }
$arguments['_confirmation_token'] = $token;
return $this->client->callTool($toolName, $arguments); }}اربط McpClientInterface وHumanApproverInterface وApprovalDeniedException بناقلك وقناة الموافقة الخاصَّين بك. تُعيد المحاولة استخدام الوسائط الأصلية إضافةً إلى الرمز الصادر؛ ولا تُوافِق آليًا على تحدٍّ قط دون قرار بشري. راجع طبقات مخاطر HITL.
نقاط التوسيع
قسم بعنوان «نقاط التوسيع»وسّع الخادم بإضافة الأدوات وتوفير المزوّدين، لا بتحرير السجلّ.
| نقطة التوسيع | استخدمها لـ | القيد |
|---|---|---|
صنف يُنفّذ ToolInterface | قدرة محرك جديدة مُتاحة بوصفها أداة. | أعلِن tier() وriskLevel() وcategory() ومخطط JSON Schema لـ inputSchema()؛ وأبقِ الصنف غلافًا رفيعًا للمحرك. |
مزوّد ToolProviderInterface | تسجيل مجموعة من الأدوات لطبقة. | يُستكشف مزوّدو Pro وEnterprise بـ class_exists()؛ ولا تطلب الحزمة المملوكة من الخادم. |
enabled_tools قائمة السماح | تحديد نطاق الفهرس المُتاح وفق أقل امتياز. | قائمة السماح تطرح فقط؛ ولا يمكنها تسجيل أداة غائبة. |
risk_level_overrides | تقوية النشر برفع مستوى مخاطر أداة. | الترقية فقط؛ وخفض أداة ApprovalRequired يُفشِل الإقلاع. |
| وصلات الناقل والعامل القابلة للحقن | اختبار الخادم بمعزل. | هذه الحدود موجودة للاختبارات، لا لربط التطبيق. |
سير عمل العمليات
قسم بعنوان «سير عمل العمليات»- اختر ملف تعريف. شغّل
.rr.yamlأو.rr.grpc.yamlأو.rr.full.yamlللنواقل التي تُتيحها. - ركّب المفاتيح من ملف سرّي. وجّه
NEXTPDF_API_KEYS_FILEإلى ملف سرّي؛ وفضّل مخزن مفاتيح الملف القابل لإعادة التحميل الساخن بحيث لا يتطلّب التدوير إعادة تشغيل. - هيّئ المخازن المشتركة. عيّن
NEXTPDF_REDIS_HOSTوتأكّد منext-redisلأي تجمّع أكبر من عامل واحد؛ وضع مخزن مهام SQLite على وحدة تخزين يستطيع كل العمّال الكتابة إليها. - أنهِ TLS. شغّل REST خلف مُنهِي أمان طبقة النقل (TLS)؛ وشغّل gRPC بـ TLS مُتبادل على أي شبكة غير موثوقة، مع توفير مفتاح الخادم وشهادة الخادم وسلطة شهادة العميل بوصفها أسرار نشر.
- افحص الصحة. استخدم نقطتَي النهاية غير المصادقتين
/healthzو/readyz(REST) أو استدعاءَي الإجراء البعيدHealthCheckوReadinessCheck(gRPC) لفحوصات المُنسِّق. - حدّد نطاق الفهرس. قيّد
enabled_toolsعلى أصغر مجموعة يحتاجها التكامل.
تحقّق من صحة Redis بدلًا من افتراضها. يرجع خادم REST إلى مخازن في الذاكرة عند فشل الاتصال بـ Redis المُهيّأ. راجع النشر والأمان والعمليات.
معالجة الأعطال
قسم بعنوان «معالجة الأعطال»| العطل | حيث يظهر | الاستجابة المُوصى بها |
|---|---|---|
document_id غير معروف | تنفيذ الأداة | أرجِع خطأً مُعرَّفًا إلى المُستدعِي؛ ووجّهه إلى استدعاء create_pdf أولًا. |
| ETag قديم على طفرة | أداة طفرات AST | أعِد قراءة المستند بـ get_document_ast وأعِد المحاولة بـ ETag حديث. |
| مفتاح API مفقود أو غير صالح (REST) | وسيط المصادقة | أرجِع 401 مع تحدّي WWW-Authenticate: Bearer؛ ولا تُسرّب أي جزء كان خاطئًا. |
| الطبقة غير مُستحَقّة (REST) | التخويل | أرجِع 403؛ فطبقة المفتاح أدنى من طبقة العملية. |
| مسار الطبقة غائب (REST) | المُوجِّه | أرجِع 404؛ فالحزمة غير مُثبَّتة. هذه حالة متوقَّعة، لا عطل. |
| رمز غير صالح (gRPC) | مُصادِق gRPC | أفشِل الاستدعاء بـ UNAUTHENTICATED. |
| تعذّر الوصول إلى Redis | الإقلاع أو وقت التشغيل | انتقل إلى مخازن في الذاكرة؛ ونبّه المُشغّلين وتحقّق من صحة Redis. |
| مسار إخراج خارج الدليل الأساس | أداة إخراج الملفات | أفشِل مُغلَقًا؛ فالمسار يُحوَّل إلى صيغته القانونية ويُرفَض الاجتياز. |
أظهِر أعطال المحرك بوصفها كائنات أخطاء مُعرَّفة، لا بوصفها نجاحات صامتة قط. يُفصّل مرجع API نموذج الأخطاء لكل ناقل.
القيم الافتراضية الآمنة
قسم بعنوان «القيم الافتراضية الآمنة»| الشأن | الافتراضي | متى تتجاوزه |
|---|---|---|
parse_pdf | مُعطَّل (تفعيل اختياري عبر NEXTPDF_MCP_TOOL_PARSE_PDF_ENABLED). | فعّله فقط عندما يحتاج التكامل إلى فحص بنيوي. |
enabled_tools | فارغة (تُسمح كل الأدوات المُكتشفة). | عيّن قائمة سماح صريحة لعمليات النشر بأقل امتياز. |
| تجاوزات المخاطر | لا شيء. | ارفع المخاطر لنشر مُقوّى؛ ولا تحاول الخفض قط. |
document_ttl / max_documents | 1800 ثانية / 50 مستندًا. | اخفضهما لعمليات النشر الحسّاسة لمتطلبات الإقامة أو المحدودة الذاكرة. |
allow_file_output | مُمكَّن. | عيّنه إلى false لعمليات النشر عديمة الحالة والحسّاسة للإقامة. |
| عدد العمّال | أربعة (HTTP)، اثنان (gRPC). | حدّد الحجم وفق زمن الاستجابة المُلاحَظ والأنوية المتاحة. |
| مُستمِع REST | HTTP بنص صريح خلف مُنهِي TLS. | أنهِ TLS دائمًا في الأعلى؛ ولا تُعرّض HTTP بنص صريح على شبكة غير موثوقة قط. |
| gRPC على الشبكات غير الموثوقة | TLS مُتبادل. | مطلوب؛ ولا تُشغّل مُستمِع gRPC بنص صريح على شبكة غير موثوقة قط. |
قائمة فحص الاختبار
قسم بعنوان «قائمة فحص الاختبار»- تتحقّق اختبارات السجلّ من تجاوز طبقة Pro أو Enterprise الغائبة بصمت ومن استمرار تسجيل الفهرس الأساسي.
- تتحقّق اختبارات قائمة السماح من أن
enabled_toolsتطرح ولا تضيف قط أداةً لم يكتشفها السجلّ. - تتحقّق اختبارات بوابة التأكيد من أن أداة
ApprovalRequiredتُرجِع تحدّيًا عند أول استدعاء، وتعمل مرة واحدة برمز صالح ذي استخدام واحد، وتنتهي صلاحية الرمز بعد مدة بقائه. - تتحقّق اختبارات الخفض من أن مُدخل
risk_level_overridesالذي يُضعِف أداةApprovalRequiredيُفشِل الإقلاع. - تغطّي اختبارات المصادقة المفاتيح المفقودة والمُشوَّهة والمُعطَّلة والمنتهية في REST (
401معWWW-Authenticate) وgRPC (UNAUTHENTICATED)، ورفض استحقاق الطبقة (403). - تتحقّق اختبارات التزامن من أن ETag القديم يُفشِل الطفرة وأن تكرار
idempotency_keyيُعيد النتيجة المُخزَّنة مؤقتًا. - تتحقّق اختبارات احتواء المسار من رفض مسار إخراج ملف يُحَلّ خارج الدليل الأساس.
- أبقِ التجهيزات صغيرة وغير حسّاسة؛ ولا تُودِع مفتاح API حقيقيًا أو محتوى مستند قط.
انظر أيضًا
قسم بعنوان «انظر أيضًا»- مرجع API — رموز الأدوات وRPC والرسائل الدقيقة
- فهرس الأدوات — المجموعة الأساسية المُتحقَّق منها وأعداد وقت التشغيل
- طبقات مخاطر HITL — نموذج المخاطر وغلاف التأكيد
- التهيئة — ترتيب الحلّ وتجاوز الترقية فقط
- النشر — ملفات تعريف RoadRunner وRedis وTLS المُتبادل
- الأمان والعمليات — المصادقة وأمان الناقل ونموذج التهديد