# An eighty-page document does not fit in your agent's head

> Eighty pages returned into a conversation are about twenty thousand tokens that never leave again, and they degrade every answer that comes after.

Canonical HTML version: https://mcpbelt.com/problems/read-an-eighty-page-document

## The problem

The document is eighty pages and somebody needs it understood. The obvious move is to read it and hand the text to the model, and the obvious move is the one that ruins the conversation.

Eighty pages of text are roughly twenty thousand tokens. That is not a one-off cost. Once they are in the conversation they stay there, they are re-sent with every following turn, and they push out the things your agent actually needs to remember. The answer about the document gets worse, and so does the next answer about something else entirely.

The part that makes it hard to notice is that nothing fails. The tool call succeeds, the text is correct, the summary is plausible. What degrades is everything after, and there is no error message for that.

## Why it fails locally

Reading the file yourself gives you the whole thing at once, and that is the problem: extraction hands you one string and no place to put it. Whatever you do next, you have already paid the context for all of it.

The fixes people write are worse than they look. Truncating to the first N characters answers questions about the first chapter and lies about the rest. Chunking and summarising each chunk means one model call per chunk, and the summary is now a lossy copy you cannot search: the clause you needed was in the sentence that got compressed away.

The real requirement is to keep the full text somewhere the model can query without carrying it, and to know how much context you dodged. **Neither of those exists in a local extraction call.** It returns a string, and a string has no handle, no page map and no token count.

## The code

`read` returns a preview, a map and a handle, not the text. Then you ask for the part you need. `result` is free, however many times you call it.

```
upload(filename="report.pdf", content_type="application/pdf")
  -> key, upload_url

curl -T report.pdf "<upload_url>"

read(key="<key>")
  -> handle, engine, structure, chars, tokens_if_inlined, truncated

result(handle="<handle>", outline=true)
  -> section titles, each with its page

result(handle="<handle>", pages="12-14")
  -> just those pages

result(handle="<handle>", offset=0)
  -> a window of text, plus next_offset to continue
```

## What it costs

`read` in `balanced` mode costs 0.007 EUR per page, so eighty pages are about 0.56 EUR. A PDF that already carries its own text is extracted locally and costs nothing at all: you pay only when an engine has to look at the pages.

`exact` costs 0.016 EUR per page and skips the free attempt. Pages are counted from the file, not estimated from its size, so eighty pages are charged as eighty pages and not as a guess.

The context saving is measured, not claimed: on a forty-page document the response was 459 tokens instead of the 6,355 it would have taken inlined. The `tokens_if_inlined` field tells you, on your own file, what you did not spend.

Every call to `result` after that is free. Outline, page ranges, searches, windows: the work was paid for when it ran, and querying it costs nothing.

## What this does not do

- The full text is kept for a limited time. When it expires the handle stops answering and reading the file again is a new job at the normal price.
- Email files (EML, MSG) and ebooks (EPUB) are read by no engine. Extract the text or convert to PDF.
- `result` will not hand you the whole document back in one call. That is the point of it: if you genuinely need all eighty pages in context, this page is not solving your problem.
- Section titles come from the document when the engine reports them and are inferred from the text otherwise. `structure_source` says which one you got.
