# media-optimizer — agent integration playbook

**Start here:** fetch this file, then [openapi.json](./openapi.json). Machine index: [llms.txt](./llms.txt).

Public base URL: `https://media-optimizer.seiro.io`

## What this service is

In-memory image compress/convert (Squoosh-like). No persistent media storage and no new database tables. Callers receive the optimized bytes and upload them to **their own** cloud storage if they need to keep the file.

Auth matches the other VPS services (browser-render, browser-agent, workers, session-daemon): one Bearer secret.

## Auth

Mutating endpoints require `Authorization: Bearer <MEDIA_OPTIMIZER_SECRET>`.

1. Bootstrap writes the secret to `/etc/media-optimizer.env`.
2. Mirror **that same value** to Desk `.env.local` / Vercel. Do not invent a second secret.
3. HTTP 401 means the Bearer does not match. Do not rotate the VPS secret to “fix” it.
4. `MEDIA_OPT_SECRET` is a fallback alias for the same secret.

Website humans sign in with seiro-desk email/password (same Supabase/GoTrue as Desk). The UI uses that session for `/optimize`. There is no JWT-paste field.

Public (no auth): `/`, `/health`, `/public-config` (`{ loginAvailable }` only — no Desk keys), `/auth/login`, `/auth/refresh`, `/llms.txt`, `/AGENTS.md`, `/openapi.json`.

## Client env (other Seiro projects)

Same shape as browser-render:

```bash
MEDIA_OPTIMIZER_URL=https://media-optimizer.seiro.io
MEDIA_OPTIMIZER_SECRET=<from /etc/media-optimizer.env — same value as Desk/Vercel>
```

Local:

```bash
MEDIA_OPTIMIZER_URL=http://127.0.0.1:8793
MEDIA_OPTIMIZER_SECRET=dev-secret-change-me-16
```

## Endpoints

| Method | Path | Auth | Purpose |
|--------|------|------|---------|
| GET | `/` | no | Website (Desk email/password) |
| GET | `/health` | no | Liveness + flags |
| POST | `/auth/login` | no | Website Desk email/password |
| POST | `/auth/refresh` | no | Refresh a Desk session |
| GET | `/auth/me` | yes | `{ auth: "desk"\|"service", userId? }` |
| POST | `/optimize` | yes | Compress/convert; file or JSON out |
| POST | `/mcp` | yes | MCP JSON-RPC |
| GET | `/llms.txt` | no | Agent index |
| GET | `/AGENTS.md` | no | This playbook |
| GET | `/openapi.json` | no | OpenAPI 3.1 |

### POST /optimize

```bash
curl -sS -X POST https://media-optimizer.seiro.io/optimize \
  -H "Authorization: Bearer $MEDIA_OPTIMIZER_SECRET" \
  -F file=@./photo.png \
  -F format=webp \
  -F quality=80 \
  -F maxWidth=1920 \
  -F maxHeight=1080 \
  -o photo.webp
```

JSON (`Accept: application/json`): `{ imageBase64, format, quality, maxWidth, maxHeight }` → `{ filename, format, mimeType, width, height, bytesBefore, bytesAfter, compressionRatio, imageBase64, requestId }`.

`format`: `jpeg` | `webp` | `avif` | `png` (default `webp`). Quality 1–100 (default 80). Fit-inside resize, no enlarge. 15 MB cap.

## MCP

HTTP JSON-RPC at `POST /mcp`. **Same Bearer as the API.** No `login` tool — put the secret in the client config.

```json
{
  "mcpServers": {
    "media-optimizer": {
      "url": "https://media-optimizer.seiro.io/mcp",
      "headers": {
        "Authorization": "Bearer <MEDIA_OPTIMIZER_SECRET>"
      }
    }
  }
}
```

Tools: `optimize_image` (`image_base64`, `format?`, `quality?`, `maxWidth?`, `maxHeight?`, `filename?`), `list_capabilities`.

```bash
curl -sS https://media-optimizer.seiro.io/mcp \
  -H "Authorization: Bearer $MEDIA_OPTIMIZER_SECRET" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
```

## Errors

| HTTP | Meaning |
|------|---------|
| 401 | Bearer missing or does not match `MEDIA_OPTIMIZER_SECRET` (or a valid Desk access_token on the website path) |
| 400 | Bad image or options |
| 413 | Input too large |
| 429 | Rate limited |
| 502 | Encoder failure |

## Do not

- Invent a second API secret for Desk/Vercel
- Rotate `/etc/media-optimizer.env` because a client got 401
- Commit `MEDIA_OPTIMIZER_SECRET` or `SUPABASE_JWT_SECRET`
- Ask this service to persist media or create Supabase tables/buckets
- Add an MCP email/password `login` tool
