تخطَّ إلى المحتوى

دليل المطوّر لـ 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/corenextpdf/premium)توليد محتوى ⁨PDF⁩ وفحصه وتحويله.مسؤوليات الناقل أو المصادقة.

لكل ناقل نقطة دخول ومصنع إقلاع خاصان به. وينشئ كلٌّ منها مخطّط كائناته صراحةً. ولا توجد حاوية حقن تبعيّات يلزم تسجيلها.

  1. تحميل التهيئة. يحلّ خادم ⁨MCP⁩ التهيئة من متغيّرات البيئة (NEXTPDF_MCP_*)، ثم قسم nextpdf_mcp من ملف ⁨YAML⁩، ثم القيم الافتراضية المُدمجة، وينتج عنها readonlyMcpConfig. ويقرأ خادما ⁨REST⁩ و⁨gRPC⁩ القيمة HttpConfig من متغيّرات البيئة NEXTPDF_*. راجع التهيئة.
  2. بناء سياسة الأمان. تُبنى قائمة السماح enabled_tools قبل السجلّ، بحيث تُقيّد الاكتشاف منذ أول تسجيل.
  3. إنشاء السجلّ واكتشاف الأدوات. يسجّل ToolRegistry::registerDefaults() الطبقة الأساسية، ثم مزوّدي ⁨Pro⁩ و⁨Enterprise⁩ عند إمكان حلّ أصنافهما، ثم مزوّدي ⁨AST⁩ والطفرات المُدمجَين وفق بوّابات البيئة الخاصة بهما.
  4. بناء المخازن المشتركة والبوابة. يُبنى مخزن المستندات في الذاكرة من قيمة ⁨TTL⁩ والسعة المُهيّأتين؛ ويُجمَّع ConfirmationGate مع مخزن رموز الاستخدام الواحد الخاص به.
  5. ربط الناقل. يدخل ⁨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.

Terminal window
export NEXTPDF_API_KEYS_FILE=/run/secrets/api-keys
export NEXTPDF_WORKER_COUNT=8
export NEXTPDF_GRPC_WORKER_COUNT=4
export NEXTPDF_REDIS_HOST=redis
./vendor/bin/rr serve -c .rr.full.yaml

عند استخدام تجمّع عمّال متعدّد، هيّئ ⁨Redis⁩ وتأكّد من وجود ext-redis في صورة التشغيل. وبدونه تكون مخازن تحديد المعدّل وثبات الأثر والمستندات لكل عامل على حدة. راجع النشر.

يبني NextPDF\Server\ToolRegistry (src/ToolRegistry.php) الفهرس عند الإقلاع. وطبقة كل أداة ثابتة ومُعلَنة: إذ تُرجِع كل أداة tier() وriskLevel() الخاصتَين بها. ولا يستنتج السجلّ الطبقة قط من فضاء الأسماء أو التحزيم.

  1. الطبقة الأساسية تُسجَّل دون شروط: أدوات المستندات والتشخيص، إضافةً إلى generate_barcode عند وجود سجلّ مُرمِّز الباركود الأساسي، وإلى parse_pdf فقط عندما تكون قيمة NEXTPDF_MCP_TOOL_PARSE_PDF_ENABLED هي true أو 1.
  2. مزوّدو ⁨Pro⁩ و⁨Enterprise⁩ يُسجَّلون عند إمكان حلّ أصناف مزوّديهم، مع الاستكشاف بـ class_exists(). وتُتجاوَز أي طبقة غائبة بصمت.
  3. مزوّدو ⁨AST⁩ والطفرات المُدمجون يُسجَّلون تحت طبقة ⁨Pro⁩، مُقيَّدين بـ NEXTPDF_AST_TOOLS_ENABLED وNEXTPDF_MUTATION_TOOLS_ENABLED (كلاهما مُمكَّن افتراضيًا).
  4. مُرشِّح سياسة الأمان يتقاطع مع كل تسجيل عبر قائمة السماح 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⁩، وعند ورود تحدّي تأكيد يعرض التحدّي على مُوافِق بشري قبل إعادة المحاولة بالرمز الصادر. وهو يُعلِن أنواعًا صارمة، ومُحدَّد الأنواع بالكامل، ويلتقط أكثر الاستثناءات تحديدًا بدلًا من ابتلاع كل خطأ.

examples/connect/confirm-and-call.php
<?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 يُفشِل الإقلاع.
وصلات الناقل والعامل القابلة للحقناختبار الخادم بمعزل.هذه الحدود موجودة للاختبارات، لا لربط التطبيق.
  1. اختر ملف تعريف. شغّل .rr.yaml أو .rr.grpc.yaml أو .rr.full.yaml للنواقل التي تُتيحها.
  2. ركّب المفاتيح من ملف سرّي. وجّه NEXTPDF_API_KEYS_FILE إلى ملف سرّي؛ وفضّل مخزن مفاتيح الملف القابل لإعادة التحميل الساخن بحيث لا يتطلّب التدوير إعادة تشغيل.
  3. هيّئ المخازن المشتركة. عيّن NEXTPDF_REDIS_HOST وتأكّد من ext-redis لأي تجمّع أكبر من عامل واحد؛ وضع مخزن مهام ⁨SQLite⁩ على وحدة تخزين يستطيع كل العمّال الكتابة إليها.
  4. أنهِ ⁨TLS.⁩ شغّل ⁨REST⁩ خلف مُنهِي أمان طبقة النقل (⁨TLS⁩)؛ وشغّل ⁨gRPC⁩ بـ ⁨TLS⁩ مُتبادل على أي شبكة غير موثوقة، مع توفير مفتاح الخادم وشهادة الخادم وسلطة شهادة العميل بوصفها أسرار نشر.
  5. افحص الصحة. استخدم نقطتَي النهاية غير المصادقتين /healthz و/readyz (⁨REST⁩) أو استدعاءَي الإجراء البعيد HealthCheck وReadinessCheck (⁨gRPC⁩) لفحوصات المُنسِّق.
  6. حدّد نطاق الفهرس. قيّد 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_documents1800 ثانية / 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⁩ حقيقيًا أو محتوى مستند قط.