Repository navigation
Security
Every version before 0.5.0 let any program that could reach the add-on's port drive Blender and run
Python as you, and a web page you opened could do it too (some browsers block or ask first). 0.5.0
requires a token on every connection and keeps execute_script off until you click Allow Python.
Upgrade, and remove the old blender_mcp_addon add-on. Details are in
SECURITY.md.
Added
- The add-on installs as a Blender extension. The release ZIP is now
meshwire-addon-<version>.zip,
with ablender_manifest.tomlat its root, and installs from Edit > Preferences > Get Extensions >
dropdown > Install from Disk... on Blender 4.2 and later. CI validates the built ZIP, installs it into a
fresh Blender and runs the handshake andpingagainst it, on 4.5 and 5.2. The manifest declares the
networkandfilespermissions, andbl_infois gone. An older Meshwire add-on still enabled
(installed from a pre-0.5.0 ZIP asblender_mcp_addon) makes the new one show a warning in its sidebar
tab and refuse to start its server, so two servers never run together. Remove the old copy in
Preferences > Add-ons and restart Blender. The Start and Stop operators and the panel were renamed
(meshwire.start_server,meshwire.stop_server,MESHWIRE_PT_server) so they cannot collide with the old
copy's, which would otherwise replace them while both are enabled. A keymap entry or script that calls
bpy.ops.mcp.start_serverorbpy.ops.mcp.stop_servermust call themeshwireoperator instead. - Several Blenders at once. Each running add-on now writes a small file,
instances/<port>.json, in the
Meshwire config folder next to the token, and removes it when its server stops or Blender quits normally. The file names the port,
process, Blender version, add-on version and.blendfile, and holds no token. With no--port, the
server reads these files, tries each port, deletes the files of Blenders it finds are gone (on Windows a file left by a
crash stays until a Blender binds that port again), and connects to
the most recently started live one. It looks again at every connection, and logs the port, Blender version
and file it chose. It moves on to an older Blender only past a program that is not a Meshwire add-on with
your token (connection refused, a reply that is not Meshwire's, or no valid proof). A newest Blender that
is busy, full, closes before answering, or needs updating gives an error naming its port, instance file
and process ID instead of a switch. Pass--portor setMESHWIRE_PORTto pick one. The order is now--port, then the newMESHWIRE_PORTvariable, then discovery, then
9876. Discovery runs only for a loopback--host. The--portdefault is no longer 9876, so a setup that
relied on that exact default still works whenever Blender is on 9876, and finds the right Blender when it is not. - Two Blenders no longer fight over a port. The add-on binds the first free port from 9876 to 9885 when
Preferences says 0, and exactly the port you set otherwise, failing with a message that says why. On
Windows the port is now bound exclusively, so another program cannot share it. CI also runs the token,
instance file and socket tests on Windows and macOS.
Fixed
-
Only a client with the token can use the add-on's socket. Until now any program on the machine could
connect to the port and drive Blender, andexecute_scriptran any Python it was sent. This affects
every version before this one (the releases were v0.2.0, v0.3.0, v0.4.0 and v0.5.0a1); seeSECURITY.md.
What testing confirmed: on the last commit before authentication, a rawobject_createsent with no hello
was served and the connection stayed open (unauthenticated_call_refusedfails there, on Blender 4.5.15).
On v0.4.0 in Blender 4.5.15, a rawobject_createand an HTTP POST (as a browserfetchwith
Content-Type: text/plainsends it, with one command line as the body) both created an object, so a web
page could make Blender run a command, and withexecute_script, any Python. v0.5.0a1 has the same socket
code. Some current browsers block or ask before a public page requests a local address, so this depends
on the browser. The host was also a Scene property saved in the.blend, so a shared file could carry a
non-loopback host; it is now an add-on Preference.
The add-on now makes a token in your Meshwire config folder (~/.config/meshwire/tokenon Linux, mode 0600). A connection
must open with ahelloand then ahello_proof, each step within 2 seconds, in lines of at most 4 KiB. The two
sides prove they hold the token with HMAC-SHA256 over fresh nonces, so the token itself never crosses the
socket. The add-on's proof also covers the address it received the connection at, and the server refuses a
connection that reached a different address, so a program relaying the traffic from another port or
address is caught (an SSH tunnel on purpose needsMESHWIRE_ADDON_ADDRESS). Anything else is closed at
once; a wrong proof, or a client that does not speakhello, gets one error that says what to update. Sockets
that have not finished the handshake have their own pool, so idle ones cannot lock out the real client, and
a flood evicts the oldest of them, and a client that is evicted gets a clear error instead of being sent to another Blender. A client that failed its
handshake can make the add-on read at most 64 KiB more from it.SECURITY.mdnow says how to rotate the
token: stop the server in every Blender that runs Meshwire (each keeps the token it started with), delete
the token file, start the servers again, and restart the MCP clients.
The server reads the token file on every connect, so it needs no setup. For another machine, set
MESHWIRE_TOKENthere (it overrides the file) and use Copy token in the Meshwire tab. After the
handshake the traffic is neither encrypted nor integrity-protected, so a non-loopback host sends commands
and results in plaintext; use an SSH tunnel for remote use. A new server
against an older add-on, and the reverse, now say which side to update instead of hanging. -
exit()in a script no longer ends the session. A script that callsexit(),sys.exit()or raises
SystemExitused to escape the add-on's timer, which could close Blender or leave the server deaf. It now
returns a normal error ("The script called exit() or sys.exit(); Blender keeps running.") with the output so
far, and any other handler that does the same gets an error reply. -
Large replies arrive whole, and bad requests get an answer. The add-on used to cut off any reply
bigger than the socket buffer; a 32 MiB reply now arrives complete. A malformed, non-object, non-UTF-8 or
oversized request, and a client past the connection limit, now get an error reply that says what was wrong,
and the add-on then closes that connection. The server reports that reason instead of "Disconnected". -
execute_scriptnow needs the panel switch. It refuses every call, before running anything, until you
click Allow Python in the Meshwire sidebar tab in Blender. The switch is off every time Blender starts
and stays on only until it closes. No tool, socket message or saved file can turn it on. Anything that
calledexecute_scriptmust be allowed once per Blender session. -
Settings moved from the scene to add-on Preferences. Host, port and the new Rodin key, Meshy key and
ComfyUI workflow path are stored per user in Preferences, not inside the.blendfile, so a shared file
no longer carries them. Port 0, the new default, picks the first free port from 9876 to 9885. Starting the
server now reports an error in Blender when it cannot bind, instead of claiming it started. -
ai_configure_backendtakes only safe keys. It acceptsenabled,api_key,host,timeout,deviceand
model(an Ollama model name), andhostmust be an http or https URL with no user name or password. Any other key, such as
workflow,python_path,model_pathorapi_base_url, is refused with a message that names it and
points to Preferences (Meshwire add-on). -
An MCP client can now see that a tool failed. A reply from Blender that carries an error, or reports
success: false, now comes back withisErrorset, so the client treats it as a failure. The JSON text
is unchanged. The server's argument log also no longer holds API keys or whole scripts: values under
keys such asapi_key,token,secretandpasswordare logged as<redacted>, and any string over
200 characters is logged as its length. -
The socket lane runs nightly on 4.2, 4.3, 4.4, 5.0 and 5.1. Before, the viewport and sculpt tools
that the background driver cannot reach were checked on 4.5 and 5.2 only. The nightly job now runs the
lane after the driver as a best-effort step, andsocket-lane.jsonholds a baseline for all seven
series. The README says which series run the lane, and lists each failing socket check with the series it
fails on. All of this is generated byscripts/tool_status.py. -
sculpt_mesh_filterwithERASE_DISPLACEMENTworks on Blender 4.2. 4.2 spells that filter type
ERASE_DISCPLACEMENTinsculpt.mesh_filter, so the call failed with an enum error there. The add-on
now reads the operator's enum items and uses whichever spelling the running Blender offers. -
The
annotation_addnote names the right series. The harness reason and the README table said
Blender 4.3 to 4.5 has no Python call for annotation strokes. The baselines show 4.3, 4.4, 4.5, 5.0 and
5.1 return that message, and only 4.2 and 5.2 draw the stroke, so the text now says 4.3 to 5.1. -
The truth harness no longer lets an allowed failure hide a new one. Each row in
SOFT_FAIL_ALLOWEDandKNOWN_UNREACHEDnow carries a regex for the message the tool really returns
("No AI backends are available", "needs an open 3D viewport", and so on). ASOFT_FAILwhose message
does not match its tool's pattern is classedBUG, so an allowed tool that starts failing for another
reason shows up in the next run. The README table reads the reason from the same row. -
The nightly harness fails on too many session crashes.
--retry-crashesstill forgives the known
Blender 4.2 to 4.4 segfault, which lands on a different case each run and passes alone. A run with
more than 3 such crashes now exits non-zero, so a crash of ours that happens to pass alone cannot hide
behind it. -
The truth harness no longer touches your Blender user files. The driver and the socket lane set
BLENDER_USER_RESOURCESto a directory under the run's temp dir, and dropBLENDER_USER_CONFIG,
BLENDER_USER_SCRIPTSand the other user path variables. Before, a local run ofai_queue_clearor
ai_clear_historycould delete your real AI job history, andai_get_historycould return it. -
Undo and replies that fail. A reply of
{"success": true, "error": null}, whichexecute_script
returns, now pushes its undo step; only a truthyerrororsuccess: falsecounts as a failure.
ai_model_statuspushes one undo step when it imports the finished model and none for a poll that
imports nothing, so undoing the import no longer takes an earlier tool call with it. -
mesh_knife_projectsays when it cut nothing. It compares the vertex, edge and face counts and
returnssuccess: false("the cutter does not overlap the target") when they did not change, instead
of claiming success. A newview_axisparameter (TOPby default, orBOTTOM,FRONT,BACK,
LEFT,RIGHT) sets the direction the cutter is projected along. For the call only, the first 3D view is turned
to that axis and framed on the target and cutter, then restored, so the cut no longer depends on
where the viewport happens to look. The reply reports the axis used. -
Long jobs no longer time out at 30 seconds through the server. Every
bake_*tool,
msfs_export_model,msfs_batch_export_lods,physics_simulate,physics_fluid_quick,
render_imageandmaterial_preview_rendernow wait 600 seconds for Blender by default and declare
an optionaltimeout(seconds the server waits) in their schemas. Onlyai_generate_texture_sync,
whose handler readstimeoutas its polling limit, still receives it, and the server waits 30 seconds
longer than that limit so the handler's own timeout reply arrives. For other tools the server keeps
timeoutto itself. This replaces the earlier rule that forwardedtimeoutto every tool declaring it. -
ai_redo_generationreplays the right kind of job. Jobs now record whether they are a 3D model or
a texture. A texture job is redone as a texture instead of being submitted as a paid 3D model, with
the backend inputs it was first sent (an inpaint job's image and mask, size, seed), and a job kind
that cannot be replayed gives a clear error.ai_generate_variationsaccepts at most 8
variations, in the schema and in the handler. -
object_separatereturns to Object mode when the operator raises, for exampleMATERIALon a
mesh with one material slot, instead of leaving the scene in Edit mode. -
The pipeline's MSFS stage exports.
ai_pipeline_generatecalledmsfs_export_modelwith
output_dir, which the handler does not take, so the export always failed unnoticed. It now passes a
filepathbuilt fromoutput_dirand the object name, and an export error fails the stage. -
tools/listand the addon handlers now agree. Seven handlers had no tool and are now listed:
ai_get_backend_info,ai_generate_variations,ai_cancel_generation,ai_redo_generation,
ai_queue_list,ai_queue_clearandai_get_history.pingstays a protocol call.export_fbx
andexport_objlist the options they already read (scale, axes,bake_anim,apply_unit_scale,
export_materials) with the enum values both Blender 4.5 and 5.2 accept.ai_generate_textureand
ai_generate_texture_syncno longer readtexture_types, which no workflow used.
ai_pipeline_statusdropsresume, which nothing implemented. A tool that declarestimeout
now receives it: the server used to strip it before forwarding, soai_generate_texture_syncalways
polled for its default 300 seconds.execute_scriptsaystimeoutis how long the server waits, not a
script limit.material_set_colorrequirescoloras its schema says, andmeasuredocuments which
mode needs which argument.ai_generate_variationsreportssuccess: Falsewhen no variation was
generated. New static gaterequired_matchescompares each schema'srequiredwith the handler. -
Defects that hid behind SOFT_FAIL and PASS.
ai_auto_uvLIGHTMAP no longer passes the removed
PREF_APPLY_IMAGEandPREF_IMG_PX_SIZEkeywords.ai_mesh_decimatemapsUN_SUBDIVIDEto
UNSUBDIVandPLANARtoDISSOLVE.constraint_addsetstargetonly on constraints that have
one, soLIMIT_LOCATIONandLIMIT_ROTATIONwork.physics_fluid_quickmapsGASflows to the
SMOKEflow type.physics_simulatereadsRigidBodyWorld.collectionin place of the removed
group.export_gltfdropsGLTF_EMBEDDEDfrom its schema, since the exporter never accepted it.
ai_pipeline_generatereturnssuccess: Falseand anerrorwhen a stage fails, and a failed
generation, import or texture reply now marks its stage failed.analyze_viewportandai_refine
returnsuccess: Falsewhen the vision analysis fails, in place of a successful reply that
carries a failed analysis;refine_iterationfollows. -
ai_texture_from_renderandgrease_pencil_markupdo the work they report. The depth and
normal control images are now the real passes: the object renders in a throwaway scene through the
compositor (depth ramped so near is light with a clear background, normals mapped to 0-1 RGB), so
the caller's scene, view layer and compositor are never touched. A failed render or a missing object
returns a clear error, and the temp file comes fromtempfile.mkstemp.grease_pencil_markupnow
draws arrows, circles and rectangles into the image pixels with numpy when Pillow is missing, which
is always the case in Blender's Python, in place of a compositor fallback that drew nothing yet
reported success. Colour and thickness are honoured,output_pathis validated,annotations_drawn
is the real count, text items are listed underskipped(Blender'sblfdraws nothing into an
image buffer), andsuccessis false when nothing was drawn. The socket lane checks both from the
output pixels. -
Blender 5.x differences go through
compat.py, by feature detection. No handler or compat
function compares a version number.render_set_engineacceptsEEVEE,BLENDER_EEVEEand
BLENDER_EEVEE_NEXTand sets the one this Blender registers;ai_texture_from_renderno longer
hard-codesBLENDER_EEVEE_NEXT, so its depth and normal renders work on 5.x and the tool reaches
the AI backend.boolean_opmaps theFASTsolver toFLOATwhere that is the name.
geonode_applyandgeonode_inspectread and write modifier inputs through
modifier.properties.inputswhere Blender offers it.keyframe_listreads curves from the
action's channelbags (only the object's own slot) in place of the removedslot.layers.
mesh_select_edge_loopscallsselect_edge_loop_multiorselect_edge_ring_multiwhere
loop_multi_selectis gone.grease_pencil_markup's compositor fallback finds the compositor
tree inScene.compositing_node_groupand uses a group output where the Composite node is gone. -
Annotation and grease pencil tools work on 4.5 and 5.x.
grease_pencil_createdraws through
the v3 drawing API (bpy.data.grease_pencils_v3on 4.3 to 4.5).annotation_addand
annotation_clearuseScene.annotationwhere annotations are their own datablock. Blender 4.3
to 4.5 has no Python call that creates an annotation stroke, so thereannotation_addreturns an
error and leaves nothing behind; a new socket test covers both outcomes. -
Behaviour changes in the grease pencil tools.
grease_pencil_createreturns an error when no
stroke has two or more points, where it used to create an empty object. On the v3 data API the
point radius is the stroke thickness divided by 2000 (the legacy API used a pixelline_width).
boolean_opstill takesFASTorEXACTas the solver;FASTis the cross-version name and
becomesFLOATwhere Blender calls it that. -
get_version_inforeports detected features. It no longer returnsis_5_0andis_4_2;
featuressays which API shapes this build has. -
Sculpt tools use Blender's real identifiers.
sculpt_face_set_createcalls
sculpt.face_sets_init, whose modes the criteria map to (LINKEDisLOOSE_PARTS);
face_sets_createnever took them.sculpt_mask_by_topologyusessculpt.mask_from_cavityand
sculpt.mask_initin place of the removeddirty_maskandvertex_paint_masks, and blurs with
onemask_filtercall.sculpt_extract_maskrunssculpt.paint_mask_extractand reads the
.sculpt_maskattribute, so a mesh with no mask gets a clear error.sculpt_multires_reshape
no longer listsDELETE_LOWER, which Blender never had.sculpt_to_retopobakes a tangent-space
normal map, sincebakehas noDISPLACEMENTtype. The face set, mask and blur operators crash
Blender in background mode, so those tools answer "needs an open 3D viewport" there. -
A failing sculpt tool leaves Object mode. The sculpt tools used to return an error after
entering Sculpt mode and stay there.restores_object_mode(error_replies=True)now also covers
error replies, and a successful call still keeps Sculpt mode. -
mesh_selectcombines criteria with AND (#38). Several criteria used to be unioned, so a
second criterion could only add elements. An element now has to match every criterion given; a
criterion that does not apply to the mode is ignored. The tool description says so. -
Mesh tools use Blender's real identifiers.
mesh_subdividemapsINNERVERTto the
INNER_VERTthatbmesh.ops.subdivide_edgestakes.mesh_edge_slidepassesuse_even, not
even, and returns "needs an open 3D viewport" in background mode, where the slide operator
crashes Blender 4.5.mesh_creasewrites thecrease_edgeattribute, since
BMLayerAccessEdge.creaseis gone.curve_to_meshno longer listsfill_typeNONE, which
Blender rejects for 3D curves; a 2D curve still accepts it. -
Each successful tool call is one undo step in the GUI. Operators called from the socket
timer push no undo step, soundoreverted nothing or too much.CommandHandlers.handlenow
callsbpy.ops.ed.undo_push(message=<tool>)after a tool that does not report an error or
success: false, after any rename the tool made. Read-only tools (NON_MUTATING),undo,
redoandpingnever push, so redo keeps working.execute_scriptno longer pushes a step
of its own before running, which left an extra no-op step. Background mode has undo disabled
and is unchanged. -
Viewport-only tools no longer crash Blender, and work in a GUI session (closes #37).
mesh_loop_cut,mesh_knife_project,sculpt_mesh_filter,sculpt_mask_by_topology
(ALL,NONEandinvert) andrender_screenshotcall operators that need a 3D viewport.
In background mode they segfaulted or raised. They now find a viewport by walking the window
manager, because the socket server runs handlers from a timer wherebpy.context.areais
None, and run the operator undertemp_override. With no viewport they return
{"success": false, "error": "<tool> needs an open 3D viewport"}.sculpt_mesh_filtermaps
ENHANCE_DETAILto Blender'sENHANCE_DETAILSandSURFACE_NOISEtoRANDOM.
mesh_knife_projectlost its boolean INTERSECT fallback, which deleted everything outside
the cutter, and now selects the cutter after entering Edit mode so the operator sees it.
Mesh tools that enter Edit mode (mesh_loop_cut,mesh_bridge,mesh_fill,
mesh_edge_slide,mesh_knife_project,mesh_separate_selected,
mesh_select_shortest_path,mesh_select_edge_loops) return to Object mode when they fail. -
Missing arguments are rejected with a validation error, and
~paths work. Sixteen
tools (object_create,object_delete,object_get,object_transform,
object_duplicate,object_join,object_separate,object_parent,
material_set_principled,material_add_texture,render_animation,
render_screenshot,render_set_engine,render_set_resolution,polyhaven_download,
ai_model_status) andai_pipeline_statusraised a bareKeyErroror accepted{}.
They now report the missing parameter throughrequire_param.validate_filepathreturns
the absolute path with~expanded and checks existence after expansion.ai_inpaint_texture
andreference_image_setupcalled it without anameor discarded the result; a static gate
now catches an unused result. -
Every path parameter resolves
~and//.save_as, the bake tools,render_multi_angle,
material_preview_render,sculpt_to_retopo, the MSFS export and livery tools, the AI
tools that take an image or output directory, and the five tools that takereference_image
passed the raw string to Python file I/O, so~/bakesbecame a folder named~in Blender's
working directory. They now resolve the path first and report the absolute path they used. A
//path resolves against the saved .blend file, and is refused with a clear error when the file
has never been saved. A static gate fails the build when a path parameter skips the resolver. -
ai_texture_from_renderbuilds its depth and normal control images on Blender 4.2 to 4.4.
Those compositors refuse shader math nodes, so the tool failed before it reached the AI backend.
It now uses the compositor's own nodes where the shader nodes are refused. -
bake_curvaturefrees its image and mesh data when it fails, and saves through the same
checked writer as the other bake tools, so a failed write is an error, not a silent success. -
Five of the six baking tools never worked.
bake_pbr_batch,bake_highpoly_to_lowpoly,
bake_from_multires,bake_to_vertex_colorsandbake_id_mapcalled eight_bake_*
helpers that were never written, so each raisedAttributeErroronce past argument
checks. The helpers now exist. The target image node and the emission wiring that
METALLICandDISPLACEMENTbake through are tracked as they are added and removed
in afinally, including when the bake raises. A material is left with the same
nodes, links, socket values, selection, active node and active Material Output
(including a Cycles-only output) it had; this is checked on a linked and an unlinked
Metallic socket, a displacement chain, a shared material and a multi-slot object, on
Blender 4.2, 4.5 and 5.2. The render engine, the bake settings and the object
selection are also put back after each bake, which they were not. A setting that cannot be
put back, such as an add-on render engine that is no longer installed, is named in
warnings.bake_id_mapnow
restores material slots and face material indices in every colour mode. An object
with no node material gets a clear error frombake_pbr_batch; the other tools add a
temporary material and remove it again. A bake that writes no file, including
channels: [], returns an error rather thansuccess, and empty material slots are
named in awarningsentry.bake_from_multirescalled an operator that rejects its
map types; it now uses the multires baker, and bakes to level 0 when the modifier is
at its top level, since a level baked to itself carries no displacement.
bake_highpoly_to_lowpolynow lists thenormal_spaceparameter it already read.
bake_curvaturenever called the helpers and is unchanged. -
All 38
msfs_*tools failed on every call.handlers/msfs.pyimported
from .msfs, which resolves to the handler module itself, so each call raised an
ImportError or "not a package". It now imports themsfspackage. These tools
now run; their output is not yet verified. Five more defects behind the import:
msfs_create_glass_materialsetMaterial.shadow_method, absent from Blender
4.5 and later;msfs_export_modelpassed the removedexport_colorsoption and
the formatGLTF, which the exporter spellsGLTF_SEPARATE;
msfs_livery_extract_colors,msfs_livery_transferand
msfs_livery_map_elementsdid not accept the parameters their schemas offer;
andmsfs_livery_export_uv_layoutnow says it needs a GPU context in background
mode instead of raising, and no longer leaves the object in Edit mode. -
ai_auto_uvread freed memory. It held a UV layer reference across a mode change, then
read its name. The outcome depended on what was left in that memory: it crashed Blender 5.2
every time and failed unpredictably on 4.5. -
validate_enum()called with swapped arguments in 20 handlers. Every
affected handler rejected all of its documented enum values, because the
allowedlist landed in thenameslot and the parameter-name string landed
inallowed, so iterating astrmade the check compare against its individual
characters.mesh_fill,curve_create,curve_to_mesh,mesh_extrude,
mesh_select,mesh_select_shortest_pathand others were unusable as a
result, and the error messages they raised named the wrong parameter. -
import_filecould not import.stl. It calledbpy.ops.import_mesh.stl,
which Blender 4.x removed; now usesbpy.ops.wm.stl_import, matching the
wm.stl_exportalready used on the export side. -
render_set_enginefailed on Blender 5.x.compat.get_eevee_engine_name()
hard-codedBLENDER_EEVEE_NEXTfor 4.2+, but 5.0 renamed the engine back to
BLENDER_EEVEE. It now queries theengineenum instead of mapping from the
version number.
Thanks to Muhammet Ali (muhammetali) for this fix.
Added
- Every Blender series from 4.2 through 5.2 is now covered. Blender 4.3.2, 4.4.3, 5.0.1 and 5.1.2
join 4.2.23 as nightly series, each with its own harness baseline. 4.5 and 5.2 stay gated on every
pull request. The nightly job is now a matrix over the five best-effort series. The baseline sync
test finds baselines by glob, so a new series needs no test edit. - The code is formatted with
ruff format, and CI checks it. The lint job fails on an
unformatted Python file..git-blame-ignore-revsletsgit blameskip the format commit. - The harness driver takes
--retry-crashes. It reruns each crashed case alone. A case that
passes alone is reported as a session crash instead of a regression. Only the nightly job uses it,
because Blender 4.2 and 4.3 crash inside Blender late in a full run, on a different case each time.
The 4.2 baseline is re-recorded with every repair so far. tests/test_handler_signatures.py: Blender-free static checks that guard
againstvalidate_enumargument-order regressions and against calling
Blender operators removed in 4.x.- Integration tests for the STL export/import round-trip and for
mesh_fill
enum handling.
What's Changed
- fix: re-land #41 (validate_enum, STL import, EEVEE on 5.x) by @RFingAdam in #51
- chore(deps): bump the python-minor-patch group across 1 directory with 4 updates by @dependabot[bot] in #48
- fix: stop ai_auto_uv reading freed memory by @RFingAdam in #52
- fix: make the MSFS tools reach their modules by @RFingAdam in #53
- fix: write the missing bake helpers so the baking tools run by @RFingAdam in #54
- docs: generate the README tool status from the harness baselines by @RFingAdam in #55
- fix: reject missing required arguments and expand ~ in file paths by @RFingAdam in #56
- fix: run viewport-only tools under a 3D view override by @RFingAdam in #57
- fix: make each successful tool call one undo step by @RFingAdam in #58
- fix: use Blender's real identifiers in the mesh tools, AND mesh_select criteria by @RFingAdam in #59
- fix: use Blender's real identifiers in the sculpt tools by @RFingAdam in #60
- fix: route Blender 4.x and 5.x API differences through compat.py by @RFingAdam in #61
- Fix defects hidden behind SOFT_FAIL and false passes; count only tools that ran by @RFingAdam in #62
- Render real depth and normal passes and draw real markup; empty the defect tables by @RFingAdam in #63
- Make tools/list and the addon handlers agree by @RFingAdam in #64
- ci: cover Blender 4.3, 4.4, 5.0 and 5.1 nightly by @RFingAdam in #65
- Format with ruff, gate it, and retry session crashes on nightly series by @RFingAdam in #66
- Resolve ~ and // for every path parameter, and fix control images on 4.2 to 4.4 by @RFingAdam in #67
- Fix undo steps, long tool timeouts and mesh_knife_project's projection by @RFingAdam in #68
- Make allowed harness failures name their message, and run the socket lane nightly by @RFingAdam in #69
- Replay a texture job's backend inputs on redo, and outwait handler timeouts by @RFingAdam in #70
- Report tool failures as isError and redact secrets from the argument log by @RFingAdam in #71
- Turn Python execution off by default, move settings to Preferences, and limit ai_configure_backend by @RFingAdam in #72
- Bound each socket client's buffers and replies by @RFingAdam in #73
- Require a token handshake before the add-on serves a client by @RFingAdam in #74
- Find the right Blender when several are open by @RFingAdam in #75
- Ship the add-on as a Blender extension zip by @RFingAdam in #76
- M4 Task 7: SECURITY.md and what older versions exposed by @RFingAdam in #77
- Don't drop a client that answered while Blender was busy by @RFingAdam in #78
- M4 final review fixes: deterministic discovery, bounded pre-auth input, exit() safety, meshwire idnames by @RFingAdam in #79
- Release prep: 0.5.0 by @RFingAdam in #80
New Contributors
- @dependabot[bot] made their first contribution in #48
Full Changelog: v0.5.0a1...v0.5.0