Skip to main content
Glama
fusion-mcp

fusion-mcp

fusion-mcp

MCP server that lets LLM agents (Claude Desktop, Claude Code, any MCP client) build models in Autodesk Fusion 360.

It has two parts:

  • FusionMCP add-in (fusion_addin/) runs inside Fusion. It listens on 127.0.0.1 only, requires a random token and runs every request on Fusion's main thread.

  • MCP server (fusion-mcp, src/fusion_mcp/) is started by the MCP client over stdio and forwards tool calls to the add-in.

The add-in publishes its port and token in ~/.fusion-mcp/bridge.json while it runs.

Requirements

  • Autodesk Fusion 360 on Windows or macOS.

  • uv and Python ≥ 3.11 for the MCP server. The add-in uses Fusion's bundled Python and needs no extra packages.

Related MCP server: Fusion360 MCP Server

Install the add-in

Step-by-step guide for any machine, including manual install and troubleshooting: INSTALL.md.

From this directory (mcp-plugin/):

uv run fusion-mcp install-addin

This links fusion_addin/ into Fusion's AddIns folder as FusionMCP:

  • Windows: %APPDATA%\Autodesk\Autodesk Fusion 360\API\AddIns\FusionMCP (a junction)

  • macOS: ~/Library/Application Support/Autodesk/Autodesk Fusion 360/API/AddIns/FusionMCP (a symlink)

If links cannot be created on your machine, use uv run fusion-mcp install-addin --copy. It copies the add-in and bundles the protocol package into FusionMCP/_vendor/. Re-run it after every update.

The installer never touches a FusionMCP folder it did not create. To remove the add-in, run uv run fusion-mcp uninstall-addin.

Restart Fusion. The add-in starts automatically. Its button is in the Utilities → Add-ins panel and shows the state: FusionMCP: Running :7432 or FusionMCP: Stopped. Click it to stop or start the bridge. The default port is 7432; if it is busy, the add-in picks a free port and writes it to the discovery file.

Connect an MCP client

Print a ready config:

uv run fusion-mcp print-config                       # Claude Desktop
uv run fusion-mcp print-config --client claude-code  # Claude Code (.mcp.json)

The Claude Desktop output looks like this; merge it into claude_desktop_config.json:

{
  "mcpServers": {
    "fusion360": {
      "command": "uv",
      "args": ["run", "--directory", "/abs/path/to/mcp-plugin", "fusion-mcp"]
    }
  }
}

For Claude Code, put the --client claude-code output into .mcp.json of your project, or run claude mcp add fusion360 -- uv run --directory /abs/path/to/mcp-plugin fusion-mcp.

Check the connection

Ask the agent to call fusion_status. With Fusion and the add-in running it returns the Fusion version, the add-in version, Fusion's Python version, the active document, the design type and the document units. Otherwise the error starts with NOT_CONNECTED and says what to start. The MCP server re-reads the discovery file on every reconnect, so restarting Fusion or the add-in does not require restarting the client.

Tools

Tool

What it does

fusion_status

Connection check, versions, active document, design type, units

execute_python

Runs Python inside Fusion (adsk, app, ui, design, root, params in scope) and returns result, stdout, stderr

Units: tool inputs are millimetres and degrees, and strings are Fusion expressions ("10 mm", "width / 2"). The Fusion API inside execute_python works in centimetres and radians.

Errors come back as tool results with isError = true and the text "<CODE>: <message>" plus JSON details (for example a Fusion traceback). This lets the agent see what went wrong and fix it.

Sketches

The sketch_* tools (sketch_create, sketch_list, sketch_get, sketch_profiles, sketch_draw, sketch_constrain, sketch_dimension, sketch_dimension_set, sketch_set_construction, sketch_delete, sketch_transform, sketch_offset, sketch_trim, sketch_extend, sketch_fillet, sketch_mirror, sketch_pattern, sketch_project) build fully constrained, parametric 2D sketches. A typical sketch takes sketch_create plus one sketch_draw with geometry, constraints and dimensions together.

  • Coordinates are sketch space, mm. Points are [x, y] on the sketch plane (numbers only; the units parameter of sketch_draw can switch to cm/m/in/ft). Fusion picks the sketch axes: sketch_create and sketch_get return transform = {origin, x_axis, y_axis, normal} (model mm, unit vectors), and model = origin + x·x_axis + y·y_axis. On origin:XY sketch x/y are model x/y, but on origin:XZ the sketch Y axis is model −Z: a point drawn at y = 10 ends up at z = −10. Read transform, or give points in model space as {"model": [x, y, z]} (projected onto the sketch plane; an off-plane point adds a warning).

  • Geometry is approximate, dimensions are exact. Expressions are refused in coordinates (["w/2", 0] fails with INVALID_PARAMS). Exact and parametric sizes come from dimensions: a number is mm (degrees for angles), a string is a Fusion expression ("plate_w * 0.6"). parameter_name names a dimension's parameter, so later dimensions and parameter_update can use it.

  • Local ids live for one call. Inside a sketch_draw call an item's id, and sub-paths such as r.bottom, r.center, l1.end or slot.c0, can be used by later items, constraints and dimensions. origin is the sketch origin point. The result refs maps every local path to a real entity ref. Use those refs in later calls, because the local ids are gone after the call.

  • Profile refs. Fusion profiles have no persistent id, and their order changes whenever the sketch changes. A profile is therefore addressed by its sketch and a point inside the region: profile:<sketch token>@<x>,<y> (sketch mm). Mutating sketch tools and sketch_profiles return each profile with ref, interior point, area_mm2, centroid, bbox and its outer and inner loops. Pass the ref string to features as the profile. It stays valid through moderate dimension changes. If the region has moved away from the point, the feature fails with ENTITY_NOT_FOUND and the current profiles; call sketch_profiles(contains=[x, y]) to get a fresh ref.

  • Atomicity. Every mutating sketch tool is all or nothing. On failure, everything it created in the sketch is deleted and the changed properties (expressions, construction, fixed, positions) are restored. The error names details.phase, index and id of the failing item. Fusion cannot undo trim, extend and sketch fillet inside a batch, so sketch_trim, sketch_extend and sketch_fillet take one curve or corner per call. They replace curves, so use the refs they return for the next step. The one exception is sketch_delete: it validates all refs before deleting anything, but if Fusion itself fails in the middle of the batch, the entities already deleted stay deleted (FUSION_API_ERROR with details.deleted).

  • Changing a sketch that features already use can break later timeline features. Check feature health afterwards (inspect_tree).

Solid features

The feature_* tools turn sketches into solids and modify bodies, one parametric timeline feature per call:

Tool

What it does

feature_extrude

Extrude profiles, planar faces or sketch texts: one side, two sides or symmetric; distance, to an entity or through all; taper, start offset, thin wall

feature_revolve

Revolve profiles around a sketch line, construction axis or straight edge: full, angle, two angles or to an entity

feature_sweep

Sweep profiles along sketch curves or edges, with twist, taper, a guide rail and path share

feature_loft

Loft through profiles, planar faces and end points, with end conditions, rails or a centerline

feature_rib, feature_web

Thin stiffening walls from open sketch curves, joined to the body

feature_hole

Simple, counterbore or countersink holes at a point, sketch points, offsets from edges or a circular edge's centre; optional thread makes a tapped hole in the same call

feature_thread

Cosmetic or modeled thread on cylindrical faces (hole or shaft is detected)

feature_thread_options

Read-only lookup of thread types, sizes, designations, classes and a recommendation for a diameter

feature_fillet

Constant, variable or chord-length fillets on edges

feature_rule_fillet

Fillet all edges of faces/features, or the edges between two sets

feature_chamfer

Equal, two-distance or distance-angle chamfers

feature_shell

Hollow a body, removing faces (open shell) or closed, inside and/or outside

feature_draft

Tilt faces by a draft angle about a neutral plane

feature_offset_faces

Press-pull faces by a signed distance

  • Units. A plain number is a length in the tool's units (default mm; cm, m, in, ft also work) or an angle in degrees. Shares of a path, weights and counts are plain numbers. A string is a Fusion expression ("wall * 2", "5 deg") and keeps the feature driven by user parameters.

  • Where refs come from. Profiles come from sketch_draw / sketch_profiles (profile:<sketch>@x,y) or a spec such as {"sketch": <ref>, "all": true}. Sketch curves and sketch points (paths, rails, rib curves, hole points) come from the refs of sketch_draw. Faces, edges, vertices and bodies come from inspect_query / inspect_describe. Planes, axes and points come from construction_plane, construction_axis, construction_point or origin:XY|XZ|YZ|X|Y|Z|O. Face, edge and body refs go stale after later features, so query them again from the latest model instead of reusing old ones.

  • Operations. Extrude, revolve, sweep and loft take operation = new_body (default), join, cut, intersect or new_component. participant_bodies limits which bodies join/cut/intersect act on. Holes always cut, and ribs and webs always join: to target_body, by default the one solid body their curves touch (none or several -> INVALID_PARAMS with details.candidates). A rib grows on one side of its curve; if Fusion reports a warning, try flip=true. thickness_location="side2" is not available in the current Fusion API.

  • Result. Every feature tool returns {"feature": {ref, type, name}, "health": {"state": ok|warning|error|unknown, "message"}, "created_bodies", "modified_bodies", "removed_bodies"} (body items are {ref, type, name, is_solid}), plus component for new_component, holes (the count) and thread for feature_hole, and thread for feature_thread. Body geometry is not repeated, so measure it with the inspect_* tools.

  • Health and rollback. Bad input (a missing field for the chosen mode, a wrong entity kind, an unknown thread designation with details.available) fails with INVALID_PARAMS before anything changes. A stale profile point fails with ENTITY_NOT_FOUND and the current profiles. If Fusion computes the feature in the error state, the tool fails with FUSION_API_ERROR (details.health, details.feature_type) and the timeline is rolled back. A tapped hole whose thread fails leaves neither the hole nor the thread. A warning keeps the feature and is reported in health. A feature the running Fusion API lacks (rib, web, rule or chord fillet on an old version) fails with FUSION_API_ERROR "... not available" and changes nothing, so use execute_python.

Example: an open housing with four counterbored holes and one M5 tapped hole:

sketch_create(plane="origin:XY") -> sketch_draw(rectangle 80 x 50) -> profiles[0].ref
feature_extrude(profiles=[<profile>], side1={"type": "distance", "distance": 20})
feature_fillet(edges=<inspect_query edge, line, direction [0,0,1]>, radius=5)
feature_shell(faces=[<inspect_query face, normal [0,0,-1]>], inside_thickness=3)
sketch_create(plane=<top face>) -> sketch_draw(4 points) -> refs
feature_hole(placement={"type": "sketch_points", "points": [...]}, kind="counterbore",
             diameter=5.5, cb_diameter=9, cb_depth=1.5, extent={"type": "through_all"})
feature_hole(placement={"type": "point", "face": <top face>, "point": [0, 0, 20]},
             diameter=4.2, extent={"type": "through_all"}, thread={"designation": "M5x0.8"})

Body operations & patterns

The pattern_* and body_* tools copy, combine and reshape bodies. Most of them add one parametric timeline feature per call:

Tool

What it does

pattern_rectangular

Copy features, bodies, faces or occurrences along one or two directions (quantity, spacing or extent, symmetric)

pattern_circular

Copy them around an axis, including the axis of a cylindrical or conical face (quantity, total angle, symmetric)

pattern_path

Copy them along a path of sketch curves or edges (start share, flip, orientation along the path)

pattern_mirror

Mirror across a planar face, construction plane or origin plane. combine joins mirrored bodies with their originals

body_combine

Join, cut or intersect tool bodies with a target body (keep tools, new component)

body_split / body_split_face

Split bodies, or faces of a body, with a plane, face, body (or sketch curve for faces)

body_move

Move bodies, or copies of them (keep_original): translate, along an entity, rotate, rotate about a free axis, point to point, rigid 4x4 matrix

body_scale

Scale about a point (default origin:O), uniformly or per axis

body_thicken

Thicken faces of a surface into a solid

body_boundary_fill

Make solids from the closed cells that bodies, faces and planes enclose

body_delete_faces / body_replace_face

Delete faces and let Fusion heal the body, or replace faces with a face, plane or surface body

body_rename / body_set_visibility / body_remove

Rename, show or hide and set opacity, remove (a Remove feature) or delete bodies

  • Units. Lengths and the translate / rotate_about point and the matrix translation are in the tool's units (default mm). Angles are in degrees. Quantities, the path start share (0..1) and scale factors are unitless numbers. Strings are Fusion expressions, except in rotate_about and matrix, which take plain numbers.

  • Input refs. entities of a pattern must all be one kind: feature refs from earlier feature_* results, body or face refs (c03 inspect_query), or occurrence refs. Fusion patterns one kind at a time, and a mix fails with details.kinds. Directions, axes, planes and points come from origin:X|Y|Z|XY|XZ|YZ|O, from the c06 construction_* tools, or from edges, faces and vertices of inspect_query. The compute option (adjust, optimized, identical) only applies to feature input. Boundary fill cells are never picked by index. You pick them with cell_points; a point in no cell fails, and details.cells lists every cell's centre and volume.

  • Result. Feature tools return the same result as the feature_* tools: feature, health, created_bodies, modified_bodies and removed_bodies (tokens of consumed bodies). On top of that:

    • occurrence patterns add created_occurrences;

    • body_split_face adds the new faces;

    • body_move with keep_original adds copy.

    Body tokens change after patterns and combines, so take the refs from the latest result. body_rename, body_set_visibility and body_remove return the body refs, the visibility state, and the removed refs with mode_used.

  • Atomicity. Bad input fails with INVALID_PARAMS before anything changes. A feature computed in the error state is rolled back. A copy made for a failed body_move is removed too. body_set_visibility restores every body's previous values if Fusion refuses one. body_remove in a direct design always deletes the bodies, and Fusion cannot undo those deletions.

Example: a symmetric part from overlapping blocks:

feature_extrude(<20 x 20 mm square>, 10 mm) -> created_bodies[0] = cube
pattern_rectangular(entities=[cube], direction1="origin:X", quantity1=3, distance1=15,
                    direction2="origin:Y", quantity2=2, distance2=15)
pattern_mirror(entities=<all bodies>, plane="origin:YZ")
body_combine(target=cube, tools=<the other bodies>)

Surfaces

The surface_* tools model with surface bodies (sheets without volume). Each call adds one parametric timeline feature, except surface_trim_cells, which only previews:

Tool

What it does

surface_patch

Fill a closed boundary (sketch profile, sketch curves or edges) with a surface; continuity connected / tangent / curvature to the edge faces

surface_extend

Extend free edges of a surface body by a distance (natural, tangent, perpendicular)

surface_trim_cells

List the cells a trim tool cuts the surfaces into (centre, bbox, area in mm); changes nothing

surface_trim

Trim with a body, face, plane or sketch curve and remove the cells nearest to given points

surface_untrim

Remove all, external or internal (hole) loops of faces of surface bodies

surface_stitch

Stitch surfaces along shared edges within a tolerance (default 0.1 mm); reports is_solid

surface_unstitch

Split faces or bodies (solid or surface) into separate surface bodies

surface_ruled

Ruled surface from edges or sketch curves: normal, tangent or along a direction, with angle and corner type

surface_offset

New surface bodies at a signed distance from faces (the faces stay; moving faces of a solid is feature_offset_faces)

  • Surface features from sketches. feature_extrude, feature_revolve, feature_sweep and feature_loft take is_solid (default true). With is_solid=false they create a surface body: only new_body / new_component, no thin for extrude. Extrude and sweep then also accept open sketch curves or edges as the profile (one kind, connected curves are chained), e.g. an open line extruded into a wall sheet.

  • Trim cells by points. Cells of a trim are temporary and have no refs. Call surface_trim_cells first, then pass surface_trim a point (in units, default mm) on or near each cell to remove, such as a cell centre. A point farther than max_distance from every cell fails with INVALID_PARAMS, and details.cells lists the cells. The preview always cancels its trim input, so nothing stays half-built.

  • Solid or not. Every body in a surface result has is_solid. surface_stitch also returns the is_solid of the stitched body: false means gaps remain, so raise tolerance or patch the openings. To give a surface a thickness, use body_thicken (c08); to fill a closed set of surfaces with a solid, use body_boundary_fill.

  • Refs. Edges and faces come from inspect_query, curves and profiles from sketch_*. Surface bodies get new tokens after trim, extend and stitch, so take refs from the latest result. Bad input fails with INVALID_PARAMS before anything changes, and a feature in the error state is rolled back.

Example: a closed box from surfaces:

feature_extrude(profiles=[<20 x 20 mm square>], side1={"type": "distance", "distance": 20},
                is_solid=false)                        -> walls
surface_patch(boundary=[<the square profile>])         -> bottom
surface_patch(boundary=[<the 4 top edges of walls>])   -> top
surface_stitch(surfaces=[walls, bottom, top])          -> is_solid = true

Assemblies

The assembly_* tools build multi-part designs: components, occurrences, joints and interference checks.

Tool

What it does

assembly_list

Components and occurrences (transform, grounded, light bulb, visibility, joint count)

assembly_new_component / assembly_component_from_bodies

Empty component with a new occurrence (under root or a parent occurrence), or a component made from bodies of one component

assembly_activate / assembly_rename_component

Activate an occurrence (or root); rename a component (returns the new occurrence paths)

assembly_add_occurrence

Insert another occurrence of a component, referenced or as an independent copy

assembly_transform_occurrence

Move or rotate an occurrence, or place it by origin and axes; the position is captured with a snapshot

assembly_set_occurrence_state / assembly_delete

Ground, show or hide an occurrence; delete occurrences, joints, joint origins, rigid groups

assembly_create_joint_origin

Joint origin on a point, face, curve or profile, in the component that owns the geometry

