MPFB MCP
OfficialAn MCP server for inspecting and driving MakeHuman/MPFB character workflows inside Blender, combining read-only discovery with guarded write operations.
Inspect MPFB status/configuration and current Blender objects, and summarize character phenotype, rig, assets, skin, targets, face, expressions, and material settings.
Browse installed rigs, mesh/skin assets, asset alternative materials, modeling targets, expressions, presets, developer docs, and community URLs.
Create MakeHuman characters, including from saved presets, and save characters as reusable presets.
Adjust phenotype/macro sliders and modeling targets; symmetrize targets; refit assets and rigs after shape changes.
Attach standard, custom, or Rigify rigs, and generate a final Rigify rig from a meta rig.
Equip/remove garments, body parts, and body proxies; switch or restore asset materials.
Compose ARKit face units, apply saved expressions, and save live faces as reusable expression files.
Apply skins and edit procedural eye, layered skin, hair, and garment material settings.
Writes are batched/guarded with detailed results, refusals, dry-run support, and overwrite protection; pose/export/placement tools mentioned in the README are not present in this schema.
Provides an MPFB-specific bridge for Blender, enabling tools to create, inspect, and modify MakeHuman/MPFB characters, rigs, assets, materials, face units, expressions, presets, and scene objects.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@MPFB MCP create a MakeHuman character and summarize it for me"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
MPFB MCP
An MCP server with MPFB tools. Its Blender-side half is a companion add-on of our own, the MPFB Bridge in bridge/, which dispatches a closed vocabulary of named commands rather than executing code.
In practice, you will most likely want to use this in parallel with a Blender MCP bridge such as either of:
Blender Lab's Blender MCP
Ahujasid's MCP for Blender
In fact, you can control MPFB solely by using either of these, but it will then be an inefficient and token-heavy thing. By steering MPFB-specific operation to the MPFB specific bridge, you can speed up things and save some tokens.
Status
Early beta. Forty-two tools are implemented.
Introspection — read-only, and each of them always answers rather than failing:
mpfb_get_status— is MPFB present, initialized and correctly configured?mpfb_get_character_summary— what is this character, in one call: phenotype, rig, assets, skin, morphs, face and where it stands, each exactly as the detailed tool below would report it?mpfb_list_objects— which MakeHuman objects are in the current scene?mpfb_get_object_info— what is this object, what was it made from, and what belongs with it?mpfb_get_macro_details— what is this character's phenotype?mpfb_get_target_stack— which modeling targets are on this character, and how strong?mpfb_get_face_units— what is this character's face doing, in ARKit face units?mpfb_get_expression— which saved expressions is this character wearing, and do they explain its face?mpfb_get_material_settings— what are this character's iris colours, layered skin and hair and garment tints, exactly as a preset would save them?mpfb_get_pose_controls— which bones pose this character, by body part, what does each do, and where does it rest?mpfb_get_pose— what is this character's pose now: what is off rest, where are its hands, feet, hips and head, and is a limb stretched or out of reach?mpfb_get_rigify_hand_shape— on a Rigify character, how curled and spread is each finger, what shape is each hand making, and where are the fingertips?
Catalogues — what could be added, each entry named the way the acting tool will want it:
mpfb_list_rigs— which armatures could be attached?mpfb_list_assets— which garments, body parts, body proxies and skins are installed?mpfb_list_targets— which modeling targets could be set?mpfb_list_asset_materials— which other materials ship beside this equipped asset?mpfb_list_presets— which characters have been saved?mpfb_list_expressions— which saved expressions are installed?
Documentation — addresses to look something up, and neither of them fetches anything:
mpfb_list_urls— where to download MPFB, get asset packs, ask on the forum, file a bug. Answers even when MPFB or Blender is unreachable, which is when those links matter most.mpfb_list_docs— MPFB's developer documentation, one document per service and file format.
Creation and modification:
mpfb_create_human— wraps MPFB'sHumanService.create_human().mpfb_set_macro_details— change a character's phenotype in place.mpfb_set_targets— set modeling targets, batched.mpfb_symmetrize_targets— copy one side of a character onto the other.mpfb_set_face_units— compose a character's face from ARKit face units. Transient: not saved by a preset, and overwritten by the next expression applied.mpfb_apply_expressions— put a character into saved expressions, blended at chosen weights, or take them all off.mpfb_save_expression— keep a composed face as an expression file, which is what makes it survive: apply the file, and presets carry it.mpfb_refit_human— refit everything to a changed body.mpfb_add_rig/mpfb_generate_rigify_rig— attach an armature, and finish a Rigify meta rig.mpfb_add_asset/mpfb_remove_asset— equip an MHCLO asset, and take it off properly.mpfb_set_skin— give the character a skin, in any of MPFB's five material models.mpfb_set_asset_material— recolour an equipped asset, or restore its own material.mpfb_set_material_settings— change iris colours, the layered skin and the tint of hair and garments, batched, in a way a preset keeps.mpfb_set_pose_bones— pose a character: move, rotate, aim and scale its controls in the character's own forward, left and up, batched, and say where each one actually ended up.mpfb_set_pose_switches— change a generated Rigify rig's IK/FK, pole, parent and stretch switches, keeping each limb where it is as Rigify's own buttons do.mpfb_set_rigify_hand_shape— on a Rigify character, make a fist, point, grip or pinch, or curl and spread any finger by an amount, one call per change.mpfb_reset_pose— put a character back at rest, and answer with the calls that put the pose back: Blender's own undo does not see what these tools do.mpfb_place_character— stand a character somewhere in the scene, facing a direction or a point or the camera, and say how much room it takes up, so that several can be lined up. MPFB builds every character at the origin.mpfb_save_preset/mpfb_create_human_from_preset— keep a character past this Blender session, and build a new one from a saved character.mpfb_create_export_copy/mpfb_export_character— take a character to a game engine or another application: a processed copy, as MPFB's Export copy panel makes one, with visemes, ARKit face units and GameEngine materials if asked; then one FBX, glTF or USD file, with presets for Unity, Unreal and Godot. The file goes in a directory set in the MPFB Bridge's preferences, never one the agent picks.
mpfb_save_preset, mpfb_save_expression and mpfb_export_character are the only tools here
that write a file, and nothing in Blender can undo it, so each refuses to overwrite unless told to.
Order matters and MPFB reports no error when it is wrong: add the rig before the garments, generate a Rigify rig after them, and dress a character before placing it - a garment with its own sub-rig, such as a ponytail, equipped on a character away from the origin is bound wrong until the character is refitted. The tools report the violation they can see rather than enforcing it.
See src/mpfbmcp and CLAUDE.md for how they work and how to run them.
Related MCP server: blender-unified
Documentation
The structured specifications for the project live in the specifications/ directory. Start with its index. Highlights:
Vision — why this project exists, why a bridge add-on of our own, and the target tool catalog.
Architecture — standing architectural principles new tools should follow.
To install every part from this checkout — MPFB, the bridge add-on, the server and an MCP client configuration — follow INSTALL.md. Developer setup and commands are documented in CLAUDE.md. Planned and in-progress development efforts are tracked in feature-requests/.
Available Tools
34 toolsmpfb_add_assetADestructive
Equip a MakeHuman character with one mesh asset from an MHCLO - a garment, a body part (hair, eyes, eyebrows, eyelashes, teeth, tongue) or the body proxy.
Rig the character before dressing it: MPFB rigs a garment only if a
rig is present when the garment is attached, and nothing rigs it
retroactively. The asset is attached either way, and rigged_to names
the armature or is null with parented_to naming the basemesh.
object_type is required, and is exactly what
mpfb_list_assets reports for the entry: Clothes, Proxymeshes,
Eyes, Eyebrows, Eyelashes, Hair, Teeth or Tongue. MPFB's
own function defaults it to "Clothes", which mislabels a body part
silently and permanently, so there is no default here;
object_type_recorded echoes what was stored.
Name the asset with either path or fragment, never both;
mpfb_list_assets reports both. A fragment ("fedora/fedora.mhclo")
is portable but is resolved by basename, so two packs shipping
hat.mhclo resolve to a coin toss - check resolved_path when
path_resolved_by is "fragment".
material_type is MAKESKIN, GAMEENGINE, PROCEDURAL_EYES or
NONE, and is best left unset: it then follows MPFB's settings panel
per asset type - NONE for Proxymeshes, MAKESKIN for everything
else - and material_type_used reports the choice. PROCEDURAL_EYES
is accepted only for Eyes. NONE deletes the imported mesh's
materials and creates nothing, even when the MHCLO names one;
material_created and warnings say when that happened.
subdiv_levels (default 1, MPFB's own) sets the subdivision modifier's
render level, viewport level 0; 0 adds no modifier.
set_up_rigging, interpolate_weights, import_subrig and
import_weights are MPFB's own flags at MPFB's own defaults. Fitting
to the body and the delete group are unconditional, so neither has an
argument, and an alternative material is chosen afterwards with
mpfb_set_asset_material.
On added: true, result carries asset_object_name - read off the
created object, since Blender uniquifies a name already in use, and the
address mpfb_remove_asset and mpfb_set_asset_material need - plus
basemesh_name, resolved_path/path_resolved_by/asset_source,
object_type_recorded, material_type_used,
material_created/material_name, rigged_to or parented_to,
subrig_object_name, delete_group_name and
delete_group_applied_to, subdiv_modifier_added, warnings for what
MPFB only logs, and proxy_extras - the four things a Proxymeshes
asset gets from MPFB's .mhm loading path, which this follows rather
than its proxy library panel.
Refusals come back as added: false (and so performed: false) with a
blocked_by and a sentence: subject_not_found, asset_not_found,
unknown_object_type (with known_object_types),
invalid_material_type, no_asset_subdir and not_object_mode.
Inputs: object_type (required), name, path, fragment, +6 more. Returns: object
mpfb_add_rigADestructive
Attach a rig to an existing MakeHuman character - MPFB's "Add standard rig" / "Add rigify rig" / "Add custom rig".
Rig the character before dressing it. MPFB rigs a garment only if a
rig is present when the garment is attached, and nothing rigs it
retroactively. This tool does not refuse to rig a dressed character -
decorative garments are legitimate - but mesh_assets_not_rigged names
every asset it just failed to rig, and a non-empty list is a mistake
unless you meant it.
identifier is exactly what mpfb_list_rigs reports in its
identifier field, never the name beside it and never a filename:
"default_no_toes" for a standard rig, "rigify.human" for a Rigify
one, "custom.my_rig" for a user one. The prefix selects which of
MPFB's two non-interchangeable adding functions runs, and
add_function_used says which was taken.
import_weights (default true, MPFB's own) loads the vertex weights
and adds the armature modifier. With it false the mesh is parented to
the armature but not deformed by it.
A rigify.* identifier produces a meta rig, not a finished rig.
is_metarig: true comes back with a next_step: attach the garments
first, then call mpfb_generate_rigify_rig. A meta rig deforms nothing
on its own.
On added: true, result carries rig_object_name - read off the
created object, since Blender uniquifies a name already in use, and the
address other tools need for the rig - plus basemesh_name,
add_function_used, family, is_metarig/next_step,
weights_loaded with weights_from and weights_path (MPFB
resolves weights through a fallback table, so a rig legitimately
borrowing another's is normal and weights_loaded: false is not),
armature_modifier_added, basemesh_location_before with
basemesh_moved_to_origin and rig_location - both adding functions
move the basemesh to the origin and give the armature its old location,
which visibly moves a character standing anywhere else - and
mesh_assets_not_rigged / subrigs_not_rigged.
Refusals come back as added: false (and so performed: false) with a
blocked_by and a sentence: subject_not_found, unknown_identifier
(with known_identifiers for the family you addressed),
rigify_unavailable, not_object_mode, and already_rigged - MPFB
cannot swap a rig, so an existing one has to be deleted first.
Inputs: name, identifier, import_weights. Returns: object
mpfb_apply_expressionsADestructiveIdempotent
Put a MakeHuman character into saved expressions, through MPFB's
applied-expressions stack - the mechanism its expressions-library panel
and presets use, so the result survives mpfb_save_preset.
expressions is a list of {fragment, weight}: fragment as
mpfb_list_expressions reports it, weight in 0.0-1.0. Weight 0.0
removes that expression. mode is "merge" (default: add or update
these rows, keep the rest) or "replace" (the stack becomes exactly
these rows) - replace with an empty list takes every expression
off. Weights from several rows add up per face unit and are clamped
at 1.0.
Nothing is written unless every fragment resolves; the refusal
(blocked_by: "unresolved_fragments") names the misses and the closest
existing fragments. It also refuses without the faceunits01 pack.
The face is rebuilt from the stack, so units composed on top of it
with mpfb_set_face_units are discarded and named in
discarded_face_units - call mpfb_save_expression first to keep them.
refit (default true, as MPFB's library panel) refits the mesh assets and the rig.
result carries changed (the stack or the face moved), requested
(per row: action of added / updated /
removed / unchanged / absent, and resolved_path), the resulting stack
and face as mpfb_get_expression reports them (applied_expressions,
aggregate, clamped_face_units, matches_stack), stack_before,
removed_by_replace and panel_synced (MPFB's library sliders updated).
Inputs: mode, name, refit, expressions. Returns: object
mpfb_create_humanADestructive
Create a new MakeHuman character - a basemesh with a phenotype -
through MPFB's HumanService.create_human(). The starting point for
building a character: shape it further with mpfb_set_targets, rig it
with mpfb_add_rig before dressing it with mpfb_add_asset, and
give it a skin with mpfb_set_skin, without which it stays grey.
The eleven macro sliders (gender, age, muscle, weight,
proportions, height, cupsize, firmness, race_asian,
race_caucasian, race_african) are 0.0-1.0 and are the same
sliders under the same names as mpfb_set_macro_details takes, so a
character can be created and then adjusted without relearning the
vocabulary. The two differ in what an omitted slider means: here every
one has a default and the character is built from the full set, while
there an omitted slider is left alone. Set the phenotype in this call
when you know it; use mpfb_set_macro_details to change one
afterwards.
0.5 is neutral for every slider except the three race weights, whose
neutral is 0.33 each. age runs 0.0 = baby, 0.1875 = child, 0.5 =
young adult, 1.0 = old; gender 0.0 = fully female, 1.0 = fully male.
The three race weights are independent and MPFB does not normalize
them, so the defaults sum to 0.99 and setting one to 1.0 does not
reduce the other two.
scale is the basemesh scale factor (0.1 = decimeters, MPFB's own
default). Change it only deliberately: mpfb_set_skin's enhanced skin
types read it to pick subsurface radii.
create_human()'s own defaults are used for mask_helpers,
detailed_helpers, extra_vertex_groups and feet_on_ground; this
tool does not expose them.
On status: "ok", result carries basemesh_name - the address every
later tool needs, since Blender uniquifies a name already in use - plus vertex_count,
location and the macro_detail_dict that was applied, in MPFB's own
nested shape. performed is true: creation either succeeds or raises,
so this tool has no separate verb of its own.
Inputs: age, scale, gender, height, +8 more. Returns: object
mpfb_create_human_from_presetA
Build a new character from a saved MPFB preset: phenotype, modeling targets, rig, body parts, garments, skin and eye materials. It adds a character and changes nothing already in the scene - this is not "load into the current character". Seconds, not milliseconds: it imports and fits every asset the preset names.
preset_name is a name, never a path - mpfb_list_presets reports the
ones that exist, and a miss here comes back with available_presets
naming them.
Each override defaults to null meaning use what the preset says;
overrides in the response reports, per argument, what you asked for,
what the preset held and what was used.
override_rig:"NONE"for no rig, or anyidentifiermpfb_list_rigsreports,custom.*included. Arigify.*preset gives you a meta rig - finish it withmpfb_generate_rigify_rig.override_skin_type:mpfb_set_skin's fiveskin_typevalues, plus"NONE"for no skin at all.override_clothes_material_type/override_eyes_material_type:mpfb_add_asset'smaterial_type, for garments and every body part but the eyes, and for the eyes.load_clothesfalse builds the body and skips the garments.scale: 0.1 metre (MPFB's default), 1.0 decimetre, 10.0 centimetre.material_instances_policy:NEVER,ENHANCEDorENHANCEDMS- which skin types get per-region material slots. Defaults toENHANCED, which is MPFB's preset panel's default rather than theNEVERits service function defaults to; both come back, asmaterial_instances_policy_usedand_service_default.
On created: true (and so performed: true), result carries
basemesh_name, rig_object_name and rig_identified_as,
equipped_assets (kind, name and asset_source per item),
skin_material_identified_as, settings_used (MPFB's own settings
dict, in MPFB's own key names), objects_created and
active_object_after - the selection is not restored, because
deserialization activates what it creates and there is no prior state
to return to.
Read unresolved_assets. A preset that names a garment or body
part which is not installed here loads without it and MPFB says
nothing; that field names each one and the subdirectory it was looked
for in.
Refusals come back as created: false with a blocked_by:
preset_not_found (with available_presets), preset_unreadable,
not_object_mode, unknown_material_instances_policy,
config_dir_missing,
settings_incomplete, and deserialization_failed - the one that is
not a no-op, since a character is built in stages, so
objects_created names what was left behind. Its commonest cause is a
rig the preset names and this Blender lacks: MPFB's rig adders raise
rather than degrade, so retry with override_rig.
Inputs: preset_name (required), scale, load_clothes, override_rig, +4 more. Returns: object
mpfb_generate_rigify_rigADestructive
Turn a character's Rigify meta rig into a generated, poseable
Rigify rig - the second step of the two mpfb_add_rig starts when
given a rigify.* identifier.
Attach the character's garments and other mesh assets before calling
this. Generation re-parents and re-weights whatever is on the
character at the moment it runs, and nothing handles an asset added
afterwards. mesh_assets_present reports what was there.
Unlike the other character tools, name resolves to the meta rig
rather than to the basemesh, and metarig_name says which armature was
used. generated_rig_name is a basename, not the final object name:
omit it for MPFB's own fallback, which derives a unique name from the
meta rig's, and read rig_object_name for what it became.
meta_rig_action (default "hide", MPFB's own) is what becomes of the
meta rig afterwards: "keep" leaves it visible, "hide" keeps it in
the scene but out of viewport and renders, "delete" removes it.
Prefer "hide". Deleting the meta rig makes the character
permanently unrefittable: mpfb_refit_human can only refit a generated
Rigify rig through its meta rig, and with none in the scene it refits
the mesh assets, leaves the rig behind and says nothing.
refit_will_be_possible reports this either way.
This tool is not undoable and cannot restore your selection.
Generation's own last act is to select and activate the rig it made, so
active_object_after reports what is active now instead.
On generated: true, result carries rig_object_name,
metarig_name, metarig_disposition (kept/hidden/deleted),
refit_will_be_possible, mesh_assets_present and
active_object_after.
generated: false does not mean nothing happened, though
performed follows it. When Rigify judges the meta rig invalid it
returns after MPFB has already deselected everything, activated the
meta rig and possibly renamed it or run Rigify's face upgrade; that
case reports metarig_renamed and metarig_name_after beside the
refusal. Other refusals carry a blocked_by: subject_not_found,
no_armature_found, not_a_metarig (rigged, but not with a Rigify
meta rig), already_generated (generation moved this character onto
its generated rig, so its meta rig is no longer among its relatives),
rigify_unavailable and not_object_mode.
Inputs: name, meta_rig_action, generated_rig_name. Returns: object
mpfb_get_character_summaryARead-onlyIdempotent
Summarize one MakeHuman character before changing it, in one call: what it is, what it wears, and what its face is doing. Changes nothing. Call this first; call a detailed tool only for what the summary leaves out.
result carries one section per detailed tool: a subset of its
fields under the same names, read by the same code, so the two never
disagree.
phenotype-mpfb_get_macro_details.rig-mpfb_get_object_infoon the rig;nullwhen there is none.rigify_rolesays whether it is a meta rig or generated.equipped_assets-mpfb_get_object_info's related objects: every equipped garment, body part and body proxy, by type then name. Not capped.skin-mpfb_get_object_infoon the basemesh.targets-mpfb_get_target_stackwith its defaults: themodifiersrollup,asymmetriesand the counts. Capped: ifrollup_truncated, only the largest entries are here, andmodifier_count/asymmetry_countgive the whole.face-mpfb_get_face_units(non-zero units only) andmpfb_get_expression(applied_expressions,matches_stack,unexplained_face_units). A non-emptyunexplained_face_unitsis composed work the nextmpfb_apply_expressionscall destroys.
On a miss found is false and every section is null or empty.
Inputs: name. Returns: object
mpfb_get_expressionARead-onlyIdempotent
Read which saved expressions a MakeHuman character is wearing (MPFB's
applied-expressions stack) and whether they explain its live face.
Changes nothing. For the raw live face-unit values, call
mpfb_get_face_units; this tool reports only how they differ from the
stack.
result's applied_expressions is one row per expression: fragment,
weight, resolved and path. A row whose file cannot be found or
read (resolved: false, counted in unresolved_count) contributes
nothing to the face. aggregate is the face the stack produces;
clamped_face_units names units whose sum across rows passed 1.0.
matches_stack is false when the live face differs from
aggregate; unexplained_face_units then lists each such unit with
its live and from_stack values. That is composed work (see
mpfb_set_face_units) that the next mpfb_apply_expressions call or
preset load will overwrite; mpfb_save_expression keeps it.
faceunits01_installed is always present; refresh re-probes for it.
An unresolvable subject is found: false, not an error;
basemesh_name names the object actually read.
Inputs: name, refresh. Returns: object
mpfb_get_face_unitsARead-onlyIdempotent
Read the ARKit face units currently applied to a MakeHuman character's
face - the live !ex- shape key values mpfb_set_face_units writes.
Changes nothing.
result's face_units is one entry per face unit: face_unit (the bare ARKit
name, e.g. "jawOpen"), value, and shapekey_present - whether a
real shape key backs this value or MPFB is reporting a default for a
unit that has never been touched. Defaults to the non-zero units only;
include_zero (default false) returns all 52.
known_face_units is always present regardless of whether a
subject resolves: every legal name mpfb_set_face_units will accept,
grouped by facial region (brow, eye, cheek, jaw, mouth, nose, tongue)
the way MPFB's own composer panel lays out its sliders.
faceunits01_installed is always present too, and is the one
thing that separates "a neutral face" from "the faceunits01 asset pack
was never installed" - both read as every unit at 0.0, and MPFB
itself gives no other way to tell them apart. That check is cached for
the Blender session; refresh (default false) busts the cache, which
matters if the pack was installed after this Blender started.
A subject that cannot be resolved to a basemesh is an answer, found: false with a sentence, not an error; basemesh_name names the object
the answer was actually read from.
Inputs: name, refresh, include_zero. Returns: object
mpfb_get_macro_detailsARead-onlyIdempotent
Read a MakeHuman character's macro details - its phenotype sliders: gender, age, muscle, weight, proportions, height, cupsize, firmness and the three race weights. Changes nothing.
Call this before mpfb_set_macro_details: that tool leaves unnamed
sliders alone, so knowing the current values is what makes a relative
change ("a bit older") possible. An unresolvable name, nothing active,
or an object with no basemesh among its relatives each come back as
found: false with a message, not as an error.
result carries:
macro_details: the current values in MPFB's own nested shape (gender,age, ..., plusraceholdingasian,caucasianandafrican).mpfb_set_macro_detailsreturns the same shape but takes its arguments flat:race.asianis set asrace_asian.default_macro_details: what MPFB considers neutral - every slider 0.5, every race weight 0.33.race_sumandrace_normalized: the three race weights are independent 0.0-1.0 properties and MPFB does not normalize them. The default sums to 0.99; settingrace_asianto 1.0 and leaving the others alone builds a character from weights summing to 1.66, which is legal and probably not what was wanted.macro_target_stackandmacro_target_count: what those values mean in target terms, each entry carrying thetarget_fragmentMPFB loads from disk and theshapekey_nameit becomes. Neither is a name any tool accepts as input; they explain the shape, they do not address it.current_macro_shapekeys: the macro shape keys actually on the mesh now, under the names they are stored with - the same vocabulary asmacro_target_stack'sshapekey_name, so the two can be compared directly. If they disagree, the properties were changed without a recalculation andmpfb_set_macro_detailswill repair it.macro_driftis that comparison made for you, weights included.current_macro_shapekeys_decodedis the same list in MPFB's readable form, for reading rather than comparing.has_shapekeysandis_human_project: a mesh tagged as a basemesh but never built by MPFB reads back a full set of macro properties that mean nothing. These two are how that is told apart.basemesh_name,subject_nameandsubject_resolved_by("name" or "active").
Inputs: name. Returns: object
mpfb_get_material_settingsARead-onlyIdempotent
Read a MakeHuman character's procedural material settings - exactly
what mpfb_save_preset saves for them - for
mpfb_set_material_settings to change. Changes nothing.
result has three sections: eyes (procedural eyes), skin (the
LAYERED skin) and color_adjustments (one record per mesh asset, for
the MakeSkin node on its Base Color). One that does not apply says
applies: false and a reason. section ("eyes", "skin" or
"color_adjustments") reads one and reports the others as null; a
full answer can pass 20 KB.
Per node - the eyes, each group in skin.groups (keyed color,
body, face, ... as the preset keys them), each colour adjustment -
keyed by MPFB's own socket names:
settings: each value as the preset holds it, a float or a colour as four scene-linear RGBA numbers. A write takes these as is.srgb_hex:#rrggbbper colour socket, derived for reading only.ranges:[min, max]where a float declares one,nullfor an open end;values_outside_rangenames any value already outside.linked: sockets driven by another node (from_node,from_socket), which a write cannot change. Most layered region colours are linked from thecolorgroup.material_shared_with: other objects a write would change too.
A colour adjustment record also has object_name, object_type,
uuid (the preset's key) and node_name: diffuseIntensity, or on
an asset with an AO map aoMix, whose only writable socket is the AO
strength - MPFB saves that node, and the tint is out of reach. The
eyes never keep one. An unresolved subject is found: false.
Inputs: name, section. Returns: object
mpfb_get_object_infoARead-onlyIdempotent
Identify one Blender object, say what MakeHuman asset it was made from, and list what else belongs with it. Changes nothing, selects nothing.
name is a Blender object name, typically one from
mpfb_list_objects. Omit it to ask about the currently active
object - what the user just created or clicked. Not resolving a
subject is a normal answer: found is false and message says whether
no such object exists or nothing is active.
result always carries found, subject_resolved_by ("name" or
"active") and message. When found is true it also carries:
name: the resolved object's name. Carry this forward rather than re-deriving from the active object, which changes as the user clicks.in_current_scene: object names are unique across the whole .blend, so a name can resolve to an objectmpfb_list_objectsdoes not list. False here is not a contradiction between the two tools.object_type(MPFB's type, or null for a plain Blender object),blender_type,is_makehuman_object.rigify_role: "generated_rig", "metarig", or null - reported whatever the object's type, because MPFB tags the rig it generates through Rigify as aSkeleton.asset_info: what the object was made from, or null when it has no MPFB type. Its keys depend on the object type - a skeleton has no mhclo, so it has nomhclo_pathkey rather than a null one.Skeleton/Subrigcarryrig_identified_asandrig_definition_path; a mesh asset (Clothes,Eyes,Hair,Proxymeshes, ...) carriesasset_source,mhclo_path,material_identified_as,material_sourceandmhmat_path; aBasemeshcarries the last three. An unrecognized MakeHuman type gets an empty dict.related_objects: the MakeHuman objects among this one's parents, children and siblings - "what belongs with this character" - each with the same fields plus its ownasset_info, excluding the subject. A flat list, not a tree; call this tool again on a name to walk the structure.other_related_objects: relatives carrying no MPFB type, each with arigify_role. This is where a Rigify rig built outside MPFB shows up: it drives the character but appears in no other list this server returns.
Reading asset_info correctly: every *_path is an absolute path or
null, while the *_source fields beside them are MPFB's short
fragments and are not paths. The pair keeps two situations apart -
a null fragment means nothing was recorded, a fragment with a null path
means the asset is recorded but is not installed under any asset root
this Blender can see. A null material_source on a mesh asset is
ordinary: the object uses the default material named inside its mhclo,
deliberately not resolved here. The *_identified_as values are read
off the object as it is now, while the *_source fragments
record what was loaded and are never rewritten when the object is
edited by hand; where they disagree, the identified value describes
reality. And mhclo_path may point at a .proxy file, so do not
decide what something is from the suffix.
Inputs: name. Returns: object
mpfb_get_statusARead-onlyIdempotent
Report whether MPFB is loaded and usable in the connected Blender, and how it is configured. Takes no arguments, changes nothing.
Call this first when any other MPFB tool fails unexpectedly: those tools fail with a bare error when MPFB is missing or broken, and this one tells the two apart.
result always carries:
state: "absent" (MPFB not loaded), "not_initialized" (loaded, but registration did not complete - installed and broken, or half-registered) or "ok". All three are normal answers, not errors.message: one sentence naming the state and the likely next step, suitable for showing to a user verbatim.candidate_modules: every loaded module name ending in "mpfb". Normally one; two or more means MPFB is installed twice, which explains erratic behavior from the other MPFB tools.package,enabled,blender.version.
With state "not_initialized" or "ok" it also carries version and
build_info. With state "ok" it additionally carries
is_source_dist, addon_installation_path, paths (each entry a
path plus a configured flag), asset_roots, asset_packs,
rigify_available, and blender.platform /
blender.meets_mpfb_minimum / blender.mpfb_minimum_version.
Parts of the result (paths.second_root and anything derived from it)
are scene-scoped and change when a different .blend is loaded. Re-call
rather than cache.
Inputs: no named parameters. Returns: object
mpfb_get_target_stackARead-onlyIdempotent
Read the modeling targets currently applied to a MakeHuman character - every shape key on its basemesh, and the modeling sliders they add up to. Changes nothing.
result has two views of the same facts, addressed differently.
targets- one entry per shape key:shapekey_name(the raw Blender name, and the addressmpfb_set_targets'targetslist takes),decoded_name(readable; a name over 60 characters is stored encoded, and only the raw one works as an address),value,kind(macro/expression/detail/unknown), and where the target sits in MPFB's index:section,category,side,polarity,listed_in_target_json, all null for a user target belonging to no category.modifiers- the same information rolled up pertarget.jsoncategory, each{section, category, side, value}withvaluein -1.0..+1.0. This is the view MPFB's own sliders show and the one that feeds straight back intompfb_set_targets'modifierslist. Only categories with a non-zero reading appear; never paged, never filtered byname_contains.
asymmetries lists the left/right categories whose two sides differ -
which MPFB's own UI does not surface anywhere - and is what makes
mpfb_symmetrize_targets an informed operation rather than a blind
one. basemesh_name names the object the stack was read from.
include_macro (default false) adds the $md- phenotype shape keys,
which are mpfb_get_macro_details' subject; include_expressions
(default false) adds the !ex- expression ones. counts_by_kind
reports both counts whether or not they were included.
The answer is capped. limit defaults to 200 and cannot exceed
1000. Read truncated and total_count before concluding a target is
not on this character, and narrow with name_contains rather than
paging blindly; counts_by_section says where the entries are.
This tool sees one thing MPFB itself cannot. MPFB excludes any
shape key whose name contains "basis", not merely equals it, so a
user target called basis-nose-widen is real, is deforming the mesh,
and is invisible to every MPFB read and write. It is listed here with
visible_to_targetservice: false, and it cannot be changed through
mpfb_set_targets either.
A subject that cannot be resolved to a basemesh is an answer, found: false with a sentence, not an error. A character whose macro numbers
and macro shape keys have drifted apart is reported as it is, not
repaired.
Inputs: name, limit, offset, include_macro, +2 more. Returns: object
mpfb_list_asset_materialsARead-onlyIdempotent
List the alternative materials that ship beside one equipped MHCLO asset - the other colours of a hat - and name the one it is wearing now. Changes nothing about the character.
These are not in mpfb_list_assets' answer. That tool lists MPFB's
asset library sections; alternative materials live in the asset's own
directory instead. This is the only catalogue for them, and it is what
mpfb_set_asset_material consumes.
name is the asset's own Blender object name, as
mpfb_list_objects reports it or as mpfb_add_asset returned it in
asset_object_name.
The answer is a snapshot. MPFB caches this scan per asset and
nothing invalidates that cache on its own, so a material added to the
asset's directory after the first call for that asset - in this
Blender session - will not appear. refresh=true clears the cache
first; cache_invalidated says whether it did. That clear is global -
every asset's cached list is dropped, not only this one's - which is
why the default stays false.
result carries asset_object_name, object_type, asset_source and
the asset_subdir searched; default_material, the absolute path the
asset's own MHCLO names, with exists saying whether that file is
there, or null with default_material_reason saying why not;
current_alternative_material, the fragment recorded on the object
now; materials, one entry per alternative with path, fragment,
name and is_default - MPFB does not filter the asset's own
material out of this scan, so the default usually appears and is
flagged rather than removed; count; search_roots, the directories
actually scanned, so "this hat has no other colours" is distinguishable
from "the hat's asset source no longer resolves"; and
cache_invalidated.
An object that is not an asset comes back as found: false, or with an
empty list and an explanation, never as an error.
Inputs: name (required), refresh. Returns: object
mpfb_list_assetsARead-onlyIdempotent
Find the MakeHuman assets installed in this Blender - garments, hair,
eyes, eyebrows, eyelashes, teeth, tongue, body proxies, skins,
poses - narrowed by subdir, by a keyword in the name, and by asset
pack. Adds nothing to the scene. The forward counterpart of
mpfb_get_object_info, which says what an existing object was made
from.
The answer is capped and is usually a subset. Check truncated
before concluding an asset is not installed; total_count says how
many matched. The first call for a subdir is the slow one: MPFB loads a
preview image per asset, once per subdir per Blender session.
Arguments, all optional and combining with AND:
asset_subdir- one of"clothes","hair","eyes","eyebrows","eyelashes","teeth","tongue","proxymeshes","skins","poses","ink_layers", matched exactly and case-insensitively. Omit it to search every subdir, then readcounts_by_asset_subdirto pick a narrower one.name_contains- case-insensitive substring of the asset's name or label.pack- substring of an installed pack's name, so"hair03"findshair03_ccby.limit(default 200, max 1000) andoffset- paging over the matched set, sorted by subdir then name.refresh- rescan first. Needed only when assets were installed after Blender started; it rescans the whole library and writes MPFB's caches.
result carries:
assets: this page's entries, each withname(filename without extension),label(MPFB's display text),fragment,path,object_type,asset_subdir,file_type,pack,pack_ambiguousandthumb_path.counts_by_asset_subdir: how many assets each scanned subdir holds, ignoringname_contains,packand the cap.requested_asset_subdir/asset_subdir_recognized/known_asset_subdirsandrequested_pack/pack_recognized/known_packs, so a misspelling is distinguishable from an empty subdir or pack.asset_roots_searched: per subdir, the directories actually scanned. A configured data root that does not hold that subdir is not searched, which is the usual explanation for "I installed it and it is not listed".count,total_count,truncated,offset,limit.
How to name an asset when applying it. Pass an entry's path
(absolute) or its fragment ("fedora/fedora.mhclo", what MPFB
records on the resulting object and what survives a move to another
machine) to mpfb_add_asset, together with its object_type. Assets
in skins are materials rather than meshes and go to mpfb_set_skin
instead. A fragment is not a path; handing one to a file-opening
tool fails confusingly. For skins, poses and ink_layers the
object_type ("Material", "Pose", "Other") says what the asset
is rather than naming an argument.
pack is derived from a directory-name convention, not recorded by
MPFB. pack: null is ordinary for a hand-installed asset, and
pack_ambiguous: true means two packs claim the name and the reported
one is a coin toss. total_count can under-report too: MPFB's cache is
keyed by a label derived from the filename alone, so two assets whose
filenames differ only in case or underscores collapse into one entry.
Inputs: pack, limit, offset, refresh, +2 more. Returns: object
mpfb_list_docsARead-onlyIdempotent
Addresses for MPFB's developer documentation - one document per service
(HumanService, TargetService, ...), per file format (.mhclo,
.mhmat, .target, the preset and rig JSON) and for its object
property store. Use it to answer "how does MPFB actually do X" rather
than inferring it from a tool response.
Changes nothing, needs no Blender and no MPFB, and fetches nothing:
it returns URLs for the client to retrieve. raw_url returns the
markdown; page_url is the rendered page for a person.
Arguments, both optional: topic (general, services,
fileformats, entities, ui; exact, case-insensitive) and keyword
(case-insensitive substring over path, title, description and
keywords). With neither, returns everything it has.
A curated subset, not the tree. curated is always true,
tree_document_count says how large the tree it was drawn from is, and
tree_url is the full listing - go there when what you need is not
here, rather than concluding it does not exist. Pinned to master
(ref), so a document may describe a newer MPFB than the installed one.
result carries:
documents: each{path, raw_url, page_url, title, description, keywords, topic},pathbeing repo-relative (docs/services/humanservice.md). Titles, descriptions and keywords are mpfb-mcp's own text; MPFB publishes no index.count,curated,curated_document_count,tree_document_count,tree_url,ref,repository.requested_topic,topic_recognized,known_topics,requested_keyword. An unknown topic matches nothing rather than failing, so checktopic_recognizedbefore reading an emptydocumentsas "no such documentation".
Not capped and not paged: under twenty entries, so no truncated or
total_count to check.
Inputs: topic, keyword. Returns: object
mpfb_list_expressionsARead-onlyIdempotent
List the saved expressions MPFB can apply - named, weighted
combinations of ARKit face units such as a smile - as
mpfb_apply_expressions takes them. Changes nothing.
result's expressions is one entry each: fragment, the identifier
to pass (library-relative, portable across machines), path (the
absolute file, for checking), root, label, description, tags,
author, license and face_units (what the expression sets). Not
capped or paged.
roots lists the directories scanned, in MPFB's priority order,
whether or not anything was found. unreadable names files MPFB
skips because they do not parse. shadowed names files hidden behind a
same-named file in a higher-priority root: MPFB cannot apply them.
faceunits01_installed is always present: without that asset pack no
expression can be applied. refresh (default false) re-probes for the
pack; the file scan itself is never cached.
Inputs: refresh. Returns: object
mpfb_list_objectsARead-onlyIdempotent
List the MakeHuman objects in the connected Blender's current scene, optionally filtered by MPFB object type. Changes nothing.
Use this to find a subject for the other MPFB tools when you did not
create the character yourself, then pass a returned name to
mpfb_get_object_info to learn what that object actually is.
object_type is one of MPFB's own type names ("Basemesh",
"Skeleton", "Subrig", "Proxymeshes", "Clothes", "Eyes",
"Eyelashes", "Eyebrows", "Teeth", "Tongue", "Hair"); omit it
to get every MakeHuman object. Matching is MPFB's own, a
case-insensitive substring test rather than equality: "rig" matches
Subrig, and "mesh" matches both Basemesh and Proxymeshes. That
is deliberate on MPFB's side and is not a bug here.
Only the current scene is searched, so results match what the user is
looking at. An object that exists in the .blend without being linked
into the scene is not listed - mpfb_get_object_info will still
resolve it by name and say so.
result carries objects, one entry per match with name (the
Blender object name, which is how every other tool addresses it),
object_type (MPFB's type) and blender_type ("MESH", "ARMATURE",
...); count; requested_object_type, the filter as given or null;
object_type_recognized, whether it matched a type MPFB knows -
check this before concluding anything from an empty list, since
"no basemeshes in this scene" and "you asked for Basemseh" are
otherwise the same answer; and known_object_types, MPFB's full type
vocabulary read from MPFB itself, so a misspelling can be corrected
from this same response.
The result is an address other tools will act on. Re-call rather than cache: loading another .blend, or the user deleting an object, invalidates it entirely.
Inputs: object_type. Returns: object
mpfb_list_presetsARead-onlyIdempotent
List the character presets saved in MPFB's user config directory -
MPFB's "save files", the same ones its own preset panel offers. Each
entry's name is what mpfb_save_preset and
mpfb_create_human_from_preset take; neither accepts a path.
Not capped and not paged, unlike the other listing tools: a preset
collection is tens of files. No preset is parsed, so this says nothing
about what is in one; mpfb_create_human_from_preset reports that for
the one it loads.
refresh=true rescans the directory through MPFB. MPFB caches the list
for the Blender session and rebuilds it only when a preset is saved, so
one written by hand, by another Blender or by an earlier session is
missing until then - but you do not need to pass refresh to find that
out: missing_from_mpfb_list already names any preset file the cache
does not hold, because this tool lists the directory itself as well.
result carries:
presets: per presetname,path,size_bytes,modified(ISO 8601 with a UTC offset) andexists.size_bytesandmodifiedcome fromos.stathere, not from MPFB, which records neither.exists: falsemeans MPFB's cached list still names a preset whose file has been deleted.Per preset,
addressableandnot_addressable_reason. MPFB's own panel accepts names these tools will not - anything that could become a path - so a preset saved by hand can be listed here and refused by the other two. Rare, and worth seeing here rather than in a refusal.config_dirandconfig_dir_exists: the directory that was scanned, reported whether or not anything was found, so an empty list is an answer rather than an ambiguity.count,files_in_config_dir,missing_from_mpfb_list,refreshed,listing_failed(a sentence when MPFB could not read the directory at all) andmessage.
Inputs: refresh. Returns: object
mpfb_list_rigsARead-onlyIdempotent
List every rig this Blender could add to a MakeHuman basemesh: MPFB's bundled standard and Rigify rigs, plus custom rigs found in the user's data directories. Adds nothing to the scene.
Pass a rig's identifier, not its name, to mpfb_add_rig. The
two are not the same string: a standard rig is "default_no_toes", a
Rigify one "rigify.human", a custom one "custom.my_rig". The prefix
also picks between MPFB's two non-interchangeable adding functions -
add_function says which - and crossing them does not read as the
mistake it is: a built-in name handed to the custom function comes back
missing under a mangled one.
refresh=true rescans the user data directories for custom rigs first.
MPFB caches that list for the lifetime of the Blender session, so a rig
installed after Blender started will not appear otherwise.
result carries:
rigs: one entry per rig, withname,identifier,family("standard"/"rigify"/"custom"),path(absolute, or null),label/description(MPFB's own UI text, null for custom rigs),add_function,availableandunavailable_reason.Per entry, what adding it would do about weights:
has_weights,weights_pathandweights_from. MPFB resolves weights through a fallback table, not by filename, soweights_fromdiffers fromnamefordefault_no_toes(which borrowsdefault's) andrigify.human(which borrowsrigify.human_toes's). That is normal.has_weights: falseis not: adding that rig produces a character with no vertex weights.count,families,message, andrigify_available- whether Rigify is enabled here. Rigify rigs are listed either way, carryingavailable: falsewhen it is not, since adding one then raises rather than degrading.rig_dirs: every directory looked in, each flagged with whether it exists. MPFB scans its own data dir and the user data roots - not the MakeHuman user data directory.unrecognized_custom_rig_files:.jsonfiles in a scanned user rigs directory that MPFB refused as rig definitions - a name outside[A-Za-z0-9_], or noidentifying_boneskey. MPFB drops these silently, which otherwise makes "I put the file there and it does not show up" undiagnosable.
Do not expect this list to match mpfb_get_object_info's
rig_identified_as. That value comes from MPFB identifying an armature by its
bone names and can be rigify_generated.* or unknown, neither of
which names something addable. A character whose rig is not in this
list is ordinary, not an error.
Inputs: refresh. Returns: object
mpfb_list_targetsARead-onlyIdempotent
Find the MakeHuman modeling targets available in this Blender - the
named morphs like nose-scale-depth-incr that shape a character - and
report each under the name that setting it will require. Changes
nothing.
The phenotype (gender, age, weight, muscle, height, proportions) is
not here: they are attributes on the basemesh
rather than target files, and are mpfb_get_macro_details /
mpfb_set_macro_details territory.
The answer is capped. Check truncated before concluding a target
does not exist; total_count says how many matched.
Arguments, all optional: section (a section name from target.json
or synthesized from a user target directory, matched exactly and
case-insensitively; omit it for the overview), name_contains
(case-insensitive substring, applied to category and target names
alike), and limit (default 200, max 1000) with offset, which page
over a section's categories when it has them and over user_targets
otherwise.
result carries:
sections: every section, each{name, label, source, category_count, target_count}. Around thirty entries, always present.sourceis"system","user", or"both"when a user directory shares a bundled section's name - common, and MPFB merges the two, so such a section returns both.categories: present whensectionnamed one with bundled categories, each{name, label, has_left_and_right, targets, opposites}fromtarget.json. These are whatmpfb_set_targets'modifiersentries address, andoppositesis thedecr/incrand left/right pairing behind MPFB's sliders.nullwhen no section was asked for, or the one asked for is only a user directory.user_targets: what the user data directories hold, filtered tosectionwhen one was given, each withname,shapekey_name,pathandlisted_in_mpfb_ui.target_json_path/target_json_existsandsystem_targets_dir: the bundled index is ~140 KB of JSON and is not returned here - a client that can read the Blender host's filesystem should parse it directly instead.unindexed_system_target_dirs: bundled target directories with notarget.jsonsection, each with a count. The index reads as the complete list of bundled targets and is not.user_target_dirs: the directories actually scanned, so a target that did not appear can be looked for where it was expected.requested_section/section_recognized/known_sections,count,total_count,truncated,offset,limit.
How to name a target when setting it. Use shapekey_name, never
name. name is the filename with its extension stripped, for
display; shapekey_name is what MPFB calls the shape key and the only
string it accepts. The two are equal for most targets and not above
60 characters, where MPFB encodes the name - and a caller using name
there addresses nothing at all, silently. Inside a category, targets
and opposites are already in that form.
Two differences from MPFB's own modeling panels, both real rather than
bugs here: this tool scans per call, so it reports a target installed
since Blender started, which the panels cannot show until it restarts;
and listed_in_mpfb_ui: false marks a *.target.gz outside the
custom section, loadable but skipped by MPFB's own scan.
Inputs: limit, offset, section, name_contains. Returns: object
mpfb_list_urlsARead-onlyIdempotent
Addresses for the MPFB and MakeHuman community sites: downloading MPFB, asset packs, documentation, forum, issue tracker. Takes no arguments, changes nothing, and fetches nothing - it hands back URLs for the client to retrieve.
Use it rather than composing a makehumancommunity.org address. Reach
for it when mpfb_list_assets finds little (URL_ASSET_PACKS) or
mpfb_get_status reports the system assets pack missing
(URL_SYSTEM_ASSETS). For MPFB's developer documentation, one
document per service and file format, use mpfb_list_docs instead.
It answers even when MPFB or Blender is unreachable, which is when
these links matter most - so check source_of_truth before quoting a
URL: "mpfb" was read from the running MPFB, "builtin_fallback" is
mpfb-mcp's vendored copy with fallback_reason saying why. Neither is
an error.
result carries:
urls: every link, each{key, url, title, description, keywords, source}.keyis MPFB's own constant name (URL_ASSET_PACKS).sourceis"mpfb"for one of MPFB's constants,"mpfb_mcp"for an ecosystem link this package adds (MakeHuman itself, the community asset repository).title,descriptionandkeywordsare mpfb-mcp's text rather than MPFB's, and arenullfor a constant MPFB has added since.source_of_truth,fallback_reason,blender_reachable, andmpfb_status(state:ok,absent,not_initializedorunreachable; pluspackage,version,weburls_module,weburls_read).fallback_staleandfallback_differences: whether the vendored copy disagrees with the running MPFB, and per key how (changed,added_by_mpfb,missing_from_mpfb). Bothnullwhen there was nothing live to compare against, which is not agreement.count,vendored_mpfb_key_count,skipped_keys.
Not capped and not paged: around twenty entries, all of them, every
call. No truncated or total_count to check.
Inputs: no named parameters. Returns: object
mpfb_refit_humanADestructiveIdempotent
Re-fit everything on a MakeHuman character to the current shape of its basemesh: every mesh asset (garments, body parts, the body proxy), the rig, and any sub-rigs.
Call this after changing a character's shape with
mpfb_set_macro_details, mpfb_set_targets or
mpfb_symmetrize_targets while leaving their refit at its default of
false - those tools report assets_possibly_stale when they leave work
for this one. A refit re-runs the vertex fit per asset, so make a
series of modeling changes first and refit once at the end. It is
idempotent: refitting a character already in fit is safe and costs the
same.
result carries refit_performed, basemesh_name, rig_object_name,
mesh_assets with mesh_asset_count, and subrigs.
Check refit_performed rather than assuming success; performed
is set from it, so the two cannot disagree. One case refits the mesh
assets but leaves the rig untouched: a rig generated by Rigify whose
meta rig is no longer in the scene cannot be refitted at all, and MPFB
reports this through a channel that does not reach an MCP tool.
refit_incomplete_reason then says so, and the fix - regenerating with
the meta rig kept - is the user's to make in Blender. A basemesh left
in edit mode answers with ready: false, and an unresolvable subject
with found: false and blocked_by: "subject_not_found".
Inputs: name. Returns: object
mpfb_remove_assetADestructive
Take one mesh asset - a garment, a body part or the body proxy - off a MakeHuman character and clean up after it, the way MPFB's own "unload" does.
Use this rather than deleting the object. MPFB hides the body under a garment with a mask modifier on the basemesh (and on the body proxy, for garments), and a garment may have brought a sub-rig of its own. Deleting the object with a generic Blender tool leaves both behind, and the character keeps a hole in it with nothing visible to explain it.
name is required and is the asset object's own Blender name, as
mpfb_list_objects reports it or as mpfb_add_asset returned it in
asset_object_name. There is no active-object fallback: this deletes
an object. Equipping two copies of one asset gives ...hat and
...hat.001, so check which you are naming. This is not undoable
across the socket: the object and its mesh data are gone when the
call returns.
On removed: true, result carries asset_object_name, object_type
and asset_source - all read before the deletion - plus
basemesh_name, objects_removed naming everything the call deleted,
mask_modifiers_removed naming the objects and modifiers that went,
subrig_removed, and two things MPFB leaves behind and never mentions:
vertex_groups_left_behind (the Delete.<name> groups themselves;
only the modifiers referencing them are removed) and
mesh_data_orphaned (the mesh datablock, which keeps no users until
the file is saved and reloaded). Both are harmless and both are
invisible unless reported.
Refusals come back as removed: false (and so performed: false) with
a blocked_by and a sentence: subject_not_found, basemesh_not_found,
not_object_mode, asset_source_missing - without it the mask
modifier cannot be identified and removal would be silently partial -
and not_a_mesh_asset, which refuses a basemesh or a skeleton
outright, because the underlying MPFB function would happily delete
either.
Inputs: name (required). Returns: object
mpfb_save_expressionADestructive
Save a MakeHuman character's live face - every non-zero ARKit face unit
as a named expression file that
mpfb_apply_expressionscan apply and presets can carry. This writes a file outside the .blend, and nothing in Blender can undo it. The character is not changed.
expression_name is a name, never a path: the file is
<expression_name>.json in the expressions directory of MPFB's user
data, and path and fragment are in every answer. Same rule as preset
names: letters, digits, _, -, ., at most 64 characters, no leading
dot.
What is saved is the whole live face, including what applied
expressions contribute. To make it durable, call
mpfb_apply_expressions with mode: "replace" and the new fragment
at 1.0 - replace, not merge, or the stack counts twice. result's
apply_with holds exactly those arguments.
overwrite (default false) refuses an existing file
(blocked_by: "expression_exists", file_before giving its size and
age); the directory is shared with installed asset packs. Other
refusals, nothing written: name_shadowed (a same-named file in a
higher-priority data root would hide this one from MPFB for good -
shadowed_by names it), empty_expression (every unit is 0.0),
subject_not_found.
Optional metadata, stored as given: description, tags (list of
strings), author, copyright, license (default "CC0", MPFB's
composer default), homepage. On success result also carries
face_units and metadata as read back from the file, overwrote,
and panel_synced (whether MPFB's library panel gained the slider).
Inputs: expression_name (required), name, tags, author, +5 more. Returns: object
mpfb_save_presetADestructive
Save a character as an MPFB preset - phenotype, modeling targets, rig,
body parts, garments, skin and eye materials - to be rebuilt later with
mpfb_create_human_from_preset or from MPFB's own preset panel.
This writes a file outside the .blend, and nothing in Blender can
undo it.
preset_name is a name, never a path: the file is always
human.<preset_name>.json in MPFB's user config directory, and path
in the response says which file that was. Letters, digits, _, - and .
only, at most 64 characters, no leading dot - stricter than MPFB's own
panel, which rejects only a space, so that a name cannot become a path.
basemesh_name says which character was actually serialized.
overwrite (default false) is the only thing standing between a call
and the loss of an existing preset. With it false and the preset
present, the tool refuses - blocked_by: "preset_exists", nothing
written - and file_before carries that file's size and age so the
decision can be made from the response.
A generated Rigify rig does not round-trip. MPFB stores the meta
rig it was generated from, so loading the preset back gives you the
meta rig and mpfb_generate_rigify_rig finishes the job. Nothing is
lost and nothing fails; rig_identified_as and rig_saved_as show the
substitution on the call where it happened.
On saved: true (and so performed: true), result carries path,
size_bytes, modified, overwrote, file_before (the replaced
file's facts, or null), config_dir, basemesh_name, rig_object_name,
rig_identified_as/rig_saved_as, and contents - what the written
file actually holds, read back from it: rig, proxy, bodyparts,
clothes, skin_mhmat, skin_material_type, eyes_material_type,
target_count, expression_count, makeup_count.
Refusals come back as saved: false with a blocked_by, having
written nothing: subject_not_found, preset_exists,
not_a_human_project (MPFB only serializes characters made within
MPFB, not imported meshes), rig_not_identifiable (an armature MPFB
cannot name - for a custom rig, its definition is no longer in your
user data), config_dir_missing and serialize_failed.
Inputs: preset_name (required), name, overwrite. Returns: object
mpfb_set_asset_materialADestructive
Replace the material on an equipped MHCLO asset with one of the alternatives that ship beside it - a hat in another colour - or put the asset's own material back.
name is required and is the asset's own Blender object name,
as mpfb_list_objects reports it or as mpfb_add_asset returned it in
asset_object_name - not the character's. There is no active-object
fallback: this destroys that object's current material.
Name the material with either path or fragment, never both.
Both come from mpfb_list_asset_materials, the only catalogue for
them: alternative materials sit in the asset's own directory rather
than in an asset library section, so mpfb_list_assets does not know
about them.
restore_default (default false) instead puts back the material named
by the asset's own MHCLO and clears the recorded
alternative_material. It cannot be combined with path or
fragment.
MPFB has no service-level "set an alternative material" - the logic
exists only in its asset library panel - and two of that panel's quirks
are reproduced here rather than tidied up, because tidying them would
make the result differ from what a user gets from the panel: the new
material is always a MakeSkin material named makeskinmaterial,
whatever the asset had before, and the slots are popped rather than
deleted, so node groups from the previous material survive. The
viewport display colour comes from MPFB's per-type table keyed on the
asset's object_type, so an asset mislabelled when it was equipped
gets the wrong colour here too; diffuse_color_from reports which type
was used and is null when the neutral grey fallback applied.
On applied: true, result carries asset_object_name,
object_type, asset_subdir, path_resolved_by/resolved_path,
alternative_material (the fragment now recorded on the object, empty
when the default was restored) beside alternative_material_before,
materials_destroyed, material_name and diffuse_color_from.
Refusals come back as applied: false (and so performed: false) with
a blocked_by and a sentence: subject_not_found, not_an_mpfb_object,
material_not_found, not_object_mode, asset_source_missing and
default_material_not_found (both for restore_default on an asset
whose own MHCLO cannot be found or names no material on disk), and
type_not_supported for a Basemesh, Proxymeshes or Skeleton -
MPFB's own panel refuses all three, and the first two have a skin
rather than an asset material, which is mpfb_set_skin's job.
Inputs: name (required), path, fragment, restore_default. Returns: object
mpfb_set_face_unitsADestructiveIdempotent
Compose a MakeHuman character's face from ARKit face units - the same
52-unit vocabulary mpfb_get_face_units reads and MPFB's own composer
panel edits, applied directly to the !ex- shape keys.
Send the whole expression as one call. face_units is a list of
{face_unit, value}, value in 0.0-1.0. Call mpfb_get_face_units
first if you need the exact 52 legal names, grouped by region in
known_face_units.
Nothing is written unless every name resolves. Every face_unit is
checked against MPFB's own vocabulary before anything is touched; one
misspelled name refuses the whole call and unknown_face_units names
it together with the closest legal spellings. This tool also refuses
outright when the faceunits01 asset pack is not installed, since
every target file would then be missing - check
mpfb_get_face_units' faceunits01_installed first if unsure.
mode is "merge" by default, matching MPFB: a face unit not
mentioned in face_units is left exactly as it was. "replace" zeroes
every one of the 52 units before applying this call's entries, which is
the difference between "smile a bit more" and "make this face and
nothing else"; removed_by_replace names what it zeroed.
refit (default true, unlike every other refitting tool here:
composing is normally one call) re-fits the mesh assets and the rig afterwards.
A composed face is transient. MPFB has two mechanisms over one set
of shape keys: this tool writes them directly, while saved expressions
live on a stack (mpfb_get_expression) that mpfb_apply_expressions
and preset loads rebuild the face from, discarding anything composed
here. result's matches_stack is false when the face now differs
from the stack, and unexplained_face_units lists what the next rebuild
would overwrite. mpfb_save_expression keeps a composed face.
result carries changes - one entry per unit actually written, with
previous_value and new_value - plus loaded_from_disk (units whose
shape key had to be created from a target file on this call),
could_not_load (a unit whose target file was missing even though the
pack passed its own install probe - a partially installed pack), and
skipped_absent_at_zero (a unit requested at 0.0 with no shape key
yet, which is left alone rather than created). basemesh_name names
the object actually changed. A subject that cannot be resolved
(found: false, subject_not_found) and a basemesh in edit mode
(ready: false) are answers, not errors.
Inputs: mode, name, refit, face_units. Returns: object
mpfb_set_macro_detailsADestructiveIdempotent
Change a MakeHuman character's macro details - its phenotype sliders - and rebuild the shape from them, exactly as MPFB's own sliders do.
Every slider is optional and an omitted one is left alone, so a
relative change is one call: read the character with
mpfb_get_macro_details, then pass only what should differ. Passing a
slider its current value is not the same as omitting it - it is
reported in changes with previous_value equal to new_value.
Sliders are 0.0-1.0, and 0.5 is neutral for all but the three race
weights, whose neutral is 0.33 each. age runs 0.0 = baby, 0.1875 =
child, 0.5 = young adult, 1.0 = old; gender 0.0 = fully female, 1.0 =
fully male. The three race weights are independent and MPFB does not
normalize them: setting race_asian to 1.0 does not reduce the other
two, and the default sums to 0.99. Set all three when changing one, or
read race_sum in the response and decide.
prune (default true, MPFB's own) deletes macro shape keys whose
weight falls to zero, keeping the shape key list from growing as
sliders move. refit (default false, MPFB's own) re-fits the mesh
assets and the rig to the new body shape. The default is false because a refit
is expensive, not because it is unnecessary: leave it false, read
assets_possibly_stale, and call mpfb_refit_human once after a
series of changes rather than paying for a refit per slider.
result carries changes (one {name, previous_value, new_value}
per slider named), the full macro_details after the change,
race_sum, macro_shapekeys_before/_after with shapekeys_removed
and shapekeys_added - all four naming shape keys as the mesh stores
them ($md-$as-$fe-$yn), so a name from here can be looked up rather
than only read - plus recalculated, refit_performed,
assets_possibly_stale and basemesh_name.
Two situations answer rather than fail, both with changes: []: a
subject that resolves to no basemesh (found: false,
subject_not_found), and a basemesh that is not ready to be modified -
left in edit mode, or with no shape keys at all (ready: false,
blocked_by naming which). A call that
names no slider also does nothing, deliberately, rather than paying for
a shape rebuild that would change nothing; it comes back performed: false.
Inputs: age, name, prune, refit, +10 more. Returns: object
mpfb_set_material_settingsAIdempotent
Change a MakeHuman character's procedural material settings - iris
colours, the LAYERED skin, the tint of hair and garments - as one
all-or-nothing batch that survives mpfb_save_preset and
mpfb_create_human_from_preset. Take section, group and socket names
from mpfb_get_material_settings.
eyes:{socket, value | color}skin:{group, socket, value | color},groupas the read keys itcolor_adjustments:{object_name, socket, value | color}
Exactly one of value (a float socket) and color (a colour socket).
A color is four scene-linear RGBA numbers, like the read's
settings, not sRGB: a colour picked by eye comes out too light
unless converted.
Nothing is written unless every entry resolves; resolution_errors
gives each failure's reason: section not applicable, unknown group
or socket (with closest), wrong key for the socket's kind, a float
outside its range, or a linked socket, which a write cannot change.
Most layered region colours are linked from the color group, and
write_instead names the socket to set.
On the layered skin, color's SkinColor shows fully with no diffuse
texture and over one only as far as SkinOverride raises it; each
region colour has its own *Override. A colour adjustment mixes
Color1 with the texture by Factor, so a low Factor is flat
colour without texture detail.
mpfb_set_skin, mpfb_set_asset_material and re-adding the eyes
rebuild a material from MPFB's defaults, discarding these settings.
result's changes lists each socket in request order with
previous_value/new_value and previous_srgb_hex/new_srgb_hex;
materials_written names other objects sharing a written material,
which changed too.
Inputs: eyes, name, skin, color_adjustments. Returns: object
mpfb_set_skinADestructive
Give a MakeHuman character a skin, the way MPFB's own skin library panel does.
This destroys every material already on the character. MPFB deletes
all materials on the basemesh and on the body proxy, node groups
included, before building the new one, and there is no undo across the
socket. materials_destroyed names what went, per object.
Name the skin with either path or fragment, never both;
mpfb_list_assets reports both for every entry whose object_type is
Material (the skins subdir). A fragment is resolved by
basename, so resolved_path always reports which file was actually
loaded. Give neither only with skin_type="LAYERED", the one type
that builds a material from nothing.
skin_type is MAKESKIN (default), GAMEENGINE, ENHANCED,
ENHANCED_SSS or LAYERED: five entirely different node trees built
from the same MHMAT - MakeSkin's own, a plain PBR material for export,
the enhanced one without and with subsurface scattering, and the
multilayered one, which MPFB warns is expensive to render rather than
to build. All five cost about the same to build, so pick on the look
you want. The default follows MPFB's settings panel, not
set_character_skin()'s own signature, which defaults to
ENHANCED_SSS.
material_instances (default true) asks for the per-vertex-group
material slots - fingernails, lips, ears, nipples, toenails, genitals.
MPFB's UI forces it off for LAYERED, GAMEENGINE and MAKESKIN,
and so does this tool, so the default call creates no instances at
all. material_instances_requested comes back beside
material_instances_used, with a sentence when they differ.
On applied: true, result carries basemesh_name and
bodyproxy_name - MPFB applies the skin to the body proxy too, and
nothing else would tell you - plus resolved_path, material_source
(the fragment MPFB recorded, written only when an MHMAT was given,
so a LAYERED skin with no file leaves the previous value in place,
which material_source_before makes visible), skin_type_used,
material_instances_requested/_used, materials_destroyed,
material_slots per object, material_identified_as,
active_body_slot, and two facts nothing in Blender would show you:
settings_file_created, true when the enhanced skin types copied
enhanced_settings.default.json into your user config directory - the
only file mpfb-mcp ever writes outside the .blend - and
scale_assumption (METER/DECIMETER/CENTIMETER), which the
enhanced types derive from the character's scale_factor and which
changes the subsurface radii. It is null for the three types that do
not use it, and METER for an ordinary MPFB character.
Refusals come back as applied: false (and so performed: false) with
a blocked_by and a sentence, and change nothing on the way to finding
out: subject_not_found, unknown_skin_type (with
known_skin_types), no_material_given, skin_not_found,
not_object_mode, and skin_failed for a failure inside MPFB itself -
reported rather than raised precisely because the materials are already
gone by then.
Inputs: name, path, fragment, skin_type, +1 more. Returns: object
mpfb_set_targetsADestructiveIdempotent
Change a MakeHuman character's modeling targets - one modifier (a per-category slider), one raw target, or fifty of them in one call.
Send the whole change as one call. A round trip costs about half a second and the work inside costs milliseconds.
modifiers is the level to use normally. Each entry is {section, category, value, side}, naming a target.json section and one of its
categories exactly as mpfb_list_targets reports them:
valueruns -1.0..+1.0 for a category that hasopposites- the sign picks which of the opposing pair is loaded, and the other is driven to zero - and 0.0..1.0 for one that does not.sideis"left","right"or"unsided". Required for a category withhas_left_and_right: true, and omitted or"unsided"for one without.
targets is the escape hatch, for a user-installed target that
belongs to no category. Each entry is {shapekey_name, value} with
value in 0.0..1.0, the range Blender clamps a shape key to. Use the
shapekey_name mpfb_list_targets reports, not the filename:
above 60 characters MPFB encodes the name, and a filename then
addresses nothing at all, silently.
Both lists are optional and either may be empty; a call naming neither does nothing and says so.
Nothing is applied unless everything resolves. Every entry is
checked inside Blender first - the section and category exist, the side
fits the category, the value is in that category's range, the target
file can be found - and if any entry fails, resolution_errors names
which and zero changes are made. Fix them and resend the whole
batch; known_sections and known_categories_in_section come back
with the error.
symmetry (default false, MPFB's own) also applies a sided change to
the other side, so one entry touches up to four shape keys. prune
(default true, MPFB's own) deletes a target's shape key once its value
reaches zero. refit (default false, MPFB's own) re-fits the mesh assets and
the rig afterwards; leave it false, read assets_possibly_stale, and
call mpfb_refit_human once when the modeling is done.
result carries changes - one entry per requested change, in request
order, each listing every target file touched with present_before,
previous_value, new_value, loaded_from (set when the target was
read off disk on this call) and pruned - plus shapekeys_added and
shapekeys_removed, refit_performed, assets_possibly_stale and
basemesh_name. An unresolvable subject answers found: false with
blocked_by: "subject_not_found", and a basemesh in edit mode or
without shape keys ready: false with blocked_by. performed is false whenever changes is empty, the
all-or-nothing resolution failure included.
Inputs: name, prune, refit, targets, +2 more. Returns: object
mpfb_symmetrize_targetsADestructiveIdempotent
Make a MakeHuman character's modeling targets left/right symmetric, by copying one side's modeling onto the other.
MPFB itself cannot do this. Its symmetry setting only mirrors
changes made while it is on and leaves previously set values alone, so
a character that has already drifted asymmetric has no repair path in
MPFB's UI. Call mpfb_get_target_stack first: its asymmetries field
lists which categories differ and by how much.
This is destructive and there is no undo across the socket. It
overwrites values the user may have set on purpose. direction is
required - "left_to_right" or "right_to_left" - because which half
of a face is the good one is not something a tool can guess. Run it
with dry_run: true first: the answer lists exactly the changes a
real run would make, and writes nothing.
section restricts the operation to one target.json section, so
"make the eyes symmetric" does not also flatten deliberate asymmetry in
the hands; omit it to cover every section. Only categories with
has_left_and_right: true are considered, paired through
target.json's opposites table rather than by matching l-/r-
name prefixes, which would be a guess.
prune (default true, MPFB's own) deletes a target's shape key once
its value reaches zero. refit (default false, MPFB's own) re-fits
the mesh assets and the rig afterwards; read assets_possibly_stale and call
mpfb_refit_human when the modeling is done.
result carries changes - per category, both sides' values before,
the value after, and every target file touched, with targets being
null rather than [] under dry_run: true, because which files a
write would touch is only knowable by doing the write - plus
already_symmetric, basemesh_name, and skipped for a category
whose target file could not be found, since one unreachable target is
reported rather than abandoning the rest of the body.
Under dry_run: true, performed is false even though changes has
entries in it: those are the writes that would happen. A subject that
cannot be resolved (found: false, subject_not_found) and a basemesh
in edit mode or without shape keys (ready: false) are answers, not
errors.
Inputs: direction (required), name, prune, refit, +2 more. Returns: object
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 34 tools
The set is exceptionally well-differentiated: read/write pairs are clearly split (get_face_units vs get_expression, set_targets vs symmetrize_targets), and the two-step rigging and material tools have explicit boundaries. The summary tool overlaps other readers but is explicitly positioned as a convenience first-call, so ambiguity is low.
All tools use the mpfb_ prefix and a snake_case verb_noun pattern (add_asset, get_object_info, set_skin), with only natural domain wording differences such as human/character. Naming is predictable and consistent throughout.
At 34 tools this is heavy for an MCP surface, exceeding the typical well-scoped range; many list/get/set pairs and niche diagnostics could be consolidated. The broad MakeHuman domain justifies some breadth, but context cost is high.
Core character lifecycle is covered: create/from preset, rig/add rigify, dress/undress assets, shape targets, face units/expressions, skins/materials, save/load presets, refit, and status/docs/list support. Missing a direct character/rig deletion or swap tool and some pose/ink-layer/makeup application paths, but those are minor workarounds.
Maintenance
Related MCP Connectors
Connect your AI assistant to Blender for 3D modeling, Geometry Nodes, materials, lighting, animation, rendering and export. Inspect real scenes and viewport images, refine the result and restore checkpoints. OAuth connects your chat to Blender Bridge Desktop on an online Windows 10/11 x64 computer running Blender 4.2+. The chat can run on another device. Requires an active Blender Bridge account; 7-day trial available. AI model access is separate.
Blender-as-a-service for agents: search 3D assets, run Blender Python, or brief the studio agent.
Control Unreal Engine to browse assets, import content, and manage levels and sequences. Automate…
3D avatar/asset foundry: text/image -> rigged, validated, engine-ready GLB via x402.
Related MCP Servers
- AlicenseCqualityBmaintenanceEnables secure, local automation of Blender through typed MCP tools for scene, modeling, material, animation, rendering, and file workflows via an authenticated loopback bridge.173MIT
- AlicenseNot gradedqualityCmaintenanceEnables MCP-compatible clients to control Blender for modeling, materials, animation, physics, rendering, scene inspection, documentation search, and asset/generation service integration. It exposes a stdio endpoint with many Blender operations for creating and editing 3D content.AGPL 3.0
- AlicenseNot gradedqualityBmaintenanceEnables MCP hosts and coding agents to model, inspect, measure, and deliver real Blender scenes through 15 tools and 217 catalog operations, returning actual rendered images after key edits. Works against a live Blender GUI via addon or a persistent headless worker, producing editable .blend files, GLB exports, previews, and acceptance records.1BSD 3-Clause
- AlicenseBqualityBmaintenanceEnables AI clients to control Blender through its official MCP add-on: running arbitrary bpy code or background CLI jobs, auditing scenes and blend files, searching Blender API and manual docs, capturing screenshots and renders, and searching or importing free Poly Haven models, HDRIs and textures at real-world scale. All 28 tools are served over one stdio connection to a single Blender instance.28GPL 3.0