MCP Document Converter: Converting and Sharing Documents from a Conversation
9 September 2026 · updated 21 October 2026 · 28 min read
An assistant writes Markdown all day. Ask it for release notes, a summary of a meeting, a first draft of a specification, and what comes back is hashes, asterisks and pipe characters in a chat window. It reads correctly there, because the chat window renders it. It reads like nothing anywhere else.
TL;DR
An MCP document converter is a connector: a small server the assistant can call, so the Markdown it just wrote becomes a converted file or a published page without a person moving text between two tabs. The useful shape is five verbs — convert, save, share, list, fetch back — and the awkward part is not the conversion but the authorisation, which should be an approval you can revoke rather than a long-lived key you pasted. It is genuinely convenient and it is genuinely a standing grant to act on your behalf, which means a document the model reads can try to talk it into using your tools. Use a connector for the document that exists inside a conversation, and an API, a CLI or a build step for everything else.
The usual repair is to copy it out. Select the answer, copy, find a converter, paste, wait, download, rename the file, attach it, notice the table came out as a paragraph of pipes, go back and do it again. Every one of those steps works. The sequence is the problem, and it is the step that keeps breaking — the copy that grabs half a code fence, the paste that arrives with the chat's own formatting attached, the file called download (3).html. That friction has its own article: what actually happens when you move model output into a document covers the manual route and what it costs, and this piece does not repeat it.
What is strange about the manual route is that the assistant is already a program that calls other programs. It reads files, runs searches, opens pull requests. The one thing it usually cannot do is hand you the document it just wrote in a form a person can open. Not because that is hard, but because nobody connected the converter.
That is the gap a connector closes, and the rest of this article is about what a good one looks like, what it is allowed to do on your behalf, and the cases where reaching for it is the wrong instinct.
What MCP is, plainly
The Model Context Protocol is "an open-source standard for connecting AI applications to external systems" (checked on modelcontextprotocol.io, 9 September 2026). That is the whole idea. Before it, every assistant had its own plugin format, and every tool provider wrote the same integration several times over. A shared protocol means a tool is built once and reached from anything that speaks it.
It has a client-server shape, with three named participants rather than two. The host is the AI application; it creates one client per server, and each client holds a dedicated connection to its server, which is "a program that provides context to MCP clients" (checked on modelcontextprotocol.io, 9 September 2026). In practice you can read "host" as the assistant you are typing into, "client" as the piece of it that talks to one particular tool, and "server" as the tool.
| Participant | What it is | In this article |
|---|---|---|
| Host | The AI application, coordinating one or many clients | The assistant you are talking to |
| Client | Holds one connection and obtains context from one server | Created by the host, not something you configure directly |
| Server | A program that provides context and tools | The converter |
A server exposes up to three kinds of thing: tools, which are executable functions the application can invoke to perform actions; resources, which are data sources providing context; and prompts, which are reusable templates (checked on modelcontextprotocol.io, 9 September 2026). A converter is almost entirely tools. Converting is an action with a side effect on the world — a file exists that did not before — which is what a tool is for.
There are two transports. Stdio "uses standard input/output streams for direct process communication between local processes on the same machine", and Streamable HTTP "uses HTTP POST for client-to-server messages with optional Server-Sent Events for streaming capabilities", which "enables remote server communication and supports standard HTTP authentication methods including bearer tokens, API keys, and custom headers", with OAuth recommended for obtaining those tokens (checked on modelcontextprotocol.io, 9 September 2026).
That distinction decides how a connector feels to install. A stdio server is a process on your machine: you install it, it runs when the assistant starts it, and it can reach your filesystem because it is standing in your filesystem. An HTTP server is a URL: nothing is installed, it is the same server for everyone who adds it, and the interesting question becomes how it knows which person is asking. A hosted document converter is the second kind, which is why most of this article is about that question.
Two things MCP deliberately is not. It is not a way of running a model — the protocol "focuses solely on the protocol for context exchange" and does not dictate how applications use models or manage context (checked on modelcontextprotocol.io, 9 September 2026). And it is not a permission system. It carries authorisation, and it defines nothing about whether the model should have called the tool it just called. That judgement stays with the tool's author and with you.
What a converter is worth as a connector
The case for connecting a document converter is not that conversion is difficult. It is that the document is already in the conversation, and everything you would do next is a separate application.
Five verbs cover almost all of it. Convert, so the Markdown becomes a page. Save, so it has an address instead of living in a scroll-back buffer. Share, so somebody else can open it. List, so the assistant can answer "what have I got". Fetch back, so a document written three weeks ago can be edited rather than rewritten from memory. With those five, the model finishes the job in the conversation rather than handing the reader a wall of asterisks and wishing them luck.
TransformPipe's connector exposes nineteen tools, and the split is deliberate: eight read or convert and change nothing, seven add, change or rearrange what is on the account, and four change who can read something or whether it exists at all.
| Tool | What it is for | What it can cause |
|---|---|---|
tp_search_documentation |
Answers questions about how the product works, from its documentation rather than from memory | Nothing. It reads documentation sections and returns them |
tp_convert_from_markdown |
Markdown in; sanitised HTML, Confluence storage format, Jira wiki markup or Slack mrkdwn out; optionally a whole self-contained HTML document | Nothing is saved. The output travels back through the conversation, so a long document costs context |
tp_convert_to_markdown |
HTML, CSV, TSV, JSON, plain text, rich text or an Evernote export in, Markdown out | Nothing is saved. The Markdown comes back through the conversation, the same way |
tp_save_document |
Saves a new document — Markdown, or one of those formats converted on save — optionally into a folder, and publishes it in the same call when asked | Writes a document, and any missing folders on its path. Publishing it, or saving into a shared folder, requires an explicit confirmation |
tp_update_document |
New text for a document already on the account — the same id and the same link, the old text kept as a revision | Changes what a link shows. On a shared document, requires an explicit confirmation |
tp_list_documents |
What is on the account — names, sizes, dates, folders, whether each is shared — with the id the other tools take | Reads. Reveals the document list to the conversation |
tp_list_folders |
The account's folders as a tree, with each one's document count and sharing state, and the account's totals | Reads. Reveals the folder structure to the conversation |
tp_create_folder |
A new folder at the top level or inside another; asking twice returns the folder the first call made | Adds a folder. Nothing existing changes |
tp_move_documents |
Files documents into a folder, or takes them out of all folders | Rearranges. Into a shared folder, requires an explicit confirmation, because its readers can then read them |
tp_get_document |
One document, by id, as its Markdown source or as rendered HTML | Reads. Pulls a whole document into the conversation |
tp_summarize_document |
A short summary of one document, cached on the account so asking again is free | Stores the summary beside the document. The text is sent to Google's Gemini API to write it |
tp_document_versions |
A document's history: the texts its updates replaced, each readable again, and the documents saved as its later versions | Reads. Earlier texts come back into the conversation on request |
tp_share_document |
Changes who may open a document: a link, named addresses, or nobody — or adds or removes one reader | Publishes or unpublishes. Publishing requires an explicit confirmation; revoking breaks a URL already sent |
tp_share_folder |
The same for a folder and everything in it and its subfolders | Publishes or unpublishes every document inside at once, including documents saved there later |
tp_update_folder |
Renames a folder, or moves it with its contents under another folder or to the top level | Rearranges. Under a shared folder, requires an explicit confirmation |
tp_delete_folder |
Deletes a folder; what it holds moves up a level, or goes to the Trash with it when asked | Removes the folder for good and ends its link. Requires an explicit confirmation on every call |
tp_usage |
What the account is using against its limits | Reads. Worth asking when a save was refused |
tp_delete_document |
Moves one document to the Trash, where it is kept for 14 days | Ends its share link at once. Requires an explicit confirmation, and removes exactly one |
tp_restore_document |
Lists the Trash, or puts a deleted document back with its folder, sharing and versions | Brings back what was deleted. Removes nothing |
Two structural details matter more than the list itself.
The first is that the tools are not a second implementation of anything. Each one calls the application's own public API in process, with the caller's credential forwarded, so a conversation and a script get the same answer from the same code. That sounds like an internal tidiness point and it is not. A tool that queried the database directly would be a second implementation of "whose documents are these", and that is the question you least want two answers to. The same reasoning applies to the conversion itself: the HTML a tool returns is the HTML the browser page produces, sanitised against the same allow-list, because it is the same renderer.
The second is tp_search_documentation. A model asked how a product works will answer from whatever it absorbed in training, which for any product younger than its cutoff is a confident description of something that does not exist. A documentation tool turns that into a lookup. It is the least glamorous tool in the table and the one that prevents the most wrong answers.
Adding it, and the sign-in that has no key in it
The address is the deployment plus /api/mcp:
https://transformpipe.com/api/mcp
On claude.ai the connector is also listed in Claude's connector directory, so adding it is Connect and a sign-in; the Claude connector page has the steps, and an organisation that keeps the directory switched off pastes the address under Settings → Connectors → Add custom connector instead. In ChatGPT it goes in by address as an MCP app: Plugins, Add, Create MCP App. From a terminal:
claude mcp add --transport http transformpipe https://transformpipe.com/api/mcp
That is the whole of the configuration. There is no key to paste, and the absence is the point.
Under the address, the transport is JSON-RPC over a single POST, with no event stream. Every tool here answers from the database or from blob storage in a single round trip, so the only thing a stream would buy is progress reporting on work that has no intermediate steps to report. A GET gets a 405, which is a conforming way to say there is no stream at this address.
What happens on the first call
The first call carries no token, and what comes back is a 401. The status is the protocol signal, and this is worth stating plainly because it is the most common way a home-made connector fails: a 200 carrying a politely worded error is read as a tool that failed, and it never starts a sign-in. Only the status code does that.
The 401 carries a WWW-Authenticate header naming a protected-resource document and the scopes it wants — documents:read documents:write. From there the client walks a chain of well-known documents to find out where to sign in, registers itself, and sends the person to a page on the site.
The order of events, which is not obvious from any one part of it:
- The client POSTs the endpoint with no token and gets a 401 plus a
WWW-Authenticateheader naming the protected-resource document. - It reads
/.well-known/oauth-protected-resourceto find the authorisation server, then/.well-known/oauth-authorization-serverto find that server's endpoints. - It registers itself and receives a
client_id. No secret is issued: a client running on somebody else's machine cannot keep one, which is what PKCE is for. - It sends the person to
/authorizewith a PKCE challenge. Not signed in, they are parked and bounced through the application's own sign-in first. - They approve — with a POST from a page they actually read, so a link on its own authorises nothing.
- The client exchanges the code and its verifier for an access token and a refresh token.
The site has to be its own authorisation server for this, rather than handing over the session it already has. The authorisation specification forbids a resource accepting a token issued by anybody else, so the person signs in exactly as they always do, approves a named client on a page they looked at, and the client walks away with a token of the site's own making.
What the client actually gets
A token that acts as that person, for their documents, and reaches nothing else. Not the account. Not the sign-in that the account is attached to. Not the API keys, which are a separate credential for a separate purpose. Access tokens are minted with a thirty-day life and refresh tokens with a hundred and eighty, so a connector you use keeps working and a connector you forget about eventually stops.
Revoking is in the account menu, under API keys, and it takes effect on the next call rather than at the end of some cache window.
Two details on the consent page exist because of specific attacks rather than good taste. The page names the address the client is about to act as, because "approve" with no subject is not consent. And the client's own name is stripped of control characters and bidirectional overrides before it is displayed, because a client can otherwise register itself as something ending in a right-to-left override and have the page render a lie — a problem that escaping HTML does nothing about.
Why this shape rather than a key
A connector holding a long-lived API key you pasted is a credential in a place you will forget about. It sits in a configuration file, or in a hosted assistant's settings, and it is as strong as the key you happened to paste — which, if you pasted the one you already had, is the same key your deployment scripts use. Rotating it breaks both. Auditing it tells you a key was used, not which client used it.
An approved client is a different object. It has a name you can read, a scope narrower than the account, its own expiry, and a revoke button that does not break anything else you own. When you look at the list in six months and do not recognise an entry, you can remove that entry alone. That is the whole argument, and it is worth the extra page in the flow.
The four tools shaped for the trouble they can cause
Fifteen of the nineteen tools are ordinary — the ones that save, update or move ask for a confirmation only when the result would be read by somebody else: a document published as it is saved, new text on a shared document, a document or a folder moved where a shared folder's readers can see it. Four are not ordinary — the two that share and the two that delete — and they are written differently on purpose.
Sharing publishes a page on the public web. There are three modes, and the transition between them is the part people get wrong.
| Mode | Who can open it | The consequence worth knowing |
|---|---|---|
private |
The owner only | Revokes an existing link entirely, so a URL already sent stops working |
link |
Anyone holding the URL | It is on the public web. A URL is not a password, and links travel |
people |
Only the addresses given | emails replaces the list; add and remove change it by one address and leave the rest. Only an address new to the list is emailed |
tp_share_folder takes the same three modes for a folder, and a folder shared by link shows every document in it and in its subfolders, including documents saved there afterwards. Saving can publish in the same call, which is convenient and is exactly why the server's own instructions to the model name every call that discloses something and needs a confirmation first. A tool that both stores and publishes in one step is a tool that can turn "keep this" into "post this" through a single misread sentence. The mitigation is not clever: the description says what it does in the first line, the mode is an explicit enumeration rather than a boolean called public, and the reply to the model says which mode the document is now in and what its URL is, so the assistant's summary to you is a statement you can check. On top of that, link and people both take confirm: true, on a save as on a share, and so does saving into a shared folder: without it the call says what would be disclosed and to whom, and changes nothing.
Deleting takes an explicit confirmation, and a deleted document waits in a Trash. confirm: true is required on both delete tools, on every call, and without it the tool refuses, says what would be removed, and tells the model to go and ask. tp_delete_document removes exactly one document and moves it to the Trash for 14 days, where tp_restore_document puts it back with its folder, sharing and versions; after that it is gone for good, and its share link stops working the moment it is deleted. There is still no tool that deletes by pattern — no glob, no "delete all shared documents", no date range. That is a deliberate absence rather than a missing feature. The one way to remove many documents in a call is tp_delete_folder with with_documents, which is bound to a folder somebody named, and whose refusal states how many documents the folder holds before anything happens. A bulk delete is the one tool where a single misunderstood instruction destroys a great deal of work, and a connector that cannot express the instruction cannot carry it out.
The confirmation is a real mitigation and a partial one, which is the theme of the next section. It stops an accidental deletion, because an accident does not usually include a confirmation flag. It does not stop a deletion the model was talked into, because a model that has been convinced to delete something will pass confirm: true as readily as it passes the id. The Trash is what covers that case, for 14 days, provided somebody notices within them.
Where a connector fails, and what that costs
A connector is a standing grant to act on your behalf. That is not a caveat at the bottom of the page; it is what the thing is. Once it is added, the assistant can call those tools whenever it judges them relevant, in a conversation you are not necessarily reading closely, on the basis of text you did not necessarily write.
A model can be talked into using your tools by the document it is reading. This is prompt injection, and it is not hypothetical for a document converter, because reading documents is the entire job. Somebody sends you a Markdown file. You ask the assistant to convert it and publish it. Somewhere in the middle of that file, in a comment or a code block or white-on-white text, is a paragraph addressed to the model rather than to you. The model is now processing instructions from a stranger while holding a token that acts as you.
The mitigations are real, and they are partial. Stating them honestly means stating both halves.
| Mitigation | What it genuinely prevents | What it does not |
|---|---|---|
| A token scoped to one product's data | Reaching your email, your repositories, your other accounts, or the API keys on the same account | Anything inside the scope: reading, publishing and deleting your documents |
| An explicit confirmation on the destructive tools | Accidental deletion, and casual deletion the person never asked about | A deletion the model was persuaded to make and confirms itself |
| Sharing being visible and revocable | A publication staying secret from you, or being permanent | The window between publishing and your noticing. A copied page stays copied |
| No delete by pattern, and a Trash behind every deleted document | One instruction destroying many documents beyond recovery | A folder deleted with its documents, or repeated single calls, if nobody looks in the Trash within 14 days |
| The person reading what the assistant says it did | Most of it, in practice, if the person actually reads it | Anything in a conversation nobody reviewed, which is most long conversations |
That last row is doing more work than the others, and it is the least reliable. The honest summary is that a connector's safety currently rests on a narrow scope plus a person paying attention, and the second half of that decays with exactly the workload that makes a connector worth having.
There are three further costs that are not about injection at all.
It is another service holding your documents. Signed out, the browser conversion on this site sends nothing anywhere: the file is read, converted and rendered on your own machine, and you can watch the network tab stay empty while it happens. A connector is the opposite arrangement by necessity. Saving a document means an account, an account means storage, and storage means a company holding text you wrote. For a README that is irrelevant. For a contract, a patient note or an unreleased plan it is the whole question, and the right answer may be to convert in the browser and never save at all.
The document goes into the conversation. tp_convert_from_markdown returns the converted output through the same channel as everything else, which means a long document is now part of a transcript held by whoever hosts the assistant. The tool clips returned text at forty thousand characters and says how much it dropped, rather than truncating silently — silent truncation reads as completeness, which is worse than a visible gap — but clipping is a context-window mercy, not a privacy control. For anything long, saving it and sharing the link is both cheaper and less exposed.
Sanitising is still your problem to understand, not to perform. Raw HTML in a Markdown source goes through a sanitiser with a fixed allow-list before it reaches a page, so a <script> tag in a file somebody sent you does not survive the conversion. That is a property of the converter rather than of the connector, and it is worth reading how sanitising works and where it has to happen if you are converting files you did not write. What the sanitiser cannot do is tell you that the prose itself was addressed to your assistant.
The limits, and why one of them is 4 MB
The connector is not a separate product with separate ceilings. The same numbers apply whether a document arrives from a browser tab, a script or a conversation, which is the only arrangement that does not produce support tickets.
| Limit | Value | Why it is that number |
|---|---|---|
| Per conversion | 10 MB of text; 50 MB for a Word, PowerPoint or Excel file; 250 MB for an export .zip | The conversion runs in the browser, so this is a judgement about the machine in front of the person rather than a platform rule. Several files dropped together count as the one document they become |
| Per kept document | 4 MB | Not a policy. The platform refuses a request or a response body over 4.5 MB before any of the application's code runs, so a larger document could be neither saved nor read back |
| Per account | 250 MB, 5,000 documents | Bytes and rows are capped separately: a thousand tiny files cost real rows |
| Per caller | 60 calls a minute | A caller that trips this is looping, not working |
| Returned text | 40,000 characters | A tool reply has to travel through the conversation, and a document should not eat it |
The 4 MB figure is the one worth understanding, because it is the only limit that is not a choice. It is set below the platform's own 4.5 MB rather than at it, so that the refusal arrives from the application with both sizes named in it rather than as a bare rejection from underneath — which is the difference between a model that can tell you what to do next and a model that reports a failure it cannot explain. A document over that size still converts, still previews and still downloads — the conversion runs in your browser, where no request body is involved — it just stays out of the stored history, and the application says so rather than reporting a save that did not happen. A connector has no such way round it: a tool's arguments arrive in a request body like any other, so tp_convert_from_markdown refuses Markdown over 4 MB just as tp_save_document does.
If a save is refused, tp_usage is the tool that says why, in the form of bytes and documents held against the ceiling on each. It exists because "it did not save" is a sentence a model will otherwise interpret creatively.
One more property that is easy to miss: the export is a complete file rather than a fragment. Doctype, head, styles inline, no external requests. That is what makes a converted document survive being emailed, opened offline, or read on a machine that has never seen the site — and it is a specific property with specific trade-offs rather than a marketing line.
When a connector is the wrong tool
A connector is for the document that exists inside a conversation. That is a narrower case than it first appears, and reaching for it outside that case produces the worst of both arrangements: a person in the loop, plus a non-deterministic step in the middle.
| The job | The right tool | Why not a connector |
|---|---|---|
| A script converts documents as part of something larger | The REST API | A script does not need a model to decide anything. It needs a status code and a body |
| A folder of files, converted now | The command line | A hundred files is a loop, not a hundred tool calls. It is faster, cheaper and repeatable |
| A repository publishes on every push | The GitHub Action | The trigger is a commit, and there is nobody in the conversation to ask |
| A document you already have on disk, once | The browser page | Adding a connector to convert one file is more configuration than the task |
The test is where the document is at the moment you want it converted. If it is on disk, in a repository, or in a variable, a program should convert it. If it only exists as text a model just produced, then moving it out to be converted and back in to be discussed is the copy-paste problem again, wearing a different hat.
For context, the reference MCP servers published alongside the protocol show what the local, stdio-shaped case looks like: Filesystem, "secure file operations with configurable access controls"; Git, "tools to read, search, and manipulate Git repositories"; Fetch, "web content fetching and conversion for efficient LLM usage"; plus Memory, Time, Sequential Thinking and an Everything test server (checked on github.com/modelcontextprotocol/servers, 9 September 2026). Note the division of labour. Filesystem and Git already reach your disk and your repository, so a document that lives in either does not need a hosted converter to fetch it — it needs one to convert what those tools handed over, or nothing at all.
How to judge a document connector
- Check whether it can be revoked without breaking something else. A connector that reuses your existing API key means rotating that key kills your deploy scripts too, and you will find that out at the worst moment; a connector that holds its own approval can be removed on a hunch with no consequences.
- Read the destructive tool's description before you add it. If deleting takes no confirmation, or if a tool deletes more than one thing at a time with nothing to restore from, then one misread instruction in a long conversation is unrecoverable data loss rather than an annoying mistake.
- Find out whether sharing is a separate step or a flag on saving. Either is defensible, but a save that publishes in the same call needs the mode named explicitly in the reply, otherwise "saved it" and "posted it on the internet" are the same sentence to the person reading the summary.
- Ask what the tools return through the conversation. A tool that hands back whole documents will fill the context window and put your text in the transcript, so a connector that returns a URL for anything long is doing you a favour that shows up as lower cost and less exposure.
- Confirm the limits match the rest of the product. A connector with its own quieter ceilings will refuse something the website accepted, and the failure arrives as a model apologising vaguely rather than as an error you can act on.
- Decide, before you add it, which documents you are prepared to have stored. A connector that saves is a service holding your text, and the only version of that decision that survives contact with a busy week is one you made in advance, not one you make while pasting.
Conclusion
A connector earns its place when the document is already inside the conversation and every alternative involves a person moving text between two windows. What makes it worth adding rather than merely clever is the boring part: a token that covers one product's documents and nothing else, an approval with a name on it and a revoke button that breaks nothing, destructive tools that ask first and a Trash behind them, and a share that says out loud what it just published. Those are the properties to check on any connector, not only this one. If you would rather keep the document on your own machine, the same conversion runs in the browser with nothing uploaded when you are signed out — and if the job is a script, a folder or a repository, use the API, the CLI or the Action instead, and leave the conversation for the documents that only exist there.
FAQ
What is an MCP document converter?
It is a document converter exposed as an MCP server, so an assistant can call it as a tool instead of a person converting the file by hand. In practice it means the model can turn Markdown it just wrote into HTML, save it, publish it as a page and read it back later, all inside the conversation where the text already is.
Do I need an API key to add the connector?
No. The first call comes back unauthorised, the assistant follows that to a page on the site, and you sign in with the account you already use and approve a named client. The client receives a token good for your documents and nothing else, and you revoke it from the account menu under API keys.
Can an assistant publish my document without asking?
It can, if it passes the confirmation itself, which is why the tools are shaped the way they are: saving can publish in the same call, and publishing on a save or a share requires confirm: true, without which the tool changes nothing and says what would be disclosed. Sharing is visible in your document list and revocable, and setting a document back to private stops an already-sent link from opening — but a page that was copied while public stays copied.
What happens if my document is larger than the limit?
Conversion in the browser is capped at 10 MB for a text file and a stored document at 4 MB, so a file between those sizes converts and downloads but cannot be kept on the account. That second limit is the platform's rather than a policy: a function refuses a request or response body over 4.5 MB before any of the application's code runs, so the document could be neither saved nor read back.
Is a connector safer than pasting into an online converter?
They fail in different ways. Pasting risks the copy itself — half a code fence, a mangled table, the wrong tab — while a connector risks a standing grant being used on the strength of text you did not write, which is prompt injection. Converting in the browser while signed out uploads nothing at all, and for a document you cannot afford to store anywhere, that remains the strongest option.
Does an MCP connector only work with one assistant?
No. MCP is an open standard supported across many clients, so a remote server reached over HTTP works with anything that speaks the protocol and can complete the sign-in. What differs between applications is where you paste the address and how they present the approval step, not the server.
What should I do if the connector stops working?
Check the approval first: a revoked client, or a refresh token past its life, produces exactly the same unauthorised response as a brand new connector, and re-approving fixes it. If it authorises and then refuses to save, ask the assistant to call the usage tool, which reports bytes and documents held against the account ceiling instead of leaving the model to guess.
Does converting through a connector actually save anything?
Tokens, and the amount is arithmetic rather than a claim. A tool call that returns a link puts eleven tokens in the transcript where the document itself would have put thousands — and the transcript is re-sent on every subsequent turn, so the difference compounds. What a document costs an assistant works through the numbers, including the case where the model genuinely has to read the document and the saving is zero.