assembly_create_joint / assembly_create_as_built_joint

Rigid, revolute, slider, cylindrical, pin-slot, planar or ball joint (in root)

assembly_set_joint_limits / assembly_drive_joint

Joint limits per degree of freedom; move a joint to values (clamped values are reported)

assembly_create_rigid_group / assembly_list_joints

Lock occurrences together; list joints, as-built joints, joint origins and rigid groups

assembly_analyze_interference

Overlapping pairs of occurrences or bodies with volume and bounding box

  • Refs. Components are component:<name>, occurrences occurrence:<fullPathName> (occurrence:Box:1, nested occurrence:Box:1+Hinge:1). An entity seen through an occurrence is <native ref>@<occurrence path> (AbC=@Lid:1, origin:Z@Lid:1); all tools return and accept this form. A native ref of a component inserted exactly once is coerced to that occurrence; with several occurrences the error lists the candidates. Renaming a component changes its occurrence paths, so old refs stop resolving.

  • Units. Lengths in mm, angles in degrees; joint values and limits use degrees for rotation/pitch/yaw/roll and mm for slides.

  • Atomicity. Created components, occurrences, joints and groups are removed on failure; names, grounding, visibility, transforms, joint values, limits and the active component are restored.

Example: a lid on a hinge:

assembly_new_component(name="Box"); assembly_new_component(name="Lid")   # + geometry
assembly_set_occurrence_state(occurrence="occurrence:Box:1", grounded=true)
inspect_query(kind="edge", scope=["occurrence:Box:1"], direction=[1, 0, 0], ...) -> E2=@Box:1
assembly_create_joint(type="revolute", geometry_one={"kind": "curve", "entity": "E1=@Lid:1"},
                      geometry_two={"kind": "curve", "entity": "E2=@Box:1"},
                      motion={"axis": "E2=@Box:1"})
assembly_drive_joint(joint=<joint ref>, values={"rotation": 90})
assembly_analyze_interference(items=["occurrence:Box:1", "occurrence:Lid:1"])

Материалы, экспорт и импорт

Materials, appearances and file exchange:

Tool

What it does

material_list_libraries

Loaded libraries with their material and appearance counts

material_list / appearance_list

Items of one library, of every library or of the design (in_design), with a name query, limit and offset

material_get

Physical material and appearance of a body, component or occurrence

material_assign

Physical material (mass, density) for a body, a component, or an occurrence (applied to its component)

appearance_assign

Appearance for a body, face or occurrence; a library appearance is copied into the design first

appearance_set_color

Plain RGBA colour ("#RRGGBB", "#RRGGBBAA", [r, g, b(, a)]): a design copy of a base appearance, reused when identical

export_cad

Design, component or occurrence to STEP, IGES, SAT, SMT, F3D archive or USDZ

export_mesh

Design, component, occurrence or body to STL, 3MF or OBJ (+ .mtl); refinement low/medium/high/custom

export_sketch_dxf

A sketch to DXF

import_file

STEP, IGES, SAT, SMT, F3D (as occurrences/bodies) or STL, OBJ, 3MF (as mesh bodies, mesh_units) into a component

  • Ids, not names. Material and appearance names are localized and repeat across libraries. Take the id from material_list / appearance_list. A name found in several places fails with details.candidates. Library items are never modified. After material_assign, check the mass with inspect_physical_properties.

  • Paths. Every path is absolute, and the extension must match the format (.step/.stp, .iges/.igs, .sat, .smt, .f3d, .usdz, .stl, .3mf, .obj, .dxf). The tool never appends an extension for you. An export also needs the directory to exist; an import needs the file to exist. Bad paths fail with INVALID_PARAMS and details.reason set to not_absolute, bad_extension, parent_missing, is_directory, exists or not_found. The server checks the path before contacting Fusion.

  • overwrite. An existing file is replaced only with overwrite=true. The old file (and for OBJ its .mtl) is deleted before the export, so if that export then fails, the old file is gone. Every export reports the files it wrote with their sizes. An empty or missing file is FUSION_API_ERROR "export failed".

  • Exporting F3D is not saving. export_cad(format="f3d") writes a copy of the design to a local archive; the document itself stays unsaved and keeps its name. To save the document to the cloud project, use document_save (c04).

  • Mesh settings. Custom refinement values are numbers: surface_deviation and max_edge_length in units (default mm), normal_deviation in degrees, and aspect_ratio. Giving them without refinement="custom" is an error. file_units applies to STL and OBJ only (3MF returns a warning), and binary to STL only.

  • Import. What was created is reported as refs in created.occurrences, bodies and mesh_bodies. An import that produces nothing fails, and in a parametric design its timeline items are rolled back. In a direct design, the created objects are deleted.

Листовой металл

Sheet metal rules, flanges, bends and the flat pattern:

Tool

What it does

sheet_metal_capabilities

Which sheet metal operations this Fusion API supports (no changes); sketch_bend is always false

sheet_metal_list_rules

Design and library rules: thickness, bend radius, gap, relief sizes in mm with expressions, K-factor, relief shape

sheet_metal_create_rule

Design rule copied from a base rule (default: the library default) with new values

sheet_metal_assign_rule

Active rule of a component; a library rule is copied into the design first

sheet_metal_convert

Solid plate body to sheet metal from a planar base face

sheet_metal_base_flange

Flat sheet metal body from closed profiles

sheet_metal_contour_flange

Bent body from an open profile (sketch curves / edges), one side, symmetric or two sides

sheet_metal_edge_flange

Wall on linear edges: height or to-entity, angle, width (full / symmetric / two sided / two offsets), height datum, bend position, mitered corners, flip, bend radius

sheet_metal_list_bends

Inner / outer bend face pairs with the radius in mm

sheet_metal_unfold / sheet_metal_refold

Unfold all or selected bends about a stationary face; refold an unfold feature

sheet_metal_create_flat_pattern / get / delete

The component's flat pattern: size, thickness, bend count, bend angles and directions

sheet_metal_export_flat_pattern

Flat pattern to DXF (bend / extent lines, file units, splines to polylines) or STEP

Fusion API coverage:

Area

API

Status

Rules, active rule, isSheetMetal

SheetMetalRules, Component.activeSheetMetalRule, BRepBody.isSheetMetal

stable

Flat pattern and DXF export

Component.createFlatPattern, FlatPattern, createDXFFlatPatternExportOptions

stable

STEP export of the flat pattern

createSTEPExportOptionsForFlatPattern

preview

Convert

BRepBody.convertToSheetMetal

preview

Base / contour / edge flange

FlangeFeatures.create*FlangeInput

preview

Bends, unfold, refold

BRepBody.getBendFaces, UnfoldFeatures, RefoldFeatures

preview

Bend along a sketch line

—

none

  • Check sheet_metal_capabilities first. A tool built on a missing preview API fails with FUSION_API_ERROR and details = {"reason": "api_unavailable", "api": "<name>"} before it changes anything. Without the flange API a bracket needs the Fusion UI or execute_python.

  • No Bend along a sketch line. The Fusion API has no object for it (sketch_bend is always false). Model a bend with sheet_metal_edge_flange, or draw it into the open profile of sheet_metal_contour_flange.

  • Rules. A rule is addressed by its name and source (design, library, all - design first). Numbers are in units (default mm); strings are expressions that may use Thickness ("Thickness * 1.5"). Write units in expressions ("2 mm"): a rule in inches reads bare numbers as inches. Library rules are never changed. A failed call deletes the rule it created and restores the previous active rule. Fusion may refuse a rule on a component without sheet metal data; then pass rule to the first flange tool.

  • Refs change after every flange. Take edges and faces from the latest result or query them again with inspect_query.

  • Flat pattern. One per component, addressed by the component (default: root). sheet_metal_create_flat_pattern refuses an existing one unless replace=true, and switches Fusion back to the design workspace afterwards. replace is atomic: the tool remembers the stationary face (a component attribute) and recreates the old flat pattern if the new one fails; a flat pattern made in the UI cannot be restored, so replace refuses it (not_restorable) - delete it with sheet_metal_delete_flat_pattern first. Export paths follow the export rules above (absolute, .dxf / .step / .stp, overwrite).

Bracket recipe:

  1. sheet_metal_capabilities - check contour_flange, edge_flange, flat_pattern.

  2. sheet_metal_create_rule(name="Steel 2mm", thickness=2, bend_radius="Thickness * 1", k_factor=0.44).

  3. sketch_create(plane="origin:XY"), then sketch_draw with two lines forming an open L.

  4. sheet_metal_contour_flange(profiles=[<line a>, <line b>], distance=50, rule="Steel 2mm").

  5. inspect_query(kind="edge", scope=[<body>]) -> sheet_metal_edge_flange(edges=[<outer edge>], height=20).

  6. sheet_metal_create_flat_pattern(stationary_face=<planar face>) -> sheet_metal_export_flat_pattern(path="C:/out/bracket.dxf").

Формы (T-splines)

Organic shapes from T-spline bodies (the Form environment):

Tool

What it does

form_list

Form features of the design or a component with their T-spline bodies: control-mesh counts, bbox in mm, the B-Rep body ref

form_create_primitive

Box, plane, cylinder, sphere, torus or quadball with sizes in mm, face counts, origin / directions and symmetry ({"x","y","z"} or "circular"), in a new or an existing form

form_create_from_tsm / form_get_tsm

TSM (T-spline mesh) text or a .tsm file in and out

form_inspect

Control-mesh vertices (control and smooth positions), edges (start, end, midpoint, crease) and faces (center) in mm

form_move

Move vertices or faces picked by points, or the whole body, by a vector

form_crease

Crease or smooth edges picked by points

form_insert_edge

Insert edges next to edges of one loop (preview API)

form_convert_to_brep

Independent B-Rep copy of the form's body (in a base feature), the source hidden

  • Not parametric. The Fusion API takes primitive sizes as numbers: expressions and user parameters are refused (INVALID_PARAMS "not parametric"), and a form does not follow parameter changes. A parameter of another shape (e.g. height for a sphere) is refused.

  • Points, not indices. Control-mesh vertices, edges and faces have no stable ids (INV-7). The editing tools pick them by points in mm: take the vertex position, the edge midpoint or the face center from form_inspect. A point with nothing within tolerance (0.5 mm) or equally near two elements (symmetric meshes) fails with details.nearest and changes nothing.

  • Atomic edits. Every selector is resolved before the first change; if a later move or crease fails, the earlier ones are undone. The form never stays in edit mode, and its B-Rep is regenerated after every call - a body without a B-Rep is an error (rolled back).

  • Convert = copy. The API has no "Convert" command: form_convert_to_brep adds an independent copy of the form's B-Rep (later form edits do not change it) and hides the form, which stays in the timeline.

  • TSM path for the rest. Pull, Bridge, Fill Hole, Weld / Unweld, Subdivide, Merge, Thicken, soft modification, sketch-driven forms (extrude / revolve / sweep / loft in Form), symmetry changes after creation and mesh-to-form conversion have no Fusion API. Read the TSM with form_get_tsm, edit the text and create the body again with form_create_from_tsm (or use execute_python for what the API does have).

  • form_insert_edge uses the preview API: without it the tool fails with FUSION_API_ERROR reason="api_unavailable", nothing changed.

Handle recipe:

  1. form_create_primitive(shape="box", x_size=80, y_size=20, z_size=20, x_faces=4).

  2. form_inspect(body=<body>, include=["faces"]) - pick the face centers to pull.

  3. form_move(body=<body>, kind="face", near=[<center>], vector=[0, 0, 15]).

  4. form_crease(body=<body>, near=[<edge midpoint>]) for a sharp edge.

  5. form_convert_to_brep(body=<body>, name="Handle") -> shell / fillet the solid as usual.

Limitations

  • Timeouts. Every request has a timeout (execute_python takes timeout_s, default 60 s). The Fusion API cannot be interrupted, so when a request times out the operation keeps running in Fusion. Requests run one at a time, in order. Call fusion_status before retrying.

  • Atomicity needs a parametric design. If a tool fails in a parametric design (one with a timeline), the timeline items it added are rolled back. A direct-modeling design has no timeline, so there is no rollback. The error says so in details.rollback = "unavailable_direct_design".

  • Local only: the bridge accepts connections from 127.0.0.1 with the token from the discovery file. There is no remote access.

Development

uv run pytest -q             # unit tests (adsk stubs, fake bridge)
uv run pytest -m fusion      # smoke tests on a live Fusion with the add-in running
uv run ruff check . && uv run ruff format --check . && uv run mypy .

Hot reload of the add-in

Fusion keeps the add-in's modules in sys.modules, so an edit to a linked install is not picked up until the add-in restarts. To load edited handler code into the running add-in:

uv run fusion-mcp reload-addin   # calls dev.reload, prints reloaded modules and handler count

It clears the handler registry, drops the add-in's modules (and fusion_mcp.protocol.*) from sys.modules, imports them again (handlers first) and points the globals of the modules it keeps (the entry point's Context, say) at the new classes. Exit code is non-zero on error: an import error in an edited module comes back as FUSION_API_ERROR with the traceback (status.get and dev.reload keep working); fix the file and run reload-addin again. A few modules hold the running bridge and are never reloaded: the entry point FusionMCP.py, core/server.py, core/dispatcher.py, core/registry.py and fusion_mcp.protocol.errors / wire / discovery. After changing one of them restart the add-in: Utilities > Add-ins > FusionMCP > Stop, Run. A change to handlers/dev.py itself takes effect on the second reload-addin. dev.reload is for development only and is not an MCP tool.

Available Tools

154 tools
appearance_assignA

Assign an appearance to a body, a face or an occurrence. A library appearance is copied into the design first (the library is never changed). A component has no appearance: assign it to its bodies or to an occurrence. Changes only the look, not the physical material (see material_assign).

Returns {"target", "appearance": {"id", "name", "library": "design"}, "previous": {...} | null, "copied": bool}.

Example: appearance_assign(target="", appearance="").

Inputs: target (required), appearance (required), library.

appearance_listA

Appearances (visual look) of one library, of every library (default) or of the design (in_design=true), filtered by a name substring and paginated.

Returns {"items": [{"id", "name", "library"}], "total", "truncated"}.

Example: appearance_list(query="paint", limit=20).

Inputs: limit, query, offset, library, +1 more.

appearance_set_colorA

