# @offlinecreator/mcp

MCP server + thin CLI for [OfflineCreator Studio](https://offlinecreatorstudio.com).

Gives Cursor, Claude Desktop, Claude Code, Hermes, Windsurf, and other MCP clients tools to list models, check credits, run image/video/audio/3D workflows, upload typed assets, and retrieve every result.

**Current release:** [`@offlinecreator/mcp@0.1.3`](https://www.npmjs.com/package/@offlinecreator/mcp)

**Recommended remote MCP:** `https://mcp.offlinecreatorstudio.com/mcp` (Streamable HTTP + OAuth 2.1)

**API-key fallback:** local stdio or `https://offlinecreatorstudio.com/mcp`

## Setup

Add the recommended URL to your MCP client, then complete Studio browser
sign-in and consent. No API key is stored in the client configuration.

For local stdio or legacy remote fallback, create a scoped key in **Settings**
and copy the secret once (`oc_live_…` or `oc_test_…`).

### Environment

| Variable | Required | Description |
|----------|----------|-------------|
| `OFFLINECREATOR_API_KEY` | Yes | Personal API key from Settings |
| `OFFLINECREATOR_API_BASE` | No | API origin. Default `https://offlinecreatorstudio.com`. Localhost allowed; other hosts need `OFFLINECREATOR_ALLOW_INSECURE_API_BASE=true`. |
| `OFFLINECREATOR_UPLOAD_ROOT` | No | Directory that `upload_input` and `upload_asset` file paths must stay inside (default: process cwd). |
| `OFFLINECREATOR_ALLOW_INSECURE_API_BASE` | No | Set `true` only for private/non-prod API hosts. |
| `X402_EVM_PRIVATE_KEY` | No | Optional EVM wallet private key for stdio MCP / CLI. Pays x402 USDC challenges for top-ups and pay-as-you-go generations. Never paste into chat. |
| `OFFLINECREATOR_X402_MAX_USD` | No | Optional per-payment spend cap in USD (default `50`). |

## Security notes

- API keys stay in env / MCP client config — tools never echo them.
- `upload_input` cannot read arbitrary disk paths: paths must stay under the upload root, use image extensions, pass size limits, and match image magic bytes.
- `upload_asset` uses the same root boundary, a media/mesh extension allowlist, server-side slot validation, and a 250 MB ceiling.
- The client only calls `/api/v1/*` on a trusted API origin (HTTPS except localhost).
- Generations still use Studio moderation, credit reserve/refund, and ownership checks.
- x402 is payment, not identity: API-key auth still runs first. Wallet keys stay in the agent environment; the hosted OAuth Worker never holds them.

Operator/agent SOP for stdio `filePath` vs remote `imageBase64` (including Cursor tool-bridge size limits): [`docs/mcp-media-upload.md`](../../docs/mcp-media-upload.md).

Product overview for dual-rail payments: [x402 agent payments](https://offlinecreatorstudio.com/x402).

## Install by client

### Cursor

Recommended remote OAuth:

```json
{
  "mcpServers": {
    "offlinecreator": {
      "url": "https://mcp.offlinecreatorstudio.com/mcp"
    }
  }
}
```

API-key stdio fallback:

```json
{
  "mcpServers": {
    "offlinecreator": {
      "command": "npx",
      "args": ["-y", "@offlinecreator/mcp"],
      "env": {
        "OFFLINECREATOR_API_KEY": "oc_live_…"
      }
    }
  }
}
```

Never put the key in the URL or use `?api_key=`.

Local monorepo development:

```json
{
  "mcpServers": {
    "offlinecreator": {
      "command": "node",
      "args": ["C:/path/to/mcp_tool/packages/mcp/dist/index.js"],
      "env": {
        "OFFLINECREATOR_API_KEY": "oc_test_…",
        "OFFLINECREATOR_API_BASE": "http://localhost:3000"
      }
    }
  }
}
```

### Claude Desktop

Add `https://mcp.offlinecreatorstudio.com/mcp` in **Settings → Connectors →
Add custom connector**. Use the stdio JSON above in
`%APPDATA%\Claude\claude_desktop_config.json` as the API-key fallback.

### Claude Code

Remote OAuth:

```bash
claude mcp add offlinecreator --transport http https://mcp.offlinecreatorstudio.com/mcp
```

Local stdio:

```bash
claude mcp add offlinecreator --env OFFLINECREATOR_API_KEY=oc_live_… -- npx -y @offlinecreator/mcp
```

### Hermes

Add to `~/.hermes/config.yaml`, then run `/reload-mcp`:

```yaml
mcp_servers:
  offlinecreator:
    url: "https://mcp.offlinecreatorstudio.com/mcp"
```

### Windsurf

Add to `%USERPROFILE%\.codeium\windsurf\mcp_config.json`:

```json
{
  "mcpServers": {
    "offlinecreator": {
      "serverUrl": "https://mcp.offlinecreatorstudio.com/mcp"
    }
  }
}
```

### VS Code / Copilot

VS Code uses `servers` rather than `mcpServers`. Add to `.vscode/mcp.json` or
the MCP user configuration:

```json
{
  "servers": {
    "offlinecreator": {
      "type": "http",
      "url": "https://mcp.offlinecreatorstudio.com/mcp"
    }
  }
}
```

### Legacy remote API-key fallback

Clients that support fixed headers can still use:

```json
{
  "mcpServers": {
    "offlinecreator": {
      "url": "https://offlinecreatorstudio.com/mcp",
      "headers": {
        "Authorization": "Bearer ${env:OFFLINECREATOR_API_KEY}"
      }
    }
  }
}
```

Never put a key in the URL or use `?api_key=`.

## Tools

| Tool | Purpose |
|------|---------|
| `list_models` | Launch catalog + credit costs |
| `quote_generation` | Lock a provider-routed quote before generation |
| `plan_outcome` | Intent → route → quote → local workflow DAG → evaluate. Preview only; does not start live catalog jobs. Optional `includePilot` (`?pilot=1`) compares third-party pilot listings; default is first-party only. Authenticated execute is `execute_outcome`. Unauthenticated production returns `NOT_LIVE`. |
| `quote_outcome` | Payable outcome quote against the studio credit ledger (`offlinecreator.payment/v1`) with a SHA-256 routing attestation. `accepted_rails` lists credits, optional x402, human Stripe, and reserved Visa MPP. Unauthenticated production returns `NOT_LIVE`. |
| `execute_outcome` | Run the workflow. API keys call the generation service and project settlement eligibility from reservations. Never settled; no outcome-level ledger write. `policy.prefer_rail=x402` is pay-per-outcome USDC even when the credit ledger has balance. Optional `includePilot` compares pilot listings; API keys do not imply marketplace routing. Unauthenticated production returns `NOT_LIVE`. |
| `get_receipt` | Fetch the stored receipt and live run for an attestation hash. Reservation `media_url` is the deliverable. The local logo stub is not. Unauthenticated production returns `NOT_LIVE`. |
| `wait_outcome` | Poll the stored run until completed or failed. Does not start catalog work. Use `download_output` on a reservation `generation_id` for the signed file. Unauthenticated production returns `NOT_LIVE`. |
| `list_outcome_capabilities` | Rate-card + optional marketplace pilot capabilities. Unauthenticated production returns `NOT_LIVE`. |
| `verify_attestation` | Re-hash a routing attestation. Unauthenticated production returns `NOT_LIVE`. |
| `get_credits` | Current balance |
| `generate` | Start generation (`wait: true` to poll) |
| `upload_input` | Attach image for image-to-video, then submit |
| `upload_asset` | Attach an ordered image, video, audio, mesh, or draft-cache input; optionally submit |
| `get_generation` | Current status |
| `wait_generation` | Poll until done |
| `download_output` | Short-lived signed URL for a completed output |
| `cancel_generation` | Cancel reserved job + refund |
| `list_generations` | Recent jobs |

Tools are filtered by key scope (`models`, `read`, `generate`). Top-up
discovery and Checkout creation are CLI/API features, not MCP tools.

**Two payment rails:**

- **Humans / Stripe:** CLI `topups` / `topup --id … --stripe` (or Studio
  pricing Buy) return a Checkout URL for a human browser action. Agents must
  not complete card checkout inside the MCP client.
- **Agents / x402 (optional):** With `X402_EVM_PRIVATE_KEY` set, `topup` and
  `generate` can settle USDC when the API returns HTTP 402 with a
  `PAYMENT-REQUIRED` header. Legacy JSON `INSUFFICIENT_CREDITS` 402s (no
  `PAYMENT-REQUIRED`) still mean “fund via Stripe.” See
  [x402 agent payments](https://offlinecreatorstudio.com/x402).

## CLI sugar

```bash
npx @offlinecreator/mcp models
npx @offlinecreator/mcp balance
npx @offlinecreator/mcp topups
npx @offlinecreator/mcp topup --id topup-1000          # x402 when wallet set; else Stripe URL
npx @offlinecreator/mcp topup --id topup-1000 --stripe # force Stripe Checkout URL
npx @offlinecreator/mcp quote --model seedance-2-5-text --options '{"duration":5,"resolution":"720p"}'
npx @offlinecreator/mcp plan-outcome --north-star
npx @offlinecreator/mcp execute-outcome --ecommerce --x402 --wait
npx @offlinecreator/mcp generate --model flux-schnell --prompt "A clean product still" --wait
```

Pass the quote response's `lockedQuoteToken` as `quoteToken` to `generate`.
Studio manages provider selection and permits only bounded failover that does
not increase the reserved customer charge.

## Development

```bash
npm install
npm run mcp:build
OFFLINECREATOR_API_KEY=oc_test_… OFFLINECREATOR_API_BASE=http://localhost:3000 npm run mcp:start
```

## Privacy note

Studio generations run on disclosed cloud providers (not on-device). LocalForge remains the offline product.
