Spesso, no. Per una cartella di contratti, report o email, un agente IA con uno strumento di ricerca full‑text trova i file giusti, legge solo i passaggi corrispondenti e li cita, e l’indice viene eseguito localmente senza modello di embedding e senza archivio vettoriale. GroupDocs.Search.Mcp fornisce a Claude Desktop, Claude Code, Cursor o Copilot quello strumento in un unico comando Docker:

Indicizza la cartella dei contratti, poi dimmi quali contratti menzionano una penale di risoluzione e cita la clausola.

La versione passo‑passo con configurazione e risoluzione dei problemi è nella documentazione: How to search documents with AI agents using MCP.

Perché tutti ricorrono prima agli embedding?

Perché la “retrieval‑augmented generation” è arrivata come una ricetta: suddividere i documenti in blocchi, incorporare ogni blocco, memorizzare i vettori, incorporare la domanda, prendere i blocchi più vicini e incollarli nel prompt. Funziona, e per domande formulate in modo molto diverso dai documenti è lo strumento giusto. Ma è una pipeline con un modello di embedding da chiamare, un archivio da gestire, una segmentazione da regolare e un lavoro di re‑embedding ogni volta che i documenti cambiano. Per “quali dei miei 300 contratti menzionano una penale di risoluzione”, quella macchina risponde a una domanda a cui un indice di ricerca risponde direttamente.

Le evidenze hanno raggiunto l’intuizione. Uno studio pubblicato su arXiv alla fine del 2025 (Keyword search is all you need) ha fornito a un agente solo ricerca per parole chiave e regex su una cartella e lo ha confrontato con una pipeline RAG standard: oltre il 90% dei punteggi RAG, senza database vettoriale, e più adatto a collezioni che cambiano spesso. Gli agenti di codifica avevano già mostrato il modello nella pratica: cercano con grep, affinano e cercano di nuovo.

Cosa fa invece l’agente?

Tre chiamate. GroupDocs.Search.Mcp espone otto strumenti; il ciclo ne richiede tre:

