Servidor MCP de Python
Servidor MCP de Python
Sección titulada «Servidor MCP de Python»El SDK de Python de NextPDF incluye un servidor de Model Context Protocol (MCP) que expone las operaciones de extracción de PDF como herramientas nativas para agentes. Un agente compatible con MCP —por ejemplo, Claude Code— registra el servidor una sola vez y luego invoca las herramientas de NextPDF del mismo modo que cualquier otra herramienta.
El servidor funciona como un adaptador ligero. Cada herramienta lee un PDF del disco local, llama al cliente asíncrono en el punto de conexión configurado de NextPDF Connect y devuelve el resultado como una cadena JSON. El servidor en sí no contiene lógica de negocio ni almacena datos entre llamadas.
Instalar el SDK con el extra de MCP:
pip install nextpdf[mcp]El extra mcp añade el paquete upstream mcp (restricción mcp>=1.0,<2.0). El servidor requiere Python 3.10 o posterior.
Ejecutar el módulo del servidor desde la configuración del cliente MCP. El ejemplo de abajo lee ambos valores de conexión desde el entorno del host en lugar de incrustar un secreto en el archivo de configuración (véase Seguridad):
{ "mcpServers": { "nextpdf": { "command": "python", "args": ["-m", "nextpdf.mcp"], "env": { "NEXTPDF_BASE_URL": "https://connect.example.com", "NEXTPDF_API_KEY": "${NEXTPDF_API_KEY}" } } }}El punto de entrada python -m nextpdf.mcp ejecuta main(), que inicia el servidor sobre la entrada/salida estándar (stdio) mediante asyncio.run(serve()). No confundir esto con python -m nextpdf, que ejecuta la interfaz de línea de comandos (CLI), no el servidor MCP.
Tanto NEXTPDF_BASE_URL como NEXTPDF_API_KEY son obligatorias. El servidor construye su cliente de forma diferida en la primera llamada a una herramienta. Si cualquiera de las dos variables está vacía, genera un RuntimeError que se devuelve al agente como un error de herramienta en vez de hacer fallar el proceso.
Catálogo de herramientas y correspondencia con el SDK
Sección titulada «Catálogo de herramientas y correspondencia con el SDK»El servidor registra ocho herramientas. El nombre de cada herramienta lleva el prefijo nextpdf_. Cada una se corresponde con un método del espacio de nombres ast del cliente asíncrono (AsyncNextPDF.ast), excepto las dos herramientas compuestas que se indican más abajo, que se componen dentro del servidor a partir de llamadas de nivel inferior.
| Herramienta MCP | Llamada al SDK | Notas |
|---|---|---|
nextpdf_extract_text | ast.extract_cited_text(pdf_data, page_index=..., headings_only=...) | Devuelve una lista de CitedTextBlock. |
nextpdf_extract_tables | ast.extract_cited_tables(pdf_data, page_range=...) | Devuelve ExtractCitedTablesResponse. |
nextpdf_get_ast | ast.get_document_ast(pdf_data, page_range_start=0, page_range_end=..., token_budget=...) | Devuelve AstDocument. |
nextpdf_info | ast.get_document_ast(pdf_data) | El servidor proyecta un resumen de metadatos; no tiene un punto de conexión dedicado. |
nextpdf_health | ninguno | Solo inspecciona las variables de entorno; no realiza ninguna llamada de red. |
nextpdf_search | ast.search_ast_nodes(pdf_data, node_type=..., page_index=..., text_query=..., max_results=...) | Devuelve SearchAstNodesResponse. |
nextpdf_get_outline | ast.search_ast_nodes(pdf_data, node_type="heading", max_results=500) | El servidor reorganiza los nodos de encabezado en un esquema. |
nextpdf_diff | ast.get_ast_diff(original_pdf_data, modified_pdf_data) | Devuelve GetAstDiffResponse. |
Antes de conectar un agente, conviene tener en cuenta estas notas sobre la entrada de las herramientas:
- Todos los campos de ruta (
pdf_path,original_pdf_path,modified_pdf_path) son rutas absolutas a archivos en la máquina que ejecuta el servidor. El agente pasa una ruta; el servidor lee los bytes de forma local. No hay ninguna herramienta de carga. nextpdf_extract_textdeclara un campomax_pagesen su esquema de entrada, pero el controlador de texto no se lo pasa al SDK. La limitación por páginas para el texto se hace mediantepage_index(una sola página basada en 0). Usarnextpdf_get_astconmax_pagescuando sea necesario acotar un recorrido del documento completo.nextpdf_get_asttraducemax_pagesa un rango de páginas inclusivo de[0, max_pages - 1](el valor predeterminado demax_pageses 50). Pasartoken_budgetpara limitar el tamaño del árbol devuelto.nextpdf_infodevuelveschema_version,source_hash,page_count,estimated_tokens,root_node_typeyroot_children_count. Estos provienen del modeloAstDocument, dondeestimated_tokenses una propiedad calculada (aproximadamente cuatro caracteres por token).nextpdf_get_outlinedevuelve una entrada por cada encabezado conid,page_index,textydepth(leído desde elattributes["level"]del nodo, con 1 como valor predeterminado), además deheading_count,total_matchesytruncated.
Las herramientas de extracción con citas añaden un CitationAnchor a cada resultado. Cada ancla incluye node_id, page_index, un bbox normalizado (coordenadas en el rango de 0.0 a 1.0) y una puntuación de confidence (de 0.0 a 1.0). Los agentes que necesiten la procedencia deberían exponer estos campos, no solo el texto sin procesar.
Manejo de errores, tiempos de espera y cuota
Sección titulada «Manejo de errores, tiempos de espera y cuota»El servidor nunca permite que una excepción se propague al transporte del agente. El despachador call_tool captura cada error y lo devuelve como TextContent JSON, de modo que una llamada de herramienta fallida produce una carga útil estructurada que el agente puede leer, en lugar de una conexión interrumpida. Las formas de la carga útil son:
| Condición | JSON devuelto |
|---|---|
| Nombre de herramienta desconocido | {"error": "Unknown tool: <name>"} |
| Archivo de entrada no encontrado | {"error": "PDF file not found: <path>"} |
Cualquier NextPDFError o subclase | {"error": "<message>", "error_type": "<class>", "status_code": <int?>} |
| Cualquier otra excepción | {"error": "Unexpected error: <message>"} |
status_code se incluye solo cuando el error subyacente lleva uno. El SDK asigna las respuestas HTTP a una jerarquía de excepciones tipadas, todas con raíz en NextPDFError:
| Excepción | Estado HTTP | error_code | Cuándo |
|---|---|---|---|
NextPDFLicenseError | 402 | license/tier-required | El punto de conexión requiere un nivel de licencia más alto del lado del servidor para la operación. |
AstNoStructTreeError | 422 | ast/no-struct-tree | El PDF está sin etiquetar y el modo heurístico de respaldo no está habilitado en el servidor. |
QuotaExceededError | 429 | quota/exceeded | Se alcanzó un límite de tasa o una cuota. Lleva retry_after (en segundos) cuando el servidor envía un encabezado Retry-After. |
AstBuildTimeoutError | 504 | ast/build-timeout | La construcción del AST superó el presupuesto de tiempo del servidor. Reduce el rango de páginas. |
NextPDFAPIError | otros 4xx/5xx | proporcionado por el servidor | Cualquier otro fallo a nivel de API. |
Orientación práctica para las integraciones de agentes:
- Tiempos de espera. El cliente HTTP usa un tiempo de espera predeterminado fijo: 60 segundos en total, con un tiempo de espera de conexión de 10 segundos. Un documento lento o grande se manifiesta como un
AstBuildTimeoutError(el servidor desistió de construir el AST) o, si el propio cliente agota su tiempo de espera, como una carga útil deUnexpected errorde la capa de transporte. Cuando aparezcaast/build-timeout, indicar al agente que reduzca el alcance: reducirmax_pagesennextpdf_get_ast, o establecerpage_index/page_startypage_enden las herramientas de extracción. - Cuota y reintentos progresivos. Ante un 429, la herramienta devuelve un
error_typedeQuotaExceededErrorconstatus_code429. El valor deretry_afterreside en el objeto de excepción. Como el servidor solo serializaerror,error_typeystatus_code, el agente debería tratar el 429 como una señal para pausar y reintentar más tarde, en lugar de analizar un encabezado de reintento de la salida de la herramienta. Aplicar las cuotas en el punto de conexión de Connect, no en el agente. - PDF sin etiquetar. Un 422
ast/no-struct-treesignifica que el PDF de origen no tiene árbol de estructura. Habilitar el modo heurístico en el servidor para esos documentos, o enviarlos a un paso de etiquetado antes de la extracción.
Seguridad: alcance de la clave de API y privilegio mínimo
Sección titulada «Seguridad: alcance de la clave de API y privilegio mínimo»Tratar la clave de API como un secreto, con el mismo cuidado que la contraseña de una base de datos.
- No incrustar nunca la clave en el archivo de configuración de MCP. El ejemplo JSON de arriba hace referencia a
${NEXTPDF_API_KEY}, de modo que el valor se resuelve desde el entorno del host o desde un gestor de secretos en el momento del arranque. Un archivo de configuración se registra en el control de versiones; un secreto no debe hacerlo. - Acotar la clave a la extracción de solo lectura. El servidor MCP solo llama a la superficie de extracción del AST (
extract_cited_text,extract_cited_tables,get_document_ast,search_ast_nodes,get_ast_diff). No realiza renderizado, firma, redacción ni mutación de documentos. Entregar al agente una clave cuyo alcance del lado del servidor esté limitado a esas rutas de lectura, para que un agente comprometido no pueda alcanzar operaciones de escritura ni de nivel superior. - Usar una clave dedicada por agente. Una clave por agente permite revocar o rotar una integración sin afectar a las demás, y hace que los registros del punto de conexión sean atribuibles a un agente concreto.
- Restringir el sistema de archivos. Como cada herramienta lee una ruta absoluta del disco local, el servidor puede leer cualquier archivo que el proceso del host pueda leer. Ejecutarlo como un usuario sin privilegios, restringir su directorio de trabajo a una carpeta de documentos y nunca ejecutarlo como una cuenta con privilegios.
- Preferir la seguridad de la capa de transporte (TLS). Apuntar
NEXTPDF_BASE_URLa un punto de conexiónhttps://en cualquier despliegue que no sea local. El SDK envía la clave como un tokenBeareren el encabezadoAuthorization, por lo que un transporte sin cifrar la expondría en la red.
Consultar Seguridad y operaciones de Connect para conocer los controles del lado del punto de conexión que respaldan estas prácticas del lado del cliente.
Probar el servidor de forma local antes de conectar un agente
Sección titulada «Probar el servidor de forma local antes de conectar un agente»Validar el servidor de forma aislada antes de conectar un agente. La comprobación más rápida no necesita ningún PDF ni red:
python -c "from nextpdf.mcp import _tool_definitions; print(len(_tool_definitions()))"Una instalación correcta imprime 8. Si aparece un ImportError que menciona el extra mcp, falta la dependencia opcional: reinstalar con pip install nextpdf[mcp].
A continuación, probar mediante la CLI las mismas rutas del SDK que usan las herramientas. La CLI se comunica con el punto de conexión usando las mismas dos variables de entorno. Definirlas una sola vez:
export NEXTPDF_BASE_URL="https://connect.example.com"export NEXTPDF_API_KEY="$(cat /run/secrets/nextpdf_api_key)"Luego, confirmar la versión, la conectividad y una extracción real:
nextpdf versionnextpdf info /path/to/sample.pdfnextpdf extract text /path/to/sample.pdf --headings-onlynextpdf version se ejecuta sin credenciales y confirma que el paquete se importa. nextpdf info prueba get_document_ast, la misma llamada que hay detrás de nextpdf_get_ast y nextpdf_info. Si ambas tienen éxito, las credenciales y el punto de conexión son correctos y las herramientas MCP correspondientes funcionarán.
Para manejar el protocolo MCP directamente, usar el MCP Inspector original (incluido con el paquete mcp). Apuntarlo al mismo comando y entorno que usará el agente, y luego enumerar e invocar las herramientas a mano. Verificar que nextpdf_health informe status: "ok". Devuelve misconfigured siempre que NEXTPDF_BASE_URL o NEXTPDF_API_KEY no esté definida, que es la forma más rápida de detectar un valor de entorno ausente antes de que un agente llegue a llamar a una herramienta real.
Supervisión y depuración de las llamadas a herramientas
Sección titulada «Supervisión y depuración de las llamadas a herramientas»El servidor MCP se comunica por stdio, por lo que su salida estándar transporta el flujo del protocolo y debe mantenerse limpia. El servidor no configura su propio registro de aplicación, por lo que los canales principales de observabilidad son las cargas útiles estructuradas de error de herramienta, la CLI y los propios registros del punto de conexión.
- Las cargas útiles de error de herramienta son la señal. Cada llamada fallida devuelve un objeto JSON con
errory, en el caso de los errores del SDK,error_typeystatus_code(véase Manejo de errores). Configurar el host del agente para que registre estas cargas útiles; identifican la herramienta que falla y la causa precisa sin ninguna instrumentación adicional en el servidor. - Reproducir a través de la CLI con registro de depuración. El servidor MCP en sí no emite registros, pero la CLI ejecuta las mismas llamadas al SDK y sí emite registros. Reproducir una herramienta que falla a través del comando de la CLI correspondiente con
--log-level debug. La CLI registra en stderr con marcas de tiempo y guarda las trazas de pila completas de los errores inesperados, lo que es la forma más directa de ver qué hace un controlador sin conectar un depurador. - Health como sonda. Llamar a
nextpdf_healthpara confirmar que el servidor ve una URL base y una clave de API. El resultado informasdk_version,server_url,api_key_configured(un valor booleano, nunca la clave en sí) ystatus. - Observabilidad del lado del punto de conexión. Como cada herramienta se corresponde con una solicitud de Connect, correlacionar la actividad de las herramientas con los registros de acceso del punto de conexión por clave de API y marca de tiempo. Ejecutar el punto de conexión detrás de los mismos controles de autenticación, cuota y observabilidad que se usan para otros clientes de servicio.
Solución de problemas comunes de integración con agentes
Sección titulada «Solución de problemas comunes de integración con agentes»| Síntoma | Causa probable | Resolución |
|---|---|---|
El servidor no arranca y devuelve un ImportError sobre el extra mcp | La dependencia opcional mcp no está instalada | Instalar con pip install nextpdf[mcp]. |
La primera llamada a una herramienta devuelve {"error": "NEXTPDF_BASE_URL environment variable is required..."} | El bloque env de MCP no pasó la URL base, o el shell no expandió ${NEXTPDF_BASE_URL} | Definir la variable en el entorno del host del agente y confirmar que el lanzador la expande. |
nextpdf_health informa "status": "misconfigured" | Una de las dos variables obligatorias está vacía | Proporcionar ambas, NEXTPDF_BASE_URL y NEXTPDF_API_KEY. |
Cada herramienta basada en rutas devuelve {"error": "PDF file not found: <path>"} | El agente pasó una ruta relativa o del lado del host que el proceso del servidor no puede ver | Pasar una ruta absoluta legible por el usuario del servidor; confirmarlo con nextpdf info <path>. |
La herramienta devuelve error_typeNextPDFLicenseError (estado 402) | La operación necesita un nivel de licencia más alto del lado del servidor | Usar un punto de conexión y una clave con derecho a la operación. |
La herramienta devuelve error_typeAstNoStructTreeError (estado 422) | El PDF está sin etiquetar y el respaldo heurístico está desactivado | Habilitar el modo heurístico en el punto de conexión, o etiquetar primero el PDF. |
La herramienta devuelve error_typeQuotaExceededError (estado 429) | Se alcanzó un límite de tasa o una cuota | Pausar y reintentar; aumentar la cuota del punto de conexión si el límite es demasiado bajo. |
La herramienta devuelve error_typeAstBuildTimeoutError (estado 504), o un tiempo de espera del transporte | El documento es demasiado grande para el presupuesto de tiempo | Reducir el alcance con max_pages, page_index o page_start/page_end. |
| El agente no registra ninguna herramienta de NextPDF | El agente invocó python -m nextpdf (la CLI) en lugar de python -m nextpdf.mcp | Usar python -m nextpdf.mcp como command/args. |
Para los fallos a nivel del punto de conexión y las comprobaciones de despliegue, consultar Solución de problemas de Connect. Para las operaciones del SDK subyacente que envuelven estas herramientas, consultar la Referencia de la CLI y la Introducción al SDK.