> ## Documentation Index
> Fetch the complete documentation index at: https://docs.vespper.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Primitives

> The three MCP tools that read, search, and edit a Word document

Vespper exposes three primitives over MCP. They are stateless data operations designed to be
chained inside an agent loop: every call carries the document, and `edit_document` hands back
the patched bytes for the next call.

<CardGroup cols={3}>
  <Card title="Read document" icon="file-word" href="/primitives/read-document">
    Return a range of pages as HTML.
  </Card>

  <Card title="Search document" icon="magnifying-glass" href="/primitives/search-document">
    Regex-match blocks without loading the whole document.
  </Card>

  <Card title="Edit document" icon="pen-to-square" href="/primitives/edit-document">
    Apply `old` → `new` edits as Word tracked changes.
  </Card>
</CardGroup>

## Attaching the document

The document is never a tool argument. Your client attaches it to the per-call MCP `_meta`
object, base64-encoded, under reverse-DNS namespaced keys:

| `_meta` key            | Required | Description                                                   |
| ---------------------- | -------- | ------------------------------------------------------------- |
| `com.vespper/document` | Yes      | The `.docx` bytes, base64-encoded                             |
| `com.vespper/author`   | No       | Name Word shows on each tracked change. Defaults to `Vespper` |

That keeps the tool schemas clean — `read_document()`, `search_document(pattern)`,
`edit_document(edits)` — so the model chooses the edit and never spends context on base64.

<Warning>
  Because the client injects `_meta`, a stock MCP client that cannot set it cannot drive these
  tools; calls come back with `No document attached.` See the [Quickstart](/quickstart) for the
  framework and native paths that inject it for you.
</Warning>

## Choosing a primitive

Reading the whole document is rarely the right first move.

| You know                                      | Start with                                                             |
| --------------------------------------------- | ---------------------------------------------------------------------- |
| The text to change (a name, a date, a clause) | `search_document` — it returns each hit as a complete, pasteable block |
| Nothing about the document's shape            | `read_document` — page through as far as the task needs                |
| The document is short                         | `read_document` once                                                   |

Both tools return the same HTML, so an anchor copied from either is equally valid in
`edit_document`.

## Typical flow

```
search_document (or read_document)  →  edit_document  →  thread the returned base64 forward
```

There is no server-side document session. Pass the current bytes on every call, and after
`edit_document` continue with the `base64` it returns or decode it to save a `.docx`.

## Billing

`read_document` and `search_document` are metered as reads; `edit_document` is metered as an
edit. Every response carries the `cost_usd` for that call.
