Skip to main content
Glama

Server Details

Manufacturing cost of CNC and sheet-metal parts from STEP or DXF: process plan, times, 10 lot sizes.

Ownership verified
Status
Healthy
Uptime
44.6% over 43 days
OAuth
Works in Glama
Last Tested
Transport
Streamable HTTP · MCP 2025-11-25
URL
Repository
arcnm/arcnm-mcp
GitHub Stars
0

TDQS

A4.3/5.0

Scored across 18 tools

Disambiguation5/5

Tools split cleanly along the quoting lifecycle: precheck vs. real upload/quote, single vs. list/compare, explanation vs. line-item vs. process-plan views, and free what-if vs. billable re-quote. The descriptions repeatedly name the intended neighboring tool, so misselection risk is low.

Naming Consistency4/5

Nearly all tools use a predictable snake_case verb_noun pattern such as get_calculation, quote_part, and check_quota. A few action phrases like upload_and_quote and precheck_part deviate slightly, but the set remains readable and consistent overall.

Tool Count4/5

At 18 tools, the surface is slightly above a tight 3–15 range, but the domain has several distinct phases and analysis modes. Each tool appears to cover a real operation, though the analysis side is fairly broad.

Completeness4/5

The core lifecycle is well covered: precheck, upload/quote, status tracking, cancellation, drawing attachment, quota checks, environments, cost explanations, comparison, optimization, and savings suggestions. Gaps remain around part/environment CRUD and deletion or export workflows, but ordinary quoting workflows are not dead-ended.

Available Tools

18 tools
attach_drawingAttach DrawingA
Destructive
Inspect

Give a drawing (PDF, PNG or JPEG) to the part it belongs to, whatever the two files are called. Before a run: precheck_id from precheck_part and the row's component_key from get_precheck (or assembly, for the assembly's own drawing), with data_source_id of a drawing the precheck holds or the file as base64. The drawing goes with that part when upload_and_quote starts the precheck; attaching before the start is free and bills nothing. After a run: calculation_id of the part's own calculation (for an assembly, a component's) and the drawing. It becomes that part's drawing and, with run true (the default), the part is priced again as a new calculation, billable only if it succeeds; the same drawing again changes nothing. By default (apply=false) it only plans and attaches nothing; apply=true attaches. Returns where the precheck's drawings go, or the new calculation.

NameRequiredDescriptionDefault
runNoWith calculation_id: price the part again with the drawing (default true; billable only if it succeeds). False attaches only.
applyNoFalse (the default): plan only, read the target and say what would change; nothing is attached. True: attach.
precheck_idNoBefore the start: the precheck, as precheck_part returns it. With component_key; not with calculation_id.
component_keyNoWith precheck_id: the part the drawing belongs to, a row's component_key from get_precheck, or assembly for the assembly's own drawing.
calculation_idNoAfter a run: the calculation of the part, as upload_and_quote, quote_part or list_calculations return it (for an assembly, a component's own). Not with precheck_id.
data_source_idNoA drawing already stored: with precheck_id one the precheck holds (its drawings in get_precheck), with calculation_id a drawing of this organization that no unstarted precheck holds. Not with drawing_file_b64.
drawing_file_b64NoThe drawing itself, a PDF, PNG or JPEG as base64 (or a data: URI). With drawing_filename; not with data_source_id.
drawing_filenameNoThe file name of drawing_file_b64 with its extension, e.g. ZX-0001_A.pdf.
drawing_content_typeNoMIME type of drawing_file_b64, when known.

Output Schema

NameRequiredDescription
targetYes`precheck`: placed before the start. `calculation`: attached to a calculated part.
appliedYesFalse: a plan only, nothing was attached. True: the drawing was attached.
changedNoFalse when this drawing already was the part's drawing: nothing was attached and nothing runs.
drawingsNoEvery drawing the precheck holds, and where each goes.
revisionNoThe precheck's revision, to start it with.
next_stepYesWhat happens next.
precheck_idNo
prices_againNoFor a calculated part: whether it is priced again — a new calculation, or a component's own in place. In a plan, what apply=true does.
component_keyNoThe part the drawing goes to on the precheck, or `assembly`.
calculation_idNo
data_source_idNoThe drawing, as stored.
precheck_statusNoThe precheck's status: `received` while a new drawing's title block is read, `ready` once answered.
new_calculation_idNoThe calculation that prices the part with this drawing, when run is true and the drawing changed.
rerun_calculation_idNoFor a component of an assembly: its own calculation, priced again in place.
new_calculation_statusNoIts status: `queued` is a run, `succeeded` an identical earlier run answering it unbilled, `blocked` a run held for quota.

TDQS

A4.6/5.0
Behavior4/5

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

Adds substantial context beyond the annotations: attaching before the start is free, re-pricing is billable only on success, and apply=false is a dry run. The claim that 'the same drawing again changes nothing' sits in mild tension with idempotentHint=false, but it is a scoped nuance rather than a contradiction, since attaching a different drawing does mutate state.

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?

Front-loads the purpose, then organizes by 'Before a run' / 'After a run' phases, which matches how an agent reasons about the call. It is a dense single block of ~180 words; a bulleted split would be easier to scan, but almost every clause carries information.

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?

Covers both invocation modes, file sourcing, default dry-run, billing implications, and what the call returns, for a 9-parameter tool with annotations and an output schema. Nothing an agent needs to call it correctly appears to be missing.

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

Parameters4/5

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

Schema coverage is 100%, so the baseline is 3, but the description goes further by explaining which parameters pair together (precheck_id + component_key, calculation_id alone, data_source_id xor drawing_file_b64) and where each value comes from. It adds cross-parameter guidance the schema does not encode.

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?

States a specific verb and resource ('give a drawing ... to the part it belongs to') and immediately names the file types accepted. It also splits the operation into its two distinct modes (before a run vs after a run), which is what actually distinguishes it from siblings like upload_and_quote or precheck_part.

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?

Explicitly names when to use each path: 'Before a run: precheck_id from precheck_part and the row's component_key from get_precheck', and 'After a run: calculation_id'. It also states the alternative for supplying the file (data_source_id vs base64) and the default plan-only behavior, leaving little to infer.

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

cancel_calculationCancel CalculationA
Destructive
Inspect

Stop a calculation that is queued or running. Use it as soon as a run is no longer wanted, for example one started with the wrong file, lot size or costing environment. Free: a cancelled calculation is never charged, because only a calculation that succeeds uses the quota. Cancelling an assembly also stops its component calculations. A cancelled run cannot be resumed. To price the part again, use quote_part. A calculation that has already finished is returned unchanged. Returns the calculation id, its status and its costing environment.

NameRequiredDescriptionDefault
calculation_idYesId of a calculation, as upload_and_quote, quote_part or list_calculations return it.

TDQS

A4.7/5.0
Behavior5/5

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

Goes well beyond the annotations (destructiveHint=true, idempotentHint=false): it discloses that cancellation is never charged quota, that cancelling an assembly cascades to component calculations, that a cancelled run is unrecoverable, and that an already-finished run is returned unchanged. These are non-obvious behavioral facts an agent needs before invoking a destructive tool.

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

Conciseness5/5

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

Front-loaded with the core action, followed by tightly ordered sentences covering cost, cascade behavior, irreversibility, alternative tool, and return payload. No sentence is filler; even the return-value sentence compensates for the absent output schema.

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?

For a single-parameter destructive tool with no output schema, the description covers the action, eligibility, cost implications, cascade effects, irreversibility, alternative tool, and return contents. Nothing needed to call it correctly is missing.

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

Parameters3/5

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

Schema description coverage is 100% and the schema already documents calculation_id with format uuid and provenance ('as upload_and_quote, quote_part or list_calculations return it'). The description adds no additional parameter semantics, so the baseline 3 applies.

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?

States a specific verb (stop/cancel) and resource (calculation), plus the scope of which runs are eligible ('queued or running'). An agent can immediately distinguish it from siblings like get_calculation, list_calculations, or quote_part.

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?

Explicitly says when to use it ('as soon as a run is no longer wanted', e.g. wrong file, lot size or costing environment) and names the alternative for the follow-up action ('To price the part again, use quote_part'). Both the trigger condition and the sibling routing are given.

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

check_quotaCheck QuotaA
Read-onlyIdempotent
Inspect

Check this organization's calculation allowance for the current period: included, used and remaining calculations, whether more runs are blocked or billed as overage, the remaining overage budget and whether runs are paused. Use it before starting several billable calculations with upload_and_quote or quote_part. Read-only and free.

NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription
planNo
usedNo
bonusNoThank-you calculations granted on top of the plan this window.
windowNo'month' or 'year'.
guidanceYes
includedNoCalculations included per window.
rolloverNoUnused calculations carried in from last window.
effectiveNoCeiling this window (included + rollover + bonus).
remainingNoCalculations still available this window.
over_quotaNo
hard_cappedNoTrue: over-quota runs park as blocked. False: they bill as overage.
window_startNoISO 8601 start of the current quota window.
overage_centsNoPrice of one calculation beyond the included volume, in cents.
payment_blockedNoTrue when billing is suspended and nothing will run.
wallet_overdrawnNoTrue when the prepaid balance has reached its hard floor — calculations are paused and further runs park as 'blocked' until the balance is topped up.
overage_cap_centsNoMonthly overage spend cap in cents, or null when uncapped. Bounds what over-quota runs may cost.
spend_cap_blockedNoTrue when the overage cap is reached and set to pause — further over-quota runs park as blocked.
has_payment_methodNoWhether a payment method is on file; a 'wallet' plan needs one for calculations beyond the included volume.
overage_settlementNoHow overage is paid: 'wallet' (a prepaid balance that is the ceiling) or 'invoice' (contracted, billed in arrears).
overage_spend_centsNoOverage already billed this calendar month, in cents.
wallet_balance_centsNoPrepaid balance in cents ('wallet' settlement only).
wallet_overdraft_centsNoHow far the prepaid balance is below zero, in cents.
wallet_funded_calculationsNoHow many more overage calculations the current balance covers; beyond it, calculations park as 'blocked'.
wallet_overdraft_floor_centsNoHard floor on the prepaid balance, in cents; the balance can never go below its negation.
overage_budget_remaining_centsNoOverage spend still inside the cap, in cents; null when uncapped.

TDQS

A4.6/5.0
Behavior4/5

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

Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false and openWorldHint=false, so the safety profile is covered. The description still adds genuine context not in the annotations: the operation is free of charge, and it discloses the operational state it surfaces (runs blocked, billed as overage, paused). It does not add auth or rate-limit detail, but that is a minor gap given the annotation coverage.

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?

Two sentences, front-loaded with the purpose and ending with the routing guidance. The middle clause enumerates every returned field, which is somewhat list-heavy and partly duplicates the output schema, but it is not padded with filler.

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?

With no parameters, an output schema, and rich annotations, the definition supplies everything an agent needs: what is measured, that it is free and read-only, and when to call it relative to upload_and_quote and quote_part. Nothing required for correct invocation is missing.

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

Parameters4/5

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

The tool takes zero parameters, so there is nothing to document and the schema trivially covers 100% of the surface. Baseline of 4 applies since the description has no parameter semantics to add or omit.

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?

States a specific verb and resource (check the organization's calculation allowance for the current period) and enumerates exactly what is reported: included/used/remaining calculations, blocking vs overage billing, remaining overage budget, and pause state. That scope is distinguishable from siblings like list_calculations or explain_cost without opening any schema.

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?

Gives an explicit trigger and names the alternatives: 'Use it before starting several billable calculations with upload_and_quote or quote_part.' This is a clear when-to-use rule tied to concrete sibling tools, leaving nothing to inference.

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

compare_calculationsCompare CalculationsA
Read-onlyIdempotent
Inspect

Compare 2 to 20 calculations by offer price. Use it to choose between designs, materials, lot sizes or costing environments. Two ids return the price and unit-cost difference between them (pair). Three or more return a ranking, cheapest first, with each option's premium over the cheapest (ranking); blocked or unpriced ones are listed last. It flags options that are different parts, or were priced on different materials, at different lot sizes, in different environments or with different overhead schemes, and never compares across currencies. Read-only and free: it re-prices nothing.

NameRequiredDescriptionDefault
calculation_idsYes2 to 20 distinct calculation ids: 2 for the delta, 3 to 20 for the ranking.

Output Schema

NameRequiredDescription
pairNoSet for exactly two calculation ids.
rankingNoSet for three to twenty calculation ids.
not_foundNoThe calculation_ids that name no calculation of your organization, in the order given. A ranking leaves them out and ranks the others; a pair needs both ids, so it is refused instead.

TDQS

A4.5/5.0
Behavior5/5

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

Adds substantial context beyond the annotations: cardinality-dependent output modes (pair delta vs ranking with premium over cheapest), placement of blocked/unpriced entries last, cross-option difference flags (different parts, materials, lot sizes, environments, overhead schemes), and a hard constraint that it never compares across currencies. It also confirms 're-prices nothing' and is free, consistent with readOnlyHint/idempotentHint.

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

Conciseness5/5

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

Front-loaded with the action and scope, then usage, then output behavior by cardinality, then constraints  every sentence carries distinct information with no filler or restatement of the name/title.

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?

With only one parameter, full schema coverage, an existing output schema, and clear annotations, the description covers the remaining gaps an agent needs: input cardinality rules, the two result shapes, edge-case ordering, comparability caveats, and cost/side-effect profile.

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

Parameters3/5

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

Schema description coverage is 100% and the schema already states the 2-for-delta / 3-to-20-for-ranking split. The description's extra detail (price and unit-cost difference, cheapest-first ranking) describes output semantics rather than adding new meaning about the parameter itself, so the baseline 3 applies.

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?

States a specific verb (compare) and resource (calculations) with an explicit ceiling/floor of 2-20 and the comparison basis (offer price). It is immediately distinguishable from read-oriented siblings like get_calculation and get_cost_breakdown, which return one calculation rather than a multi-option comparison.

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

Usage Guidelines4/5

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

Explicitly names the decision contexts that call for it: choosing between designs, materials, lot sizes or costing environments. It does not name an alternative tool or state when not to use this (e.g., single-calculation lookups), so it falls short of full routing guidance.

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

explain_costExplain CostA
Read-onlyIdempotent
Inspect

Explain what a priced calculation costs and why, in one short structured answer. Use it first once a calculation has succeeded. Returns the unit, total and setup cost, the prediction band and confidence, the cost categories, the machine used, how many times each machine clamps the part, work the drawing asks for that is not in the price, and the top cost drivers: the cost categories with their share of the unit cost first, then the features. The drivers show what to change in the design or to challenge in a quote. For the itemised line items, use get_cost_breakdown. For the status of a calculation that is still running, use get_calculation. Read-only and free.

NameRequiredDescriptionDefault
detailNoHow many cost drivers to list: 'concise' (the default) lists the top 3 cost categories and the top 3 features (an assembly's top 3 rows), 'detailed' the top 10.concise
calculation_idYesId of a calculation, as upload_and_quote, quote_part or list_calculations return it.

Output Schema

NameRequiredDescription
nameNo
errorNoWhy this calculation produced no price, in one sentence, when its status is terminal (failed / cancelled). Absent while it is still running and on a priced calculation.
routeNoEvery machine / work centre the priced route runs on, in order — the same chain get_process_plan lists. One entry on a single-machine quote; e.g. [bandsaw, lathe] when the blank is sawn first. Empty when the calculation carries no process plan.
timesNoTime per category behind the cost lines — programming, inspection, finishing, deburring, packaging, and the machine-side phases. Every line except material, tooling and outsourced work is time x rate, so this is the basis the money is struck on. Absent on a calculation that recorded no time breakdown.
statusYes
machineNoMachine the part was priced on.
coverageNoPresent only when status is 'blocked': the calculation was created but not run because the organization has no included calculations left, has reached its monthly overage cap, or has its billing paused. Carries {reason, message, remaining, used, included, tier_slug, window}: 'reason' says which, 'message' states it in a sentence. The part is saved; a later calculation of it runs once the block is lifted. Never a 402.
currencyNoThe calculation's currency. EVERY money figure on this result is stated in it — unit_cost, offer_price, total_cost, setup_cost, the band, every cost_breakdown line and every driver.
guidanceYesWhat to do next to act on or reduce the cost.
lot_sizeNo
materialNoMaterial, when known.
unpricedNoWork the drawing requires that no machine in this environment can do, so it is not in the price. Each entry names the process and why. Absent when the route covers what the drawing asks for.
clampingsNoHow many times each machine on the route clamps the part, in route order — the same count the route was costed on. Absent when the route did not state a count.
cost_bandNo[low, high] prediction band for the unit cost.
unit_costNoUnit cost per part: direct cost plus overhead_var and overhead_fixed. Where the costing environment states no Material-/Fertigungsgemeinkosten, overhead_var is the flat variable overhead the environment states (none by default); once it states them, those overheads sit above unit_cost as cost-sheet rungs, with administration and selling, margin and the other surcharges. Not the price to quote: that is offer_price, equal to unit_cost only where no surcharges are stated.
confidenceNoQuote-trust signal: calibrated to the shop, or a model estimate — read together with the prediction band.
setup_costNoOne-time setup cost of the lot, on the same basis as unit_cost (below the cost-sheet rungs).
total_costNounit_cost for the whole lot (unit_cost x lot_size), on the same basis as unit_cost; the lot at the offer price is offer_price x lot_size.
offer_priceNoThe offer price per unit — unit_cost plus the cost-sheet surcharges the costing environment states (scrap, overheads, administration and selling, freight, duty, mark-up). Equal to unit_cost when no sheet is stated; this is the figure the tenant's cost sheet and the calculation's own analytics headline as the price. This is the authoritative price: quote from it, not from cost_breakdown.angebotspreis, which is the cost sheet's own total and can differ from it. Absent on older calculations.
top_driversNoWhat drives the cost, largest first. On a part: the cost categories first (setup, subcontract, material, machine …), each with its cost and its share of unit_cost, and an 'other' row with the categories not listed, so these rows add up to unit_cost; then the features (pocket, hole, slot), which split the run-time categories (machine, labour, finishing) and so are part of those rows, never added to them. A part with no machined features (a flat pattern) lists the categories alone; one priced before the cost sheet existed, the features alone. On an assembly: its components and its own joining. The top 3 categories and the top 3 features (an assembly's top 3 rows), or 10 with detail 'detailed'.
unit_time_sNoTotal time per unit in seconds, every work system: the machine run, the finishing pass and the bench work (deburring, packaging) under the allowance, plus the per-unit shares of programming and inspection. Excludes the lot setup (setup_time_s).
cycle_time_sNoMachining cycle time per unit, in seconds.
needs_reviewNo
setup_time_sNoOne-time setup time for the whole lot, in seconds (NOT per unit; divide by the lot size for the per-unit share). Time and cost side by side, for quoting / scheduling / capacity planning.
material_noteNoPlain-language material assumption (which grade was priced, or that a default was used).
calculation_idYes
cost_breakdownNoCost figures per unit, keyed by line, all in `currency` (the calculation's currency — the same basis as unit_cost and offer_price, so the lines add up to the headline). The LINES that sum to unit_cost are material_cost, machine_cost, labour_cost, programming_cost, tooling_cost, finishing_cost, inspection_cost, subcontract_cost, overhead_var and overhead_fixed. Six keys RESTATE money already inside those lines and must not be added again: machine_setup_cost and labour_setup_cost are the setup shares machine_cost and labour_cost already include (the tenant's cost sheet shows the same money as a separate 'setup' row and correspondingly smaller machine and labour rows); transfer_cost is the inter-machine hand-off charge on a composed route, which is priced inside overhead_fixed; and material_purchased_cost and remnant_credit derive material_cost, which is material_purchased_cost minus remnant_credit — the stock bought, less what its reusable remnant is worth back in stock (0 unless the costing environment credits remnants). scrap_credit is what the scrap fetches (0 unless the environment credits scrap): a cost-sheet rung SUBTRACTED inside herstellkosten, before scrap_cost and material_overhead are struck on the net material. direct_unit_cost, herstellkosten, selbstkosten, barverkaufspreis and zielverkaufspreis are SUBTOTALS; angebotspreis is the cost sheet's own offer-price total — offer_price is the authoritative price and the one to quote from, and the two can differ; scrap_cost, material_overhead, production_overhead, sga_cost, packaging_cost, freight_cost, duty_cost, margin (the profit mark-up on selbstkosten), cash_discount, sales_commission and customer_discount are the cost-sheet rungs between unit_cost and offer_price. cost_categories holds the sheet's buckets as the page shows them (setup separate); for the itemised sheet with the tiers beneath each line use get_cost_breakdown.
machine_time_sNoMachine time per unit in seconds: the billed run plus the finishing pass, under the allowance — the time one piece occupies the machine, and the t_e the product's cost sheet states.
review_reasonsNo
cost_categoriesNoThe cost sheet's own buckets per unit (material, setup, machine, labour, programming, tooling, finishing, overheads …) in the quote's currency — exactly the lines the product shows, setup as its own line. On an assembly: its roll-up terms (components_cost, joining_cost, …) and the cost-sheet rungs above them, the same map get_cost_breakdown states, adding up to offer_price. Absent on calculations priced before the sheet existed.
drawing_pairingNoWhether the drawing sent with this calculation describes its model: {status (matched | suspect | mismatched | unverified), drawing_excluded, checks[{name, status}]}. When drawing_excluded is true the drawing describes another part and was left out — the price is the model's alone. Absent when no drawing was paired.
material_pricedNoThe material this calculation was priced as, by its short name — the environment's default material when material_resolved is false. On an assembly whose components name their own materials, each one, comma-separated.
material_sourceNoWhere material_priced came from: 'request', 'drawing_title_block' (the part's drawing), 'step_material_property' (the material its STEP file names), 'assembly_parts_list' (the assembly drawing's parts-list row naming the component), 'assembly_drawing_title_block', 'assembly_parts_list_dominant' (the grade most of that list's made rows name, inferred for a component no row names) or 'environment_default'. The first that names a material wins, in that order: request, drawing, parts-list row, assembly drawing or dominant grade, STEP file, environment default.
material_resolvedNoFalse when no material grade resolved and the part was priced on the environment's default — set material_ref and re-run to correct.
selection_failureNoThe same refusal as data when no machine in the costing environment could make the part: the requirement that stopped it, the machine that came closest with its measured values, and how much of the fleet shares the blocker. Absent unless that is why it failed.
price_completenessNo'partial' when `unpriced` lists work the price leaves out — then unit_cost is a LOWER BOUND for the drawing, not a price for it; 'complete' when the price covers everything. Absent on a calculation from before the contract and on one without a price.
assembly_completenessNoASSEMBLIES ONLY. Whether `unit_cost` is a price or a LOWER BOUND. Carries {n_unique, n_priced, n_pending, n_unpriced, n_excluded, n_partial, total_is_lower_bound, priced_complete, unpriced[], partial[], unpriced_steps[]}, where each unpriced entry has a closed-enum `reason_code`, a `by_design` flag and, where one exists, a `remedy`. `priced_complete` and `total_is_lower_bound` cover the COMPONENTS only (the BOM rows counted in n_unique): `priced_complete` is true when every component priced, and when `total_is_lower_bound` is true a component is missing, so `unit_cost` is a lower bound, not a complete price. `unpriced_steps` lists the assembly's own route steps that carry no price, with their reason, worded as get_process_plan words them (e.g. 'Straightening — unpriced (straightening_shop_specific)'); they are not in `unit_cost` whatever the two flags say. A `by_design` reason (a part budget, a plan quota, a cancellation) is a configured limit, not a processing error.
costing_environment_idNoThe costing environment this was priced in: the machines, rates and overheads behind these numbers (list_environments names it).
inputs_changed_since_runNoNull when this price reflects every input on its part revision. Otherwise {roles, corrections, latest_at}: files attached and corrections applied to the part after the run read its inputs, which a new calculation reads and this one did not.
environment_changed_since_runNoNull when this price was computed on its costing environment as it stands. Otherwise {latest_at}: the environment was edited after the run read it, and a new calculation prices with the current setup while this result does not.

TDQS

A4.3/5.0
Behavior4/5

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

Annotations already declare readOnly/destructive/idempotent, so the bar is met cheaply, but the description adds "free" (a quota/billing trait not present in annotations) and spells out the response contents in domain terms. The one gap is that it doesn't warn what happens on an unpriced or failed calculation, so it stops short of a 5.

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

Conciseness3/5

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

Front-loaded and well ordered (purpose, trigger, returns, alternatives), but the return-value enumeration is a long run-on sentence that restates what the output schema already declares. It is longer than the decision it supports requires.

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?

For a two-parameter, read-only reader with a full output schema and complete annotations, the description covers purpose, trigger condition, return semantics at a domain level, and sibling routing. Nothing an agent needs in order to call it correctly is missing.

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

Parameters3/5

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

Schema coverage is 100% and the enum's own description already explains concise (top 3 categories/features) vs detailed (top 10). The description only implies the default via "one short structured answer" and adds no syntax or edge-case guidance for calculation_id beyond what the schema states, so baseline 3 applies.

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?

States a specific verb and object ("explain what a priced calculation costs and why") and immediately bounds the output shape ("one short structured answer"). It is clearly distinguishable from get_cost_breakdown (line items) and suggest_cost_savings (savings), both of which appear as siblings.

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?

Gives an explicit ordering rule ("Use it first once a calculation has succeeded") and names two siblings with the condition that selects each: get_cost_breakdown for itemised line items, get_calculation for a still-running calculation. Nothing about when-to-use is left to inference.

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

get_calculationGet CalculationA
Read-onlyIdempotent
Inspect

Read one calculation: its status, its inputs and, once it has succeeded, its costed result. Use it to follow a calculation that upload_and_quote or quote_part started until its status is final: succeeded, failed, cancelled, timed_out or blocked (held for quota or billing). Until then it is queued, running or polling (an assembly waiting for its components): check again every few seconds. Returns the status, the part revision, the costing environment, lot size, material and the result. The large analytics object is left out unless include_analytics is true. For a short answer on what it costs and why, use explain_cost. Read-only and free.

NameRequiredDescriptionDefault
calculation_idYesId of a calculation, as upload_and_quote, quote_part or list_calculations return it.
include_analyticsNoWhether to include the `analytics` object (the full cost breakdown and audit detail, often over 100 kB). Omitted: included for the app and the REST API, left out (null) for an MCP agent — pass true to get it, or read the cost through the cost sheet (the `get_cost_breakdown` tool; over MCP, `get_cost_breakdown`), which is compact. Pass false to leave it out anywhere.

TDQS

A4.4/5.0
Behavior4/5

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

Annotations already cover the safety profile (readOnlyHint, idempotent, non-destructive), and 'Read-only and free' largely restates them. However, the description adds real context beyond annotations: the full status lifecycle, the meaning of 'blocked' (quota/billing) and 'polling' (assembly awaiting components), and the agent-specific default that analytics is omitted over MCP.

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?

Front-loaded with the core action and then layered with lifecycle and return detail; most sentences earn their place. There is mild redundancy between the status list and the 'Read-only and free' tail that repeats the annotations, but it stays dense and purposeful.

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?

With no output schema, the description carries the burden of describing returns and does so concretely (status, part revision, costing environment, lot size, material, result). The status lifecycle, polling guidance, and analytics default make it complete for correct invocation.

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

Parameters3/5

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

Schema description coverage is 100%, so both parameters (calculation_id and include_analytics) are already fully documented in the schema, including the MCP default. The description's note that 'analytics is left out unless include_analytics is true' echoes the schema rather than adding new meaning, so baseline 3 applies.

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?

States a specific verb and resource ('Read one calculation') and enumerates exactly what it returns (status, inputs, costed result). It distinguishes itself from siblings by routing to explain_cost for a short cost answer and naming upload_and_quote/quote_part as the producers of the id.

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?

Explicitly says to use it to follow a calculation started by upload_and_quote or quote_part until status is final, lists the terminal statuses, gives polling cadence ('check again every few seconds'), and names the alternative (explain_cost) for short answers.

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

get_cost_breakdownGet Cost BreakdownA
Read-onlyIdempotent
Inspect

Get the itemised cost sheet of a calculation as one tree: headline, cost category, operation and feature, with time and cost side by side. Use it when someone needs the line items, for a negotiation, a work plan or a design review. Each line carries its time, its rate and the factor keys that move it, which preview_cost accepts. persona selects the tiers and quantity restates the headline, times and cost tier at another lot size. max_depth sets how deep the cost sheet goes (default 2, the categories and one tier beneath; null for the whole tree), and a line cut short says in children_hidden how many lines it hides. Also returns the stock the part is bought as, with its scrap and remnant credits. For a short summary, use explain_cost. Read-only and free.

NameRequiredDescriptionDefault
personaNoWhich tiers to return: 'full' (the default, every tier), 'procurement' (headline and band), 'workprep' (the operations as a work plan), 'operations' (operations and machines) or 'design' (the cost sheet and feature drivers).full
quantityNoLot size to read the headline, the times and the cost tier at; omit for the lot the calculation was priced for. The operations, feature and material_stock tiers describe the priced lot either way.
max_depthNoHow many tiers of cost_lines to return: 1 the cost categories only, 2 (the default) the categories and the tier beneath, null the whole tree. A line cut short states in children_hidden how many lines sit beneath it. With a depth set, a line also leaves out the keys it has no value for (null, [] or {}).
calculation_idYesId of a calculation, as upload_and_quote, quote_part or list_calculations return it.

Output Schema

NameRequiredDescription
basisNoWhere the figures at `quantity` come from: 'priced' (the ordered lot, exact), 'curve_point' (recorded on the calculation's lot-size curve while pricing) or 'restated' (priced from the same closed form the curve was built from). Null when the calculation records no lot-size curve.
errorNoWhy this calculation produced no price, in one sentence, when its status is terminal (failed / cancelled).
statusYes
personaYesThe persona view this result is sliced for.
currencyNoThe calculation's currency; every money figure here is in it.
featuresNo
guidanceYes
machinesNo
quantityNoThe lot size this result is stated at: the calculation's own ordered lot unless `quantity` was passed, in which case the headline, the times and the cost tier are all at that lot size.
cost_bandNo[low, high] prediction band for the unit cost. Stated at the lot the calculation was priced at only: the band is fitted to that run and does not carry to another quantity.
unit_costNoUnit cost per part at `quantity`: direct cost plus overhead_var and overhead_fixed. Where the costing environment states no Material-/Fertigungsgemeinkosten, overhead_var is the flat variable overhead the environment states (none by default); once it states them, those overheads sit above unit_cost as cost-sheet rungs, with administration and selling, margin and the other surcharges. The price to quote is offer_price.
confidenceNoQuote-trust signal — the headline the procurement / supplier persona reads together with the prediction band.
cost_linesNoThe itemised cost sheet as a tree — every category with the tiers beneath it, each carrying its time, its rate and the factors that move it.
operationsNo
setup_costNoSetup cost for the whole lot at `quantity`, in `currency` — the sheet's setup line times the lot.
total_costNounit_cost for the whole lot at `quantity`, on the same basis as unit_cost.
offer_priceNoThe offer price per unit — unit_cost plus the cost-sheet surcharges the costing environment states; equal to unit_cost when no sheet is stated. The SAME figure explain_cost states, so the shareable procurement headline is the price, not the bare manufacturing cost. Absent on older calculations.
unit_time_sNoTime per unit at `quantity`, in seconds, across every activity: machine time plus the bench work plus the per-part programming and inspection shares. One meaning at every lot size, and never smaller than `machine_time_s`. Null at a lot size a calculation priced before the two were told apart.
needs_reviewNoTrue when this cost needs a human check before it is trusted. Reported for EVERY persona — a trust flag must never be sliced away, or a persona that doesn't get the review tier reads a flagged cost as clean.
setup_time_sNoSetup time for the whole lot at `quantity`, in seconds.
material_noteNo
calculation_idYes
machine_time_sNoMachine time per unit at `quantity`, in seconds: the billable run plus the finishing pass under the allowance.
material_stockNoThe stock the part is bought as — format, size, parts per stock — its mass balance, and the material line's purchase and credits, at the lot the calculation was priced for whichever quantity was asked. Null on a catalogue part and on a calculation priced before 2026-08-28, which recorded no material detail; one priced before the 2026-09-26 release states no scrap or remnant mass and no bar length.
cost_categoriesNoPer-unit cost by category, keyed by the cost sheet's own bucket slugs (material, setup, machine, labour, programming, tooling, inspection, finishing, subcontract, then the surcharge ladder). The top level of ``cost_lines`` flattened: same numbers, in the calculation's currency, adding up to the price per part.
currency_factorNoWhat every money figure here was multiplied by to carry it from the environment's rate currency into `currency`; 1.0 when the two are the same. The prices and per-lot charges in a cost line's `label_params` are in the rate currency, so a line's amount is that arithmetic (mass x price per kilogram, time x rate) times this factor — and times the calibration it was charged at on a calibrated environment. Absent where the calculation does not state it.
machine_name_at_nNoThe machine the figures at `quantity` were priced on, where it differs from or restates the calculation's own route.
material_resolvedNo
selection_failureNoThe same refusal as data when no machine in the costing environment could make the part.
cost_sheet_rebuiltNoTrue when the sheet was reconstructed from the rates, times and cost lines this calculation stored rather than recorded while it was priced. A reconstructed sheet carries the cost categories and the surcharge ladder but not the per-machine, per-clamping or per-operation tiers — those are recorded only while pricing and cannot be derived afterwards. Every amount is the amount charged either way. Null when no sheet was read for this persona.
costing_environment_idNoThe costing environment this was priced in: the machines, rates and overheads the factors named in each line's ``factors`` belong to.
inputs_changed_since_runNoNull when this price reflects every input on its part revision. Otherwise {roles, corrections, latest_at}: files attached and corrections applied to the part after the run read its inputs, which a new calculation reads and this one did not.
environment_changed_since_runNoNull when this price was computed on its costing environment as it stands. Otherwise {latest_at}: the environment was edited after the run read it, and a new calculation prices with the current setup while this result does not.

TDQS

A4.6/5.0
Behavior4/5

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

Annotations already cover read-only, idempotent, non-destructive and closed-world, so the bar is lower, yet the description still adds real behavior: the call is 'free', max_depth defaults to 2, cut lines report children_hidden, keys with no value are omitted when a depth is set, and quantity only restates headline/times/cost tier. It stops short of describing ordering or size limits, so not a 5.

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 purpose and tree shape are front-loaded, then usage cases, then per-parameter behavior — a logical order with little filler. It is dense and long for a read tool, and the material_stock sentence sits mid-paragraph rather than with the other return-shape content, which costs it a point.

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?

With an output schema present, return values need no explanation, yet the description still flags the notable extras (truncation via children_hidden, null-key omission, material stock with scrap/remnant credits). Given four params and full schema coverage, an agent has everything needed to call it correctly.

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

Parameters4/5

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

Schema coverage is 100%, so baseline is 3; the description still adds interpretive value by explaining that persona 'selects the tiers', that quantity only moves the headline/times/cost tier while other tiers stay at the priced lot, and that the returned factor keys are what preview_cost accepts. These are cross-tool semantics the schema text does not fully convey.

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?

States a specific verb and resource ('Get the itemised cost sheet of a calculation') and describes the exact shape returned — a tree of headline, cost category, operation and feature with time and cost side by side. It explicitly separates itself from explain_cost (short summary) and links to preview_cost for the factor keys, so an agent can tell it apart from siblings.

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?

Gives concrete use cases ('when someone needs the line items, for a negotiation, a work plan or a design review') and names the alternative for the lighter case: 'For a short summary, use explain_cost.' Nothing about tool selection is left to inference.

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

get_precheckGet PrecheckA
Read-onlyIdempotent
Inspect

Read a precheck from precheck_part: its status and, once read, how its calculation splits, how many calculations it starts and what the plan pays for them. Use it until status is no longer received. Read-only and free.

NameRequiredDescriptionDefault
precheck_idYesThe precheck, as precheck_part returned it.

TDQS

A3.9/5.0
Behavior4/5

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

Annotations already declare readOnly/idempotent/non-destructive, so the description's real contribution is that results become available only 'once read' (progressive enrichment) and that the call is 'free' (no quota cost, relevant given the check_quota sibling). That is useful behavior beyond the annotations, though it doesn't cover latency or failure modes.

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?

Three short clauses, with the core action and the polling rule front-loaded; the mid-sentence list of result fields is slightly dense but every sentence carries information.

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

Completeness4/5

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

There is no output schema, so the description usefully summarizes what comes back (status, split, calculation count, plan payment). Combined with the annotations and fully documented parameter, an agent has enough to call and interpret it, though the transition path after status resolves is left implicit.

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

Parameters3/5

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

Single parameter with 100% schema description coverage, so the schema already documents the UUID and its origin in precheck_part. The description reinforces the precheck_part linkage but adds no format or constraint detail beyond the schema.

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

Purpose4/5

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

States a specific verb and resource ('Read a precheck from precheck_part') and enumerates the payload (status, calculation splits, number of calculations, plan payment), which lets an agent tell it apart from siblings like get_calculation or get_process_plan. The phrasing 'how its calculation splits' is a bit opaque, keeping it short of a 5.

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

Usage Guidelines4/5

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

'Use it until status is no longer received' gives concrete polling guidance, and naming precheck_part implicitly routes creation to that sibling. It does not explicitly say what to do after the status changes (e.g., switch to get_calculation), so a small gap remains.

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

get_process_planGet Process PlanA
Read-onlyIdempotent
Inspect

Get the process plan (Arbeitsplan) of a calculation: the operations in the order they run, each with its work center and cycle time, then the post-processing chain such as welding, heat treatment and coating with what each is charged per part. Also returns the setup, cycle and total time, the machines used, how many times each one clamps the part, and the processes the drawing asks for that no machine here can do. Use it for work preparation, scheduling or to check how the part is made. Machining cost sits with the features, not with the steps. explain_cost ranks the features. Read-only and free.

NameRequiredDescriptionDefault
calculation_idYesId of a calculation, as upload_and_quote, quote_part or list_calculations return it.

Output Schema

NameRequiredDescription
errorNoWhy this calculation produced no plan, in one sentence, when its status is terminal (failed / cancelled).
stepsNo
statusYes
currencyNoThe calculation's currency — the basis of every subcontract_per_part figure on the steps.
guidanceYes
machinesNoMachine(s) / work center(s), in route order.
unpricedNoWork the drawing requires that no machine in this environment can do, so it is not in the price. Each entry names the process and why. Absent when the route covers what the drawing asks for.
clampingsNoHow many times each machine clamps the part, in route order — the same count the route was costed on. Absent when the route did not state a count.
unit_time_sNoTotal time per unit, seconds.
cycle_time_sNoTotal machining cycle time per unit, seconds.
setup_time_sNoOne-time setup time for the whole lot, in seconds (NOT per unit; divide by the lot size for the per-unit share).
calculation_idYes
machine_time_sNoMachine time per unit in seconds: the billed run plus the finishing pass, under the allowance. Absent on older calculations.
operation_countNoNumber of process steps in the plan.
selection_failureNoThe same refusal as data when no machine in the costing environment could make the part.
price_completenessNo'partial' when `unpriced` lists work the price leaves out — the plan covers the rest and the price is a lower bound; 'complete' when it covers everything. Absent before the contract.

TDQS

A4.2/5.0
Behavior3/5

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

Annotations already declare readOnlyHint, idempotentHint and destructiveHint=false, so 'Read-only and free' largely restates structured data (though 'free' adds quota-relevant context). The description does disclose what data is returned and the notable caveat that machining cost is not attributed to steps — useful beyond annotations — but adds nothing on pagination, failure modes, or what happens with an invalid/expired calculation id.

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?

Purpose is front-loaded in the first clause and every sentence carries information. The long enumeration of return fields is somewhat dense and partly redundant with the output schema, costing a point on tightness.

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?

For a single-parameter read tool with full schema coverage, annotations and an output schema, the description supplies purpose, content scope, intended use, and the cost-attribution caveat. An agent has everything needed to select and call it correctly.

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

Parameters3/5

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

Schema coverage is 100% with a single required parameter whose description already explains provenance ('as upload_and_quote, quote_part or list_calculations return it'). The description adds no parameter-level detail, so the baseline 3 applies.

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?

States a specific verb and resource ('get the process plan of a calculation') and enumerates its contents: ordered operations with work center and cycle time, post-processing chain with per-part charges, setup/cycle/total times, machines, clamping counts, and infeasible drawing requirements. This is far more specific than siblings like get_calculation or get_cost_breakdown allow an agent to distinguish.

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?

Explicitly names intended uses ('work preparation, scheduling or to check how the part is made') and routes the agent away for costing: 'Machining cost sits with the features, not with the steps. explain_cost ranks the features.' Both when-to-use and the alternative are stated.

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

list_calculationsList CalculationsA
Read-onlyIdempotent
Inspect

List this organization's calculations, newest first, each with its status, lot size, unit cost and offer price. Use it to find calculations started outside this conversation, such as the ones a person starts on the upload page (upload_session_id set to the link's upload_session_id lists exactly those), or to check many at once (ids, up to 500). Filter by status, part or batch. Page with cursor until has_more is false. For one calculation in full, use get_calculation. Read-only and free.

NameRequiredDescriptionDefault
idsNoComma-separated calculation IDs (max 500). THE polling surface for bulk clients: one weight-1 sweep returns the status of every listed calculation, instead of N weight-1 detail requests that exhaust the per-org rate budget (self-DoS). When set, `limit` and ordering are ignored and every matching row is returned.
sortNoOrdering key. Rows with no value yet (an in-flight run has no unit cost) sort last in both directions. Ignored when `ids` is set. `offer_price` orders on the price each calculation headlines and the comparison ranks on (the item's `offer_price`; an assembly priced only in part states none and sorts last); `unit_cost` on the unit cost (direct cost plus the flat overheads, below the cost-sheet rungs). `created_at`, `offer_price`, `lot_size` and `annual_volume` support `cursor`; `unit_cost` and `finished_at` are null until a run settles, so a cursor over them cannot reach every row and is rejected — those two return the first page only.created_at
limitNoMaximum rows to return in one page.
orderNoSort direction over the collection's ordering key. Use `asc` to reconcile a batch: rows come oldest-first, so work created while you page lands after your position instead of shifting rows under it.desc
cursorNoOpaque position token from the previous page's `next_cursor` (or the `Link` / `X-Next-Cursor` response header). Omit it for the first page. Keep every other query parameter identical for the whole walk — a cursor replayed against different filters is rejected.
part_idNoOnly the calculations of this part, by its id (part_id on any calculation).
batch_idNoNarrow to one batch's calculations — e.g. every cell of a multi-environment comparison grid. Pair with the batch comparison endpoint, which returns the pivoted matrix.
created_afterNoOnly rows created at or after this instant (RFC 3339, e.g. `2026-07-20T09:00:00Z`). Inclusive.
include_totalNoAlso return the total number of rows matching the query, across all pages. Off by default because it costs an extra scan; `has_more` is the cheap way to know whether to keep paging.
status_filterNoFilter by lifecycle status (e.g. queued, running, succeeded, failed, cancelled). Repeatable; several values are OR-ed.
created_beforeNoOnly rows created strictly before this instant (RFC 3339). Exclusive, so an `after`/`before` pair tiles a range without overlap.
include_facetsNoAlso return `facets`: status and material values with counts, each computed over everything the OTHER active filters allow.
material_grade_idNoOnly runs priced against one of these material grades. Repeatable; several values are OR-ed, so passing every value is the same as passing none.
upload_session_idNoOnly the calculations created through one upload link, by the `upload_session_id` the link was issued with — the parts a person uploaded on its page, and no one else's.
include_componentsNoWith `part_id`: also list the calculations this part received as a component of an assembly (each at the lot the assembly implied). Ignored without `part_id`.
parent_calculation_idNoOnly the component calculations of this assembly. By default the list contains top-level calculations only — assembly components are reachable through their parent.

TDQS

A4.3/5.0
Behavior4/5

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

The annotations already declare readOnlyHint, idempotentHint, destructiveHint=false and closed-world, so safety is covered. The description adds non-annotation context: that the call is 'free' (no quota cost) and that results come back newest-first by default with cursor-based paging. It does not, however, describe the free/paid distinction in more detail, nor the failure modes when a cursor is replayed against changed filters.

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?

Front-loaded with what is listed and in what order, then usage, filtering, paging and the alternative — a sensible priority order. It is dense but nearly every clause carries information; the nested parenthetical about upload_session_id is slightly convoluted to parse but still short.

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

Completeness4/5

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

With 16 optional parameters and no output schema, the description covers the returned shape at a high level (status, lot size, unit cost, offer price) and the paging contract, which is what an agent needs to iterate. It omits mention of several parameters (facets, include_total, created_after/before, parent_calculation_id), but those are fully documented in the schema, so the description is adequate for correct invocation.

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

Parameters3/5

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

Schema description coverage is 100% and the parameter descriptions are exceptionally rich (ids polling guidance, cursor consistency rules, sort/cursor compatibility). The description's own parameter mention ('ids, up to 500', 'filter by status, part or batch') merely restates a fraction of what the schema already documents, so it adds no meaningful semantics beyond the structured fields. Baseline 3 is correct.

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?

States a specific verb and resource ('List this organization's calculations'), the default ordering ('newest first'), and the fields returned ('status, lot size, unit cost and offer price'). It also explicitly distinguishes itself from get_calculation, so an agent can choose between them without opening either schema.

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?

Gives concrete use cases (finding calculations started outside the conversation, bulk status checks via ids up to 500), names the sibling alternative for the single-record case ('For one calculation in full, use get_calculation'), and states the paging termination condition ('until has_more is false'). This is explicit when/when-not/alternative guidance.

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

list_environmentsList EnvironmentsA
Read-onlyIdempotent
Inspect

List the organization's costing environments, newest first. Each one is a set of machines, rates and overheads for a plant, a supplier or a region. Use it to find the environment id to price a part in. Without one, upload_and_quote and quote_part use the organization's default environment. Page with cursor until has_more is false. Read-only and free.

NameRequiredDescriptionDefault
limitNoMaximum rows to return in one page.
orderNoSort direction over the collection's ordering key. Use `asc` to reconcile a batch: rows come oldest-first, so work created while you page lands after your position instead of shifting rows under it.desc
cursorNoOpaque position token from the previous page's `next_cursor` (or the `Link` / `X-Next-Cursor` response header). Omit it for the first page. Keep every other query parameter identical for the whole walk — a cursor replayed against different filters is rejected.
offsetNoRows to skip. Superseded by `cursor`, which is stable under concurrent writes; kept for existing integrations. Bounded — past the cap, page with `cursor`.
created_afterNoOnly rows created at or after this instant (RFC 3339, e.g. `2026-07-20T09:00:00Z`). Inclusive.
created_beforeNoOnly rows created strictly before this instant (RFC 3339). Exclusive, so an `after`/`before` pair tiles a range without overlap.

Output Schema

NameRequiredDescription
dataYesThis page's rows, in the order and shape the REST list returns them.
has_moreYesFalse on the last page. Stop on this, never on a short page.
next_cursorYesPass as `cursor` to read the next page. Null on the last page.

TDQS

A4.4/5.0
Behavior4/5

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

Annotations already declare readOnly, idempotent, non-destructive and closed-world, and the description reinforces this with 'Read-only and free' — 'free' adds quota-relevant context not present in the annotations. It also discloses pagination behavior ('Page with cursor until has_more is false'), which is genuinely useful beyond the structured fields, though it doesn't detail rate limits or default page size.

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?

Front-loaded with purpose, then identity, then usage routing, then paging mechanics — a good ordering with no wasted sentences. 'Read-only and free' is mildly redundant with the readOnlyHint annotation, which keeps it from a 5.

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?

With an output schema present, the description needn't document return values, and it still covers purpose, sibling routing, the default-environment fallback, and the cursor walk. Nothing an agent needs to call this correctly is missing.

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

Parameters3/5

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

Schema description coverage is 100% and the parameter docs are unusually rich (order explains the reconciliation use of `asc`, cursor explains the replay/rejection rule), so the schema does the heavy lifting. The description only gestures at paging via cursor and adds no syntax beyond that, making the baseline 3 appropriate.

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?

States a specific verb and resource ('List the organization's costing environments') plus the ordering ('newest first') and what an environment actually is ('a set of machines, rates and overheads for a plant, a supplier or a region'). No sibling tool lists environments, so the agent can distinguish this immediately.

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?

Gives explicit when-to-use ('find the environment id to price a part in') and names the downstream alternatives with the fallback condition: 'Without one, upload_and_quote and quote_part use the organization's default environment.' This routes the agent correctly without any inference.

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

optimize_lot_sizeOptimize Lot SizeA
Read-onlyIdempotent
Inspect

Find the lot size with the lowest total cost for a calculation: production cost plus holding cost (capital tie-up and storage), capped at one year of demand. Use it to answer how many parts to make per batch. Returns the optimal lot, the yearly saving of moving there, the cost-versus-quantity curve, an Andler/EOQ cross-check and at most two directions (change the lot size, cut setup time). To price one other lot size exactly, use preview_cost. Read-only and free.

NameRequiredDescriptionDefault
calculation_idYesId of a calculation, as upload_and_quote, quote_part or list_calculations return it.

Output Schema

NameRequiredDescription
curveNoCompact curve points: {quantity, unit_cost, direct_unit_cost (before overhead, setup amortised over that lot), offer_price (the per-unit figure a quote shows), setup_time_s, unit_time_s} — cost AND time vs quantity in one read, when present; money in currency. Exact at exact_at_quantity, indicative elsewhere (see accuracy).
statusYes
accuracyNoHow far a curve point may sit from a real run at that quantity, as the API publishes it: {basis, max_deviation_pct, note}. Null on older calculations.
currencyNoCurrency every money figure on this result is stated in (the calculation's), the optimum and the curve alike.
guidanceYes
scenarioNoThe scenario recommended_lot_size states — buyer_stock: the buyer orders in lots and holds the stock. Absent on older calculations.
scenariosNoEvery lot-size scenario's answer on the same curve: buyer_stock, supplier_stock (the supplier produces ahead of a steady call-off and holds the stock, economic production quantity), make_to_order (shipped complete, consumed on delivery — only the supplier's work in progress is held), joint (a frame contract with call-offs, both parties' costs minimised together: the call-off and the supplier's production lot) and consignment (the frame contract with supplier-owned stock at the buyer's site until use — capital at the supplier's production cost on every unit, storage where it sits). Pick the one that is your situation. Empty on older calculations.
annual_volumeNoAnnual demand the optimum weighs holding against.
calculation_idYes
andler_lot_sizeNoClassic Andler/EOQ closed-form cross-check quantity.
recommendationsNoAt most two solid optimization directions; empty when nothing material or the calculation predates the optimum.
valuation_basisNoHow the scenarios value a piece. purchase_price: the buyer pays and holds at the purchase price after the supplier's customer and cash discounts; the supplier holds at production cost including material and production overheads. offer_price: a calculation made before that basis — the buyer at the offer price, the supplier's stock at manufacturing cost; recalculate to restate it. Absent on older calculations.
current_lot_sizeNo
current_unit_costNoProduction cost per piece at the ordered lot, in currency.
exact_at_quantityNoThe lot this calculation was run for: the curve reproduces its price exactly here and is indicative at every other quantity. Null on older calculations.
net_annual_savingNoNet saving per year of moving to the recommended lot, production plus inventory holding, in currency.
single_lot_demandNoTrue when one lot already covers the whole annual demand (annual_volume ≤ current_lot_size). There is then no lot-size trade-off to optimise: the recommendation equals the current lot by construction, not because the lot is economically optimal. annual_volume defaults to 1 when a request omits it — pass the real annual demand to get a recommendation.
recommended_lot_sizeNoTotal-cost optimal lot (≤ one year of demand).
recommended_unit_costNoProduction cost per piece at the recommended lot, in currency.
ordering_cost_per_orderNoThe buyer's fixed cost per order or delivery (order handling and inbound freight) the buyer-side scenarios weigh against the price breaks (0 where the environment states none), in currency.
inputs_changed_since_runNoNull when this price reflects every input on its part revision. Otherwise {roles, corrections, latest_at}: files attached and corrections applied to the part after the run read its inputs, which a new calculation reads and this one did not.
production_rate_per_yearNoPieces the route can make in a year of its machines' run hours — the finite production rate behind the supplier and joint scenarios. Absent where no machine states annual hours.
current_effective_unit_costNoThe buyer's effective cost per piece at the ordered lot (buyer_stock): the price per piece on the basis valuation_basis names, plus the per-piece ordering and inventory holding cost, in currency.
environment_changed_since_runNoNull when this price was computed on its costing environment as it stands. Otherwise {latest_at}: the environment was edited after the run read it, and a new calculation prices with the current setup while this result does not.
recommended_effective_unit_costNoThe buyer's effective cost per piece at the recommended lot (buyer_stock), on the same basis as current_effective_unit_cost, in currency.

TDQS

A4.4/5.0
Behavior4/5

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

Openness is largely covered by the readOnly/idempotent/non-destructive annotations, but the description still adds real context: the one-year-of-demand cap on the search space, and that it returns at most two recommendations. 'Read-only and free' is mild repetition of the annotations, keeping it from a 5.

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?

Front-loaded with purpose, then usage, then the return payload in one dense paragraph with zero filler sentences. The return-value enumeration is slightly redundant given an output schema exists, but it is compact and useful for triage.

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?

For a one-parameter, read-only analytical tool with an output schema and full annotations, the description supplies everything needed: the cost model, the search constraint, when to call it versus preview_cost, and what the answer contains.

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

Parameters3/5

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

The single parameter has full schema coverage and the schema already explains where calculation_id comes from, so the description is correctly not spending words on it. It adds domain framing (the optimization is scoped to the calculation) but no parameter-level detail beyond the schema.

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?

States a specific verb and objective ('find the lot size with the lowest total cost') plus the exact cost model (production + holding/capital tie-up + storage) and the cap of one year of demand. It also names the sibling preview_cost as the different tool, so an agent can distinguish them without reading schemas.

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?

Gives a concrete use case ('answer how many parts to make per batch') and an explicit routing rule: 'To price one other lot size exactly, use preview_cost.' The boundary between optimizing and previewing is unambiguous.

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

precheck_partPrecheck PartA
Destructive
Inspect

See what a CAD file's calculation will do before it starts: free, never billable. Send the STEP file as base64 (gzip accepted) and optional drawings. ARCNM reads it the way the calculation will and answers how an assembly splits into made parts, catalogue parts and parts left out, how many calculations it starts, how many the plan pays for (metered_max) and the overage it may cost. Usually answers within seconds; while status is received, read it again with get_precheck. A drawing its names did not match goes to its part with attach_drawing (precheck_id and the row's component_key). Start it with upload_and_quote, passing precheck_id and its revision: the calculation is what was shown, and max_overage_cents caps what it may cost past the plan. A precheck nobody starts is deleted with its files after 24 hours.

NameRequiredDescriptionDefault
batch_idNoGroups the files of one drop; they are answered in position order.
drawingsNoDrawings of the assembly or its parts.
positionNoOrder of this file in its drop.
part_numberNoThe part number it will be started under.
cad_file_b64YesBase64 (or a data: URI) of the STEP file; gzip-compressed is accepted.
cad_filenameYese.g. frame.step — used for format detection.
cad_content_typeNoMIME type of the file, when known.

TDQS

A4.6/5.0
Behavior5/5

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

Annotations declare destructiveHint=true, readOnlyHint=false and openWorldHint=false, and the description explains the destructive dimension directly: a precheck nobody starts is deleted with its files after 24 hours. It also adds traits annotations cannot express — the operation is free/never billable, it returns asynchronously within seconds, and cost past the plan is capped at start time via max_overage_cents. No contradiction with the declared write/destructive profile.

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?

Purpose and the free/non-billable guarantee are front-loaded, and every sentence conveys operational information. It runs as one long paragraph with several clauses chained together (metered_max, overage, polling, attach, start), which costs some scannability but no sentence is filler.

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?

There is no output schema, and the description compensates by enumerating what comes back: how the assembly splits into made/catalogue/excluded parts, how many calculations start, how many the plan pays for (metered_max) and the possible overage. Combined with the async polling contract and expiry rule, an agent has everything needed to call and follow up correctly.

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

Parameters3/5

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

Schema description coverage is 100%, so the schema already carries batch_id grouping, position ordering, drawing structure and the gzip/data-URI acceptance. The description restates the base64/gzip file convention and drawings but adds no new semantics for batch_id, position, part_number or content types; baseline 3 applies.

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 gives a concrete verb and resource — it previews what a CAD file's calculation will do before the calculation is started, and returns a breakdown of made parts, catalogue parts, excluded parts and metered counts. It also names the siblings that handle the follow-up steps (get_precheck for polling, attach_drawing for drawings, upload_and_quote for starting), so an agent can place it precisely among 18 tools.

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?

Usage is spelled out with conditions and alternatives: send the STEP file as base64, poll with get_precheck while status is received, route unmatched drawings via attach_drawing with precheck_id and component_key, and start the calculation with upload_and_quote passing precheck_id and max_overage_cents. The 24-hour non-started expiry is an explicit consequence, not left to inference.

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

preview_costPreview CostA
Read-onlyIdempotent
Inspect

Price a what-if on a priced calculation without saving anything: move cost factors (a rate, a time allowance, the material price) or the lot size, and get the new cost sheet with the change per cost category. Use it to test a cheaper option before deciding. Free: it uses no calculation of the quota and changes nothing, not this calculation and not its costing environment. The part is re-priced by the same engine, so the answer is a price, not an estimate. A factor outside its allowed range is refused by name. By default it answers with a summary: the headline before and after, the change per cost category and only the cost lines that moved; pass detail='full' for the whole previewed cost sheet. To price the part for real, use quote_part. Read-only.

NameRequiredDescriptionDefault
detailNo'summary' (the default): the headline before and after, the change per cost category and only the cost lines that moved. 'full': the whole previewed cost sheet in cost_lines instead.summary
lot_sizeNoLot size to price the what-if at. Omit to keep the calculation's own lot size.
adjustmentsNoThe factors to move, as {factor_key: new_value}. The keys are the ones get_cost_breakdown shows on each cost line. Omit to re-price at another lot_size only.
calculation_idYesId of a calculation, as upload_and_quote, quote_part or list_calculations return it.

Output Schema

NameRequiredDescription
afterNodetail='summary' only: the headline under the what-if.
deltaNoChange per top-level cost category, new minus current. A category on only one side carries its whole amount, so a line that appears or disappears is visible rather than skipped.
beforeNodetail='summary' only: the priced calculation's headline.
currencyNo
guidanceYes
lot_sizeNoLot size this preview was priced at.
unit_costNoCost per part under the adjustments — the manufacturing cost, on the same basis as the calculation's own unit cost, so the two are directly comparable. The offer price with your surcharges and mark-up on top is the sum of every top-level line in ``cost_lines``.
cost_linesNoThe previewed cost sheet as a tree, same shape as get_cost_breakdown's. Empty under detail='summary'.
reconciledNoWhether every tier of the previewed sheet added up to the line above it. False means a tier was dropped rather than shown not adding up — read the amounts, not the missing tier.
adjustmentsNoThe factor values this preview was priced at, echoed back.
moved_linesNodetail='summary' only: every cost line, at any depth, whose amount moved, each with its path in the tree. Top-level lines only when the calculation recorded no itemised sheet to compare.
total_deltaNoChange in the cost per part against the priced calculation: new minus current, in the currency above.
calculation_idYes

TDQS

A4.6/5.0
Behavior5/5

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

Beyond the read-only annotations, the description discloses important behavior: nothing is saved, no quota is consumed, neither the calculation nor its costing environment changes, invalid factors are refused by name, and the result is a real re-priced answer rather than an estimate. It also explains the default summary output versus detail='full'.

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 core purpose and usage are front-loaded in the first two sentences, and the rest adds useful behavioral context. It is slightly longer than necessary, with some repetition around 'without saving anything' and 'changes nothing', plus a trailing 'Read-only' that restates the annotation.

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?

With annotations covering safety and an output schema covering return shape, the description supplies all additional context an agent needs: what the tool previews, what changes, quota impact, validation behavior, and when to use quote_part instead.

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

Parameters3/5

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

Schema description coverage is 100%, so parameter meanings are already well documented. The description reinforces the concepts of cost factors, lot size, and detail levels, but does not add syntax or format details beyond what the schema already provides.

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 states a specific verb and resource — pricing a what-if on a priced calculation — and explains exactly what can be moved: cost factors or lot size. It distinguishes the tool from quote_part, which prices the part for real, so an agent can tell the two apart without opening either schema.

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 explicitly says to use this tool to test a cheaper option before deciding, and names quote_part as the alternative for real pricing. It also clarifies that the tool is free, uses no quota, and changes nothing, which gives clear conditions for choosing it.

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

quote_partQuote PartA
Destructive
Inspect

Price a part that is already in ARCNM again: at another lot size, with another material or stock format, or in another costing environment. Use it when the part has a revision. Every calculation carries its part_revision_id (get_calculation). With derived_from_calculation_id it keeps that calculation's material and annual_volume unless you pass them. Pass several costing_environment_ids to price it in up to 16 environments at once. The runs share a batch_id. Billable: each part in each environment uses one calculation of the quota, only if it succeeds. An assembly uses one per different part. The calculation runs in the background. Returns the calculation id, its status and eta_seconds. Follow it with get_calculation. For a free what-if on a priced calculation, use preview_cost. For a new file, use upload_and_quote.

NameRequiredDescriptionDefault
nameNoOptional human-readable label; defaults to a timestamped name when omitted.
engineNoPricing engine selector; retained for back-compat and always normalized to the sole engine.arcnm
regionNoPricing region override; defaults to the costing environment's region when omitted.
currencyNoISO 4217 currency code for the quote; defaults to the costing environment's currency when omitted. Another currency needs an exchange rate from the environment's currency: a code that is not ISO 4217 is refused with 422 `currency_unknown`, one the environment has no exchange rate into with 422 `currency_not_configured`, before any calculation is created.
languageNoBCP 47 language for the calculation's captured context (e.g. 'de', 'en'). Part of the calculation's cache identity.de
lot_sizeNoNumber of identical parts produced per batch (1 to 1,000,000,000).
material_refNoFree-form material reference (URN, Werkstoffnummer, AISI/SAE code, trade name, or your SKU); resolved to a material grade. Unresolvable values are rejected with 422 material_unresolved plus ranked candidates. Omit to price the material read from the part's drawing (or the environment default). On a re-run (`derived_from_calculation_id`), omitting both it and `material_grade_id` keeps the material the calculation re-run was asked for (one read from its drawing is read again); send `null` to price the drawing's material instead.
nest_item_idNoPrice this calculation's material on its part's line of a job nest — the `id` of a line (`items[].id`) of a job nest that has solved it. The material is then the line's share of the sheets the job nest cut it from together with other parts, less its share of what their skeleton and reusable rests earn back; everything else is priced as usual. The line must be of your organization, of this costing environment and of this part revision, and its job nest must have solved it; otherwise the request is rejected with 422 `nest_item_unresolved`, `details.reason` saying why. It cannot be combined with `stock_format_id` or with customer-supplied material. An upload creates a new part revision, so the upload forms reject every line. A line of the sheets an assembly shares among its own components prices that assembly only: naming one is rejected as `not_found`, and a re-run of such a component prices it on its own sheet. Omit it to price the part on its own sheet. On a re-run (`derived_from_calculation_id`), omitting it keeps the line of the calculation re-run; send `null` to price the part on its own sheet.
annual_volumeNoExpected yearly quantity, used for amortizing setup over the run (1 to 1,000,000,000). On a re-run (`derived_from_calculation_id`), omitting it keeps the annual volume of the calculation re-run.
dataset_link_idNoUUID of a specific dataset link to use; omit to use the revision's active primary CAD.
stock_format_idNoPrice this calculation on one stock format — the `id` of a format from the `materials_list_stock_formats` tool (toolset `catalog`). An id names the format, not only the version it came from: when the format has been changed since, the version current on the day the calculation is created is used. An id your organization cannot price with today (unknown, retired or hidden) is rejected with 422 `stock_format_unresolved`. When the part cannot be cut from that format — too small, not bought in the part's thickness or material, or one the machine cannot load — or is not cut from sheet at all (milled, turned or bought finished), the calculation is priced as if none had been chosen, and `analytics.pipeline_notes` says why (`stock_format_pin_unavailable`). Omit it to price on the format that uses the least material per part. On a re-run (`derived_from_calculation_id`), omitting it keeps the format of the calculation re-run; send `null` to price without one.
stock_format_mmNoPrice this calculation on a sheet of this size — length and width in mm — instead of a stock format from the `materials_list_stock_formats` tool (toolset `catalog`): the part is laid out on that one sheet, cut to size by your supplier, and the purchased stock says `format_source` `custom`. It cannot be combined with `stock_format_id` or `nest_item_id`. When the part does not fit the sheet, or is not cut from sheet stock at all, the calculation is priced as if none had been stated and `analytics.pipeline_notes` says why. On a re-run (`derived_from_calculation_id`), omitting both it and `stock_format_id` keeps the size or format of the calculation re-run; send `null` to price without one.
part_revision_idYesUUID of the part revision to price.
full_stock_chargeNoHow the started sheet or bar of the lot is charged: `auto` applies the environment's `full_stock_threshold` (the lot pays the whole piece once its parts fill that share of it, the unused cells credited as scrap where scrap is credited); `full` charges the whole piece at any lot; `full_no_credit` charges it whole with no scrap credit on the unused cells; `share` charges only the lot's share at any lot. A lot of whole pieces, or a piece holding one part, is charged the same under every word. On a re-run (`derived_from_calculation_id`), omitting it keeps the word of the calculation re-run.auto
material_grade_idNoUUID of a resolved material grade; takes precedence over material_ref when both are supplied. On a re-run (`derived_from_calculation_id`), omitting both it and `material_ref` keeps the material the calculation re-run was asked for (one read from its drawing is read again).
provided_stock_kindNoShape of the provided stock. 'near_net_profile' (extruded profile) additionally scopes the process plan to the features the profile does not already provide.none
material_is_providedNoTrue when the customer supplies the raw material (beigestellt) — the material cost line is set to zero; machining, setup and overheads are billed normally.
costing_environment_idNoUUID of the costing environment (machine rates, region) to price against. Omit to use your organization's default environment (the auto-provisioned default baseline).
costing_environment_idsNoPrice this part in several environments at once, in comparison order. Each environment becomes one calculation and counts as one against the plan quota. Mutually exclusive with ``costing_environment_id``; duplicates are collapsed preserving first occurrence. The response then carries ``batch_id`` and ``environment_runs``.
derived_from_calculation_idNoThe calculation this one is re-run from — pass it when pricing again after a drawing was attached or from a result's own page, so the new calculation records what it supersedes. Must name a calculation of your organization; the new calculation is its own row and counts as one.

TDQS

A4.8/5.0
Behavior5/5

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

Annotations only flag the call as non-read-only and destructive; the description adds the operational profile that matters: quota is consumed per part per environment, only on success, one per distinct assembly part; multi-environment runs share a batch_id; the calculation runs in the background and returns id, status and eta_seconds, with get_calculation as the follow-up. That is genuine context beyond the structured fields.

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?

Front-loaded with purpose, then usage, then billing/async behavior, then alternatives. Dense but each sentence carries signal; the middle billing sentences are the wordiest part and could be tightened slightly without losing meaning.

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?

For a 20-parameter, billable, asynchronous mutation with no output schema, the description covers everything an agent needs: what it creates (a calculation row), what it costs (quota), that it is async, what the response contains (id, status, eta_seconds, batch_id), and how to retrieve results. Return-shape information is supplied despite the absence of an output schema.

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

Parameters4/5

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

Schema coverage is 100%, so the baseline is 3, but the description adds cross-parameter semantics the schema cannot easily express: derived_from_calculation_id inherits material and annual_volume unless overridden, and several costing_environment_ids price up to 16 environments in one batch. It does not re-explain the remaining 18 parameters, which is appropriate given the rich schema.

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?

States a specific verb and resource ('Price a part that is already in ARCNM') plus the scope variations (lot size, material, stock format, costing environment). It explicitly distinguishes itself from the two nearest siblings, preview_cost and upload_and_quote, so an agent can tell which tool to open without comparing schemas.

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?

Gives the enabling condition ('Use it when the part has a revision') and names concrete alternatives with the condition that selects each: preview_cost for a free what-if on a priced calculation, upload_and_quote for a new file. No routing decision is left to inference.

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

suggest_cost_savingsSuggest Cost SavingsA
Read-onlyIdempotent
Inspect

List the ways a calculation could cost less: lot size and setup, tolerances, material use, outside processes, inspection and programming shares, volume bundling, design-for-manufacturing issues and the gap to a supplier quote when one is on file. Use it to brief a redesign or a supplier negotiation. Each finding names its lever, says whether its figures are exact engine results or directional, and names the method it applies. To price one of them, use preview_cost. Read-only and free.

NameRequiredDescriptionDefault
calculation_idYesId of a calculation, as upload_and_quote, quote_part or list_calculations return it.

Output Schema

NameRequiredDescription
statusYes
currencyNo
findingsNo
guidanceYes
calculation_idYes
human_finding_countNoHow many findings are headline (human-audience) ones.
inputs_changed_since_runNoNull when this price reflects every input on its part revision. Otherwise {roles, corrections, latest_at}: files attached and corrections applied to the part after the run read its inputs, which a new calculation reads and this one did not.
environment_changed_since_runNoNull when this price was computed on its costing environment as it stands. Otherwise {latest_at}: the environment was edited after the run read it, and a new calculation prices with the current setup while this result does not.

TDQS

A4.2/5.0
Behavior4/5

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

Annotations already declare readOnlyHint/idempotent/destructiveHint, so the safety bar is low; the description still adds real value by explaining what each finding contains (named lever, exact engine results vs directional figures, applied method). 'Read-only and free' is partly redundant with the annotations, but the 'free' claim and the finding-shape disclosure are net additions.

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 lever inventory is front-loaded and each sentence carries information, but the long comma-separated list of levers is heavier than an agent needs for selection. Still, no sentence is pure filler and the routing and safety notes come after the main purpose.

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?

With an output schema present, the description need not explain return values, and annotations cover safety. It supplies purpose, usage contexts, the alternative for pricing, the nature of the findings, and the cost of the call — everything an agent needs to select and invoke it correctly.

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

Parameters3/5

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

One parameter at 100% schema description coverage, so the schema already fully documents calculation_id and even points at the tools that return it. The description adds only indirect parameter context ('the gap to a supplier quote when one is on file'), which is the expected baseline for a fully documented single-param tool.

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?

States a specific verb and resource (list cost-reduction levers for a calculation) and enumerates the levers concretely rather than abstractly. It also distinguishes itself from the sibling that prices a lever ('use preview_cost'), so an agent can separate it from the other analysis tools without opening a schema.

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

Usage Guidelines4/5

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

Gives clear intended contexts ('brief a redesign or a supplier negotiation') and an explicit alternative with its condition ('To price one of them, use preview_cost'). It does not, however, contrast itself against the other analysis siblings such as explain_cost or get_cost_breakdown, so the routing is helpful but not exhaustive.

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

upload_and_quoteUpload And QuoteA
Destructive
Inspect

Price a new part from its CAD file in one call (German: Fertigungskosten). Send a STEP file as base64, or a DXF flat pattern with sheet_gauge_mm and a material; a PDF drawing is optional (tolerances, finishes, treatments). It files the part under part_number and starts the calculation; after precheck_part, send precheck_id and no file. Billable: one calculation per different part and costing environment, only if it succeeds; copies of one part count once, a catalogue part such as a screw not at all. A single part may be up to 5 MB, an assembly up to 25 MB; send a large STEP gzip-compressed, about 5x smaller. It runs in the background, usually for seconds; returns the calculation id, status, eta_seconds and the part. Follow it with get_calculation. File on the person's computer: get_upload_link. Part already in ARCNM: quote_part.

NameRequiredDescriptionDefault
engineNoPricing engine selector; retained for back-compat and always normalized to the sole engine.arcnm
regionNoPricing region override; defaults to the costing environment's region when omitted.
currencyNoISO 4217 currency code for the quote; defaults to the costing environment's currency when omitted.
languageNoBCP 47 language for the calculation's captured context (e.g. 'de', 'en'). Part of the calculation's cache identity.de
lot_sizeNoNumber of identical parts produced per batch (1 to 1,000,000,000).
folder_idNoOptional workspace folder to file the created part into.
on_conflictNoHow to resolve a part_number that already exists: keep_folder (add a revision, leave the part where it is — the historical behaviour), move (add a revision and re-file into folder_id), new_part (create a separate part under a distinct number), or skip (upload nothing, create no calculation, meter nothing). The outcome is always reported in ``filing``.keep_folder
part_numberYesNatural-key part number; reused to attach a new revision if the part already exists.
precheck_idNoStart this precheck (the app only (not available over MCP)): its stored file, drawings and statements — send no file. Starting it again answers with the calculation it started.
cad_file_b64NoBase64 (or a data: URI) of the 3D CAD file (e.g. STEP). Required unless precheck_id is sent.
cad_filenameNoCAD filename including extension, e.g. bracket.step — used for format detection. Required with cad_file_b64.
material_refNoFree-form material reference (URN, Werkstoffnummer, AISI/SAE code, trade name, or your SKU). Unresolvable values are rejected with 422 material_unresolved plus ranked candidates. Omit to price the material read from the part's drawing (or the environment default).
nest_item_idNoPrice this calculation's material on its part's line of a job nest — the `id` of a line (`items[].id`) of a job nest that has solved it. The material is then the line's share of the sheets the job nest cut it from together with other parts, less its share of what their skeleton and reusable rests earn back; everything else is priced as usual. The line must be of your organization, of this costing environment and of this part revision, and its job nest must have solved it; otherwise the request is rejected with 422 `nest_item_unresolved`, `details.reason` saying why. It cannot be combined with `stock_format_id` or with customer-supplied material. An upload creates a new part revision, so the upload forms reject every line. A line of the sheets an assembly shares among its own components prices that assembly only: naming one is rejected as `not_found`, and a re-run of such a component prices it on its own sheet. Omit it to price the part on its own sheet.
rfq_file_b64NoOptional base64 (or data: URI) of an RFQ text file.
rfq_filenameNoRFQ filename including extension.
annual_volumeNoExpected yearly quantity used to amortize setup cost (1 to 1,000,000,000).
sheet_gauge_mmNoSheet thickness in millimetres — required when the CAD file is a DXF flat pattern (a 2D cutting file carries no thickness); ignored for STEP.
stock_format_idNoPrice this calculation on one stock format — the `id` of a format from the `materials_list_stock_formats` tool (toolset `catalog`). An id names the format, not only the version it came from: when the format has been changed since, the version current on the day the calculation is created is used. An id your organization cannot price with today (unknown, retired or hidden) is rejected with 422 `stock_format_unresolved`. When the part cannot be cut from that format — too small, not bought in the part's thickness or material, or one the machine cannot load — or is not cut from sheet at all (milled, turned or bought finished), the calculation is priced as if none had been chosen, and `analytics.pipeline_notes` says why (`stock_format_pin_unavailable`). Omit it to price on the format that uses the least material per part.
cad_content_typeNoMIME type of the CAD file, when known.
drawing_file_b64NoOptional base64 (or data: URI) of a 2D drawing (PDF/PNG/JPEG).
drawing_filenameNoDrawing filename including extension.
rfq_content_typeNoMIME type of the RFQ file, when known.
material_grade_idNoUUID of a resolved material grade; takes precedence over material_ref when both are supplied.
max_overage_centsNoThe most this calculation may cost past your plan's included calculations, in cents; parts past it wait (run_spend_cap).
precheck_revisionNoThe revision the precheck showed; refused with 409 precheck_changed when what it decides moved since.
provided_stock_kindNoShape of the provided stock; 'near_net_profile' scopes the plan.none
drawing_content_typeNoMIME type of the drawing file, when known.
material_is_providedNoTrue when the customer supplies the raw material (beigestellt).
costing_environment_idNoUUID of the costing environment to price against. Omit to use your organization's default environment.
costing_environment_idsNoPrice the part in several environments at once, in comparison order. The file is uploaded once; each environment becomes one calculation and counts as one against the plan quota. The response then carries ``batch_id`` and ``environment_runs``. Mutually exclusive with ``costing_environment_id``.

TDQS

A4.9/5.0
Behavior5/5

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

Beyond the annotations, the description discloses billing rules, file-size limits, gzip handling, background execution, and the returned calculation id, status, eta_seconds, and part. It also explains the precheck continuation path and the alternative tools for local files and existing parts.

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

Conciseness5/5

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

Despite covering a complex 30-parameter operation, the description is front-loaded and dense with useful information. Each sentence contributes workflow, billing, size, execution, or routing guidance without wasteful repetition.

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?

For a complex, destructive, non-idempotent upload-and-price operation, the description covers the main workflow, alternatives, billing implications, async behavior, and follow-up tool. The remaining parameter-level details are thoroughly documented in the schema.

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

Parameters4/5

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

Schema coverage is 100%, so the schema already carries most parameter detail, but the description adds meaningful conditional semantics: STEP vs DXF flat pattern requiring sheet_gauge_mm and material, optional PDF drawings, and sending precheck_id with no file after precheck_part. It does not explain every advanced parameter, but it adds real value beyond the schema.

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 opens with a specific verb and resource: pricing a new part from a CAD file in one call. It clearly distinguishes this tool from precheck_part, quote_part, get_upload_link, and get_calculation, so an agent can select it without opening sibling schemas.

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 gives explicit routing rules: use get_upload_link for a file on the person's computer, quote_part for a part already in ARCNM, precheck_part before sending precheck_id, and get_calculation afterward. The when-to-use logic is unusually complete.

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

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 9 tool updates
    • Addedattach_drawing
    • Changedexplain_cost5 fields changed
      • changedOutput schema / properties / assembly_completeness / description
        Previous value: -"ASSEMBLIES ONLY. Whether `unit_cost` is a price or a LOWER BOUND. Carries {n_unique, n_priced, n_pending, n_unpriced, total_is_lower_bound, priced_complete, unpriced[], unpriced_steps[]}, where each unpriced entry has a closed-enum `reason_code`, a `by_design` flag and, where one exists, a `remedy`. `priced_complete` and `total_is_lower_bound` cover the COMPONENTS only (the BOM rows counted in n_unique): `priced_complete` is true when every component priced, and when `total_is_lower_bound` is true a component is missing, so `unit_cost` is a lower bound, not a complete price. `unpriced_steps` lists the assembly's own route steps that carry no price, with their reason, worded as get_process_plan words them (e.g. 'Straightening — unpriced (straightening_shop_specific)'); they are not in `unit_cost` whatever the two flags say. A `by_design` reason (a part budget, a plan quota, a cancellation) is a configured limit, not a processing error."New value: +"ASSEMBLIES ONLY. Whether `unit_cost` is a price or a LOWER BOUND. Carries {n_unique, n_priced, n_pending, n_unpriced, n_excluded, n_partial, total_is_lower_bound, priced_complete, unpriced[], partial[], unpriced_steps[]}, where each unpriced entry has a closed-enum `reason_code`, a `by_design` flag and, where one exists, a `remedy`. `priced_complete` and `total_is_lower_bound` cover the COMPONENTS only (the BOM rows counted in n_unique): `priced_complete` is true when every component priced, and when `total_is_lower_bound` is true a component is missing, so `unit_cost` is a lower bound, not a complete price. `unpriced_steps` lists the assembly's own route steps that carry no price, with their reason, worded as get_process_plan words them (e.g. 'Straightening — unpriced (straightening_shop_specific)'); they are not in `unit_cost` whatever the two flags say. A `by_design` reason (a part budget, a plan quota, a cancellation) is a configured limit, not a processing error."
      • addedOutput schema / properties / drawing_pairing
        Added value: +{
        +  "anyOf": [
        +    {
        +      "additionalProperties": true,
        +      "type": "object"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Whether the drawing sent with this calculation describes its model: {status (matched | suspect | mismatched | unverified), drawing_excluded, checks[{name, status}]}. When drawing_excluded is true the drawing describes another part and was left out — the price is the model's alone. Absent when no drawing was paired."
        +}
      • changedOutput schema / properties / material_source / description
        Previous value: -"Where material_priced came from: 'request', 'drawing_title_block' (the part's drawing), 'step_material_property' (the material its STEP file names), 'assembly_drawing_title_block' or 'environment_default'. The first that names a material wins, in that order: request, drawing, STEP file, environment default."New value: +"Where material_priced came from: 'request', 'drawing_title_block' (the part's drawing), 'step_material_property' (the material its STEP file names), 'assembly_parts_list' (the assembly drawing's parts-list row naming the component), 'assembly_drawing_title_block', 'assembly_parts_list_dominant' (the grade most of that list's made rows name, inferred for a component no row names) or 'environment_default'. The first that names a material wins, in that order: request, drawing, parts-list row, assembly drawing or dominant grade, STEP file, environment default."
      • addedOutput schema / properties / price_completeness
        Added value: +{
        +  "anyOf": [
        +    {
        +      "enum": [
        +        "complete",
        +        "partial"
        +      ],
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "'partial' when `unpriced` lists work the price leaves out — then unit_cost is a LOWER BOUND for the drawing, not a price for it; 'complete' when the price covers everything. Absent on a calculation from before the contract and on one without a price."
        +}
      • changedOutput schema / properties / unpriced / anyOf
        Previous value: -[
        -  {
        -    "items": {
        -      "description": "Work the drawing requires that no machine here can do.",
        -      "properties": {
        -        "process": {
        -          "anyOf": [
        -            {
        -              "type": "string"
        -            },
        -            {
        -              "type": "null"
        -            }
        -          ],
        -          "default": null,
        -          "description": "The manufacturing process, in plain words."
        -        },
        -        "reason": {
        -          "anyOf": [
        -            {
        -              "type": "string"
        -            },
        -            {
        -              "type": "null"
        -            }
        -          ],
        -          "default": null,
        -          "description": "Why this work is not in the price."
        -        }
        -      },
        -      "type": "object"
        -    },
        -    "type": "array"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "items": {
        +      "description": "Work the drawing requires that no machine here can do — one gap of a\npartial price, in words and as the codes an agent acts on.",
        +      "properties": {
        +        "disabled_capable_machines": {
        +          "anyOf": [
        +            {
        +              "items": {
        +                "additionalProperties": true,
        +                "type": "object"
        +              },
        +              "type": "array"
        +            },
        +            {
        +              "type": "null"
        +            }
        +          ],
        +          "default": null,
        +          "description": "Switched-off machines of this environment that could do the work ({name, machine_class})."
        +        },
        +        "feature_count": {
        +          "anyOf": [
        +            {
        +              "type": "integer"
        +            },
        +            {
        +              "type": "null"
        +            }
        +          ],
        +          "default": null,
        +          "description": "Features the work covers."
        +        },
        +        "process": {
        +          "anyOf": [
        +            {
        +              "type": "string"
        +            },
        +            {
        +              "type": "null"
        +            }
        +          ],
        +          "default": null,
        +          "description": "The manufacturing process, in plain words."
        +        },
        +        "process_class": {
        +          "anyOf": [
        +            {
        +              "type": "string"
        +            },
        +            {
        +              "type": "null"
        +            }
        +          ],
        +          "default": null,
        +          "description": "Stable code for the process; `process` is its label."
        +        },
        +        "reason": {
        +          "anyOf": [
        +            {
        +              "type": "string"
        +            },
        +            {
        +              "type": "null"
        +            }
        +          ],
        +          "default": null,
        +          "description": "Why this work is not in the price."
        +        },
        +        "remedies": {
        +          "anyOf": [
        +            {
        +              "items": {
        +                "type": "string"
        +              },
        +              "type": "array"
        +            },
        +            {
        +              "type": "null"
        +            }
        +          ],
        +          "default": null,
        +          "description": "What would put this work into the price, as codes in the order to try them: enable_machine (a switched-off machine here can do it — see disabled_capable_machines), add_machine_class, relax_callout, subcontract; on an assembly's welding, attach_weld_drawing and confirm_weld_scope."
        +        },
        +        "requirement": {
        +          "anyOf": [
        +            {
        +              "additionalProperties": true,
        +              "type": "object"
        +            },
        +            {
        +              "type": "null"
        +            }
        +          ],
        +          "default": null,
        +          "description": "The callout left out ({kind, value, unit, and gdt_kind naming a gdt callout's characteristic}) when the gap is a requirement rather than a process."
        +        },
        +        "review_code": {
        +          "anyOf": [
        +            {
        +              "type": "string"
        +            },
        +            {
        +              "type": "null"
        +            }
        +          ],
        +          "default": null,
        +          "description": "The review reason this gap twins."
        +        },
        +        "violation": {
        +          "anyOf": [
        +            {
        +              "type": "string"
        +            },
        +            {
        +              "type": "null"
        +            }
        +          ],
        +          "default": null,
        +          "description": "Stable code for the requirement the closest machine failed."
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "type": "array"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
    • Changedget_cost_breakdown3 fields changed
      • changedOutput schema / $defs / CostSheetNode / properties / amount / description
        Previous value: -"What this line costs per unit, in the calculation's currency."New value: +"What this line costs per unit, in the calculation's currency, as shown: a tier adds up exactly to the line above it."
      • addedOutput schema / $defs / CostSheetNode / properties / exact
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "number"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "This line's amount before it was rounded for display; a per-lot figure is it times the lot, rounded once."
        +}
      • changedOutput schema / properties / material_stock / description
        Previous value: -"The stock the part is bought as — format, size, parts per stock — its mass balance, and the material line's purchase and credits, at the lot the calculation was priced for whichever quantity was asked. Null on a bought-in part and on a calculation priced before 2026-08-28, which recorded no material detail; one priced before the 2026-09-26 release states no scrap or remnant mass and no bar length."New value: +"The stock the part is bought as — format, size, parts per stock — its mass balance, and the material line's purchase and credits, at the lot the calculation was priced for whichever quantity was asked. Null on a catalogue part and on a calculation priced before 2026-08-28, which recorded no material detail; one priced before the 2026-09-26 release states no scrap or remnant mass and no bar length."
    • Addedget_precheck
    • Changedget_process_plan2 fields changed
      • addedOutput schema / properties / price_completeness
        Added value: +{
        +  "anyOf": [
        +    {
        +      "enum": [
        +        "complete",
        +        "partial"
        +      ],
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "'partial' when `unpriced` lists work the price leaves out — the plan covers the rest and the price is a lower bound; 'complete' when it covers everything. Absent before the contract."
        +}
      • changedOutput schema / properties / unpriced / anyOf
        Previous value: -[
        -  {
        -    "items": {
        -      "description": "Work the drawing requires that no machine here can do.",
        -      "properties": {
        -        "process": {
        -          "anyOf": [
        -            {
        -              "type": "string"
        -            },
        -            {
        -              "type": "null"
        -            }
        -          ],
        -          "default": null,
        -          "description": "The manufacturing process, in plain words."
        -        },
        -        "reason": {
        -          "anyOf": [
        -            {
        -              "type": "string"
        -            },
        -            {
        -              "type": "null"
        -            }
        -          ],
        -          "default": null,
        -          "description": "Why this work is not in the price."
        -        }
        -      },
        -      "type": "object"
        -    },
        -    "type": "array"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "items": {
        +      "description": "Work the drawing requires that no machine here can do — one gap of a\npartial price, in words and as the codes an agent acts on.",
        +      "properties": {
        +        "disabled_capable_machines": {
        +          "anyOf": [
        +            {
        +              "items": {
        +                "additionalProperties": true,
        +                "type": "object"
        +              },
        +              "type": "array"
        +            },
        +            {
        +              "type": "null"
        +            }
        +          ],
        +          "default": null,
        +          "description": "Switched-off machines of this environment that could do the work ({name, machine_class})."
        +        },
        +        "feature_count": {
        +          "anyOf": [
        +            {
        +              "type": "integer"
        +            },
        +            {
        +              "type": "null"
        +            }
        +          ],
        +          "default": null,
        +          "description": "Features the work covers."
        +        },
        +        "process": {
        +          "anyOf": [
        +            {
        +              "type": "string"
        +            },
        +            {
        +              "type": "null"
        +            }
        +          ],
        +          "default": null,
        +          "description": "The manufacturing process, in plain words."
        +        },
        +        "process_class": {
        +          "anyOf": [
        +            {
        +              "type": "string"
        +            },
        +            {
        +              "type": "null"
        +            }
        +          ],
        +          "default": null,
        +          "description": "Stable code for the process; `process` is its label."
        +        },
        +        "reason": {
        +          "anyOf": [
        +            {
        +              "type": "string"
        +            },
        +            {
        +              "type": "null"
        +            }
        +          ],
        +          "default": null,
        +          "description": "Why this work is not in the price."
        +        },
        +        "remedies": {
        +          "anyOf": [
        +            {
        +              "items": {
        +                "type": "string"
        +              },
        +              "type": "array"
        +            },
        +            {
        +              "type": "null"
        +            }
        +          ],
        +          "default": null,
        +          "description": "What would put this work into the price, as codes in the order to try them: enable_machine (a switched-off machine here can do it — see disabled_capable_machines), add_machine_class, relax_callout, subcontract; on an assembly's welding, attach_weld_drawing and confirm_weld_scope."
        +        },
        +        "requirement": {
        +          "anyOf": [
        +            {
        +              "additionalProperties": true,
        +              "type": "object"
        +            },
        +            {
        +              "type": "null"
        +            }
        +          ],
        +          "default": null,
        +          "description": "The callout left out ({kind, value, unit, and gdt_kind naming a gdt callout's characteristic}) when the gap is a requirement rather than a process."
        +        },
        +        "review_code": {
        +          "anyOf": [
        +            {
        +              "type": "string"
        +            },
        +            {
        +              "type": "null"
        +            }
        +          ],
        +          "default": null,
        +          "description": "The review reason this gap twins."
        +        },
        +        "violation": {
        +          "anyOf": [
        +            {
        +              "type": "string"
        +            },
        +            {
        +              "type": "null"
        +            }
        +          ],
        +          "default": null,
        +          "description": "Stable code for the requirement the closest machine failed."
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "type": "array"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
    • Addedprecheck_part
    • Changedpreview_cost2 fields changed
      • changedOutput schema / $defs / CostSheetNode / properties / amount / description
        Previous value: -"What this line costs per unit, in the calculation's currency."New value: +"What this line costs per unit, in the calculation's currency, as shown: a tier adds up exactly to the line above it."
      • addedOutput schema / $defs / CostSheetNode / properties / exact
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "number"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "This line's amount before it was rounded for display; a per-lot figure is it times the lot, rounded once."
        +}
    • Changedquote_part2 fields changed
      • changedInput schema / properties / material_grade_id / description
        Previous value: -"UUID of a resolved material grade; takes precedence over material_ref when both are supplied. On a re-run (`derived_from_calculation_id`), omitting both it and `material_ref` keeps the material of the calculation re-run."New value: +"UUID of a resolved material grade; takes precedence over material_ref when both are supplied. On a re-run (`derived_from_calculation_id`), omitting both it and `material_ref` keeps the material the calculation re-run was asked for (one read from its drawing is read again)."
      • changedInput schema / properties / material_ref / description
        Previous value: -"Free-form material reference (URN, Werkstoffnummer, AISI/SAE code, trade name, or your SKU); resolved to a material grade. Unresolvable values are rejected with 422 material_unresolved plus ranked candidates. Omit to price the material read from the part's drawing (or the environment default). On a re-run (`derived_from_calculation_id`), omitting both it and `material_grade_id` keeps the material of the calculation re-run; send `null` to price the drawing's material instead."New value: +"Free-form material reference (URN, Werkstoffnummer, AISI/SAE code, trade name, or your SKU); resolved to a material grade. Unresolvable values are rejected with 422 material_unresolved plus ranked candidates. Omit to price the material read from the part's drawing (or the environment default). On a re-run (`derived_from_calculation_id`), omitting both it and `material_grade_id` keeps the material the calculation re-run was asked for (one read from its drawing is read again); send `null` to price the drawing's material instead."
    • Changedupload_and_quote12 fields changed
      • addedInput schema / properties / cad_file_b64 / anyOf
        Added value: +[
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • changedInput schema / properties / cad_file_b64 / description
        Previous value: -"Base64 (or a data: URI) of the 3D CAD file (e.g. STEP). Required."New value: +"Base64 (or a data: URI) of the 3D CAD file (e.g. STEP). Required unless precheck_id is sent."
      • removedInput schema / properties / cad_file_b64 / type
        Removed value: -"string"
      • addedInput schema / properties / cad_filename / anyOf
        Added value: +[
        +  {
        +    "maxLength": 255,
        +    "minLength": 1,
        +    "type": "string"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • changedInput schema / properties / cad_filename / description
        Previous value: -"CAD filename including extension, e.g. bracket.step — used for format detection."New value: +"CAD filename including extension, e.g. bracket.step — used for format detection. Required with cad_file_b64."
      • removedInput schema / properties / cad_filename / maxLength
        Removed value: -255
      • removedInput schema / properties / cad_filename / minLength
        Removed value: -1
      • removedInput schema / properties / cad_filename / type
        Removed value: -"string"
      • addedInput schema / properties / max_overage_cents
        Added value: +{
        +  "anyOf": [
        +    {
        +      "maximum": 1000000000,
        +      "minimum": 0,
        +      "type": "integer"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "description": "The most this calculation may cost past your plan's included calculations, in cents; parts past it wait (run_spend_cap).",
        +  "title": "Max Overage Cents"
        +}
      • addedInput schema / properties / precheck_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "format": "uuid",
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "description": "Start this precheck (the app only (not available over MCP)): its stored file, drawings and statements — send no file. Starting it again answers with the calculation it started.",
        +  "title": "Precheck Id"
        +}
      • addedInput schema / properties / precheck_revision
        Added value: +{
        +  "anyOf": [
        +    {
        +      "maxLength": 32,
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "description": "The revision the precheck showed; refused with 409 precheck_changed when what it decides moved since.",
        +  "title": "Precheck Revision"
        +}
      • changedInput schema / required
        Previous value: -[
        -  "part_number",
        -  "cad_file_b64",
        -  "cad_filename"
        -]New value: +[
        +  "part_number"
        +]
  2. 1 tool update
    • Changedget_upload_link1 field changed
      • changedOutput schema / properties / calculations_remaining / description
        Previous value: -"Calculations left in this billing window: each part priced from the page uses one. Null when the plan states no limit."New value: +"Calculations left in this billing window. Each different part priced from the page uses one, and an assembly uses one per different part once the file is read. Null when the plan states no limit."
  3. 9 tool updates
    • Changedcompare_calculations4 fields changed
      • addedInput schema / properties / calculation_ids / items / format
        Added value: +"uuid"
      • addedOutput schema / properties / not_found
        Added value: +{
        +  "description": "The calculation_ids that name no calculation of your organization, in the order given. A ranking leaves them out and ranks the others; a pair needs both ids, so it is refused instead.",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
      • changedOutput schema / properties / pair / anyOf
        Previous value: -[
        -  {
        -    "properties": {
        -      "a": {
        -        "properties": {
        -          "assembly_partial": {
        -            "default": false,
        -            "description": "True when this calculation is an assembly priced only in part: a component did not price, so unit_cost and total_cost cover the priced components only — a lower bound, not a price. It states no offer_price, is never ranked or called cheaper, and is never a quote; read its components with explain_cost.",
        -            "type": "boolean"
        -          },
        -          "calculation_id": {
        -            "type": "string"
        -          },
        -          "currency": {
        -            "anyOf": [
        -              {
        -                "type": "string"
        -              },
        -              {
        -                "type": "null"
        -              }
        -            ],
        -            "default": null,
        -            "description": "Currency this side's offer_price / unit_cost / total_cost are stated in."
        -          },
        -          "environment_changed_since_run": {
        -            "anyOf": [
        -              {
        -                "additionalProperties": true,
        -                "type": "object"
        -              },
        -              {
        -                "type": "null"
        -              }
        -            ],
        -            "default": null,
        -            "description": "Null when this price was computed on its costing environment as it stands. Otherwise {latest_at}: the environment was edited after the run read it, and a new calculation prices with the current setup while this result does not."
        -          },
        -          "inputs_changed_since_run": {
        -            "anyOf": [
        -              {
        -                "additionalProperties": true,
        -                "type": "object"
        -              },
        -              {
        -                "type": "null"
        -              }
        -            ],
        -            "default": null,
        -            "description": "Null when this price reflects every input on its part revision. Otherwise {roles, corrections, latest_at}: files attached and corrections applied to the part after the run read its inputs, which a new calculation reads and this one did not."
        -          },
        -          "lot_size": {
        -            "anyOf": [
        -              {
        -                "type": "integer"
        -              },
        -              {
        -                "type": "null"
        -              }
        -            ],
        -            "default": null
        -          },
        -          "machine": {
        -            "anyOf": [
        -              {
        -                "type": "string"
        -              },
        -              {
        -                "type": "null"
        -              }
        -            ],
        -            "default": null
        -          },
        -          "name": {
        -            "anyOf": [
        -              {
        -                "type": "string"
        -              },
        -              {
        -                "type": "null"
        -              }
        -            ],
        -            "default": null
        -          },
        -          "needs_review": {
        -            "default": false,
        -            "description": "True when this calculation is flagged for human review — its number is not a quote yet. The reasons are on the calculation.",
        -            "type": "boolean"
        -          },
        -          "offer_price": {
        -            "anyOf": [
        -              {
        -                "type": "number"
        -              },
        -              {
        -                "type": "null"
        -              }
        -            ],
        -            "default": null,
        -            "description": "The headline: offer price per unit, cost-sheet surcharges included — the figure the calculation itself headlines (explain_cost's offer_price) and the one comparisons and rankings are struck on. Equal to unit_cost where the environment states no surcharges. Null until priced, and null on an assembly priced only in part (assembly_partial)."
        -          },
        -          "overhead_scheme": {
        -            "anyOf": [
        -              {
        -                "type": "string"
        -              },
        -              {
        -                "type": "null"
        -              }
        -            ],
        -            "default": null,
        -            "description": "Which overhead system unit_cost was built on: 'flat' when the cost sheet carries the flat variable overhead (overhead_var) inside unit_cost, 'ladder' when the environment states Material-/Fertigungsgemeinkosten, which switch that default off and sit above unit_cost; null when the result states neither."
        -          },
        -          "status": {
        -            "anyOf": [
        -              {
        -                "type": "string"
        -              },
        -              {
        -                "type": "null"
        -              }
        -            ],
        -            "default": null
        -          },
        -          "total_cost": {
        -            "anyOf": [
        -              {
        -                "type": "number"
        -              },
        -              {
        -                "type": "null"
        -              }
        -            ],
        -            "default": null,
        -            "description": "unit_cost for the whole lot, on the same basis as unit_cost."
        -          },
        -          "unit_cost": {
        -            "anyOf": [
        -              {
        -                "type": "number"
        -              },
        -              {
        -                "type": "null"
        -              }
        -            ],
        -            "default": null,
        -            "description": "Unit cost per part: direct cost plus overhead_var and overhead_fixed. Where the costing environment states no Material-/Fertigungsgemeinkosten, overhead_var is the flat variable overhead (platform default 15 % of direct cost); once it states them, that default is 0 and those overheads sit above unit_cost as cost-sheet rungs, with administration and selling, margin and the other surcharges. Secondary: it is not like-for-like across environments, nor across overhead schemes (see overhead_scheme)."
        -          },
        -          "unit_time_s": {
        -            "anyOf": [
        -              {
        -                "type": "number"
        -              },
        -              {
        -                "type": "null"
        -              }
        -            ],
        -            "default": null,
        -            "description": "Production time per unit, in seconds."
        -          }
        -        },
        -        "required": [
        -          "calculation_id"
        -        ],
        -        "type": "object"
        -      },
        -      "b": {
        -        "properties": {
        -          "assembly_partial": {
        -            "default": false,
        -            "description": "True when this calculation is an assembly priced only in part: a component did not price, so unit_cost and total_cost cover the priced components only — a lower bound, not a price. It states no offer_price, is never ranked or called cheaper, and is never a quote; read its components with explain_cost.",
        -            "type": "boolean"
        -          },
        -          "calculation_id": {
        -            "type": "string"
        -          },
        -          "currency": {
        -            "anyOf": [
        -              {
        -                "type": "string"
        -              },
        -              {
        -                "type": "null"
        -              }
        -            ],
        -            "default": null,
        -            "description": "Currency this side's offer_price / unit_cost / total_cost are stated in."
        -          },
        -          "environment_changed_since_run": {
        -            "anyOf": [
        -              {
        -                "additionalProperties": true,
        -                "type": "object"
        -              },
        -              {
        -                "type": "null"
        -              }
        -            ],
        -            "default": null,
        -            "description": "Null when this price was computed on its costing environment as it stands. Otherwise {latest_at}: the environment was edited after the run read it, and a new calculation prices with the current setup while this result does not."
        -          },
        -          "inputs_changed_since_run": {
        -            "anyOf": [
        -              {
        -                "additionalProperties": true,
        -                "type": "object"
        -              },
        -              {
        -                "type": "null"
        -              }
        -            ],
        -            "default": null,
        -            "description": "Null when this price reflects every input on its part revision. Otherwise {roles, corrections, latest_at}: files attached and corrections applied to the part after the run read its inputs, which a new calculation reads and this one did not."
        -          },
        -          "lot_size": {
        -            "anyOf": [
        -              {
        -                "type": "integer"
        -              },
        -              {
        -                "type": "null"
        -              }
        -            ],
        -            "default": null
        -          },
        -          "machine": {
        -            "anyOf": [
        -              {
        -                "type": "string"
        -              },
        -              {
        -                "type": "null"
        -              }
        -            ],
        -            "default": null
        -          },
        -          "name": {
        -            "anyOf": [
        -              {
        -                "type": "string"
        -              },
        -              {
        -                "type": "null"
        -              }
        -            ],
        -            "default": null
        -          },
        -          "needs_review": {
        -            "default": false,
        -            "description": "True when this calculation is flagged for human review — its number is not a quote yet. The reasons are on the calculation.",
        -            "type": "boolean"
        -          },
        -          "offer_price": {
        -            "anyOf": [
        -              {
        -                "type": "number"
        -              },
        -              {
        -                "type": "null"
        -              }
        -            ],
        -            "default": null,
        -            "description": "The headline: offer price per unit, cost-sheet surcharges included — the figure the calculation itself headlines (explain_cost's offer_price) and the one comparisons and rankings are struck on. Equal to unit_cost where the environment states no surcharges. Null until priced, and null on an assembly priced only in part (assembly_partial)."
        -          },
        -          "overhead_scheme": {
        -            "anyOf": [
        -              {
        -                "type": "string"
        -              },
        -              {
        -                "type": "null"
        -              }
        -            ],
        -            "default": null,
        -            "description": "Which overhead system unit_cost was built on: 'flat' when the cost sheet carries the flat variable overhead (overhead_var) inside unit_cost, 'ladder' when the environment states Material-/Fertigungsgemeinkosten, which switch that default off and sit above unit_cost; null when the result states neither."
        -          },
        -          "status": {
        -            "anyOf": [
        -              {
        -                "type": "string"
        -              },
        -              {
        -                "type": "null"
        -              }
        -            ],
        -            "default": null
        -          },
        -          "total_cost": {
        -            "anyOf": [
        -              {
        -                "type": "number"
        -              },
        -              {
        -                "type": "null"
        -              }
        -            ],
        -            "default": null,
        -            "description": "unit_cost for the whole lot, on the same basis as unit_cost."
        -          },
        -          "unit_cost": {
        -            "anyOf": [
        -              {
        -                "type": "number"
        -              },
        -              {
        -                "type": "null"
        -              }
        -            ],
        -            "default": null,
        -            "description": "Unit cost per part: direct cost plus overhead_var and overhead_fixed. Where the costing environment states no Material-/Fertigungsgemeinkosten, overhead_var is the flat variable overhead (platform default 15 % of direct cost); once it states them, that default is 0 and those overheads sit above unit_cost as cost-sheet rungs, with administration and selling, margin and the other surcharges. Secondary: it is not like-for-like across environments, nor across overhead schemes (see overhead_scheme)."
        -          },
        -          "unit_time_s": {
        -            "anyOf": [
        -              {
        -                "type": "number"
        -              },
        -              {
        -                "type": "null"
        -              }
        -            ],
        -            "default": null,
        -            "description": "Production time per unit, in seconds."
        -          }
        -        },
        -        "required": [
        -          "calculation_id"
        -        ],
        -        "type": "object"
        -      },
        -      "comparable": {
        -        "description": "False if the two used different lot sizes, costing environments, currencies or overhead schemes, or either is an assembly priced only in part — see incomparable_reasons for which.",
        -        "type": "boolean"
        -      },
        -      "guidance": {
        -        "default": "",
        -        "description": "What the delta means and what to do next (alias of note for naming consistency with the other tools).",
        -        "type": "string"
        -      },
        -      "incomparable_reasons": {
        -        "description": "Why comparable is false: lot_size_mismatch, environment_mismatch, currency_mismatch and/or assembly_partial (the same vocabulary the REST comparison matrix uses), and cost_scheme_mismatch when one side's unit_cost carries the flat variable overhead and the other's a stated MGK/FGK ladder above it (unit_cost_delta is then null; compare at the offer price or Herstellkosten). Empty when comparable.",
        -        "items": {
        -          "type": "string"
        -        },
        -        "type": "array"
        -      },
        -      "note": {
        -        "type": "string"
        -      },
        -      "offer_price_delta": {
        -        "anyOf": [
        -          {
        -            "type": "number"
        -          },
        -          {
        -            "type": "null"
        -          }
        -        ],
        -        "default": null,
        -        "description": "b − a offer price, per unit, in the shared currency — the delta that says which option is cheaper. Null when the two are quoted in different currencies — there is no FX rail, so a cross-currency difference would be an invented number — and when either side is an assembly priced only in part."
        -      },
        -      "offer_price_delta_pct": {
        -        "anyOf": [
        -          {
        -            "type": "number"
        -          },
        -          {
        -            "type": "null"
        -          }
        -        ],
        -        "default": null,
        -        "description": "offer_price_delta as % of a; null wherever it is."
        -      },
        -      "unit_cost_delta": {
        -        "anyOf": [
        -          {
        -            "type": "number"
        -          },
        -          {
        -            "type": "null"
        -          }
        -        ],
        -        "default": null,
        -        "description": "b − a unit cost (see CalcSide.unit_cost for what it holds), per unit, in the shared currency; null across currencies, across overhead schemes (cost_scheme_mismatch) and when either side is an assembly priced only in part. Secondary: it can point the other way from offer_price_delta when the two environments state different surcharges."
        -      },
        -      "unit_cost_delta_pct": {
        -        "anyOf": [
        -          {
        -            "type": "number"
        -          },
        -          {
        -            "type": "null"
        -          }
        -        ],
        -        "default": null,
        -        "description": "unit_cost_delta as % of a; null wherever it is."
        -      },
        -      "unit_time_delta_s": {
        -        "anyOf": [
        -          {
        -            "type": "number"
        -          },
        -          {
        -            "type": "null"
        -          }
        -        ],
        -        "default": null,
        -        "description": "b − a, production seconds per unit — time beside cost, so a cheaper option that is slower (capacity impact) is visible. Null when either side is an assembly priced only in part."
        -      }
        -    },
        -    "required": [
        -      "a",
        -      "b",
        -      "comparable",
        -      "note"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "properties": {
        +      "a": {
        +        "properties": {
        +          "assembly_partial": {
        +            "default": false,
        +            "description": "True when this calculation is an assembly priced only in part: a component did not price, so unit_cost and total_cost cover the priced components only — a lower bound, not a price. It states no offer_price, is never ranked or called cheaper, and is never a quote; read its components with explain_cost.",
        +            "type": "boolean"
        +          },
        +          "calculation_id": {
        +            "type": "string"
        +          },
        +          "currency": {
        +            "anyOf": [
        +              {
        +                "type": "string"
        +              },
        +              {
        +                "type": "null"
        +              }
        +            ],
        +            "default": null,
        +            "description": "Currency this side's offer_price / unit_cost / total_cost are stated in."
        +          },
        +          "environment_changed_since_run": {
        +            "anyOf": [
        +              {
        +                "additionalProperties": true,
        +                "type": "object"
        +              },
        +              {
        +                "type": "null"
        +              }
        +            ],
        +            "default": null,
        +            "description": "Null when this price was computed on its costing environment as it stands. Otherwise {latest_at}: the environment was edited after the run read it, and a new calculation prices with the current setup while this result does not."
        +          },
        +          "inputs_changed_since_run": {
        +            "anyOf": [
        +              {
        +                "additionalProperties": true,
        +                "type": "object"
        +              },
        +              {
        +                "type": "null"
        +              }
        +            ],
        +            "default": null,
        +            "description": "Null when this price reflects every input on its part revision. Otherwise {roles, corrections, latest_at}: files attached and corrections applied to the part after the run read its inputs, which a new calculation reads and this one did not."
        +          },
        +          "lot_size": {
        +            "anyOf": [
        +              {
        +                "type": "integer"
        +              },
        +              {
        +                "type": "null"
        +              }
        +            ],
        +            "default": null
        +          },
        +          "machine": {
        +            "anyOf": [
        +              {
        +                "type": "string"
        +              },
        +              {
        +                "type": "null"
        +              }
        +            ],
        +            "default": null
        +          },
        +          "name": {
        +            "anyOf": [
        +              {
        +                "type": "string"
        +              },
        +              {
        +                "type": "null"
        +              }
        +            ],
        +            "default": null
        +          },
        +          "needs_review": {
        +            "default": false,
        +            "description": "True when this calculation is flagged for human review — its number is not a quote yet. The reasons are on the calculation.",
        +            "type": "boolean"
        +          },
        +          "offer_price": {
        +            "anyOf": [
        +              {
        +                "type": "number"
        +              },
        +              {
        +                "type": "null"
        +              }
        +            ],
        +            "default": null,
        +            "description": "The headline: offer price per unit, cost-sheet surcharges included — the figure the calculation itself headlines (explain_cost's offer_price) and the one comparisons and rankings are struck on. Equal to unit_cost where the environment states no surcharges. Null until priced, and null on an assembly priced only in part (assembly_partial)."
        +          },
        +          "overhead_scheme": {
        +            "anyOf": [
        +              {
        +                "type": "string"
        +              },
        +              {
        +                "type": "null"
        +              }
        +            ],
        +            "default": null,
        +            "description": "Which overhead system unit_cost was built on: 'flat' when the cost sheet carries the flat variable overhead (overhead_var) inside unit_cost, 'ladder' when the environment states Material-/Fertigungsgemeinkosten, which switch that default off and sit above unit_cost; null when the result states neither."
        +          },
        +          "status": {
        +            "anyOf": [
        +              {
        +                "type": "string"
        +              },
        +              {
        +                "type": "null"
        +              }
        +            ],
        +            "default": null
        +          },
        +          "total_cost": {
        +            "anyOf": [
        +              {
        +                "type": "number"
        +              },
        +              {
        +                "type": "null"
        +              }
        +            ],
        +            "default": null,
        +            "description": "unit_cost for the whole lot, on the same basis as unit_cost."
        +          },
        +          "unit_cost": {
        +            "anyOf": [
        +              {
        +                "type": "number"
        +              },
        +              {
        +                "type": "null"
        +              }
        +            ],
        +            "default": null,
        +            "description": "Unit cost per part: direct cost plus overhead_var and overhead_fixed. Where the costing environment states no Material-/Fertigungsgemeinkosten, overhead_var is the flat variable overhead the environment states (none by default); once it states them, those overheads sit above unit_cost as cost-sheet rungs, with administration and selling, margin and the other surcharges. Secondary: it is not like-for-like across environments, nor across overhead schemes (see overhead_scheme)."
        +          },
        +          "unit_time_s": {
        +            "anyOf": [
        +              {
        +                "type": "number"
        +              },
        +              {
        +                "type": "null"
        +              }
        +            ],
        +            "default": null,
        +            "description": "Production time per unit, in seconds."
        +          }
        +        },
        +        "required": [
        +          "calculation_id"
        +        ],
        +        "type": "object"
        +      },
        +      "b": {
        +        "properties": {
        +          "assembly_partial": {
        +            "default": false,
        +            "description": "True when this calculation is an assembly priced only in part: a component did not price, so unit_cost and total_cost cover the priced components only — a lower bound, not a price. It states no offer_price, is never ranked or called cheaper, and is never a quote; read its components with explain_cost.",
        +            "type": "boolean"
        +          },
        +          "calculation_id": {
        +            "type": "string"
        +          },
        +          "currency": {
        +            "anyOf": [
        +              {
        +                "type": "string"
        +              },
        +              {
        +                "type": "null"
        +              }
        +            ],
        +            "default": null,
        +            "description": "Currency this side's offer_price / unit_cost / total_cost are stated in."
        +          },
        +          "environment_changed_since_run": {
        +            "anyOf": [
        +              {
        +                "additionalProperties": true,
        +                "type": "object"
        +              },
        +              {
        +                "type": "null"
        +              }
        +            ],
        +            "default": null,
        +            "description": "Null when this price was computed on its costing environment as it stands. Otherwise {latest_at}: the environment was edited after the run read it, and a new calculation prices with the current setup while this result does not."
        +          },
        +          "inputs_changed_since_run": {
        +            "anyOf": [
        +              {
        +                "additionalProperties": true,
        +                "type": "object"
        +              },
        +              {
        +                "type": "null"
        +              }
        +            ],
        +            "default": null,
        +            "description": "Null when this price reflects every input on its part revision. Otherwise {roles, corrections, latest_at}: files attached and corrections applied to the part after the run read its inputs, which a new calculation reads and this one did not."
        +          },
        +          "lot_size": {
        +            "anyOf": [
        +              {
        +                "type": "integer"
        +              },
        +              {
        +                "type": "null"
        +              }
        +            ],
        +            "default": null
        +          },
        +          "machine": {
        +            "anyOf": [
        +              {
        +                "type": "string"
        +              },
        +              {
        +                "type": "null"
        +              }
        +            ],
        +            "default": null
        +          },
        +          "name": {
        +            "anyOf": [
        +              {
        +                "type": "string"
        +              },
        +              {
        +                "type": "null"
        +              }
        +            ],
        +            "default": null
        +          },
        +          "needs_review": {
        +            "default": false,
        +            "description": "True when this calculation is flagged for human review — its number is not a quote yet. The reasons are on the calculation.",
        +            "type": "boolean"
        +          },
        +          "offer_price": {
        +            "anyOf": [
        +              {
        +                "type": "number"
        +              },
        +              {
        +                "type": "null"
        +              }
        +            ],
        +            "default": null,
        +            "description": "The headline: offer price per unit, cost-sheet surcharges included — the figure the calculation itself headlines (explain_cost's offer_price) and the one comparisons and rankings are struck on. Equal to unit_cost where the environment states no surcharges. Null until priced, and null on an assembly priced only in part (assembly_partial)."
        +          },
        +          "overhead_scheme": {
        +            "anyOf": [
        +              {
        +                "type": "string"
        +              },
        +              {
        +                "type": "null"
        +              }
        +            ],
        +            "default": null,
        +            "description": "Which overhead system unit_cost was built on: 'flat' when the cost sheet carries the flat variable overhead (overhead_var) inside unit_cost, 'ladder' when the environment states Material-/Fertigungsgemeinkosten, which switch that default off and sit above unit_cost; null when the result states neither."
        +          },
        +          "status": {
        +            "anyOf": [
        +              {
        +                "type": "string"
        +              },
        +              {
        +                "type": "null"
        +              }
        +            ],
        +            "default": null
        +          },
        +          "total_cost": {
        +            "anyOf": [
        +              {
        +                "type": "number"
        +              },
        +              {
        +                "type": "null"
        +              }
        +            ],
        +            "default": null,
        +            "description": "unit_cost for the whole lot, on the same basis as unit_cost."
        +          },
        +          "unit_cost": {
        +            "anyOf": [
        +              {
        +                "type": "number"
        +              },
        +              {
        +                "type": "null"
        +              }
        +            ],
        +            "default": null,
        +            "description": "Unit cost per part: direct cost plus overhead_var and overhead_fixed. Where the costing environment states no Material-/Fertigungsgemeinkosten, overhead_var is the flat variable overhead the environment states (none by default); once it states them, those overheads sit above unit_cost as cost-sheet rungs, with administration and selling, margin and the other surcharges. Secondary: it is not like-for-like across environments, nor across overhead schemes (see overhead_scheme)."
        +          },
        +          "unit_time_s": {
        +            "anyOf": [
        +              {
        +                "type": "number"
        +              },
        +              {
        +                "type": "null"
        +              }
        +            ],
        +            "default": null,
        +            "description": "Production time per unit, in seconds."
        +          }
        +        },
        +        "required": [
        +          "calculation_id"
        +        ],
        +        "type": "object"
        +      },
        +      "comparable": {
        +        "description": "False if the two are different parts, were priced on different materials, used different lot sizes, costing environments, currencies or overhead schemes, or either is an assembly priced only in part — see incomparable_reasons for which.",
        +        "type": "boolean"
        +      },
        +      "guidance": {
        +        "default": "",
        +        "description": "What the delta means and what to do next (alias of note for naming consistency with the other tools).",
        +        "type": "string"
        +      },
        +      "incomparable_reasons": {
        +        "description": "Why comparable is false: lot_size_mismatch, environment_mismatch, currency_mismatch and/or assembly_partial (the same vocabulary the REST comparison matrix uses); cost_scheme_mismatch when one side's unit_cost carries the flat variable overhead and the other's a stated MGK/FGK ladder above it (unit_cost_delta is then null; compare at the offer price or Herstellkosten); material_mismatch when they were priced on different materials (two grades, or a grade and the environment's default material); and different_part when they price two different parts (two revisions of one part are one part). Empty when comparable.",
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "note": {
        +        "type": "string"
        +      },
        +      "offer_price_delta": {
        +        "anyOf": [
        +          {
        +            "type": "number"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "description": "b − a offer price, per unit, in the shared currency — the delta that says which option is cheaper. Null when the two are quoted in different currencies — there is no FX rail, so a cross-currency difference would be an invented number — and when either side is an assembly priced only in part."
        +      },
        +      "offer_price_delta_pct": {
        +        "anyOf": [
        +          {
        +            "type": "number"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "description": "offer_price_delta as % of a; null wherever it is."
        +      },
        +      "unit_cost_delta": {
        +        "anyOf": [
        +          {
        +            "type": "number"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "description": "b − a unit cost (see CalcSide.unit_cost for what it holds), per unit, in the shared currency; null across currencies, across overhead schemes (cost_scheme_mismatch) and when either side is an assembly priced only in part. Secondary: it can point the other way from offer_price_delta when the two environments state different surcharges."
        +      },
        +      "unit_cost_delta_pct": {
        +        "anyOf": [
        +          {
        +            "type": "number"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "description": "unit_cost_delta as % of a; null wherever it is."
        +      },
        +      "unit_time_delta_s": {
        +        "anyOf": [
        +          {
        +            "type": "number"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "description": "b − a, production seconds per unit — time beside cost, so a cheaper option that is slower (capacity impact) is visible. Null when either side is an assembly priced only in part."
        +      }
        +    },
        +    "required": [
        +      "a",
        +      "b",
        +      "comparable",
        +      "note"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • changedOutput schema / properties / ranking / anyOf
        Previous value: -[
        -  {
        -    "description": "N calculations ranked by offer price, lowest first, with time beside\ncost — what ``compare_calculations`` answers for 3 to 20 ids.",
        -    "properties": {
        -      "best_calculation_id": {
        -        "anyOf": [
        -          {
        -            "type": "string"
        -          },
        -          {
        -            "type": "null"
        -          }
        -        ],
        -        "default": null,
        -        "description": "The cheapest priced option's id (the ranking winner), or null if none are priced yet."
        -      },
        -      "comparable": {
        -        "description": "True only when there are at least two priced options AND they share a lot size, costing environment, overhead scheme and currency. False either because the options are not like-with-like (the spread is then not purely the part) or because fewer than two are priced and there is nothing to compare — read `note` / `incomparable_reasons` for which.",
        -        "type": "boolean"
        -      },
        -      "guidance": {
        -        "default": "",
        -        "description": "What the ranking means and what to do next.",
        -        "type": "string"
        -      },
        -      "incomparable_reasons": {
        -        "description": "Why comparable is false: lot_size_mismatch, environment_mismatch, cost_scheme_mismatch (the flat variable overhead vs a stated MGK/FGK ladder: unit-cost deltas are then null) and/or currency_mismatch. On currency_mismatch the options are NOT ranked at all (no rank, no deltas, no winner): there is no FX rail, so a cross-currency order would be invented.",
        -        "items": {
        -          "type": "string"
        -        },
        -        "type": "array"
        -      },
        -      "note": {
        -        "type": "string"
        -      },
        -      "priced_count": {
        -        "description": "How many of the inputs carry a price.",
        -        "type": "integer"
        -      },
        -      "ranked": {
        -        "description": "Priced options by offer price, lowest first (rank 1…k), then any blocked / unpriced calcs and any assembly priced only in part (rank null) in the order given.",
        -        "items": {
        -          "description": "One calculation's place in an N-way ranking (lowest offer price first).",
        -          "properties": {
        -            "assembly_partial": {
        -              "default": false,
        -              "description": "True when this calculation is an assembly priced only in part: a component did not price, so unit_cost and total_cost cover the priced components only — a lower bound, not a price. It states no offer_price, is never ranked or called cheaper, and is never a quote; read its components with explain_cost.",
        -              "type": "boolean"
        -            },
        -            "calculation_id": {
        -              "type": "string"
        -            },
        -            "currency": {
        -              "anyOf": [
        -                {
        -                  "type": "string"
        -                },
        -                {
        -                  "type": "null"
        -                }
        -              ],
        -              "default": null,
        -              "description": "Currency this side's offer_price / unit_cost / total_cost are stated in."
        -            },
        -            "environment_changed_since_run": {
        -              "anyOf": [
        -                {
        -                  "additionalProperties": true,
        -                  "type": "object"
        -                },
        -                {
        -                  "type": "null"
        -                }
        -              ],
        -              "default": null,
        -              "description": "Null when this price was computed on its costing environment as it stands. Otherwise {latest_at}: the environment was edited after the run read it, and a new calculation prices with the current setup while this result does not."
        -            },
        -            "inputs_changed_since_run": {
        -              "anyOf": [
        -                {
        -                  "additionalProperties": true,
        -                  "type": "object"
        -                },
        -                {
        -                  "type": "null"
        -                }
        -              ],
        -              "default": null,
        -              "description": "Null when this price reflects every input on its part revision. Otherwise {roles, corrections, latest_at}: files attached and corrections applied to the part after the run read its inputs, which a new calculation reads and this one did not."
        -            },
        -            "lot_size": {
        -              "anyOf": [
        -                {
        -                  "type": "integer"
        -                },
        -                {
        -                  "type": "null"
        -                }
        -              ],
        -              "default": null
        -            },
        -            "machine": {
        -              "anyOf": [
        -                {
        -                  "type": "string"
        -                },
        -                {
        -                  "type": "null"
        -                }
        -              ],
        -              "default": null
        -            },
        -            "name": {
        -              "anyOf": [
        -                {
        -                  "type": "string"
        -                },
        -                {
        -                  "type": "null"
        -                }
        -              ],
        -              "default": null
        -            },
        -            "needs_review": {
        -              "default": false,
        -              "description": "True when this calculation is flagged for human review — its number is not a quote yet. The reasons are on the calculation.",
        -              "type": "boolean"
        -            },
        -            "offer_price": {
        -              "anyOf": [
        -                {
        -                  "type": "number"
        -                },
        -                {
        -                  "type": "null"
        -                }
        -              ],
        -              "default": null,
        -              "description": "The headline: offer price per unit, cost-sheet surcharges included — the figure the calculation itself headlines (explain_cost's offer_price) and the one comparisons and rankings are struck on. Equal to unit_cost where the environment states no surcharges. Null until priced, and null on an assembly priced only in part (assembly_partial)."
        -            },
        -            "offer_price_delta_vs_best": {
        -              "anyOf": [
        -                {
        -                  "type": "number"
        -                },
        -                {
        -                  "type": "null"
        -                }
        -              ],
        -              "default": null,
        -              "description": "Offer-price premium per unit over the winner (0 for the winner)."
        -            },
        -            "offer_price_delta_vs_best_pct": {
        -              "anyOf": [
        -                {
        -                  "type": "number"
        -                },
        -                {
        -                  "type": "null"
        -                }
        -              ],
        -              "default": null,
        -              "description": "Premium as % of the winner's offer price."
        -            },
        -            "overhead_scheme": {
        -              "anyOf": [
        -                {
        -                  "type": "string"
        -                },
        -                {
        -                  "type": "null"
        -                }
        -              ],
        -              "default": null,
        -              "description": "Which overhead system unit_cost was built on: 'flat' when the cost sheet carries the flat variable overhead (overhead_var) inside unit_cost, 'ladder' when the environment states Material-/Fertigungsgemeinkosten, which switch that default off and sit above unit_cost; null when the result states neither."
        -            },
        -            "rank": {
        -              "anyOf": [
        -                {
        -                  "type": "integer"
        -                },
        -                {
        -                  "type": "null"
        -                }
        -              ],
        -              "default": null,
        -              "description": "1 = the priced option with the lowest offer_price. Null for a calc with no price yet (blocked / not succeeded) and for an assembly priced only in part (assembly_partial); those sort to the end."
        -            },
        -            "status": {
        -              "anyOf": [
        -                {
        -                  "type": "string"
        -                },
        -                {
        -                  "type": "null"
        -                }
        -              ],
        -              "default": null
        -            },
        -            "total_cost": {
        -              "anyOf": [
        -                {
        -                  "type": "number"
        -                },
        -                {
        -                  "type": "null"
        -                }
        -              ],
        -              "default": null,
        -              "description": "unit_cost for the whole lot, on the same basis as unit_cost."
        -            },
        -            "unit_cost": {
        -              "anyOf": [
        -                {
        -                  "type": "number"
        -                },
        -                {
        -                  "type": "null"
        -                }
        -              ],
        -              "default": null,
        -              "description": "Unit cost per part: direct cost plus overhead_var and overhead_fixed. Where the costing environment states no Material-/Fertigungsgemeinkosten, overhead_var is the flat variable overhead (platform default 15 % of direct cost); once it states them, that default is 0 and those overheads sit above unit_cost as cost-sheet rungs, with administration and selling, margin and the other surcharges. Secondary: it is not like-for-like across environments, nor across overhead schemes (see overhead_scheme)."
        -            },
        -            "unit_cost_delta_vs_best": {
        -              "anyOf": [
        -                {
        -                  "type": "number"
        -                },
        -                {
        -                  "type": "null"
        -                }
        -              ],
        -              "default": null,
        -              "description": "This option's unit cost minus the winner's (the winner is the lowest offer price). Negative when this option costs less to make but more to buy: its environment states larger cost-sheet surcharges than the winner's. Null when the options use different overhead schemes (cost_scheme_mismatch)."
        -            },
        -            "unit_cost_delta_vs_best_pct": {
        -              "anyOf": [
        -                {
        -                  "type": "number"
        -                },
        -                {
        -                  "type": "null"
        -                }
        -              ],
        -              "default": null,
        -              "description": "unit_cost_delta_vs_best as % of the winner's unit cost."
        -            },
        -            "unit_time_delta_vs_best_s": {
        -              "anyOf": [
        -                {
        -                  "type": "number"
        -                },
        -                {
        -                  "type": "null"
        -                }
        -              ],
        -              "default": null,
        -              "description": "Production seconds/unit vs the cheapest option — so a cheaper winner that is slower (capacity impact) stays visible."
        -            },
        -            "unit_time_s": {
        -              "anyOf": [
        -                {
        -                  "type": "number"
        -                },
        -                {
        -                  "type": "null"
        -                }
        -              ],
        -              "default": null,
        -              "description": "Production time per unit, in seconds."
        -            }
        -          },
        -          "required": [
        -            "calculation_id"
        -          ],
        -          "type": "object"
        -        },
        -        "type": "array"
        -      },
        -      "total_count": {
        -        "description": "How many distinct calculations were ranked.",
        -        "type": "integer"
        -      }
        -    },
        -    "required": [
        -      "ranked",
        -      "priced_count",
        -      "total_count",
        -      "comparable",
        -      "note"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "description": "N calculations ranked by offer price, lowest first, with time beside\ncost — what ``compare_calculations`` answers for 3 to 20 ids.",
        +    "properties": {
        +      "best_calculation_id": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "description": "The cheapest priced option's id (the ranking winner), or null if none are priced yet."
        +      },
        +      "comparable": {
        +        "description": "True only when there are at least two priced options AND they are one part, priced on one material, and share a lot size, costing environment, overhead scheme and currency. False either because the options are not like-with-like (incomparable_reasons names what differs) or because fewer than two are priced and there is nothing to compare — read `note` / `incomparable_reasons` for which.",
        +        "type": "boolean"
        +      },
        +      "guidance": {
        +        "default": "",
        +        "description": "What the ranking means and what to do next.",
        +        "type": "string"
        +      },
        +      "incomparable_reasons": {
        +        "description": "Why comparable is false: lot_size_mismatch, environment_mismatch, cost_scheme_mismatch (the flat variable overhead vs a stated MGK/FGK ladder: unit-cost deltas are then null), currency_mismatch, material_mismatch (priced on different materials: two grades, or a grade and the environment's default material) and/or different_part (not all one part; two revisions of one part are one part). On currency_mismatch the options are NOT ranked at all (no rank, no deltas, no winner): there is no FX rail, so a cross-currency order would be invented.",
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "note": {
        +        "type": "string"
        +      },
        +      "priced_count": {
        +        "description": "How many of the inputs carry a price.",
        +        "type": "integer"
        +      },
        +      "ranked": {
        +        "description": "Priced options by offer price, lowest first (rank 1…k), then any blocked / unpriced calcs and any assembly priced only in part (rank null) in the order given.",
        +        "items": {
        +          "description": "One calculation's place in an N-way ranking (lowest offer price first).",
        +          "properties": {
        +            "assembly_partial": {
        +              "default": false,
        +              "description": "True when this calculation is an assembly priced only in part: a component did not price, so unit_cost and total_cost cover the priced components only — a lower bound, not a price. It states no offer_price, is never ranked or called cheaper, and is never a quote; read its components with explain_cost.",
        +              "type": "boolean"
        +            },
        +            "calculation_id": {
        +              "type": "string"
        +            },
        +            "currency": {
        +              "anyOf": [
        +                {
        +                  "type": "string"
        +                },
        +                {
        +                  "type": "null"
        +                }
        +              ],
        +              "default": null,
        +              "description": "Currency this side's offer_price / unit_cost / total_cost are stated in."
        +            },
        +            "environment_changed_since_run": {
        +              "anyOf": [
        +                {
        +                  "additionalProperties": true,
        +                  "type": "object"
        +                },
        +                {
        +                  "type": "null"
        +                }
        +              ],
        +              "default": null,
        +              "description": "Null when this price was computed on its costing environment as it stands. Otherwise {latest_at}: the environment was edited after the run read it, and a new calculation prices with the current setup while this result does not."
        +            },
        +            "inputs_changed_since_run": {
        +              "anyOf": [
        +                {
        +                  "additionalProperties": true,
        +                  "type": "object"
        +                },
        +                {
        +                  "type": "null"
        +                }
        +              ],
        +              "default": null,
        +              "description": "Null when this price reflects every input on its part revision. Otherwise {roles, corrections, latest_at}: files attached and corrections applied to the part after the run read its inputs, which a new calculation reads and this one did not."
        +            },
        +            "lot_size": {
        +              "anyOf": [
        +                {
        +                  "type": "integer"
        +                },
        +                {
        +                  "type": "null"
        +                }
        +              ],
        +              "default": null
        +            },
        +            "machine": {
        +              "anyOf": [
        +                {
        +                  "type": "string"
        +                },
        +                {
        +                  "type": "null"
        +                }
        +              ],
        +              "default": null
        +            },
        +            "name": {
        +              "anyOf": [
        +                {
        +                  "type": "string"
        +                },
        +                {
        +                  "type": "null"
        +                }
        +              ],
        +              "default": null
        +            },
        +            "needs_review": {
        +              "default": false,
        +              "description": "True when this calculation is flagged for human review — its number is not a quote yet. The reasons are on the calculation.",
        +              "type": "boolean"
        +            },
        +            "offer_price": {
        +              "anyOf": [
        +                {
        +                  "type": "number"
        +                },
        +                {
        +                  "type": "null"
        +                }
        +              ],
        +              "default": null,
        +              "description": "The headline: offer price per unit, cost-sheet surcharges included — the figure the calculation itself headlines (explain_cost's offer_price) and the one comparisons and rankings are struck on. Equal to unit_cost where the environment states no surcharges. Null until priced, and null on an assembly priced only in part (assembly_partial)."
        +            },
        +            "offer_price_delta_vs_best": {
        +              "anyOf": [
        +                {
        +                  "type": "number"
        +                },
        +                {
        +                  "type": "null"
        +                }
        +              ],
        +              "default": null,
        +              "description": "Offer-price premium per unit over the winner (0 for the winner)."
        +            },
        +            "offer_price_delta_vs_best_pct": {
        +              "anyOf": [
        +                {
        +                  "type": "number"
        +                },
        +                {
        +                  "type": "null"
        +                }
        +              ],
        +              "default": null,
        +              "description": "Premium as % of the winner's offer price."
        +            },
        +            "overhead_scheme": {
        +              "anyOf": [
        +                {
        +                  "type": "string"
        +                },
        +                {
        +                  "type": "null"
        +                }
        +              ],
        +              "default": null,
        +              "description": "Which overhead system unit_cost was built on: 'flat' when the cost sheet carries the flat variable overhead (overhead_var) inside unit_cost, 'ladder' when the environment states Material-/Fertigungsgemeinkosten, which switch that default off and sit above unit_cost; null when the result states neither."
        +            },
        +            "rank": {
        +              "anyOf": [
        +                {
        +                  "type": "integer"
        +                },
        +                {
        +                  "type": "null"
        +                }
        +              ],
        +              "default": null,
        +              "description": "1 = the priced option with the lowest offer_price. Null for a calc with no price yet (blocked / not succeeded) and for an assembly priced only in part (assembly_partial); those sort to the end."
        +            },
        +            "status": {
        +              "anyOf": [
        +                {
        +                  "type": "string"
        +                },
        +                {
        +                  "type": "null"
        +                }
        +              ],
        +              "default": null
        +            },
        +            "total_cost": {
        +              "anyOf": [
        +                {
        +                  "type": "number"
        +                },
        +                {
        +                  "type": "null"
        +                }
        +              ],
        +              "default": null,
        +              "description": "unit_cost for the whole lot, on the same basis as unit_cost."
        +            },
        +            "unit_cost": {
        +              "anyOf": [
        +                {
        +                  "type": "number"
        +                },
        +                {
        +                  "type": "null"
        +                }
        +              ],
        +              "default": null,
        +              "description": "Unit cost per part: direct cost plus overhead_var and overhead_fixed. Where the costing environment states no Material-/Fertigungsgemeinkosten, overhead_var is the flat variable overhead the environment states (none by default); once it states them, those overheads sit above unit_cost as cost-sheet rungs, with administration and selling, margin and the other surcharges. Secondary: it is not like-for-like across environments, nor across overhead schemes (see overhead_scheme)."
        +            },
        +            "unit_cost_delta_vs_best": {
        +              "anyOf": [
        +                {
        +                  "type": "number"
        +                },
        +                {
        +                  "type": "null"
        +                }
        +              ],
        +              "default": null,
        +              "description": "This option's unit cost minus the winner's (the winner is the lowest offer price). Negative when this option costs less to make but more to buy: its environment states larger cost-sheet surcharges than the winner's. Null when the options use different overhead schemes (cost_scheme_mismatch)."
        +            },
        +            "unit_cost_delta_vs_best_pct": {
        +              "anyOf": [
        +                {
        +                  "type": "number"
        +                },
        +                {
        +                  "type": "null"
        +                }
        +              ],
        +              "default": null,
        +              "description": "unit_cost_delta_vs_best as % of the winner's unit cost."
        +            },
        +            "unit_time_delta_vs_best_s": {
        +              "anyOf": [
        +                {
        +                  "type": "number"
        +                },
        +                {
        +                  "type": "null"
        +                }
        +              ],
        +              "default": null,
        +              "description": "Production seconds/unit vs the cheapest option — so a cheaper winner that is slower (capacity impact) stays visible."
        +            },
        +            "unit_time_s": {
        +              "anyOf": [
        +                {
        +                  "type": "number"
        +                },
        +                {
        +                  "type": "null"
        +                }
        +              ],
        +              "default": null,
        +              "description": "Production time per unit, in seconds."
        +            }
        +          },
        +          "required": [
        +            "calculation_id"
        +          ],
        +          "type": "object"
        +        },
        +        "type": "array"
        +      },
        +      "total_count": {
        +        "description": "How many distinct calculations were ranked.",
        +        "type": "integer"
        +      }
        +    },
        +    "required": [
        +      "ranked",
        +      "priced_count",
        +      "total_count",
        +      "comparable",
        +      "note"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
    • Changedexplain_cost12 fields changed
      • addedInput schema / properties / calculation_id / format
        Added value: +"uuid"
      • changedInput schema / properties / detail / description
        Previous value: -"How many cost drivers to list: 'concise' (the default) lists the top 3, 'detailed' the top 10."New value: +"How many cost drivers to list: 'concise' (the default) lists the top 3 cost categories and the top 3 features (an assembly's top 3 rows), 'detailed' the top 10."
      • addedOutput schema / properties / clampings
        Added value: +{
        +  "anyOf": [
        +    {
        +      "items": {
        +        "description": "How many times one machine clamps the part.",
        +        "properties": {
        +          "count": {
        +            "anyOf": [
        +              {
        +                "type": "integer"
        +              },
        +              {
        +                "type": "null"
        +              }
        +            ],
        +            "default": null,
        +            "description": "Clampings on that machine — the count its handling was costed on."
        +          },
        +          "machine": {
        +            "anyOf": [
        +              {
        +                "type": "string"
        +              },
        +              {
        +                "type": "null"
        +              }
        +            ],
        +            "default": null,
        +            "description": "Machine / work centre, by the name it is known by."
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "How many times each machine on the route clamps the part, in route order — the same count the route was costed on. Absent when the route did not state a count."
        +}
      • addedOutput schema / properties / material_priced
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "The material this calculation was priced as, by its short name — the environment's default material when material_resolved is false. On an assembly whose components name their own materials, each one, comma-separated."
        +}
      • addedOutput schema / properties / material_source
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Where material_priced came from: 'request', 'drawing_title_block' (the part's drawing), 'step_material_property' (the material its STEP file names), 'assembly_drawing_title_block' or 'environment_default'. The first that names a material wins, in that order: request, drawing, STEP file, environment default."
        +}
      • changedOutput schema / properties / top_drivers / description
        Previous value: -"What drives the cost, largest first: a part's features (pocket, hole, slot), or an assembly's components and its own joining. 3 drivers, or 10 with detail 'detailed'."New value: +"What drives the cost, largest first. On a part: the cost categories first (setup, subcontract, material, machine …), each with its cost and its share of unit_cost, and an 'other' row with the categories not listed, so these rows add up to unit_cost; then the features (pocket, hole, slot), which split the run-time categories (machine, labour, finishing) and so are part of those rows, never added to them. A part with no machined features (a flat pattern) lists the categories alone; one priced before the cost sheet existed, the features alone. On an assembly: its components and its own joining. The top 3 categories and the top 3 features (an assembly's top 3 rows), or 10 with detail 'detailed'."
      • addedOutput schema / properties / top_drivers / items / properties / category
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Set on a cost-category row: its key in cost_categories (setup, subcontract, material, machine …), or 'other' on the row that holds every category not listed. Absent on a feature or component row."
        +}
      • changedOutput schema / properties / top_drivers / items / properties / cost / description
        Previous value: -"Cost contribution per unit, in the calculation's currency (the result's `currency`) — the DIRECT run-time cost the feature consumes (machine, labour and finishing time), before any setup, programming, tooling or overhead is spread onto it. The tenant's cost-driver card can show the same rows fully loaded, so its per-feature figure is higher than this by one uniform factor; the ranking and the relative shares are identical on both bases."New value: +"Cost contribution per unit, in the calculation's currency (the result's `currency`). On a cost-category row it is that line of the cost sheet. On a feature row it is the DIRECT run-time cost the feature consumes (machine, labour and finishing time), before any setup, programming, tooling or overhead is spread onto it. The tenant's cost-driver card can show the feature rows fully loaded, so its per-feature figure is higher than this by one uniform factor; the ranking and the relative shares are identical on both bases."
      • changedOutput schema / properties / top_drivers / items / properties / cost_share_pct / description
        Previous value: -"Share of unit cost, 0–100, on the same direct basis as cost. Sum the listed rows against attributed_cost_share_pct, not against 100."New value: +"Share of unit cost, 0–100, on the same basis as cost. The category rows, 'other' included, add up to 100. The feature rows add up to the share the named features explain (attributed_cost_share_pct where the result states it), not to 100."
      • changedOutput schema / properties / top_drivers / items / properties / rank / description
        Previous value: -"1 = the largest driver."New value: +"1 = the largest driver. Cost categories and features are ranked separately; null on the row that holds the categories not listed."
      • changedOutput schema / properties / unit_cost / description
        Previous value: -"Unit cost per part: direct cost plus overhead_var and overhead_fixed. Where the costing environment states no Material-/Fertigungsgemeinkosten, overhead_var is the flat variable overhead (platform default 15 % of direct cost); once it states them, that default is 0 and those overheads sit above unit_cost as cost-sheet rungs, with administration and selling, margin and the other surcharges. Not the price to quote: that is offer_price, equal to unit_cost only where no surcharges are stated."New value: +"Unit cost per part: direct cost plus overhead_var and overhead_fixed. Where the costing environment states no Material-/Fertigungsgemeinkosten, overhead_var is the flat variable overhead the environment states (none by default); once it states them, those overheads sit above unit_cost as cost-sheet rungs, with administration and selling, margin and the other surcharges. Not the price to quote: that is offer_price, equal to unit_cost only where no surcharges are stated."
      • addedOutput schema / properties / unpriced
        Added value: +{
        +  "anyOf": [
        +    {
        +      "items": {
        +        "description": "Work the drawing requires that no machine here can do.",
        +        "properties": {
        +          "process": {
        +            "anyOf": [
        +              {
        +                "type": "string"
        +              },
        +              {
        +                "type": "null"
        +              }
        +            ],
        +            "default": null,
        +            "description": "The manufacturing process, in plain words."
        +          },
        +          "reason": {
        +            "anyOf": [
        +              {
        +                "type": "string"
        +              },
        +              {
        +                "type": "null"
        +              }
        +            ],
        +            "default": null,
        +            "description": "Why this work is not in the price."
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Work the drawing requires that no machine in this environment can do, so it is not in the price. Each entry names the process and why. Absent when the route covers what the drawing asks for."
        +}
    • Changedget_cost_breakdown7 fields changed
      • addedInput schema / properties / calculation_id / format
        Added value: +"uuid"
      • changedInput schema / properties / max_depth / description
        Previous value: -"How many tiers of cost_lines to return: 1 the cost categories only, 2 (the default) the categories and the tier beneath, null the whole tree. A line cut short states in children_hidden how many lines sit beneath it."New value: +"How many tiers of cost_lines to return: 1 the cost categories only, 2 (the default) the categories and the tier beneath, null the whole tree. A line cut short states in children_hidden how many lines sit beneath it. With a depth set, a line also leaves out the keys it has no value for (null, [] or {})."
      • addedOutput schema / $defs / CostDriverLine / properties / category
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Set on a cost-category row: its key in cost_categories (setup, subcontract, material, machine …), or 'other' on the row that holds every category not listed. Absent on a feature or component row."
        +}
      • changedOutput schema / $defs / CostDriverLine / properties / cost / description
        Previous value: -"Cost contribution per unit, in the calculation's currency (the result's `currency`) — the DIRECT run-time cost the feature consumes (machine, labour and finishing time), before any setup, programming, tooling or overhead is spread onto it. The tenant's cost-driver card can show the same rows fully loaded, so its per-feature figure is higher than this by one uniform factor; the ranking and the relative shares are identical on both bases."New value: +"Cost contribution per unit, in the calculation's currency (the result's `currency`). On a cost-category row it is that line of the cost sheet. On a feature row it is the DIRECT run-time cost the feature consumes (machine, labour and finishing time), before any setup, programming, tooling or overhead is spread onto it. The tenant's cost-driver card can show the feature rows fully loaded, so its per-feature figure is higher than this by one uniform factor; the ranking and the relative shares are identical on both bases."
      • changedOutput schema / $defs / CostDriverLine / properties / cost_share_pct / description
        Previous value: -"Share of unit cost, 0–100, on the same direct basis as cost. Sum the listed rows against attributed_cost_share_pct, not against 100."New value: +"Share of unit cost, 0–100, on the same basis as cost. The category rows, 'other' included, add up to 100. The feature rows add up to the share the named features explain (attributed_cost_share_pct where the result states it), not to 100."
      • changedOutput schema / $defs / CostDriverLine / properties / rank / description
        Previous value: -"1 = the largest driver."New value: +"1 = the largest driver. Cost categories and features are ranked separately; null on the row that holds the categories not listed."
      • changedOutput schema / properties / unit_cost / description
        Previous value: -"Unit cost per part at `quantity`: direct cost plus overhead_var and overhead_fixed. Where the costing environment states no Material-/Fertigungsgemeinkosten, overhead_var is the flat variable overhead (platform default 15 % of direct cost); once it states them, that default is 0 and those overheads sit above unit_cost as cost-sheet rungs, with administration and selling, margin and the other surcharges. The price to quote is offer_price."New value: +"Unit cost per part at `quantity`: direct cost plus overhead_var and overhead_fixed. Where the costing environment states no Material-/Fertigungsgemeinkosten, overhead_var is the flat variable overhead the environment states (none by default); once it states them, those overheads sit above unit_cost as cost-sheet rungs, with administration and selling, margin and the other surcharges. The price to quote is offer_price."
    • Changedget_process_plan3 fields changed
      • addedInput schema / properties / calculation_id / format
        Added value: +"uuid"
      • addedOutput schema / properties / clampings
        Added value: +{
        +  "anyOf": [
        +    {
        +      "items": {
        +        "description": "How many times one machine clamps the part.",
        +        "properties": {
        +          "count": {
        +            "anyOf": [
        +              {
        +                "type": "integer"
        +              },
        +              {
        +                "type": "null"
        +              }
        +            ],
        +            "default": null,
        +            "description": "Clampings on that machine — the count its handling was costed on."
        +          },
        +          "machine": {
        +            "anyOf": [
        +              {
        +                "type": "string"
        +              },
        +              {
        +                "type": "null"
        +              }
        +            ],
        +            "default": null,
        +            "description": "Machine / work centre, by the name it is known by."
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "How many times each machine clamps the part, in route order — the same count the route was costed on. Absent when the route did not state a count."
        +}
      • addedOutput schema / properties / unpriced
        Added value: +{
        +  "anyOf": [
        +    {
        +      "items": {
        +        "description": "Work the drawing requires that no machine here can do.",
        +        "properties": {
        +          "process": {
        +            "anyOf": [
        +              {
        +                "type": "string"
        +              },
        +              {
        +                "type": "null"
        +              }
        +            ],
        +            "default": null,
        +            "description": "The manufacturing process, in plain words."
        +          },
        +          "reason": {
        +            "anyOf": [
        +              {
        +                "type": "string"
        +              },
        +              {
        +                "type": "null"
        +              }
        +            ],
        +            "default": null,
        +            "description": "Why this work is not in the price."
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Work the drawing requires that no machine in this environment can do, so it is not in the price. Each entry names the process and why. Absent when the route covers what the drawing asks for."
        +}
    • Changedget_upload_link12 fields changed
      • changedInput schema / properties / environment_id / description
        Previous value: -"Costing environment to price the uploads in (optional; the organization's default when omitted)."New value: +"Costing environment to price the uploaded parts in (optional; the organization's default when omitted)."
      • changedInput schema / properties / folder_id / description
        Previous value: -"Folder to file the uploads into (optional)."New value: +"Folder to file the uploaded parts into (optional)."
      • addedInput schema / properties / max_uploads
        Added value: +{
        +  "default": 1,
        +  "description": "How many parts the person may upload through the link, 1 to 20 (default 1). Each part is one STEP file with an optional drawing.",
        +  "maximum": 20,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • changedOutput schema / description
        Previous value: -"A link to the arcnm upload page, for the person to open in a browser.\nThe files go from their computer straight to arcnm; nothing passes\nthrough the agent."New value: +"A link to the arcnm upload page that works without signing in, for the\nperson to open in a browser. The files go from their computer straight\nto arcnm; nothing passes through the agent."
      • changedOutput schema / properties / environment_id / description
        Previous value: -"The costing environment the uploads are priced in; omitted means the organization's default."New value: +"The costing environment the parts are priced in."
      • addedOutput schema / properties / expires_at
        Added value: +{
        +  "description": "When the link stops working (RFC 3339, UTC).",
        +  "type": "string"
        +}
      • changedOutput schema / properties / folder_id / description
        Previous value: -"The folder the uploads are filed into."New value: +"The folder the parts are filed into; null for the root."
      • changedOutput schema / properties / issued_at / description
        Previous value: -"When this link was issued (RFC 3339, UTC). As list_calculations' created_after, it lists the calculations the person starts on the page."New value: +"When this link was issued (RFC 3339, UTC)."
      • addedOutput schema / properties / max_uploads
        Added value: +{
        +  "description": "How many parts the person may upload through the link.",
        +  "type": "integer"
        +}
      • addedOutput schema / properties / upload_session_id
        Added value: +{
        +  "description": "The link's id. Every calculation an upload on the page creates carries it, and list_calculations with upload_session_id set to it lists exactly those calculations, and no one else's.",
        +  "type": "string"
        +}
      • changedOutput schema / properties / url / description
        Previous value: -"The arcnm upload page, scoped to the folder and environment named in the call. The person opens it while signed in to arcnm, drops the STEP (3D) and PDF (drawing) files, and arcnm files and prices each part."New value: +"The arcnm upload page. The person opens it in a browser, without signing in, and drops one STEP (3D) file per part, a PDF drawing optional; arcnm files and prices each part in the folder and costing environment below. Whoever has the URL can upload into this organization until it expires, so it is for that person only."
      • changedOutput schema / required
        Previous value: -[
        -  "url",
        -  "issued_at",
        -  "next_step"
        -]New value: +[
        +  "url",
        +  "upload_session_id",
        +  "expires_at",
        +  "max_uploads",
        +  "issued_at",
        +  "next_step"
        +]
    • Changedlist_calculations4 fields changed
      • addedInput schema / properties / limit / maximum
        Added value: +500
      • addedInput schema / properties / limit / minimum
        Added value: +1
      • changedInput schema / properties / sort / description
        Previous value: -"Ordering key. Rows with no value yet (an in-flight run has no unit cost) sort last in both directions. Ignored when `ids` is set. `offer_price` orders on the price each calculation headlines and the comparison ranks on (the item's `offer_price`; an assembly priced only in part states none and sorts last); `unit_cost` on the unit cost (direct cost plus the flat overheads, below the cost-sheet rungs). `created_at`, `lot_size` and `annual_volume` support `cursor`; `unit_cost`, `offer_price` and `finished_at` are null until a run settles, so a cursor over them cannot reach every row and is rejected — those three return the first page only."New value: +"Ordering key. Rows with no value yet (an in-flight run has no unit cost) sort last in both directions. Ignored when `ids` is set. `offer_price` orders on the price each calculation headlines and the comparison ranks on (the item's `offer_price`; an assembly priced only in part states none and sorts last); `unit_cost` on the unit cost (direct cost plus the flat overheads, below the cost-sheet rungs). `created_at`, `offer_price`, `lot_size` and `annual_volume` support `cursor`; `unit_cost` and `finished_at` are null until a run settles, so a cursor over them cannot reach every row and is rejected — those two return the first page only."
      • addedInput schema / properties / upload_session_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "format": "uuid",
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "description": "Only the calculations created through one upload link, by the `upload_session_id` the link was issued with — the parts a person uploaded on its page, and no one else's.",
        +  "title": "Upload Session Id"
        +}
    • Changedoptimize_lot_size1 field changed
      • addedInput schema / properties / calculation_id / format
        Added value: +"uuid"
    • Changedpreview_cost1 field changed
      • addedInput schema / properties / calculation_id / format
        Added value: +"uuid"
    • Changedsuggest_cost_savings2 fields changed
      • addedInput schema / properties / calculation_id / format
        Added value: +"uuid"
      • changedOutput schema / properties / findings / items / properties / kind / description
        Previous value: -"Finding kind, e.g. review_tolerance_cost."New value: +"Finding kind, e.g. adjust_lot_size."
  4. 9 tool updates
    • Changedcancel_calculation1 field changed
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedexplain_cost2 fields changed
      • changedOutput schema / properties / assembly_completeness / description
        Previous value: -"ASSEMBLIES ONLY. Whether `unit_cost` is a price or a LOWER BOUND. Carries {n_unique, n_priced, n_pending, n_unpriced, total_is_lower_bound, priced_complete, unpriced[]}, where each unpriced entry has a closed-enum `reason_code`, a `by_design` flag and, where one exists, a `remedy`. When `total_is_lower_bound` is true, `unit_cost` is a lower bound, not a complete price. A `by_design` reason (a part budget, a plan quota, a cancellation) is a configured limit, not a processing error."New value: +"ASSEMBLIES ONLY. Whether `unit_cost` is a price or a LOWER BOUND. Carries {n_unique, n_priced, n_pending, n_unpriced, total_is_lower_bound, priced_complete, unpriced[], unpriced_steps[]}, where each unpriced entry has a closed-enum `reason_code`, a `by_design` flag and, where one exists, a `remedy`. `priced_complete` and `total_is_lower_bound` cover the COMPONENTS only (the BOM rows counted in n_unique): `priced_complete` is true when every component priced, and when `total_is_lower_bound` is true a component is missing, so `unit_cost` is a lower bound, not a complete price. `unpriced_steps` lists the assembly's own route steps that carry no price, with their reason, worded as get_process_plan words them (e.g. 'Straightening — unpriced (straightening_shop_specific)'); they are not in `unit_cost` whatever the two flags say. A `by_design` reason (a part budget, a plan quota, a cancellation) is a configured limit, not a processing error."
      • changedOutput schema / properties / cost_categories / description
        Previous value: -"The cost sheet's own buckets per unit (material, setup, machine, labour, programming, tooling, finishing, overheads …) in the quote's currency — exactly the lines the product shows, setup as its own line. Absent on calculations priced before the sheet existed."New value: +"The cost sheet's own buckets per unit (material, setup, machine, labour, programming, tooling, finishing, overheads …) in the quote's currency — exactly the lines the product shows, setup as its own line. On an assembly: its roll-up terms (components_cost, joining_cost, …) and the cost-sheet rungs above them, the same map get_cost_breakdown states, adding up to offer_price. Absent on calculations priced before the sheet existed."
    • Changedget_calculation1 field changed
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedget_cost_breakdown2 fields changed
      • addedInput schema / properties / max_depth
        Added value: +{
        +  "anyOf": [
        +    {
        +      "minimum": 1,
        +      "type": "integer"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": 2,
        +  "description": "How many tiers of cost_lines to return: 1 the cost categories only, 2 (the default) the categories and the tier beneath, null the whole tree. A line cut short states in children_hidden how many lines sit beneath it."
        +}
      • addedOutput schema / $defs / CostSheetNode / properties / children_hidden
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "integer"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "How many lines sit beneath this one that `max_depth` left out: ask again with a larger `max_depth`, or null, to see them. Absent when nothing beneath this line was left out."
        +}
    • Changedlist_calculations1 field changed
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedlist_environments1 field changed
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedpreview_cost8 fields changed
      • addedInput schema / properties / detail
        Added value: +{
        +  "default": "summary",
        +  "description": "'summary' (the default): the headline before and after, the change per cost category and only the cost lines that moved. 'full': the whole previewed cost sheet in cost_lines instead.",
        +  "enum": [
        +    "summary",
        +    "full"
        +  ],
        +  "type": "string"
        +}
      • addedOutput schema / $defs / CostLineMove
        Added value: +{
        +  "description": "One cost line whose amount the what-if moved.",
        +  "properties": {
        +    "after": {
        +      "anyOf": [
        +        {
        +          "type": "number"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "default": null,
        +      "description": "Amount per part under the what-if; null when the line is gone."
        +    },
        +    "before": {
        +      "anyOf": [
        +        {
        +          "type": "number"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "default": null,
        +      "description": "Amount per part in the priced calculation; null when the line is new."
        +    },
        +    "delta": {
        +      "default": 0,
        +      "description": "after minus before.",
        +      "type": "number"
        +    },
        +    "label_id": {
        +      "anyOf": [
        +        {
        +          "type": "string"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "default": null,
        +      "description": "Message id for this line's name."
        +    },
        +    "label_params": {
        +      "additionalProperties": true,
        +      "description": "Values the label refers to, e.g. the machine name.",
        +      "type": "object"
        +    },
        +    "path": {
        +      "description": "Bucket slugs from the top-level category down to this line, so the line can be found in get_cost_breakdown's tree.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "type": "object"
        +}
      • addedOutput schema / $defs / CostPreviewHeadline
        Added value: +{
        +  "description": "One side of a what-if's headline, in the calculation's currency.",
        +  "properties": {
        +    "lot_size": {
        +      "anyOf": [
        +        {
        +          "type": "integer"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "default": null,
        +      "description": "Lot size this side is priced at."
        +    },
        +    "offer_price": {
        +      "anyOf": [
        +        {
        +          "type": "number"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "default": null,
        +      "description": "Offer price per part: every top-level cost line, the surcharges and mark-up included."
        +    },
        +    "total_cost": {
        +      "anyOf": [
        +        {
        +          "type": "number"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "default": null,
        +      "description": "unit_cost times lot_size."
        +    },
        +    "unit_cost": {
        +      "anyOf": [
        +        {
        +          "type": "number"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "default": null,
        +      "description": "Manufacturing cost per part, on the basis of the calculation's own unit cost."
        +    }
        +  },
        +  "type": "object"
        +}
      • addedOutput schema / $defs / CostSheetNode / properties / children_hidden
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "integer"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "How many lines sit beneath this one that `max_depth` left out: ask again with a larger `max_depth`, or null, to see them. Absent when nothing beneath this line was left out."
        +}
      • addedOutput schema / properties / after
        Added value: +{
        +  "anyOf": [
        +    {
        +      "$ref": "#/$defs/CostPreviewHeadline"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "detail='summary' only: the headline under the what-if."
        +}
      • addedOutput schema / properties / before
        Added value: +{
        +  "anyOf": [
        +    {
        +      "$ref": "#/$defs/CostPreviewHeadline"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "detail='summary' only: the priced calculation's headline."
        +}
      • changedOutput schema / properties / cost_lines / description
        Previous value: -"The previewed cost sheet as a tree, same shape as get_cost_breakdown's."New value: +"The previewed cost sheet as a tree, same shape as get_cost_breakdown's. Empty under detail='summary'."
      • addedOutput schema / properties / moved_lines
        Added value: +{
        +  "anyOf": [
        +    {
        +      "items": {
        +        "$ref": "#/$defs/CostLineMove"
        +      },
        +      "type": "array"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "detail='summary' only: every cost line, at any depth, whose amount moved, each with its path in the tree. Top-level lines only when the calculation recorded no itemised sheet to compare."
        +}
    • Changedquote_part5 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • changedInput schema / properties / annual_volume / description
        Previous value: -"Expected yearly quantity, used for amortizing setup over the run (1 to 1,000,000,000)."New value: +"Expected yearly quantity, used for amortizing setup over the run (1 to 1,000,000,000). On a re-run (`derived_from_calculation_id`), omitting it keeps the annual volume of the calculation re-run."
      • changedInput schema / properties / currency / description
        Previous value: -"ISO 4217 currency code for the quote; defaults to the costing environment's currency when omitted."New value: +"ISO 4217 currency code for the quote; defaults to the costing environment's currency when omitted. Another currency needs an exchange rate from the environment's currency: a code that is not ISO 4217 is refused with 422 `currency_unknown`, one the environment has no exchange rate into with 422 `currency_not_configured`, before any calculation is created."
      • changedInput schema / properties / material_grade_id / description
        Previous value: -"UUID of a resolved material grade; takes precedence over material_ref when both are supplied."New value: +"UUID of a resolved material grade; takes precedence over material_ref when both are supplied. On a re-run (`derived_from_calculation_id`), omitting both it and `material_ref` keeps the material of the calculation re-run."
      • changedInput schema / properties / material_ref / description
        Previous value: -"Free-form material reference (URN, Werkstoffnummer, AISI/SAE code, trade name, or your SKU); resolved to a material grade. Unresolvable values are rejected with 422 material_unresolved plus ranked candidates. Omit to price the material read from the part's drawing (or the environment default)."New value: +"Free-form material reference (URN, Werkstoffnummer, AISI/SAE code, trade name, or your SKU); resolved to a material grade. Unresolvable values are rejected with 422 material_unresolved plus ranked candidates. Omit to price the material read from the part's drawing (or the environment default). On a re-run (`derived_from_calculation_id`), omitting both it and `material_grade_id` keeps the material of the calculation re-run; send `null` to price the drawing's material instead."
    • Changedupload_and_quote1 field changed
      • addedInput schema / additionalProperties
        Added value: +false
  5. 28 tool updates
    • Removedapply_adjustment
    • Removedattach_upload
    • Changedcancel_calculation1 field changed
      • addedInput schema / properties / calculation_id / description
        Added value: +"Id of a calculation, as upload_and_quote, quote_part or list_calculations return it."
    • Removedcancel_nest_run
    • Removedcompare_environments
    • Removedconfirm_upload
    • Removedcreate_nest_run
    • Removedcreate_part
    • Changedexplain_cost4 fields changed
      • addedInput schema / properties / calculation_id / description
        Added value: +"Id of a calculation, as upload_and_quote, quote_part or list_calculations return it."
      • addedInput schema / properties / detail / description
        Added value: +"How many cost drivers to list: 'concise' (the default) lists the top 3, 'detailed' the top 10."
      • changedOutput schema / properties / costing_environment_id / description
        Previous value: -"The costing environment this was priced in. get_cost_factors takes it and reads the adjustable factors behind these numbers, their range and where each one is saved."New value: +"The costing environment this was priced in: the machines, rates and overheads behind these numbers (list_environments names it)."
      • addedOutput schema / properties / top_drivers / description
        Added value: +"What drives the cost, largest first: a part's features (pocket, hole, slot), or an assembly's components and its own joining. 3 drivers, or 10 with detail 'detailed'."
    • Removedexport_nest_layout
    • Changedget_calculation1 field changed
      • addedInput schema / properties / calculation_id / description
        Added value: +"Id of a calculation, as upload_and_quote, quote_part or list_calculations return it."
    • Changedget_cost_breakdown6 fields changed
      • addedInput schema / properties / calculation_id / description
        Added value: +"Id of a calculation, as upload_and_quote, quote_part or list_calculations return it."
      • addedInput schema / properties / persona / description
        Added value: +"Which tiers to return: 'full' (the default, every tier), 'procurement' (headline and band), 'workprep' (the operations as a work plan), 'operations' (operations and machines) or 'design' (the cost sheet and feature drivers)."
      • changedOutput schema / $defs / CostSheetNode / properties / factors / description
        Previous value: -"Adjustable factors that move this line, by name — the keys get_cost_factors publishes and preview_cost accepts. A factor is listed only where this line carries what is needed to work it out, so an empty list does not mean the line is fixed."New value: +"Adjustable factors that move this line, by name: the keys preview_cost accepts. A factor is listed only where this line carries what is needed to work it out, so an empty list does not mean the line is fixed."
      • changedOutput schema / $defs / ProcessStepLine / properties / subcontract_per_part / description
        Previous value: -"What this step is charged per part at the ordered lot size, in the calculation's currency — set only on an outsourced post-machining step (heat treatment, coating), and part of the subcontract cost line. Null on a machining step: machining cost attributes to features, not to operations (use get_cost_drivers). Null too when the charge was not recorded."New value: +"What this step is charged per part at the ordered lot size, in the calculation's currency — set only on an outsourced post-machining step (heat treatment, coating), and part of the subcontract cost line. Null on a machining step: machining cost attributes to features, not to operations (explain_cost ranks them). Null too when the charge was not recorded."
      • changedOutput schema / description
        Previous value: -"One calculation as a single rough-to-detailed hierarchy — headline →\ncost category → operation → feature, with time and cost side by side — so\nevery persona can stop at the depth it needs from the SAME run.\n\n``persona`` selects the slice: 'procurement' (headline + band only),\n'workprep' (the routing / operations tier), 'operations' (routing + machines\nfor balancing), 'design' (cost categories + per-feature drivers), or 'full'\n(every tier). Tiers not relevant to the persona come back empty.\n\nThe category tier is the itemised cost sheet: ``cost_lines`` is the whole\ntree — cost category, then per machine, per clamping, per work element —\nand ``cost_categories`` is its top level flattened for a quick read. Both\ncome from the one sheet the cost-sheet endpoint serves and the app renders,\nso an agent and a person read the same numbers rather than two\nderivations of them. This is the CATEGORY axis of the cost; for the\nFEATURE axis (which pocket, which hole) use get_cost_drivers."New value: +"One calculation as a single rough-to-detailed hierarchy — headline →\ncost category → operation → feature, with time and cost side by side — so\nevery persona can stop at the depth it needs from the SAME run.\n\n``persona`` selects the slice: 'procurement' (headline + band only),\n'workprep' (the routing / operations tier), 'operations' (routing + machines\nfor balancing), 'design' (cost categories + per-feature drivers), or 'full'\n(every tier). Tiers not relevant to the persona come back empty.\n\nThe category tier is the itemised cost sheet: ``cost_lines`` is the whole\ntree — cost category, then per machine, per clamping, per work element —\nand ``cost_categories`` is its top level flattened for a quick read. Both\ncome from the one sheet the cost-sheet endpoint serves and the app renders,\nso an agent and a person read the same numbers rather than two\nderivations of them. This is the CATEGORY axis of the cost; for the\nFEATURE axis (which pocket, which hole) explain_cost ranks the drivers."
      • changedOutput schema / properties / costing_environment_id / description
        Previous value: -"The costing environment this was priced in. get_cost_factors takes it and reads the factors named in each line's ``factors``, their range and where each one is saved."New value: +"The costing environment this was priced in: the machines, rates and overheads the factors named in each line's ``factors`` belong to."
    • Removedget_cost_drivers
    • Removedget_cost_factors
    • Removedget_environment
    • Removedget_nest_run
    • Removedget_nesting_summary
    • Changedget_process_plan3 fields changed
      • addedInput schema / properties / calculation_id / description
        Added value: +"Id of a calculation, as upload_and_quote, quote_part or list_calculations return it."
      • changedOutput schema / description
        Previous value: -"The ordered process plan (routing) for a calculation — the sequence of\noperations that make the part, each with its process, work center, and\ncycle time, plus the plan-level setup / cycle / total time and machine(s).\n\nThe sequence runs to the finished part: machining first, then the\npost-machining chain (welding, heat treatment, surface finishing, coating).\nThose trailing steps carry no cycle time — an outsourced treatment is priced\nper order, not in machine seconds — so they are outside the plan-level cycle\ntotal; each reports what it is charged in subcontract_per_part, and those\ncharges make up the subcontract cost line.\n\nThis is the work-plan an Arbeitsvorbereitung (work-preparation) or\noperations user acts on. Two honest limits reflect how the engine models\ncost: setup is planned per setup (not per operation) and amortised over the\nlot, so it is reported once at the plan level; and machining cost attributes\nto features, not operations, so a machining step carries no cost of its own —\nuse get_cost_drivers for the feature-level cost breakdown. An outsourced\npost-machining step is the exception: it is bought per operation, so it is\nthe one kind of step that reports what it costs."New value: +"The ordered process plan (routing) for a calculation — the sequence of\noperations that make the part, each with its process, work center, and\ncycle time, plus the plan-level setup / cycle / total time and machine(s).\n\nThe sequence runs to the finished part: machining first, then the\npost-machining chain (welding, heat treatment, surface finishing, coating).\nThose trailing steps carry no cycle time — an outsourced treatment is priced\nper order, not in machine seconds — so they are outside the plan-level cycle\ntotal; each reports what it is charged in subcontract_per_part, and those\ncharges make up the subcontract cost line.\n\nThis is the work-plan an Arbeitsvorbereitung (work-preparation) or\noperations user acts on. Two honest limits reflect how the engine models\ncost: setup is planned per setup (not per operation) and amortised over the\nlot, so it is reported once at the plan level; and machining cost attributes\nto features, not operations, so a machining step carries no cost of its own —\nexplain_cost ranks the features that carry it. An outsourced\npost-machining step is the exception: it is bought per operation, so it is\nthe one kind of step that reports what it costs."
      • changedOutput schema / properties / steps / items / properties / subcontract_per_part / description
        Previous value: -"What this step is charged per part at the ordered lot size, in the calculation's currency — set only on an outsourced post-machining step (heat treatment, coating), and part of the subcontract cost line. Null on a machining step: machining cost attributes to features, not to operations (use get_cost_drivers). Null too when the charge was not recorded."New value: +"What this step is charged per part at the ordered lot size, in the calculation's currency — set only on an outsourced post-machining step (heat treatment, coating), and part of the subcontract cost line. Null on a machining step: machining cost attributes to features, not to operations (explain_cost ranks them). Null too when the charge was not recorded."
    • Changedget_upload_link3 fields changed
      • addedOutput schema / properties / issued_at
        Added value: +{
        +  "description": "When this link was issued (RFC 3339, UTC). As list_calculations' created_after, it lists the calculations the person starts on the page.",
        +  "type": "string"
        +}
      • changedOutput schema / properties / next_step / description
        Previous value: -"How to find the new parts and calculations once the person says the upload is done."New value: +"How to find the new calculations once the person says the upload is done."
      • changedOutput schema / required
        Previous value: -[
        -  "url",
        -  "next_step"
        -]New value: +[
        +  "url",
        +  "issued_at",
        +  "next_step"
        +]
    • Changedlist_calculations1 field changed
      • addedInput schema / properties / part_id / description
        Added value: +"Only the calculations of this part, by its id (part_id on any calculation)."
    • Removedlist_part_revisions
    • Removedlist_parts
    • Changedoptimize_lot_size1 field changed
      • addedInput schema / properties / calculation_id / description
        Added value: +"Id of a calculation, as upload_and_quote, quote_part or list_calculations return it."
    • Removedpresign_upload
    • Changedpreview_cost4 fields changed
      • addedInput schema / properties / adjustments / description
        Added value: +"The factors to move, as {factor_key: new_value}. The keys are the ones get_cost_breakdown shows on each cost line. Omit to re-price at another lot_size only."
      • addedInput schema / properties / calculation_id / description
        Added value: +"Id of a calculation, as upload_and_quote, quote_part or list_calculations return it."
      • addedInput schema / properties / lot_size / description
        Added value: +"Lot size to price the what-if at. Omit to keep the calculation's own lot size."
      • changedOutput schema / $defs / CostSheetNode / properties / factors / description
        Previous value: -"Adjustable factors that move this line, by name — the keys get_cost_factors publishes and preview_cost accepts. A factor is listed only where this line carries what is needed to work it out, so an empty list does not mean the line is fixed."New value: +"Adjustable factors that move this line, by name: the keys preview_cost accepts. A factor is listed only where this line carries what is needed to work it out, so an empty list does not mean the line is fixed."
    • Removedstart_nest_run
    • Changedsuggest_cost_savings1 field changed
      • addedInput schema / properties / calculation_id / description
        Added value: +"Id of a calculation, as upload_and_quote, quote_part or list_calculations return it."
    • Addedupload_and_quote
  6. 10 tool updates
    • Addedapply_adjustment
    • Addedattach_upload
    • Addedcancel_calculation
    • Addedcancel_nest_run
    • Addedconfirm_upload
    • Addedcreate_nest_run
    • Addedcreate_part
    • Addedpresign_upload
    • Addedquote_part
    • Addedstart_nest_run
  7. 10 tool updates
    • Removedapply_adjustment
    • Removedattach_upload
    • Removedcancel_calculation
    • Removedcancel_nest_run
    • Removedconfirm_upload
    • Removedcreate_nest_run
    • Removedcreate_part
    • Removedpresign_upload
    • Removedquote_part
    • Removedstart_nest_run
  8. 3 tool updates
    • Changedexplain_cost2 fields changed
      • changedOutput schema / properties / costing_environment_id / description
        Previous value: -"The costing environment this was priced in — pass it to get_cost_factors to read the adjustable factors behind these numbers, their range and where each one is saved."New value: +"The costing environment this was priced in. get_cost_factors takes it and reads the adjustable factors behind these numbers, their range and where each one is saved."
      • changedOutput schema / properties / coverage / description
        Previous value: -"Present only when status is 'blocked': the calc was created but NOT run because the organization is out of included calculations, has reached a monthly overage cap, or is payment-blocked. Carries {reason, message, remaining, used, included, upgrade_url} — 'reason' says which, and 'message' says how to unblock it. Resolve that, then re-run the saved part. Never a 402; the part is not lost."New value: +"Present only when status is 'blocked': the calculation was created but not run because the organization has no included calculations left, has reached its monthly overage cap, or has its billing paused. Carries {reason, message, remaining, used, included, tier_slug, window}: 'reason' says which, 'message' states it in a sentence. The part is saved; a later calculation of it runs once the block is lifted. Never a 402."
    • Changedexport_nest_layout4 fields changed
      • changedOutput schema / properties / download_url / description
        Previous value: -"The whole export: the zip of every sheet (dxf, svg) or the plan (json). GET it with your API key."New value: +"The address of the whole export: the zip of every sheet (dxf, svg) or the plan (json)."
      • changedOutput schema / properties / plan_outlines_included / description
        Previous value: -"False when the inline plan left the contours out for size; the plan's download link carries them."New value: +"False when the inline plan left the contours out for size; the file at download_url carries them."
      • changedOutput schema / properties / sheets / items / properties / download_url / description
        Previous value: -"GET it with your API key for this sheet's file in the requested format."New value: +"The address of this sheet's file in the requested format."
      • changedOutput schema / properties / status / description
        Previous value: -"ready, or preparing: the files are still being built and nothing else is answered — call the tool again after retry_after_s."New value: +"ready, or preparing: the files are still being built and nothing else is answered; retry_after_s says how long that takes."
    • Changedget_cost_breakdown1 field changed
      • changedOutput schema / properties / costing_environment_id / description
        Previous value: -"The costing environment this was priced in — pass it to get_cost_factors to read the factors named in each line's ``factors``, their range and where each one is saved."New value: +"The costing environment this was priced in. get_cost_factors takes it and reads the factors named in each line's ``factors``, their range and where each one is saved."
  9. 7 tool updates
    • Changedcheck_quota5 fields changed
      • changedOutput schema / description
        Previous value: -"This organization's remaining calculation quota and monthly overage\nbudget — check before a bulk run so you can upgrade the plan (or raise the\noverage cap) up front instead of parking calcs as 'blocked'."New value: +"This organization's calculation allowance for the current period and\nits overage budget: how many calculations are included, used and\nremaining, and what happens to a run beyond the allowance."
      • changedOutput schema / properties / has_payment_method / description
        Previous value: -"Whether a card is on file. Required before any calculation beyond the included volume on a 'wallet' plan."New value: +"Whether a payment method is on file; a 'wallet' plan needs one for calculations beyond the included volume."
      • changedOutput schema / properties / overage_settlement / description
        Previous value: -"How overage is paid: 'wallet' (prepaid — the balance is the ceiling, top up to continue) or 'invoice' (contracted, billed in arrears)."New value: +"How overage is paid: 'wallet' (a prepaid balance that is the ceiling) or 'invoice' (contracted, billed in arrears)."
      • changedOutput schema / properties / wallet_funded_calculations / description
        Previous value: -"How many more overage calculations the balance covers. Check this before a bulk run — past it, calculations park as 'blocked'."New value: +"How many more overage calculations the current balance covers; beyond it, calculations park as 'blocked'."
      • changedOutput schema / properties / wallet_overdrawn / description
        Previous value: -"True when the prepaid balance has reached its hard floor — calculations are paused and further runs park as 'blocked' until the balance is topped up. Check this before a bulk run."New value: +"True when the prepaid balance has reached its hard floor — calculations are paused and further runs park as 'blocked' until the balance is topped up."
    • Changedcompare_environments1 field changed
      • changedOutput schema / properties / environments / items / properties / stale_cells / description
        Previous value: -"Cells priced before the environment's last edit — re-run before trusting them."New value: +"Cells priced before the environment's last edit; a re-run prices them on the current environment."
    • Changedexplain_cost2 fields changed
      • changedOutput schema / properties / confidence / anyOf
        Previous value: -[
        -  {
        -    "description": "Quote-trust headline — is this number calibrated to the shop, or a model\nestimate? The signal a procurement / supplier persona reads alongside the\nprediction band before trusting a should-cost.",
        -    "properties": {
        -      "calibrated": {
        -        "anyOf": [
        -          {
        -            "type": "boolean"
        -          },
        -          {
        -            "type": "null"
        -          }
        -        ],
        -        "default": null,
        -        "description": "True when a calibration to your shop's actuals moved this price. Recorded when the calculation ran — the same flag the comparison tools report — so publishing or retiring a calibration later does not change it. Null on a calculation priced before the platform recorded this: unknown, not uncalibrated."
        -      },
        -      "headline": {
        -        "anyOf": [
        -          {
        -            "type": "string"
        -          },
        -          {
        -            "type": "null"
        -          }
        -        ],
        -        "default": null,
        -        "description": "Trust headline: high | medium | low."
        -      },
        -      "state": {
        -        "anyOf": [
        -          {
        -            "type": "string"
        -          },
        -          {
        -            "type": "null"
        -          }
        -        ],
        -        "default": null,
        -        "description": "green = calibrated to your actuals; grey = uncalibrated estimate with a prediction band; white = uncalibrated model estimate."
        -      }
        -    },
        -    "type": "object"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "description": "Quote-trust headline — is this number calibrated to the shop, or a model\nestimate? The signal a procurement / supplier persona reads alongside the\nprediction band.",
        +    "properties": {
        +      "calibrated": {
        +        "anyOf": [
        +          {
        +            "type": "boolean"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "description": "True when a calibration to your shop's actuals moved this price. Recorded when the calculation ran — the same flag the comparison tools report — so publishing or retiring a calibration later does not change it. Null on a calculation priced before the platform recorded this: unknown, not uncalibrated."
        +      },
        +      "headline": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "description": "Trust headline: high | medium | low."
        +      },
        +      "state": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "description": "green = calibrated to your actuals; grey = uncalibrated estimate with a prediction band; white = uncalibrated model estimate."
        +      }
        +    },
        +    "type": "object"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • changedOutput schema / properties / confidence / description
        Previous value: -"Quote-trust signal (calibrated vs model estimate) — read it with the band before trusting the number."New value: +"Quote-trust signal: calibrated to the shop, or a model estimate — read together with the prediction band."
    • Changedget_calculation1 field changed
      • changedInput schema / properties / include_analytics / description
        Previous value: -"Whether to include the `analytics` object (the full cost breakdown and audit detail, often over 100 kB). Omitted: included for the app and the REST API, left out (null) for an MCP agent — pass true to get it, or read the cost through the cost sheet (`GET /calculations/{calculation_id}/cost-sheet`; over MCP, `get_cost_breakdown`), which is compact. Pass false to leave it out anywhere."New value: +"Whether to include the `analytics` object (the full cost breakdown and audit detail, often over 100 kB). Omitted: included for the app and the REST API, left out (null) for an MCP agent — pass true to get it, or read the cost through the cost sheet (the `get_cost_breakdown` tool; over MCP, `get_cost_breakdown`), which is compact. Pass false to leave it out anywhere."
    • Changedget_cost_breakdown2 fields changed
      • changedOutput schema / $defs / ConfidenceSignal / description
        Previous value: -"Quote-trust headline — is this number calibrated to the shop, or a model\nestimate? The signal a procurement / supplier persona reads alongside the\nprediction band before trusting a should-cost."New value: +"Quote-trust headline — is this number calibrated to the shop, or a model\nestimate? The signal a procurement / supplier persona reads alongside the\nprediction band."
      • changedOutput schema / properties / confidence / description
        Previous value: -"Quote-trust signal — the headline the procurement / supplier persona reads with the band before trusting the should-cost."New value: +"Quote-trust signal — the headline the procurement / supplier persona reads together with the prediction band."
    • Changedget_cost_factors1 field changed
      • changedOutput schema / properties / rows / items / properties / edit_path / description
        Previous value: -"How this factor is SAVED for real: the MCP tool that writes it when that tool is listed (e.g. 'the `x` tool'), else the REST call (e.g. 'PUT /environments/{env_id}/tuning'), or 'the app only (not available over MCP)'. Empty when nothing writes it yet. Saving is a write and is not part of this tool."New value: +"Where this factor is saved for real: the tool that writes it, named when the client lists that tool, else the API route, or 'the app only (not available over MCP)'. Empty when nothing writes it yet. Saving is a write and is not part of this tool."
    • Changedquote_part2 fields changed
      • changedInput schema / properties / stock_format_id / description
        Previous value: -"Price this calculation on one stock format — the `id` of a format from `GET /stock-formats`. An id names the format, not only the version it came from: when the format has been changed since, the version current on the day the calculation is created is used. An id your organization cannot price with today (unknown, retired or hidden) is rejected with 422 `stock_format_unresolved`. When the part cannot be cut from that format — too small, not bought in the part's thickness or material, or one the machine cannot load — or is not cut from sheet at all (milled, turned or bought finished), the calculation is priced as if none had been chosen, and `analytics.pipeline_notes` says why (`stock_format_pin_unavailable`). Omit it to price on the format that uses the least material per part. On a re-run (`derived_from_calculation_id`), omitting it keeps the format of the calculation re-run; send `null` to price without one."New value: +"Price this calculation on one stock format — the `id` of a format from the `materials_list_stock_formats` tool (toolset `catalog`). An id names the format, not only the version it came from: when the format has been changed since, the version current on the day the calculation is created is used. An id your organization cannot price with today (unknown, retired or hidden) is rejected with 422 `stock_format_unresolved`. When the part cannot be cut from that format — too small, not bought in the part's thickness or material, or one the machine cannot load — or is not cut from sheet at all (milled, turned or bought finished), the calculation is priced as if none had been chosen, and `analytics.pipeline_notes` says why (`stock_format_pin_unavailable`). Omit it to price on the format that uses the least material per part. On a re-run (`derived_from_calculation_id`), omitting it keeps the format of the calculation re-run; send `null` to price without one."
      • changedInput schema / properties / stock_format_mm / description
        Previous value: -"Price this calculation on a sheet of this size — length and width in mm — instead of a stock format from `GET /stock-formats`: the part is laid out on that one sheet, cut to size by your supplier, and the purchased stock says `format_source` `custom`. It cannot be combined with `stock_format_id` or `nest_item_id`. When the part does not fit the sheet, or is not cut from sheet stock at all, the calculation is priced as if none had been stated and `analytics.pipeline_notes` says why. On a re-run (`derived_from_calculation_id`), omitting both it and `stock_format_id` keeps the size or format of the calculation re-run; send `null` to price without one."New value: +"Price this calculation on a sheet of this size — length and width in mm — instead of a stock format from the `materials_list_stock_formats` tool (toolset `catalog`): the part is laid out on that one sheet, cut to size by your supplier, and the purchased stock says `format_source` `custom`. It cannot be combined with `stock_format_id` or `nest_item_id`. When the part does not fit the sheet, or is not cut from sheet stock at all, the calculation is priced as if none had been stated and `analytics.pipeline_notes` says why. On a re-run (`derived_from_calculation_id`), omitting both it and `stock_format_id` keeps the size or format of the calculation re-run; send `null` to price without one."
  10. 243 tool updates
    • Addedapply_adjustment
    • Removedarcnm_apply_adjustment
    • Removedarcnm_check_quota
    • Removedarcnm_compare_calculations
    • Removedarcnm_compare_environments
    • Removedarcnm_cost_breakdown
    • Removedarcnm_cost_drivers
    • Removedarcnm_cost_factors
    • Removedarcnm_explain_cost
    • Removedarcnm_nest_run_cancel
    • Removedarcnm_nest_run_create
    • Removedarcnm_nest_run_export
    • Removedarcnm_nest_run_result
    • Removedarcnm_nest_run_start
    • Removedarcnm_nest_run_status
    • Removedarcnm_nest_savings
    • Removedarcnm_nesting_read
    • Removedarcnm_optimization_directions
    • Removedarcnm_optimize_lot_size
    • Removedarcnm_preview_cost
    • Removedarcnm_process_plan
    • Removedarcnm_rank_calculations
    • Removedarcnm_sheet_nest_export
    • Addedattach_upload
    • Removedcalculations_assign_assembly_drawing
    • Removedcalculations_batch_calculate
    • Removedcalculations_batch_comparison
    • Removedcalculations_batch_comparison_components
    • Removedcalculations_bulk_cancel_calculations
    • Removedcalculations_bulk_delete_calculations
    • Removedcalculations_bulk_retry_calculations
    • Removedcalculations_cancel_batch
    • Removedcalculations_cancel_calculation
    • Removedcalculations_compare_environment_runs
    • Removedcalculations_create_calculation
    • Removedcalculations_create_cost_scenario
    • Removedcalculations_delete_calculation
    • Removedcalculations_delete_cost_scenario
    • Removedcalculations_get_calculation
    • Removedcalculations_get_calculation_assembly_route
    • Removedcalculations_get_calculation_bom
    • Removedcalculations_get_calculation_capacity
    • Removedcalculations_get_calculation_optimization
    • Removedcalculations_get_cost_sheet
    • Removedcalculations_get_entitlement
    • Removedcalculations_list_calculations
    • Removedcalculations_list_cost_scenarios
    • Removedcalculations_patch_assembly_component
    • Removedcalculations_patch_calculation_material
    • Removedcalculations_preview_cost
    • Removedcalculations_quote
    • Removedcalculations_run_calculation
    • Removedcalculations_update_cost_scenario
    • Removedcalculations_upload_and_quote_json
    • Removedcalibration_auto_calibrate_environment
    • Removedcalibration_auto_calibrate_from_erp
    • Removedcalibration_calibrate_selection_policy
    • Removedcalibration_deactivate_environment
    • Removedcalibration_environment_report
    • Removedcalibration_environment_run_history
    • Removedcalibration_environment_status
    • Removedcalibration_erp_preflight
    • Removedcalibration_finalize_environment
    • Removedcalibration_fit_learning_curve
    • Removedcalibration_import_calibrate
    • Removedcalibration_import_create
    • Removedcalibration_import_status
    • Removedcalibration_ingest_environment_outcomes
    • Removedcalibration_next_best_evidence
    • Removedcalibration_revert_environment_run
    • Removedcalibration_teach_environment
    • Addedcancel_calculation
    • Addedcancel_nest_run
    • Addedcheck_quota
    • Addedcompare_calculations
    • Addedcompare_environments
    • Addedconfirm_upload
    • Addedcreate_nest_run
    • Addedcreate_part
    • Removeddatasets_attach_dataset
    • Removeddatasets_detach_dataset
    • Removeddatasets_list_datasets
    • Removeddatasets_update_dataset
    • Removedenvironments_attach_env_subcontractor
    • Removedenvironments_attach_env_tool
    • Removedenvironments_attach_machine
    • Removedenvironments_clone_environment
    • Removedenvironments_clone_preset
    • Removedenvironments_create_environment
    • Removedenvironments_delete_environment
    • Removedenvironments_delete_rate
    • Removedenvironments_detach_env_subcontractor
    • Removedenvironments_detach_env_tool
    • Removedenvironments_detach_machine
    • Removedenvironments_economics_update
    • Removedenvironments_get_calculation_tuning
    • Removedenvironments_get_environment
    • Removedenvironments_get_environment_audit
    • Removedenvironments_get_environment_factors
    • Removedenvironments_get_individualization
    • Removedenvironments_get_shop_practice
    • Removedenvironments_list_env_machines
    • Removedenvironments_list_env_subcontractors
    • Removedenvironments_list_env_tools
    • Removedenvironments_list_environments
    • Removedenvironments_list_presets
    • Removedenvironments_list_rates
    • Removedenvironments_list_surcharge_presets
    • Removedenvironments_material_price_clear
    • Removedenvironments_material_price_set
    • Removedenvironments_restore_env_machines
    • Removedenvironments_restore_env_rates
    • Removedenvironments_restore_env_subcontractors
    • Removedenvironments_restore_env_tools
    • Removedenvironments_scrap_price_clear
    • Removedenvironments_scrap_price_set
    • Removedenvironments_scrap_prices
    • Removedenvironments_subcontract_price_set
    • Removedenvironments_update_calculation_tuning
    • Removedenvironments_update_env_subcontractor_membership
    • Removedenvironments_update_env_tool_membership
    • Removedenvironments_update_environment_identity
    • Removedenvironments_update_membership
    • Removedenvironments_update_shop_practice
    • Removedenvironments_upsert_rate
    • Addedexplain_cost
    • Addedexport_nest_layout
    • Removedfolders_create_folder
    • Removedfolders_delete_folder
    • Removedfolders_folder_summary
    • Removedfolders_get_folder
    • Removedfolders_list_folders
    • Removedfolders_move_parts
    • Removedfolders_update_folder
    • Removedfolders_workspace_summary
    • Removedgeometry_part_revision_drawing_url
    • Removedgeometry_part_revision_faces_url
    • Addedget_calculation
    • Addedget_cost_breakdown
    • Addedget_cost_drivers
    • Addedget_cost_factors
    • Addedget_environment
    • Addedget_nest_run
    • Addedget_nesting_summary
    • Addedget_process_plan
    • Addedget_upload_link
    • Removedimport_preview_machine_import
    • Removedimport_preview_tool_import
    • Addedlist_calculations
    • Addedlist_environments
    • Addedlist_part_revisions
    • Addedlist_parts
    • Removedmachine_library_create_library_entry
    • Removedmachine_library_delete_library_entry
    • Removedmachine_library_get_library_entry
    • Removedmachine_library_library_usage
    • Removedmachine_library_list_library
    • Removedmachine_library_rate_calculator
    • Removedmachine_library_update_library_entry
    • Removedmachines_get_machine
    • Removedmachines_get_machine_usage
    • Removedmachines_update_machine
    • Removedmaterials_create_grade_designation
    • Removedmaterials_create_org_grade
    • Removedmaterials_create_override
    • Removedmaterials_create_stock_format
    • Removedmaterials_delete_designation
    • Removedmaterials_delete_org_grade
    • Removedmaterials_delete_override
    • Removedmaterials_get_grade
    • Removedmaterials_get_grade_by_urn
    • Removedmaterials_get_grade_master
    • Removedmaterials_get_stock_format
    • Removedmaterials_ignore_unmapped_designation
    • Removedmaterials_list_grade_designations
    • Removedmaterials_list_grades
    • Removedmaterials_list_material_attribute_vocabulary
    • Removedmaterials_list_overrides
    • Removedmaterials_list_standards
    • Removedmaterials_list_stock_formats
    • Removedmaterials_list_unmapped_designations
    • Removedmaterials_list_workpiece_groups
    • Removedmaterials_lookup
    • Removedmaterials_lookup_batch
    • Removedmaterials_map_unmapped_designation
    • Removedmaterials_pricing_coverage
    • Removedmaterials_retire_stock_format
    • Removedmaterials_suggest
    • Removedmaterials_suppress_stock_format
    • Removedmaterials_unsuppress_stock_format
    • Removedmaterials_update_org_grade
    • Removedmaterials_update_override
    • Removedmaterials_update_stock_format
    • Removedmaterials_upsert_grade_override
    • Addedoptimize_lot_size
    • Removedparts_create_part
    • Removedparts_create_revision
    • Removedparts_delete_part
    • Removedparts_delete_revision
    • Removedparts_get_part
    • Removedparts_get_revision
    • Removedparts_list_parts
    • Removedparts_list_revisions
    • Removedparts_part_faces_url
    • Removedparts_part_preview_url
    • Removedparts_part_preview_urls_batch
    • Removedparts_resolve_part_numbers
    • Removedparts_update_part
    • Removedparts_update_revision
    • Addedpresign_upload
    • Addedpreview_cost
    • Addedquote_part
    • Addedstart_nest_run
    • Removedsubcontractors_create_subcontractor
    • Removedsubcontractors_delete_subcontractor
    • Removedsubcontractors_list_subcontractors
    • Removedsubcontractors_suppress_subcontractor_preset
    • Removedsubcontractors_unsuppress_subcontractor_preset
    • Removedsubcontractors_update_subcontractor
    • Addedsuggest_cost_savings
    • Removedtools_adopt_catalogue_item
    • Removedtools_copy_tool
    • Removedtools_create_tool
    • Removedtools_delete_tool
    • Removedtools_get_tool
    • Removedtools_list_catalogue_items
    • Removedtools_list_tools
    • Removedtools_reset_tool_to_article
    • Removedtools_suppress_catalogue_item
    • Removedtools_tool_catalogue
    • Removedtools_unsuppress_catalogue_item
    • Removedtools_update_tool
    • Removeduploads_bulk_cancel_uploads
    • Removeduploads_bulk_delete_uploads
    • Removeduploads_bulk_retry_uploads
    • Removeduploads_cancel_upload
    • Removeduploads_confirm
    • Removeduploads_delete_upload
    • Removeduploads_download_url
    • Removeduploads_list_uploads
    • Removeduploads_presign
    • Removeduploads_retry_upload
    • Removeduploads_update_upload
  11. 7 tool updates
    • Changedarcnm_compare_calculations2 fields changed
      • changedOutput schema / properties / a / properties / needs_review / description
        Previous value: -"True when this calculation is flagged for human review — its number is not a quote yet. Read the calculation for the reasons before comparing or sending it."New value: +"True when this calculation is flagged for human review — its number is not a quote yet. The reasons are on the calculation."
      • changedOutput schema / properties / b / properties / needs_review / description
        Previous value: -"True when this calculation is flagged for human review — its number is not a quote yet. Read the calculation for the reasons before comparing or sending it."New value: +"True when this calculation is flagged for human review — its number is not a quote yet. The reasons are on the calculation."
    • Changedarcnm_compare_environments2 fields changed
      • changedOutput schema / properties / complete / description
        Previous value: -"False while any cell is still computing — don't call a winner yet."New value: +"False while any cell is still computing; the ranking is provisional until it is true."
      • changedOutput schema / properties / mixed_calibration / description
        Previous value: -"True when the compared environments were not all priced under the same calibration — at least one is aligned to the tenant's reported costs and another is the unaligned estimate. The deltas are real, but part of the gap may be alignment rather than the environments. Say so before recommending a winner."New value: +"True when the compared environments were not all priced under the same calibration — at least one is aligned to the tenant's reported costs and another is the unaligned estimate. The deltas are real, but part of the gap may be alignment rather than the environments."
    • Changedarcnm_cost_drivers1 field changed
      • changedOutput schema / properties / attributed_cost_share_pct / description
        Previous value: -"Share of unit cost (0–100) the named drivers actually explain — so you don't over-trust the top-N as the whole story. The rest is shared/overhead cost not attributable to one feature."New value: +"Share of unit cost (0–100) the named drivers actually explain. The rest is shared/overhead cost not attributable to one feature."
    • Changedarcnm_explain_cost1 field changed
      • changedOutput schema / properties / assembly_completeness / description
        Previous value: -"ASSEMBLIES ONLY. Whether `unit_cost` is a price or a LOWER BOUND. Carries {n_unique, n_priced, n_pending, n_unpriced, total_is_lower_bound, priced_complete, unpriced[]}, where each unpriced entry has a closed-enum `reason_code`, a `by_design` flag and, where one exists, a `remedy`. **When `total_is_lower_bound` is true the cost is incomplete: qualify it, never quote it as the price.** A `by_design` reason (a part budget, a plan quota, a cancellation) is the platform working as intended, not a defect — report it as a limit the user can lift, not as a failure."New value: +"ASSEMBLIES ONLY. Whether `unit_cost` is a price or a LOWER BOUND. Carries {n_unique, n_priced, n_pending, n_unpriced, total_is_lower_bound, priced_complete, unpriced[]}, where each unpriced entry has a closed-enum `reason_code`, a `by_design` flag and, where one exists, a `remedy`. When `total_is_lower_bound` is true, `unit_cost` is a lower bound, not a complete price. A `by_design` reason (a part budget, a plan quota, a cancellation) is a configured limit, not a processing error."
    • Changedarcnm_rank_calculations1 field changed
      • changedOutput schema / properties / ranked / items / properties / needs_review / description
        Previous value: -"True when this calculation is flagged for human review — its number is not a quote yet. Read the calculation for the reasons before comparing or sending it."New value: +"True when this calculation is flagged for human review — its number is not a quote yet. The reasons are on the calculation."
    • Changedcalibration_auto_calibrate_environment1 field changed
      • changedInput schema / properties / actuals / description
        Previous value: -"Up to 20,000 (part_revision_id, actual_unit_cost) rows. Designed for ERP exports: an AI agent or a CSV uploader can stream a tenant's history in one call."New value: +"Up to 20,000 (part_revision_id, actual_unit_cost) rows. Designed for ERP exports: a tenant's history can be sent in one call."
    • Changedcalibration_auto_calibrate_from_erp1 field changed
      • changedInput schema / properties / work_orders / description
        Previous value: -"Up to 20 000 raw ERP work-order lines. Designed for the AI-agent ERP-import use case: pull tenant's last 12 months of WIP_DISCRETE_JOBS rows, POST them once, and the service resolves part numbers, decomposes setup vs variable cost from the lot-size diversity, and returns a calibrated env."New value: +"Up to 20 000 raw ERP work-order lines, e.g. an export of the last 12 months of WIP_DISCRETE_JOBS rows. From one submission the service resolves part numbers, decomposes setup vs variable cost from the lot-size diversity, and returns a calibrated env."
  12. 212 tool updates
    • First observedarcnm_apply_adjustment
    • First observedarcnm_check_quota
    • First observedarcnm_compare_calculations
    • First observedarcnm_compare_environments
    • First observedarcnm_cost_breakdown
    • First observedarcnm_cost_drivers
    • First observedarcnm_cost_factors
    • First observedarcnm_explain_cost
    • First observedarcnm_nest_run_cancel
    • First observedarcnm_nest_run_create
    • First observedarcnm_nest_run_export
    • First observedarcnm_nest_run_result
    • First observedarcnm_nest_run_start
    • First observedarcnm_nest_run_status
    • First observedarcnm_nest_savings
    • First observedarcnm_nesting_read
    • First observedarcnm_optimization_directions
    • First observedarcnm_optimize_lot_size
    • First observedarcnm_preview_cost
    • First observedarcnm_process_plan
    • First observedarcnm_rank_calculations
    • First observedarcnm_sheet_nest_export
    • First observedcalculations_assign_assembly_drawing
    • First observedcalculations_batch_calculate
    • First observedcalculations_batch_comparison
    • First observedcalculations_batch_comparison_components
    • First observedcalculations_bulk_cancel_calculations
    • First observedcalculations_bulk_delete_calculations
    • First observedcalculations_bulk_retry_calculations
    • First observedcalculations_cancel_batch
    • First observedcalculations_cancel_calculation
    • First observedcalculations_compare_environment_runs
    • First observedcalculations_create_calculation
    • First observedcalculations_create_cost_scenario
    • First observedcalculations_delete_calculation
    • First observedcalculations_delete_cost_scenario
    • First observedcalculations_get_calculation
    • First observedcalculations_get_calculation_assembly_route
    • First observedcalculations_get_calculation_bom
    • First observedcalculations_get_calculation_capacity
    • First observedcalculations_get_calculation_optimization
    • First observedcalculations_get_cost_sheet
    • First observedcalculations_get_entitlement
    • First observedcalculations_list_calculations
    • First observedcalculations_list_cost_scenarios
    • First observedcalculations_patch_assembly_component
    • First observedcalculations_patch_calculation_material
    • First observedcalculations_preview_cost
    • First observedcalculations_quote
    • First observedcalculations_run_calculation
    • First observedcalculations_update_cost_scenario
    • First observedcalculations_upload_and_quote_json
    • First observedcalibration_auto_calibrate_environment
    • First observedcalibration_auto_calibrate_from_erp
    • First observedcalibration_calibrate_selection_policy
    • First observedcalibration_deactivate_environment
    • First observedcalibration_environment_report
    • First observedcalibration_environment_run_history
    • First observedcalibration_environment_status
    • First observedcalibration_erp_preflight
    • First observedcalibration_finalize_environment
    • First observedcalibration_fit_learning_curve
    • First observedcalibration_import_calibrate
    • First observedcalibration_import_create
    • First observedcalibration_import_status
    • First observedcalibration_ingest_environment_outcomes
    • First observedcalibration_next_best_evidence
    • First observedcalibration_revert_environment_run
    • First observedcalibration_teach_environment
    • First observeddatasets_attach_dataset
    • First observeddatasets_detach_dataset
    • First observeddatasets_list_datasets
    • First observeddatasets_update_dataset
    • First observedenvironments_attach_env_subcontractor
    • First observedenvironments_attach_env_tool
    • First observedenvironments_attach_machine
    • First observedenvironments_clone_environment
    • First observedenvironments_clone_preset
    • First observedenvironments_create_environment
    • First observedenvironments_delete_environment
    • First observedenvironments_delete_rate
    • First observedenvironments_detach_env_subcontractor
    • First observedenvironments_detach_env_tool
    • First observedenvironments_detach_machine
    • First observedenvironments_economics_update
    • First observedenvironments_get_calculation_tuning
    • First observedenvironments_get_environment
    • First observedenvironments_get_environment_audit
    • First observedenvironments_get_environment_factors
    • First observedenvironments_get_individualization
    • First observedenvironments_get_shop_practice
    • First observedenvironments_list_env_machines
    • First observedenvironments_list_env_subcontractors
    • First observedenvironments_list_env_tools
    • First observedenvironments_list_environments
    • First observedenvironments_list_presets
    • First observedenvironments_list_rates
    • First observedenvironments_list_surcharge_presets
    • First observedenvironments_material_price_clear
    • First observedenvironments_material_price_set
    • First observedenvironments_restore_env_machines
    • First observedenvironments_restore_env_rates
    • First observedenvironments_restore_env_subcontractors
    • First observedenvironments_restore_env_tools
    • First observedenvironments_scrap_price_clear
    • First observedenvironments_scrap_price_set
    • First observedenvironments_scrap_prices
    • First observedenvironments_subcontract_price_set
    • First observedenvironments_update_calculation_tuning
    • First observedenvironments_update_env_subcontractor_membership
    • First observedenvironments_update_env_tool_membership
    • First observedenvironments_update_environment_identity
    • First observedenvironments_update_membership
    • First observedenvironments_update_shop_practice
    • First observedenvironments_upsert_rate
    • First observedfolders_create_folder
    • First observedfolders_delete_folder
    • First observedfolders_folder_summary
    • First observedfolders_get_folder
    • First observedfolders_list_folders
    • First observedfolders_move_parts
    • First observedfolders_update_folder
    • First observedfolders_workspace_summary
    • First observedgeometry_part_revision_drawing_url
    • First observedgeometry_part_revision_faces_url
    • First observedimport_preview_machine_import
    • First observedimport_preview_tool_import
    • First observedmachine_library_create_library_entry
    • First observedmachine_library_delete_library_entry
    • First observedmachine_library_get_library_entry
    • First observedmachine_library_library_usage
    • First observedmachine_library_list_library
    • First observedmachine_library_rate_calculator
    • First observedmachine_library_update_library_entry
    • First observedmachines_get_machine
    • First observedmachines_get_machine_usage
    • First observedmachines_update_machine
    • First observedmaterials_create_grade_designation
    • First observedmaterials_create_org_grade
    • First observedmaterials_create_override
    • First observedmaterials_create_stock_format
    • First observedmaterials_delete_designation
    • First observedmaterials_delete_org_grade
    • First observedmaterials_delete_override
    • First observedmaterials_get_grade
    • First observedmaterials_get_grade_by_urn
    • First observedmaterials_get_grade_master
    • First observedmaterials_get_stock_format
    • First observedmaterials_ignore_unmapped_designation
    • First observedmaterials_list_grade_designations
    • First observedmaterials_list_grades
    • First observedmaterials_list_material_attribute_vocabulary
    • First observedmaterials_list_overrides
    • First observedmaterials_list_standards
    • First observedmaterials_list_stock_formats
    • First observedmaterials_list_unmapped_designations
    • First observedmaterials_list_workpiece_groups
    • First observedmaterials_lookup
    • First observedmaterials_lookup_batch
    • First observedmaterials_map_unmapped_designation
    • First observedmaterials_pricing_coverage
    • First observedmaterials_retire_stock_format
    • First observedmaterials_suggest
    • First observedmaterials_suppress_stock_format
    • First observedmaterials_unsuppress_stock_format
    • First observedmaterials_update_org_grade
    • First observedmaterials_update_override
    • First observedmaterials_update_stock_format
    • First observedmaterials_upsert_grade_override
    • First observedparts_create_part
    • First observedparts_create_revision
    • First observedparts_delete_part
    • First observedparts_delete_revision
    • First observedparts_get_part
    • First observedparts_get_revision
    • First observedparts_list_parts
    • First observedparts_list_revisions
    • First observedparts_part_faces_url
    • First observedparts_part_preview_url
    • First observedparts_part_preview_urls_batch
    • First observedparts_resolve_part_numbers
    • First observedparts_update_part
    • First observedparts_update_revision
    • First observedsubcontractors_create_subcontractor
    • First observedsubcontractors_delete_subcontractor
    • First observedsubcontractors_list_subcontractors
    • First observedsubcontractors_suppress_subcontractor_preset
    • First observedsubcontractors_unsuppress_subcontractor_preset
    • First observedsubcontractors_update_subcontractor
    • First observedtools_adopt_catalogue_item
    • First observedtools_copy_tool
    • First observedtools_create_tool
    • First observedtools_delete_tool
    • First observedtools_get_tool
    • First observedtools_list_catalogue_items
    • First observedtools_list_tools
    • First observedtools_reset_tool_to_article
    • First observedtools_suppress_catalogue_item
    • First observedtools_tool_catalogue
    • First observedtools_unsuppress_catalogue_item
    • First observedtools_update_tool
    • First observeduploads_bulk_cancel_uploads
    • First observeduploads_bulk_delete_uploads
    • First observeduploads_bulk_retry_uploads
    • First observeduploads_cancel_upload
    • First observeduploads_confirm
    • First observeduploads_delete_upload
    • First observeduploads_download_url
    • First observeduploads_list_uploads
    • First observeduploads_presign
    • First observeduploads_retry_upload
    • First observeduploads_update_upload

Publisher details

Operator
rattle mng GmbH (ARCNM), Überlingen, Germany · Publisher source
Vendor relationship
First-party · Publisher source
Trust center
Not available
Restrictions
Requires an ARCNM account; the Free plan works (10 calculations a month, no card). Starting a calculation uses the plan's calculation quota. The nesting tools need the Nesting add-on. · Publisher source

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Intelligently generates cost estimates and lead times for manufacturing RFPs by parsing requests, matching against historical quotes, and calculating activity-based costs with confidence scoring and human approval workflows.
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables 2D irregular polygon nesting (bin-packing) with tools to design, preview, get reports, and export DXF files for laser cutting or CNC routing.
    MIT
  • A
    license
    A
    quality
    A
    maintenance
    Generates quality control plans and inspection reports from technical-drawing PDFs: tolerances, fits, threads, GD&T and surface finishes are extracted automatically by Imnoo's drawing analysis, numbered as balloons with acceptance limits and measuring instruments, and exported as a ballooned drawing PDF, an inspection package and an Excel measurement report.
    5
    1
    MIT
Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.