Server MCP Python
Server MCP Python
Sezione intitolata “Server MCP Python”L’SDK Python di NextPDF include un server Model Context Protocol (MCP) che espone le operazioni di estrazione PDF come strumenti nativi per gli agenti. Un agente compatibile con MCP — ad esempio Claude Code — registra il server una sola volta e poi richiama gli strumenti NextPDF come qualsiasi altro strumento.
Il server è un adattatore leggero. Ogni strumento legge un PDF dal disco locale, richiama il client asincrono verso l’endpoint NextPDF Connect e restituisce il risultato come stringa JSON. Il server in sé non contiene logica di business e non conserva alcun dato tra una chiamata e l’altra.
Installare l’SDK con l’extra MCP:
pip install nextpdf[mcp]L’extra mcp aggiunge il pacchetto mcp upstream (vincolo mcp>=1.0,<2.0). Il server richiede Python 3.10 o versione successiva.
Avviare il modulo del server dalla configurazione del client MCP. L’esempio seguente legge entrambi i valori di connessione dall’ambiente host anziché incorporare un segreto nel file di configurazione (vedere Sicurezza):
{ "mcpServers": { "nextpdf": { "command": "python", "args": ["-m", "nextpdf.mcp"], "env": { "NEXTPDF_BASE_URL": "https://connect.example.com", "NEXTPDF_API_KEY": "${NEXTPDF_API_KEY}" } } }}Il punto di ingresso python -m nextpdf.mcp esegue main(), che avvia il server tramite lo standard input/output (stdio) con asyncio.run(serve()). Non va confuso con python -m nextpdf, che esegue l’interfaccia a riga di comando (CLI) e non il server MCP.
NEXTPDF_BASE_URL e NEXTPDF_API_KEY sono entrambe obbligatorie. Il server inizializza il proprio client in modo lazy alla prima chiamata di uno strumento. Se una delle due variabili è vuota, viene generato un RuntimeError che viene restituito all’agente come errore dello strumento, anziché terminare il processo.
Catalogo degli strumenti e mappatura dell’SDK
Sezione intitolata “Catalogo degli strumenti e mappatura dell’SDK”Il server registra otto strumenti. Ogni nome di strumento ha il prefisso nextpdf_. Ciascuno è mappato su un metodo dello spazio dei nomi ast del client asincrono (AsyncNextPDF.ast), a eccezione dei due strumenti compositi indicati di seguito, che vengono assemblati all’interno del server a partire da chiamate di livello inferiore.
| Strumento MCP | Chiamata SDK | Note |
|---|---|---|
nextpdf_extract_text | ast.extract_cited_text(pdf_data, page_index=..., headings_only=...) | Restituisce un elenco di CitedTextBlock. |
nextpdf_extract_tables | ast.extract_cited_tables(pdf_data, page_range=...) | Restituisce ExtractCitedTablesResponse. |
nextpdf_get_ast | ast.get_document_ast(pdf_data, page_range_start=0, page_range_end=..., token_budget=...) | Restituisce AstDocument. |
nextpdf_info | ast.get_document_ast(pdf_data) | Il server proietta un riepilogo dei metadati; nessun endpoint dedicato. |
nextpdf_health | nessuna | Esamina solo le variabili d’ambiente; non esegue alcuna chiamata di rete. |
nextpdf_search | ast.search_ast_nodes(pdf_data, node_type=..., page_index=..., text_query=..., max_results=...) | Restituisce SearchAstNodesResponse. |
nextpdf_get_outline | ast.search_ast_nodes(pdf_data, node_type="heading", max_results=500) | Il server rimodella i nodi di intestazione in una struttura. |
nextpdf_diff | ast.get_ast_diff(original_pdf_data, modified_pdf_data) | Restituisce GetAstDiffResponse. |
Alcune note sugli input degli strumenti prima di collegare un agente:
- Tutti gli input di percorso (
pdf_path,original_pdf_path,modified_pdf_path) sono percorsi assoluti di file sulla macchina che esegue il server. L’agente passa un percorso; il server legge i byte in locale. Non esiste alcuno strumento di caricamento. nextpdf_extract_textdichiara un campomax_pagesnel proprio schema di input, ma il gestore del testo non lo passa all’SDK. La delimitazione delle pagine per il testo avviene tramitepage_index(una singola pagina con indice a base 0). Usarenextpdf_get_astconmax_pagesquando occorre delimitare un’analisi dell’intero documento.nextpdf_get_astconvertemax_pagesin un intervallo inclusivo di pagine[0, max_pages - 1](il valore predefinito dimax_pagesè 50). Passaretoken_budgetper limitare la dimensione dell’albero restituito.nextpdf_inforestituisceschema_version,source_hash,page_count,estimated_tokens,root_node_typeeroot_children_count. Questi valori provengono dal modelloAstDocument, doveestimated_tokensè una proprietà calcolata (all’incirca quattro caratteri per token).nextpdf_get_outlinerestituisce una voce per ogni intestazione conid,page_index,textedepth(letto dall’attributoattributes["level"]del nodo, con valore predefinito 1), oltre aheading_count,total_matchesetruncated.
Gli strumenti di estrazione con citazioni allegano un CitationAnchor a ogni risultato. Ogni ancora contiene node_id, page_index, un bbox normalizzato (coordinate nell’intervallo da 0.0 a 1.0) e un punteggio di confidence (da 0.0 a 1.0). Gli agenti che necessitano della provenienza dovrebbero esporre questi campi anziché soltanto il testo grezzo.
Gestione degli errori, timeout e quota
Sezione intitolata “Gestione degli errori, timeout e quota”Il server non lascia mai che un’eccezione raggiunga il trasporto dell’agente. Il dispatcher call_tool intercetta ogni errore e lo restituisce come TextContent JSON, in modo che una chiamata a uno strumento fallita produca un payload strutturato leggibile dall’agente anziché una connessione interrotta. I formati del payload sono:
| Condizione | JSON restituito |
|---|---|
| Nome dello strumento sconosciuto | {"error": "Unknown tool: <name>"} |
| File di input mancante | {"error": "PDF file not found: <path>"} |
Qualsiasi NextPDFError o sottoclasse | {"error": "<message>", "error_type": "<class>", "status_code": <int?>} |
| Qualsiasi altra eccezione | {"error": "Unexpected error: <message>"} |
status_code è incluso solo quando l’errore sottostante lo contiene. L’SDK mappa le risposte HTTP su una gerarchia di eccezioni tipizzata, con radice in NextPDFError:
| Eccezione | Stato HTTP | error_code | Quando |
|---|---|---|---|
NextPDFLicenseError | 402 | license/tier-required | L’endpoint richiede un livello di licenza lato server superiore per l’operazione. |
AstNoStructTreeError | 422 | ast/no-struct-tree | Il PDF non è taggato e il fallback euristico non è abilitato sul server. |
QuotaExceededError | 429 | quota/exceeded | È stato raggiunto un limite di frequenza o una quota. Contiene retry_after (in secondi) quando il server invia un’intestazione Retry-After. |
AstBuildTimeoutError | 504 | ast/build-timeout | La costruzione dell’AST ha superato il budget di tempo del server. Ridurre l’intervallo di pagine. |
NextPDFAPIError | altri 4xx/5xx | fornito dal server | Qualsiasi altro errore a livello API. |
Indicazioni pratiche per le integrazioni degli agenti:
- Timeout. Il client HTTP usa un timeout predefinito fisso — 60 secondi complessivi con un timeout di connessione di 10 secondi. Un documento lento o di grandi dimensioni si manifesta come un
AstBuildTimeoutError(il server ha rinunciato a costruire l’AST) oppure, se scade il client stesso, come un payloadUnexpected errordal livello di trasporto. Quando compareast/build-timeout, istruire l’agente a restringere l’ambito: ridurremax_pagessunextpdf_get_ast, oppure impostarepage_index/page_startepage_endsugli strumenti di estrazione. - Quota e backoff. In caso di 429, lo strumento restituisce
error_typepari aQuotaExceededErrorestatus_code429. Il valoreretry_afterrisiede sull’oggetto eccezione. Poiché il server serializza soloerror,error_typeestatus_code, l’agente dovrebbe trattare il 429 come un segnale per mettere in pausa e riprovare in seguito, anziché analizzare un’intestazione di retry dall’output dello strumento. Applicare le quote sull’endpoint Connect, non nell’agente. - PDF non taggati. Un 422
ast/no-struct-treesignifica che il PDF di origine non ha un albero della struttura. Abilitare la modalità euristica sul server per quei documenti, oppure instradarli verso una fase di tagging prima dell’estrazione.
Sicurezza: ambito della chiave API e privilegio minimo
Sezione intitolata “Sicurezza: ambito della chiave API e privilegio minimo”Trattare la chiave API come un segreto, con la stessa cura riservata a una password di database.
- Non incorporare mai la chiave nel file di configurazione MCP. L’esempio JSON precedente fa riferimento a
${NEXTPDF_API_KEY}in modo che il valore venga risolto dall’ambiente host o da un gestore di segreti al momento dell’avvio. Un file di configurazione può finire nel controllo del codice sorgente; un segreto non deve finirci. - Limitare la chiave all’estrazione in sola lettura. Il server MCP richiama solo la superficie di estrazione AST (
extract_cited_text,extract_cited_tables,get_document_ast,search_ast_nodes,get_ast_diff). Non esegue alcun rendering, firma, redazione o mutazione del documento. Rilasciare all’agente una chiave il cui ambito lato server sia limitato a tali percorsi di lettura, in modo che un agente compromesso non possa raggiungere operazioni di scrittura o di livello superiore. - Usare una chiave dedicata per ogni agente. Una chiave per agente consente di revocare o ruotare un’integrazione senza incidere sulle altre e rende i log dell’endpoint attribuibili a un agente specifico.
- Limitare il file system. Poiché ogni strumento legge un percorso assoluto dal disco locale, il server può leggere qualsiasi file leggibile dal processo host. Eseguirlo come utente senza privilegi, limitarne la directory di lavoro a una cartella di documenti e non eseguirlo mai con un account privilegiato.
- Preferire Transport Layer Security (TLS). Puntare
NEXTPDF_BASE_URLa un endpointhttps://in qualsiasi distribuzione non locale. L’SDK invia la chiave come tokenBearernell’intestazioneAuthorization, quindi un trasporto in chiaro la esporrebbe sulla rete.
Vedere Sicurezza e operazioni di Connect per i controlli lato endpoint che supportano queste pratiche lato client.
Test del server in locale prima di collegare un agente
Sezione intitolata “Test del server in locale prima di collegare un agente”Convalidare il server in isolamento prima di collegare un agente. Il controllo più rapido non richiede alcun PDF né alcuna rete:
python -c "from nextpdf.mcp import _tool_definitions; print(len(_tool_definitions()))"Un’installazione corretta stampa 8. Se compare un ImportError che menziona l’extra mcp, la dipendenza opzionale è mancante — reinstallare con pip install nextpdf[mcp].
Successivamente, esercitare tramite la CLI gli stessi percorsi dell’SDK usati dagli strumenti. La CLI comunica con l’endpoint usando le stesse due variabili d’ambiente. Impostarle una volta:
export NEXTPDF_BASE_URL="https://connect.example.com"export NEXTPDF_API_KEY="$(cat /run/secrets/nextpdf_api_key)"Quindi verificare versione, connettività e una vera estrazione:
nextpdf versionnextpdf info /path/to/sample.pdfnextpdf extract text /path/to/sample.pdf --headings-onlynextpdf version viene eseguito senza credenziali e conferma che il pacchetto sia importabile. nextpdf info esercita get_document_ast, la stessa chiamata alla base di nextpdf_get_ast e nextpdf_info. Se entrambi vanno a buon fine, le credenziali e l’endpoint sono corretti e i corrispondenti strumenti MCP funzioneranno.
Per pilotare direttamente il protocollo MCP, usare l’MCP Inspector upstream (incluso nel pacchetto mcp). Puntarlo allo stesso comando e allo stesso ambiente che userà l’agente, quindi elencare e invocare gli strumenti manualmente. Verificare che nextpdf_health riporti status: "ok". Restituisce misconfigured ogni volta che NEXTPDF_BASE_URL o NEXTPDF_API_KEY non è impostata, ed è il modo più rapido per intercettare un valore d’ambiente mancante prima ancora che un agente richiami uno strumento reale.
Monitoraggio e debug delle chiamate agli strumenti
Sezione intitolata “Monitoraggio e debug delle chiamate agli strumenti”Il server MCP comunica tramite stdio, quindi il suo standard output trasporta il flusso del protocollo e deve rimanere pulito. Il server non configura un proprio logging applicativo; i principali canali di osservabilità sono quindi i payload strutturati di errore degli strumenti, la CLI e i log dell’endpoint in uso.
- I payload di errore degli strumenti sono il segnale. Ogni chiamata fallita restituisce un oggetto JSON con
errore, per gli errori dell’SDK,error_typeestatus_code(vedere Gestione degli errori). Fare in modo che l’host dell’agente registri questi payload; identificano lo strumento che fallisce e la causa precisa senza alcuna strumentazione aggiuntiva nel server. - Riprodurre tramite la CLI con il logging di debug. Il server MCP stesso non emette log, ma la CLI esercita le stesse chiamate dell’SDK e registra i log. Riprodurre uno strumento che fallisce tramite il comando CLI corrispondente con
--log-level debug. La CLI scrive i log su stderr con timestamp e annota i traceback completi per gli errori imprevisti, il modo più diretto per vedere cosa sta facendo un gestore senza collegare un debugger. - Health come sonda. Richiamare
nextpdf_healthper verificare che il server veda un URL di base e una chiave API. Il risultato riportasdk_version,server_url,api_key_configured(un valore booleano, mai la chiave stessa) estatus. - Osservabilità lato endpoint. Poiché ogni strumento è mappato su una singola richiesta Connect, correlare l’attività degli strumenti con i log di accesso dell’endpoint per chiave API e timestamp. Eseguire l’endpoint dietro gli stessi controlli di autenticazione, quota e osservabilità usati per gli altri client di servizio.
Risoluzione dei problemi comuni di integrazione degli agenti
Sezione intitolata “Risoluzione dei problemi comuni di integrazione degli agenti”| Sintomo | Causa probabile | Soluzione |
|---|---|---|
Il server non si avvia con un ImportError relativo all’extra mcp | La dipendenza opzionale mcp non è installata | Installare con pip install nextpdf[mcp]. |
La prima chiamata a uno strumento restituisce {"error": "NEXTPDF_BASE_URL environment variable is required..."} | Il blocco env MCP non ha passato l’URL di base, oppure la shell non ha espanso ${NEXTPDF_BASE_URL} | Impostare la variabile nell’ambiente host dell’agente e verificare che il launcher la espanda. |
nextpdf_health riporta "status": "misconfigured" | Una delle due variabili obbligatorie è vuota | Fornire sia NEXTPDF_BASE_URL sia NEXTPDF_API_KEY. |
Ogni strumento basato su percorso restituisce {"error": "PDF file not found: <path>"} | L’agente ha passato un percorso relativo o lato host a cui il processo del server non può accedere | Passare un percorso assoluto leggibile dall’utente del server; verificare con nextpdf info <path>. |
Lo strumento restituisce error_typeNextPDFLicenseError (stato 402) | L’operazione necessita di un livello di licenza lato server superiore | Usare un endpoint e una chiave abilitati per l’operazione. |
Lo strumento restituisce error_typeAstNoStructTreeError (stato 422) | Il PDF non è taggato e il fallback euristico è disattivato | Abilitare la modalità euristica sull’endpoint, oppure taggare prima il PDF. |
Lo strumento restituisce error_typeQuotaExceededError (stato 429) | È stato raggiunto un limite di frequenza o una quota | Mettere in pausa e riprovare; aumentare la quota dell’endpoint se il limite è troppo basso. |
Lo strumento restituisce error_typeAstBuildTimeoutError (stato 504), oppure un timeout di trasporto | Il documento è troppo grande per il budget di tempo | Restringere l’ambito con max_pages, page_index o page_start/page_end. |
| L’agente non registra alcuno strumento NextPDF | L’agente ha invocato python -m nextpdf (la CLI) anziché python -m nextpdf.mcp | Usare python -m nextpdf.mcp come command/args. |
Per gli errori a livello di endpoint e i controlli di distribuzione, vedere Risoluzione dei problemi di Connect. Per le operazioni SDK sottostanti che questi strumenti incapsulano, vedere il riferimento della CLI e la panoramica dell’SDK.