Il tuo agente di codifica è molto bravo a trovare cose in un repository, purché siano testo. Chiedi a Claude Code o Cursor cosa dice il datasheet del sensore riguardo alla temperatura operativa e lui usa grep, non trova nulla e o indovina o si arrende, perché il datasheet è un PDF e il record di decisione è un file Word. GroupDocs.Search.Mcp gira localmente in Docker e fornisce all’agente un indice full‑text su quei documenti, con lo stesso ciclo di ricerca‑poi‑lettura che già usa per il codice:

Indicizza la cartella docs, poi dimmi cosa dice il datasheet del sensore sulla temperatura operativa e quale ADR ha deciso lo storage della telemetria.

La versione passo‑passo con configurazione e risoluzione dei problemi è nella documentazione: Come consentire a Claude Code o Cursor di cercare i PDF e i documenti Word in un repository.

Perché grep restituisce risultati vuoti?

Perché PDF e DOCX non memorizzano le parole come testo semplice. Un DOCX è un archivio zip; un PDF comprime i suoi flussi di testo. Cercare byte per byte non trova le parole. L’abbiamo testato con un piccolo repository: un datasheet PDF, un record di decisione architetturale e un documento dei requisiti in DOCX, e un file sorgente.

$ grep -ri "TimescaleDB\|operating temperature\|I2C" docs/
$ grep -rn "datasheet" src/
src/sensor.py:1:MAX_TEMP_C = 85  # see docs/datasheet

L’unico risultato è un commento nel codice che punta al documento che l’agente non può leggere. Questo è il divario: la ragione dietro una costante, la decisione dietro un design, il requisito dietro un test spesso vivono proprio in quei file.

Cosa cambia con un indice?

L’agente ottiene uno strumento di recupero per i documenti. Registra il server dalla radice del repository, così il repository è montato come cartella di storage:

claude mcp add groupdocs-search -- docker run --rm -i \
  -v "$(pwd)":/data ghcr.io/groupdocs-search/search-net-mcp:latest

Poi le stesse domande restituiscono risposte. Questo è quello che il server ha restituito nel nostro repository di test (percorsi mostrati relativi alla radice del repository):

-> add_to_index {"documentsPath":"docs","indexName":"gateway"}
<- Indexed 'docs' into index 'gateway': 3 document(s) added,
   3 in the index.

-> search {"query":"TimescaleDB","indexName":"gateway"}
<- documentsFound 1: docs/adr-007-telemetry-storage.docx

-> get_text_fragments {"query":"I2C","indexName":"gateway"}
<- === docs/requirements-v2.docx (1 occurrence(s)) ===
     …REQ-15: the I2C bus runs at 400 kHz.…
   === docs/tmp117-sensor-datasheet.pdf (1 occurrence(s)) ===
     …I2C address selection: ADD0 pin to GND gives 0x48…

Una query ha trovato sia il requisito sia la riga del datasheet insieme, il tipo di riferimento incrociato che è tedioso da fare manualmente e impossibile con grep. Nel nostro piccolo indice, le ricerche sono tornate in 80‑240 millisecondi dopo la prima chiamata.

Il ciclo che l’agente già conosce

user              agent                         Search MCP server
 |  "What does the datasheet say about I2C addresses?"         |
 |---------------->|                                           |
 |                 |-- search {"query":"I2C"} --------------->|
 |                 |<- requirements-v2.docx,                   |
 |                 |   tmp117-sensor-datasheet.pdf ------------|
 |                 |-- get_text_fragments {"query":"I2C"} --->|
 |                 |<- "...ADD0 pin to GND gives 0x48..." -----|
 |<- "0x48 with ADD0 to GND, 0x49 to V+ (datasheet, p.1);      |
 |    REQ-15 runs the bus at 400 kHz."                         |

search risponde quali file, get_text_fragments restituisce le righe corrispondenti con qualche parola di contesto, e l’agente cita entrambi. È la forma di grep, estesa a 82 formati: PDF, DOCX, XLSX, PPTX, HTML, Markdown, persino i thread email esportati nel repository.

Indica all’agente quando usarlo

Gli agenti seguono le istruzioni del progetto su quando ricorrere a uno strumento. Tre righe in CLAUDE.md o AGENTS.md fanno la differenza tra un agente che prova grep, fallisce e si arrende, e uno che prima cerca nell’indice:

PDF, DOCX and XLSX files under docs/ are indexed in the groupdocs-search MCP index
'docs'. grep cannot read them: use search (quote phrases) and get_text_fragments
for anything in specs, datasheets or ADRs, and cite the file.
Run update_index (indexName: docs) after pulling changes.

Due punti di manutenzione. L’indice è scritto in .groupdocs-search-index/ nella radice della cartella montata, quindi aggiungilo a .gitignore. E dopo un pull, update_index rilegge solo ciò che è cambiato, quindi mantenere l’indice aggiornato costa una chiamata.

Cursor e VS Code

Lo stesso contenitore funziona in qualsiasi client MCP. In VS Code, un workspace .vscode/mcp.json può montare qualsiasi cartella aperta, così l’indice segue il progetto:

{
  "servers": {
    "groupdocs-search": {
      "type": "stdio",
      "command": "docker",
      "args": [ "run", "--rm", "-i",
                "-v", "${workspaceFolder}:/data",
                "ghcr.io/groupdocs-search/search-net-mcp:latest" ]
    }
  }
}

Cursor usa lo stesso command e args sotto mcpServers in .cursor/mcp.json. Effettua il commit del file di configurazione e ogni sviluppatore del progetto ottiene lo strumento; mantieni l’indice stesso fuori dal git.

Perché non convertire tutto in testo prima?

Puoi: far convertire all’agente ogni PDF quando ne ha bisogno, o controllare copie Markdown nel repository. Entrambe le soluzioni funzionano per un piccolo numero di file. L’indice esegue la conversione una sola volta, la mantiene aggiornata con una chiamata, e risponde quale file è rilevante prima che l’agente legga qualcosa, passo che mantiene piccolo il contesto di una lunga sessione. Il motore dietro è GroupDocs.Search, che legge direttamente i documenti Office e PDF invece di passare per un convertitore da mantenere.

Limiti onesti

  • In modalità valutazione un indice contiene al massimo 100 documenti e una ricerca restituisce al massimo 10; chiama prima get_license_status.
  • Full‑text, non semantico: l’agente deve usare le parole che i documenti usano, o provare varianti.
  • Nessun OCR: un datasheet scansionato senza livello di testo è indicizzato solo dalle proprietà del file.
  • Solo Docker. Su Linux, aggiungi --user "$(id -u):$(id -g)" affinché il contenitore possa scrivere l’indice in un repository di tua proprietà.

FAQ

Claude Code può leggere i file PDF nel mio repository?
Non con grep. Con il server GroupDocs.Search MCP può cercarli e citarli, localmente, senza convertirli prima.

Funziona anche in Cursor e VS Code?
Sì. Usa gli stessi argomenti docker run in .cursor/mcp.json o .vscode/mcp.json; VS Code può montare ${workspaceFolder}.

L’indice finirà nei miei commit?
Solo se lo permetti. Aggiungi .groupdocs-search-index/ a .gitignore.

Approfondisci