Metadata-Version: 2.4
Name: thrixel-mcp
Version: 0.1.3
Summary: MCP server for Thrixel — text/image to editable, game-ready 3D assets.
Project-URL: Homepage, https://thrixel.com
Project-URL: Documentation, https://docs.thrixel.com
Project-URL: Repository, https://github.com/thrixel/thrixel_mcp
Author-email: Thrixel <support@thrixel.com>
License: MIT
License-File: LICENSE
Keywords: 3d,gamedev,glb,mcp,model-context-protocol,thrixel
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Multimedia :: Graphics :: 3D Modeling
Requires-Python: >=3.10
Requires-Dist: httpx>=0.27
Requires-Dist: mcp>=1.23.0
Requires-Dist: pillow>=10.0
Requires-Dist: pydantic>=2.7
Provides-Extra: dev
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: respx>=0.21; extra == 'dev'
Description-Content-Type: text/markdown

# Thrixel MCP Server

[Model Context Protocol (MCP)](https://modelcontextprotocol.io) server for the [Thrixel](https://thrixel.com) 3D generation platform. Enables AI agents to create, edit, detail, and download game-ready 3D models through natural conversation — and to *see* each result before building on it.

<!-- TODO(screenshot): hero demo GIF — agent prompted for a game prop, tool call runs,
     GLB lands in the project, thumbnail comes back inline. Save as docs/demo.gif -->
> **TODO** — demo GIF goes here (`docs/demo.gif`).

## Features

12 tools covering the Thrixel generation pipeline:

| Category | Tools |
|----------|-------|
| **Create** | `thrixel_create_model`, `thrixel_sculpt_model` |
| **Refine** | `thrixel_edit_model`, `thrixel_autofix_model` |
| **Detail & Texture** | `thrixel_detail_model`, `thrixel_retexture_model` |
| **Optimize** | `thrixel_reduce_triangles` |
| **Inspect** | `thrixel_inspect_model`, `thrixel_list_assets` |
| **Jobs & Download** | `thrixel_job_status`, `thrixel_download` |
| **Account** | `thrixel_account_status` |

### Key Capabilities

- **Text to 3D**: `create_model` returns an *editable, multi-part* mesh — parts stay separate and named, so you can retexture or transform individual pieces later. The default for props, vehicles, buildings, weapons, furniture.
- **Image to 3D**: `sculpt_model` turns a photo or a description into a dense single organic mesh — creatures, characters, plants, food.
- **Natural-language editing**: `edit_model` changes one thing and leaves the rest alone, optionally scoped to named parts. Iterating beats regenerating.
- **Detail & retexture**: `detail_model` adds high-resolution geometry and PBR texture; `retexture_model` swaps materials without touching geometry — the cheap way to restyle a whole asset set.
- **Free triangle reduction**: `reduce_triangles` hits a game budget for zero cubes and routes to the right backend operation automatically. Never re-run a detail pass just to get a lighter mesh.
- **Budget-aware**: `account_status` reports the cube balance, the enforced concurrency cap, and what is running, so a batch can be sized before it starts instead of failing partway through.
- **Visual feedback loop**: every finished job returns a rendered thumbnail as image content, so the agent can judge the result and retry rather than carrying a broken asset forward.
- **Waits for you**: job tools block until the model is finished and write the GLB straight into your project. One tool call equals one finished asset — no agent-authored polling loop to silently give up halfway.
- **Style consistency**: reuse one `reference_image_id` across many assets, or pass `style_reference_submission_id`, to keep a set looking like a set. Reusing a reference image is not re-charged.

## Prerequisites

- [uv](https://github.com/astral-sh/uv) — one binary, no Python setup needed.

  **macOS / Linux**
  ```bash
  curl -LsSf https://astral.sh/uv/install.sh | sh
  ```

  **Windows** (PowerShell)
  ```powershell
  irm https://astral.sh/uv/install.ps1 | iex
  ```
- A Thrixel API key ([get one here](https://thrixel.com/beta) — Account → API keys)

`uvx` fetches the server and a suitable Python into a throwaway environment on
first run. You do not need to clone anything, create a virtualenv, or install
Python yourself.

## Installation

### Option 1 · Claude Code · Recommended

This form takes no JSON, so it works identically in every shell — use it on
Windows and macOS / Linux alike:

```bash
claude mcp add thrixel --env THRIXEL_API_KEY=sk-thrixel-YOUR_API_KEY -- uvx thrixel-mcp
```

<details>
<summary>Prefer <code>add-json</code>? Quoting differs per shell</summary>

Only the outer quoting changes; the JSON itself is identical.

**macOS / Linux, Git Bash, WSL**
```bash
claude mcp add-json thrixel '{"command":"uvx","args":["thrixel-mcp"],"env":{"THRIXEL_API_KEY":"sk-thrixel-YOUR_API_KEY"}}'
```

**Windows PowerShell** — PowerShell rewrites inner double quotes when passing
arguments to a native command, so they must be escaped. Without this you get
`Invalid configuration: : Invalid input`.
```powershell
claude mcp add-json thrixel '{\"command\":\"uvx\",\"args\":[\"thrixel-mcp\"],\"env\":{\"THRIXEL_API_KEY\":\"sk-thrixel-YOUR_API_KEY\"}}'
```

**Windows CMD** — wrap in double quotes and double every inner one.
```cmd
claude mcp add-json thrixel "{""command"":""uvx"",""args"":[""thrixel-mcp""],""env"":{""THRIXEL_API_KEY"":""sk-thrixel-YOUR_API_KEY""}}"
```

</details>

Verify with `claude mcp list`, then open a **new** session.

### Option 2 · Install by Asking Your AI Agent

Already chatting with Cursor / Claude Code / Codex? Paste this prompt:

```
Install the Thrixel MCP server for me. Docs: https://github.com/thrixel/thrixel_mcp
Run it with: uvx thrixel-mcp
Use this env var: THRIXEL_API_KEY=sk-thrixel-YOUR_API_KEY
```

### Option 3 · Manual Install

<details>
<summary><b>Cursor</b></summary>

Paste into `.cursor/mcp.json` (project) or `~/.cursor/mcp.json` (global):

**macOS / Linux**
```json
{
  "mcpServers": {
    "thrixel": {
      "command": "uvx",
      "args": ["thrixel-mcp"],
      "env": { "THRIXEL_API_KEY": "sk-thrixel-YOUR_API_KEY" }
    }
  }
}
```

**Windows** — GUI apps often do not inherit your shell `PATH`, so give the full
path to `uvx.exe` (find it with `where.exe uvx`):
```json
{
  "mcpServers": {
    "thrixel": {
      "command": "C:\\Users\\YOU\\.local\\bin\\uvx.exe",
      "args": ["thrixel-mcp"],
      "env": { "THRIXEL_API_KEY": "sk-thrixel-YOUR_API_KEY" }
    }
  }
}
```

</details>

<details>
<summary><b>Claude Desktop</b></summary>

Add to `claude_desktop_config.json`:

- **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
- **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`

```json
{
  "mcpServers": {
    "thrixel": {
      "command": "uvx",
      "args": ["thrixel-mcp"],
      "env": { "THRIXEL_API_KEY": "sk-thrixel-YOUR_API_KEY" }
    }
  }
}
```

> **Windows**: replace `"uvx"` with the absolute path to `uvx.exe` — the desktop
> app does not inherit your shell `PATH`. See the Cursor block above.

</details>

<details>
<summary><b>Codex / VS Code / Windsurf</b></summary>

Same shape as above — `command: "uvx"`, `args: ["thrixel-mcp"]`, and
`THRIXEL_API_KEY` in the `env` block.

</details>

<details>
<summary><b>Without uv (pip fallback)</b></summary>

```bash
pip install thrixel-mcp
```

Then point the client at your interpreter:

```json
{
  "mcpServers": {
    "thrixel": {
      "command": "python",
      "args": ["-m", "thrixel_mcp.server"],
      "env": { "THRIXEL_API_KEY": "sk-thrixel-YOUR_API_KEY" }
    }
  }
}
```

Use an absolute path to `python` if the client cannot find it on `PATH`.

</details>

<details>
<summary><b>Pre-release / unpublished builds</b></summary>

`uvx` can run straight from the repository, no PyPI release needed:

```bash
# latest main, ahead of the newest release
uvx --from git+https://github.com/thrixel/thrixel_mcp thrixel-mcp

# a local checkout
uvx --from /path/to/thrixel_mcp thrixel-mcp
```

Same shape in a client config — replace `args` with
`["--from", "git+https://github.com/thrixel/thrixel_mcp", "thrixel-mcp"]`.

</details>

## Activate After Install

Most clients auto-load the new server, but **Cursor and VS Code require a manual toggle**:

| Client | What to do | Verify |
|---|---|---|
| **Claude Code** | Nothing — auto-loads on next message | `/mcp` shows `thrixel ✓ connected` |
| **Cursor** | Restart → `Settings` → `MCP & Integrations` → toggle `thrixel` **on** → wait for green dot ● → open a **new chat** | `List the thrixel tools available` |
| **Claude Desktop** | Quit & relaunch the app | `List the thrixel tools available` |
| **VS Code** | Run command `MCP: List Servers` → click `thrixel` → **Start** | `List the thrixel tools available` |
| **Codex** | Nothing — auto-loads on next session | `List the thrixel tools available` |

<!-- TODO(screenshot): connected-state screenshot (Cursor green dot / `/mcp` output).
     Save as docs/connected.png -->
> **TODO** — connected-state screenshot goes here (`docs/connected.png`).

## Usage

Once connected, just ask:

```
Make me a low-poly wooden market stall for a game, under 5000 triangles.
```

The agent will chain `thrixel_create_model` → `thrixel_detail_model` → `thrixel_reduce_triangles`, save the GLB into `./thrixel_assets/`, and show you the render at each step.

<!-- TODO(screenshot): before/after — Architect blockout vs detailed result.
     Save as docs/pipeline.png -->
> **TODO** — pipeline before/after image goes here (`docs/pipeline.png`).

## Troubleshooting

- **`Invalid configuration: : Invalid input`** (Windows) — `claude mcp add-json` received mangled JSON because PowerShell rewrote the inner double quotes. Either escape them (`\"`) or skip JSON entirely and use the flag form: `claude mcp add thrixel --env THRIXEL_API_KEY=... -- uvx thrixel-mcp`. See [Option 1](#option-1--claude-code--recommended).
- **`spawn uvx ENOENT`** — the client cannot find `uvx` on `PATH`. Use the absolute path: `which uvx` on macOS / Linux, `where.exe uvx` on Windows (usually `C:\Users\YOU\.local\bin\uvx.exe`). GUI clients are the usual culprits — they don't inherit your shell `PATH`.
- **`THRIXEL_API_KEY is not set`** — the key didn't reach the server. Make sure it sits inside an `"env": {...}` block in your MCP config, not in `args`.
- **Tool calls return "Thrixel rejected the API key"** — the key is invalid or revoked. Regenerate at https://thrixel.com/beta (Account → API keys).
- **First call is slow** — `uvx` is resolving and caching the package. Subsequent starts are fast.
- **"You have N jobs already running"** — you hit the per-plan concurrency cap (free 2, pro 5, studio 10). Run large batches in waves; `thrixel_account_status` shows what's in flight.
- **"Out of cubes"** — see [Costs](#costs). `thrixel_account_status` shows the balance; `thrixel_reduce_triangles` and rebakes are free.
- **Jobs time out** — GPU work can queue behind other jobs. Raise `THRIXEL_TIMEOUT_S`, or submit with `wait=false` and poll via `thrixel_job_status`.
- **Client doesn't list `thrixel`** — make sure the config file is valid JSON (no trailing commas), then fully restart the client.
- **Stuck on an old version** — `uvx` caches builds. Force a refresh with `uvx --refresh thrixel-mcp`.

## Costs

Cubes are Thrixel's usage credits. Three pricing shapes:

| Operation | Cost |
|---|---|
| `detail_model`, `sculpt_model`, `retexture_model` | Flat **40 cubes** each |
| `reduce_triangles`, texture rebake | **Free** |
| `create_model`, `edit_model`, `autofix_model` | **Metered** — charged after the run on actual model usage |

Metered is not a synonym for cheap. It scales with how complex the request is:
observed runs land anywhere from single digits to over 100 cubes, so a complex
`create_model` can cost more than a flat GPU operation. Call
`thrixel_account_status` to see your balance before a big batch.

Every export format (GLB, FBX, OBJ, STL, USDZ) is free on every plan.

## Configuration

| Environment Variable | Description | Default |
|---------------------|-------------|---------|
| `THRIXEL_API_KEY` | **Required.** Your Thrixel API key (starts with `sk-thrixel-`) | — |
| `THRIXEL_API_BASE` | API base URL | `https://api.thrixel.com` |
| `THRIXEL_OUTPUT_DIR` | Where generated models are written. Writes outside it are refused | `./thrixel_assets` |
| `THRIXEL_TIMEOUT_S` | Ceiling in seconds for a single submit-and-wait cycle | `600` |
| `THRIXEL_LOG_LEVEL` | Server log level, written to stderr | `INFO` |

## Development

```bash
git clone https://github.com/thrixel/thrixel_mcp.git
cd thrixel_mcp

# uv
uv sync

# or conda
conda env create -f environment.yml
conda activate thrixel-mcp
```

Run the server the way a client does, against a local backend:

```bash
THRIXEL_API_BASE=http://localhost:8000 THRIXEL_API_KEY=sk-thrixel-... \
  uvx --from . thrixel-mcp
```

To see the raw protocol, point the MCP Inspector at it - `-e` flags go *after*
the target command:

```bash
npx -y @modelcontextprotocol/inspector --cli uvx thrixel-mcp \
  --method tools/list -e THRIXEL_API_KEY=sk-thrixel-...
```

Drop `--cli` for a web UI that shows each request/response pair. Claude Code's
`claude --debug-file /tmp/mcp.log -p "..."` logs the connection, negotiated
capabilities and dispatched tools, though not the JSON-RPC payloads.

This server holds no state and no business logic - it is a client of the public
Thrixel API. Anything it can do, a direct API caller can do too.

## HTTP Transport

<!-- TODO(phase-2): remote Streamable HTTP transport + OAuth 2.1, mounted into the
     existing FastAPI service. Not implemented yet. -->
> **TODO** — remote HTTP transport is planned but not implemented. `stdio` only for now.

## License

[MIT](LICENSE)
