Vaak niet. Voor een map met contracten, rapporten of e‑mail vindt een AI‑agent met een full‑text zoektool de juiste bestanden, leest alleen de overeenkomende passages en citeert ze, en de index draait lokaal zonder embed‑model en zonder vector‑store. GroupDocs.Search.Mcp geeft Claude Desktop, Claude Code, Cursor of Copilot die tool in één Docker‑opdracht:

Index de contractenmap, en vertel me vervolgens welke contracten een beëindigingsboete vermelden en citeer de clausule.

De stap‑voor‑stap versie met configuratie en probleemoplossing staat in de documentatie: How to search documents with AI agents using MCP.

Waarom grijpt iedereen eerst naar embeddings?

Omdat “retrieval‑augmented generation” als een recept kwam: splits de documenten in fragmenten, embed elk fragment, sla de vectoren op, embed de vraag, neem de dichtstbijzijnde fragmenten en plak ze in de prompt. Het werkt, en voor vragen die niets lijken op de documenten is het het juiste hulpmiddel. Maar het is een pijplijn met een embed‑model dat moet worden aangeroepen, een store die moet draaien, chunk‑instellingen die moeten worden afgestemd, en een re‑embed‑taak elke keer dat de documenten veranderen. Voor “welke van mijn 300 contracten een beëindigingsboete vermelden” beantwoordt die mechaniek een vraag die een zoekindex direct beantwoordt.

Het bewijs heeft de intuïtie ingehaald. Een studie gepubliceerd op arXiv eind 2025 (Keyword search is all you need) gaf een agent niets anders dan sleutelwoord‑ en regex‑zoekopdrachten over een map en vergeleek dit met een standaard RAG‑pijplijn: meer dan 90 % van de RAG‑scores, zonder vector‑database, en beter geschikt voor collecties die vaak veranderen. Codeer‑agents hadden het patroon al in de praktijk laten zien: ze zoeken met grep, verfijnen en zoeken opnieuw.

Wat doet de agent in plaats daarvan?

Drie oproepen. GroupDocs.Search.Mcp biedt acht tools; de lus heeft er drie van nodig:

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 leest de bestanden één keer en bewaart de tekst in een benoemde index op schijf. search retourneert de overeenkomende bestanden als JSON met aantallen. get_text_fragments geeft elke match terug met een paar woorden context, zodat de agent de clausule citeert in plaats van het hele contract te laden.

Hier is wat de server daadwerkelijk teruggaf in onze test, tegen vijf synthetische contracten:

-> 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…

Let op het derde contract. De Initech NDA kwam overeen met termination AND penalty omdat het zegt “there is no fee and no penalty associated with termination”. De passage is wat een match van een vermelding onderscheidt, en een agent die de passages leest, zegt dat. Dat is grounding: elke bewering in het antwoord wijst naar een bestand en een zin die je kunt openen.

Waar wint elke aanpak?

Embedding‑pijplijn                       Agentische full‑text zoekopdracht
-------------------------------------    -------------------------------------
splitsen, embedden, opslaan in een vector‑store    add_to_index: een lokale full‑text index
embed de vraag, neem top‑k fragmenten            agent zoekt, verfijnt, zoekt opnieuw
plak de fragmenten in de prompt                   get_text_fragments: geciteerde passages
her‑embedden wanneer documenten veranderen         update_index leest opnieuw wat veranderd is
heeft een embed‑model en een store nodig           geen model‑aanroepen, geen netwerk tijdens uitvoering
komt overeen met betekenis; ranking is ondoorzichtig   komt overeen met woorden; elke hit is verklaarbaar

Full‑text zoeken faalt wanneer de vraag en het document geen gemeenschappelijke woorden hebben: “which contracts are risky for us?” heeft geen sleutelwoord. Het slaagt wanneer de woordenschat gedeeld is, wat de meeste vragen beschrijft die mensen over hun eigen documenten stellen: een clausulenaam, een product, een klant, een factuurnummer, een datumbereik. Wanneer een query mist, probeert de agent renewal OR renews, of een fuzzy‑match, zoals een persoon zou doen. De server helpt: een niet‑geciteerde twee‑woord query komt nergens overeen in GroupDocs.Search, en het lege resultaat bevat een hint die de agent vertelt de frase te citeren.

Welke tool voor welke vraag?

De gebruiker vraagt De agent roept aan
“Index deze map” add_to_index
“Welke bestanden vermelden X?” search
“Wat zegt het over X?” get_text_fragments
“Bestanden gewijzigd, vernieuw” update_index
“Vergeet de conceptenmap” remove_from_index
“Wat staat er in de index?” get_index_info
“Start een aparte index” create_index
“Waarom slechts 10 resultaten?” get_license_status

De index begrijpt 82 formaten, waaronder PDF, Office, OpenDocument, HTML en e‑mailarchieven (PST, OST, MSG, EML) met hun bijlagen.

Hoe voer je het uit?

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 met GitHub Copilot en de andere clients gebruiken dezelfde container in hun eigen configuratiebestand: Register in AI clients. Op Linux voeg --user "$(id -u):$(id -g)" toe zodat de container zijn index in jouw map kan schrijven. De server draait de GroupDocs.Search 26.10 engine, waarvan het nieuwe indexformaat indexen kleiner maakt en ongeveer hun geheugenverbruik halveert (release notes).

Eerlijke beperkingen

  • In evaluatiemodus bevat een index maximaal 100 documenten en retourneert een zoekopdracht maximaal 10; elke respons vermeldt dit. Roep eerst get_license_status aan.
  • Het is full‑text zoeken, geen semantisch zoeken: het matcht woorden, niet betekenis.
  • Geen OCR: gescande PDF’s zonder tekstlaag worden alleen op basis van hun bestandseigenschappen geïndexeerd.
  • Het wordt alleen geleverd als Docker‑image (het verpakte hulpmiddel overschrijdt de grootte‑limiet van NuGet).

FAQ

Kan Claude mijn lokale documenten doorzoeken zonder ze te uploaden?
Ja. De server draait in een container op jouw machine en leest de map die je mount; alleen de passages die de agent citeert, bereiken het model.

Is dit RAG?
Het is retrieval‑augmented, maar agentisch: het model beslist wat er gezocht wordt en wanneer het genoeg heeft, met behulp van een full‑text index in plaats van embeddings.

Wat gebeurt er als mijn documenten veranderen?
Vraag de agent om te vernieuwen. update_index leest alleen de gewijzigde, toegevoegde en verwijderde bestanden opnieuw.

Ga dieper