Dirigir una sesión de documento de agente por MCP
De un vistazo
Sección titulada «De un vistazo»Esta es una sesión de agente completa contra el servidor Model Context
Protocol (MCP) de NextPDF Connect, mensaje a mensaje: initialize,
tools/list, seis invocaciones de tools/call que construyen un informe
de proyecto de una página y el ciclo de ida y vuelta con intervención
humana (HITL) que controla la escritura final del archivo. Cada mensaje
JSON-RPC que aparece a continuación se capturó literalmente de un proceso
bin/nextpdf-mcp en vivo (solo herramientas de nivel Core) y, después, se
saneó exactamente de dos maneras: el token de confirmación de un solo uso
se muestra como confirm_<single-use-hex>, y el directorio temporal del
sistema de la máquina se abrevia a C:\Temp. Los identificadores, los
esquemas, las posiciones y los recuentos de bytes son exactamente lo que
envió el servidor.
Instalación
Sección titulada «Instalación»composer require nextpdf/serverEnlazar el transporte stdio en el host MCP; para Claude Desktop (los hosts lanzan el comando desde su propio directorio, así que conviene usar una ruta absoluta; el transporte stdio no necesita clave de API, a diferencia del transporte REST):
{ "mcpServers": { "nextpdf": { "command": "php", "args": ["/absolute/path/to/your/project/vendor/bin/nextpdf-mcp"] } }}El servidor habla JSON-RPC 2.0 delimitado por saltos de línea en stdin/stdout y mantiene la salida del protocolo estrictamente separada de los diagnósticos: las líneas de arranque y de auditoría van a stderr, nunca a stdout.
Descripción conceptual
Sección titulada «Descripción conceptual»Una sesión de documento MCP mantiene estado. create_pdf abre un
documento en el almacén en memoria del servidor y devuelve un
document_id; cada llamada posterior apunta a ese identificador. Las
herramientas de contenido (set_font, add_text, add_table) se
ejecutan de inmediato en el nivel de riesgo Precaución con registro de
auditoría; preview_layout es una lectura de nivel Seguro; y output_pdf
con un file_path es Aprobación requerida: no se ejecuta en la primera
llamada. En su lugar, el servidor devuelve un desafío con un token de un
solo uso, el agente transmite el desafío a la persona y solo una nueva
llamada que lleve _confirmation_token ejecuta la escritura. Los
documentos que quedan en el almacén caducan tras el tiempo de vida
configurado (30 minutos de forma predeterminada).
Las mismas llamadas de herramientas impulsan el motor de herramientas sobre REST y gRPC (los transportes comparten un único ejecutor), así que todo lo que hay aquí, salvo el encuadre de stdio, se traslada igual. Véase Renderizar una factura de principio a fin por REST para el mismo motor en la superficie HTTP.
Superficie de la API
Sección titulada «Superficie de la API»| Herramienta | Función en esta sesión | Nivel de riesgo |
|---|---|---|
create_pdf | Abrir el documento, obtener document_id | Precaución |
set_font | Seleccionar la fuente de encabezado y luego la del cuerpo | Precaución |
add_text | Línea de título y luego párrafo de introducción | Precaución |
add_table | Tabla de tareas con responsable y fecha de vencimiento | Precaución |
preview_layout | Leer el estado del diseño antes de la salida | Seguro |
output_pdf (modo de archivo) | Escribir el PDF — con puerta | Aprobación requerida |
El despliegue capturado aquí registró 20 herramientas (13 de Core, 6 de
Pro, 1 de Enterprise; los recuentos aparecen en la respuesta de
initialize que se muestra más abajo); esta sesión usa únicamente
herramientas de Core, por lo que se ejecuta sin cambios en una instalación
exclusivamente de código abierto. El catálogo de referencia es la
respuesta tools/list de su propio servidor, y la escala de riesgo se
define en la
referencia de niveles de riesgo HITL.
La sesión, mensaje a mensaje
Sección titulada «La sesión, mensaje a mensaje»1. Inicializar la conexión
Sección titulada «1. Inicializar la conexión»El cliente abre la sesión e indica su versión de protocolo:
{ "jsonrpc": "2.0", "id": 1, "method": "initialize", "params": { "protocolVersion": "2025-06-18", "capabilities": {}, "clientInfo": { "name": "planning-agent", "version": "1.0.0" } }}El servidor confirma la versión de protocolo y declara sus capacidades, incluidos los recuentos de herramientas por nivel y que el control HITL está habilitado:
{ "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" } }}El cliente confirma con una notificación (las notificaciones no llevan
id ni reciben respuesta):
{ "jsonrpc": "2.0", "method": "notifications/initialized"}2. Descubrir las herramientas
Sección titulada «2. Descubrir las herramientas»{ "jsonrpc": "2.0", "id": 2, "method": "tools/list"}La respuesta completa enumera las 20 herramientas registradas con sus esquemas de entrada completos. Aquí se muestra abreviada a las dos herramientas que abren y cierran esta sesión; las 18 entradas omitidas tienen la misma forma:
{ "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 } } ] }}Observar el esquema de output_pdf: file_path es opcional, y las
anotaciones llevan openWorldHint: true: la herramienta puede afectar al
mundo fuera de la sesión, que es precisamente por lo que el modo de
archivo tiene puerta.
3. Abrir el documento
Sección titulada «3. Abrir el documento»{ "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" } }}Cada resultado de herramienta llega dos veces en un mismo mensaje: un
bloque de texto content legible por personas y structuredContent
legible por máquinas. Leer structuredContent.document_id y pasarlo por
cada una de las llamadas siguientes.
4. Añadir el encabezado
Sección titulada «4. Añadir el encabezado»Establecer una fuente en negrita de 16 puntos y luego colocar el título:
{ "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. Añadir el párrafo del cuerpo
Sección titulada «5. Añadir el párrafo del cuerpo»De vuelta a una fuente normal de 11 puntos para el texto de introducción;
width: 0 selecciona un diseño multicelda de ancho completo:
{ "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. Añadir la tabla de tareas
Sección titulada «6. Añadir la tabla de tareas»{ "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 } } }}Cada llamada de contenido devuelve la position actualizada del cursor,
de modo que el agente siempre sabe dónde cae el siguiente elemento.
7. Previsualizar antes de solicitar aprobación
Sección titulada «7. Previsualizar antes de solicitar aprobación»preview_layout es una llamada de nivel Seguro, de solo lectura: un
agente que se comporta correctamente comprueba lo que ha construido antes
de pedir a una persona que apruebe una escritura:
{ "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. Solicitar la escritura del archivo: la puerta responde primero
Sección titulada «8. Solicitar la escritura del archivo: la puerta responde primero»El agente pide a output_pdf que escriba el informe terminado en disco,
manteniendo vivo el documento (destroy: false) por si la persona lo
rechaza y hay que recurrir a la salida en base64:
{ "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 } }}El archivo no se escribe. Como el modo de archivo es Aprobación requerida, el servidor responde en su lugar con un desafío de confirmación:
{ "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. La persona aprueba: nueva llamada con el token
Sección titulada «9. La persona aprueba: nueva llamada con el token»El agente transmite el texto del desafío a la persona. Tras la aprobación,
llama de nuevo a output_pdf con los mismos argumentos más
_confirmation_token:
{ "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>" } }}El token se consume, la escritura se ejecuta y el resultado informa del archivo escrito:
{ "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 } }}Verificar el archivo escrito
Sección titulada «Verificar el archivo escrito»La sesión escribió kickoff-brief.pdf (3612 bytes, una página,
coincidiendo con structuredContent.file_size y page_count). Salida
capturada de qpdf --check para ese archivo exacto:
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 detectSe trata de una comprobación estructural, en palabras del propio qpdf, no de una determinación de conformidad.
Casos límite y trampas
Sección titulada «Casos límite y trampas»- La nueva llamada debe repetir los mismos argumentos. El token de
confirmación está vinculado al nombre de la herramienta más un resumen
canónico de los argumentos para los que se emitió. Volver a llamar con
cualquier cambio —incluso invirtiendo
destroy— no consume el token; el servidor responde en su lugar con un desafío nuevo. Repetir los argumentos exactamente y añadir únicamente_confirmation_token. - El token es de un solo uso y caduca. El desafío indica el vencimiento (300 segundos). Tras la caducidad o el consumo, la siguiente llamada con puerta obtiene un nuevo desafío; transmitir el nuevo.
- La salida de archivos cae dentro de un directorio en lista de
permitidos. El servidor rechaza un
file_pathfuera de su directorio temporal configurado conOutput path rejected by security policy. La raíz de la lista de permitidos predeterminada esnextpdf-mcpbajo el directorio temporal del sistema; los operadores la cambian con el ajustetemp_dirennextpdf-mcp.yaml. - El modo base64 no tiene puerta.
output_pdfsinfile_pathdevuelve el PDF como base64 en el nivel Revisión, sin efecto secundario en el sistema de archivos; véase Exigir aprobación humana para la salida de archivos para conocer en profundidad ese límite. - Un desafío es un resultado, no un error. El mensaje de desafío llega
con
isError: false; una aprobación pendiente es una pausa del flujo de trabajo. No reintentar en un bucle y nunca fabricar un token. - Las notificaciones no obtienen respuesta. Tras
notifications/initialized, no bloquear esperando una línea de respuesta.
Rendimiento
Sección titulada «Rendimiento»La sesión es en memoria de principio a fin: en la ejecución capturada, las llamadas de contenido respondieron en milisegundos, y el tiempo total está dominado por el ciclo de ida y vuelta de la aprobación humana, que es el propósito de la puerta. El almacén de documentos conserva una sesión durante 30 minutos de inactividad de forma predeterminada (50 documentos como máximo), de modo que una aprobación lenta no pierde el documento construido, pero uno abandonado se recupera.
Notas de seguridad
Sección titulada «Notas de seguridad»- Tratar el token de confirmación como un secreto de un solo uso. Transmitir el texto del desafío a la persona; no registrar ni conservar el token. Esta página censura el token capturado precisamente por ese motivo.
- El rastro de auditoría está en stderr. Cada ejecución de nivel Precaución o superior se registra en auditoría (herramienta, riesgo, argumentos, resultado) mediante PSR-3, con los parámetros sensibles censurados. Los diagnósticos nunca se mezclan en el flujo del protocolo.
- La lista de permitidos de rutas es el límite del sistema de
archivos. Apuntar
temp_dira un directorio dedicado a la salida de Connect; no ampliarlo a una ubicación de uso general. - Los niveles de riesgo solo pueden subir. Una anulación por parte del
operador en
nextpdf-mcp.yamlpuede elevar el nivel de riesgo de una herramienta, pero nunca puede bajaroutput_pdfpor debajo de Aprobación requerida.
Conformidad
Sección titulada «Conformidad»Esta receta no formula ninguna afirmación normativa sobre estándares.
Documenta el transporte stdio de MCP (JSON-RPC 2.0, versión de protocolo
2025-06-18 según se negoció en el intercambio initialize capturado) y
el contrato de riesgo y confirmación del servidor. El paso qpdf --check
anterior confirma únicamente la integridad estructural del archivo
escrito; la conformidad con un estándar la determina un validador
independiente, no la afirma el software productor.
Véase también
Sección titulada «Véase también»- Exigir aprobación humana para la salida de archivos — la puerta de confirmación en profundidad, incluida la ruta de rechazo.
- Renderizar una factura de principio a fin por REST — el mismo motor de herramientas sobre HTTP, con la transcripción del tráfico capturada.
- Generar su primer PDF — la sesión de Connect más pequeña.
- Convenciones de las recetas de Connect — el contrato que sigue cada receta de Connect.
- Niveles de riesgo HITL — la escala de riesgo canónica y la resolución de políticas.
- Catálogo de herramientas — el catálogo de herramientas de referencia.