“Which of our contracts carry a termination penalty?” sounds like a job for an AI agent, and it is, but not by reading the contracts. An agent that opens every file to answer it spends its context on 297 irrelevant documents and still has to trust that it noticed the clause in the other three. With GroupDocs.Search.Mcp running locally in Docker, Claude Desktop, Cursor or Copilot indexes the folder once, asks the index which contracts match, and reads only the clauses:
Which of my contracts mention a termination penalty? Quote the clause for each one.
The step-by-step version with config and troubleshooting is in the documentation: How to ask questions across a folder of contracts with an AI agent.
What goes wrong when the agent reads everything?
Three things, in increasing order of danger. It is slow and expensive: every contract goes through the context window, every time you ask. It runs out of room: past a few dozen long documents, the early ones fall out of the window or get summarised, and a summary is where a clause goes missing. And it fails quietly: “I found two contracts with a termination penalty” sounds the same whether the agent checked all 300 or skimmed 40. Nothing in the reply tells you which.
An index removes the first problem and exposes the third. The question “which files contain these words” has an exact answer, and a search tool returns it with a count you can check.
What does the right sequence look like?
Index once, search, then read the matches. Here is what the server returned in our test, against five synthetic contracts: two with a penalty clause, and one NDA that mentions both words but rules a penalty out.
-> add_to_index {"documentsPath":"contracts","indexName":"contracts"}
<- Indexed 'contracts' into index 'contracts': 5 document(s) added,
5 in the index.
-> search {"query":"termination penalty","indexName":"contracts"}
<- { "documentsFound": 0,
"hint": "Unquoted words separated by spaces do not match. Search the
phrase as \"termination penalty\", or combine the words with
AND / OR, e.g. termination AND penalty." }
-> 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 ===
…a termination penalty of three monthly fees applies, payable
within 30…
=== contracts/globex-consulting-agreement.docx ===
…Early termination penalty: the Client pays 50 percent of the fees…
What do the three results teach?
The first query missed, and the server said why. In GroupDocs.Search, words separated by spaces without quotes do not match as a phrase. Rather than return a bare zero, the server attaches a hint explaining the fix, and agents correct themselves on the next call. This is the most common first-time miss, and it is handled in the response itself.
AND found three, the phrase found two. AND is evaluated per document. The Initech NDA contains both words in the sentence “There is no fee and no penalty associated with termination of this NDA”. A model reading only the search result would count it; reading the passage, it reports the NDA separately as a contract that explicitly excludes the penalty. That distinction is the whole value of the third call.
Formats did not matter. The matches came from a PDF and a DOCX, and a TXT contract sat in the same index. The engine indexes 82 formats, so a folder that grew over ten years of different tools answers one query.
The calls, in order
user agent Search MCP server
| "Which contracts mention a termination penalty?" |
|---------------->| |
| |-- add_to_index (once) ------------------>|
| |-- search {"query":"termination AND |
| | penalty"} -------------------->|
| |<- 3 files --------------------------------|
| |-- get_text_fragments {"query": |
| | "\"termination penalty\""} ----------->|
| |<- the two clauses, with context ----------|
|<- "Acme: 3 monthly fees (12.3). Globex: 50% of remaining |
| fees. Initech NDA: explicitly no penalty." |
After the first indexing, each new question costs two calls however many contracts there are. “Which contracts have a force majeure clause?” is "force majeure". “Which leases renew automatically?” is renewal OR renews, and the passage says “renews automatically for 12 months unless notice is given”. A clause about notice periods is terminat? AND notice, where the ? stands for one character and matches terminate.
Where the human stays in the loop
This is not contract review, and it should not pretend to be. The index finds and quotes text; the agent summarises what it quoted. Two habits keep it honest. Ask for the quote with every claim, so a wrong summary is visible next to the sentence it misread. And ask for the near-misses too, “list contracts that mention the words without the clause”, because those are where a reader’s judgement matters most.
Honest limits
- In evaluation mode an index holds at most 100 documents and a search returns at most 10, and every response says so. Call
get_license_statusbefore a real run, because a capped answer looks complete. - Scanned contracts without a text layer are indexed by their file properties only; there is no OCR.
- Full-text search matches words: an agent has to use the contract’s vocabulary, or try variants.
- Removing one file from an indexed folder is not supported; remove the folder and add back what you want.
FAQ
Can an AI agent search all my contracts without uploading them? Yes. The index is built and searched in a container on your machine; only the clauses the agent quotes reach the model.
How many contracts can it handle? Licensed, as many as your disk and memory allow; the index is built once and updated incrementally. Evaluation mode stops at 100 per index.
Why did my search for two words return nothing?
Unquoted words do not match as a phrase. Quote it, "termination penalty", or join the words with AND; the server’s hint says the same.
Go deeper
- Documentation, canonical how-to: How to ask questions across a folder of contracts with an AI agent
- Documentation hub: GroupDocs.Search MCP Server
- Start here: Do you need a vector database to ask questions about a folder of documents?
- Related: Grounded answers from your files: quote the passage, not the model’s memory
- Related: grep can’t read PDF: give your coding agent a document index
- Related: Search your email archive with an AI agent: PST, MSG, EML and the attachments inside
- Related: Project memory for AI agents: one index per project, kept current
- On-premise and security model: 3 architectures for AI document processing, and the one that keeps files inside your network
- Questions: GroupDocs Search forum
- Source: GroupDocs.Search.Mcp on GitHub