Eine Agenten-Dokumentsitzung über MCP steuern
Auf einen Blick
Abschnitt betitelt „Auf einen Blick“Dies ist eine vollständige Agentensitzung mit dem Model-Context-Protocol-Server
(MCP) von NextPDF Connect, Nachricht für Nachricht: initialize,
tools/list, sechs tools/call-Aufrufe, die ein einseitiges Projekt-Briefing
erstellen, und der Human-in-the-Loop-Roundtrip (HITL), der den finalen
Dateischreibvorgang absichert. Jede der folgenden JSON-RPC-Nachrichten wurde
wortgetreu aus einem laufenden bin/nextpdf-mcp-Prozess (ausschließlich
Core-Tier-Tools) aufgezeichnet und anschließend in genau zwei Punkten bereinigt: Das einmalig
verwendbare Bestätigungs-Token wird als
confirm_<single-use-hex> dargestellt, und das temporäre Systemverzeichnis des
Rechners ist auf C:\Temp gekürzt. Bezeichner, Schemata, Positionen und
Byte-Zahlen sind exakt das, was der Server gesendet hat.
Installation
Abschnitt betitelt „Installation“composer require nextpdf/serverBinden Sie den Stdio-Transport in Ihren MCP-Host ein — für Claude Desktop (Hosts starten den Befehl aus ihrem eigenen Verzeichnis, verwenden Sie daher einen absoluten Pfad; der Stdio-Transport benötigt, anders als der REST-Transport, keinen API-Schlüssel):
{ "mcpServers": { "nextpdf": { "command": "php", "args": ["/absolute/path/to/your/project/vendor/bin/nextpdf-mcp"] } }}Der Server spricht zeilengetrenntes JSON-RPC 2.0 über stdin/stdout und hält die Protokollausgabe strikt von der Diagnose getrennt: Start- und Audit-Zeilen gehen an stderr, niemals an stdout.
Konzeptioneller Überblick
Abschnitt betitelt „Konzeptioneller Überblick“Eine MCP-Dokumentsitzung ist zustandsbehaftet. create_pdf öffnet ein Dokument im
speicherinternen Store des Servers und gibt eine document_id zurück; jeder
spätere Aufruf adressiert diesen Bezeichner. Inhalts-Tools (set_font, add_text,
add_table) werden sofort auf der Risikostufe Vorsicht mit
Audit-Protokollierung ausgeführt; preview_layout ist ein sicherer Lesevorgang;
und output_pdf mit einem file_path ist „Genehmigung erforderlich“ — es läuft
beim ersten Aufruf nicht. Stattdessen gibt der Server eine Challenge mit einem
einmalig verwendbaren Token zurück, der Agent gibt die Challenge an den Menschen
weiter, und erst ein erneuter Aufruf mit _confirmation_token führt den
Schreibvorgang aus. Im Store verbliebene Dokumente laufen nach der konfigurierten
Lebensdauer ab (standardmäßig 30 Minuten).
Dieselben Tool-Aufrufe steuern die Tool-Engine über REST und gRPC — die Transporte teilen sich einen Executor — sodass alles hier außer dem Stdio-Framing übertragbar ist. Siehe Eine Rechnung durchgängig über REST rendern für dieselbe Engine auf der HTTP-Oberfläche.
API-Oberfläche
Abschnitt betitelt „API-Oberfläche“| Tool | Rolle in dieser Sitzung | Risikostufe |
|---|---|---|
create_pdf | Das Dokument öffnen, document_id erhalten | Vorsicht |
set_font | Überschrift, dann Fließtextschrift wählen | Vorsicht |
add_text | Titelzeile, dann Einleitungsabsatz | Vorsicht |
add_table | Checklisten-Tabelle mit Verantwortlichen/Fälligkeitsdaten | Vorsicht |
preview_layout | Layout-Status vor der Ausgabe lesen | Sicher |
output_pdf (file-Modus) | Das PDF schreiben — über das Gate | Genehmigung erforderlich |
Das hier aufgezeichnete Deployment registrierte 20 Tools (13 Core, 6 Pro, 1
Enterprise — die Zahlen erscheinen weiter unten in der initialize-Antwort); diese
Sitzung verwendet ausschließlich Core-Tools und läuft daher unverändert auf einer
reinen Open-Source-Installation. Maßgeblich ist die tools/list-Antwort Ihres
eigenen Servers, und die Risikoleiter ist in der
Referenz zu den HITL-Risikostufen definiert.
Die Sitzung, Nachricht für Nachricht
Abschnitt betitelt „Die Sitzung, Nachricht für Nachricht“1. Die Verbindung initialisieren
Abschnitt betitelt „1. Die Verbindung initialisieren“Der Client eröffnet die Sitzung und gibt seine Protokollversion an:
{ "jsonrpc": "2.0", "id": 1, "method": "initialize", "params": { "protocolVersion": "2025-06-18", "capabilities": {}, "clientInfo": { "name": "planning-agent", "version": "1.0.0" } }}Der Server bestätigt die Protokollversion und deklariert seine Capabilities, einschließlich der Tool-Zahlen je Tier und der Aktivierung des HITL-Gatings:
{ "jsonrpc": "2.0", "id": 1, "result": { "protocolVersion": "2025-06-18", "capabilities": { "tools": { "listChanged": false }, "nextpdf": { "tiers": { "core": 13, "pro": 6, "enterprise": 1 }, "tool_count": 20, "risk_model_version": 1, "hitl_enabled": true } }, "serverInfo": { "name": "NextPDF Connect", "version": "1.0.0" } }}Der Client quittiert mit einer Notification (Notifications tragen keine id
und erhalten keine Antwort):
{ "jsonrpc": "2.0", "method": "notifications/initialized"}2. Die Tools ermitteln
Abschnitt betitelt „2. Die Tools ermitteln“{ "jsonrpc": "2.0", "id": 2, "method": "tools/list"}Die vollständige Antwort listet alle 20 registrierten Tools mit ihren kompletten Eingabeschemata auf. Sie ist hier auf die zwei Tools gekürzt dargestellt, die diese Sitzung eröffnen und beenden — die ausgelassenen 18 Einträge haben dieselbe Struktur:
{ "jsonrpc": "2.0", "id": 2, "result": { "tools": [ { "name": "create_pdf", "description": "Create a new PDF document and return a document_id for subsequent operations", "inputSchema": { "type": "object", "properties": { "page_size": { "type": "string", "description": "Page size name (e.g. \"A4\", \"Letter\", \"Legal\", \"A3\")", "default": "A4" }, "orientation": { "type": "string", "enum": [ "portrait", "landscape" ], "description": "Page orientation", "default": "portrait" }, "title": { "type": "string", "description": "Document title metadata" }, "author": { "type": "string", "description": "Document author metadata" } }, "required": [] }, "annotations": { "destructiveHint": false, "idempotentHint": false } }, { "name": "output_pdf", "description": "Finalize the PDF and output to file or return as base64", "inputSchema": { "type": "object", "properties": { "document_id": { "type": "string", "description": "The document_id returned by create_pdf" }, "file_path": { "type": "string", "description": "Absolute file path to save the PDF. If omitted, returns base64-encoded PDF data." }, "destroy": { "type": "boolean", "description": "Whether to remove the document from the store after output", "default": true } }, "required": [ "document_id" ] }, "annotations": { "destructiveHint": false, "openWorldHint": true } } ] }}Beachten Sie das Schema von output_pdf: file_path ist optional, und die
Annotationen tragen openWorldHint: true — das Tool kann auf die Welt außerhalb
der Sitzung einwirken, und genau deshalb läuft der file-Modus über das Gate.
3. Das Dokument öffnen
Abschnitt betitelt „3. Das Dokument öffnen“{ "jsonrpc": "2.0", "id": 3, "method": "tools/call", "params": { "name": "create_pdf", "arguments": { "page_size": "A4", "orientation": "portrait", "title": "Project kickoff brief", "author": "Planning agent" } }}{ "jsonrpc": "2.0", "id": 3, "result": { "content": [ { "type": "text", "text": "{\"document_id\":\"doc_3b9f435efa0f32d1da7a131d\",\"page_count\":1,\"page_size\":\"A4\",\"orientation\":\"portrait\"}" } ], "structuredContent": { "document_id": "doc_3b9f435efa0f32d1da7a131d", "page_count": 1, "page_size": "A4", "orientation": "portrait" } }}Jedes Tool-Ergebnis kommt zweifach in einer Nachricht an: als menschenlesbarer
content-Textblock und als maschinenlesbarer structuredContent. Lesen Sie
structuredContent.document_id aus und führen Sie sie durch jeden folgenden
Aufruf.
4. Die Überschrift hinzufügen
Abschnitt betitelt „4. Die Überschrift hinzufügen“Setzen Sie eine fette 16-Punkt-Schrift und platzieren Sie dann den Titel:
{ "jsonrpc": "2.0", "id": 4, "method": "tools/call", "params": { "name": "set_font", "arguments": { "document_id": "doc_3b9f435efa0f32d1da7a131d", "family": "helvetica", "style": "B", "size": 16 } }}{ "jsonrpc": "2.0", "id": 4, "result": { "content": [ { "type": "text", "text": "Font set to helvetica B 16pt on document doc_3b9f435efa0f32d1da7a131d." } ] }}{ "jsonrpc": "2.0", "id": 5, "method": "tools/call", "params": { "name": "add_text", "arguments": { "document_id": "doc_3b9f435efa0f32d1da7a131d", "text": "Project kickoff brief" } }}{ "jsonrpc": "2.0", "id": 5, "result": { "content": [ { "type": "text", "text": "{\"document_id\":\"doc_3b9f435efa0f32d1da7a131d\",\"position\":{\"x\":10,\"y\":16,\"page\":0}}" } ], "structuredContent": { "document_id": "doc_3b9f435efa0f32d1da7a131d", "position": { "x": 10, "y": 16, "page": 0 } } }}5. Den Fließtextabsatz hinzufügen
Abschnitt betitelt „5. Den Fließtextabsatz hinzufügen“Zurück zu einer regulären 11-Punkt-Schrift für den Einleitungstext; width: 0
wählt ein Multi-Cell-Layout über die volle Breite:
{ "jsonrpc": "2.0", "id": 6, "method": "tools/call", "params": { "name": "set_font", "arguments": { "document_id": "doc_3b9f435efa0f32d1da7a131d", "family": "helvetica", "style": "", "size": 11 } }}{ "jsonrpc": "2.0", "id": 6, "result": { "content": [ { "type": "text", "text": "Font set to helvetica 11pt on document doc_3b9f435efa0f32d1da7a131d." } ] }}{ "jsonrpc": "2.0", "id": 7, "method": "tools/call", "params": { "name": "add_text", "arguments": { "document_id": "doc_3b9f435efa0f32d1da7a131d", "text": "Prepared by the planning agent for the 14 July kickoff. Scope, owners, and the first-week checklist are tabled below.", "width": 0, "line_height": 6 } }}{ "jsonrpc": "2.0", "id": 7, "result": { "content": [ { "type": "text", "text": "{\"document_id\":\"doc_3b9f435efa0f32d1da7a131d\",\"position\":{\"x\":10,\"y\":29.75,\"page\":0}}" } ], "structuredContent": { "document_id": "doc_3b9f435efa0f32d1da7a131d", "position": { "x": 10, "y": 29.75, "page": 0 } } }}6. Die Checklisten-Tabelle hinzufügen
Abschnitt betitelt „6. Die Checklisten-Tabelle hinzufügen“{ "jsonrpc": "2.0", "id": 8, "method": "tools/call", "params": { "name": "add_table", "arguments": { "document_id": "doc_3b9f435efa0f32d1da7a131d", "html": "<table><tr><th>Work item</th><th>Owner</th><th>Due</th></tr><tr><td>Repository bootstrap</td><td>Devon</td><td>2026-07-15</td></tr><tr><td>CI pipeline</td><td>Ana</td><td>2026-07-17</td></tr><tr><td>Staging deploy</td><td>Priya</td><td>2026-07-21</td></tr></table>" } }}{ "jsonrpc": "2.0", "id": 8, "result": { "content": [ { "type": "text", "text": "{\"document_id\":\"doc_3b9f435efa0f32d1da7a131d\",\"position\":{\"x\":10,\"y\":84.75,\"page\":0}}" } ], "structuredContent": { "document_id": "doc_3b9f435efa0f32d1da7a131d", "position": { "x": 10, "y": 84.75, "page": 0 } } }}Jeder Inhaltsaufruf gibt die aktualisierte Cursor-position zurück, sodass der
Agent stets weiß, wo das nächste Element landet.
7. Vorschau, bevor eine Freigabe angefordert wird
Abschnitt betitelt „7. Vorschau, bevor eine Freigabe angefordert wird“preview_layout ist ein nur lesender Aufruf der Risikostufe Sicher — ein
wohlerzogener Agent prüft, was er erstellt hat, bevor er einen Menschen um die
Freigabe eines Schreibvorgangs bittet:
{ "jsonrpc": "2.0", "id": 9, "method": "tools/call", "params": { "name": "preview_layout", "arguments": { "document_id": "doc_3b9f435efa0f32d1da7a131d" } }}{ "jsonrpc": "2.0", "id": 9, "result": { "content": [ { "type": "text", "text": "{\"document_id\":\"doc_3b9f435efa0f32d1da7a131d\",\"total_pages\":1,\"current_page\":0,\"page_dimensions\":{\"width\":595.276,\"height\":841.89},\"margins\":{\"top\":10,\"right\":10,\"bottom\":10,\"left\":10},\"cursor_position\":{\"x\":10,\"y\":84.75}}" } ], "structuredContent": { "document_id": "doc_3b9f435efa0f32d1da7a131d", "total_pages": 1, "current_page": 0, "page_dimensions": { "width": 595.276, "height": 841.89 }, "margins": { "top": 10, "right": 10, "bottom": 10, "left": 10 }, "cursor_position": { "x": 10, "y": 84.75 } } }}8. Den Dateischreibvorgang anfordern — das Gate antwortet zuerst
Abschnitt betitelt „8. Den Dateischreibvorgang anfordern — das Gate antwortet zuerst“Der Agent bittet output_pdf, das fertige Briefing auf die Festplatte zu
schreiben, und hält das Dokument am Leben (destroy: false), falls der Mensch
ablehnt und auf die base64-Ausgabe zurückgegriffen werden muss:
{ "jsonrpc": "2.0", "id": 10, "method": "tools/call", "params": { "name": "output_pdf", "arguments": { "document_id": "doc_3b9f435efa0f32d1da7a131d", "file_path": "C:\\Temp\\nextpdf-mcp\\kickoff-brief.pdf", "destroy": false } }}Die Datei wird nicht geschrieben. Da der file-Modus „Genehmigung erforderlich“ ist, antwortet der Server stattdessen mit einer Bestätigungs-Challenge:
{ "jsonrpc": "2.0", "id": 10, "result": { "content": [ { "type": "text", "text": "⚠️ CONFIRMATION REQUIRED\n\nOperation: output_pdf\nDescription: Finalize the PDF and output to file or return as base64\n\nTo proceed, call output_pdf again with parameter _confirmation_token: \"confirm_<single-use-hex>\"\nExpires in 300 seconds." } ], "isError": false }}9. Der Mensch genehmigt — erneuter Aufruf mit dem Token
Abschnitt betitelt „9. Der Mensch genehmigt — erneuter Aufruf mit dem Token“Der Agent gibt den Challenge-Text an den Menschen weiter. Nach der Freigabe ruft
er output_pdf erneut mit denselben Argumenten plus _confirmation_token auf:
{ "jsonrpc": "2.0", "id": 11, "method": "tools/call", "params": { "name": "output_pdf", "arguments": { "document_id": "doc_3b9f435efa0f32d1da7a131d", "file_path": "C:\\Temp\\nextpdf-mcp\\kickoff-brief.pdf", "destroy": false, "_confirmation_token": "confirm_<single-use-hex>" } }}Das Token wird verbraucht, der Schreibvorgang wird ausgeführt, und das Ergebnis meldet die geschriebene Datei:
{ "jsonrpc": "2.0", "id": 11, "result": { "content": [ { "type": "text", "text": "{\"document_id\":\"doc_3b9f435efa0f32d1da7a131d\",\"file_path\":\"C:\\\\Temp\\\\nextpdf-mcp\\\\kickoff-brief.pdf\",\"file_size\":3612,\"page_count\":1,\"destroyed\":false}" } ], "structuredContent": { "document_id": "doc_3b9f435efa0f32d1da7a131d", "file_path": "C:\\Temp\\nextpdf-mcp\\kickoff-brief.pdf", "file_size": 3612, "page_count": 1, "destroyed": false } }}Die geschriebene Datei überprüfen
Abschnitt betitelt „Die geschriebene Datei überprüfen“Die Sitzung schrieb kickoff-brief.pdf (3.612 Bytes, eine Seite, passend zu
structuredContent.file_size und page_count). Aufgezeichnete qpdf --check-
Ausgabe für genau diese Datei:
checking kickoff-brief.pdfPDF Version: 2.0File is not encryptedFile is not linearizedNo syntax or stream encoding errors found; the file may still containerrors that qpdf cannot detectDas ist eine Strukturprüfung, in qpdfs eigenen Worten — keine Konformitätsfeststellung.
Grenzfälle und Fallstricke
Abschnitt betitelt „Grenzfälle und Fallstricke“- Der erneute Aufruf muss dieselben Argumente wiederholen. Das
Bestätigungs-Token ist an den Toolnamen sowie an einen kanonischen Digest der
Argumente gebunden, für die es ausgestellt wurde. Ein erneuter Aufruf mit
irgendeiner Änderung — selbst das Umschalten von
destroy— verbraucht das Token nicht; der Server antwortet stattdessen mit einer neuen Challenge. Wiederholen Sie die Argumente exakt und fügen Sie ausschließlich_confirmation_tokenhinzu. - Das Token ist einmalig verwendbar und läuft ab. Die Challenge nennt die Ablaufzeit (300 Sekunden). Nach Ablauf oder Verbrauch erhält der nächste über das Gate laufende Aufruf eine neue Challenge; geben Sie die neue weiter.
- Die Dateiausgabe landet in einem auf der Allow-Liste stehenden Verzeichnis.
Der Server weist einen
file_pathaußerhalb seines konfigurierten temporären Verzeichnisses mitOutput path rejected by security policyzurück. Der Standard-Wurzelpfad der Allow-Liste istnextpdf-mcpunter dem temporären Systemverzeichnis; Betreiber ändern ihn über die Einstellungtemp_dirinnextpdf-mcp.yaml. - Der base64-Modus läuft nicht über das Gate.
output_pdfohnefile_pathgibt das PDF als base64 auf der Review-Stufe zurück, ohne Seiteneffekt im Dateisystem — siehe Menschliche Freigabe für die Dateiausgabe verlangen für diese Grenze im Detail. - Eine Challenge ist ein Ergebnis, kein Fehler. Die Challenge-Nachricht
kommt mit
isError: falsean; eine ausstehende Freigabe ist eine Workflow-Pause. Wiederholen Sie den Aufruf nicht in einer Schleife und erfinden Sie niemals ein Token. - Notifications erhalten keine Antwort. Blockieren Sie nach
notifications/initializednicht in der Erwartung einer Antwortzeile.
Performance
Abschnitt betitelt „Performance“Die Sitzung läuft durchgängig im Arbeitsspeicher: Inhaltsaufrufe kehrten im aufgezeichneten Lauf in Millisekunden zurück, und die Gesamtlaufzeit wird vom menschlichen Freigabe-Roundtrip dominiert — was gerade der Sinn des Gates ist. Der Dokumentspeicher hält eine Sitzung standardmäßig 30 Minuten im Leerlauf (maximal 50 Dokumente), sodass eine langsame Freigabe das erstellte Dokument nicht verliert — ein aufgegebenes wird jedoch zurückgewonnen.
Sicherheitshinweise
Abschnitt betitelt „Sicherheitshinweise“- Behandeln Sie das Bestätigungs-Token als einmaliges Geheimnis. Geben Sie den Challenge-Text an den Menschen weiter; protokollieren oder speichern Sie das Token nicht. Diese Seite schwärzt das aufgezeichnete Token aus genau diesem Grund.
- Der Audit-Trail liegt auf stderr. Jede Ausführung ab der Stufe Vorsicht wird per PSR-3 protokolliert (Tool, Risiko, Argumente, Ergebnis), wobei sensible Parameter geschwärzt werden. Diagnose vermischt sich niemals mit dem Protokollstrom.
- Die Pfad-Allow-Liste ist die Dateisystemgrenze. Richten Sie
temp_dirauf ein Verzeichnis, das ausschließlich der Connect-Ausgabe dient; weiten Sie es nicht auf einen Allzweck-Speicherort aus. - Risikostufen können nur nach oben verschoben werden. Ein Betreiber-Override
in
nextpdf-mcp.yamlkann die Risikostufe eines Tools anheben,output_pdfjedoch niemals unter „Genehmigung erforderlich“ senken.
Konformität
Abschnitt betitelt „Konformität“Dieses Rezept erhebt keinen normativen Standardanspruch. Es dokumentiert den
MCP-Stdio-Transport (JSON-RPC 2.0, Protokollversion 2025-06-18, wie im
aufgezeichneten initialize-Austausch ausgehandelt) sowie den Risiko- und
Bestätigungsvertrag des Servers. Der obige qpdf --check-Schritt bestätigt
ausschließlich die strukturelle Integrität der geschriebenen Datei; die
Konformität mit einem Standard wird von einem unabhängigen Validator
festgestellt, nicht von der erzeugenden Software behauptet.
Siehe auch
Abschnitt betitelt „Siehe auch“- Menschliche Freigabe für die Dateiausgabe verlangen — das Bestätigungs-Gate im Detail, einschließlich des Ablehnungspfads.
- Eine Rechnung durchgängig über REST rendern — dieselbe Tool-Engine über HTTP, mit dem aufgezeichneten Wire-Transkript.
- Ihr erstes PDF erzeugen — die kleinste Connect-Sitzung.
- Konventionen für Connect-Rezepte — der Vertrag, dem jedes Connect-Rezept folgt.
- HITL-Risikostufen — die kanonische Risikoleiter und Policy-Auflösung.
- Tool-Katalog — der maßgebliche Tool-Katalog.