The Model Didn't Hallucinate. Our Tool Description Was Missing.
A user on DataToRAG made a few hundred Google Workspace calls over two days, chaining Docs and Sheets together in a way we had not seen anyone do before. A handful of those calls failed. I sat down expecting to read a list of a model getting confused.
That is not what the list said.
Three failures, and we caused all three
The first one:
docs_get: unknown parameter "view_range". Accepted: "document_id", "mode"
The model asked to read part of a document. Our docs_get takes a document ID and a mode, and
that is all it takes. There is no way to say "just this section". So the model reached for a
parameter that would obviously exist if anyone had thought about long documents, found nothing,
and failed.
That is not a hallucination. That is a feature request, written in the only language a tool call has. When a model invents a parameter, it is usually describing the shape of the hole.
The second:
requests[0].replaceAllText.matchCase: Unknown property.
Valid properties: ["tabsCriteria", "replaceText", "containsText"]
Google nests matchCase inside containsText. The model put it at the top level. Our tool
description for docs_batch_update never showed what a request actually looks like, so there
was nothing to copy and the model guessed a reasonable structure that happened to be wrong.
Our error message here is good. It names the valid properties. But it arrives after a failed call, and a description that showed one worked example would have prevented the call from being made wrong in the first place.
The third one is the one that stung:
Unable to parse range: Sheet1!A1:A100
The spreadsheet had no tab called Sheet1. And where did Sheet1 come from? Our own
parameter description, which used Sheet1!A:D as its example. The model copied our
placeholder into a real call, and Google handed back a parse error that named the problem
without naming the fix.
The pattern
Every one of these is the same shape. The tool surface knew something the description did not say. Sheets knows its own tab names and we did not offer them. Docs has a request format and we did not show it. And in the first case the tool did not know something it should have: there was no way to read part of a document, so no description could have helped.
Writing MCP tools feels like writing an API. It is closer to writing documentation that executes. The description is not a comment attached to the real thing. For a model, the description is the entire interface. A parameter you did not mention does not exist. An example you wrote carelessly is the example that ends up in production traffic.
What changed
docs_getcan now read part of a long document, using the same character indices thatmode: "index"reports and thatdocs_batch_updatealready consumes. One coordinate system across reads and writes, not two. It also reports the document's total length and whether what you got back was clipped, so a caller can tell a short document from a truncated one.docs_batch_updatecarries a worked example,replaceAllTextincluded, so the nesting is visible before the call instead of after it.sheets_find_rowsanswers a bad tab name by listing the tabs the file actually has, and the example in its description no longer names a tab that usually does not exist.
The part worth stealing
We only found any of this because we read the failed calls on a real account, one at a time, and asked what each one was trying to do rather than what it got wrong.
Error logs on an MCP server are not a bug queue. They are the clearest product feedback you will ever get, because a model has no ego about the interface and no patience for guessing twice. It tells you exactly what it expected to find. If you are running tools for agents, go read your failures this week and count how many are yours.
Ours was most of them.
Ready to connect your data to AI?
Give Claude write access to your Google Workspace. Start free, or talk to us about your setup.
Related articles
Writing values into Google Sheets gives you no formatting at all, and the failure is invisible to whoever caused it. Four new tools fix that: a one-call readable pass, targeted styling, a raw escape hatch, and row lookup that doesn't read the whole sheet.
Claude Can Send Formatted Email Now. Here's What That Took.Until August 26, our Gmail tools sent every message as plain text, so asking Claude for a formatted email got you literal HTML tags in your inbox. Here's the fix, the one asymmetry to know about, and where the workflow builders stand.
Hosted Google Workspace MCP: DataToRAG vs Google's Official Servers vs Claude's Native ConnectorsGoogle shipped eight official Workspace MCP servers. Claude has three native connectors. We host one endpoint. Every tool on all three, enumerated on August 24, 2026, including the surprise: Google's own Gmail MCP cannot send email.