# animate_3d_model

Check discovery first: this tool is served only where it is enabled and priced. It adds one
animation clip, generated from a description, to a rigged humanoid model: the same file comes
back with the motion inside it, ready to play in Blender, Godot, three.js or any tool that reads
glTF. Mesh, textures and skeleton are unchanged; earlier animations are replaced.

Input: one self-contained, uncompressed `.glb` with one skeleton that has two legs, two arms and
a head, up to 1,000,000 triangles, as `job_file` (e.g. `model.glb` of a `rig_3d_model` job),
`upload_id` or a public HTTPS `url`. A model rigged elsewhere works too: bone roles are found
from the skeleton's shape, not its names, and the model's own facing and proportions are kept.
A static model must be rigged first (`rig_3d_model`).

Options: `description` (required, 3–500 characters), `duration` (1–10 seconds, default 4),
`in_place` (default false: the character travels as it walks or runs), optional `seed`
(0–4294967295; another seed gives another take). Write the description as "A person…" with one
or two actions ("A person walks forward confidently", "A person waves with their right hand").
Everyday movement, gestures, dancing and fighting work best. Keep the description out of URLs:
send it in the JSON body or as MCP arguments. `idempotency_key` is **required**: repeating the
same request with the same key returns the same job instead of paying again.

The job is accepted asynchronously with a one-hour deadline from creation, including queueing and
execution. `wait_seconds` is at most 45, so poll `get_job` with `wait_seconds: 45` until the status
is final; the job reports `workflow.stage` and `workflow.deadline`. Do not start the job again
while it runs. While the job advertises `capabilities.can_cancel`, `cancel_job` cancels and
refunds it.

Outputs:

- `model.glb`: the input model with one animation named `animation` (30 frames per second).
- `motion.json`: frames, fps, duration, `in_place`, the model's `facing`, the hips' `travel`,
  `roles` (which of your bones play hips, spine, neck, head, shoulders, arms, hands, legs, feet
  and toes) and each foot's `contacts` (heel or toes, frames).
- `motion_report.json`: `status`, `thresholds`, `metrics` (per foot: contacts, largest slide and
  float; floor depth; largest bone turn per frame and its change) and `issues`, each with `type`,
  `side` or `bone`, `frames`, `value`, `threshold` and `severity`.
- `motion_preview.png`: six moments from the model's own front and side, skeleton drawn over.
- `generation.json`: options without the description, version and timings.

The job's `result` carries `duration`, `frames`, `status` and the first five `issues`.

**A succeeded job means the motion was written, not that it looks right.** Before using the clip,
read `motion_report.json` and look at `motion_preview.png`:

- `passed`: no measurement crossed its threshold.
- `needs_review`: at least one did; check the named frames in the preview.
- `failed_checks`: a measurement reached twice its threshold.

Issue types: `foot_slide` (a planted foot drifting), `foot_float` (a planted foot above the
floor), `floor` (the model going below the floor, e.g. a tail or long clothes when sitting on the
ground), `pop` (a bone turning too far in one frame) and `jitter` (that turn changing sharply).
Lengths are fractions of the model's height; turns are degrees. If a clip fails, tell the user
what the report says; another `seed` or wording may do better, and each job is charged.

Price: read `pricing` in `GET /v1/tools` before starting the job. The charge is made once the
input passes validation; a job that fails or is canceled is refunded, and a refused input is not
charged. Free limits: 20 jobs per rolling 24 hours (3 until the account's first credit
purchase), models up to 50 MB.

Without MCP, send a JSON body (it keeps the description out of the URL):

```bash
curl https://api.mcpbytes.com/v1/tools/animate_3d_model/jobs \
  -H "Authorization: Bearer $MCPBYTES_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"job_file": {"job_id": "j_...", "name": "model.glb"},
       "options": {"description": "A person walks forward confidently.", "duration": 5},
       "idempotency_key": "my-knight-walk"}'
```

Or with the bundled client: write the options to a JSON file and run
`python scripts/mcpbytes.py run animate_3d_model --job-file <job_id> model.glb --options-json options.json --out animated/`.

Handle `invalid_mesh` (not a readable, self-contained GLB), `limit_exceeded` (more than
1,000,000 triangles; a file over the plan's upload size is refused at once with HTTP 413
`too_large`), `unsupported_rig` (no skeleton, several skeletons, over 256 joints, or no humanoid:
two legs, two arms and a head; refused before any charge), `inference_failed` (try another seed or
wording) and `timeout`. A failed job is refunded. Do not repeat a failed input unchanged.
