Skip to main content
Glama

Agentic Fabrication Network (AFN)

Refine quote

refine_quote

Narrow an existing quote with new constraints (destination ZIP the user just provided, deadline, outdoor/waterproof/heat/food-safety requirements, budget, vendor reliability, verbatim requirements terms, drawing callouts, a process filter — "no, I meant in sheet metal" → processes — a ship-from country filter — "only US vendors" → ships_from — or a vendor filter — "only show A3D Manufacturing" → vendors) — or CHANGE its spec: material, color, or quantities. Changing material/quantity is a spec change, not a narrowing — pass it via the material/color/quantities args, NOT as a requirements term; the affected lanes re-price with the new spec through warm vendor sessions. For side-by-side comparisons ("how does carbon steel compare?"), add a scenario label — labeled refines coexist instead of replacing each other (max 4). "Organize by" ("sort by cheapest", "soonest arrival on top", "most green first") is also this tool: sort_by for objective orders, sort_order + sort_label for orders you judged yourself from the previews — presentation only, instant, nothing re-prices. GOING BACK is also this tool: undo_last_step ALONE takes back exactly one refine step (the quote's steps[] names each step, newest first — the network restores the previous stored state exactly); clear removes whole constraints ("drop the deadline" → clear ["deadline"]); remove_requirements takes back individual requirements terms. Call with ONLY quote_id to re-read the quote (e.g. to pick up preview images that finished rendering).

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
bendsNoNew bend records for this part — a spec change: sheet lanes requote with exactly these bends (the list REPLACES the previous one, never patches it). Same shape as on get_fabrication_quote: each bend is two points in the part's own mm frame (flat DXF parts use z=0) plus angle_deg, direction up|down, and an optional requested radius_mm. Pass null to REMOVE every articulated bend
clearNoREMOVE constraints entirely ("drop the deadline", "forget the budget", "no more food-safe requirement"): list the constraints to clear and each is removed from the quote — the one deliberate widening besides undo. Clearing a deadline or budget answers instantly from held offers (near-misses convert back); clearing an attribute/reliability/requirements demand re-prices honestly. Same effect as ["any"] on the three filter args, extended to every constraint
colorNoNew color for this part (spec change — lanes requote). Colour WORDS only ('black', 'green', 'clear'); the network resolves them to each maker's stocked shades, dyes, filaments or coatings — a family word ('blue') brings back EVERY stocked shade of it, and the quote's color_shades_available lists them — never pass a material or a shade you invented. Pass null to REMOVE a previously asked color — back to vendor defaults
scaleNoRescale the DESIGN ITSELF before re-quoting: per-axis stretch factors over the file's current geometry ("make it 2x bigger" = {"x":2,"y":2,"z":2}). Mesh designs are genuinely converted — the child quote prices a rescaled file; STEP/IGES designs keep their original file with the dimensions riding as callouts (pass those too). {1,1,1} is a no-op
finishNoNew surface finish ("powder coat", "anodized", "bead blasted") — a spec change: finish-capable lanes (sheet metal, CNC, metal print) requote WITH it; 3D-print lanes have no coating step, so they ignore the finish but keep the COLOR. A colored finish ask ("black powder coat") should set BOTH finish and color, so every lane lands on the buyer's color. Pass null to REMOVE a previously asked finish
insertsNoNew hardware-insert records for this part — a spec change: sheet lanes requote with exactly these inserts (the list REPLACES the previous one, never patches it). Same shape as on get_fabrication_quote: species (nut|flush_nut|standoff|blind_standoff|stud) and thread required, hole geometry optional. Pass null to REMOVE every insert
sort_byNo"Organize by": re-order the quote's offer cards ("sort by cheapest" → "price"; "soonest arrival first" → "arrival"; "best rated" → "rating"; "total_price" = part + cheapest shipping; "recommended" restores the default price+speed rank). PURE PRESENTATION — answers instantly on the same quote, never re-prices or drops offers, and the ordering sticks across re-reads, streaming, and later refines until changed
tappingNoNew tapped-hole records for this part — a spec change: sheet lanes requote with exactly these taps (the list REPLACES the previous one, never patches it). Same shape as on get_fabrication_quote: thread callout ("M6", "1/4-20") required, hole geometry optional. Pass null to REMOVE every tap
vendorsNoOnly these specific vendors/makers ("only show A3D Manufacturing", "just Slant 3D and Fictiv") — an INCLUDE list of vendor names as they appear on offers. A CONSTRAINT like processes: other vendors' offers drop instantly (nothing re-prices), further refines inherit the filter, and ["any"] clears it to show every vendor again. Friendly names accepted ("A3D", "slant 3d"); unmatched names are reported, never an error. This is THE way to answer "show me everything vendor X offers" — the filtered quote lists that vendor's complete lineup
calloutsNoDimensions you read off the user's drawing that matter ("hole_diameter 6.5mm ±0.1"). The tightest tolerance prunes vendors that cannot hold it.
deadlineNoLatest acceptable delivery date, ISO YYYY-MM-DD
materialNoNew material for this part ("I need it in PLA" → "pla"). A spec change: lanes requote with this material through warm vendor sessions; an explicit material here replaces the quote's material fan-out. Free-form — unstocked asks resolve to the closest stocked material with a substitution note. Do NOT pass material changes as requirements terms. Pass null to REMOVE a previously asked material ("forget the aluminum ask") — the ask comes off the record and the process-default material fan returns
quote_idYes
scenarioNoComparison lane label. A labeled refine sits SIDE BY SIDE with the quote's other offers instead of replacing them: refines with the same label replace that scenario, different labels coexist (max 4 per quote), and a refine WITHOUT a scenario resets the baseline and supersedes every lane. "How does X compare to Y?" = one labeled refine per scenario (e.g. scenario "carbon steel" + material "carbon steel", then scenario "aluminum" + material "aluminum"). Keep labels short and human, like "carbon steel"
food_safeNo
high_tempNo
processesNoNarrow this quote to specific fabrication processes ("no, I meant in sheet metal" → ["sheet metal"]). A CONSTRAINT, not a new quote: excluded lanes drop while warm vendor sessions survive, and further refines inherit the filter. Friendly terms accepted ("sheet metal", "3d printing", "cnc", "laser"); pass ["any"] to clear the filter and show every process again. When comparison scenarios are open and the user narrows the process, re-refine EVERY active scenario label with this same arg so all columns prune together
quantitiesNoNew quantities the user wants (spec change — lanes requote at the new quantity). Same rules as on get_fabrication_quote: pass the real ask, never inflate it. Pass null to REMOVE a previously asked quantity — the quote returns to single-part pricing
ships_fromNoOnly vendors that ship from these countries/regions ("only US vendors", "just European shops", "keep it domestic") — an INCLUDE list naming where the user DOES want vendors from. A CONSTRAINT like processes: non-matching vendors drop instantly (nothing re-prices), further refines inherit the filter, and ["any"] clears it to show vendors everywhere again. Friendly terms accepted ("US", "Europe", "Germany", "China", "UK"). Vendors whose origin is unknown or whose network is worldwide (a specific origin cannot be guaranteed) are excluded, each with an honest note. For "nothing from X" asks, pass the regions the user does want instead
sort_labelNoShort human wording for a sort_order, displayed on the board ("most green first") — required with sort_order, since only you know what your order means
sort_orderNoEXPLICIT card order for asks only you can judge ("sort the most green to the top"): look at the offers' preview images, decide the order yourself, and pass the offer ids first-on-top. Offers you leave out (including ones that stream in later) land below the listed ones in the default rank. Pass sort_label with it
ship_to_zipNoDestination US ZIP code, exactly as the user stated it — use this when the user provides their ZIP after a quote priced to the assumed central-US destination (routing.ship_to); the refined prices become theirs. NEVER guess or invent a ZIP
submersibleNo
color_shadesNoNarrow the board to these color SHADES exactly as the quote lists them (color_shades_available / "Colors on this board") — instant, nothing re-prices, the same quote id comes back with only those shades; pass null to show every shade again. Never invent a shade name.
requirementsNoVerbatim context terms from the user — materials, finishes, certifications, tolerances ("UV resistant", "anodized: red", "iso 13485", "tolerance: 0.1mm"). UFP applies what it can and reports what it could not; unresolvable terms are logged for vendor sourcing. Do not interrogate the user to fill this — pass what they said.
thickness_inNoNew sheet thickness in INCHES ("make it in 1/8" → 0.125) — a spec change: sheet lanes requote at the nearest stocked gauge, flagging the substitution when the match isn't close. Pass null to REMOVE a previously asked thickness — back to the material's default gauge
outdoor_ratedNo
max_budget_usdNo
sort_directionNoFlip a sort_by ordering: "desc" reverses the key's natural direction ("most expensive first" = sort_by "price" + "desc"). Only meaningful with sort_by
undo_last_stepNoGO BACK EXACTLY ONE STEP ("undo that", "go back", "put it back how it was"): the network restores the previous quote's stored spec and constraints EXACTLY — never reconstructed from conversation — and re-prices where needed. Send it ALONE (no other args besides quote_id); combining it with changes is rejected. The quote's steps[] names what each undo would take back — steps[0] is the newest. Undo resets the baseline like any unlabeled refine, so open comparison scenarios close. Undoing the original quote is rejected with honest wording — relay it
min_vendor_starsNoOnly vendors whose displayed review rating is at least this many stars (1-5); vendors with no reviews yet are excluded
min_vendor_reviewsNoOnly vendors with at least this many verified-purchase reviews
proven_spec_ordersNoOnly vendors with at least N completed orders for this exact process+material — "a vendor that prints PC reliably"
remove_requirementsNoTake back INDIVIDUAL requirements terms ("drop the anodized ask, keep the rest"): each listed term is removed from the quote's requirements by normalized match, the others stay. Unknown terms are ignored, never an error. Re-stating the requirements list can never drop a term (terms merge as a union) — this is the removal channel

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed2 schema fields changed
    • changedInput schema / properties / color / description
      Previous value: -"New color for this part (spec change — lanes requote). Colour WORDS only ('black', 'green', 'clear'); the network resolves them to each maker's stocked shade, dye, filament or coating — never pass a material or a shade you invented. Pass null to REMOVE a previously asked color — back to vendor defaults"New value: +"New color for this part (spec change — lanes requote). Colour WORDS only ('black', 'green', 'clear'); the network resolves them to each maker's stocked shades, dyes, filaments or coatings — a family word ('blue') brings back EVERY stocked shade of it, and the quote's color_shades_available lists them — never pass a material or a shade you invented. Pass null to REMOVE a previously asked color — back to vendor defaults"
    • addedInput schema / properties / color_shades
      Added value: +{
      +  "anyOf": [
      +    {
      +      "items": {
      +        "maxLength": 48,
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "maxItems": 64,
      +      "type": "array"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "description": "Narrow the board to these color SHADES exactly as the quote lists them (color_shades_available / \"Colors on this board\") — instant, nothing re-prices, the same quote id comes back with only those shades; pass null to show every shade again. Never invent a shade name."
      +}
  2. Changed1 schema field changed
    • changedInput schema / properties / color / description
      Previous value: -"New color for this part (spec change — lanes requote). Pass null to REMOVE a previously asked color — back to vendor defaults"New value: +"New color for this part (spec change — lanes requote). Colour WORDS only ('black', 'green', 'clear'); the network resolves them to each maker's stocked shade, dye, filament or coating — never pass a material or a shade you invented. Pass null to REMOVE a previously asked color — back to vendor defaults"
  3. Changed1 schema field changed
    • changedInput schema / properties / bends / anyOf
      Previous value: -[
      -  {
      -    "anyOf": [
      -      {
      -        "not": {}
      -      },
      -      {
      -        "items": {
      -          "additionalProperties": false,
      -          "properties": {
      -            "angle_deg": {
      -              "exclusiveMaximum": 180,
      -              "exclusiveMinimum": 0,
      -              "type": "number"
      -            },
      -            "direction": {
      -              "enum": [
      -                "up",
      -                "down"
      -              ],
      -              "type": "string"
      -            },
      -            "id": {
      -              "maxLength": 32,
      -              "minLength": 1,
      -              "type": "string"
      -            },
      -            "line": {
      -              "additionalProperties": false,
      -              "properties": {
      -                "p1": {
      -                  "items": [
      -                    {
      -                      "type": "number"
      -                    },
      -                    {
      -                      "type": "number"
      -                    },
      -                    {
      -                      "type": "number"
      -                    }
      -                  ],
      -                  "maxItems": 3,
      -                  "minItems": 3,
      -                  "type": "array"
      -                },
      -                "p2": {
      -                  "items": [
      -                    {
      -                      "type": "number"
      -                    },
      -                    {
      -                      "type": "number"
      -                    },
      -                    {
      -                      "type": "number"
      -                    }
      -                  ],
      -                  "maxItems": 3,
      -                  "minItems": 3,
      -                  "type": "array"
      -                }
      -              },
      -              "required": [
      -                "p1",
      -                "p2"
      -              ],
      -              "type": "object"
      -            },
      -            "radius_mm": {
      -              "exclusiveMinimum": 0,
      -              "type": "number"
      -            }
      -          },
      -          "required": [
      -            "line",
      -            "angle_deg",
      -            "direction"
      -          ],
      -          "type": "object"
      -        },
      -        "maxItems": 50,
      -        "type": "array"
      -      }
      -    ],
      -    "description": "Sheet-metal bend lines, each as TWO POINTS in the part's own mm frame (flat DXF parts use z=0: a bend from (0,12.7) to (76.2,12.7) is p1 [0,12.7,0], p2 [76.2,12.7,0]). angle_deg is the target bend angle (90 = a right-angle flange), direction \"up\"/\"down\" is the fold direction relative to the flat pattern, radius_mm the requested inside radius (omit it — the shop resolves to its tooling and reports what it used). Pass these when the user articulates WHERE the bends go; a bare \"it has 2 bends\" is bend_count, not this."
      -  },
      -  {
      -    "type": "null"
      -  }
      -]New value: +[
      +  {
      +    "anyOf": [
      +      {
      +        "not": {}
      +      },
      +      {
      +        "items": {
      +          "additionalProperties": false,
      +          "properties": {
      +            "angle_deg": {
      +              "exclusiveMaximum": 180,
      +              "exclusiveMinimum": 0,
      +              "type": "number"
      +            },
      +            "direction": {
      +              "enum": [
      +                "up",
      +                "down"
      +              ],
      +              "type": "string"
      +            },
      +            "face_id": {
      +              "type": "integer"
      +            },
      +            "id": {
      +              "maxLength": 32,
      +              "minLength": 1,
      +              "type": "string"
      +            },
      +            "line": {
      +              "additionalProperties": false,
      +              "properties": {
      +                "p1": {
      +                  "items": [
      +                    {
      +                      "type": "number"
      +                    },
      +                    {
      +                      "type": "number"
      +                    },
      +                    {
      +                      "type": "number"
      +                    }
      +                  ],
      +                  "maxItems": 3,
      +                  "minItems": 3,
      +                  "type": "array"
      +                },
      +                "p2": {
      +                  "items": [
      +                    {
      +                      "type": "number"
      +                    },
      +                    {
      +                      "type": "number"
      +                    },
      +                    {
      +                      "type": "number"
      +                    }
      +                  ],
      +                  "maxItems": 3,
      +                  "minItems": 3,
      +                  "type": "array"
      +                }
      +              },
      +              "required": [
      +                "p1",
      +                "p2"
      +              ],
      +              "type": "object"
      +            },
      +            "radius_mm": {
      +              "exclusiveMinimum": 0,
      +              "type": "number"
      +            },
      +            "source": {
      +              "enum": [
      +                "detected",
      +                "user"
      +              ],
      +              "type": "string"
      +            }
      +          },
      +          "required": [
      +            "line",
      +            "angle_deg",
      +            "direction"
      +          ],
      +          "type": "object"
      +        },
      +        "maxItems": 50,
      +        "type": "array"
      +      }
      +    ],
      +    "description": "Sheet-metal bend lines, each as TWO POINTS in the part's own mm frame (flat DXF parts use z=0: a bend from (0,12.7) to (76.2,12.7) is p1 [0,12.7,0], p2 [76.2,12.7,0]). angle_deg is the target bend angle (90 = a right-angle flange), direction \"up\"/\"down\" is the fold direction relative to the flat pattern, radius_mm the requested inside radius (omit it — the shop resolves to its tooling and reports what it used). Pass these when the user articulates WHERE the bends go; a bare \"it has 2 bends\" is bend_count, not this."
      +  },
      +  {
      +    "type": "null"
      +  }
      +]
  4. Changed16 schema fields changed
    • addedInput schema / properties / bends
      Added value: +{
      +  "anyOf": [
      +    {
      +      "anyOf": [
      +        {
      +          "not": {}
      +        },
      +        {
      +          "items": {
      +            "additionalProperties": false,
      +            "properties": {
      +              "angle_deg": {
      +                "exclusiveMaximum": 180,
      +                "exclusiveMinimum": 0,
      +                "type": "number"
      +              },
      +              "direction": {
      +                "enum": [
      +                  "up",
      +                  "down"
      +                ],
      +                "type": "string"
      +              },
      +              "id": {
      +                "maxLength": 32,
      +                "minLength": 1,
      +                "type": "string"
      +              },
      +              "line": {
      +                "additionalProperties": false,
      +                "properties": {
      +                  "p1": {
      +                    "items": [
      +                      {
      +                        "type": "number"
      +                      },
      +                      {
      +                        "type": "number"
      +                      },
      +                      {
      +                        "type": "number"
      +                      }
      +                    ],
      +                    "maxItems": 3,
      +                    "minItems": 3,
      +                    "type": "array"
      +                  },
      +                  "p2": {
      +                    "items": [
      +                      {
      +                        "type": "number"
      +                      },
      +                      {
      +                        "type": "number"
      +                      },
      +                      {
      +                        "type": "number"
      +                      }
      +                    ],
      +                    "maxItems": 3,
      +                    "minItems": 3,
      +                    "type": "array"
      +                  }
      +                },
      +                "required": [
      +                  "p1",
      +                  "p2"
      +                ],
      +                "type": "object"
      +              },
      +              "radius_mm": {
      +                "exclusiveMinimum": 0,
      +                "type": "number"
      +              }
      +            },
      +            "required": [
      +              "line",
      +              "angle_deg",
      +              "direction"
      +            ],
      +            "type": "object"
      +          },
      +          "maxItems": 50,
      +          "type": "array"
      +        }
      +      ],
      +      "description": "Sheet-metal bend lines, each as TWO POINTS in the part's own mm frame (flat DXF parts use z=0: a bend from (0,12.7) to (76.2,12.7) is p1 [0,12.7,0], p2 [76.2,12.7,0]). angle_deg is the target bend angle (90 = a right-angle flange), direction \"up\"/\"down\" is the fold direction relative to the flat pattern, radius_mm the requested inside radius (omit it — the shop resolves to its tooling and reports what it used). Pass these when the user articulates WHERE the bends go; a bare \"it has 2 bends\" is bend_count, not this."
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "description": "New bend records for this part — a spec change: sheet lanes requote with exactly these bends (the list REPLACES the previous one, never patches it). Same shape as on get_fabrication_quote: each bend is two points in the part's own mm frame (flat DXF parts use z=0) plus angle_deg, direction up|down, and an optional requested radius_mm. Pass null to REMOVE every articulated bend"
      +}
    • changedInput schema / properties / color / description
      Previous value: -"New color for this part (spec change — lanes requote)"New value: +"New color for this part (spec change — lanes requote). Pass null to REMOVE a previously asked color — back to vendor defaults"
    • changedInput schema / properties / color / type
      Previous value: -"string"New value: +[
      +  "string",
      +  "null"
      +]
    • changedInput schema / properties / finish / description
      Previous value: -"New surface finish (\"powder coat\", \"anodized\", \"bead blasted\") — a spec change: finish-capable lanes (sheet metal, CNC, metal print) requote WITH it; 3D-print lanes have no coating step, so they ignore the finish but keep the COLOR. A colored finish ask (\"black powder coat\") should set BOTH finish and color, so every lane lands on the buyer's color"New value: +"New surface finish (\"powder coat\", \"anodized\", \"bead blasted\") — a spec change: finish-capable lanes (sheet metal, CNC, metal print) requote WITH it; 3D-print lanes have no coating step, so they ignore the finish but keep the COLOR. A colored finish ask (\"black powder coat\") should set BOTH finish and color, so every lane lands on the buyer's color. Pass null to REMOVE a previously asked finish"
    • changedInput schema / properties / finish / type
      Previous value: -"string"New value: +[
      +  "string",
      +  "null"
      +]
    • addedInput schema / properties / inserts
      Added value: +{
      +  "anyOf": [
      +    {
      +      "anyOf": [
      +        {
      +          "not": {}
      +        },
      +        {
      +          "items": {
      +            "additionalProperties": false,
      +            "properties": {
      +              "axis": {
      +                "items": [
      +                  {
      +                    "type": "number"
      +                  },
      +                  {
      +                    "type": "number"
      +                  },
      +                  {
      +                    "type": "number"
      +                  }
      +                ],
      +                "maxItems": 3,
      +                "minItems": 3,
      +                "type": "array"
      +              },
      +              "depth_mm": {
      +                "exclusiveMinimum": 0,
      +                "type": "number"
      +              },
      +              "drilled_diameter_mm": {
      +                "exclusiveMinimum": 0,
      +                "type": "number"
      +              },
      +              "face_id": {
      +                "type": "integer"
      +              },
      +              "hole": {
      +                "minimum": 1,
      +                "type": "integer"
      +              },
      +              "insert": {
      +                "enum": [
      +                  "nut",
      +                  "flush_nut",
      +                  "standoff",
      +                  "blind_standoff",
      +                  "stud"
      +                ],
      +                "type": "string"
      +              },
      +              "length_mm": {
      +                "exclusiveMinimum": 0,
      +                "type": "number"
      +              },
      +              "located_at_mm": {
      +                "additionalProperties": false,
      +                "properties": {
      +                  "x": {
      +                    "type": "number"
      +                  },
      +                  "y": {
      +                    "type": "number"
      +                  },
      +                  "z": {
      +                    "type": "number"
      +                  }
      +                },
      +                "required": [
      +                  "x",
      +                  "y",
      +                  "z"
      +                ],
      +                "type": "object"
      +              },
      +              "points": {
      +                "items": [
      +                  {
      +                    "type": "number"
      +                  },
      +                  {
      +                    "type": "number"
      +                  },
      +                  {
      +                    "type": "number"
      +                  }
      +                ],
      +                "maxItems": 3,
      +                "minItems": 3,
      +                "type": "array"
      +              },
      +              "thread": {
      +                "maxLength": 32,
      +                "minLength": 1,
      +                "type": "string"
      +              }
      +            },
      +            "required": [
      +              "insert",
      +              "thread"
      +            ],
      +            "type": "object"
      +          },
      +          "maxItems": 200,
      +          "type": "array"
      +        }
      +      ],
      +      "description": "PEM-style hardware inserts pressed into holes of a sheet-metal part — one record per hole. `insert` is the species (nut | flush_nut | standoff | blind_standoff | stud) and `thread` its size (\"M4\", \"1/4-20\"); both are required. When known, add length_mm (standoff/stud post length), the hole's center (located_at_mm, part's own mm frame), its axis, the drilled diameter, and `points` — the signed unit vector the insert's functional side faces (flip = negate). Pass these when the user asks for press-in nuts/standoffs/studs; vendors with a hardware service price them."
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "description": "New hardware-insert records for this part — a spec change: sheet lanes requote with exactly these inserts (the list REPLACES the previous one, never patches it). Same shape as on get_fabrication_quote: species (nut|flush_nut|standoff|blind_standoff|stud) and thread required, hole geometry optional. Pass null to REMOVE every insert"
      +}
    • changedInput schema / properties / material / description
      Previous value: -"New material for this part (\"I need it in PLA\" → \"pla\"). A spec change: lanes requote with this material through warm vendor sessions; an explicit material here replaces the quote's material fan-out. Free-form — unstocked asks resolve to the closest stocked material with a substitution note. Do NOT pass material changes as requirements terms"New value: +"New material for this part (\"I need it in PLA\" → \"pla\"). A spec change: lanes requote with this material through warm vendor sessions; an explicit material here replaces the quote's material fan-out. Free-form — unstocked asks resolve to the closest stocked material with a substitution note. Do NOT pass material changes as requirements terms. Pass null to REMOVE a previously asked material (\"forget the aluminum ask\") — the ask comes off the record and the process-default material fan returns"
    • changedInput schema / properties / material / type
      Previous value: -"string"New value: +[
      +  "string",
      +  "null"
      +]
    • addedInput schema / properties / quantities / anyOf
      Added value: +[
      +  {
      +    "items": {
      +      "exclusiveMinimum": 0,
      +      "type": "integer"
      +    },
      +    "maxItems": 5,
      +    "type": "array"
      +  },
      +  {
      +    "type": "null"
      +  }
      +]
    • changedInput schema / properties / quantities / description
      Previous value: -"New quantities the user wants (spec change — lanes requote at the new quantity). Same rules as on get_fabrication_quote: pass the real ask, never inflate it"New value: +"New quantities the user wants (spec change — lanes requote at the new quantity). Same rules as on get_fabrication_quote: pass the real ask, never inflate it. Pass null to REMOVE a previously asked quantity — the quote returns to single-part pricing"
    • removedInput schema / properties / quantities / items
      Removed value: -{
      -  "exclusiveMinimum": 0,
      -  "type": "integer"
      -}
    • removedInput schema / properties / quantities / maxItems
      Removed value: -5
    • removedInput schema / properties / quantities / type
      Removed value: -"array"
    • addedInput schema / properties / scale
      Added value: +{
      +  "additionalProperties": false,
      +  "description": "Rescale the DESIGN ITSELF before re-quoting: per-axis stretch factors over the file's current geometry (\"make it 2x bigger\" = {\"x\":2,\"y\":2,\"z\":2}). Mesh designs are genuinely converted — the child quote prices a rescaled file; STEP/IGES designs keep their original file with the dimensions riding as callouts (pass those too). {1,1,1} is a no-op",
      +  "properties": {
      +    "x": {
      +      "maximum": 100,
      +      "minimum": 0.01,
      +      "type": "number"
      +    },
      +    "y": {
      +      "maximum": 100,
      +      "minimum": 0.01,
      +      "type": "number"
      +    },
      +    "z": {
      +      "maximum": 100,
      +      "minimum": 0.01,
      +      "type": "number"
      +    }
      +  },
      +  "required": [
      +    "x",
      +    "y",
      +    "z"
      +  ],
      +  "type": "object"
      +}
    • addedInput schema / properties / tapping
      Added value: +{
      +  "anyOf": [
      +    {
      +      "anyOf": [
      +        {
      +          "not": {}
      +        },
      +        {
      +          "items": {
      +            "additionalProperties": false,
      +            "properties": {
      +              "axis": {
      +                "items": [
      +                  {
      +                    "type": "number"
      +                  },
      +                  {
      +                    "type": "number"
      +                  },
      +                  {
      +                    "type": "number"
      +                  }
      +                ],
      +                "maxItems": 3,
      +                "minItems": 3,
      +                "type": "array"
      +              },
      +              "depth_mm": {
      +                "exclusiveMinimum": 0,
      +                "type": "number"
      +              },
      +              "drilled_diameter_mm": {
      +                "exclusiveMinimum": 0,
      +                "type": "number"
      +              },
      +              "face_id": {
      +                "type": "integer"
      +              },
      +              "hole": {
      +                "minimum": 1,
      +                "type": "integer"
      +              },
      +              "located_at_mm": {
      +                "additionalProperties": false,
      +                "properties": {
      +                  "x": {
      +                    "type": "number"
      +                  },
      +                  "y": {
      +                    "type": "number"
      +                  },
      +                  "z": {
      +                    "type": "number"
      +                  }
      +                },
      +                "required": [
      +                  "x",
      +                  "y",
      +                  "z"
      +                ],
      +                "type": "object"
      +              },
      +              "thread": {
      +                "maxLength": 32,
      +                "minLength": 1,
      +                "type": "string"
      +              }
      +            },
      +            "required": [
      +              "thread"
      +            ],
      +            "type": "object"
      +          },
      +          "maxItems": 200,
      +          "type": "array"
      +        }
      +      ],
      +      "description": "Tapped (threaded) holes for a sheet-metal part — one record per hole the user wants threads cut into. `thread` is the callout in the user's words (\"M6\", \"M4 x 0.7\", \"1/4-20\") and is all that's required; when known, add the hole's center in the part's own mm frame (located_at_mm), its unit axis, the pre-tap drilled diameter, and depth_mm so the shop taps the right hole. Pass these when the user asks for threaded/tapped holes; vendors with a tapping service price them."
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "description": "New tapped-hole records for this part — a spec change: sheet lanes requote with exactly these taps (the list REPLACES the previous one, never patches it). Same shape as on get_fabrication_quote: thread callout (\"M6\", \"1/4-20\") required, hole geometry optional. Pass null to REMOVE every tap"
      +}
    • addedInput schema / properties / thickness_in
      Added value: +{
      +  "anyOf": [
      +    {
      +      "exclusiveMinimum": 0,
      +      "maximum": 1,
      +      "type": "number"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "description": "New sheet thickness in INCHES (\"make it in 1/8\" → 0.125) — a spec change: sheet lanes requote at the nearest stocked gauge, flagging the substitution when the match isn't close. Pass null to REMOVE a previously asked thickness — back to the material's default gauge"
      +}
  5. Changed3 schema fields changed
    • addedInput schema / properties / clear
      Added value: +{
      +  "description": "REMOVE constraints entirely (\"drop the deadline\", \"forget the budget\", \"no more food-safe requirement\"): list the constraints to clear and each is removed from the quote — the one deliberate widening besides undo. Clearing a deadline or budget answers instantly from held offers (near-misses convert back); clearing an attribute/reliability/requirements demand re-prices honestly. Same effect as [\"any\"] on the three filter args, extended to every constraint",
      +  "items": {
      +    "enum": [
      +      "deadline",
      +      "budget",
      +      "outdoor_rated",
      +      "submersible",
      +      "high_temp",
      +      "food_safe",
      +      "reliability",
      +      "requirements",
      +      "processes",
      +      "ships_from",
      +      "vendors"
      +    ],
      +    "type": "string"
      +  },
      +  "minItems": 1,
      +  "type": "array"
      +}
    • addedInput schema / properties / remove_requirements
      Added value: +{
      +  "description": "Take back INDIVIDUAL requirements terms (\"drop the anodized ask, keep the rest\"): each listed term is removed from the quote's requirements by normalized match, the others stay. Unknown terms are ignored, never an error. Re-stating the requirements list can never drop a term (terms merge as a union) — this is the removal channel",
      +  "items": {
      +    "maxLength": 120,
      +    "minLength": 1,
      +    "type": "string"
      +  },
      +  "maxItems": 20,
      +  "minItems": 1,
      +  "type": "array"
      +}
    • addedInput schema / properties / undo_last_step
      Added value: +{
      +  "description": "GO BACK EXACTLY ONE STEP (\"undo that\", \"go back\", \"put it back how it was\"): the network restores the previous quote's stored spec and constraints EXACTLY — never reconstructed from conversation — and re-prices where needed. Send it ALONE (no other args besides quote_id); combining it with changes is rejected. The quote's steps[] names what each undo would take back — steps[0] is the newest. Undo resets the baseline like any unlabeled refine, so open comparison scenarios close. Undoing the original quote is rejected with honest wording — relay it",
      +  "type": "boolean"
      +}
  6. Changed1 schema field changed
    • addedInput schema / properties / vendors
      Added value: +{
      +  "description": "Only these specific vendors/makers (\"only show A3D Manufacturing\", \"just Slant 3D and Fictiv\") — an INCLUDE list of vendor names as they appear on offers. A CONSTRAINT like processes: other vendors' offers drop instantly (nothing re-prices), further refines inherit the filter, and [\"any\"] clears it to show every vendor again. Friendly names accepted (\"A3D\", \"slant 3d\"); unmatched names are reported, never an error. This is THE way to answer \"show me everything vendor X offers\" — the filtered quote lists that vendor's complete lineup",
      +  "items": {
      +    "minLength": 1,
      +    "type": "string"
      +  },
      +  "maxItems": 16,
      +  "type": "array"
      +}
  7. Changed1 schema field changed
    • addedInput schema / properties / ships_from
      Added value: +{
      +  "description": "Only vendors that ship from these countries/regions (\"only US vendors\", \"just European shops\", \"keep it domestic\") — an INCLUDE list naming where the user DOES want vendors from. A CONSTRAINT like processes: non-matching vendors drop instantly (nothing re-prices), further refines inherit the filter, and [\"any\"] clears it to show vendors everywhere again. Friendly terms accepted (\"US\", \"Europe\", \"Germany\", \"China\", \"UK\"). Vendors whose origin is unknown or whose network is worldwide (a specific origin cannot be guaranteed) are excluded, each with an honest note. For \"nothing from X\" asks, pass the regions the user does want instead",
      +  "items": {
      +    "minLength": 1,
      +    "type": "string"
      +  },
      +  "maxItems": 8,
      +  "type": "array"
      +}
  8. Changed1 schema field changed
    • addedInput schema / properties / finish
      Added value: +{
      +  "description": "New surface finish (\"powder coat\", \"anodized\", \"bead blasted\") — a spec change: finish-capable lanes (sheet metal, CNC, metal print) requote WITH it; 3D-print lanes have no coating step, so they ignore the finish but keep the COLOR. A colored finish ask (\"black powder coat\") should set BOTH finish and color, so every lane lands on the buyer's color",
      +  "type": "string"
      +}
  9. Changed1 schema field changed
    • changedInput schema / properties / ship_to_zip / description
      Previous value: -"Destination US ZIP code, exactly as the user stated it — use this when the user provides their ZIP after a quote whose delivery dates were estimated for a default destination. NEVER guess or invent a ZIP"New value: +"Destination US ZIP code, exactly as the user stated it — use this when the user provides their ZIP after a quote priced to the assumed central-US destination (routing.ship_to); the refined prices become theirs. NEVER guess or invent a ZIP"
  10. Changed4 schema fields changed
    • addedInput schema / properties / sort_by
      Added value: +{
      +  "description": "\"Organize by\": re-order the quote's offer cards (\"sort by cheapest\" → \"price\"; \"soonest arrival first\" → \"arrival\"; \"best rated\" → \"rating\"; \"total_price\" = part + cheapest shipping; \"recommended\" restores the default price+speed rank). PURE PRESENTATION — answers instantly on the same quote, never re-prices or drops offers, and the ordering sticks across re-reads, streaming, and later refines until changed",
      +  "enum": [
      +    "recommended",
      +    "price",
      +    "unit_price",
      +    "total_price",
      +    "arrival",
      +    "rating"
      +  ],
      +  "type": "string"
      +}
    • addedInput schema / properties / sort_direction
      Added value: +{
      +  "description": "Flip a sort_by ordering: \"desc\" reverses the key's natural direction (\"most expensive first\" = sort_by \"price\" + \"desc\"). Only meaningful with sort_by",
      +  "enum": [
      +    "asc",
      +    "desc"
      +  ],
      +  "type": "string"
      +}
    • addedInput schema / properties / sort_label
      Added value: +{
      +  "description": "Short human wording for a sort_order, displayed on the board (\"most green first\") — required with sort_order, since only you know what your order means",
      +  "maxLength": 60,
      +  "minLength": 1,
      +  "type": "string"
      +}
    • addedInput schema / properties / sort_order
      Added value: +{
      +  "description": "EXPLICIT card order for asks only you can judge (\"sort the most green to the top\"): look at the offers' preview images, decide the order yourself, and pass the offer ids first-on-top. Offers you leave out (including ones that stream in later) land below the listed ones in the default rank. Pass sort_label with it",
      +  "items": {
      +    "minLength": 1,
      +    "type": "string"
      +  },
      +  "maxItems": 200,
      +  "minItems": 1,
      +  "type": "array"
      +}
  11. First observed

TDQS

A4.8/5.0
Behavior5/5

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

No annotations are provided, so the description carries the full burden — and it delivers extensively. It discloses which operations re-price (spec changes, constraint clears) versus which are instant (sorting, vendor/process filters), the max-4 scenario coexistence rule, undo's exact-restore semantics ('never reconstructed from conversation'), substitution notes for unstocked materials, unmatched vendor names being 'reported, never an error', and the ships_from exclusion rule for worldwide/unknown-origin vendors. This is unusually rich behavioral disclosure.

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

Conciseness3/5

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

Information-dense but structurally poor: the description is one multi-hundred-word run-on paragraph stuffed with parentheticals ('no, I meant in sheet metal' → processes, 'only show A3D Manufacturing' → vendors). Every sentence carries real content, so nothing is wasted, but the lack of paragraph breaks or bullets, plus the 'GOING BACK is also this tool' section feeling like an afterthought, makes it hard for an agent to scan. For a 34-parameter tool some length is justified, but this could be organized far better.

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

Completeness5/5

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

For an extremely complex tool (34 params, nested objects, no annotations, no output schema), nothing an agent needs is missing. It covers operation semantics, side-effect behavior (instant drops vs re-prices, warm vendor sessions), edge-case handling (undoing the original quote is 'rejected with honest wording'), and cross-references to other quote fields (steps[], color_shades_available, routing.ship_to) that partially compensate for the absent output schema. Remarkably complete.

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

Parameters5/5

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

Schema coverage is 82% (high), so the baseline is 3, but the description adds meaning the schema structurally cannot: it classifies the 34 args into narrowing vs spec-change (material, color, quantities) vs presentation-only (sort_by, sort_order) vs revert (undo, clear, remove_requirements), and explains inter-param coupling (sort_label required with sort_order, undo must be sent alone, requirement terms merge as a union so remove_requirements is the only removal channel). The material-vs-requirements misclassification caution alone prevents a severe mis-invocation.

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

Purpose5/5

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

States a specific verb+resource — 'Narrow an existing quote' — and enumerates the full operation families: constraint narrowing, spec changes, scenario comparison, sorting, and undo/clear. It distinguishes itself from siblings like get_fabrication_quote (which creates quotes) and finalize_quote/poll_quote by making clear this tool operates on an already-existing quote. An agent can tell exactly what this tool is for.

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

Usage Guidelines5/5

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

Extremely explicit about when to use each path and what NOT to do: 'Changing material/quantity is a spec change, not a narrowing — pass it via the material/color/quantities args, NOT as a requirements term'; 'Send it ALONE... combining it with changes is rejected'. It also gives multi-step guidance, such as re-refining every active scenario label when narrowing processes. No other tool in this batch needs this much routing, and it is delivered.

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

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources