Skip to main content
Glama

CutOptim Engine

Optimize timber

optimize_wood

Metered: one Engine API call. Cut timber parts grouped by cross-section from matching stock lengths. Timber optimization (cross-section-aware 1D). Cut lengths from bars that have a CROSS-SECTION. Unlike /v1/optimize/1d, where every bar can serve every part, a 50×150 part can only come out of 50×150 stock — so the job is split by cross-section, each section is matched to its own stock and solved separately, and the response carries both per-section and job-wide totals.

Fanning the same job out into several /v1/optimize/1d calls is not equivalent: it costs one call per section against your quota, moves the stock matching to your code, and cannot distinguish "no material of this section" from "did not fit" — which this endpoint reports separately as unmatched and unplaced.

sw and sh may be given in either order: 50×100 and 100×50 are the same bar turned over and are matched as one section. The response reports the normalised short/long form.

Input Schema

NameRequiredDescriptionDefault
partsYes
stockYesAt most 50 rows. Since every cross-section needs at least one stock row, this is also the practical ceiling on cross-sections in a single job; a wider catalogue should be split into several requests.
engineNoAs in 1D, `max` is not offered here (a **400** before a call is charged). `balanced` resolves to the same packer as `heuristic`: within a section a timber job is a length problem, and free nesting has nothing to offer it. The value is accepted, echoed back, and a warning states which packer actually ran.heuristic
includeNoThree kinds of token. NARROWING (`cutPlan`, `offcuts`): omit the field entirely to get both; a present array keeps only the narrowing tokens it lists (an empty array drops both). ADDITIVE EXPORT (`svg`, `csv`, `dxf`): each adds an inline export STRING to the response (`svg` a standalone 2D layout — 2D only, a warning is returned for 1D/wood; `dxf` an R12/AC1009 drawing; `csv` a cut list, RFC 4180 quoted (a part name with a comma or a quote stays one field) and formula-injection-guarded (a name beginning with `=`, `+`, `-`, `@`, TAB or CR is prefixed with an apostrophe so a spreadsheet reads it as text, not a formula — CWE-1236). 2D DATA (`labels`, `planHash`, `pdf`, `labelsPdf`): `labels` adds per-piece label data (`labels[]`, see `Label2D`), `planHash` a 64-hex fingerprint of the plan (the same plan always gives the same hash), `pdf` the cutting-plan PDF and `labelsPdf` the label PDF, both base64-encoded and drawn by the same code as the CutOptim app. These four are 2D only: a 1D or wood request returns a `warnings` entry instead. `pdf` renders at most 500 parts (total quantity); a larger 2D request with `pdf` is a 413 `too_large` with `details.path: "include"`. Export and data tokens do not affect narrowing, so `["svg"]` adds svg and — listing no narrowing token — drops cutPlan/offcuts; use `["cutPlan","offcuts","svg"]` to keep everything.
optionsNoIdentical to `Options1D` — a cross-section changes what fits, not how a bar is cut.

Output Schema

NameRequiredDescriptionDefault
csvNo
dxfNo
engineYes
timingYes
cutPlanNo
metricsYes
sectionsYes
unplacedYes
warningsYes
unmatchedYes
deterministicYes
engineVersionYes
contractVersionYes

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed7 schema fields changed
    • addedInput schema / properties / options / properties / mitrePairing
      Added value: +{
      +  "default": false,
      +  "description": "Pair parts of one section whose facing ends (`parts[].ends`) can share ONE saw cut. Off by default: a request without it is solved exactly as before. On, a plan with pairs is returned only when it ranks strictly better than the unpaired plan by the packer's own ranking (parts placed first, then material — or price with `minimizeCost`); otherwise the unpaired plan comes back. Pairs only, no chains of three or more.",
      +  "type": "boolean"
      +}
    • addedInput schema / properties / parts / items / properties / ends
      Added value: +{
      +  "description": "Angled ends (mitre pairing). The `angle` is seen on `sh` AS ENTERED and the `bevel` on `sw`, so send the section the way the angles were measured.",
      +  "properties": {
      +    "end": {
      +      "description": "One end cut of a part, in degrees from square (0 = a square end), signed. The part is measured long point to long point (`length` is its overall length). A part whose two end cuts would cross inside its section (shorter than its leads) cannot be made: a 400 `invalid_request` naming `parts[i].ends` says how long it must at least be.",
      +      "properties": {
      +        "angle": {
      +          "description": "The face angle: the mitre or plumb cut as seen on the `depth` side (wood: on `sh` as entered).",
      +          "exclusiveMaximum": 90,
      +          "exclusiveMinimum": -90,
      +          "type": "number"
      +        },
      +        "bevel": {
      +          "default": 0,
      +          "description": "The edge angle: the bevel as seen on the `thickness` side (wood: on `sw` as entered). A compound cut has both.",
      +          "exclusiveMaximum": 90,
      +          "exclusiveMinimum": -90,
      +          "type": "number"
      +        }
      +      },
      +      "required": [
      +        "angle"
      +      ],
      +      "type": "object"
      +    },
      +    "start": {
      +      "description": "One end cut of a part, in degrees from square (0 = a square end), signed. The part is measured long point to long point (`length` is its overall length). A part whose two end cuts would cross inside its section (shorter than its leads) cannot be made: a 400 `invalid_request` naming `parts[i].ends` says how long it must at least be.",
      +      "properties": {
      +        "angle": {
      +          "description": "The face angle: the mitre or plumb cut as seen on the `depth` side (wood: on `sh` as entered).",
      +          "exclusiveMaximum": 90,
      +          "exclusiveMinimum": -90,
      +          "type": "number"
      +        },
      +        "bevel": {
      +          "default": 0,
      +          "description": "The edge angle: the bevel as seen on the `thickness` side (wood: on `sw` as entered). A compound cut has both.",
      +          "exclusiveMaximum": 90,
      +          "exclusiveMinimum": -90,
      +          "type": "number"
      +        }
      +      },
      +      "required": [
      +        "angle"
      +      ],
      +      "type": "object"
      +    }
      +  },
      +  "type": "object"
      +}
    • addedInput schema / properties / parts / items / properties / flip
      Added value: +{
      +  "default": "none",
      +  "description": "Mitre pairing only: which 180° turns of the part on the bar are allowed, so its angled end can meet a neighbour's. `none` (default — a profiled moulding or one-sided stock), `face` (end for end, the crown or top edge stays up — roof members), `edge` (end for end over the edge — flat stock, frames), `any`.",
      +  "enum": [
      +    "none",
      +    "face",
      +    "edge",
      +    "any"
      +  ],
      +  "type": "string"
      +}
    • changedOutput schema / properties / cutPlan / items / allOf
      Previous value: -[
      -  {
      -    "properties": {
      -      "axis": {
      -        "enum": [
      -          "h",
      -          "v"
      -        ],
      -        "type": "string"
      -      },
      -      "length": {
      -        "minimum": 0,
      -        "type": "number"
      -      },
      -      "pos": {
      -        "type": "number"
      -      },
      -      "sheet": {
      -        "minimum": 0,
      -        "type": "integer"
      -      },
      -      "stage": {
      -        "minimum": 1,
      -        "type": "integer"
      -      },
      -      "step": {
      -        "minimum": 1,
      -        "type": "integer"
      -      }
      -    },
      -    "required": [
      -      "sheet",
      -      "step",
      -      "axis",
      -      "pos",
      -      "length",
      -      "stage"
      -    ],
      -    "type": "object"
      -  }
      -]New value: +[
      +  {
      +    "properties": {
      +      "angle": {
      +        "type": "number"
      +      },
      +      "axis": {
      +        "enum": [
      +          "h",
      +          "v"
      +        ],
      +        "type": "string"
      +      },
      +      "bevel": {
      +        "type": "number"
      +      },
      +      "length": {
      +        "minimum": 0,
      +        "type": "number"
      +      },
      +      "pos": {
      +        "type": "number"
      +      },
      +      "sheet": {
      +        "minimum": 0,
      +        "type": "integer"
      +      },
      +      "stage": {
      +        "minimum": 1,
      +        "type": "integer"
      +      },
      +      "step": {
      +        "minimum": 1,
      +        "type": "integer"
      +      }
      +    },
      +    "required": [
      +      "sheet",
      +      "step",
      +      "axis",
      +      "pos",
      +      "length",
      +      "stage"
      +    ],
      +    "type": "object"
      +  }
      +]
    • addedOutput schema / properties / metrics / properties / sharedCuts
      Added value: +{
      +  "type": "integer"
      +}
    • addedOutput schema / properties / sections / items / properties / rods / items / properties / parts / items / properties / flipped
      Added value: +{
      +  "enum": [
      +    "face",
      +    "edge",
      +    "roll"
      +  ],
      +  "type": "string"
      +}
    • addedOutput schema / properties / sections / items / properties / rods / items / properties / parts / items / properties / sharedCut
      Added value: +{
      +  "properties": {
      +    "angle": {
      +      "type": "number"
      +    },
      +    "bevel": {
      +      "type": "number"
      +    },
      +    "kerfAlongAxis": {
      +      "type": "number"
      +    },
      +    "lead": {
      +      "type": "number"
      +    }
      +  },
      +  "required": [
      +    "angle",
      +    "bevel",
      +    "kerfAlongAxis",
      +    "lead"
      +  ],
      +  "type": "object"
      +}
  2. First observed

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description adds significant operational behavioral context beyond the general safety hints in the annotations, detailing performance characteristics (one API call), failure modes (unmatched vs. unplaced), and specific matching logic (50x150 part only from 50x150 stock). It informs the agent about why certain inputs are grouped or split.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is extremely detailed and verbose, which hurts conciseness. However, its structure is highly logical, front-loading the core optimization logic and then dedicating sections to comparing it against alternative methods. The length is justified by the complexity of the tool.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the high complexity of the input (multiple nested objects, multiple cross-section definitions), the definition is exceptionally complete. It covers cost implication, logical constraints, and the mechanics of the output plan, providing all necessary context for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

While the schema is detailed, the description adds vital semantic understanding, such as the fact that `sw` and `sh` order is irrelevant, that `material` creates independent sections, and the complexity of the `include` and `options` tokens. This knowledge elevates the understanding of parameter interactions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the purpose is timber optimization grouped by cross-section. It specifically distinguishes itself from sibling tools like `/v1/optimize/1d` by explaining that it is 'cross-section-aware,' which is a critical functional difference.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It provides extremely explicit usage guidance by comparing this tool against the primary alternative (`/v1/optimize/1d`). It explicitly warns agents against 'fanning the job out,' detailing the negative consequences of that approach (increased cost, lost stock matching context, inability to distinguish between 'unmatched' and 'unplaced' parts).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.