# Storage modes

Three storage modes determine whether pdf-mcp stores a generated PDF and what the REST API or MCP server returns.

In the [workspace release](https://pdf-mcp.io/docs/workspaces), storage configuration and retention belong to the workspace. Only admins change those settings. Stored outputs belong to the authenticated member: consumers and editors see their own files, and admins see all files in the workspace.

---

## Storage modes

| Mode | Stores to S3 | Response | Use it for |
|------|-------------|----------|----------|
| **`memory`** | No | Binary PDF (REST) or `EmbeddedResource` (MCP) | One-off downloads, simple integrations |
| **`default`** | Yes (pdf-mcp bucket) | Stored-document metadata and access link | AI agents, file management, audit trails |
| **`byob`** | Yes (your bucket) | Stored-document metadata and access link | Enterprise, compliance, data sovereignty |

### `memory`: no persistence

The PDF is generated in memory and returned directly in the response. Nothing is stored. Once the response is delivered, the file is gone.

- **REST:** Returns an `application/pdf` binary that you can pipe to a file or stream to a client.
- **MCP:** Returns a short `TextContent` summary plus an `application/pdf` `EmbeddedResource`. The MCP wire representation contains base64, but whether the resource appears as an attachment, preview, or download is client-dependent.

Use `memory` when you need the PDF bytes only once.

### `default`: pdf-mcp cloud storage

The PDF is uploaded to the pdf-mcp S3 bucket and a document record is created in the credential's workspace. REST returns document metadata and a presigned download URL. MCP returns a text summary with metadata and a signed browser view link; add `return_binary=true` if the client also needs an embedded PDF resource.

- Files are accessible via the [Files API](/docs/api-files) (list, search, download, delete).
- Delivered presigned URLs expire within five minutes. Request a fresh link when needed.
- Documents can auto-expire via `retention_days`.
- Full-text search is available on stored document content.

### `byob`: bring your own bucket

This mode returns the same response as `default`, but stores the PDF in the workspace's S3 bucket. A workspace admin configures and verifies BYOB in storage settings. Existing documents retain their original storage destination when the current bucket changes. Buckets and objects remain private.

---

## Workspace defaults

Both REST and MCP use the workspace's storage setting when a request omits the mode. A workspace admin can choose `memory`, `default`, or verified `byob` storage. For predictable integration behavior, pass an explicit mode; do not assume every REST response will be binary or every MCP result will be stored.

### When stored output is useful

When an AI agent generates a PDF via MCP, storing it is usually more useful than returning the raw resource in every tool result:

1. **Small default response.** With `default` storage and `return_binary: false`, the result is a short metadata summary instead of an embedded PDF resource.

2. **Client-independent delivery.** The result includes a signed browser view link. An `EmbeddedResource` is useful when requested, but each MCP client decides how to present or save it.

3. **File management.** Stored documents get a `document_id` that can be passed to `download_document`, `search_documents`, `list_documents`, and `delete_document` MCP tools. The AI agent can organize, search, and retrieve files across conversations.

4. **Multi-step workflows.** When the agent needs to merge, split, or convert a previously generated PDF, it can reference it by URL or document ID instead of holding megabytes of base64 in context.

5. **Reliability.** The signed browser view link works without asking the client to interpret an embedded binary resource. Authenticated code can also use `/files/{id}/download`.

You can always override the default by passing `storage_mode: "memory"` explicitly.

---

## Set the storage mode

### REST API

Pass a `storage` object in the JSON request body:

```json
{
  "html": "<h1>Hello</h1>",
  "storage": {
    "mode": "default",
    "filename": "hello.pdf",
    "expires_in": 300,
    "retention_days": 30
  }
}
```

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `mode` | string | Workspace setting | `memory`, `default`, or `byob` |
| `filename` | string | auto | Custom filename for stored PDFs |
| `expires_in` | integer | At most `300` delivered | Requested signed URL lifetime; accepted values are 60-604800, but delivered links are capped at 300 seconds |
| `retention_days` | integer | Workspace setting | Explicit auto-delete interval in days (1-365); omission uses configured retention |

### MCP Server

Pass `storage_mode` as a tool parameter:

```
html_to_pdf(html="<h1>Hello</h1>", storage_mode="memory")
```

The MCP interface uses a flat `storage_mode` string instead of a nested object. It does not expose `expires_in` or `retention_days`; retention follows workspace settings and delivered links are capped at five minutes.

---

## Resolution order

1. An explicit request parameter: `storage.mode` (REST) or `storage_mode` (MCP)
2. The bound workspace's configured storage mode
3. Only when no configured value exists: the channel fallback (`memory` for REST or `default` for MCP)

Anonymous local-development operations return in-memory output and cannot store workspace files.

---

## The `return_binary` parameter

Use `return_binary` to store a file in S3 and receive the binary PDF in the same response. Every PDF-producing endpoint accepts this parameter.

| `return_binary` | `storage.mode` | What happens |
|-----------------|----------------|--------------|
| `false` (default) | `memory` | Return binary (no storage) |
| `false` (default) | `default` / `byob` | Store, return JSON metadata |
| `true` | `memory` | Return binary (no change) |
| `true` | `default` / `byob` | Store **and** return binary |

### REST API

When `return_binary: true` is set with `default` or `byob` storage, the response is `application/pdf` binary (same as memory mode) with storage metadata in custom headers:

```
Content-Type: application/pdf
Content-Disposition: attachment; filename="report.pdf"
X-Document-Id: 550e8400-e29b-41d4-a716-446655440000
X-Storage-Mode: default
X-Storage-Url: https://s3.eu-central-1.amazonaws.com/...
```

```bash
curl -X POST https://api.pdf-mcp.io/htmlToPdf \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "html": "<h1>Report</h1>",
    "storage": { "mode": "default" },
    "return_binary": true
  }' \
  --output report.pdf
```

The file remains available through the Files API after the response returns the PDF bytes.

### MCP Server

When `return_binary: true` with `default` or `byob`, the MCP response includes the PDF as an `EmbeddedResource` (same format as memory mode) after the file has been stored:

```
html_to_pdf(html="<h1>Report</h1>", storage_mode="default", return_binary=true)
```

---

## MCP response format

MCP tools return structured content that separates what the LLM sees from the actual file data.

### Memory mode response

Two content blocks are returned:

1. `TextContent`: a short summary the LLM can read:
   > PDF generated: **report.pdf** (45 KB)

2. `EmbeddedResource`: the PDF binary as a `BlobResourceContents` object. How it is displayed or saved depends on the MCP client.

### Stored mode response (`default` / `byob`)

By default (`return_binary: false`), one content block is returned:

1. `TextContent`: metadata and a signed browser view link:
   > PDF stored successfully
   >
   > **Document ID:** 550e8400...
   > **Size:** 45.2 KB
   > **Pages:** 3
   > **Storage:** default
   > **View in browser:** https://api.pdf-mcp.io/view/...

When `return_binary: true`, a second **`EmbeddedResource`** block is added after the file is stored.

The default stored response stays small. Request the binary only when the client needs it; the stored document remains available for retrieval, search, and management.

---

## Supported operations

The following MCP tools produce stored or in-memory PDFs and expose `storage_mode`:

| Operation | MCP Tool |
|----------|----------|
| HTML to PDF | `html_to_pdf` |
| Text to PDF | `text_to_pdf` |
| Image to PDF | `image_to_pdf` |
| Extract Pages | `extract_pages` |
| Merge PDFs | `merge_pdfs` |
| Fill form | `fill_form` |
| Render template | `render_template` |

The MCP client's live tool schema is authoritative. Inspection tools such as `extract_text`, `pdf_to_image`, `get_page_count`, `grep_pdf`, and `get_form_fields` do not produce a PDF and do not expose a storage mode.

---

## File management

Documents stored with `default` or `byob` mode are tracked in their workspace. File lists, search results, and downloads enforce the member's own-file or admin access:

### REST API: [Files API](https://pdf-mcp.io/docs/api-files)

| Endpoint | Description |
|----------|-------------|
| `GET /files` | List accessible stored documents (paginated) |
| `GET /files/search?q=...` | Full-text search across document contents |
| `GET /files/{id}` | Get document metadata + fresh presigned URL |
| `GET /files/{id}/download` | Download PDF binary directly |
| `DELETE /files/{id}` | Delete a document |

### MCP tools

| Tool | Description |
|------|-------------|
| `list_documents` | List stored documents with pagination |
| `search_documents` | Search document contents (fulltext or grep) |
| `get_document` | Get document metadata and download URL |
| `download_document` | Return a signed browser link and download command for a stored PDF |
| `delete_document` | Delete a document from storage |

With these tools, an AI agent can generate, store, search, retrieve, and delete documents in a conversation.

---

## Related documentation

- [Quick start](https://pdf-mcp.io/docs/quick-start): get your API key and make your first request
- [Files API](https://pdf-mcp.io/docs/api-files): manage files through the REST API
- [MCP server](https://pdf-mcp.io/docs/mcp-server): connect an AI agent
- [HTML to PDF](https://pdf-mcp.io/docs/api-html-to-pdf): use the primary PDF generation endpoint
- [Authentication](https://pdf-mcp.io/docs/authentication): set up an API key or OAuth
