Platform feature. Requires
WANIWANI_API_KEY. Works whether your MCP server is self-hosted or on Managed Hosting. About the Platform.Setup
The documents client sits on the Waniwani client instance:Read a document you have a URL for
Describe what you want with a Zod schema and pass the URL:filename is not decoration. It is how an unsupported type gets refused before anything is fetched.
The URL has to be publicly fetchable. Private and loopback addresses are refused.
What you get back
Read a file the visitor attached
Turn Modules → Documents on for the agent first. While it is off the widget shows no paperclip and the upload endpoint answers 403, so nothing arrives. With it on, the visitor gets a paperclip, a drop target and paste. The bytes go straight from the browser to storage, never through your server, and your tool call arrives with a handle instead of a file. Read it off the scoped client:documentId, filename and mediaType. Only the id is load-bearing, and there is no filename to pass to extract() because the platform kept it.
Your agent needs a tool like this before the toggle does anything visible. The platform stores the file and hands over an id; reading it is the agent’s job.
On your own chat route
If you run the chat backend yourself rather than using the hosted widget, pull the same handles out of the request body:documents array when the widget sent one, and otherwise falls back to the latest user turn in messages.
Read only some pages
Billing is per page processed, so narrow the range when you know where the answer is. Indexes are zero-based, and the option is ignored for images.Limits
Both the size and page caps are the OCR vendor’s. A PDF is counted before the vendor is called, so an oversized document is refused rather than billed.
After 7 days the stored file is gone and its
documentId no longer resolves. Extract what you need and keep the fields, not the id.
Widget configuration
The hosted widget picks the module state up on its own, soWaniwaniChat and the script embed need no code for any of this.
ChatEmbed, the bring-your-own-backend primitive, takes it as a prop instead, and can send the upload calls under a different credential than the chat. See Chat in React.