ARCNM
Server Details
Manufacturing cost of CNC and sheet-metal parts from STEP or DXF: process plan, times, 10 lot sizes.
- 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
Scored across 18 tools
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.
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.
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.
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 toolsattach_drawingAttach DrawingADestructiveInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| run | No | With calculation_id: price the part again with the drawing (default true; billable only if it succeeds). False attaches only. | |
| apply | No | False (the default): plan only, read the target and say what would change; nothing is attached. True: attach. | |
| precheck_id | No | Before the start: the precheck, as precheck_part returns it. With component_key; not with calculation_id. | |
| component_key | No | With 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_id | No | After 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_id | No | A 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_b64 | No | The drawing itself, a PDF, PNG or JPEG as base64 (or a data: URI). With drawing_filename; not with data_source_id. | |
| drawing_filename | No | The file name of drawing_file_b64 with its extension, e.g. ZX-0001_A.pdf. | |
| drawing_content_type | No | MIME type of drawing_file_b64, when known. |
Output Schema
| Name | Required | Description |
|---|---|---|
| target | Yes | `precheck`: placed before the start. `calculation`: attached to a calculated part. |
| applied | Yes | False: a plan only, nothing was attached. True: the drawing was attached. |
| changed | No | False when this drawing already was the part's drawing: nothing was attached and nothing runs. |
| drawings | No | Every drawing the precheck holds, and where each goes. |
| revision | No | The precheck's revision, to start it with. |
| next_step | Yes | What happens next. |
| precheck_id | No | |
| prices_again | No | For 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_key | No | The part the drawing goes to on the precheck, or `assembly`. |
| calculation_id | No | |
| data_source_id | No | The drawing, as stored. |
| precheck_status | No | The precheck's status: `received` while a new drawing's title block is read, `ready` once answered. |
| new_calculation_id | No | The calculation that prices the part with this drawing, when run is true and the drawing changed. |
| rerun_calculation_id | No | For a component of an assembly: its own calculation, priced again in place. |
| new_calculation_status | No | Its status: `queued` is a run, `succeeded` an identical earlier run answering it unbilled, `blocked` a run held for quota. |
TDQS
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.
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.
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.
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.
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.
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 CalculationADestructiveInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| calculation_id | Yes | Id of a calculation, as upload_and_quote, quote_part or list_calculations return it. |
TDQS
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.
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.
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.
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.
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.
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 QuotaARead-onlyIdempotentInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| plan | No | |
| used | No | |
| bonus | No | Thank-you calculations granted on top of the plan this window. |
| window | No | 'month' or 'year'. |
| guidance | Yes | |
| included | No | Calculations included per window. |
| rollover | No | Unused calculations carried in from last window. |
| effective | No | Ceiling this window (included + rollover + bonus). |
| remaining | No | Calculations still available this window. |
| over_quota | No | |
| hard_capped | No | True: over-quota runs park as blocked. False: they bill as overage. |
| window_start | No | ISO 8601 start of the current quota window. |
| overage_cents | No | Price of one calculation beyond the included volume, in cents. |
| payment_blocked | No | True when billing is suspended and nothing will run. |
| wallet_overdrawn | No | 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. |
| overage_cap_cents | No | Monthly overage spend cap in cents, or null when uncapped. Bounds what over-quota runs may cost. |
| spend_cap_blocked | No | True when the overage cap is reached and set to pause — further over-quota runs park as blocked. |
| has_payment_method | No | Whether a payment method is on file; a 'wallet' plan needs one for calculations beyond the included volume. |
| overage_settlement | No | How overage is paid: 'wallet' (a prepaid balance that is the ceiling) or 'invoice' (contracted, billed in arrears). |
| overage_spend_cents | No | Overage already billed this calendar month, in cents. |
| wallet_balance_cents | No | Prepaid balance in cents ('wallet' settlement only). |
| wallet_overdraft_cents | No | How far the prepaid balance is below zero, in cents. |
| wallet_funded_calculations | No | How many more overage calculations the current balance covers; beyond it, calculations park as 'blocked'. |
| wallet_overdraft_floor_cents | No | Hard floor on the prepaid balance, in cents; the balance can never go below its negation. |
| overage_budget_remaining_cents | No | Overage spend still inside the cap, in cents; null when uncapped. |
TDQS
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.
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.
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.
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.
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.
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 CalculationsARead-onlyIdempotentInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| calculation_ids | Yes | 2 to 20 distinct calculation ids: 2 for the delta, 3 to 20 for the ranking. |
Output Schema
| Name | Required | Description |
|---|---|---|
| pair | No | Set for exactly two calculation ids. |
| ranking | No | Set for three to twenty calculation ids. |
| not_found | No | 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. |
TDQS
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.
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.
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.
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.
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.
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 CostARead-onlyIdempotentInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| detail | No | 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. | concise |
| calculation_id | Yes | Id of a calculation, as upload_and_quote, quote_part or list_calculations return it. |
Output Schema
| Name | Required | Description |
|---|---|---|
| name | No | |
| error | No | Why 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. |
| route | No | Every 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. |
| times | No | Time 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. |
| status | Yes | |
| machine | No | Machine the part was priced on. |
| coverage | No | 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. |
| currency | No | The 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. |
| guidance | Yes | What to do next to act on or reduce the cost. |
| lot_size | No | |
| material | No | Material, when known. |
| unpriced | No | 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. |
| clampings | No | 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. |
| cost_band | No | [low, high] prediction band for the unit cost. |
| unit_cost | No | 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. |
| confidence | No | Quote-trust signal: calibrated to the shop, or a model estimate — read together with the prediction band. |
| setup_cost | No | One-time setup cost of the lot, on the same basis as unit_cost (below the cost-sheet rungs). |
| total_cost | No | unit_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_price | No | The 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_drivers | No | 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'. |
| unit_time_s | No | Total 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_s | No | Machining cycle time per unit, in seconds. |
| needs_review | No | |
| setup_time_s | No | One-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_note | No | Plain-language material assumption (which grade was priced, or that a default was used). |
| calculation_id | Yes | |
| cost_breakdown | No | Cost 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_s | No | Machine 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_reasons | No | |
| cost_categories | No | 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. |
| drawing_pairing | No | 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. |
| material_priced | No | 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. |
| material_source | No | 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. |
| material_resolved | No | False when no material grade resolved and the part was priced on the environment's default — set material_ref and re-run to correct. |
| selection_failure | No | The 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_completeness | No | '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_completeness | No | 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. |
| costing_environment_id | No | The costing environment this was priced in: the machines, rates and overheads behind these numbers (list_environments names it). |
| inputs_changed_since_run | No | 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. |
| environment_changed_since_run | No | 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. |
TDQS
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.
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.
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.
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.
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.
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 CalculationARead-onlyIdempotentInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| calculation_id | Yes | Id of a calculation, as upload_and_quote, quote_part or list_calculations return it. | |
| include_analytics | No | 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. |
TDQS
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.
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.
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.
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.
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.
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 BreakdownARead-onlyIdempotentInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| persona | No | 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). | full |
| quantity | No | Lot 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_depth | No | 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 {}). | |
| calculation_id | Yes | Id of a calculation, as upload_and_quote, quote_part or list_calculations return it. |
Output Schema
| Name | Required | Description |
|---|---|---|
| basis | No | Where 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. |
| error | No | Why this calculation produced no price, in one sentence, when its status is terminal (failed / cancelled). |
| status | Yes | |
| persona | Yes | The persona view this result is sliced for. |
| currency | No | The calculation's currency; every money figure here is in it. |
| features | No | |
| guidance | Yes | |
| machines | No | |
| quantity | No | The 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_band | No | [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_cost | No | 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. |
| confidence | No | Quote-trust signal — the headline the procurement / supplier persona reads together with the prediction band. |
| cost_lines | No | The 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. |
| operations | No | |
| setup_cost | No | Setup cost for the whole lot at `quantity`, in `currency` — the sheet's setup line times the lot. |
| total_cost | No | unit_cost for the whole lot at `quantity`, on the same basis as unit_cost. |
| offer_price | No | The 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_s | No | Time 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_review | No | True 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_s | No | Setup time for the whole lot at `quantity`, in seconds. |
| material_note | No | |
| calculation_id | Yes | |
| machine_time_s | No | Machine time per unit at `quantity`, in seconds: the billable run plus the finishing pass under the allowance. |
| material_stock | No | 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. |
| cost_categories | No | Per-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_factor | No | What 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_n | No | The machine the figures at `quantity` were priced on, where it differs from or restates the calculation's own route. |
| material_resolved | No | |
| selection_failure | No | The same refusal as data when no machine in the costing environment could make the part. |
| cost_sheet_rebuilt | No | True 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_id | No | The costing environment this was priced in: the machines, rates and overheads the factors named in each line's ``factors`` belong to. |
| inputs_changed_since_run | No | 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. |
| environment_changed_since_run | No | 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. |
TDQS
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.
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.
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.
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.
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.
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 PrecheckARead-onlyIdempotentInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| precheck_id | Yes | The precheck, as precheck_part returned it. |
TDQS
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.
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.
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.
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.
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.
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 PlanARead-onlyIdempotentInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| calculation_id | Yes | Id of a calculation, as upload_and_quote, quote_part or list_calculations return it. |
Output Schema
| Name | Required | Description |
|---|---|---|
| error | No | Why this calculation produced no plan, in one sentence, when its status is terminal (failed / cancelled). |
| steps | No | |
| status | Yes | |
| currency | No | The calculation's currency — the basis of every subcontract_per_part figure on the steps. |
| guidance | Yes | |
| machines | No | Machine(s) / work center(s), in route order. |
| unpriced | No | 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. |
| clampings | No | 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. |
| unit_time_s | No | Total time per unit, seconds. |
| cycle_time_s | No | Total machining cycle time per unit, seconds. |
| setup_time_s | No | One-time setup time for the whole lot, in seconds (NOT per unit; divide by the lot size for the per-unit share). |
| calculation_id | Yes | |
| machine_time_s | No | Machine time per unit in seconds: the billed run plus the finishing pass, under the allowance. Absent on older calculations. |
| operation_count | No | Number of process steps in the plan. |
| selection_failure | No | The same refusal as data when no machine in the costing environment could make the part. |
| price_completeness | No | '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
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.
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.
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.
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.
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.
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.
get_upload_linkGet Upload LinkAInspect
Get a link to the ARCNM upload page that works without signing in, for the person to open in a browser. Use it when the CAD file is on the person's computer and you cannot send its content, as in a chat app. They drop one STEP file per part, a PDF drawing optional; ARCNM files and prices each part in the folder and costing environment named here. Issuing is free; each different part uploaded is billable, one calculation if it succeeds (an assembly one per different part, counted once the file is read). The link works for 30 minutes and max_uploads parts; whoever has it can upload, so it is for that person only. Returns the url, upload_session_id, expiry and the calculations left. Afterwards list_calculations with upload_session_id finds exactly the calculations they started. If you can send the file content, use upload_and_quote instead.
| Name | Required | Description | Default |
|---|---|---|---|
| folder_id | No | Folder to file the uploaded parts into (optional). | |
| max_uploads | No | 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. | |
| environment_id | No | Costing environment to price the uploaded parts in (optional; the organization's default when omitted). |
Output Schema
| Name | Required | Description |
|---|---|---|
| url | Yes | 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. |
| folder_id | No | The folder the parts are filed into; null for the root. |
| issued_at | Yes | When this link was issued (RFC 3339, UTC). |
| next_step | Yes | How to find the new calculations once the person says the upload is done. |
| expires_at | Yes | When the link stops working (RFC 3339, UTC). |
| max_uploads | Yes | How many parts the person may upload through the link. |
| environment_id | No | The costing environment the parts are priced in. |
| upload_session_id | Yes | 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. |
| calculations_remaining | No | 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. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare it is not read-only and not idempotent; the description carries far more: the link is unauthenticated so 'whoever has it can upload', it expires in 30 minutes and caps at max_uploads parts, issuing is free but each distinct uploaded part is billable (one calculation on success, assemblies counted per part), and it names the returned fields and the follow-up query (list_calculations with upload_session_id). That is substantive behavioral context an agent cannot get from 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
The purpose and the person-facing constraint are front-loaded, the alternative tool is named at the end, and every sentence carries information (expiry, cap, billing model, returns). It is dense and somewhat long for a three-parameter tool, but there is no filler or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool that hands an unauthenticated upload session to a human, the description covers the essential unknowns: lifetime, upload cap, sharing risk, billing consequences, and how to retrieve the resulting calculations. An output schema exists, and the description only summarizes its fields rather than duplicating them.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3, but the description adds real meaning beyond the schema: the folder and environment 'named here' are where ARCNM files and prices the parts, and max_uploads is framed as 'one STEP file per part, a PDF drawing optional' rather than just a count. It stops short of explaining what happens when folder_id/environment_id are omitted versus defaulted.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a concrete verb and resource — 'Get a link to the ARCNM upload page that works without signing in' — and immediately scopes who uses it (a person opening it in a browser). It also explicitly distinguishes itself from the sibling upload_and_quote, so an agent can choose between them without reading either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives an explicit selection condition ('when the CAD file is on the person's computer and you cannot send its content, as in a chat app') and an explicit counter-case with the named alternative ('If you can send the file content, use upload_and_quote instead'). 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.
list_calculationsList CalculationsARead-onlyIdempotentInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| ids | No | Comma-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. | |
| sort | No | 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. | created_at |
| limit | No | Maximum rows to return in one page. | |
| order | No | Sort 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 |
| cursor | No | Opaque 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_id | No | Only the calculations of this part, by its id (part_id on any calculation). | |
| batch_id | No | Narrow 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_after | No | Only rows created at or after this instant (RFC 3339, e.g. `2026-07-20T09:00:00Z`). Inclusive. | |
| include_total | No | Also 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_filter | No | Filter by lifecycle status (e.g. queued, running, succeeded, failed, cancelled). Repeatable; several values are OR-ed. | |
| created_before | No | Only rows created strictly before this instant (RFC 3339). Exclusive, so an `after`/`before` pair tiles a range without overlap. | |
| include_facets | No | Also return `facets`: status and material values with counts, each computed over everything the OTHER active filters allow. | |
| material_grade_id | No | Only 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_id | No | 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. | |
| include_components | No | With `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_id | No | Only the component calculations of this assembly. By default the list contains top-level calculations only — assembly components are reachable through their parent. |
TDQS
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.
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.
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.
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.
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.
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 EnvironmentsARead-onlyIdempotentInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum rows to return in one page. | |
| order | No | Sort 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 |
| cursor | No | Opaque 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. | |
| offset | No | Rows to skip. Superseded by `cursor`, which is stable under concurrent writes; kept for existing integrations. Bounded — past the cap, page with `cursor`. | |
| created_after | No | Only rows created at or after this instant (RFC 3339, e.g. `2026-07-20T09:00:00Z`). Inclusive. | |
| created_before | No | Only rows created strictly before this instant (RFC 3339). Exclusive, so an `after`/`before` pair tiles a range without overlap. |
Output Schema
| Name | Required | Description |
|---|---|---|
| data | Yes | This page's rows, in the order and shape the REST list returns them. |
| has_more | Yes | False on the last page. Stop on this, never on a short page. |
| next_cursor | Yes | Pass as `cursor` to read the next page. Null on the last page. |
TDQS
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.
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.
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.
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.
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.
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 SizeARead-onlyIdempotentInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| calculation_id | Yes | Id of a calculation, as upload_and_quote, quote_part or list_calculations return it. |
Output Schema
| Name | Required | Description |
|---|---|---|
| curve | No | Compact 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). |
| status | Yes | |
| accuracy | No | How 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. |
| currency | No | Currency every money figure on this result is stated in (the calculation's), the optimum and the curve alike. |
| guidance | Yes | |
| scenario | No | The scenario recommended_lot_size states — buyer_stock: the buyer orders in lots and holds the stock. Absent on older calculations. |
| scenarios | No | Every 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_volume | No | Annual demand the optimum weighs holding against. |
| calculation_id | Yes | |
| andler_lot_size | No | Classic Andler/EOQ closed-form cross-check quantity. |
| recommendations | No | At most two solid optimization directions; empty when nothing material or the calculation predates the optimum. |
| valuation_basis | No | How 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_size | No | |
| current_unit_cost | No | Production cost per piece at the ordered lot, in currency. |
| exact_at_quantity | No | The 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_saving | No | Net saving per year of moving to the recommended lot, production plus inventory holding, in currency. |
| single_lot_demand | No | True 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_size | No | Total-cost optimal lot (≤ one year of demand). |
| recommended_unit_cost | No | Production cost per piece at the recommended lot, in currency. |
| ordering_cost_per_order | No | The 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_run | No | 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. |
| production_rate_per_year | No | Pieces 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_cost | No | The 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_run | No | 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. |
| recommended_effective_unit_cost | No | The buyer's effective cost per piece at the recommended lot (buyer_stock), on the same basis as current_effective_unit_cost, in currency. |
TDQS
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.
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.
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.
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.
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.
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 PartADestructiveInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| batch_id | No | Groups the files of one drop; they are answered in position order. | |
| drawings | No | Drawings of the assembly or its parts. | |
| position | No | Order of this file in its drop. | |
| part_number | No | The part number it will be started under. | |
| cad_file_b64 | Yes | Base64 (or a data: URI) of the STEP file; gzip-compressed is accepted. | |
| cad_filename | Yes | e.g. frame.step — used for format detection. | |
| cad_content_type | No | MIME type of the file, when known. |
TDQS
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.
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.
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.
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.
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.
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 CostARead-onlyIdempotentInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| detail | No | '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_size | No | Lot size to price the what-if at. Omit to keep the calculation's own lot size. | |
| adjustments | No | 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. | |
| calculation_id | Yes | Id of a calculation, as upload_and_quote, quote_part or list_calculations return it. |
Output Schema
| Name | Required | Description |
|---|---|---|
| after | No | detail='summary' only: the headline under the what-if. |
| delta | No | Change 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. |
| before | No | detail='summary' only: the priced calculation's headline. |
| currency | No | |
| guidance | Yes | |
| lot_size | No | Lot size this preview was priced at. |
| unit_cost | No | Cost 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_lines | No | The previewed cost sheet as a tree, same shape as get_cost_breakdown's. Empty under detail='summary'. |
| reconciled | No | Whether 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. |
| adjustments | No | The factor values this preview was priced at, echoed back. |
| moved_lines | No | 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. |
| total_delta | No | Change in the cost per part against the priced calculation: new minus current, in the currency above. |
| calculation_id | Yes |
TDQS
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.
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.
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.
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.
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.
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 PartADestructiveInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | Optional human-readable label; defaults to a timestamped name when omitted. | |
| engine | No | Pricing engine selector; retained for back-compat and always normalized to the sole engine. | arcnm |
| region | No | Pricing region override; defaults to the costing environment's region when omitted. | |
| currency | No | 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. | |
| language | No | BCP 47 language for the calculation's captured context (e.g. 'de', 'en'). Part of the calculation's cache identity. | de |
| lot_size | No | Number of identical parts produced per batch (1 to 1,000,000,000). | |
| material_ref | No | 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. | |
| nest_item_id | No | Price 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_volume | No | 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. | |
| dataset_link_id | No | UUID of a specific dataset link to use; omit to use the revision's active primary CAD. | |
| stock_format_id | No | 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. | |
| stock_format_mm | No | 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. | |
| part_revision_id | Yes | UUID of the part revision to price. | |
| full_stock_charge | No | How 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_id | No | 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). | |
| provided_stock_kind | No | Shape 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_provided | No | True 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_id | No | UUID 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_ids | No | Price 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_id | No | The 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
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.
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.
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.
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.
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.
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 SavingsARead-onlyIdempotentInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| calculation_id | Yes | Id of a calculation, as upload_and_quote, quote_part or list_calculations return it. |
Output Schema
| Name | Required | Description |
|---|---|---|
| status | Yes | |
| currency | No | |
| findings | No | |
| guidance | Yes | |
| calculation_id | Yes | |
| human_finding_count | No | How many findings are headline (human-audience) ones. |
| inputs_changed_since_run | No | 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. |
| environment_changed_since_run | No | 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. |
TDQS
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.
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.
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.
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.
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.
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 QuoteADestructiveInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| engine | No | Pricing engine selector; retained for back-compat and always normalized to the sole engine. | arcnm |
| region | No | Pricing region override; defaults to the costing environment's region when omitted. | |
| currency | No | ISO 4217 currency code for the quote; defaults to the costing environment's currency when omitted. | |
| language | No | BCP 47 language for the calculation's captured context (e.g. 'de', 'en'). Part of the calculation's cache identity. | de |
| lot_size | No | Number of identical parts produced per batch (1 to 1,000,000,000). | |
| folder_id | No | Optional workspace folder to file the created part into. | |
| on_conflict | No | How 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_number | Yes | Natural-key part number; reused to attach a new revision if the part already exists. | |
| precheck_id | No | 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. | |
| cad_file_b64 | No | Base64 (or a data: URI) of the 3D CAD file (e.g. STEP). Required unless precheck_id is sent. | |
| cad_filename | No | CAD filename including extension, e.g. bracket.step — used for format detection. Required with cad_file_b64. | |
| material_ref | No | Free-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_id | No | Price 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_b64 | No | Optional base64 (or data: URI) of an RFQ text file. | |
| rfq_filename | No | RFQ filename including extension. | |
| annual_volume | No | Expected yearly quantity used to amortize setup cost (1 to 1,000,000,000). | |
| sheet_gauge_mm | No | Sheet 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_id | No | 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. | |
| cad_content_type | No | MIME type of the CAD file, when known. | |
| drawing_file_b64 | No | Optional base64 (or data: URI) of a 2D drawing (PDF/PNG/JPEG). | |
| drawing_filename | No | Drawing filename including extension. | |
| rfq_content_type | No | MIME type of the RFQ file, when known. | |
| material_grade_id | No | UUID of a resolved material grade; takes precedence over material_ref when both are supplied. | |
| max_overage_cents | No | The most this calculation may cost past your plan's included calculations, in cents; parts past it wait (run_spend_cap). | |
| precheck_revision | No | The revision the precheck showed; refused with 409 precheck_changed when what it decides moved since. | |
| provided_stock_kind | No | Shape of the provided stock; 'near_net_profile' scopes the plan. | none |
| drawing_content_type | No | MIME type of the drawing file, when known. | |
| material_is_provided | No | True when the customer supplies the raw material (beigestellt). | |
| costing_environment_id | No | UUID of the costing environment to price against. Omit to use your organization's default environment. | |
| costing_environment_ids | No | Price 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
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.
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.
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.
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.
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.
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.
9 tool updates
- Added
attach_drawing - Changed
explain_cost5 fields changed- changed
Output schema / properties / assembly_completeness / descriptionPrevious 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." - added
Output schema / properties / drawing_pairingAdded 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." +} - changed
Output schema / properties / material_source / descriptionPrevious 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." - added
Output schema / properties / price_completenessAdded 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." +} - changed
Output schema / properties / unpriced / anyOfPrevious 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" + } +]
- Changed
get_cost_breakdown3 fields changed- changed
Output schema / $defs / CostSheetNode / properties / amount / descriptionPrevious 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." - added
Output schema / $defs / CostSheetNode / properties / exactAdded 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." +} - changed
Output schema / properties / material_stock / descriptionPrevious 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."
- Added
get_precheck - Changed
get_process_plan2 fields changed- added
Output schema / properties / price_completenessAdded 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." +} - changed
Output schema / properties / unpriced / anyOfPrevious 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" + } +]
- Added
precheck_part - Changed
preview_cost2 fields changed- changed
Output schema / $defs / CostSheetNode / properties / amount / descriptionPrevious 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." - added
Output schema / $defs / CostSheetNode / properties / exactAdded 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." +}
- Changed
quote_part2 fields changed- changed
Input schema / properties / material_grade_id / descriptionPrevious 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)." - changed
Input schema / properties / material_ref / descriptionPrevious 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."
- Changed
upload_and_quote12 fields changed- added
Input schema / properties / cad_file_b64 / anyOfAdded value: +[ + { + "type": "string" + }, + { + "type": "null" + } +] - changed
Input schema / properties / cad_file_b64 / descriptionPrevious 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." - removed
Input schema / properties / cad_file_b64 / typeRemoved value: -"string" - added
Input schema / properties / cad_filename / anyOfAdded value: +[ + { + "maxLength": 255, + "minLength": 1, + "type": "string" + }, + { + "type": "null" + } +] - changed
Input schema / properties / cad_filename / descriptionPrevious 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." - removed
Input schema / properties / cad_filename / maxLengthRemoved value: -255 - removed
Input schema / properties / cad_filename / minLengthRemoved value: -1 - removed
Input schema / properties / cad_filename / typeRemoved value: -"string" - added
Input schema / properties / max_overage_centsAdded 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" +} - added
Input schema / properties / precheck_idAdded 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" +} - added
Input schema / properties / precheck_revisionAdded 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" +} - changed
Input schema / requiredPrevious value: -[ - "part_number", - "cad_file_b64", - "cad_filename" -]New value: +[ + "part_number" +]
1 tool update
- Changed
get_upload_link1 field changed- changed
Output schema / properties / calculations_remaining / descriptionPrevious 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."
9 tool updates
- Changed
compare_calculations4 fields changed- added
Input schema / properties / calculation_ids / items / formatAdded value: +"uuid" - added
Output schema / properties / not_foundAdded 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" +} - changed
Output schema / properties / pair / anyOfPrevious 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" + } +] - changed
Output schema / properties / ranking / anyOfPrevious 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" + } +]
- Changed
explain_cost12 fields changed- added
Input schema / properties / calculation_id / formatAdded value: +"uuid" - changed
Input schema / properties / detail / descriptionPrevious 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." - added
Output schema / properties / clampingsAdded 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." +} - added
Output schema / properties / material_pricedAdded 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." +} - added
Output schema / properties / material_sourceAdded 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." +} - changed
Output schema / properties / top_drivers / descriptionPrevious 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'." - added
Output schema / properties / top_drivers / items / properties / categoryAdded 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." +} - changed
Output schema / properties / top_drivers / items / properties / cost / descriptionPrevious 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." - changed
Output schema / properties / top_drivers / items / properties / cost_share_pct / descriptionPrevious 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." - changed
Output schema / properties / top_drivers / items / properties / rank / descriptionPrevious 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." - changed
Output schema / properties / unit_cost / descriptionPrevious 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." - added
Output schema / properties / unpricedAdded 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." +}
- Changed
get_cost_breakdown7 fields changed- added
Input schema / properties / calculation_id / formatAdded value: +"uuid" - changed
Input schema / properties / max_depth / descriptionPrevious 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 {})." - added
Output schema / $defs / CostDriverLine / properties / categoryAdded 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." +} - changed
Output schema / $defs / CostDriverLine / properties / cost / descriptionPrevious 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." - changed
Output schema / $defs / CostDriverLine / properties / cost_share_pct / descriptionPrevious 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." - changed
Output schema / $defs / CostDriverLine / properties / rank / descriptionPrevious 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." - changed
Output schema / properties / unit_cost / descriptionPrevious 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."
- Changed
get_process_plan3 fields changed- added
Input schema / properties / calculation_id / formatAdded value: +"uuid" - added
Output schema / properties / clampingsAdded 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." +} - added
Output schema / properties / unpricedAdded 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." +}
- Changed
get_upload_link12 fields changed- changed
Input schema / properties / environment_id / descriptionPrevious 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)." - changed
Input schema / properties / folder_id / descriptionPrevious value: -"Folder to file the uploads into (optional)."New value: +"Folder to file the uploaded parts into (optional)." - added
Input schema / properties / max_uploadsAdded 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" +} - changed
Output schema / descriptionPrevious 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." - changed
Output schema / properties / environment_id / descriptionPrevious 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." - added
Output schema / properties / expires_atAdded value: +{ + "description": "When the link stops working (RFC 3339, UTC).", + "type": "string" +} - changed
Output schema / properties / folder_id / descriptionPrevious value: -"The folder the uploads are filed into."New value: +"The folder the parts are filed into; null for the root." - changed
Output schema / properties / issued_at / descriptionPrevious 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)." - added
Output schema / properties / max_uploadsAdded value: +{ + "description": "How many parts the person may upload through the link.", + "type": "integer" +} - added
Output schema / properties / upload_session_idAdded 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" +} - changed
Output schema / properties / url / descriptionPrevious 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." - changed
Output schema / requiredPrevious value: -[ - "url", - "issued_at", - "next_step" -]New value: +[ + "url", + "upload_session_id", + "expires_at", + "max_uploads", + "issued_at", + "next_step" +]
- Changed
list_calculations4 fields changed- added
Input schema / properties / limit / maximumAdded value: +500 - added
Input schema / properties / limit / minimumAdded value: +1 - changed
Input schema / properties / sort / descriptionPrevious 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." - added
Input schema / properties / upload_session_idAdded 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" +}
- Changed
optimize_lot_size1 field changed- added
Input schema / properties / calculation_id / formatAdded value: +"uuid"
- Changed
preview_cost1 field changed- added
Input schema / properties / calculation_id / formatAdded value: +"uuid"
- Changed
suggest_cost_savings2 fields changed- added
Input schema / properties / calculation_id / formatAdded value: +"uuid" - changed
Output schema / properties / findings / items / properties / kind / descriptionPrevious value: -"Finding kind, e.g. review_tolerance_cost."New value: +"Finding kind, e.g. adjust_lot_size."
9 tool updates
- Changed
cancel_calculation1 field changed- added
Input schema / additionalPropertiesAdded value: +false
- Changed
explain_cost2 fields changed- changed
Output schema / properties / assembly_completeness / descriptionPrevious 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." - changed
Output schema / properties / cost_categories / descriptionPrevious 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."
- Changed
get_calculation1 field changed- added
Input schema / additionalPropertiesAdded value: +false
- Changed
get_cost_breakdown2 fields changed- added
Input schema / properties / max_depthAdded 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." +} - added
Output schema / $defs / CostSheetNode / properties / children_hiddenAdded 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." +}
- Changed
list_calculations1 field changed- added
Input schema / additionalPropertiesAdded value: +false
- Changed
list_environments1 field changed- added
Input schema / additionalPropertiesAdded value: +false
- Changed
preview_cost8 fields changed- added
Input schema / properties / detailAdded 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" +} - added
Output schema / $defs / CostLineMoveAdded 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" +} - added
Output schema / $defs / CostPreviewHeadlineAdded 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" +} - added
Output schema / $defs / CostSheetNode / properties / children_hiddenAdded 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." +} - added
Output schema / properties / afterAdded value: +{ + "anyOf": [ + { + "$ref": "#/$defs/CostPreviewHeadline" + }, + { + "type": "null" + } + ], + "default": null, + "description": "detail='summary' only: the headline under the what-if." +} - added
Output schema / properties / beforeAdded value: +{ + "anyOf": [ + { + "$ref": "#/$defs/CostPreviewHeadline" + }, + { + "type": "null" + } + ], + "default": null, + "description": "detail='summary' only: the priced calculation's headline." +} - changed
Output schema / properties / cost_lines / descriptionPrevious 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'." - added
Output schema / properties / moved_linesAdded 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." +}
- Changed
quote_part5 fields changed- added
Input schema / additionalPropertiesAdded value: +false - changed
Input schema / properties / annual_volume / descriptionPrevious 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." - changed
Input schema / properties / currency / descriptionPrevious 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." - changed
Input schema / properties / material_grade_id / descriptionPrevious 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." - changed
Input schema / properties / material_ref / descriptionPrevious 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."
- Changed
upload_and_quote1 field changed- added
Input schema / additionalPropertiesAdded value: +false
28 tool updates
- Removed
apply_adjustment - Removed
attach_upload - Changed
cancel_calculation1 field changed- added
Input schema / properties / calculation_id / descriptionAdded value: +"Id of a calculation, as upload_and_quote, quote_part or list_calculations return it."
- Removed
cancel_nest_run - Removed
compare_environments - Removed
confirm_upload - Removed
create_nest_run - Removed
create_part - Changed
explain_cost4 fields changed- added
Input schema / properties / calculation_id / descriptionAdded value: +"Id of a calculation, as upload_and_quote, quote_part or list_calculations return it." - added
Input schema / properties / detail / descriptionAdded value: +"How many cost drivers to list: 'concise' (the default) lists the top 3, 'detailed' the top 10." - changed
Output schema / properties / costing_environment_id / descriptionPrevious 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)." - added
Output schema / properties / top_drivers / descriptionAdded 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'."
- Removed
export_nest_layout - Changed
get_calculation1 field changed- added
Input schema / properties / calculation_id / descriptionAdded value: +"Id of a calculation, as upload_and_quote, quote_part or list_calculations return it."
- Changed
get_cost_breakdown6 fields changed- added
Input schema / properties / calculation_id / descriptionAdded value: +"Id of a calculation, as upload_and_quote, quote_part or list_calculations return it." - added
Input schema / properties / persona / descriptionAdded 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)." - changed
Output schema / $defs / CostSheetNode / properties / factors / descriptionPrevious 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." - changed
Output schema / $defs / ProcessStepLine / properties / subcontract_per_part / descriptionPrevious 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." - changed
Output schema / descriptionPrevious 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." - changed
Output schema / properties / costing_environment_id / descriptionPrevious 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."
- Removed
get_cost_drivers - Removed
get_cost_factors - Removed
get_environment - Removed
get_nest_run - Removed
get_nesting_summary - Changed
get_process_plan3 fields changed- added
Input schema / properties / calculation_id / descriptionAdded value: +"Id of a calculation, as upload_and_quote, quote_part or list_calculations return it." - changed
Output schema / descriptionPrevious 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." - changed
Output schema / properties / steps / items / properties / subcontract_per_part / descriptionPrevious 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."
- Changed
get_upload_link3 fields changed- added
Output schema / properties / issued_atAdded 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" +} - changed
Output schema / properties / next_step / descriptionPrevious 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." - changed
Output schema / requiredPrevious value: -[ - "url", - "next_step" -]New value: +[ + "url", + "issued_at", + "next_step" +]
- Changed
list_calculations1 field changed- added
Input schema / properties / part_id / descriptionAdded value: +"Only the calculations of this part, by its id (part_id on any calculation)."
- Removed
list_part_revisions - Removed
list_parts - Changed
optimize_lot_size1 field changed- added
Input schema / properties / calculation_id / descriptionAdded value: +"Id of a calculation, as upload_and_quote, quote_part or list_calculations return it."
- Removed
presign_upload - Changed
preview_cost4 fields changed- added
Input schema / properties / adjustments / descriptionAdded 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." - added
Input schema / properties / calculation_id / descriptionAdded value: +"Id of a calculation, as upload_and_quote, quote_part or list_calculations return it." - added
Input schema / properties / lot_size / descriptionAdded value: +"Lot size to price the what-if at. Omit to keep the calculation's own lot size." - changed
Output schema / $defs / CostSheetNode / properties / factors / descriptionPrevious 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."
- Removed
start_nest_run - Changed
suggest_cost_savings1 field changed- added
Input schema / properties / calculation_id / descriptionAdded value: +"Id of a calculation, as upload_and_quote, quote_part or list_calculations return it."
- Added
upload_and_quote
10 tool updates
- Added
apply_adjustment - Added
attach_upload - Added
cancel_calculation - Added
cancel_nest_run - Added
confirm_upload - Added
create_nest_run - Added
create_part - Added
presign_upload - Added
quote_part - Added
start_nest_run
10 tool updates
- Removed
apply_adjustment - Removed
attach_upload - Removed
cancel_calculation - Removed
cancel_nest_run - Removed
confirm_upload - Removed
create_nest_run - Removed
create_part - Removed
presign_upload - Removed
quote_part - Removed
start_nest_run
3 tool updates
- Changed
explain_cost2 fields changed- changed
Output schema / properties / costing_environment_id / descriptionPrevious 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." - changed
Output schema / properties / coverage / descriptionPrevious 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."
- Changed
export_nest_layout4 fields changed- changed
Output schema / properties / download_url / descriptionPrevious 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)." - changed
Output schema / properties / plan_outlines_included / descriptionPrevious 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." - changed
Output schema / properties / sheets / items / properties / download_url / descriptionPrevious 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." - changed
Output schema / properties / status / descriptionPrevious 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."
- Changed
get_cost_breakdown1 field changed- changed
Output schema / properties / costing_environment_id / descriptionPrevious 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."
7 tool updates
- Changed
check_quota5 fields changed- changed
Output schema / descriptionPrevious 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." - changed
Output schema / properties / has_payment_method / descriptionPrevious 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." - changed
Output schema / properties / overage_settlement / descriptionPrevious 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)." - changed
Output schema / properties / wallet_funded_calculations / descriptionPrevious 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'." - changed
Output schema / properties / wallet_overdrawn / descriptionPrevious 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."
- Changed
compare_environments1 field changed- changed
Output schema / properties / environments / items / properties / stale_cells / descriptionPrevious 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."
- Changed
explain_cost2 fields changed- changed
Output schema / properties / confidence / anyOfPrevious 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" + } +] - changed
Output schema / properties / confidence / descriptionPrevious 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."
- Changed
get_calculation1 field changed- changed
Input schema / properties / include_analytics / descriptionPrevious 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."
- Changed
get_cost_breakdown2 fields changed- changed
Output schema / $defs / ConfidenceSignal / descriptionPrevious 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." - changed
Output schema / properties / confidence / descriptionPrevious 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."
- Changed
get_cost_factors1 field changed- changed
Output schema / properties / rows / items / properties / edit_path / descriptionPrevious 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."
- Changed
quote_part2 fields changed- changed
Input schema / properties / stock_format_id / descriptionPrevious 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." - changed
Input schema / properties / stock_format_mm / descriptionPrevious 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."
243 tool updates
- Added
apply_adjustment - Removed
arcnm_apply_adjustment - Removed
arcnm_check_quota - Removed
arcnm_compare_calculations - Removed
arcnm_compare_environments - Removed
arcnm_cost_breakdown - Removed
arcnm_cost_drivers - Removed
arcnm_cost_factors - Removed
arcnm_explain_cost - Removed
arcnm_nest_run_cancel - Removed
arcnm_nest_run_create - Removed
arcnm_nest_run_export - Removed
arcnm_nest_run_result - Removed
arcnm_nest_run_start - Removed
arcnm_nest_run_status - Removed
arcnm_nest_savings - Removed
arcnm_nesting_read - Removed
arcnm_optimization_directions - Removed
arcnm_optimize_lot_size - Removed
arcnm_preview_cost - Removed
arcnm_process_plan - Removed
arcnm_rank_calculations - Removed
arcnm_sheet_nest_export - Added
attach_upload - Removed
calculations_assign_assembly_drawing - Removed
calculations_batch_calculate - Removed
calculations_batch_comparison - Removed
calculations_batch_comparison_components - Removed
calculations_bulk_cancel_calculations - Removed
calculations_bulk_delete_calculations - Removed
calculations_bulk_retry_calculations - Removed
calculations_cancel_batch - Removed
calculations_cancel_calculation - Removed
calculations_compare_environment_runs - Removed
calculations_create_calculation - Removed
calculations_create_cost_scenario - Removed
calculations_delete_calculation - Removed
calculations_delete_cost_scenario - Removed
calculations_get_calculation - Removed
calculations_get_calculation_assembly_route - Removed
calculations_get_calculation_bom - Removed
calculations_get_calculation_capacity - Removed
calculations_get_calculation_optimization - Removed
calculations_get_cost_sheet - Removed
calculations_get_entitlement - Removed
calculations_list_calculations - Removed
calculations_list_cost_scenarios - Removed
calculations_patch_assembly_component - Removed
calculations_patch_calculation_material - Removed
calculations_preview_cost - Removed
calculations_quote - Removed
calculations_run_calculation - Removed
calculations_update_cost_scenario - Removed
calculations_upload_and_quote_json - Removed
calibration_auto_calibrate_environment - Removed
calibration_auto_calibrate_from_erp - Removed
calibration_calibrate_selection_policy - Removed
calibration_deactivate_environment - Removed
calibration_environment_report - Removed
calibration_environment_run_history - Removed
calibration_environment_status - Removed
calibration_erp_preflight - Removed
calibration_finalize_environment - Removed
calibration_fit_learning_curve - Removed
calibration_import_calibrate - Removed
calibration_import_create - Removed
calibration_import_status - Removed
calibration_ingest_environment_outcomes - Removed
calibration_next_best_evidence - Removed
calibration_revert_environment_run - Removed
calibration_teach_environment - Added
cancel_calculation - Added
cancel_nest_run - Added
check_quota - Added
compare_calculations - Added
compare_environments - Added
confirm_upload - Added
create_nest_run - Added
create_part - Removed
datasets_attach_dataset - Removed
datasets_detach_dataset - Removed
datasets_list_datasets - Removed
datasets_update_dataset - Removed
environments_attach_env_subcontractor - Removed
environments_attach_env_tool - Removed
environments_attach_machine - Removed
environments_clone_environment - Removed
environments_clone_preset - Removed
environments_create_environment - Removed
environments_delete_environment - Removed
environments_delete_rate - Removed
environments_detach_env_subcontractor - Removed
environments_detach_env_tool - Removed
environments_detach_machine - Removed
environments_economics_update - Removed
environments_get_calculation_tuning - Removed
environments_get_environment - Removed
environments_get_environment_audit - Removed
environments_get_environment_factors - Removed
environments_get_individualization - Removed
environments_get_shop_practice - Removed
environments_list_env_machines - Removed
environments_list_env_subcontractors - Removed
environments_list_env_tools - Removed
environments_list_environments - Removed
environments_list_presets - Removed
environments_list_rates - Removed
environments_list_surcharge_presets - Removed
environments_material_price_clear - Removed
environments_material_price_set - Removed
environments_restore_env_machines - Removed
environments_restore_env_rates - Removed
environments_restore_env_subcontractors - Removed
environments_restore_env_tools - Removed
environments_scrap_price_clear - Removed
environments_scrap_price_set - Removed
environments_scrap_prices - Removed
environments_subcontract_price_set - Removed
environments_update_calculation_tuning - Removed
environments_update_env_subcontractor_membership - Removed
environments_update_env_tool_membership - Removed
environments_update_environment_identity - Removed
environments_update_membership - Removed
environments_update_shop_practice - Removed
environments_upsert_rate - Added
explain_cost - Added
export_nest_layout - Removed
folders_create_folder - Removed
folders_delete_folder - Removed
folders_folder_summary - Removed
folders_get_folder - Removed
folders_list_folders - Removed
folders_move_parts - Removed
folders_update_folder - Removed
folders_workspace_summary - Removed
geometry_part_revision_drawing_url - Removed
geometry_part_revision_faces_url - Added
get_calculation - Added
get_cost_breakdown - Added
get_cost_drivers - Added
get_cost_factors - Added
get_environment - Added
get_nest_run - Added
get_nesting_summary - Added
get_process_plan - Added
get_upload_link - Removed
import_preview_machine_import - Removed
import_preview_tool_import - Added
list_calculations - Added
list_environments - Added
list_part_revisions - Added
list_parts - Removed
machine_library_create_library_entry - Removed
machine_library_delete_library_entry - Removed
machine_library_get_library_entry - Removed
machine_library_library_usage - Removed
machine_library_list_library - Removed
machine_library_rate_calculator - Removed
machine_library_update_library_entry - Removed
machines_get_machine - Removed
machines_get_machine_usage - Removed
machines_update_machine - Removed
materials_create_grade_designation - Removed
materials_create_org_grade - Removed
materials_create_override - Removed
materials_create_stock_format - Removed
materials_delete_designation - Removed
materials_delete_org_grade - Removed
materials_delete_override - Removed
materials_get_grade - Removed
materials_get_grade_by_urn - Removed
materials_get_grade_master - Removed
materials_get_stock_format - Removed
materials_ignore_unmapped_designation - Removed
materials_list_grade_designations - Removed
materials_list_grades - Removed
materials_list_material_attribute_vocabulary - Removed
materials_list_overrides - Removed
materials_list_standards - Removed
materials_list_stock_formats - Removed
materials_list_unmapped_designations - Removed
materials_list_workpiece_groups - Removed
materials_lookup - Removed
materials_lookup_batch - Removed
materials_map_unmapped_designation - Removed
materials_pricing_coverage - Removed
materials_retire_stock_format - Removed
materials_suggest - Removed
materials_suppress_stock_format - Removed
materials_unsuppress_stock_format - Removed
materials_update_org_grade - Removed
materials_update_override - Removed
materials_update_stock_format - Removed
materials_upsert_grade_override - Added
optimize_lot_size - Removed
parts_create_part - Removed
parts_create_revision - Removed
parts_delete_part - Removed
parts_delete_revision - Removed
parts_get_part - Removed
parts_get_revision - Removed
parts_list_parts - Removed
parts_list_revisions - Removed
parts_part_faces_url - Removed
parts_part_preview_url - Removed
parts_part_preview_urls_batch - Removed
parts_resolve_part_numbers - Removed
parts_update_part - Removed
parts_update_revision - Added
presign_upload - Added
preview_cost - Added
quote_part - Added
start_nest_run - Removed
subcontractors_create_subcontractor - Removed
subcontractors_delete_subcontractor - Removed
subcontractors_list_subcontractors - Removed
subcontractors_suppress_subcontractor_preset - Removed
subcontractors_unsuppress_subcontractor_preset - Removed
subcontractors_update_subcontractor - Added
suggest_cost_savings - Removed
tools_adopt_catalogue_item - Removed
tools_copy_tool - Removed
tools_create_tool - Removed
tools_delete_tool - Removed
tools_get_tool - Removed
tools_list_catalogue_items - Removed
tools_list_tools - Removed
tools_reset_tool_to_article - Removed
tools_suppress_catalogue_item - Removed
tools_tool_catalogue - Removed
tools_unsuppress_catalogue_item - Removed
tools_update_tool - Removed
uploads_bulk_cancel_uploads - Removed
uploads_bulk_delete_uploads - Removed
uploads_bulk_retry_uploads - Removed
uploads_cancel_upload - Removed
uploads_confirm - Removed
uploads_delete_upload - Removed
uploads_download_url - Removed
uploads_list_uploads - Removed
uploads_presign - Removed
uploads_retry_upload - Removed
uploads_update_upload
7 tool updates
- Changed
arcnm_compare_calculations2 fields changed- changed
Output schema / properties / a / properties / needs_review / descriptionPrevious 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." - changed
Output schema / properties / b / properties / needs_review / descriptionPrevious 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."
- Changed
arcnm_compare_environments2 fields changed- changed
Output schema / properties / complete / descriptionPrevious 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." - changed
Output schema / properties / mixed_calibration / descriptionPrevious 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."
- Changed
arcnm_cost_drivers1 field changed- changed
Output schema / properties / attributed_cost_share_pct / descriptionPrevious 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."
- Changed
arcnm_explain_cost1 field changed- changed
Output schema / properties / assembly_completeness / descriptionPrevious 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."
- Changed
arcnm_rank_calculations1 field changed- changed
Output schema / properties / ranked / items / properties / needs_review / descriptionPrevious 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."
- Changed
calibration_auto_calibrate_environment1 field changed- changed
Input schema / properties / actuals / descriptionPrevious 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."
- Changed
calibration_auto_calibrate_from_erp1 field changed- changed
Input schema / properties / work_orders / descriptionPrevious 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."
212 tool updates
- First observed
arcnm_apply_adjustment - First observed
arcnm_check_quota - First observed
arcnm_compare_calculations - First observed
arcnm_compare_environments - First observed
arcnm_cost_breakdown - First observed
arcnm_cost_drivers - First observed
arcnm_cost_factors - First observed
arcnm_explain_cost - First observed
arcnm_nest_run_cancel - First observed
arcnm_nest_run_create - First observed
arcnm_nest_run_export - First observed
arcnm_nest_run_result - First observed
arcnm_nest_run_start - First observed
arcnm_nest_run_status - First observed
arcnm_nest_savings - First observed
arcnm_nesting_read - First observed
arcnm_optimization_directions - First observed
arcnm_optimize_lot_size - First observed
arcnm_preview_cost - First observed
arcnm_process_plan - First observed
arcnm_rank_calculations - First observed
arcnm_sheet_nest_export - First observed
calculations_assign_assembly_drawing - First observed
calculations_batch_calculate - First observed
calculations_batch_comparison - First observed
calculations_batch_comparison_components - First observed
calculations_bulk_cancel_calculations - First observed
calculations_bulk_delete_calculations - First observed
calculations_bulk_retry_calculations - First observed
calculations_cancel_batch - First observed
calculations_cancel_calculation - First observed
calculations_compare_environment_runs - First observed
calculations_create_calculation - First observed
calculations_create_cost_scenario - First observed
calculations_delete_calculation - First observed
calculations_delete_cost_scenario - First observed
calculations_get_calculation - First observed
calculations_get_calculation_assembly_route - First observed
calculations_get_calculation_bom - First observed
calculations_get_calculation_capacity - First observed
calculations_get_calculation_optimization - First observed
calculations_get_cost_sheet - First observed
calculations_get_entitlement - First observed
calculations_list_calculations - First observed
calculations_list_cost_scenarios - First observed
calculations_patch_assembly_component - First observed
calculations_patch_calculation_material - First observed
calculations_preview_cost - First observed
calculations_quote - First observed
calculations_run_calculation - First observed
calculations_update_cost_scenario - First observed
calculations_upload_and_quote_json - First observed
calibration_auto_calibrate_environment - First observed
calibration_auto_calibrate_from_erp - First observed
calibration_calibrate_selection_policy - First observed
calibration_deactivate_environment - First observed
calibration_environment_report - First observed
calibration_environment_run_history - First observed
calibration_environment_status - First observed
calibration_erp_preflight - First observed
calibration_finalize_environment - First observed
calibration_fit_learning_curve - First observed
calibration_import_calibrate - First observed
calibration_import_create - First observed
calibration_import_status - First observed
calibration_ingest_environment_outcomes - First observed
calibration_next_best_evidence - First observed
calibration_revert_environment_run - First observed
calibration_teach_environment - First observed
datasets_attach_dataset - First observed
datasets_detach_dataset - First observed
datasets_list_datasets - First observed
datasets_update_dataset - First observed
environments_attach_env_subcontractor - First observed
environments_attach_env_tool - First observed
environments_attach_machine - First observed
environments_clone_environment - First observed
environments_clone_preset - First observed
environments_create_environment - First observed
environments_delete_environment - First observed
environments_delete_rate - First observed
environments_detach_env_subcontractor - First observed
environments_detach_env_tool - First observed
environments_detach_machine - First observed
environments_economics_update - First observed
environments_get_calculation_tuning - First observed
environments_get_environment - First observed
environments_get_environment_audit - First observed
environments_get_environment_factors - First observed
environments_get_individualization - First observed
environments_get_shop_practice - First observed
environments_list_env_machines - First observed
environments_list_env_subcontractors - First observed
environments_list_env_tools - First observed
environments_list_environments - First observed
environments_list_presets - First observed
environments_list_rates - First observed
environments_list_surcharge_presets - First observed
environments_material_price_clear - First observed
environments_material_price_set - First observed
environments_restore_env_machines - First observed
environments_restore_env_rates - First observed
environments_restore_env_subcontractors - First observed
environments_restore_env_tools - First observed
environments_scrap_price_clear - First observed
environments_scrap_price_set - First observed
environments_scrap_prices - First observed
environments_subcontract_price_set - First observed
environments_update_calculation_tuning - First observed
environments_update_env_subcontractor_membership - First observed
environments_update_env_tool_membership - First observed
environments_update_environment_identity - First observed
environments_update_membership - First observed
environments_update_shop_practice - First observed
environments_upsert_rate - First observed
folders_create_folder - First observed
folders_delete_folder - First observed
folders_folder_summary - First observed
folders_get_folder - First observed
folders_list_folders - First observed
folders_move_parts - First observed
folders_update_folder - First observed
folders_workspace_summary - First observed
geometry_part_revision_drawing_url - First observed
geometry_part_revision_faces_url - First observed
import_preview_machine_import - First observed
import_preview_tool_import - First observed
machine_library_create_library_entry - First observed
machine_library_delete_library_entry - First observed
machine_library_get_library_entry - First observed
machine_library_library_usage - First observed
machine_library_list_library - First observed
machine_library_rate_calculator - First observed
machine_library_update_library_entry - First observed
machines_get_machine - First observed
machines_get_machine_usage - First observed
machines_update_machine - First observed
materials_create_grade_designation - First observed
materials_create_org_grade - First observed
materials_create_override - First observed
materials_create_stock_format - First observed
materials_delete_designation - First observed
materials_delete_org_grade - First observed
materials_delete_override - First observed
materials_get_grade - First observed
materials_get_grade_by_urn - First observed
materials_get_grade_master - First observed
materials_get_stock_format - First observed
materials_ignore_unmapped_designation - First observed
materials_list_grade_designations - First observed
materials_list_grades - First observed
materials_list_material_attribute_vocabulary - First observed
materials_list_overrides - First observed
materials_list_standards - First observed
materials_list_stock_formats - First observed
materials_list_unmapped_designations - First observed
materials_list_workpiece_groups - First observed
materials_lookup - First observed
materials_lookup_batch - First observed
materials_map_unmapped_designation - First observed
materials_pricing_coverage - First observed
materials_retire_stock_format - First observed
materials_suggest - First observed
materials_suppress_stock_format - First observed
materials_unsuppress_stock_format - First observed
materials_update_org_grade - First observed
materials_update_override - First observed
materials_update_stock_format - First observed
materials_upsert_grade_override - First observed
parts_create_part - First observed
parts_create_revision - First observed
parts_delete_part - First observed
parts_delete_revision - First observed
parts_get_part - First observed
parts_get_revision - First observed
parts_list_parts - First observed
parts_list_revisions - First observed
parts_part_faces_url - First observed
parts_part_preview_url - First observed
parts_part_preview_urls_batch - First observed
parts_resolve_part_numbers - First observed
parts_update_part - First observed
parts_update_revision - First observed
subcontractors_create_subcontractor - First observed
subcontractors_delete_subcontractor - First observed
subcontractors_list_subcontractors - First observed
subcontractors_suppress_subcontractor_preset - First observed
subcontractors_unsuppress_subcontractor_preset - First observed
subcontractors_update_subcontractor - First observed
tools_adopt_catalogue_item - First observed
tools_copy_tool - First observed
tools_create_tool - First observed
tools_delete_tool - First observed
tools_get_tool - First observed
tools_list_catalogue_items - First observed
tools_list_tools - First observed
tools_reset_tool_to_article - First observed
tools_suppress_catalogue_item - First observed
tools_tool_catalogue - First observed
tools_unsuppress_catalogue_item - First observed
tools_update_tool - First observed
uploads_bulk_cancel_uploads - First observed
uploads_bulk_delete_uploads - First observed
uploads_bulk_retry_uploads - First observed
uploads_cancel_upload - First observed
uploads_confirm - First observed
uploads_delete_upload - First observed
uploads_download_url - First observed
uploads_list_uploads - First observed
uploads_presign - First observed
uploads_retry_upload - First observed
uploads_update_upload
Publisher details
- Operator
- rattle mng GmbH (ARCNM), Überlingen, Germany · Publisher source
- Operator website
- https://arcnm.io · Publisher source
- Vendor relationship
- First-party · Publisher source
- Documentation
- https://arcnm.io/docs/mcp · 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
Should-cost of a machined, sheet metal or cast part from its PDF, DXF or STEP drawing, line by line.
Instant parametric cost estimates for custom manufacturing: CNC, molding, sheet metal, 3DP, PCB.
Quoting, pricing, production and part data for contract manufacturers (3D printing, CNC).
Instant 3D printing and CNC machining quotes from your CAD files (STL, STEP, 3MF, OBJ): price and ship date for SLS nylon, FDM plastic, aluminum and brass parts made in the US
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceIntelligently 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
- AlicenseNot gradedqualityDmaintenanceEnables 2D irregular polygon nesting (bin-packing) with tools to design, preview, get reports, and export DXF files for laser cutting or CNC routing.MIT
- FlicenseAqualityBmaintenanceParametric price benchmarking for engineering and procurement trade-offs. Agentic first, runs on your data, stays on your machine.1228 PyPI2-
- AlicenseAqualityAmaintenanceGenerates 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.51MIT
Glama MCP Gateway
Add one secure layer between your agents and this server.