Install
$ agentstack add skill-ig-shadow-walker-blenderxalpha-3dgenskill-alpha-scene-gen ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ● Network access Used
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
Alpha3D Scene Generator (for Blender)
Turns a plain-language scene or asset description into real, AI-generated 3D models, placed and scaled correctly inside the user's currently open Blender file. You are the orchestrator: your 3D provider's MCP connector does the AI generation, the Blender MCP connector does the placement, and you do the scene reasoning that ties them together, deciding what to generate, how big it should be, where it goes, and (by actually looking at the result) whether it landed right.
Three files carry the parts of this skill that are pure mechanism rather than judgment, so you don't have to re-derive them each time:
references/providers/.md: the adapter for your chosen 3D
provider (alpha3d, tripo, or meshy). Each maps that provider's MCP tools to the workflow's primitives. Read the one that matches provider.json (see "Which 3D provider" below).
references/blender_helpers.md: proven Python (download, sanitize,
import, normalize, place, and render a view so you can see the scene) to adapt inside your execute_blender_code calls. The sanitize step in particular fixes a real, previously-debugged Blender import failure. Don't skip it or try to reinvent it.
references/troubleshooting.md: what to do when a specific thing goes
wrong (bridge disconnected, malformed GLB, job errored, insufficient credits).
Which 3D provider (read this first)
This skill works with one configured 3D-generation provider. Before anything else, determine which one:
- Read
provider.jsonin this skill's own folder (next to this SKILL.md).
Its provider value is one of alpha3d (default), tripo, or meshy. If the file is missing or unreadable, default to alpha3d; if that provider's MCP is not connected but a different one is, tell the user which is connected and ask which to use.
- Read the matching adapter,
references/providers/.md. Each maps
that provider's real MCP tools to the four primitives this workflow needs: generate (text/image to a job), poll (job status), download URL (a GLB), and balance (credits, if the provider exposes it), plus refinement and reuse.
Throughout this workflow the Alpha3D tool names (generate_3d, get_job, fetch, get_credit_balance, list_generation_options) appear as the running example, since Alpha3D is the default and most complete provider. If your configured provider is Tripo or Meshy, substitute the equivalent tool from its adapter table; the logic of every step is identical. The Blender half (download, sanitize, import, scale, ground, place, look) is the same for every provider. The user picked the provider at install time and can change it by editing provider.json or re-running the installer with --provider.
Before anything else: confirm both connections are actually alive
This skill depends on two independent MCP connections, and either one can be missing or can have silently dropped since it was last used (the Blender bridge in particular is session-scoped to a running Blender instance and does not survive Blender closing or its add-on server being stopped). Don't assume either is up just because the tools appear in your tool list. Verify with a cheap, free call to each:
- Your 3D provider's MCP: make a cheap read call to confirm it is
connected and authenticated (Alpha3D get_credit_balance; Meshy meshy_check_balance; Tripo has no balance tool, so just confirm its tools are listed, or call get_task_status on a throwaway id). See your provider's adapter.
- Blender MCP bridge: run a trivial
execute_blender_codecall, e.g.
result = {"blender_version": bpy.app.version_string}. If this errors with a connection failure, the bridge server isn't running.
The exact tool names you call may carry a connector-specific prefix (e.g. mcp____generate_3d) that varies by session. If the plain names aren't already visible in your tool list, use your tool-search mechanism to find them by their short name (generate_3d, execute_blender_code, etc.) rather than assuming a fixed prefix.
If either check fails, stop and tell the user plainly what's missing and how to fix it (see references/troubleshooting.md for exact wording). Don't proceed partway and produce a confusing failure later.
Step 1: Turn the description into an asset plan
First, understand what you are building into. The scene is often not empty. If the request references existing content ("on the desk", "next to the character", "fill the empty corner") or the scene may already have objects, inspect it with a free execute_blender_code call (summarize_scene in references/blender_helpers.md) for the exact coordinates, and, for anything beyond a trivial empty scene, also look at it: use your bridge's screenshot tool or render a view (render_scene, see "Seeing the scene" in references/blender_helpers.md). A picture tells you the layout and orientation that a list of bounding boxes cannot. Anchor new assets to the real coordinates of what is already there, and keep them clear of existing geometry. Treat the scene as an empty floor only if it actually is one.
Then build a structured plan, one entry per distinct object. For each, decide:
- name: a short, descriptive label.
- count: how many of this exact object. If the user wants several
identical copies ("three crates", "a row of six pillars"), plan ONE entry with count > 1, not N separate entries. You generate or fetch the asset once and duplicate it in Blender (Step 4), so nine identical crates still cost a single generation. Only make separate entries when the copies should genuinely differ ("three different cottages" is three entries).
- source:
generate,reuse,primitive, orskip. This decision
drives cost, so make it deliberately:
reuse(free): if the user refers to something they already made
("my dragon from last week", "the crate I generated earlier", "use my existing models"), find it and import its download link instead of regenerating. This spends zero credits, so always prefer it. How you find it depends on the provider: Alpha3D search/list_library then fetch; Meshy meshy_list_tasks; Tripo can only re-fetch by a task id you kept (no library listing). If your provider can't list past work and you don't have the id, you may have to regenerate.
generate(spends credits): reserve AI generation for objects where
it earns its keep, like hero props, organic shapes, characters, anything with visual complexity or a specific look the user described.
primitive(free): a flat table, a simple crate, a wall, a floor
plane: build these with ordinary bpy primitives instead; generating a cube costs a full generation's credits for something bpy.ops.mesh.primitive_cube_add() does for free with an identical result.
skip: purely atmospheric elements (sky, fog, ambient light) aren't
meshes at all; note them in your final report and move on.
- prompt (for
generateitems): a clear, specific text prompt, or an
image URL if the user gave you a reference image.
- quality:
standard(fast/cheap, no PBR, fine for a rough
placeholder), pbr (full materials, the right default for anything the camera will actually see and that should look finished), or low_poly (real-time/game-ready). Don't default to the most expensive tier without a reason; ask yourself what the user actually needs it for.
- targetsizem: the object's largest real-world dimension in meters,
reasoned from what it is (a house is meters tall, a coin is centimeters). Generated meshes come back at an arbitrary internal scale, not the real world size. You normalize this after import in Step 4.
- needs_postprocess: does this asset need
rig_3d(a character or
creature the user wants to animate or pose), segment_3d (a mechanical object the user wants to manipulate part-by-part), retopologize, or uv_unwrap? Most background/dressing props need none of these; each one roughly doubles that asset's cost, so only add them when the user's intent calls for it (e.g. "rig it so I can pose it" clearly wants rig_3d; "make a village" alone does not imply any background prop needs rigging).
- placement: reason out where this belongs relative to everything else
from the description itself (and relative to any existing objects you found above). "Around a well" implies a circle; "along a path" implies points spaced along a line; an unordered list of props implies a simple grid with spacing derived from each item's target_size_m so nothing ends up overlapping. For a count > 1, write one coordinate per copy. Write down actual (x, y) coordinates now, you'll apply them in Step 4. If the description implies a facing (a cart "facing the well", chairs "around a table"), note a Z rotation too; generated meshes have no guaranteed front, so treat facing as best-effort and call it out in your report so the user can spin any that end up backwards.
Two provider-dependent tricks are worth knowing while planning (see your provider's adapter for what it supports):
- If the user dropped a local image into the chat, or wants
multi-view-to-3D (several angles of one object), you may not be able to submit it directly. Alpha3D has open_generator (hands them a web link); Tripo's community server has multiview_to_3d / upload_file; otherwise ask the user for image URLs. Then pick the result up with the provider's poll/list tools and import it like any other asset.
- A concept image first can lock a look before spending 3D credits: with
Alpha3D, generate_image (free) makes one you can feed into image mode. Check your adapter for whether your provider offers an equivalent.
Step 2: Show the plan, then STOP for explicit confirmation
This step is not optional and there is no phrasing of the user's original request that counts as already having given this confirmation, no matter how detailed their description was. Credits are debited the moment a job is submitted (refunded automatically only if that job later fails). So a misunderstood prompt, an unnecessarily high quality tier, or a postprocess step the user didn't actually want is real spent money, not something an undo button fixes.
Get the balance and pricing from your provider (never hardcode credit amounts; the provider is the source of truth and pricing can change). Alpha3D: get_credit_balance + list_generation_options (live per-op cost). Meshy: meshy_check_balance (per-op cost varies, so estimate from its pricing). Tripo: no MCP balance tool, so you cannot show a live number; say so, point the user at their Tripo console, and still show the plan and confirm. Then show the user a plan table: asset name, source, quality, credits (if known), any postprocess + its credits, subtotal, the grand total, and the balance remaining after. Reuse, primitive, and skip rows are free; only generate and postprocess rows cost credits.
If any credits will be spent, wait for an explicit go-ahead in the conversation before calling generate_3d (or any other credit-spending tool). If the whole plan happens to be free (all reuse/primitive/skip), you can proceed once you've shown it, but still show it first so the user can correct anything before you build.
If the balance will not cover the whole plan, say so now. Generation runs one asset at a time (Step 3) and stops when credits run out, so tell the user roughly how many assets their balance covers and let them top up, trim, or reprioritize before you start. Order the plan by importance so that if it does stop early, the scene still got the assets that matter most.
Step 3: Generate and place, one asset at a time (a queue)
Work through the plan as a queue, one credit-spending job at a time, not in parallel. Sequential generation is what lets the run stop on a clean boundary the moment credits run out, instead of having already submitted (and paid for) a batch it cannot finish.
Reuse and primitive assets are free, so handle those whenever convenient (fetch + import, or build the primitive); they don't affect the credit logic. For the generate assets, go in the priority order you set at Step 2 and, for each one in turn:
- Check you can afford it first. Track the remaining balance from the
figure you showed at Step 2, subtracting each job as it completes. If the next asset's cost is more than what's left, stop here: do not submit it. A free get_credit_balance call confirms the real number if you are unsure.
- Submit exactly one job with
generate_3d, passing a clear, unique
title (the asset's name from your plan; it labels the asset in the user's library, which is what makes recovery and reuse possible later).
- **Poll
get_job(job_id)every 15-30 seconds until it iscompletedor
error.** Real generations take minutes; that is normal, so don't shorten the interval or give up early. This waiting naturally spans several of your own turns.
- On
completed, import and place it right away (Step 4) so the user
watches the scene fill in as it goes. On error, record the reason (the credits auto-refund) and move on; one failed asset should not sink the rest.
- Continue to the next asset in the queue.
Stopping for lack of credits is not a failure, so don't report it as one: say what got built, what is still queued, and how many more credits the rest would need. The assets already placed stay in the scene, and anything generated is saved in the user's library, so once they top up you can resume from where you left off (via the reuse path) without repaying for what is already done.
> Why one at a time and not in parallel: submitting every job at once debits > every job's credits up front. If the balance cannot cover the whole plan, a > parallel batch spends on work it cannot complete and ends in a messy, > half-done state. A queue keeps spend predictable and stops cleanly.
Step 4: Import and place one asset (one execute_blender_code call)
Each asset has a GLB download URL: for a generate asset it comes from its completed get_job; for a reuse asset it comes from fetch(id). The import is identical either way.
Do the whole thing in a single call rather than several round trips: download the GLB bytes, truncate them if Blender's strict loader would otherwise reject them ("Bad GLB: file size doesn't match" is a real, previously-hit failure; see why in references/blender_helpers.md), write to a temp file, import, compute its bounding box, scale to target_size_m, drop it to the ground plane, group it under a named Empty, and move that Empty to the coordinates you planned in Step 1. The working code is in references/blender_helpers.md. Read it and adapt the parameters per asset rather than writing it from scratch; the byte-truncation math in particular is easy to get subtly wrong if you rederive it.
For an asset with count > 1, use build_asset (in references/blender_helpers.md): it downloads the GLB once and places a uniquely-named copy at each coordinate you planned, so the extra copies cost no credits, and it cleans up the temp file for you. For a very large count, duplicate_linked makes mesh-sharing copies that keep the scene light. This is the other half of the cost story: identical copies never re-generate.
If a completed job's response includes more than one download link (segment_3d splits a mesh into labeled parts, each its own GLB), import every part under the same parent Empty rather than creating a separate Empty per part. The parts are meant to be treated as one object made of pieces, not as separate scene objects.
Step 5: Optional refinement pass
For any asset flagged needs_postprocess in Step 1, submit the relevant tool (rig_3d
…
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: ig-shadow-walker
- Source: ig-shadow-walker/BlenderXAlpha-3DGenSkill
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.