Give a body, a face or an occurrence a plain colour: a design copy of base (or of the target's current appearance) with the RGBA colour is assigned. An identical copy made earlier is reused ("created": false). Library appearances are not changed.

Returns {"target", "appearance": {"id", "name", "library": "design"}, "created", "color": "#RRGGBBAA"}.

Example: appearance_set_color(target="", color="#FF0000").

Inputs: color (required), target (required), base, name.

assembly_activateA

Activate an occurrence (new sketches and features then go into its component) or, without argument, the root component again.

Returns {"active_component": "component:", "active_occurrence": "occurrence:" | null}.

Example: assembly_activate(occurrence="occurrence:Lid:1") -> {"active_component": "component:Lid", "active_occurrence": "occurrence:Lid:1"}; assembly_activate() -> back to root.

Inputs: occurrence.

assembly_add_occurrenceA

Insert another occurrence of an existing component (a referenced instance, or an independent copy), under root or inside parent, offset by translate_mm (mm). Independent copies need a Fusion version with Occurrences.addNewComponentCopy (otherwise FUSION_API_ERROR).

Returns {"occurrence": occurrence}. Occurrence object: {"ref": "occurrence:", "component", "transform", ...}.

Example: assembly_add_occurrence(component="component:Bolt", translate_mm=[50, 0, 0]) -> {"occurrence": {"ref": "occurrence:Bolt:2", ...}}.

Inputs: component (required), parent, independent, translate_mm.

assembly_analyze_interferenceA

Check whether parts overlap. Every interfering pair comes back with the overlap volume (mm³) and its bounding box (mm); nothing is added to the design. Parts that only touch are not reported unless include_coincident_faces=true. On big assemblies pass the pairs you care about in items - the full check is slow. Fewer than two items -> INVALID_PARAMS.

Returns {"checked": , "count": , "interferences": [{"entity_one", "entity_two", "volume_mm3", "bbox": {"min_mm", "max_mm", "size_mm"}}]}.

Example: assembly_analyze_interference(items=["occurrence:Box:1", "occurrence:Lid:1"]) -> {"checked": 2, "count": 0, "interferences": []}.

Inputs: items, include_coincident_faces.

assembly_component_from_bodiesA

Turn bodies into a new component: the bodies move into a new component (one new occurrence in their current owner) and keep their position. All bodies must belong to the same component, otherwise INVALID_PARAMS and nothing is moved.

Returns {"component": "component:", "occurrence": occurrence, "bodies": [new body refs, '@']}. Old body refs stop resolving; use the returned ones.

Example: assembly_component_from_bodies(bodies=["Bd1=", "Bd2="], name="Lid") -> {"component": "component:Lid", "occurrence": {"ref": "occurrence:Lid:1", ...}, "bodies": ["Xy=@Lid:1", "Zw=@Lid:1"]}.

Inputs: name (required), bodies (required).

assembly_create_as_built_jointA

Join two occurrences where they already are (nothing moves), in the root component. geometry gives the joint position and axis (required except for rigid; refs inside occurrences look like '@'). motion keys as in assembly_create_joint.

Returns {"joint": joint object as in assembly_create_joint}.

Example: assembly_create_as_built_joint(type="revolute", occurrence_one="occurrence:Lid:1", occurrence_two="occurrence:Box:1", geometry={"kind": "curve", "entity": "E2=@Box:1"}) -> {"joint": {"type": "revolute", ...}}.

Inputs: type (required), occurrence_one (required), occurrence_two (required), name, +2 more.

assembly_create_jointA

Join two parts with a joint (created in the root component): geometry_one's part moves so its snap point lands on geometry_two's.

Getting refs: call inspect_query(kind="edge" or "face", scope=["occurrence:Lid:1"]) and use the returned refs; entities inside occurrences look like '@' (e.g. 'AbC=@Lid:1'). A native ref of a component inserted once is accepted; if inserted several times you get INVALID_PARAMS with the candidate refs.

motion keys per type (default in brackets; 'x'|'y'|'z' are axes of the joint, a ref of an edge/axis/face sets a custom direction): rigid - none; revolute - axis [z]; slider - direction [z]; cylindrical - axis [z]; pin_slot - axis [z], slide_direction [x]; planar - normal [z], primary_slide_direction (ref); ball - pitch_direction [z], yaw_direction [x]. For a hinge pass the hinge edge as the axis.

Returns {"joint": {"ref", "name", "type", "occurrence_one", "occurrence_two", "values": {"rotation_deg" | "slide_mm" | ...}, "limits": {dof: {"min", "max", "rest"}}, "is_suppressed", "health", "message"}}. Nothing is left on failure.

Example: assembly_create_joint(type="revolute", geometry_one={"kind": "curve", "entity": "E1=@Lid:1"}, geometry_two={"kind": "curve", "entity": "E2=@Box:1"}, motion={"axis": "E2=@Box:1"}) -> {"joint": {"type": "revolute", "values": {"rotation_deg": 0.0}, "occurrence_one": "occurrence:Lid:1", ...}}.

Inputs: type (required), geometry_one (required), geometry_two (required), flip, +4 more.

assembly_create_joint_originA

Create a joint origin: a reusable snap point for joints, stored in the component that owns the geometry (so it moves with the part). Geometry refs seen through an occurrence ('@Lid:1') are fine: the origin is still created in component Lid. Use it later as {"kind": "joint_origin", "entity": } in assembly_create_joint.

Returns {"joint_origin": {"ref" (in the occurrence context, '@', when the component has one), "native_ref" (inside the component), "name", "component": "component:"}}.

Example: assembly_create_joint_origin(geometry={"kind": "planar_face", "entity": "Fc=@Lid:1", "key_point": "center"}, offset_mm=[0, 0, 5]) -> {"joint_origin": {"ref": "Jo=@Lid:1", "native_ref": "Jo=", "name": "Joint Origin1", "component": "component:Lid"}}.

Inputs: geometry (required), flip, name, angle, +1 more.

assembly_create_rigid_groupA

Lock occurrences together so they move as one (a rigid group in the root component). Needs at least two different occurrences ('occurrence:' refs from assembly_list), otherwise INVALID_PARAMS. Nothing is left on failure.

Returns {"rigid_group": {"ref", "name", "occurrences": ["occurrence:"], "include_children", "is_suppressed"}}.

Example: assembly_create_rigid_group(occurrences=["occurrence:Box:1", "occurrence:Handle:1"]) -> {"rigid_group": {"ref": "Rg=", "name": "Rigid1", "occurrences": ["occurrence:Box:1", "occurrence:Handle:1"], ...}}.

Inputs: occurrences (required), name, include_children.

assembly_deleteA

Delete an occurrence, a joint, an as-built joint, a joint origin or a rigid group. Other entities are refused (INVALID_PARAMS): use body_delete, sketch_delete or timeline_delete for them. Deleting the last occurrence of a component removes the component from the design.

Returns {"deleted": {"name", "type"}}.

Example: assembly_delete(item="occurrence:Box:2") -> {"deleted": {"name": "Box:2", "type": "Occurrence"}}.

Inputs: item (required).

assembly_drive_jointA

Move a joint to the given values (e.g. open a hinge to 90 degrees). Fusion keeps values inside the joint limits: dofs whose actual value differs from the request are listed in "clamped" (the actual value is in joint.values). Values are restored if Fusion fails.

Returns {"joint": joint object (see assembly_create_joint), "requested": {dof: value}, "clamped": [dof], "captured": bool}.

Example: assembly_drive_joint(joint="Jt=", values={"rotation": 90}) -> {"joint": {"values": {"rotation_deg": 90.0}, ...}, "requested": {"rotation": 90.0}, "clamped": [], "captured": true}.

Inputs: joint (required), values (required), capture_position.

assembly_listA

List the assembly structure of the active design: every component and every occurrence (nested ones by path) with transform, grounded, light bulb, visibility and joint count.

Returns {"active_component": "component:", "components": [{"ref": "component:", "name", "is_root", "occurrence_count", "body_count", "part_number"}], "occurrences": [occurrence], "joint_count", "truncated"}. Occurrence object: {"ref": "occurrence:", "component", "full_path_name", "is_grounded", "is_visible", "is_light_bulb_on", "transform": {"translation_mm", "rotation"}, "joint_count"}.

Example: assembly_list() -> {"components": [{"ref": "component:Box", ...}], "occurrences": [{"ref": "occurrence:Box:1", ...}], ...}.

Inputs: limit.

assembly_list_jointsA

List the joints, as-built joints, joint origins and rigid groups of every component, with current joint values (degrees / mm), limits, suppression and health. Use it to check a mechanism after assembly_drive_joint.

Returns {"joints": [joint], "as_built_joints": [joint], "joint_origins": [{"ref", "native_ref", "name", "component"}], "rigid_groups": [{"ref", "name", "occurrences", "include_children", "is_suppressed"}]}. Joint object: {"ref", "name", "type", "occurrence_one", "occurrence_two", "values": {"rotation_deg" | "slide_mm" | ...}, "limits": {dof: {"min", "max", "rest"}}, "is_suppressed", "health", "message"}.

Example: assembly_list_joints() -> {"joints": [{"name": "Hinge", "type": "revolute", "values": {"rotation_deg": 90.0}, ...}], ...}.

Inputs: no named parameters.

assembly_new_componentA

Create an empty component with one new occurrence, under root or inside the component of parent, optionally offset by translate_mm (mm). Build its geometry after activating it (assembly_activate) or by targeting the component.

Returns {"component": "component:", "occurrence": occurrence}. Occurrence object: {"ref": "occurrence:", "transform", "is_grounded", ...}. The whole call is undone on failure.

Example: assembly_new_component(name="Box") -> {"component": "component:Box", "occurrence": {"ref": "occurrence:Box:1", "transform": {"translation_mm": [0, 0, 0], ...}}}.

Inputs: name (required), parent, translate_mm.

assembly_rename_componentA

Rename a component. The root component cannot be renamed (INVALID_PARAMS).

WARNING: occurrence paths contain the component name ('Box:1' -> 'Case:1'), so every old 'occurrence:Box:1' ref and '@Box:1' proxy ref stops resolving (ENTITY_NOT_FOUND); use the returned paths.

Returns {"component": "component:", "occurrences": ["occurrence:", ...]}.

Example: assembly_rename_component(component="component:Box", name="Case") -> {"component": "component:Case", "occurrences": ["occurrence:Case:1"]}.

Inputs: name (required), component (required).

assembly_set_joint_limitsA

Set the motion limits of one degree of freedom: rotation/pitch/yaw/roll in degrees, slide/primary_slide/secondary_slide in mm. A number enables the limit, "off" disables it, omitted keeps it. dof must exist for the joint type (revolute: rotation; slider: slide; cylindrical/pin_slot: rotation, slide; planar: primary_slide, secondary_slide, rotation; ball: pitch, yaw, roll), and min must not exceed max, otherwise INVALID_PARAMS.

Returns {"joint": joint object (see assembly_create_joint) with "limits"}.

Example: assembly_set_joint_limits(joint="Jt=", dof="rotation", min=0, max=110) -> {"joint": {"limits": {"rotation": {"min": 0.0, "max": 110.0, "rest": null}}, ...}}.

Inputs: dof (required), joint (required), max, min, +1 more.

assembly_set_occurrence_stateA

Ground/unground an occurrence and/or switch its light bulb (visibility). Pass at least one of grounded, light_bulb.

Returns {"occurrence": occurrence} with "is_grounded" and "is_light_bulb_on".

Example: assembly_set_occurrence_state(occurrence="occurrence:Box:1", grounded=true).

Inputs: occurrence (required), grounded, light_bulb.

assembly_transform_occurrenceA

Move an occurrence in assembly space: relative (rotate about an axis through origin_mm, then translate by translate_mm, mm/degrees) or absolute (origin and X/Y axes). Grounded occurrences are refused (INVALID_PARAMS): unground them with assembly_set_occurrence_state first. Occurrences held by joints snap back to the joints on recompute (see "constrained_by_joints"); drive joints instead.

Returns {"occurrence": occurrence, "captured": bool (a position snapshot was added in a parametric design), "constrained_by_joints": bool}.

Example: assembly_transform_occurrence(occurrence="occurrence:Lid:1", translate_mm=[0, 0, 40]) -> {"occurrence": {"transform": {"translation_mm": [0, 0, 40], ...}}, "captured": true, ...}; rotate={"axis": [0, 0, 1], "angle_deg": 90}.

Inputs: occurrence (required), rotate, absolute, translate_mm, +1 more.

body_boundary_fillA

Boundary fill: make solids from the closed cells that tool bodies, faces and planes enclose.

Cells are chosen by points, never by index: every cell by default, or the cells that contain cell_points. If a point lies in no cell, nothing is created and the error lists every cell (details.cells: center [x, y, z] mm and volume mm³) to pick points from. Refs: bodies/faces from inspect_query, planes from origin:* / construction_*.

Errors: a point in no cell, tools enclosing no cell -> INVALID_PARAMS (nothing changed); a fill Fusion cannot compute -> FUSION_API_ERROR, rolled back.

Returns {"feature", "health", "created_bodies", "modified_bodies", "removed_bodies"}.

Example: body_boundary_fill(tools=[, "origin:XY"], cell_points=[[5, 5, 5]])

Inputs: tools (required), units, operation, cell_points, +1 more.

body_combineA

Boolean of bodies: join, cut or intersect tool bodies with a target body.

The target is changed (modified_bodies); consumed tools are listed by token in removed_bodies unless keep_tools=true. With new_component=true the result body is created in a new component ("component" in the result). Refs: bodies from inspect_query or earlier results (tokens change after this feature - use the refs in the result).

Errors: the target listed in tools, a non-body ref -> INVALID_PARAMS (nothing changed); a combine Fusion cannot compute -> FUSION_API_ERROR, rolled back.

Returns {"feature", "health", "created_bodies", "modified_bodies", "removed_bodies"} (+ "component" with new_component).

Example: body_combine(target=, tools=[, ])

Inputs: tools (required), target (required), operation, keep_tools, +1 more.

body_delete_facesA

Delete faces from a body; Fusion heals the gap (e.g. remove a fillet or a boss).

Faces from inspect_query on the latest body. The bodies are listed in modified_bodies.

Errors: a non-face ref -> INVALID_PARAMS (nothing changed); faces Fusion cannot heal -> FUSION_API_ERROR, rolled back.

Returns {"feature", "health", "created_bodies", "modified_bodies", "removed_bodies"}.

Example: body_delete_faces(faces=[<fillet face 1>, <fillet face 2>])

Inputs: faces (required).

body_moveA

Move (or copy and move) bodies as a Move feature in the timeline.

Transforms: translate (x/y/z in units or expressions; design_space=false uses the component axes), translate_along (straight edge/axis + distance), rotate (axis ref + angle in degrees), rotate_about (free axis: point [x,y,z] in units, direction vector, numeric angle in degrees), align (move point from onto point to: vertex, sketch/construction point, origin:O), matrix (16 numbers row-major, a rigid rotation + translation in units; use body_scale to scale). keep_original=true copies with Copy/Paste (a non-associative copy; for associative copies use pattern_*), and only the copies move. Refs: bodies/edges/vertices from inspect_query, axes/points from origin:* or construction_*.

Errors: a non-rigid matrix, a wrong ref kind -> INVALID_PARAMS (nothing changed); on an old Fusion API expressions / component-space moves -> FUSION_API_ERROR "not available".

Returns {"feature", "health", "created_bodies" (copies), "modified_bodies" (moved originals), "removed_bodies"} + "copy": {"feature", "method"} with keep_original.

Examples:

  • body_move(bodies=[b], transform={"type": "translate", "z": 50})

  • body_move(bodies=[b], transform={"type": "rotate", "axis": "origin:Z", "angle": 90}, keep_original=true)

Inputs: bodies (required), transform (required), units, keep_original.

body_removeA

Remove bodies from the design.

mode=remove adds a Remove feature per body to the timeline of a parametric design (the bodies come back if the feature is suppressed or deleted); mode=delete deletes them. A direct design (no timeline) always deletes (mode_used = "delete"); there a Fusion failure on a later body cannot bring back earlier deleted ones.

Errors: a non-body ref -> INVALID_PARAMS (nothing removed).

Returns {"removed": [refs before removal], "features": [{ref, type, name}], "mode_used": "remove" | "delete"}.

Example: body_remove(bodies=[])

Inputs: bodies (required), mode.

body_renameA

Rename a body (not a timeline feature).

Returns {"body": {ref, type, name}, "previous_name": str}.

Errors: an empty name, a non-body ref -> INVALID_PARAMS.

Example: body_rename(body=, name="Lid")

Inputs: body (required), name (required).

body_replace_faceA

Replace faces of a body with a target face, plane or surface body (the body grows or shrinks to the target).

Refs: faces from inspect_query, planes from origin:* / construction_*, surface bodies from earlier results. A solid body is not a valid target.

Errors: a solid body or one of the faces as target -> INVALID_PARAMS (nothing changed); a replace Fusion cannot compute -> FUSION_API_ERROR, rolled back.

Returns {"feature", "health", "created_bodies", "modified_bodies", "removed_bodies"}.

Example: body_replace_face(faces=[], target=)

Inputs: faces (required), target (required), tangent_chain.

body_scaleA

Scale bodies about a base point, uniformly (factor) or per axis (factors).

Factors are unitless numbers > 0 (or Fusion expressions) - no unit conversion. Pass either factor or factors. Refs: bodies from inspect_query, points from origin:O, construction_point or vertices.

Errors: a factor <= 0, factor together with factors, a non-point base -> INVALID_PARAMS (nothing changed).

Returns {"feature", "health", "created_bodies", "modified_bodies", "removed_bodies"}.

Examples: body_scale(bodies=[b], factor=0.5); body_scale(bodies=[b], factors={"x": 1, "y": 2, "z": 0.5})

Inputs: bodies (required), point, factor, factors.

body_set_visibilityA

Show/hide bodies (light bulb) and/or set their opacity.

All or nothing: if Fusion refuses a value for one body, every body gets its previous values back. is_visible in the result is the effective visibility (a hidden component hides its bodies even with the light bulb on).

Errors: neither visible nor opacity, opacity outside 0..1 -> INVALID_PARAMS.

Returns {"bodies": [{ref, type, name, light_bulb, is_visible, opacity}]}.

Example: body_set_visibility(bodies=[a, b], visible=false)

Inputs: bodies (required), opacity, visible.

body_splitA

Split bodies into parts with a plane, a face or another body.

The new parts are listed in created_bodies, the split bodies in modified_bodies. Refs: planes from origin:* / construction_*, faces and bodies from inspect_query.

Errors: the tool among the bodies, a tool of another type -> INVALID_PARAMS (nothing changed); a tool that does not cross the body -> FUSION_API_ERROR, rolled back.

Returns {"feature", "health", "created_bodies", "modified_bodies", "removed_bodies"}.

Example: body_split(bodies=[], tool="origin:XZ")

Inputs: tool (required), bodies (required), extend_tool.

body_split_faceA

Split faces of a body with a tool (to get separate faces for draft, offset, colors).

intersection: along the tool's intersection; along_vector: project the tool along direction; closest_point: project to the closest points. Refs: faces/bodies from inspect_query, planes from origin:* / construction_*, curves from sketch_* results.

Errors: along_vector without direction, direction with another type -> INVALID_PARAMS (nothing changed); a split type this Fusion API lacks -> FUSION_API_ERROR "not available".

Returns {"feature", "health", "created_bodies", "modified_bodies", "removed_bodies", "faces": [{ref, type}] - the new faces}.

Example: body_split_face(faces=[], tool="origin:YZ")

Inputs: tool (required), faces (required), direction, split_type, +1 more.

body_thickenA

Thicken faces (usually of a surface body) into a solid.

Units: thickness in units (default mm) or a Fusion expression. Faces from inspect_query.

Errors: thickness 0, a non-face ref -> INVALID_PARAMS (nothing changed); a thicken Fusion cannot compute -> FUSION_API_ERROR, rolled back.

Returns {"feature", "health", "created_bodies", "modified_bodies", "removed_bodies"}.

Example: body_thicken(faces=[], thickness=2)

Inputs: faces (required), thickness (required), chain, units, +2 more.

construction_axisA

Create a construction axis — for revolve, circular patterns, joints.

Give method and exactly its fields:

method

fields

two_points

points (2 refs)

edge

edge (straight)

cylinder

face (cylinder, cone or torus): its axis

perpendicular_at_point

face, point (on that face): normal through it

two_planes

plane, plane2: their intersection line

Refs: origin:XY|XZ|YZ|X|Y|Z|O or refs from inspect_query (e.g. a hole face: inspect_query(kind="face", surface_type="cylinder")). A wrong entity kind fails with INVALID_PARAMS and details {param, expected, got}; a definition Fusion cannot build (parallel planes, a point off the face) fails with FUSION_API_ERROR and leaves the timeline unchanged.

Returns {"ref", "type": "ConstructionAxis", "name", "origin_mm", "direction", "health", "warning"?}.

Examples:

  • construction_axis(method="cylinder", face=)

  • construction_axis(method="two_planes", plane="origin:XZ", plane2="origin:YZ")

Inputs: method (required), edge, face, name, +5 more.

construction_planeA

Create a construction plane — a reference for sketches, mirrors, splits.

Give method and exactly its fields (others are refused with INVALID_PARAMS and the list of fields the method takes):

method

fields

offset

plane, distance

angle

edge (axis of rotation), angle, plane

midplane

plane, plane2 (midway between them)

two_edges

edge, edge2 (coplanar straight edges)

three_points

points (3 refs)

tangent

face (cylinder/cone), plane, angle = 0

tangent_at_point

face (cylinder/cone), point

along_path

path, proportion (0..1, normal to path)

Refs: origin:XY|XZ|YZ|X|Y|Z|O or refs from inspect_query / inspect_tree. Lengths are mm, angles degrees; a string is a Fusion expression ("height / 2") and keeps the plane driven by it. A wrong entity kind (e.g. a cylindrical face as plane) fails with INVALID_PARAMS and details {param, expected, got}; a definition Fusion cannot build fails with FUSION_API_ERROR and leaves the timeline unchanged.

Returns {"ref", "type": "ConstructionPlane", "name", "origin_mm", "normal", "health", "warning"?}.

Examples:

  • construction_plane(method="offset", plane="origin:XY", distance=15)

  • construction_plane(method="midplane", plane=, plane2=)

  • construction_plane(method="along_path", path=, proportion=0.5)

Inputs: method (required), edge, face, name, +10 more.

construction_pointA

Create a construction point — a joint origin, a hinge center, a sketch anchor.

Give method and exactly its fields:

method

fields

vertex

point (vertex, sketch point or construction point)

two_edges

edge, edge2: their intersection

three_planes

plane, plane2, plane3: their intersection

edge_plane

edge, plane: where the edge crosses the plane

center

entity: center of a circle, arc, sphere or torus

Points by coordinates are sketch points (sketch_draw), not construction points. Refs: origin:XY|XZ|YZ|X|Y|Z|O or refs from inspect_query (e.g. a hole edge: inspect_query(kind="edge", curve_type="circle")). A wrong entity kind fails with INVALID_PARAMS and details {param, expected, got}; a definition Fusion cannot build (edges that do not meet) fails with FUSION_API_ERROR and leaves the timeline unchanged.

Returns {"ref", "type": "ConstructionPoint", "name", "point_mm", "health", "warning"?}.

Examples:

  • construction_point(method="center", entity=)

  • construction_point(method="three_planes", plane="origin:XY", plane2="origin:XZ", plane3="origin:YZ")

Inputs: method (required), edge, name, edge2, +6 more.

design_get_settingsB

Settings of the active design.

Returns {"design_type": "parametric"|"direct", "units": "mm"|"cm"|"m"|"in"|"ft" (display units), "document": {"ref", "type", "name"}, "root_component": {"ref", "type", "name"}, "parameter_count", "timeline_count" (null for direct designs)}.

Inputs: no named parameters.

design_set_typeA

Switch the active design between parametric (timeline) and direct modelling.

Parametric -> direct DELETES THE WHOLE TIMELINE (feature history and parameters driving it) and cannot be undone or rolled back; it needs confirm_discard_history=true, otherwise INVALID_PARAMS and nothing changes. Ask the user before confirming. Direct -> parametric starts a new timeline. The same type is a no-op ("changed": false).

Returns the settings plus "changed" and "history_discarded".

Example: design_set_type(design_type="parametric").

Inputs: design_type (required), confirm_discard_history.

design_set_unitsA

Change the distance units Fusion displays and uses for unitless expressions in the active design. Numbers passed to tools are NOT affected: they stay in mm (e.g. a length of 25 is still 25 mm after design_set_units("in")).

Returns the settings (see design_get_settings).

Example: design_set_units(units="in").

Inputs: units (required).

document_activateA

Make an open document the active one; every other tool then works on it.

Two unsaved documents with the same name are ambiguous: the call fails with INVALID_PARAMS and details.candidates. A ref that matches no open document is ENTITY_NOT_FOUND.

Returns the document's info (see document_list) with "is_active": true.

Example: document_activate(document="document:file:urn:adsk.wipprod:dm.lineage:abc").

Inputs: document (required).

document_closeA

Call ONLY when the user explicitly asked to close the document.

A document with unsaved changes is not closed unless exactly one of save_changes or discard_changes is true (INVALID_PARAMS otherwise, the document stays open). save_changes needs a document that was saved before — call document_save with a name first.

Returns {"closed": {"ref", "type", "name"}, "active": | null}.

Example: document_close(discard_changes=true).

Inputs: document, save_changes, discard_changes.

document_listA

List the documents open in Fusion.

Each item: {"ref", "name", "is_active", "is_saved", "is_modified", "file_id", "version", "design_type": "parametric"|"direct"|null, "units": "mm"|...|null}. ref is document:file:<id> for a saved document and document:<name> for an unsaved one; pass it to document_activate / document_save / document_close. Other tools always work on the active document.

Returns {"documents": [...]}.

Inputs: no named parameters.

document_newA

Create a new design document and make it active. It is NOT saved; call document_save only when the user asks to save.

units only sets how Fusion displays lengths; numbers passed to tools stay in mm.

Returns the new document's info (see document_list).

Example: document_new() -> parametric design in mm.

Inputs: units, design_type.

document_openA

Open a document and make it active. Pass exactly one of file_id (a cloud file) or local_path (an existing local .f3d file; other formats such as STEP are not opened here).

A cloud file that is already open is activated instead of opened again ("already_open": true).

Returns the document's info (see document_list) plus "already_open".

Examples: document_open(file_id="urn:adsk.wipprod:dm.lineage:abc"); document_open(local_path="C:/parts/bracket.f3d").

Inputs: file_id, local_path.

document_saveA

Call ONLY when the user explicitly asked to save the document.

An already saved document gets a new version (name/folder_path are rejected: no Save As). A never-saved document needs name and is saved into the active project's root folder or the existing folder_path (missing folders are ENTITY_NOT_FOUND and never created). The upload to the cloud continues in the background ("upload": "pending").

Returns the document's info (see document_list) plus "upload": "pending".

Examples: document_save(name="Bracket"); document_save(description="hole moved").

Inputs: name, document, description, folder_path.

execute_pythonA

Run Python code inside Fusion 360 on its main thread. Use it only when no dedicated tool can do the job.

In scope: adsk (adsk.core, adsk.fusion), app (adsk.core.Application), ui, design (active adsk.fusion.Design or None), root (design.rootComponent or None) and params (the params argument, default {}).

Units: the Fusion API itself works in CENTIMETRES and RADIANS. Convert yourself: 25 mm -> 2.5, 90 deg -> math.pi / 2. Strings passed to adsk.core.ValueInput.createByString are Fusion expressions ("25 mm", "width / 2").

Returns JSON {"result", "stdout", "stderr"}: result is the value of the variable result after the code runs (JSON as is, otherwise its repr); stdout/stderr are captured and cut at 64 KiB with a truncation marker. If the code raises, the result is an error FUSION_API_ERROR with the traceback in details, and timeline items the code added are rolled back (parametric designs only).

Example: code = "sk = root.sketches.add(root.xYConstructionPlane)\n" "sk.sketchCurves.sketchCircles.addByCenterRadius(" "adsk.core.Point3D.create(0, 0, 0), params['r_mm'] / 10)\n" "result = sk.name" params = {"r_mm": 12.5}

Inputs: code (required), params, timeout_s.

export_cadA

Export the design, a component or an occurrence to STEP, IGES, SAT, SMT, an F3D archive or USDZ (if this Fusion supports USD).

The path must be absolute, its directory must exist and its extension must match the format; an existing file is replaced only with overwrite=true (the old file is deleted first, so a failed export loses it). Exporting does not save the document (document_save does).

Returns {"files": [{"path", "size_bytes"}], "format", "scope": | "root"}.

Example: export_cad(path="C:/out/housing.step").

Inputs: path (required), scope, format, overwrite.

export_meshA

Export the design, a component, an occurrence or a body as a mesh: STL, 3MF or OBJ (OBJ also writes .mtl). refinement low|medium|high, or custom with at least one of surface_deviation / normal_deviation / max_edge_length / aspect_ratio (numbers only; giving them without refinement="custom" is an error).

The path must be absolute, its directory must exist and its extension must match the format; an existing file is replaced only with overwrite=true (the old file is deleted first). Exporting does not save the document.

Returns {"files": [{"path", "size_bytes"}], "format", "scope"} (+ "warnings", e.g. file_units ignored for 3MF).

Example: export_mesh(path="C:/out/bracket.stl", scope="", refinement="high").

Inputs: path (required), scope, units, binary, +8 more.

export_sketch_dxfA

Write a sketch to a DXF file (e.g. for laser cutting). Same path rules as export_cad; fails with FUSION_API_ERROR if this Fusion cannot export sketches to DXF.

Returns {"files": [{"path", "size_bytes"}], "format": "dxf", "scope": }.

Example: export_sketch_dxf(sketch="", path="C:/out/plate.dxf").

Inputs: path (required), sketch (required), overwrite.

feature_chamferA

Bevel edges of a body with a chamfer.

Modes: equal (distance), two_distances (distance and distance2 on the two faces), distance_angle (distance and angle, default 45 deg); flip swaps which face gets which value. Units: distances in units (default mm), angle in degrees, strings are Fusion expressions. Edge refs from inspect_query on the latest body. The parent bodies are listed in modified_bodies.

Errors: distance2 / angle / flip with another mode, a missing distance2 -> INVALID_PARAMS (nothing changed); a failed chamfer -> FUSION_API_ERROR, rolled back.

Returns {"feature", "health", "created_bodies", "modified_bodies", "removed_bodies"}.

Examples:

  • feature_chamfer(edges=[e], distance=1)

  • feature_chamfer(edges=[e], mode="distance_angle", distance=2, angle=30)

Inputs: edges (required), distance (required), flip, mode, +4 more.

feature_draftA

Tilt faces by a draft angle relative to a neutral plane (moulding / casting draft).

The plane fixes the line the faces pivot about and its normal is the pull direction (flip reverses it). One angle, symmetric=true for both sides by the same angle, or angle + angle2 for two sides. Angles in degrees or Fusion expressions. Faces from inspect_query; the plane must not be one of the faces. The drafted bodies are listed in modified_bodies.

Errors: angle 0 or >= 90, angle2 with symmetric, a non-planar plane -> INVALID_PARAMS (nothing changed); a failed draft -> FUSION_API_ERROR, rolled back.

Returns {"feature", "health", "created_bodies", "modified_bodies", "removed_bodies"}.

Example: feature_draft(faces=[f1, f2, f3, f4], plane="origin:XY", angle=2)

Inputs: angle (required), faces (required), plane (required), flip, +3 more.

feature_extrudeA

Extrude sketch profiles, planar faces or sketch texts into a solid (or cut/join/ intersect existing bodies).

Units: plain-number lengths are in units (default mm), angles in degrees; a string is a Fusion expression ("wall * 2", "5 deg") and keeps the feature driven by it. Refs: profiles from sketch_draw / sketch_profiles ("profile:@x,y") or {"sketch": , "all": true}; planar faces and to_entity targets from inspect_query; planes from construction_plane or origin:XY|XZ|YZ; sketch texts from sketch_draw (kind "text"). Refs to faces/bodies go stale after later features - take them from the latest results.

Modes:

  • one_side: side1 + direction (positive = sketch normal) + taper1;

  • two_sides: side1 and side2 independent (each its own extent and taper);

  • symmetric: side1 must be a distance; symmetric_full_length picks total vs half. A negative distance extrudes the other way. operation="cut" with through_all and direction="negative" cuts down through a body below the sketch.

Surface: is_solid=false extrudes a surface body (operation new_body / new_component, no thin); profiles may then also be open sketch curve refs or edge refs (one kind, connected curves are chained) - e.g. an open line becomes a wall sheet.

Errors: wrong field for the mode or a wrong entity kind -> INVALID_PARAMS (nothing changed); a stale profile point -> ENTITY_NOT_FOUND with details.profiles (current profiles); a feature Fusion computes with an error -> FUSION_API_ERROR and the timeline is rolled back. A warning keeps the feature and is reported in health.

Returns {"feature": {ref, type, name}, "health": {"state": ok|warning|error|unknown, "message"}, "created_bodies": [{ref, type, name}], "modified_bodies": [{ref, type, name}], "removed_bodies": [<refs of bodies consumed by join/cut>], "component"?: {ref, type, name} (new_component only)}. Body geometry is not repeated: describe the bodies with inspect_* if needed.

Examples:

  • feature_extrude(profiles=["profile:@10,10"], side1={"type": "distance", "distance": 20})

  • feature_extrude(profiles=[...], operation="cut", side1={"type": "through_all"}, direction="negative")

  • feature_extrude(profiles=[...], mode="symmetric", side1={"type": "distance", "distance": 40}, symmetric_full_length=true, thin={"thickness": 2, "location": "center"})

Inputs: side1 (required), profiles (required), mode, thin, +10 more.

feature_filletA

Round edges of a body with a fillet.

Modes: constant needs radius; variable needs start_radius and end_radius, plus optional mid radii at positions 0 (edge start) .. 1 (edge end); chord needs chord_length. Fields of another mode are refused. Units: radii and lengths in units (default mm), strings are Fusion expressions ("wall / 2"). Edge refs come from inspect_query on the latest body (refs go stale after later features). The parent bodies of the edges are listed in modified_bodies.

Errors: a missing mode field, a non-edge ref -> INVALID_PARAMS (nothing changed); variable/chord fillets on an old Fusion API -> FUSION_API_ERROR "not available"; a fillet Fusion computes with an error (radius too big) -> FUSION_API_ERROR and the timeline is rolled back.

Returns {"feature": {ref, type, name}, "health": {"state", "message"}, "created_bodies": [], "modified_bodies": [{ref, type, name}], "removed_bodies": []}.

Examples:

  • feature_fillet(edges=[e1, e2, e3, e4], radius=5)

  • feature_fillet(edges=[e], mode="variable", start_radius=2, end_radius=5, mid=[{"position": 0.5, "radius": 3}])

Inputs: edges (required), g2, mid, mode, +7 more.

feature_holeA

Drill simple, counterbore or countersink holes - optionally tapped - into a body.

Units: diameters, depths, offsets and points are in units (default mm); angles in degrees; a string is a Fusion expression ("bolt_d + 0.5"). Refs: planar faces and edges from inspect_query (refs go stale after later features - use the latest results), sketch points from sketch_draw (all points of one call in one sketch on the face), construction planes from construction_plane.

Kinds: simple needs only diameter; counterbore needs cb_diameter and cb_depth; countersink needs cs_diameter (cs_angle default 90). Fields of another kind are refused. tip_angle defaults to 118 deg (180 = flat bottom). The hole always cuts; participant_bodies limits which bodies.

Tapped hole: thread={"designation": "M6x1"} (ThreadSpec: thread_type default "ISO Metric profile", designation, thread_class, modeled=false (cosmetic), full_length=true or length + offset, location high|low). Drill the tap-drill diameter (M6x1 -> 5). If the thread cannot be created the whole call fails and neither the hole nor the thread stays. See feature_thread_options for valid designations.

Errors: a missing kind field, a non-planar face, a non-circular center edge, an unknown designation (details.available) -> INVALID_PARAMS (nothing changed); a hole or thread Fusion computes with an error -> FUSION_API_ERROR and the timeline is rolled back.

Returns {"feature": {ref, type, name}, "health": {"state", "message"}, "created_bodies": [], "modified_bodies": [{ref, type, name}] (the drilled body), "removed_bodies": [], "holes": , "thread"?: {"type", "designation", "class", "internal": true, "modeled", "feature": {ref, type, name}, "health", "faces"}}.

Examples:

  • feature_hole(placement={"type": "sketch_points", "points": [p1, p2, p3, p4]}, kind="counterbore", diameter=5.5, cb_diameter=10, cb_depth=5.5, extent={"type": "through_all"})

  • feature_hole(placement={"type": "point", "face": , "point": [10, 10, 20]}, diameter=5, extent={"type": "distance", "depth": 12}, thread={"designation": "M6x1"})

Inputs: extent (required), diameter (required), placement (required), flip, +9 more.

feature_loftA

Loft a solid through two or more sections - transitions, ducts, bottle necks, domes ending in a point.

Sections: each is exactly one profile ('profile:@x,y' or a {"sketch", ...} spec selecting one region), a planar face (inspect_query), or a point - a sketch point, construction point (construction_point, origin:O) or vertex - which may only be the first or the last section. End conditions: free (default), tangent / smooth (with weight), direction (angle in degrees + weight), point_sharp / point_tangent (point sections only). Inner sections keep free unless asked otherwise.

Guides: rails (sketch curves or edges touching every section) or one centerline, never both. closed=true joins the last section back to the first (needs 3+ profile sections and no point section). is_solid=false lofts a surface body (new_body / new_component only).

Units: angles in degrees, weights plain numbers; units only applies to {"sketch", "point"} profile specs. Errors: fewer than 2 sections, rails with a centerline, a point in the middle, point_* on a profile, closed with a point, more than one profile in a section -> INVALID_PARAMS (nothing changed); a feature Fusion computes with an error -> FUSION_API_ERROR and the timeline is rolled back.

Returns {"feature": {ref, type, name}, "health": {"state": ok|warning|error|unknown, "message"}, "created_bodies": [{ref, type, name}], "modified_bodies": [{ref, type, name}], "removed_bodies": [<refs of bodies consumed by join/cut>], "component"?: {ref, type, name} (new_component only)}.

Examples:

  • feature_loft(sections=[{"entity": "profile:@0,0"}, {"entity": "profile:@0,0"}], rails=[])

  • feature_loft(sections=[{"entity": , "end_condition": "tangent"}, {"entity": , "end_condition": "point_tangent", "weight": 2}], operation="join")

Inputs: sections (required), rails, units, closed, +5 more.

feature_offset_facesA

Press-pull faces of a body: move them along their normals by a signed distance (positive grows the body outward, negative pulls the faces in).

Press-pull of a sketch profile = feature_extrude; press-pull of a fillet edge (change a rounding) = feature_fillet. Units: distance in units (default mm) or a Fusion expression. Faces from inspect_query on the latest body. The bodies are listed in modified_bodies.

Errors: distance 0, a non-face ref -> INVALID_PARAMS (nothing changed); an offset Fusion cannot compute -> FUSION_API_ERROR, rolled back.

Returns {"feature", "health", "created_bodies", "modified_bodies", "removed_bodies"}.

Example: feature_offset_faces(faces=[], distance=2)

Inputs: faces (required), distance (required), chain, units.

feature_revolveA

Revolve sketch profiles or planar faces around an axis - shafts, pulleys, bottles, grooves (operation="cut").

Units: angles are degrees (a string is a Fusion expression, e.g. "180 deg"); units only applies to {"sketch", "point"} profile specs. Refs: profiles from sketch_draw / sketch_profiles; the axis is a sketch line ref (sketch_draw refs), a construction axis (construction_axis, origin:X|Y|Z) or a straight BRep edge (inspect_query). The profile must lie on one side of the axis. is_solid=false revolves a surface body (new_body / new_component only).

Extents: full (default) = 360 deg; angle with symmetric=true splits the angle to both sides of the sketch plane; two_angles sets each side; to_entity revolves up to a face, body, construction plane, vertex or construction point, starting towards the sketch normal (direction="positive") or away from it ("negative").

Errors: an axis that is not linear (e.g. a circular edge) or a wrong extent field -> INVALID_PARAMS (nothing changed); a feature Fusion computes with an error -> FUSION_API_ERROR and the timeline is rolled back.

Returns {"feature": {ref, type, name}, "health": {"state": ok|warning|error|unknown, "message"}, "created_bodies": [{ref, type, name}], "modified_bodies": [{ref, type, name}], "removed_bodies": [<refs of bodies consumed by join/cut>], "component"?: {ref, type, name} (new_component only)}. Body geometry is not repeated: describe the bodies with inspect_* if needed.

Examples:

  • feature_revolve(profiles=["profile:@5,20"], axis="origin:Z")

  • feature_revolve(profiles=[...], axis=, extent={"type": "angle", "angle": 90, "symmetric": true}, operation="cut")

Inputs: axis (required), profiles (required), units, extent, +3 more.

feature_ribA

Add a rib (a thin stiffening wall) from open sketch curves, joined to the body it meets - gussets in housings, brackets, bosses.

Units: thickness and depth.distance are in units (default mm), a string is a Fusion expression ("wall"). Refs: open sketch curves from sketch_draw (a line or arc drawn in a sketch on a plane cutting the body, e.g. a construction_plane through the corner); circles and closed splines are refused. The rib is always joined to target_body (no operation parameter); without it, to the one solid body of the curves' component that a curve touches.

Errors: closed curve, wrong thickness_location or depth -> INVALID_PARAMS (nothing changed); no target_body and the curves touch no body or several -> INVALID_PARAMS with details.candidates (body refs to pass as target_body); thickness_location "side2" is not available in the current Fusion API (FUSION_API_ERROR, no change): use "side1" with the curve drawn the other way; a Fusion API version without rib features -> FUSION_API_ERROR "not available" with no change (use execute_python then); a rib Fusion computes with an error -> FUSION_API_ERROR and the timeline is rolled back.

Returns {"feature": {ref, type, name}, "health": {"state": ok|warning|error|unknown, "message"}, "created_bodies": [...], "modified_bodies": [{ref, type, name}] (the body the rib joins), "removed_bodies": [...]}.

Example: feature_rib(curves=[], thickness=3)

Inputs: curves (required), thickness (required), flip, depth, +3 more.

feature_rule_filletA

Rule-based fillet: round every edge of the given faces/features (all_edges) or only the edges where faces meet faces2 (between_faces), with one radius.

Units: radius in units (default mm) or a Fusion expression. Faces come from inspect_query, features from earlier feature_* results (their "feature" ref). The parent bodies are listed in modified_bodies.

Errors: faces2 with all_edges or missing with between_faces -> INVALID_PARAMS; a Fusion API without rule fillets -> FUSION_API_ERROR "not available" (nothing changed; use feature_fillet with explicit edges); a failed fillet -> FUSION_API_ERROR, rolled back.

Returns {"feature", "health", "created_bodies", "modified_bodies", "removed_bodies"}.

Example: feature_rule_fillet(faces=[], radius=1)

Inputs: faces (required), radius (required), rule, units, +1 more.

feature_shellA

Hollow a body into a shell with walls of the given thickness.

Pass faces to remove (an open box: its top face) OR bodies (a closed hollow body), and inside_thickness and/or outside_thickness. Units: thicknesses in units (default mm) or Fusion expressions. The shelled bodies are listed in modified_bodies.

Errors: no faces and no bodies, both, or no thickness -> INVALID_PARAMS (nothing changed); walls Fusion cannot build (too thick) -> FUSION_API_ERROR, rolled back.

Returns {"feature", "health", "created_bodies", "modified_bodies", "removed_bodies"}.

Example: feature_shell(faces=[], inside_thickness=3)

Inputs: faces, units, bodies, tangent_chain, +2 more.

feature_sweepA

Sweep sketch profiles or planar faces along a path - pipes, handles, springs (with twist), rails, swept cuts (operation="cut").

Units: angles in degrees (a string is a Fusion expression, e.g. "pitch_angle"); path_extent is a plain share of the path length; units only applies to {"sketch", "point"} profile specs. Refs: profiles from sketch_draw / sketch_profiles; path and guide rail from sketch_draw (sketch curve refs, the path sketch usually lies on a plane perpendicular to the profile sketch) or BRep edges from inspect_query. Do not mix sketch curves and edges in one path. With path_chain=true one curve is enough to take the whole connected chain. is_solid=false sweeps a surface (new_body / new_component only); the profile may then be open sketch curves or edges.

Rules: twist_angle / taper_angle with guide_rail -> INVALID_PARAMS; path_extent outside (0, 1] -> rejected; a path with gaps -> FUSION_API_ERROR. A feature Fusion computes with an error -> FUSION_API_ERROR and the timeline is rolled back; a warning keeps the feature and is reported in health.

Returns {"feature": {ref, type, name}, "health": {"state": ok|warning|error|unknown, "message"}, "created_bodies": [{ref, type, name}], "modified_bodies": [{ref, type, name}], "removed_bodies": [<refs of bodies consumed by join/cut>], "component"?: {ref, type, name} (new_component only)}.

Examples:

  • feature_sweep(profiles=["profile:@0,0"], path=[, ])

  • feature_sweep(profiles=[...], path=[], twist_angle=360)

  • feature_sweep(profiles=[...], path=[], guide_rail=[], rail_scaling="stretch")

Inputs: path (required), profiles (required), flip, units, +10 more.

feature_threadA

Add a cosmetic (default) or modeled thread to cylindrical faces - bolts, shafts, tapped holes made earlier.

Hole wall vs shaft is detected from the face orientation (override with internal). Without designation Fusion recommends one from the cylinder diameter (a 10 mm shaft -> M10x1.5 class 6g) and the result says which; without thread_class the first class offered for the designation is used. Strings (type, designation, class) are Fusion's own names - list them with feature_thread_options. Units: length/offset in units (default mm).

Errors: a planar or conical face, faces mixing holes and shafts, an unknown type/designation/class (details.available lists valid ones), length with full_length=true -> INVALID_PARAMS (nothing changed); a thread Fusion computes with an error -> FUSION_API_ERROR and the timeline is rolled back.

Returns {"feature": {ref, type, name}, "health": {"state", "message"}, "created_bodies": [], "modified_bodies": [...] (modeled threads), "removed_bodies": [], "thread": {"type", "designation", "class", "internal", "modeled"}}.

Examples:

  • feature_thread(faces=[])

  • feature_thread(faces=[], designation="M8x1.25", modeled=true, full_length=false, length=12)

Inputs: faces (required), units, length, offset, +7 more.

feature_thread_optionsA

Look up Fusion's thread data (read-only) - which strings feature_thread and feature_hole(thread=...) accept.

Levels: no arguments -> {"thread_types"}; thread_type -> {"sizes"}; + size -> {"designations"}; + designation -> {"classes"} (internal or external); diameter (in units, with internal=true for a hole's bore / tap drill, false for a shaft) -> {"recommended": {"designation", "class"} or null}. size, designation and diameter without thread_type use "ISO Metric profile". diameter cannot be combined with size or designation.

Errors: an unknown type, size or designation -> INVALID_PARAMS with details.available.

Examples:

  • feature_thread_options(thread_type="ISO Metric profile")

  • feature_thread_options(diameter=8, internal=false)

  • feature_thread_options(designation="M6x1", internal=true)

Inputs: size, units, diameter, internal, +2 more.

feature_webA

Add a web - a network of thin walls from several open sketch curves (e.g. a grid of stiffeners inside a shelled housing), joined to the body it meets.

Units: thickness and depth.distance are in units (default mm), a string is a Fusion expression. Refs: open sketch curves from sketch_draw, all in one sketch inside the body; circles and closed splines are refused. Always joined to target_body (no operation parameter); without it, to the one solid body of the curves' component that a curve touches.

Errors: closed curve, wrong thickness_location or depth -> INVALID_PARAMS (nothing changed); no target_body and the curves touch no body or several -> INVALID_PARAMS with details.candidates (body refs to pass as target_body); thickness_location "side2" is not available in the current Fusion API (FUSION_API_ERROR, no change); a Fusion API version without web features -> FUSION_API_ERROR "not available" with no change (use execute_python then); a web Fusion computes with an error -> FUSION_API_ERROR and the timeline is rolled back.

Returns {"feature": {ref, type, name}, "health": {"state": ok|warning|error|unknown, "message"}, "created_bodies": [...], "modified_bodies": [{ref, type, name}] (the body the web joins), "removed_bodies": [...]}.

Example: feature_web(curves=[, , ], thickness=2, depth={"type": "distance", "distance": 15})

Inputs: curves (required), thickness (required), flip, depth, +3 more.

form_convert_to_brepA

Make an independent B-Rep copy of a T-spline body's B-Rep (in a base feature in a parametric design) - the solid for further features (shell, fillet, join).

The copy is independent: later edits of the form do NOT change it, and the form stays in the timeline (hidden by default). The Fusion API has no "Convert" command.

Errors: a T-spline body without a B-Rep (e.g. an open or broken mesh) -> FUSION_API_ERROR, nothing left.

Returns {"body": ref of the new B-Rep body, "name", "source": T-spline body ref, "base_feature": ref | null, "is_solid": bool}.

Inputs: body (required), name, hide_form.

form_creaseA

Crease (sharp) or uncrease (smooth) control-mesh edges of a T-spline body; the B-Rep is regenerated.

Control-mesh edges have no stable ids: pick them by points (mm by default) - take the exact edge midpoints from form_inspect. A point with no edge within tolerance, or equally near two edges (symmetric meshes), fails with INVALID_PARAMS and details.nearest; nothing is changed. On error the crease flags already changed are restored.

Returns {"body": , "changed": number of edges whose flag changed}.

Inputs: body (required), near (required), units, creased, +1 more.

form_create_from_tsmA

Create a T-spline body from TSM (T-spline mesh) text or a .tsm file - exactly one of tsm and path.

This is the way to complex control-mesh edits the Fusion API lacks: form_get_tsm -> change the text -> form_create_from_tsm (then hide or delete the old form).

Errors: both / neither input, a path that is not absolute / missing / not .tsm, text over 8 MiB -> INVALID_PARAMS; TSM Fusion cannot read -> FUSION_API_ERROR "invalid TSM" (nothing is left).

Returns {"form": ref, "body": , "created_form": bool}.

Inputs: tsm, form, name, path, +1 more.

form_create_primitiveA

Create a T-spline primitive body (Form environment) with its control mesh.

Sizes per shape (numbers in units): box: x_size, y_size, z_size (x_faces, y_faces, z_faces); plane: x_size, y_size (x_faces, y_faces); cylinder: radius, height (radial_faces, length_faces); sphere: radius (longitude_faces, latitude_faces); torus: major_radius, minor_radius < major_radius (major_faces, minor_faces); quadball: radius (faces). Face counts default to Fusion's. A parameter of another shape -> INVALID_PARAMS.

T-spline primitives are NOT parametric: sizes are numbers, not expressions or user parameters (a string -> INVALID_PARAMS), and the body does not follow parameter changes. Shape it afterwards with form_move / form_crease / form_insert_edge, get a solid with form_convert_to_brep. Pull, Bridge, Fill Hole, Weld, Subdivide and the like have no Fusion API: read the TSM (form_get_tsm), edit it and create the body again (form_create_from_tsm).

Returns {"form": ref, "body": , "created_form": bool}; the body has a B-Rep ("brep_body") once Fusion regenerated it - a body without one fails (rolled back).

Example: form_create_primitive(shape="box", x_size=40, y_size=20, z_size=10, x_faces=4)

Inputs: shape (required), form, name, faces, +23 more.

form_get_tsmA

Read the TSM (T-spline mesh) description of a T-spline body: the text (up to 1 MiB) or, with path, a .tsm file. Changes nothing in the design.

Errors: text over 1 MiB without path -> INVALID_PARAMS "use path"; a path that is not absolute / not .tsm / whose folder is missing, an existing file without overwrite=true -> INVALID_PARAMS.

Returns {"body", "tsm", "size_bytes"} or {"body", "files": [{"path", "size_bytes"}]}.

Inputs: body (required), path, overwrite.

form_insert_edgeA

Insert edges next to control-mesh edges of a T-spline body (more faces where detail is needed); the B-Rep is regenerated.

Uses the preview Fusion API (FormFeature.insertEdge): when it is missing the tool fails with FUSION_API_ERROR reason=api_unavailable (nothing changed). The edges must be of one loop, else Fusion refuses (FUSION_API_ERROR).

Control-mesh edges have no stable ids: pick them by points (mm by default) - take the exact edge midpoints from form_inspect. A point with no edge within tolerance, or equally near two edges (symmetric meshes), fails with INVALID_PARAMS and details.nearest; nothing is changed.

Returns {"body": , "changed": selected edges, "new_edges": n}.

Inputs: body (required), near (required), mode, units, +3 more.

form_inspectA

Read the control mesh of a T-spline body in mm; changes nothing.

The positions are what form_move / form_crease / form_insert_edge match their near points to: vertex "position" (control point), edge "midpoint", face "center".

Returns {"body": , "vertices": [{"position", "smooth_position"}], "edges": [{"midpoint", "start", "end", "is_creased", "is_degenerate"}], "faces": [{"center", "vertex_count"}], "_truncated": bool, "truncated": bool}.

Inputs: body (required), limit, include.

form_listA

List the form (T-spline) features of the design or one component with their T-spline bodies; changes nothing.

Returns {"forms": [{"feature": ref, "name", "component", "health": {"state", "message"}, "bodies": []}], "count"};

Inputs: component.

form_moveA

Move control-mesh vertices or faces of a T-spline body, or the whole body, by a vector; the B-Rep is regenerated.

Control-mesh vertices and faces have no stable ids: pick them by points (mm by default) - take the exact positions for near from form_inspect (vertex position, face center). A point with no element within tolerance, or equally near two elements (symmetric meshes), fails with INVALID_PARAMS and details.nearest; nothing is changed. On a symmetric body Fusion mirrors the move to the symmetric elements.

Errors: zero vector, missing near for vertex/face -> INVALID_PARAMS. If a move fails midway, the elements already moved are moved back.

Returns {"body": , "changed": n}.

Example: form_move(body="", kind="face", near=[[5, 5, 20]], vector=[0, 0, 5])

Inputs: body (required), kind (required), vector (required), near, +2 more.

fusion_statusA

Check that Fusion 360 and the FusionMCP add-in are reachable; call this first.

Returns JSON with:

  • fusion_version: Fusion build, e.g. "2.0.21000"

  • addin_version: FusionMCP add-in version

  • python_version: Python inside Fusion

  • document: name of the active document, or null when none is open

  • design_type: "parametric" (has a timeline; failed tools roll back), "direct", or null when the active document is not a design

  • units: the design's default length unit ("mm", "cm", "in", ...); tool inputs are still millimetres unless a tool takes an explicit units

When Fusion or the add-in is not running the result is an error starting with NOT_CONNECTED and says how to fix it. After a TIMEOUT from another tool, call this before retrying: the timed-out operation may still be running in Fusion.

Inputs: no named parameters.

import_fileA

Import a CAD file (STEP, IGES, SAT, SMT, F3D) or a mesh (STL, OBJ, 3MF) into a component of the active design. CAD files usually arrive as a new occurrence, meshes as mesh bodies. A failed import leaves the design as it was.

Returns {"format", "target", "created": {"occurrences": [ref], "bodies": [ref], "mesh_bodies": [ref]}}.

Example: import_file(path="C:/in/bolt.step").

Inputs: path (required), format, target, mesh_units.

inspect_bounding_boxA

World-axis bounding boxes in mm. Tight (exact) boxes come from Fusion's measure manager; when it cannot compute one the looser boundingBox is used and the item has "tight": false. Components and occurrences are the union of their bodies.

Returns {"items": [{"ref", "min_mm", "max_mm", "size_mm", "tight"}], "union": {"min_mm", "max_mm", "size_mm"} | null, "errors": [...]}.

Example: inspect_bounding_box() -> overall size of the model in union.size_mm.

Inputs: refs.

inspect_describeA

Describe entities by ref: faces (surface type, area_mm2, centroid_mm, outward normal, geometry such as cylinder radius/axis), edges (curve type, length_mm, ends, adjacent faces), vertices, bodies (volume, area, bbox, material), components, occurrences (transform), sketches, construction geometry and features (health).

Units: mm, mm², mm³, degrees; directions are unit vectors. Accepts origin:XY etc. A ref that does not resolve goes to errors and does not fail the call.

Returns {"items": [...], "errors": [{"ref", "code", "message"}]}.

Example: inspect_describe(refs=["origin:xy", ""], detail="brief").

Inputs: refs (required), detail.

inspect_physical_propertiesB

Mass properties: mass_kg, volume_mm3, area_mm2, density_kg_m3, center_of_mass_mm (assembly coordinates for occurrences), inertia_kg_mm2 {xx, yy, zz, xy, yz, xz} about the world origin, principal_moments_kg_mm2 and the material name. Moments Fusion cannot compute are null.

Returns {"items": [...], "errors": [...]}.

Example: inspect_physical_properties(refs=[""]) -> check the volume.

Inputs: refs, accuracy.

inspect_queryA

Find faces, edges, vertices or bodies by geometry instead of writing code. All given filters must match; results are brief descriptions with refs (lengths mm, areas mm²). Filters only apply to their kind (e.g. surface_type needs kind="face") — a wrong combination or min > max fails with INVALID_PARAMS.

Returns {"items": [...], "total": , "truncated": bool}. On large models narrow scope to one body.

Examples:

  • largest face: inspect_query(kind="face", sort_by="area", limit=1)

  • planar faces facing +Z: inspect_query(kind="face", surface_type="plane", normal=[0, 0, 1])

  • edges longer than 25 mm of one body: inspect_query(kind="edge", scope=[""], length_min_mm=25)

  • 10 mm holes: inspect_query(kind="face", surface_type="cylinder", radius_min_mm=4.9, radius_max_mm=5.1)

  • vertical edges: inspect_query(kind="edge", curve_type="line", direction=[0, 0, 1])

Inputs: kind (required), axis, limit, order, +15 more.

inspect_treeA

Model tree of the active design: bodies, sketches, construction geometry, timeline features (with health) and nested occurrences, each with a stable ref.

Start here to find what to work on. Every node is a brief description (lengths mm, areas mm², volumes mm³). Origin planes/axes/point are addressed as origin:XY, origin:XZ, origin:YZ, origin:X, origin:Y, origin:Z, origin:O and are not listed. Direct (non-parametric) designs have features: [].

Returns {"design_type": "parametric"|"direct", "root": {...component node with "bodies", "sketches", "construction", "features", "occurrences"}, "item_count", "truncated"}; when truncated is true narrow component/depth/include.

Example: inspect_tree(include=["bodies", "features"]).

Inputs: depth, include, component, max_items.

material_assignA

Assign a physical material (density, mass) to a body, a component or an occurrence. An occurrence has no own material: the material is set on its component and so applies to all occurrences of that component. Take the id from material_list; a name found in several libraries fails with details.candidates. Check the new mass with inspect_physical_properties afterwards.

Returns {"target", "applied_to", "material": {"id", "name", "library"}, "previous": {...} | null} (+ "note" for an occurrence).

Example: material_assign(target="", material="").

Inputs: target (required), material (required), library.

material_getA

Physical material and appearance of a body, a component or an occurrence (an occurrence reports its component's material and its own appearance override).

Returns {"target", "material": {"id", "name", "library"} | null, "appearance": {...} | null}.

Example: material_get(target="").

Inputs: target (required).

material_listA

Physical materials of one library, of every library (default) or of the design (in_design=true), filtered by a name substring and paginated.

Returns {"items": [{"id", "name", "library"}], "total", "truncated"}; "library" is the library name or "design". Names are localized and not unique: pass the "id" to material_assign.

Example: material_list(query="steel", limit=10).

Inputs: limit, query, offset, library, +1 more.

material_list_librariesA

Loaded material libraries (physical materials and appearances).

Returns {"libraries": [{"id", "name", "is_native", "material_count", "appearance_count"}]}.

Example: material_list_libraries() -> pick a library for material_list(library=...).

Inputs: no named parameters.

measure_angleA

Angle in degrees between two entities (faces, edges, axes, planes), or — with three operands — the angle at vertex b of the points/entities a-b-c.

Returns {"angle_deg"}.

Examples: measure_angle(a="", b="origin:XY"); measure_angle(a=[10, 0, 0], b=[0, 0, 0], c=[0, 10, 0]) -> 90.

Inputs: a (required), b (required), c.

measure_distanceA

Minimum distance between two entities or points, in mm.

Each operand is a ref from another tool or a point [x, y, z] in mm. Returns {"distance_mm", "point_a_mm", "point_b_mm"}: the closest points on each operand (null when Fusion does not report them).

Example: measure_distance(a="", b="") -> height.

Inputs: a (required), b (required).

parameter_createA

Create user parameters in order (later ones may use earlier ones). All or nothing: names are checked first (pattern, not existing, no duplicates) and a Fusion error on any item removes the ones already created.

expression is a Fusion expression string ("40 mm", "width / 2") or a number in unit (default mm): 40 -> "40 mm". Use unit "deg" for angles and "" for counts.

Returns {"parameters": [...as in parameter_list], "warnings": [features that newly show a warning]}.

Example: parameter_create(parameters=[{"name": "width", "expression": 40}, {"name": "half", "expression": "width / 2"}]).

Inputs: parameters (required).

parameter_deleteA

Delete user parameters, all or nothing. Model parameters cannot be deleted. A parameter still used by another parameter outside the list (or by features) is refused with INVALID_PARAMS and details.dependents; delete or change those first, or include them in names.

Returns {"deleted": [names], "warnings": [...]}.

Example: parameter_delete(names=["half", "width"]).

Inputs: names (required).

parameter_listA

List parameters of the active design.

Each item: {"ref": "param:", "name", "kind": "user"|"model", "expression", "unit", "value" (lengths in mm, angles in degrees, unitless as is; missing for other units), "value_unit": "mm"|"deg"|"", "display" (Fusion's formatted value), "comment", "is_favorite", "created_by": {"ref", "type", "name"} | null (the feature that owns a model parameter), "role", "component", "dependents" (only with include_dependents)}.

Returns {"parameters": [...]}.

Example: parameter_list(kind="model") -> find d1 of an extrude to drive it.

Inputs: kind, component, name_contains, include_dependents.

parameter_updateA

Change expression, name, comment or favourite flag of user and model parameters — e.g. drive an extrude by setting its model parameter d1 to "width * 2".

All or nothing: if any change fails, or puts a timeline feature into the error state, every parameter keeps its previous values and the call fails with FUSION_API_ERROR and details.failed_features. Renaming updates the expressions that use the parameter.

Returns {"parameters": [...as in parameter_list], "warnings": [...]}.

Example: parameter_update(parameters=[{"name": "d1", "expression": "width * 2"}]).

Inputs: parameters (required).

pattern_circularA

Circular pattern: copy features, bodies, faces or occurrences around an axis.

Instances are spread evenly over total_angle (degrees, default 360 = full circle). Refs: bodies/faces from inspect_query, features from earlier feature_* results, the axis from origin:X|Y|Z, construction_* or inspect_query (a cylindrical face uses its axis). All entities must be of one kind.

Errors: mixed kinds, quantity < 1, a non-axis ref -> INVALID_PARAMS (nothing changed); a pattern Fusion cannot compute -> FUSION_API_ERROR, rolled back.

Returns {"feature", "health", "created_bodies", "modified_bodies", "removed_bodies"} (+ "created_occurrences" for occurrence input).

Example: pattern_circular(entities=[], axis="origin:Z", quantity=6)

Inputs: axis (required), entities (required), quantity (required), compute, +2 more.

pattern_mirrorA

Mirror features, bodies, faces or occurrences across a plane.

With combine=true (body input only) every mirrored body is joined with its original (a symmetric part from one half); the originals are then in modified_bodies. Refs: planes from origin:XY|XZ|YZ, construction_* or a planar face from inspect_query.

Errors: mixed kinds, combine with non-body input, a non-planar ref -> INVALID_PARAMS (nothing changed); a mirror Fusion cannot compute -> FUSION_API_ERROR, rolled back.

Returns {"feature", "health", "created_bodies", "modified_bodies", "removed_bodies"} (+ "created_occurrences" for occurrence input).

Example: pattern_mirror(entities=[], plane="origin:YZ", combine=true)

Inputs: plane (required), entities (required), combine, compute.

pattern_pathA

Path pattern: copy features, bodies, faces or occurrences along a path of sketch curves or edges.

Units: distance in units (default mm) or an expression; start is a share of the path length. Refs: curves from sketch_* results, edges from inspect_query. All entities must be of one kind.

Errors: mixed kinds, a path mixing curves and edges, start outside 0..1 -> INVALID_PARAMS (nothing changed); a path with gaps or a pattern Fusion cannot compute -> FUSION_API_ERROR, rolled back.

Returns {"feature", "health", "created_bodies", "modified_bodies", "removed_bodies"} (+ "created_occurrences" for occurrence input).

Example: pattern_path(entities=[], path=[], quantity=4, distance=100, orientation_along_path=true)

Inputs: path (required), distance (required), entities (required), quantity (required), +8 more.

pattern_rectangularA

Rectangular pattern: copy features, bodies, faces or occurrences along one or two directions.

Quantities count the original (quantity1=3 -> the original + 2 copies). Units: distances in units (default mm) or Fusion expressions; quantities are whole numbers or expressions. Refs: bodies/faces from inspect_query, features from earlier feature_* results, directions from inspect_query edges, construction_* axes or origin:X|Y|Z. All entities must be of one kind (Fusion requirement).

Errors: mixed kinds (details.kinds), quantity < 1, direction2 with quantity2 > 1 but no distance2 -> INVALID_PARAMS (nothing changed); a pattern Fusion cannot compute -> FUSION_API_ERROR, rolled back.

Returns {"feature": {ref, type, name}, "health": {"state", "message"}, "created_bodies": [{ref, type, name}], "modified_bodies": [...], "removed_bodies": [tokens]} plus "created_occurrences": [{ref, type, name, full_path_name}] for occurrence input.

Example: pattern_rectangular(entities=[], direction1="origin:X", quantity1=3, distance1=30, direction2="origin:Y", quantity2=2, distance2=25)

Inputs: entities (required), distance1 (required), direction1 (required), units, +8 more.

sheet_metal_assign_ruleA

Make a rule the active sheet metal rule of a component (default: root).

A library rule is first copied into the design (the design never references the library). Fusion may refuse a rule on a component without sheet metal data (FUSION_API_ERROR) - then pass rule to the first flange tool instead. On error the previous rule is restored and a copy made by the call is deleted.

Returns {"component", "rule": , "previous": name | null, "copied_from_library": bool}.

Inputs: rule (required), source, component.

sheet_metal_base_flangeA

Base flange: a flat sheet metal body from closed profiles; the thickness comes from the active rule.

Recommended order: rule (sheet_metal_create_rule / rule) -> base or contour flange -> sheet_metal_edge_flange -> sheet_metal_create_flat_pattern -> sheet_metal_export_flat_pattern. Bend along a sketch line is not available in the Fusion API: model bends with edge or contour flanges.

Uses the preview Fusion API: when it is missing the tool fails with FUSION_API_ERROR reason=api_unavailable (nothing changed) - check sheet_metal_capabilities first.

Returns {"feature", "health", "created_bodies": [{ref, type, name, is_sheet_metal}], "modified_bodies", "removed_bodies", "rule": active rule name}.

Inputs: profiles (required), rule, operation, orientation, +1 more.

sheet_metal_capabilitiesA

Report which sheet metal operations this Fusion API supports; changes nothing.

Call it before a sheet metal workflow: flanges, unfold/refold, convert, bend listing and STEP export of a flat pattern use the preview Fusion API, which may be missing. sketch_bend is always false: Fusion has no API for Bend along a sketch line - model the bend with sheet_metal_edge_flange or sheet_metal_contour_flange instead.

Returns {"rules", "flat_pattern", "flat_pattern_dxf", "flat_pattern_step", "convert", "base_flange", "contour_flange", "edge_flange", "list_bends", "unfold", "refold": bool, "sketch_bend": false, "preview_apis": [...], "fusion_version", "notes"}.

Inputs: no named parameters.

sheet_metal_contour_flangeA

Contour flange: a bent sheet metal body from an open sketch profile (the profile is the bend line shape, the thickness and radius come from the rule).

Recommended order: rule -> contour flange (e.g. an L-shaped open sketch, c05 sketch_draw lines) -> sheet_metal_edge_flange on its outer edges (inspect_query) -> sheet_metal_list_bends / unfold / refold -> sheet_metal_create_flat_pattern -> sheet_metal_export_flat_pattern. Bend along a sketch line is not available in the Fusion API: add bends with edge flanges or draw them into the contour.

Uses the preview Fusion API: when it is missing the tool fails with FUSION_API_ERROR reason=api_unavailable (nothing changed) - check sheet_metal_capabilities first.

Errors: two_sides without distance_two or distance_two with another direction -> INVALID_PARAMS; a failing flange is rolled back and the previous rule restored.

Returns {"feature", "health", "created_bodies": [{ref, type, name, is_sheet_metal}], "modified_bodies", "removed_bodies", "rule"}.

Example: sheet_metal_contour_flange(profiles=["", ""], distance=40)

Inputs: distance (required), profiles (required), rule, units, +6 more.

sheet_metal_convertA

Convert a solid plate body to sheet metal from a planar base face.

The body thickness should match the rule thickness. Use it for a plate built with feature_extrude.

Uses the preview Fusion API: when it is missing the tool fails with FUSION_API_ERROR reason=api_unavailable (nothing changed) - check sheet_metal_capabilities first.

Errors: body already sheet metal, face of another body, non-planar face -> INVALID_PARAMS; Fusion refusing the conversion -> FUSION_API_ERROR (rolled back, the previous rule restored).

Returns {"body": ref (may differ from the input), "component", "rule": , "is_sheet_metal": true}.

Inputs: body (required), base_face (required), rule, rule_source.

sheet_metal_create_flat_patternA

Create the flat pattern of the component of a sheet metal body (one per component) and return its size, thickness and bends. The design workspace is active again afterwards.

Errors: a face of a non-sheet-metal body, an existing flat pattern without replace=true -> INVALID_PARAMS (the existing one is kept). replace=true is atomic: if the new flat pattern fails, the old one is recreated from its remembered stationary face. A flat pattern not made by this tool (or whose face changed) cannot be restored, so replace refuses it (INVALID_PARAMS reason=not_restorable, nothing changed) - delete it with sheet_metal_delete_flat_pattern first.

Returns {"component", "exists": true, "size_mm": [x, y], "thickness_mm", "bend_count", "bends": [{"angle_deg", "is_up"}], "replaced"}.

Inputs: stationary_face (required), replace.

sheet_metal_create_ruleA

Create a design sheet metal rule by copying a base rule and setting values.

Units: a plain number is in units (default mm); a string is a Fusion expression and may use Thickness ("Thickness * 1.5") - write units in expressions ("2 mm"), a rule in inches reads bare numbers as inches. The rule is not used until sheet_metal_assign_rule or the rule argument of a flange tool.

Errors: name already in the design, k_factor outside 0..1, a negative length -> INVALID_PARAMS; unknown base_rule -> ENTITY_NOT_FOUND. On any error no rule is left.

Returns {"rule": , "base": {"name", "source"}}.

Example: sheet_metal_create_rule(name="Steel 2mm", thickness=2, bend_radius="Thickness * 1", k_factor=0.44, relief_shape="round")

Inputs: name (required), gap, units, k_factor, +8 more.

sheet_metal_delete_flat_patternB

Delete a component's flat pattern.

Errors: no flat pattern -> ENTITY_NOT_FOUND.

Returns {"component", "deleted": true}.

Inputs: component.

sheet_metal_edge_flangeA

Edge flange: bend up a wall from linear edges of a sheet metal body.

Exactly one of height and to_entity. Refs: edges from inspect_query on the latest body (refs change after every flange - take them from the results again). Bend along a sketch line is not available in the Fusion API: an edge flange is the way to add a bend.

Uses the preview Fusion API: when it is missing the tool fails with FUSION_API_ERROR reason=api_unavailable (nothing changed) - check sheet_metal_capabilities first.

Errors: both / neither of height and to_entity, to_entity with several edges, an edge of a non-sheet-metal body or of several bodies, a non-linear edge -> INVALID_PARAMS; a failing flange is rolled back.

Returns {"feature", "health", "created_bodies", "modified_bodies": [{ref, type, name, is_sheet_metal}], "removed_bodies", "rule"}.

Example: sheet_metal_edge_flange(edges=[""], height=20)

Inputs: edges (required), flip, angle, units, +8 more.

sheet_metal_export_flat_patternA

Export a component's flat pattern to DXF (bend / extent lines, file units, optional spline-to-polyline) or STEP. STEP uses the preview Fusion API (api_unavailable when missing; see sheet_metal_capabilities).

The path must be absolute with a matching extension; an existing file is replaced only with overwrite=true. Errors: no flat pattern -> ENTITY_NOT_FOUND (create it with sheet_metal_create_flat_pattern).

Returns {"files": [{"path", "size_bytes"}], "format", "scope": component}.

Example: sheet_metal_export_flat_pattern(path="C:/out/bracket.dxf")

Inputs: path (required), units, format, component, +6 more.

sheet_metal_get_flat_patternA

Read a component's flat pattern: size, thickness and bends, or exists=false.

Returns {"component", "exists", "size_mm", "thickness_mm", "bend_count", "bends"}.

Inputs: component.

sheet_metal_list_bendsA

List the bends of a sheet metal body: inner and outer bend face refs and the inner radius in mm (use the faces for sheet_metal_unfold).

Uses the preview Fusion API: when it is missing the tool fails with FUSION_API_ERROR reason=api_unavailable (nothing changed) - check sheet_metal_capabilities first.

Returns {"body", "bends": [{"inner", "outer", "radius_mm"}], "count"}.

Inputs: body (required).

sheet_metal_list_rulesA

List sheet metal rules: thickness, bend radius, gap and relief sizes in mm with their expressions, K-factor and relief shape.

Returns {"rules": [{"name", "source", "units", "thickness": {"mm", "expression"}, "bend_radius", "gap", "relief_width", "relief_depth", "relief_remnant", "k_factor", "relief_shape", "is_default" (library) | "is_used" (design)}], "count"}.

Inputs: source.

sheet_metal_refoldA

Refold the bends of an unfold feature.

Uses the preview Fusion API: when it is missing the tool fails with FUSION_API_ERROR reason=api_unavailable (nothing changed) - check sheet_metal_capabilities first.

Errors: a ref that is not an UnfoldFeature -> INVALID_PARAMS.

Returns {"feature", "health", "created_bodies", "modified_bodies", "removed_bodies", "rule"}.

Inputs: unfold (required).

sheet_metal_unfoldA

Unfold all bends (or the given bend faces from sheet_metal_list_bends) of a sheet metal body about a stationary face, e.g. to add cuts across a bend; refold with sheet_metal_refold.

Uses the preview Fusion API: when it is missing the tool fails with FUSION_API_ERROR reason=api_unavailable (nothing changed) - check sheet_metal_capabilities first.

Returns {"feature": {ref of the UnfoldFeature, ...}, "health", "created_bodies", "modified_bodies", "removed_bodies", "rule"}.

Inputs: stationary_face (required), bend_faces.

sketch_constrainA

Add geometric constraints in order, all or nothing.

Entities are refs from earlier results (sketch_draw refs, sketch_get) or origin. Types: coincident (point, entity) | horizontal / vertical (line, or points: [p1, p2]) | parallel / perpendicular / collinear (line1, line2) | tangent / equal / concentric (curve1, curve2) | midpoint (point, curve) | symmetry (entity1, entity2, line) | smooth (spline, curve) | fix (entity, fixed=true — sets isFixed, no constraint ref). Wrong entity types fail with INVALID_PARAMS (details.expected); an over-constrained sketch fails with FUSION_API_ERROR and details.index; nothing is kept on failure.

Returns {"constraints": [{ref, type}], "status", "profiles"}.

Example: sketch_constrain(sketch=, constraints=[{"type": "horizontal", "points": [, ]}, {"type": "equal", "curve1": , "curve2": }]).

Inputs: sketch (required), constraints (required), return_profiles.

sketch_createA

Create a 2D sketch on an origin plane, a construction plane or a planar face.

All sketch tools work in SKETCH SPACE, mm: [x, y] on the sketch plane. Fusion picks the sketch axes; the result transform = {origin, x_axis, y_axis, normal} (model mm and unit vectors) maps them: model = origin + xx_axis + yy_axis. Pitfall: on origin:XZ the sketch Y axis is model -Z (so a point drawn at y = 10 is at model z = -10) — always read transform, or give points as {"model": [x, y, z]} to sketch_draw. On origin:XY sketch x/y = model x/y.

A planar face gives a clean sketch unless project_edges=true. A non-planar face fails with INVALID_PARAMS (details.reason = "face_not_planar").

Returns {"sketch": {ref}, "name", "plane", "component", "transform"}.

Example: sketch_create(plane="origin:XY", name="Base") then sketch_draw(sketch=).

Inputs: plane (required), name, component, project_edges.

sketch_deleteA

Delete sketch entities (not the sketch itself).

All refs are checked first: a stale or foreign ref fails with ENTITY_NOT_FOUND / INVALID_PARAMS and nothing is deleted. Then dimensions, constraints, texts, curves and points are deleted in that order; entities Fusion already removed with another one (e.g. a constraint of a deleted line) are listed in cascaded.

NOT ATOMIC (the only such sketch tool): Fusion cannot undo a deletion. If Fusion itself fails in the middle of the batch, the entities deleted so far stay deleted — the error is FUSION_API_ERROR with details.deleted; re-read the sketch with sketch_get before continuing.

Returns {"deleted": [refs], "cascaded": [refs], "status", "profiles"}.

Example: sketch_delete(sketch=, entities=[, ]).

Inputs: sketch (required), entities (required), return_profiles.

sketch_dimensionA

Add driving or driven dimensions in order, all or nothing — this is how sizes become exact and parametric.

value: a number is mm (degrees for angular) -> "25 mm"; a string is a Fusion expression kept as is ("plate_w * 0.6", "wall + 2 mm"); invalid expressions fail with INVALID_PARAMS before anything is created. parameter_name renames the dimension's parameter so later dimensions (in this call too) and parameter_update can use it. driven=true makes a reference dimension that only measures (no value). Types: distance (line, or point1 + point2; orientation aligned|horizontal|vertical) | offset (line, entity: parallel line or point) | radial / diameter (curve) | angular (line1, line2; text_at picks the measured quadrant) | ellipse_major / ellipse_minor (ellipse).

Returns {"dimensions": [{ref, type, value, unit, expression, parameter, driving}], "status", "profiles"}.

Example: sketch_dimension(sketch=, dimensions=[{"type": "distance", "line": , "value": 100, "parameter_name": "plate_w"}, {"type": "radial", "curve": , "value": "plate_w / 20"}]).

Inputs: sketch (required), dimensions (required), units, return_profiles.

sketch_dimension_setA

Change existing dimensions: value/expression, driven state or parameter name. All or nothing: if any update fails the earlier ones get their previous values back.

value: number = mm/degrees, string = expression. Changing a dimension re-solves the sketch; profile refs taken before stay usable for moderate changes (re-read with sketch_profiles(contains=...) if a feature reports ENTITY_NOT_FOUND).

Returns {"dimensions": [...as in sketch_dimension], "status", "profiles"}.

Example: sketch_dimension_set(sketch=, updates=[{"dimension": , "value": "plate_w + 10"}]).

Inputs: sketch (required), updates (required), return_profiles.

sketch_drawA

Draw many sketch items, then constraints, then dimensions — one call, all or nothing (on any error the sketch is restored and details = {phase: geometry|constraints|dimensions, index, id}).

Coordinates: [x, y] sketch mm (numbers only — expressions like "w/2" are refused: draw approximately and fix exact sizes with dimensions), {"model": [x, y, z]} model mm (projected on the sketch plane; mind sketch_create's XZ pitfall), or a ref of an existing point / curve end. A point given by ref is shared (no coincident needed).

Local ids: give an item id (letters, digits, _; not origin) and later items, constraints and dimensions of THIS call can use id or id.<sub>; origin is the sketch origin point. Local ids live one call only: the result refs maps every local path to a real ref — use those refs in later calls.

Every item: {"kind", "id"?, "construction": false, ...}: | kind / mode | fields | sub-ids | | point | at | — | | line | start, end | start, end | | polyline | points (≥2), closed=false | e0..e{n-1} (edges), v0..v{n-1} | | rectangle two_point (default) | corner1, corner2 | bottom,right,top,left, bl,br,tr,tl | | rectangle center | center, corner | as two_point + center, diagonal | | rectangle three_point | p1, p2, p3 | e0..e3, v0..v3 | | circle center_radius (default) | center, radius | center | | circle two_point | p1, p2 (diameter ends) | center | | circle three_point | p1, p2, p3 | center | | arc three_point (default) | start, mid, end | start, end, center | | arc center_start_sweep | center, start, sweep (deg, + = CCW) | start, end, center | | arc tangent | from (curve end, e.g. "l1.end"), to | start, end, center | | ellipse | center, major_radius, minor_radius, angle=0 | center | | polygon | center, radius, sides 3..64, mode=inscribed|circumscribed, angle=0, constrain=true | e0.., v0.., center, circle | | spline | points (≥2 fit points), closed=false | start, end, fp0.. | | slot center_to_center (default) / overall | p1, p2, width | side0, side1, end0, end1, axis, c0, c1 | | text | text, height, corner, size=[w,h]?, font?, h_align=left, v_align=bottom | — |

constraints: [{"type": coincident (point, entity) | horizontal / vertical (line, or points [p1, p2]) | parallel / perpendicular / collinear (line1, line2) | tangent / equal / concentric (curve1, curve2) | midpoint (point, curve) | symmetry (entity1, entity2, line) | smooth (spline, curve) | fix (entity, fixed=true)}]. dimensions: [{"type": distance (line, or point1 + point2; orientation=aligned| horizontal|vertical) | offset (line, entity) | radial / diameter (curve) | angular (line1, line2) | ellipse_major / ellipse_minor (ellipse), "value": 25 (mm/deg) or "plate_w * 0.6", "parameter_name"?, "driven"=false, "text_at"?}]. A named dimension (parameter_name) can be used by later dimensions' expressions in the same call.

Returns {"sketch", "refs": {"r": {ref}, "r.bottom": {ref}, ...}, "constraints", "dimensions", "status" {fully_constrained, ...}, "profiles", "warnings"}.

Example — fully constrained 100 x 60 plate centred on the origin with a hole: sketch_draw(sketch=, items=[ {"kind": "rectangle", "mode": "center", "id": "r", "center": "origin", "corner": [50, 30]}, {"kind": "circle", "id": "h", "center": [30, 15], "radius": 4}], dimensions=[ {"type": "distance", "line": "r.bottom", "value": 100, "parameter_name": "plate_w"}, {"type": "distance", "line": "r.left", "value": "plate_w * 0.6"}, {"type": "diameter", "curve": "h", "value": 8}, {"type": "distance", "point1": "origin", "point2": "h.center", "orientation": "horizontal", "value": 30}, {"type": "distance", "point1": "origin", "point2": "h.center", "orientation": "vertical", "value": 15}]) -> status.fully_constrained = true; the plate profile has one inner loop.

Inputs: items (required), sketch (required), units, dimensions, +2 more.

sketch_extendA

Extend the end nearest point to the next intersecting curve. ONE curve per call (the curve may be replaced, so use the refs in the result). point farther than 5 mm from the curve fails with INVALID_PARAMS.

Returns {"created": [refs], "deleted": [the original ref, if replaced], "status", "profiles"}.

Example: sketch_extend(sketch=, curve=, point=[39, 0]).

Inputs: curve (required), point (required), sketch (required), return_profiles.

sketch_filletA

Round ONE corner between two curves with a tangent arc of radius. One corner per call: Fusion trims both curves, so their old refs may become stale — take the new ones from the result or sketch_get before the next fillet. Pick points default to the curves' shared end (or nearest ends).

Not fully atomic: Fusion cannot undo the fillet itself. If the radial dimension (dimension=True) cannot be added, only the dimension is rolled back — the arc stays and the call succeeds with warning fillet_dimension_failed. Dimension the arc yourself with sketch_dimension, or delete it with sketch_delete.

Returns {"arc": {ref}, "dimension"?: {...}, "status", "profiles"}.

Example: sketch_fillet(sketch=, curve1=, curve2=, radius="r_corner").

Inputs: curve1 (required), curve2 (required), radius (required), sketch (required), +4 more.

sketch_getA

Full state of a sketch, coordinates in sketch-space mm.

Sections: points [{ref, xy, fixed, reference, fully_constrained}], curves [{ref, type: line|arc|circle|ellipse|elliptical_arc|fitted_spline|fixed_spline|conic, construction, fixed, reference (projected), fully_constrained, length_mm, start, end, geometry (line {start, end}; circle {center, radius}; arc {center, radius, start, end, start_angle, sweep}; ...)}], constraints [{ref, type, entities}], dimensions [{ref, type, entities, value (mm|deg), unit, expression, parameter, driving}], texts, profiles (as sketch_profiles). Each section is an object {items: [≤ limit entries as above], total, truncated} — truncated: true when cut.

Returns {"sketch", the requested sections, "transform" (see sketch_create), "status": {fully_constrained, under_constrained_count, under_constrained: [≤ 50 refs]}}.

Example: sketch_get(sketch=, include=["dimensions"]) -> find a dimension ref for sketch_dimension_set.

Inputs: sketch (required), limit, include.

sketch_listA

List sketches of the design (or of one component).

Returns {"sketches": [{"sketch": {ref}, "name", "component", "plane", "fully_constrained", "curve_count", "profile_count", "visible"}]}.

Example: sketch_list() -> pick the sketch ref, then sketch_get / sketch_profiles.

Inputs: component.

sketch_mirrorA

Mirror entities about a line, all or nothing. Shared points stay shared and points on the axis are reused; other curve types fail with INVALID_PARAMS.

Returns {"mapping": {: }, "constraints", "status", "profiles"}.

Example: sketch_mirror(sketch=, entities=[, ], axis=).

Inputs: axis (required), sketch (required), entities (required), constrain, +1 more.

sketch_offsetA

Offset curves (with chain=true the whole connected loop) by distance toward side_point. All or nothing.

When the Fusion version supports it the offset is parametric (parametric: true, a dimension carries the distance expression, e.g. "wall"); otherwise plain copies are made (parametric: false).

Returns {"created": [refs], "parametric", "dimension"?, "status", "profiles"}.

Example: inner wall of a closed outline: sketch_offset(sketch=, curves=[], distance="wall", side_point=[0, 0]).

Inputs: curves (required), sketch (required), distance (required), side_point (required), +2 more.

sketch_patternA

Pattern sketch entities, all or nothing. Counts include the original.

  • rectangular: count_x (≥1), spacing_x (Length), count_y=1, spacing_y=0, angle=0 (degrees from sketch X) or direction (a line ref).

  • circular: center (point), count (≥2), angle=360 (total, degrees). Spacing/angle: number = mm/deg, string = expression. When the Fusion version has the pattern constraint the result is parametric (parametric: true, constraint); otherwise plain copies (parametric: false).

Returns {"instances": [[refs]...], "parametric", "constraint"?, "status", "profiles"}.

Example: 6 holes on a circle: sketch_pattern(sketch=, entities=[], kind="circular", center="origin", count=6).

Inputs: kind (required), sketch (required), entities (required), angle, +8 more.

sketch_profilesA

Closed regions (profiles) of a sketch — the input of extrude/revolve/sweep/loft.

Each profile: {"ref": {"ref": "profile:@,", "type": "Profile", "name": "P1"}, "sketch", "point": [x, y] (an interior point of the region), "area_mm2", "centroid", "bbox": {min, max}, "outer_loop": {"curves": [refs]}, "inner_loops": [{"curves": [refs]}] (holes)}. All coordinates sketch mm.

A profile has no persistent id in Fusion, so its ref is the sketch plus a point inside the region: profile:<sketch token>@x,y. Pass this string as the profile of a feature (or {"sketch": ref, "point": [x, y]}). It survives moderate dimension changes; if the region moved away from the point the feature fails with ENTITY_NOT_FOUND listing the current profiles — call sketch_profiles(contains=[x, y]) again and use the new ref. name (P1, P2...) is only the order in this answer, never an address.

Returns {"profiles": [...]}.

Example: plate with 4 holes -> 5 profiles; the plate is the one with 4 inner_loops; sketch_profiles(sketch=, contains=[0, 0]) -> just the region around [0, 0].

Inputs: sketch (required), contains.

sketch_projectA

Bring model geometry into the sketch as reference curves (to dimension or constrain against, or to close profiles). All or nothing.

Modes: project (projection onto the sketch plane; a body projects all its edges), include (linked copy of curves), intersect (intersection of the entities with the sketch plane), cut_edges (section of bodies by the sketch plane).

Returns {"created": {: [refs]}, "status", "profiles"}.

Example: sketch_project(sketch=, entities=[]) -> the face outline as reference curves.

Inputs: sketch (required), entities (required), mode, return_profiles.

sketch_set_constructionA

Turn curves into construction geometry (not part of profiles) or back. All or nothing.

Returns {"curves": [...], "status", "profiles"}.

Example: sketch_set_construction(sketch=, curves=[]) -> the profiles bounded by that line merge.

Inputs: curves (required), sketch (required), construction, return_profiles.

sketch_transformA

Move/rotate sketch entities (or copies of them): rotate by rotate degrees about about, then translate by translate mm. All or nothing.

Entities tied by constraints/dimensions may be pulled back by the solver: the result has the actual solved geometry, check it.

Returns {"entities": [...] (moved) | "created": [...] (copy=true), "status", "profiles"}.

Example: sketch_transform(sketch=, entities=[], translate=[30, 0], copy=true) -> a second circle 30 mm to the right.

Inputs: sketch (required), entities (required), copy, about, +3 more.

sketch_trimA

Trim at the segment nearest point (cut back to the neighbouring intersections). ONE curve per call: trimming replaces the curve and Fusion cannot undo it inside a batch, so the old ref becomes stale — use the refs in the result for the next trim. point farther than 5 mm from the curve fails with INVALID_PARAMS.

Returns {"created": [refs of the remaining pieces], "deleted": [the original ref, if it was replaced], "status", "profiles"}.

Example: sketch_trim(sketch=, curve=, point=[10, 0]).

Inputs: curve (required), point (required), sketch (required), return_profiles.

surface_extendA

Extend a surface body beyond its free edges by a distance (Extend feature).

Units: a plain-number distance is in units (default mm), a string is a Fusion expression. Refs: free edges of surface bodies from inspect_query (edges of a solid have no free side). The extended body keeps its identity but may get a new ref - use modified_bodies.

Errors: distance 0, a face ref -> INVALID_PARAMS; alignment="align" on a Fusion API without extendAlignment -> FUSION_API_ERROR "not available" (nothing changed).

Returns {"feature", "health", "created_bodies" / "modified_bodies": [{ref, type, name, is_solid}], "removed_bodies"}.

Example: surface_extend(edges=[], distance=5)

Inputs: edges (required), distance (required), chain, units, +2 more.

surface_offsetA

Offset surface: new surface bodies at a distance from faces (Offset feature).

The source faces stay unchanged. This differs from feature_offset_faces (c07), which moves faces of a solid; to give the result a thickness use body_thicken (c08). Units: distance in units (default mm). Refs: faces from inspect_query.

Errors: distance 0, a non-face ref, join/cut -> INVALID_PARAMS; offset_type rounded on an API without offsetType -> FUSION_API_ERROR "not available".

Returns {"feature", "health", "created_bodies" / "modified_bodies": [{ref, type, name, is_solid}], "removed_bodies"}.

Example: surface_offset(faces=[], distance=2)

Inputs: faces (required), distance (required), chain, units, +2 more.

surface_patchA

Patch surface: fill a closed boundary with a new surface body (Patch feature).

The boundary is a sketch profile, sketch curves or B-Rep edges (e.g. the free edges of an opening in a surface body). continuity/weight/flip apply to edges of bodies (ignored for sketch curves). Refs: profiles from sketch_profiles / sketch_draw, curves from sketch_* results, edges from inspect_query (refs of surface bodies change after trim/extend/stitch - take them from the latest results).

Next steps: close surfaces into a solid with surface_stitch and check is_solid; give a surface thickness with body_thicken.

Errors: join/cut operation, weight outside 0..1, a body ref -> INVALID_PARAMS (nothing changed); a boundary Fusion cannot fill -> FUSION_API_ERROR, rolled back.

Returns {"feature", "health", "created_bodies": [{ref, type, name, is_solid}], "modified_bodies", "removed_bodies"}.

Example: surface_patch(boundary=["profile:@0,0"])

Inputs: boundary (required), weight, operation, continuity, +1 more.

surface_ruledA

Ruled surface: a strip of straight rulings grown from edges or sketch curves.

Units: distance in units (default mm), angle in degrees; strings are expressions. ruled_type normal/tangent is measured against the face of the edges, direction follows the direction entity. Refs: edges from inspect_query, curves from sketch_*. Close the result with surface_stitch / thicken it with body_thicken.

Errors: ruled_type direction without direction (or direction with another type), edges mixed with sketch curves -> INVALID_PARAMS (nothing changed).

Returns {"feature", "health", "created_bodies" / "modified_bodies": [{ref, type, name, is_solid}], "removed_bodies"}.

Example: surface_ruled(edges=[], distance=10)

Inputs: edges (required), distance (required), angle, chain, +6 more.

surface_stitchA

Stitch surface bodies / faces along shared edges into one body (Stitch feature).

If the surfaces enclose a volume the result is a solid: check "is_solid" in the result. is_solid=false means gaps remain - raise tolerance (default 0.1 mm), or patch the openings with surface_patch first. Refs: bodies / faces from inspect_query or earlier results.

Errors: fewer than 2 distinct surfaces, join/cut operation -> INVALID_PARAMS.

Returns {"feature", "health", "created_bodies" / "modified_bodies": [{ref, type, name, is_solid}], "removed_bodies", "is_solid": bool of the resulting body}.

Example: surface_stitch(surfaces=[, , ], tolerance=0.1)

Inputs: surfaces (required), units, operation, tolerance.

surface_trimA

Trim surfaces with a tool and remove the cells nearest to the given points.

Call surface_trim_cells first to see the cells (center / bbox / area in mm), then pass a point per cell to remove (in units, default mm). Several points in one cell remove it once. Cells are never addressed by index.

Errors: a point farther than max_distance from every cell -> INVALID_PARAMS with details.cells (the available cells) and nothing changed; a tool that cuts nothing -> INVALID_PARAMS reason "no_cells".

Returns {"feature", "health", "created_bodies" / "modified_bodies": [{ref, type, name, is_solid}], "removed_bodies", "removed_cells": n}.

Example: surface_trim(trim_tool="origin:XY", remove_points=[[0, 0, 20]])

Inputs: trim_tool (required), remove_points (required), units, max_distance.

surface_trim_cellsA

Preview of a trim: the cells the tool cuts the surrounding surfaces into.

Nothing changes in the design (the trim input is cancelled). Each cell has "center" [x, y, z] mm, "bbox" {"min", "max"} mm, "area_mm2" and "is_solid". Cells are temporary and have no refs: pick the ones to remove by a point near them and pass those points to surface_trim.

Errors: a tool of another type -> INVALID_PARAMS.

Returns {"cells": [{center, bbox, area_mm2, is_solid}], "count"}.

Example: surface_trim_cells(trim_tool="origin:XY")

Inputs: trim_tool (required).

surface_unstitchA

Unstitch: split faces or whole bodies into separate surface bodies.

A face of a solid becomes its own surface body and the rest of the solid becomes a surface body too (check is_solid). Refs: faces / bodies from inspect_query.

Returns {"feature", "health", "created_bodies" / "modified_bodies": [{ref, type, name, is_solid}], "removed_bodies"}.

Example: surface_unstitch(entities=[], chain=False)

Inputs: entities (required), chain.

surface_untrimA

Untrim faces of surface bodies: remove their boundary loops (holes / outer trim).

loop_type internal fills holes, external restores the outer boundary of the underlying surface, all does both. Faces of solid bodies are refused (unstitch them first). Refs: faces from inspect_query.

Errors: a face of a solid, extension_distance with internal -> INVALID_PARAMS (nothing changed).

Returns {"feature", "health", "created_bodies" / "modified_bodies": [{ref, type, name, is_solid}], "removed_bodies"}.

Example: surface_untrim(faces=[], loop_type="internal")

Inputs: faces (required), units, loop_type, extension_distance.

timeline_compute_allA

Recompute the whole design (Design.computeAll) and return the timeline_health report (Returns the same shape). Slow on big designs; use it when the model looks stale or after edits made with execute_python.

Example: timeline_compute_all() -> {"ok": true, "errors": [], ...}.

Inputs: no named parameters.

timeline_create_groupA

Group a contiguous range of top-level timeline items, first..last inclusive. Groups cannot be nested; the name must be unique in the timeline.

Returns {"group": item (ref 'timeline:'), "members": [item], "marker_position", "count"}.

Example: timeline_create_group(first=, last=, name="Base").

Inputs: last (required), first (required), name.

timeline_deleteA

Delete a timeline item (feature, sketch, construction element; a group with its contents).

Without force the item is first suppressed as a probe: if other items fall into the error state, nothing is deleted and the call fails with INVALID_PARAMS and details.dependents. The probe recomputes the model (slow on big designs). Items that cannot be suppressed are deleted without the check (dependents_checked = false). With force=true new problems are reported in problems_after.

Returns {"deleted": {"name", "type"}, "dependents_checked", "problems_after": [item], "marker_position", "count"}.

Example: timeline_delete(item=).

Inputs: item (required), force.

timeline_edit_chamferA

Set the distance of every equal-distance edge set of an existing chamfer.

Example: timeline_edit_chamfer(feature=, distance=1.5).

Returns {"feature": item, "changed": [{"key", "parameter", "old_expression", "new_expression", "value", "value_unit"}]} (values in mm / deg). All given keys are applied together; if the feature (or any other) falls into the error state everything is reverted and the call fails with FUSION_API_ERROR, details.reverted = true — unless allow_errors=true. A key that does not apply to this feature fails with INVALID_PARAMS and details.available_keys; no key at all fails with 'nothing to change'.

Inputs: feature (required), distance (required), units, allow_errors.

timeline_edit_extrudeA

Change an existing extrude: distance (only distance extents, not to-object/ through-all), distance_two (two-sided extrudes) and taper_angle (degrees).

Example: timeline_edit_extrude(feature=, distance=30).

Returns {"feature": item, "changed": [{"key", "parameter", "old_expression", "new_expression", "value", "value_unit"}]} (values in mm / deg). All given keys are applied together; if the feature (or any other) falls into the error state everything is reverted and the call fails with FUSION_API_ERROR, details.reverted = true — unless allow_errors=true. A key that does not apply to this feature fails with INVALID_PARAMS and details.available_keys; no key at all fails with 'nothing to change'.

Inputs: feature (required), units, distance, taper_angle, +2 more.

timeline_edit_filletA

Set the radius of every constant-radius edge set of an existing fillet.

Example: timeline_edit_fillet(feature=, radius=3).

Returns {"feature": item, "changed": [{"key", "parameter", "old_expression", "new_expression", "value", "value_unit"}]} (values in mm / deg). All given keys are applied together; if the feature (or any other) falls into the error state everything is reverted and the call fails with FUSION_API_ERROR, details.reverted = true — unless allow_errors=true. A key that does not apply to this feature fails with INVALID_PARAMS and details.available_keys; no key at all fails with 'nothing to change'.

Inputs: radius (required), feature (required), units, allow_errors.

timeline_edit_holeA

Change an existing hole: diameter, depth (distance extents only), tip_angle, counterbore_diameter/depth (counterbore holes), countersink_diameter/angle (countersink holes). Lengths in mm (or units), angles in degrees.

Example: timeline_edit_hole(feature=, diameter=6.6, depth=12).

Returns {"feature": item, "changed": [{"key", "parameter", "old_expression", "new_expression", "value", "value_unit"}]} (values in mm / deg). All given keys are applied together; if the feature (or any other) falls into the error state everything is reverted and the call fails with FUSION_API_ERROR, details.reverted = true — unless allow_errors=true. A key that does not apply to this feature fails with INVALID_PARAMS and details.available_keys; no key at all fails with 'nothing to change'.

Inputs: feature (required), depth, units, diameter, +6 more.

timeline_edit_revolveA

Change an existing revolve's angle (degrees; angle extents only) and angle_two (two-sided revolves).

Example: timeline_edit_revolve(feature=, angle=180).

Returns {"feature": item, "changed": [{"key", "parameter", "old_expression", "new_expression", "value", "value_unit"}]} (values in mm / deg). All given keys are applied together; if the feature (or any other) falls into the error state everything is reverted and the call fails with FUSION_API_ERROR, details.reverted = true — unless allow_errors=true. A key that does not apply to this feature fails with INVALID_PARAMS and details.available_keys; no key at all fails with 'nothing to change'.

Inputs: feature (required), angle, angle_two, allow_errors.

timeline_edit_shellA

Change the inside and/or outside wall thickness of an existing shell (mm or units).

Example: timeline_edit_shell(feature=, inside_thickness=2).

Returns {"feature": item, "changed": [{"key", "parameter", "old_expression", "new_expression", "value", "value_unit"}]} (values in mm / deg). All given keys are applied together; if the feature (or any other) falls into the error state everything is reverted and the call fails with FUSION_API_ERROR, details.reverted = true — unless allow_errors=true. A key that does not apply to this feature fails with INVALID_PARAMS and details.available_keys; no key at all fails with 'nothing to change'.

Inputs: feature (required), units, allow_errors, inside_thickness, +1 more.

timeline_feature_parametersA

Model parameters created by a feature, and the keys its timeline_edit_* tool accepts.

Returns {"feature": ref, "parameters": [{"name", "expression", "value", "value_unit" ("mm", "deg", "" or "fusion_internal" for other units), "role", "comment"}], "editable_keys": [...]}.

Example: timeline_feature_parameters(feature=) -> [{"name": "d3", "expression": "20 mm", "value": 20.0, "value_unit": "mm", "role": "AlongDistance"}].

Inputs: feature (required).

timeline_healthA

Health report of the whole timeline. Returns {"ok" (no item in error), "errors": [item], "warnings": [item], "suppressed_count", "rolled_back_count", "marker_position", "count"}. Call it after a series of edits to check the model.

Example: timeline_health() -> {"ok": false, "errors": [{"name": "Fillet1", "message": "..."}], ...}.

Inputs: no named parameters.

timeline_listA

List the timeline of the active parametric design in order, with status.

Group members follow their group. Returns {"count", "marker_position", "items": [item], "total", "truncated"}; items after the marker are rolled back (not part of the current model). Address items by "ref", never by index.

Example: timeline_list(only_problems=true) -> which features are broken and why.

Item: {"index" (informational only, never an address), "name", "type" (ExtrudeFeature, Sketch, TimelineGroup...), "ref", "is_group", "group": "timeline:" | null, "is_suppressed", "is_rolled_back", "health": "ok"|"warning"|"error"|"unknown", "message" | null, "component": "component:" | null}.

Inputs: limit, offset, only_problems.

timeline_renameA

Rename a feature, sketch, construction element or timeline group. Entity refs stay valid; a group's ref becomes 'timeline:'. Bodies are renamed with the body_* tools, not here.

Returns {"item": item, "marker_position", "count"}.

Example: timeline_rename(item=, name="Base").

Inputs: item (required), name (required).

timeline_roll_toA

Move the timeline marker. Items after the marker are rolled back.

WARNING: while the marker is not at the end, features created by other tools are inserted at the marker position, and they see the rolled-back model. Roll to "end" when done. Rolling into a collapsed group expands it.

Returns {"marker_position", "count", "rolled_back_count"}.

Example: timeline_roll_to(position="before", item=) -> add a feature that comes before the extrude, then timeline_roll_to(position="end").

Inputs: position (required), item.

timeline_set_group_collapsedA

Collapse or expand a timeline group (display only).

Returns {"group": item + "is_collapsed", "marker_position", "count"}.

Example: timeline_set_group_collapsed(group="timeline:Base", collapsed=true).

Inputs: group (required), collapsed (required).

timeline_set_model_parameterA

Set the expression of a model parameter (one created by a feature) by name.

If the owning feature (or any other) falls into the error state, the old expression is restored and the call fails with the feature's message and details.reverted = true, unless allow_errors=true. User parameters are changed with parameter_update.

Returns {"parameter": {"name", "expression", "old_expression", "value", "value_unit", "unit"}, "feature": item | null}.

Example: timeline_set_model_parameter(name="d3", value=30) -> "30 mm".

Inputs: name (required), value (required), units, allow_errors.

timeline_set_suppressedA

Suppress (or unsuppress) timeline items: a suppressed feature is skipped when the model is computed but stays in the timeline.

All or nothing: if any item fails, or the change puts a feature into the error state (e.g. unsuppressing a feature whose references are gone), every item gets its previous state back and the call fails with the feature's message and details.reverted = true. allow_errors=true keeps such a change.

Returns {"items": [item], "marker_position", "count"}.

Example: timeline_set_suppressed(items=[]).

Item: {"index" (informational only, never an address), "name", "type" (ExtrudeFeature, Sketch, TimelineGroup...), "ref", "is_group", "group": "timeline:" | null, "is_suppressed", "is_rolled_back", "health": "ok"|"warning"|"error"|"unknown", "message" | null, "component": "component:" | null}.

Inputs: items (required), suppressed, allow_errors.

timeline_ungroupA

Remove a timeline group but keep its members in the timeline.

Returns {"members": [item], "marker_position", "count"}.

Example: timeline_ungroup(group="timeline:Base").

Inputs: group (required).

viewport_screenshotA

PNG picture of the active Fusion viewport, to check the model visually.

Sets the camera (and optionally the visual style) and leaves it there, so the user sees the same view. Size 64..2048 px. Returns an image and a JSON text with {"width", "height", "orientation"}.

Example: viewport_screenshot(orientation="top", visual_style="shaded_edges").

Inputs: fit, width, height, orientation, +1 more.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A3.9/5.0

    Scored across 154 tools

    Disambiguation4/5

    Most tools target clearly distinct resource/action pairs with strong domain prefixes (sketch_*, feature_*, body_*, assembly_*, timeline_*), and cross-references explicitly distinguish similar tools like feature_offset_faces vs surface_offset, body_move vs assembly_transform_occurrence, and parameter_update vs timeline_set_model_parameter. However, with 154 tools there are still several easily confused families (feature_fillet vs feature_rule_fillet, the timeline_edit_* tools vs their feature_* counterparts, sketch_dimension vs sketch_dimension_set), so selection risk is non-trivial.

    Naming Consistency4/5

    The set follows a predictable domain-prefixed snake_case convention (sketch_draw, feature_extrude, body_combine, assembly_create_joint, sheet_metal_edge_flange) that is easy to scan. A handful of unprefixed utility tools (fusion_status, execute_python, measure_distance, viewport_screenshot, import_file, export_cad) mildly break the otherwise consistent pattern.

    Tool Count2/5

    154 tools is far beyond a practical agent surface and forces heavy tool-selection overhead; many could be consolidated, e.g. the per-feature timeline_edit_* family, the multiple sheet metal tools, and the form tools. The CAD domain is broad enough that this is not an arbitrary mismatch, but the surface is still excessively large.

    Completeness5/5

    The surface is exceptionally complete across modeling, sketching, inspection, parameters, sheet metal, surfaces, T-splines, assemblies/joints, materials/appearances, documents, timeline management, and import/export. No major lifecycle dead ends are apparent; even minor gaps like direct primitive-body creation are workable via sketch+extrude.

    Maintenance

    ActivityMaintained
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • F
      license
      Not graded
      quality
      C
      maintenance
      Enables AI assistants to inspect and automate Autodesk Fusion 360 through MCP, providing tools for CAD modeling, CAM manufacturing, and document management.
      -
    • A
      license
      B
      quality
      C
      maintenance
      Connects AI coding agents to Autodesk Fusion 360 for CAD/CAM automation, exposing 84 tools for sketching, modeling, assembly, inspection, export, and G-code post-processing through any MCP-compatible client.
      85
      MIT
    • A
      license
      C
      quality
      C
      maintenance
      Enables MCP-compatible assistants to control Autodesk Fusion for mechanical modeling, assembly editing, CAM workflows, inspection, and model export through Fusion's native MCP endpoint.
      39
      1
      MIT
    • A
      license
      B
      quality
      B
      maintenance
      Enables AI coding agents to drive Autodesk Fusion 360 over the Model Context Protocol, exposing 92 tools for sketching, modeling, querying, measuring and exporting CAD geometry through natural language. Includes an in-Fusion add-in that executes API calls safely on Fusion's main thread, with stdio transport compatible with any MCP client.
      92
      MIT