user              agent                         Search MCP server
 |  "Which contracts mention a termination penalty?"           |
 |---------------->|                                           |
 |                 |-- add_to_index ------------------------->|  reads the
 |                 |   {"documentsPath":"contracts",           |  files once,
 |                 |    "indexName":"contracts"}               |  stores text
 |                 |<- "5 document(s) added, 5 in the index" --|
 |                 |-- search ------------------------------->|
 |                 |   {"query":"termination AND penalty"}     |
 |                 |<- {"documentsFound":3, "documents":[ ... |  which files
 |                 |-- get_text_fragments ------------------->|
 |                 |   {"query":"\"termination penalty\""}     |
 |                 |<- === contracts/acme-...-agreement.pdf ===|  the passages
 |<- "Two contracts carry one: Acme (3 monthly fees, 12.3),    |
 |    Globex (50% of the remaining fees). Initech excludes it."|

add_to_index legge i file una volta e conserva il testo in un indice nominato su disco. search restituisce i file corrispondenti come JSON con i conteggi delle occorrenze. get_text_fragments restituisce ogni corrispondenza con alcune parole di contesto, così l’agente cita la clausola invece di caricare l’intero contratto.

Ecco cosa ha restituito effettivamente il server nel nostro test, su cinque contratti sintetici:

-> search {"query":"termination AND penalty","indexName":"contracts"}
<- documentsFound 3: acme-master-services-agreement.pdf,
   globex-consulting-agreement.docx, initech-nda.docx

-> get_text_fragments {"query":"\"termination penalty\"",...}
<- === contracts/acme-master-services-agreement.pdf (1 occurrence(s)) ===
     …a termination penalty of three monthly fees applies, payable
     within 30…
   === contracts/globex-consulting-agreement.docx (1 occurrence(s)) ===
     …Early termination penalty: the Client pays 50 percent of the fees…

Nota il terzo contratto. L’NDA di Initech ha corrisposto a termination AND penalty perché dice “non c’è alcuna tassa e nessuna penale associata alla risoluzione”. Il passaggio è ciò che distingue una corrispondenza da una semplice menzione, e un agente che legge i passaggi lo indica. Questo è il grounding: ogni affermazione nella risposta punta a un file e a una frase che puoi aprire.

Dove vince ciascun approccio?

pipeline di embedding                       ricerca full‑text agentica
-------------------------------------    -------------------------------------
dividi, incorpora, memorizza in un archivio vettoriale    add_to_index: un indice full‑text locale
incorpora la domanda, prendi i top‑k blocchi    agent searches, refines, searches again
incolla i blocchi nel prompt    get_text_fragments: passaggi citati
re‑incorpora quando i documenti cambiano    update_index rilegge ciò che è cambiato
richiede un modello di embedding e un archivio    nessuna chiamata al modello, nessuna rete a runtime
corrisponde al significato; il ranking è opaco    corrisponde alle parole; ogni risultato è spiegabile

La ricerca full‑text perde quando la domanda e il documento non condividono parole: “quali contratti sono rischiosi per noi?” non ha parole chiave. Vince quando il vocabolario è condiviso, il che descrive la maggior parte delle domande che le persone pongono sui propri documenti: il nome di una clausola, un prodotto, un cliente, un numero di fattura, un intervallo di date. Quando una query non trova risultati, l’agente prova renewal OR renews, o una corrispondenza fuzzy, come farebbe una persona. Il server aiuta: una query di due parole non citata non corrisponde a nulla in GroupDocs.Search, e il risultato vuoto contiene un hint che indica all’agente di citare la frase.

Quale strumento per quale domanda?

L’utente chiede L’agente chiama
“Indicizza questa cartella” add_to_index
“Quali file menzionano X?” search
“Cosa dice su X?” get_text_fragments
“File modificati, aggiorna” update_index
“Dimentica la cartella dei bozzetti” remove_from_index
“Cosa c’è nell’indice?” get_index_info
“Avvia un indice separato” create_index
“Perché solo 10 risultati?” get_license_status

L’indice comprende 82 formati, tra cui PDF, Office, OpenDocument, HTML e archivi email (PST, OST, MSG, EML) con i relativi allegati.

Come eseguirlo?

claude mcp add groupdocs-search -- docker run --rm -i \
  -v /path/to/documents:/data ghcr.io/groupdocs-search/search-net-mcp:latest

Cursor, Claude Desktop, VS Code con GitHub Copilot e gli altri client usano lo stesso contenitore nel proprio file di configurazione: Register in AI clients. Su Linux aggiungi --user "$(id -u):$(id -g)" così il contenitore può scrivere il suo indice nella tua cartella. Il server esegue il motore GroupDocs.Search 26.10, il cui nuovo formato di indice rende gli indici più piccoli e dimezza approssimativamente il loro utilizzo di memoria (release notes).

Limiti onesti

  • In modalità valutazione un indice contiene al massimo 100 documenti e una ricerca restituisce al massimo 10; ogni risposta lo indica. Chiama prima get_license_status.
  • È una ricerca full‑text, non una ricerca semantica: corrisponde alle parole, non al significato.
  • Nessun OCR: i PDF scansionati senza livello di testo sono indicizzati solo dalle proprietà del file.
  • Viene distribuito solo come immagine Docker (lo strumento confezionato supera il limite di dimensione di NuGet).

FAQ

Claude può cercare i miei documenti locali senza caricarli?
Sì. Il server gira in un contenitore sulla tua macchina e legge la cartella che monti; solo i passaggi che l’agente cita raggiungono il modello.

È RAG?
È retrieval‑augmented, ma agentico: il modello decide cosa cercare e quando ha abbastanza, usando un indice full‑text invece degli embedding.

Cosa succede quando i miei documenti cambiano?
Chiedi all’agente di aggiornare. update_index rilegge solo i file modificati, aggiunti e cancellati.

Approfondisci