Skip to content
MCPBytes
DocsRig a 3D model

Tool reference · 3D Models

Rig a 3D model

Add a skeleton and skin weights to a static model, with structural checks, bend tests and a preview to judge them.

MCP tool
rig_3d_model
MCP endpoint
/mcp/3d
REST
POST /v1/tools/rig_3d_model/jobs
Price
20 credits per job

Overview

Send one static GLB (a character, animal or creature) and get it back with a skeleton and skin weights, in the input's coordinates, scale and textures. Bones are named bone_0, bone_1, … with no body-part names, and no animation is added. Every job checks the rig: the skeleton's structure, weights that reach far from their bone, and a 45° bend of every bone that measures folded triangles, stretch and volume change. rig_report.json gives the status (passed, needs_review or failed_checks) and each issue with its bone, value and threshold; rig_preview.png shows the skeleton, the weights and the worst bend. A succeeded job means a valid rig was produced, not that it is ready to animate. Start the job, keep its id and poll: it takes a few minutes.

Formats
.glb (self-contained, uncompressed, one material, not already rigged or animated)
Outputs
model.glb (skinned, up to 4 bones per vertex), rig.json, rig_report.json, rig_preview.png and generation.json
Checks
Skeleton structure, far-reaching weights and a 45° bend test of every bone (folded triangles, stretch, volume)
Duration
Asynchronous; one-hour deadline including queueing and execution

Quickstart

Send the file as the request body with the options in the query string, or refer to it in a JSON body (upload_id or url) with an options object. The response is the new job; poll it until its status is final, then download the files in result.files.

Start a jobrig.sh
# Idempotency-Key is required: repeating it returns the same job
curl "https://api.mcpbytes.com/v1/tools/rig_3d_model/jobs?filename=model.glb&seed=42" \
  -H "Authorization: Bearer $MCPBYTES_API_KEY" \
  -H "Content-Type: application/octet-stream" \
  -H "Idempotency-Key: rig-example-001" \
  --data-binary @model.glb
Response202 Accepted · trimmed
{
  "tool": "rig_3d_model",
  "status": "queued",
  "input_kind": "file",
  "workflow": {
    "stage": "Rigging",
    "deadline": "2026-09-27T09:38:40.512Z",
    "cancel_pending": false,
    "refund_pending": false
  },
  "capabilities": {
    "can_cancel": true
  },
  "options": {
    "seed": 42
  },
  "result": null
}
Get the resultread.sh
# JOB_ID is the id from the create response; poll until status is final
curl "https://api.mcpbytes.com/v1/jobs/$JOB_ID" \
  -H "Authorization: Bearer $MCPBYTES_API_KEY"

# Once status is succeeded, download each file from result.files[].url
curl -fsSLo model.glb "$MODEL_URL"
Response200 OK · trimmed
{
  "tool": "rig_3d_model",
  "status": "succeeded",
  "result": {
    "notes": [],
    "bone_count": 34,
    "status": "passed",
    "issues": [],
    "files": [
      {
        "name": "model.glb",
        "bytes": 14968112,
        "content_type": "model/gltf-binary",
        "url": "https://api.mcpbytes.com/blob/dl/…"
      },
      {
        "name": "rig.json",
        "bytes": 6549,
        "content_type": "application/json",
        "url": "https://api.mcpbytes.com/blob/dl/…"
      },
      {
        "name": "rig_report.json",
        "bytes": 5224,
        "content_type": "application/json",
        "url": "https://api.mcpbytes.com/blob/dl/…"
      },
      {
        "name": "rig_preview.png",
        "bytes": 215861,
        "content_type": "image/png",
        "url": "https://api.mcpbytes.com/blob/dl/…"
      },
      {
        "name": "generation.json",
        "bytes": 2241,
        "content_type": "application/json",
        "url": "https://api.mcpbytes.com/blob/dl/…"
      }
    ]
  },
  "compute_ms": 37404,
  "credits_charged": 20
}

Jobs of this tool take minutes. While one runs, workflow.stage says what is happening and workflow.deadline when it must finish. Cancel it with POST /v1/jobs/{id}/cancel while capabilities.can_cancel is true.

More on statuses, downloads and retention in Jobs & files.

Input

One file per job, in one of these ways. The formats it accepts are listed in the overview.

Input sources
File body
REST only: the file itself as the request body, with ?filename= and the options in the query string.
upload_id
Create an upload URL (POST /v1/uploads, or create_upload over MCP), PUT the file to it, then pass the upload_id. Upload URLs expire after an hour.
url, filename
A public https URL. Add filename when the URL does not end in the file's extension.
job_file
{job_id, name}: an output of one of your own completed jobs that has not expired. It is copied into the new job, with no download in between.
# 1. Create an upload URL (valid for one hour)
curl https://api.mcpbytes.com/v1/uploads \
  -H "Authorization: Bearer $MCPBYTES_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filename": "model.glb"}'

# 2. PUT the file to the "url" from the response
curl -X PUT --data-binary @model.glb "$UPLOAD_URL"

# 3. Start the job with the "upload_id"
curl https://api.mcpbytes.com/v1/tools/rig_3d_model/jobs \
  -H "Authorization: Bearer $MCPBYTES_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{
    \"upload_id\": \"$UPLOAD_ID\",
    \"options\": {
      \"seed\": 42
    },
    \"idempotency_key\": \"rig_3d_model-upload-001\"
  }"
idempotency_key is required. Repeating a request with the same key returns the original job instead of starting and charging a new one; reusing a key for a different request returns 409 idempotency_conflict. With a file body, send the key as an Idempotency-Key header.

Options

Put options in the query string when the file is the request body, in the options object of a JSON body, or pass them as arguments of the MCP tool. Leave an option out to use its default.

Options
seed
integer 0 – 4294967295Sampling seed, reproducible within the same tested runtime; another seed can give another skeleton. Random when omitted.

Outputs

A succeeded job lists its files in result.files, each with a download url.

Output files
model.glb
The input model with a skeleton and skin weights (up to 4 bones per vertex), its textures and coordinates unchanged. No animation.
rig.json
The skeleton as data: each bone's name, parent, rest-pose head position, side (+x, -x or center) and how many vertices it moves.
rig_report.json
status, the thresholds used, the measurements (bone count, weights, a 45° bend test per bone) and the issues, each with bone, value, threshold and severity.
rig_preview.png
1024² image: the skeleton from the front and the side, each bone's area in its own colour, and the worst bend test.
generation.json
Provenance: your options and the rigging step's version, summary and timings.

Download links last up to 24 hours, capped by output retention; read the job again for fresh links. A succeeded job means a valid rig was produced; whether it is good enough is in rig_report.json and rig_preview.png.

Result summary

Next to files, the job's result has a summary you can check without downloading anything:

result
bone_count
Bones in the skeleton.
status
The report's verdict: passed, needs_review or failed_checks.
issues
The report's first five issues: type, bone, value, threshold, severity, and details such as a bend test's axis and degrees.

Tips

  • Read rig_report.json before using the rig, and look at rig_preview.png: needs_review means a measurement crossed its threshold; failed_checks means one reached twice its threshold, or a bone has no length.
  • A rig that fails its checks can be tried again with another seed; each job is charged.
  • Pass model.glb of a create_3d_model, create_3d_model_from_image or optimize_3d_model job as job_file, with no download in between.
  • rig.json lists each bone's parent, rest position, side of the model (+x, -x or center) and how many vertices it moves: enough to pick bones without opening the GLB.
  • Export one static mesh with one material. Models that are already skinned or animated, morph targets, several materials and vertex colours without a texture are refused before any charge.
  • The rigged file grows with the triangle count; above 1,000,000 triangles the job is refused. Reduce the model with simplify_3d_model first.

MCP

Your agent calls rig_3d_model. Connect it to https://api.mcpbytes.com/mcp/3d for this tool and the rest of its family (Create a 3D model, Create a 3D model from an image, Optimize a 3D model, Simplify a 3D model, Animate a 3D model, Split a 3D model into parts, Inspect a 3D model), or to https://api.mcpbytes.com/mcp for every tool.

Claude Code

The first form signs in through the browser when you run /mcp. In .mcp.json (project root), ${MCPBYTES_API_KEY} is read from the environment when Claude Code connects. Claude Code docs

claude mcp add --transport http mcpbytes \
  https://api.mcpbytes.com/mcp/3d
Codex (CLI, IDE extension, ChatGPT desktop)

Codex reads the key from the environment variable each time it connects. The same table can go in ~/.codex/config.toml by hand; codex mcp add has no --header flag. Codex docs

codex mcp add mcpbytes --url https://api.mcpbytes.com/mcp/3d \
  --bearer-token-env-var MCPBYTES_API_KEY
Cursor

~/.cursor/mcp.json (all projects) or .cursor/mcp.json (one project). Remote servers take no "type". Without the header, the client signs you in with GitHub or an email link (OAuth). Cursor docs

~/.cursor/mcp.json
{
  "mcpServers": {
    "mcpbytes": {
      "url": "https://api.mcpbytes.com/mcp/3d",
      "headers": {
        "Authorization": "Bearer ${env:MCPBYTES_API_KEY}"
      }
    }
  }
}
11 more clients in the docs →

Arguments

The tool's options are flat arguments. Besides them:

rig_3d_model arguments
upload_id
From create_upload, after the agent has PUT the file.
url, filename
A public https URL, and the file name when the URL does not end in the extension.
job_file
{job_id, name}: an owned output of an earlier job.
wait_seconds
0–45, default 0How long the call waits for the result. If the job is still running, the agent calls get_job.
idempotency_key
RequiredReuse it with the same arguments when retrying after a network error.

What the agent sees

MCP tools
rig_3d_model
Adds a skeleton and skin weights to a static textured GLB (a character, animal or creature) so it can be posed and animated in Blender, Godot, Unity or three.js. Keeps the input's coordinates, scale and textures. Accepts one self-contained, uncompressed GLB with a single material and no skin, animation or morph targets, up to 1,000,000 triangles. Returns model.glb (skinned), rig.json (bones, hierarchy and rest positions), rig_report.json (structural checks and bend tests, status passed, needs_review or failed_checks) and rig_preview.png. A succeeded job means a valid rig was produced, not that it is ready to animate: read rig_report.json and look at rig_preview.png. This is an asynchronous job; use get_job to follow progress. A failed job is refunded. Costs 20 credits per job. Requires idempotency_key; retain it when retrying the same request.
create_upload
Returns a one-hour URL to PUT a local file to; then call the tool with the upload_id.
get_job
Status and results of a job; waits up to wait_seconds for it to finish.
cancel_job
Cancel a queued job or a workflow whose can_cancel is true; repeated calls never delete results.
list_jobs
Your most recent jobs, newest first.
read_job_file
Reads a text output (.txt .json .md .csv) of a succeeded job in chunks.

Setup for every client, and how agents upload files and read results: Connect over MCP.

Agent skill

The MCPBytes skill teaches agents this tool, in references/rig_3d_model.md. Agents without MCP run it through the REST API with the skill's script, which reads your key from MCPBYTES_API_KEY:

mcpbytes.py
python scripts/mcpbytes.py run rig_3d_model model.glb \
  -o seed=42 --out rigged/
# Or an earlier job's output, without downloading it
python scripts/mcpbytes.py run rig_3d_model \
  --job-file j_... model.glb --no-wait
python scripts/mcpbytes.py job j_...

Pricing

20 credits per job. The price is charged before paid processing starts, and a canceled job is refunded. A job that fails costs nothing: its charge is refunded.

Per job
20 credits

One credit balance pays for every tool, and a new account starts with free credits. See Credits & prices or buy credits.

Limits

Limits
Jobs
20 per rolling 24 hours; 3 until your first credit purchase
Model
Up to 50 MB and 1,000,000 triangles
At a time
1 job
Uploads
Up to 50 MB
Results
24 hours by default

GET /v1/me returns your limits and current usage; Limits & errors explains what happens when one is reached.

Errors

A failed job comes back with error.code, error.message and often error.hint. Codes are stable. Inputs that fail with a validation error will fail again unchanged.

Job errors
invalid_mesh
Not a readable, self-contained GLB, or no mesh to rig.
limit_exceeded
More than 1,000,000 triangles.
too_large
HTTP 413 at creation: the file is larger than your plan's upload size.
unsupported_feature
Already skinned or animated, morph targets, several materials, or vertex colours without a texture; export one static mesh.
inference_failed
No skeleton could be made for this model. Try again with another seed, or change the input. Any charge is refunded.
timeout
The job did not finish within its deadline. Any charge is refunded.
capacity_exhausted
Budget exhausted: HTTP 503 at creation, or a failed job if the budget ran out before charging. Try again later.
unsupported_format
The tool does not take this file type.
insufficient_credits
The job costs more than the balance, which is known once the input has been measured. Nothing was charged.
out_of_memory
The file needs more memory than a job has.

Requests can also fail before a job starts, with an HTTP status: see HTTP errors.