Skip to main content
Glama

Agentic Fabrication Network (AFN)

Server Details

Turn designs into shipped parts: quote 3D printing, CNC, and decals, then check out.

If you are the author of this connector, you can claim ownership by verifying the domain or GitHub account it belongs to. Claimed connector authors can inspect health checks, view analytics, and manage their listing.
Status
Healthy
Uptime
98.8% over 79 days
Last Tested
Transport
Streamable HTTP · MCP 2025-11-25
URL
ChatGPT
–
Claude
–

TDQS

A4.2/5.0

Scored across 13 tools

Disambiguation4/5

The tools mostly target distinct lifecycle stages, and the descriptions explicitly separate quote-related operations. However, the quote surface is crowded (get_fabrication_quote, finalize_quote, preview_quote, refine_quote, poll_quote) and an agent could still misselect among the internal/refresh/re-price variants without very careful reading.

Naming Consistency5/5

All tool names follow a consistent snake_case verb_noun pattern: create_checkout, get_fabrication_quote, refine_quote, list_orders, leave_review, reply_to_maker, etc. There are no mixed conventions or vague standalone verbs.

Tool Count5/5

With 13 tools, the surface is well within the typical 3-15 range and covers distinct quote, order, material, review, and support functions. Two tools are marked internal, but they still correspond to real server rails rather than arbitrary bloat.

Completeness4/5

The set covers the core fabrication lifecycle: capabilities discovery, quoting, refining, checkout, order listing/status, reviews, and maker replies. Minor gaps remain around explicit order cancellation/refund or direct quote retrieval beyond refine_quote re-read, but agents can work around them.

Available Tools

13 tools
create_checkoutCreate checkoutAInspect

Create the order and get a hosted payment link for a chosen offer. Call this as soon as the user picks an offer + shipping speed. This tool takes NO personal details: never ask for — and never pass — a name, address, email, or phone; the secure payment page collects the shipping address, email, and phone (and billing) itself, even when the user volunteered them in chat. Returns checkout_url — give it to the user to pay; UFP places the vendor order automatically after payment.

NameRequiredDescriptionDefault
offer_idYes
return_urlNoExact URL of the page the user is on right now, IF the client application knows it (a web app embedding this tool passes its own page URL). The post-payment page shows a 'Return to <site>' button pointing here. Omit when unknown — never invent one.
coupon_codeNoCoupon code, only if the user provided one (early-adopter codes from the AFN team). Case-insensitive. The discount appears on the payment page; a 100%-off code makes the total $0 with no card required. Never invent or guess a code.
shipping_option_idYesOne of the offer's shipping option ids

TDQS

A4.8/5.0
Behavior5/5

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

Annotations only say it is a non-read-only, non-destructive, closed-world call. The description adds the substantive behavior: no PII is accepted because the hosted page collects address/email/phone, the returned checkout_url is what the user pays with, and the vendor order is placed automatically after payment. That is exactly the context annotations cannot carry.

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

Conciseness4/5

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

Front-loaded with the action and the trigger, then the PII constraint, then the return value — good ordering. Slightly padded by the em-dash aside and the double negative phrasing ('never ask for — and never pass'), though the emphasis is arguably warranted for a high-risk constraint.

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?

No output schema exists, and the description explicitly explains the single meaningful return value (checkout_url) and what happens downstream after payment. Combined with annotations and 75% schema coverage, an agent has everything needed to call this correctly and hand off the result.

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

Parameters4/5

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

Schema coverage is 75% and the schema already documents return_url and coupon_code well (including 'never invent one'). The description reinforces the required pair as 'the offer the user picked' and 'shipping speed' and reinforces the no-PII rule, but does not add meaning for coupon_code or return_url beyond the schema.

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

Purpose5/5

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

States a specific verb and resource plus the outcome ('Create the order and get a hosted payment link for a chosen offer'), which separates it from quote-stage siblings like preview_quote and finalize_quote. An agent can tell exactly what this produces without opening the schema.

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

Usage Guidelines5/5

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

Gives an explicit trigger ('Call this as soon as the user picks an offer + shipping speed') and a hard exclusion that overrides normal assistant behavior (never ask for or pass personal details, even if volunteered). The only missing piece is naming a sibling as the alternative, but the trigger condition is unambiguous.

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

finalize_quoteFinalize quote (wait for remaining vendors)A
Read-only
Inspect

ONLY for the case where a quote response came back with an EMPTY board and told you to call this: waits for the vendors to answer (up to ~40s) and returns their offers as a full board. Call with just quote_id, immediately, and say nothing substantive before it. NEVER call it on a response that already listed offers — that board is final, and this would add nothing.

NameRequiredDescriptionDefault
quote_idYesQuote id from the still-quoting response

TDQS

A4.7/5.0
Behavior5/5

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

Annotations already declare readOnlyHint=true and destructiveHint=false, so safety is covered; the description adds latency (~40s wait), the async nature (awaits vendor answers), the result shape (full board), and even a conversational constraint ('say nothing substantive before it'). It discloses behavioral traits well beyond the annotations and is fully consistent with them.

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

Conciseness5/5

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

Front-loads the ONLY precondition, then the wait/return behavior, then the NEVER exclusion. Three tight clauses, no filler, each earning its place.

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

Completeness5/5

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

For a one-parameter, read-only, no-output-schema tool, the description covers precondition, timing, return content, and invocation style. Nothing an agent needs to call it correctly is missing.

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

Parameters3/5

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

Schema coverage is 100% and there is a single documented parameter, so the schema carries the semantic load. The description reinforces the call shape ('Call with just quote_id') but adds no syntax or format detail beyond the schema, matching the baseline for high coverage.

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 (waits for remaining vendors and returns their offers as a full board), and the empty-board precondition cleanly separates it from siblings like poll_quote and preview_quote. An agent knows exactly what this does and when it applies without opening the schema.

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

Usage Guidelines5/5

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

Explicit when-to-use ('ONLY for the case where a quote response came back with an EMPTY board and told you to call this') and when-not-to-use ('NEVER call it on a response that already listed offers — that board is final'). Both directions and the triggering signal are stated, 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.

get_fabrication_quoteGet fabrication quoteAInspect

Get ranked, purchasable offers (price, ETA, preview image) for fabricating a physical item from a design file. process=fdm_print for 3D printing a model (STL/OBJ/PLY/3MF/AMF/STEP/IGES), process=cnc or process=sheetmetal for machined/bent metal parts (STEP, IGES, DXF), process=decal for stickers/decals from artwork (any common image or design file — PNG/JPG/HEIC/TIFF/GIF/BMP/WEBP/AVIF/SVG/PDF/AI/EPS/PSD/CDR, auto-converted). A .ufp file (UFP part container: the design plus saved spec/constraints in one) is accepted anywhere a design file is — its saved intent applies automatically and anything the user states now wins. If the user just drops a file and asks for a price, omit process — UFP routes it. Provide the design either as design_file (an image/file the user attached or you generated — preferred) or file_url (a public URL). REORDERS: if the user has a UFP part number (from a receipt email or a previous session, looks like UFP-… or part_…), pass it as part_number INSTEAD of any file — the stored design and spec are reused and re-shopped across all current vendors. Locked parts additionally require share_key (from the owner's share link). Returns offers across vendors like Google Flights returns flights.

NameRequiredDescriptionDefault
cutNoDecal cut style — pass the user's words verbatim ("triangle", "die cut", "circle"). Known: contour|square|oval|kiss_cut; anything else gets closest-match offers with a substitution note. Omit to compare the main options
sizeNoPrint size — pass the user's words verbatim ("letter", "24x36", "half letter"). Cards are 3.5x2; flyers 8.5x5.5|8.5x11|11x17; posters 12x18 through 36x48. Unknown sizes get closest-match offers
bendsNoSheet-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.
colorNoONLY a color the user actually asked for — NEVER pick one for them. fdm_print: Filament color for fdm_print (e.g. black, red); resin_print: Resin color for resin_print (e.g. gray, white, black); powder_print: Powder part color: raw gray/white, or a dye ("black", "dark blue") — vendor-resolved; elastomer_print: Elastomer part color — VCJ parts ship raw; asks resolve with an honest substitution note; cnc: Colour for cnc: with finish anodized it is the anodize colour, otherwise the stock's own colour (black Delrin, clear acrylic). Colour WORDS only; each maker resolves the shade and says what it landed on; laser_cut: Colour of the flat stock for laser_cut (black, clear, natural…). Colour WORDS only; each maker quotes the materials it stocks in that colour and drops the ones that cannot be it; print: Print color ask ("full color", "black and white"). Vendors that only price full color note the substitution; apparel: Garment color for apparel ("black", "heather gray") — vendor-resolved
paperNoPaper stock — free-form ("matte", "glossy", "recycled", "14pt"). Resolved to the closest stock the vendor runs
sidesNosingle|double sided printing (defaults: cards double, flyers/posters single)
unitsNosheetmetal: DXF drawing units: "mm" (default) or "in". STEP files carry their own units; laser_cut: DXF drawing units: "mm" (default) or "in"
finishNocnc: CNC surface finish: standard|anodized|polished|bead_blasted (default standard); sheetmetal: as_cut (default) | deburred | anodized | powder_coat — anodized is aluminum-only; powder coat protects mild steel for outdoor use
insertsNoPEM-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.
processNoWhat to fabricate. If the user just drops a file and asks for a price, OMIT this — UFP detects the file type (artwork, mesh — STL/OBJ/PLY/3MF/AMF, BREP — STEP/IGES, DXF) and routes it to every process that can make it; the response's routing.also_possible lists processes UFP can't quote yet
productNoprint: Print product kind: business_cards|flyers|posters. Omit to quote every kind the artwork fits; apparel: apparel: t_shirt|hoodie|long_sleeve|tank_top (free-form — "tee", "crewneck" resolve to the closest product)
shore_aNoNumeric Shore A durometer ask (10-95, e.g. 40). Resolved to the NEAREST stocked durometer with a substitution note — never a silent swap
tappingNoTapped (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.
vendorsNoOnly these specific vendors/makers ("just quote Slant 3D") — an INCLUDE list of vendor names as they appear on offers. Friendly names accepted ("A3D", "slant 3d"); unmatched names are reported, never an error. Usually OMIT: pass it only when the user explicitly names the vendors they want
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
file_urlNoPublic URL of the design file — only when the design lives at a URL
materialNoONLY a material the user actually asked for — NEVER guess or default one (a silent "pla" on a bare file drop prunes every maker that does not stock it; OMIT instead and each process quotes across its stocked materials so every maker can bid). fdm_print: pla|petg|asa (free-form — "abs", "polycarbonate" asks resolve to the closest stocked filament with a substitution note); resin_print: standard|tough|high_temp|high_detail resin (free-form asks resolve to the closest supported resin); powder_print: Powder-bed nylon: nylon_12|nylon_12_smooth|nylon_11|nylon_12_gf|nylon_12_esd|nylon_12_white|nylon_pa2200|nylon_12_sls|tpu (free-form — "PA12", "glass filled" resolve to the closest stocked powder); elastomer_print: Jetted elastomer: tepu_30a|tepu_50a (free-form — "TPU", "soft rubber" resolve to the closest stocked durometer); cnc: aluminum_6061|aluminum_7075|stainless_304|titanium|brass|acetal|delrin|abs|nylon_pa6|peek|acrylic (free-form asks resolve to the closest supported stock); sheetmetal: mild_steel|aluminum_5052|stainless_304 (free-form — "steel", "5052", "stainless" resolve; unknown asks get closest-match offers). Omit to compare the defaults; laser_cut: acrylic|plywood|mdf|delrin|uhmw|hdpe|g10|carbon_fiber|mild_steel|aluminum_5052|stainless_304 (free-form — "plexiglass", "birch" resolve; unknown asks get closest-match offers); decal: vinyl|holographic|transparent|glitter (free-form — "chrome" etc. gets closest matches)
width_inNoDecal width in inches (default 3)
food_safeNoMust be vendor-certified food safe
height_inNoDecal height in inches (default 3)
high_tempNoMust tolerate sustained heat (vendor heat-resistance claim)
placementNoPrint placement for apparel: front (default) | back | front_back
processesNoOnly quote these fabrication processes — a constraint that narrows the auto-routing fan. Friendly terms accepted ("sheet metal", "3d printing", "cnc", "laser"); unmappable terms are reported, never an error. Usually OMIT: auto-routing quotes every process that can make the file. Pass it only when the user explicitly limits the process
share_keyNoShare key for a LOCKED part — the k=… value from the owner's share link (…/part/UFP-…?k=KEY). Required with part_number when the part is locked; omit otherwise
bend_countNoNumber of bends in the design (bend lines must be in the file). Prices CNC bending; omit for flat parts
quantitiesNoQuantities the user actually wants — pass [1] or [2] if that's the ask. Vendors with a higher minimum quote AT their minimum and the offer notes it (requested_quantity). Default: 25 for decals, 1 for prints; a part_number reorder defaults to the quantity last purchased
ships_fromNoOnly vendors that ship from these countries/regions ("only US vendors", "keep it domestic") — an INCLUDE list. Friendly terms accepted ("US", "Europe", "Germany", "China", "UK"); unmappable terms are reported, never an error. Vendors whose origin is unknown or whose network is worldwide (origin not guaranteed) are excluded, each with a note saying why. Usually OMIT: pass it only when the user explicitly limits where vendors ship from
design_fileNoThe design file itself (user-attached or generated image/STL). ChatGPT supplies the file reference automatically when the user attached a file — just bind the attachment here. Other clients may pass a data: URL (base64) or a public https URL string. Preferred over file_url.
metal_alloyNoMetal AM alloy: stainless_316l|stainless_17_4ph|titanium_ti64|aluminum_alsi10mg|inconel_718|cobalt_chrome|tool_steel_h13|copper (free-form asks like "Ti-6Al-4V" resolve to the closest stocked powder)
part_numberNoUFP part number from a previous paid order (UFP-… or part_…). Reorders: replaces design_file/file_url entirely; any other fields provided override the stored spec
ship_to_zipNoDestination US ZIP code, exactly as the user stated it. OMIT if the user has not given one — NEVER guess or invent a ZIP. Without it, prices come back all-in with shipping to an assumed central-US destination, flagged on routing.ship_to
submersibleNoMust survive submersion in water
metal_finishNoMetal AM post-processing: as_printed|bead_blast|machined_critical|polished|heat_treated (as_printed keeps support witness marks)
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_inNosheetmetal: Sheet thickness in inches (e.g. 0.063 = 14 ga aluminum). Quoted at the nearest stocked thickness; omit for ~16 ga default; laser_cut: Nominal thickness in inches; quoted at the vendor's nearest stocked thickness. Omit for the material's common stock
outdoor_ratedNoMust survive outdoor exposure
powder_finishNoPowder post-processing: as_printed (raw powder surface) | vapor_polished | polished
max_budget_usdNoHard budget cap in USD, all-in
attachment_urlsNoAdditional files for the SAME part — the PDF drawing next to the STEP, spec sheets, BOMs. Pass everything the user gave you; UFP works out which file is the part and which are supporting documents.
elastomer_finishNoElastomer post-processing: as_printed (VCJ parts ship raw — the whole lane today)
metal_technologyNoMetal AM process: laser_powder_bed (SLM/DMLS/LPBF)|binder_jet|ebm. Omit to let the vendor pick its default for the alloy
min_vendor_starsNoOnly vendors whose displayed review rating is at least this many stars (1-5). Vendors with no reviews yet are excluded — the filter demands demonstrated quality
powder_technologyNoPowder process: mjf (HP Multi Jet Fusion) | sls (laser sintering). Omit to let the vendor pick its default lane for the material
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"
elastomer_technologyNoElastomer process: vapor_cure_jetting (VCJ). Omit to let the vendor pick its default lane for the material

TDQS

A3.7/5.0
Behavior4/5

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

Annotations only cover the safety profile (readOnlyHint=false, destructiveHint=false, openWorldHint=false). The description meaningfully extends this: substitution notes for unknown sizes/materials, unmappable terms reported 'never an error', assumed central-US shipping when ship_to_zip is omitted, and routing.also_possible for unsupported processes. It stops short of stating auth needs, rate limits, or that a quote resource is created.

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?

It is front-loaded and information-dense with no filler prose, which is good. However it is a single wall of text, and whole clauses (the STL/OBJ/PLY/3MF/AMF/STEP/IGES and image-format enumerations, the repeat of the reorder mechanism) restate what the schema already documents, so not every sentence earns its place.

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

Completeness4/5

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

For a 47-parameter tool with no output schema, the description covers the essentials: what comes back, how reorders and locked parts work, how auto-routing behaves, and how unknown inputs degrade gracefully. The remaining gap is the relationship to the finalize/poll/refine siblings, which an agent in a multi-step quoting flow would need.

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

Parameters4/5

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

Schema coverage is 100%, so the baseline is 3, but the description earns above baseline by consolidating cross-parameter priority logic across 47 fields: design_file is 'preferred' over file_url, part_number replaces the file entirely for reorders, and omission of process triggers UFP auto-routing. That decision framing is not obvious from the individual per-parameter schema strings.

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

Purpose4/5

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

The first sentence states a specific verb and resource with the return content spelled out ('ranked, purchasable offers (price, ETA, preview image) for fabricating a physical item from a design file'). It further clarifies scope via process routing and reorder handling. However, it never distinguishes itself from the quote-lifecycle siblings (preview_quote, refine_quote, poll_quote, finalize_quote), so an agent still cannot tell from the description alone which quote tool to pick.

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

Usage Guidelines3/5

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

It gives clear in-tool context: omit process on a bare file drop, use part_number for reorders, use share_key for locked parts. But it offers no when-to-use/when-not guidance relative to the alternative quote tools, so the selection decision is implied rather than stated.

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

get_material_guideGet material guideA
Read-only
Inspect

Honest, cited material intelligence for material-choice / strength / durability / heat / outdoor questions ("my PLA part broke, what's stronger?", "will this survive outdoors?"). Returns caveats-FIRST facts: published specs (tensile, heat-deflection, UV/outdoor, chemical) each tagged vendor-cited vs general engineering knowledge, "stronger/tougher/hotter than X" ladders (PLA→PETG→ABS/ASA→nylon/PC→metals), and finish/coating options. Call it BEFORE answering such a question, then relay the facts. It supplies FACTS ONLY — comparative specs and vendor-admitted caveats, never a fitness-for-purpose or safety guarantee (that stays your judgment boundary); name express vendor claims "advertised", not "certified".

NameRequiredDescriptionDefault
processNoA UFP process to scope to ("fdm_print", "resin_print", "cnc", "sheetmetal", "laser_cut") — lists the materials that process makes
materialNoA material the user named or you are weighing ("PLA", "6061 aluminum", "stainless") — free-form; a family ask like "stainless" returns the whole family
questionNoThe user's raw question — mined for intent (stronger/tougher, heat/hot, outdoor/UV) so the right ladder is surfaced

TDQS

A4.4/5.0
Behavior4/5

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

Annotations cover the safety profile (readOnly, non-destructive, closed-world), so the bar is lower, yet the description adds real substance: output is caveats-first, each fact is tagged vendor-cited vs general engineering knowledge, and the tool refuses judgment calls. It doesn't discuss freshness, coverage gaps, or latency, but for a static knowledge lookup that is minor.

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

Conciseness4/5

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

Front-loaded with purpose and use-case in the first clause, and every sentence carries a distinct obligation (call timing, output shape, judgment boundary, terminology). It is dense with parentheticals and slightly over-packed, but nothing is filler.

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

Completeness5/5

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

With no output schema, the description must convey return content, and it does: caveats-first specs, comparison ladders, finish/coating options, and the epistemic tagging of each fact. Nothing an agent needs to call and correctly relay this tool is missing.

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

Parameters3/5

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

Schema description coverage is 100% and every parameter already documents its own semantics (process enum-like values, free-form material with family behavior, question intent mining). The description reinforces intent but adds no syntax or format detail beyond the schema, so baseline 3 applies.

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

Purpose5/5

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

States a specific verb and resource ('material intelligence for material-choice / strength / durability / heat / outdoor questions') and immediately gives the question class it serves, with concrete examples. No sibling tool covers this ground, so an agent can distinguish it without opening any schema.

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

Usage Guidelines5/5

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

Explicit timing instruction ('Call it BEFORE answering such a question, then relay the facts') plus an explicit scope boundary (facts only, never fitness-for-purpose or safety guarantees) and even phrasing guidance ('advertised', not 'certified'). When-to-use and when-not-to-overstep are both stated.

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

get_network_capabilitiesNetwork capabilitiesA
Read-only
Inspect

The LIVE catalog of what the fabrication network can do RIGHT NOW — no quote needed. Returns the services ledger (tapping, inserts, welding, bending, finishes… with each shop's own size/material/thickness windows), the network's sheet gauge ladder, the stocked hardware combinations (species x thread) with stocked lengths and shop counts — the most-stocked length is the steering default for an unspecified length — the finish options with their stocked color menus, and per-process manufacturability rules. This is live state, not a spec sheet: it changes as connectors join, leave, or have capability branches toggled, so call it fresh when the user asks what's possible (materials, gauges, hardware, colors, services) rather than answering from memory.

NameRequiredDescriptionDefault
processNoAdvisory scope ("sheetmetal") — v1 returns the whole catalog either way; filter what you relay

TDQS

A4.2/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=true and destructiveHint=false, so the safety profile is covered. The description adds real behavioral context beyond that: this is live, mutating state that changes as connectors join/leave or capabilities are toggled, and it discloses a built-in steering default (most-stocked length). It omits auth/permission and response-format details, keeping it at a solid 4.

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

Conciseness4/5

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

Front-loaded with the key claim ('LIVE catalog... no quote needed') and every clause carries real content about the return payload. The long parenthetical enumerations are dense but informative rather than filler.

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

Completeness5/5

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

With no output schema, the description carries the full burden of describing return contents and does so thoroughly: services ledger, gauge ladder, stocked hardware combos with lengths and shop counts, finish color menus, and process rules. Combined with the volatility warning, an agent has everything needed to invoke and interpret it.

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

Parameters3/5

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

The single 'process' parameter is fully documented in the schema (100% coverage), which already explains it is advisory and that v1 returns the whole catalog regardless. The description adds no further parameter detail, so the schema-does-the-work baseline of 3 applies.

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

Purpose5/5

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

States a specific verb+resource ('LIVE catalog of what the fabrication network can do') and enumerates exactly what it returns — services ledger, gauge ladder, stocked hardware, finish colors, manufacturability rules. This clearly distinguishes it from siblings like get_material_guide, get_shop_gauges, and get_fabrication_quote.

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

Usage Guidelines4/5

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

Gives explicit context for use: 'call it fresh when the user asks what's possible (materials, gauges, hardware, colors, services) rather than answering from memory,' and distinguishes it from quoting flows via 'no quote needed.' It does not name a specific alternative sibling to use instead, so it falls short of a full when/when-not routing statement.

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

get_order_statusGet order statusA
Read-only
Inspect

Check status, ETA and tracking for a UFP order.

NameRequiredDescriptionDefault
order_idYes

TDQS

A3.6/5.0
Behavior4/5

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

Annotations already establish readOnly, non-destructive, closed-world behavior, so the safety profile is covered. The description adds genuine value by disclosing what the call returns (status, ETA, tracking) despite there being no output schema, though it says nothing about error behavior for unknown order IDs or auth requirements.

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

Conciseness5/5

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

One short sentence, front-loaded with the action and resource and with no filler. Every word earns its place.

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

Completeness4/5

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

For a one-parameter read tool whose annotations already cover the safety profile and which has no output schema, naming the returned fields makes the definition nearly self-sufficient. The only real gap is how to supply or obtain a valid order_id.

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

Parameters2/5

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

Schema coverage is 0% and the single order_id parameter is completely undocumented in both schema and description. The description does not state the ID's format, source, or where an agent obtains it, so it fails to compensate for the coverage gap.

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

Purpose4/5

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

The description uses a specific verb ('Check') against a specific resource ('a UFP order') and enumerates the returned facets (status, ETA, tracking). The singular 'an order' implicitly contrasts with the sibling list_orders, but no sibling is named explicitly.

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

Usage Guidelines3/5

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

The requirement for a single known order_id is implied, which weakly separates this from list_orders for discovery. There is no explicit when-to-use, when-not-to-use, or named alternative, so guidance stays at the implied level.

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

get_shop_gaugesA shop's stocked sheet gaugesA
Read-only
Inspect

Every sheet thickness (gauge) ONE named shop stocks right now, per material — read live off the shop's declared catalog, no quote needed. Call it when the user asks what thicknesses/gauges a specific maker carries ("what thicknesses does SendCutSend have in mild steel?"). For the whole network's ladder use get_network_capabilities instead. Never answer a gauge question from memory.

NameRequiredDescriptionDefault
shopYesThe shop as the user or the offer cards name it ("SendCutSend", "sendcutsend")
materialNoAdvisory: narrow the relayed list to one material ("mild steel", "5052")

TDQS

A4.7/5.0
Behavior4/5

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

Annotations already cover the safety profile (readOnly, non-destructive, closed-world), and the description adds real context beyond them: the data is read live from the shop's declared catalog and requires no quote. It stops short of describing the shape of the relayed list or any freshness/caching caveats.

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

Conciseness5/5

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

Three tight sentences: scope first, then the trigger, then the exclusion and the anti-hallucination rule. No filler and nothing buried.

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

Completeness5/5

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

For a read-only two-parameter lookup with no output schema, everything an agent needs is present: what it returns conceptually (gauges per material for one shop), when to call it, when to call the sibling, and the no-memory constraint.

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

Parameters4/5

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

Schema coverage is 100%, so the baseline is 3, but the description adds meaning: 'shop' must be a single named maker (as the user or offer cards name it) and 'material' narrows the relayed list rather than being required, reinforcing the schema's advisory note.

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

Purpose5/5

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

States a specific verb and resource ('every sheet thickness a named shop stocks right now, per material') and explicitly scopes it to ONE shop, which cleanly separates it from the network-wide sibling get_network_capabilities.

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

Usage Guidelines5/5

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

Gives an explicit trigger with a sample user utterance ('what thicknesses does SendCutSend have in mild steel?'), names the alternative tool and the condition that selects it, and adds a hard directive ('Never answer a gauge question from memory').

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

leave_reviewLeave vendor reviewA
Destructive
Inspect

Record the user's verified-purchase review of how a UFP order turned out. YOUR JOB IS TO STRUCTURE THE FEEDBACK: turn what the user actually said into stars (1-5 overall) and facet scores — "the cut was sloppy" -> quality, "parts arrived 2 days late" -> timeliness, "wrong color" -> accuracy. Keep the optional comment to a short factual summary of their words; never embellish. ALWAYS draft the review (stars, facets, comment) and confirm it with the user BEFORE calling this tool — e.g. "I'll rate this 2 stars with timeliness 1 because it arrived 2 days late — send it?". One review per order: submitting again updates the existing review. Use list_orders first if you need to resolve which order they mean.

NameRequiredDescriptionDefault
starsYesOverall rating the user confirmed, 1-5
claimsNoCHECKABLE claims from the user's feedback — the network stamps each against its own records (the ordered spec, polled tracking + delivery events) and attaches evidence chips to the review. Only pass what the user actually asserted.
facetsNoScore only the facets the user actually spoke to
commentNoShort factual summary of the user's feedback, in their spirit — optional
order_idYesThe UFP order being reviewed (ord_…) — see list_orders

TDQS

A4.7/5.0
Behavior5/5

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

Annotations declare the mutation profile (readOnlyHint=false, destructiveHint=true), which is consistent with the description's disclosure that re-submitting overwrites/updates the existing review. Beyond that, the description adds workflow-critical behavior the annotations cannot convey: the mandatory draft-and-confirm step, the fact that checkable claims are stamped against network records with evidence chips, and a strict no-embellishment rule for the comment.

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

Conciseness4/5

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

Front-loaded with purpose and the structuring instruction, and every sentence carries operational weight (mapping example, confirmation requirement, overwrite semantics, order resolution). It is on the long side with two quoted examples, but none are filler given the ambiguity of natural-language-to-facet conversion.

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

Completeness4/5

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

For a mutation tool with nested params, 100% schema coverage, and no output schema, the description supplies the missing pieces: the confirm-before-send workflow, overwrite-on-resubmit semantics, and that evidence chips are attached server-side. Return values are not explained but an output schema is absent and the key side effect (review creation/update with evidence) is disclosed.

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

Parameters4/5

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

Schema coverage is 100%, so the baseline is 3, but the description adds real interpretive value: it maps natural-language complaints ("cut was sloppy", "arrived 2 days late", "wrong color") onto the quality/timeliness/accuracy facets and illustrates how claims should be derived ("never showed up" -> not_delivered). It does not add much on order_id beyond pointing at list_orders, but the facet/claim mapping guidance exceeds the schema text.

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 (record a verified-purchase review of a UFP order) and immediately frames the agent's task: converting free-text feedback into stars and facet scores. This is unambiguous and clearly distinct from sibling tools like get_order_status or reply_to_maker.

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

Usage Guidelines5/5

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

Explicitly says when to use it (after the user reports how an order turned out), what to do first (draft and confirm with the user before calling), how to resolve ambiguity (use list_orders to find the order), and what happens on repeat calls (one review per order, resubmission updates). Both alternatives and preconditions are covered.

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

list_ordersList recent ordersA
Read-only
Inspect

List this agent's recent UFP orders (newest first): order id, what was made, vendor, status, total, ETA, created date. Use it to resolve vague references — "my sticker order", "that order from 6 days ago" — to a concrete order_id before calling get_order_status or leave_review.

NameRequiredDescriptionDefault

No parameters

TDQS

A4.6/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=true, destructiveHint=false and a closed world, so the safety profile is covered. The description adds real value beyond them: it scopes results to 'this agent's' orders, specifies newest-first ordering, and enumerates the returned fields, which matters since there is no output schema. It stops short of saying how many orders are returned or whether the list is truncated.

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

Conciseness5/5

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

Two sentences, no filler. The purpose and returned fields come first, and the routing guidance to get_order_status/leave_review is front-loaded where an agent will act on it.

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

Completeness4/5

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

With no output schema, the description correctly compensates by listing the fields returned, and annotations carry the safety profile. The remaining gap is that the agent cannot tell how many orders come back or whether the list is bounded, which matters for a no-parameter list tool.

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

Parameters4/5

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

The tool takes zero parameters, so the baseline of 4 applies; there is no parameter semantics for the description to clarify. Note the description's implicit filtering (this agent's orders, recency) is behavioral scope rather than a parameter, and the agent cannot control it.

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

Purpose5/5

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

States a specific verb and resource ('List this agent's recent UFP orders'), adds scope (newest first) and enumerates the exact fields returned (order id, item, vendor, status, total, ETA, created date). This clearly separates it from sibling get_order_status, which returns a single order.

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

Usage Guidelines5/5

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

Explicitly states the use case — resolving vague references like 'my sticker order' to a concrete order_id — and names the two downstream tools it feeds (get_order_status, leave_review). The when-to-use condition is concrete and testable.

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

poll_quotePoll quote (board internal)A
Read-only
Inspect

INTERNAL — the offer board calls this to refresh itself while vendors finish pricing. Never call this yourself. The board you were given is already final for its turn; do not reach for refine_quote to look at it again either, that paints a duplicate board.

NameRequiredDescriptionDefault
quote_idYesQuote id the board is watching

TDQS

A4.2/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=true, destructiveHint=false and a closed world, so safety is covered structurally. The description adds context annotations cannot express: the tool is invoked internally by the offer board, the board is already final for the current turn, and calling refine_quote as a workaround 'paints a duplicate board' — a side-effect warning that is genuinely valuable. It does not describe any return payload, which is the only real gap.

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

Conciseness5/5

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

Three tight sentences, front-loaded with the 'INTERNAL' marker and the prohibition before the rationale. Nothing is padded, and each sentence changes agent behavior (don't call it; don't substitute refine_quote; here's why).

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

Completeness4/5

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

For a one-parameter tool with no output schema, the description supplies the decisive context an agent needs — that this is an internal lifecycle call it should never make. Return-value detail is absent, but since the intended behavior is not to invoke it at all, that omission matters little.

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

Parameters3/5

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

There is a single required parameter with 100% schema description coverage ('Quote id the board is watching'), and the description adds no syntax, format, or sourcing detail beyond that. Per the rubric, a fully documented single parameter establishes a baseline of 3.

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

Purpose4/5

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

The description states a specific function — the offer board invokes this to refresh itself while vendors are still pricing a quote — which is more than a restatement of the name 'poll_quote'. It also implicitly distinguishes itself from the sibling refine_quote by warning against using that as a substitute. It stops short of saying exactly what state the poll observes or returns, but the purpose is unmistakable.

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?

This is the strongest dimension: 'Never call this yourself' is an unambiguous when-not-to-use rule, and the description names the specific wrong alternative ('do not reach for refine_quote to look at it again') plus the reason (the board is already final for its turn). An agent has everything it needs to avoid a misuse.

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

preview_quotePreview quote routing (soft quote)A
Read-only
Inspect

INTERNAL client rail — the routing half of refine_quote with NOTHING committed: takes the same arguments as refine_quote and answers how many distinct fabricators (and which process lanes) the network WOULD ask for the refined part, plus the exclusion notes, without creating a child quote, asking any vendor, superseding in-flight work, or logging demand. An expectation, never a promise — lanes can still decline once asked. Never call this to look at prices; it carries none. Use refine_quote to actually re-price.

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

TDQS

A4.5/5.0
Behavior5/5

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

Annotations already declare readOnlyHint=true, destructiveHint=false, openWorldHint=false, but the description adds rich context beyond them: nothing committed, no child quote created, no vendor asked, no in-flight work superseded, no demand logged. It also flags the result is 'an expectation, never a promise' since lanes can decline — genuine 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.

Conciseness4/5

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

Front-loaded with the core distinction ('routing half of refine_quote with NOTHING committed') before elaborating. It is somewhat dense and em-dash heavy, but each clause carries information — the commitment guarantees, the promise caveat, and the price exclusion all matter.

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

Completeness4/5

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

For a 34-parameter tool with no output schema, the description usefully sketches the return ('how many distinct fabricators... plus the exclusion notes'). Combined with the readOnly annotations and 82% schema coverage, an agent has what it needs to invoke it correctly, though it doesn't detail the response shape beyond the headline fields.

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

Parameters3/5

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

Schema description coverage is 82%, so the schema already documents the 34 parameters thoroughly and the baseline is 3. The description's 'takes the same arguments as refine_quote' is a useful cross-reference that lets the agent reuse prior understanding, but it adds no per-parameter meaning beyond what the schema provides.

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

Purpose5/5

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

States a specific verb and resource ('routing half of refine_quote') and precisely scopes what it returns: how many distinct fabricators and which process lanes the network WOULD ask, plus exclusion notes. It explicitly distinguishes itself from the sibling refine_quote, so an agent can pick between them without opening either schema.

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

Usage Guidelines5/5

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

Gives explicit positive and negative routing: 'Use refine_quote to actually re-price' and 'Never call this to look at prices; it carries none.' When-to-use and when-not-to-use are both stated, 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.

refine_quoteRefine quoteAInspect

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).

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

TDQS

A4.6/5.0
Behavior5/5

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

Annotations only give readOnlyHint=false/destructiveHint=false/openWorldHint=false, but the description goes far beyond: it discloses that spec changes 're-price through warm vendor sessions,' that clearing deadline/budget answers instantly from held offers while attribute clears 're-price honestly,' that sorts are presentation-only and persist across re-reads, that scenarios coexist (max 4), and that undo restores stored state exactly and resets the baseline. This is unusually rich behavioral context.

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?

Purpose is front-loaded and the length is partly justified by 34 parameters and many distinct modes, but the body is a dense run-on of em-dashes and parentheticals that buries important branches (undo, clear) mid-paragraph. Every clause arguably earns its place, yet the structure makes sequential scanning harder than it needs to be.

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

Completeness4/5

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

For a no-output-schema, 34-parameter mutation tool, the description covers the high-risk behaviors an agent must get right: spec-change vs constraint, undo semantics, scenario handling, and sort persistence. Some secondary parameters rely entirely on schema text, but the description is largely sufficient for correct invocation.

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

Parameters4/5

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

Schema description coverage is 82%, so the baseline is 3, but the description adds genuine routing semantics: distinguishing requirements terms from the material/color/quantities args, defining scenario coexistence, explaining undo's interaction with scenarios, and clarifying the include-list behavior of processes/ships_from/vendors. It does not add meaning for every parameter (e.g. min_vendor_stars, min_vendor_reviews, proven_spec_orders only exist in-schema), so it stops short of a 5.

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

Purpose5/5

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

The opening states a specific verb+resource+scope: 'Narrow an existing quote with new constraints ... or CHANGE its spec,' and it explicitly draws the line between narrowing and spec changes. It also distinguishes itself from siblings by naming what it is not (a new quote) and by using get_fabrication_quote as the shape reference, so an agent can route correctly without opening the schema.

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

Usage Guidelines5/5

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

It routes real user utterances to the right argument across every major branch: narrowing vs spec change ('pass it via material/color/quantities, NOT as a requirements term'), comparison scenarios, sorting, going back, and re-reading. The explicit when-to-use guidance and the mapping of ambiguous phrasings ('no, I meant in sheet metal') leave little to inference.

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

reply_to_makerReply to the makerA
Destructive
Inspect

Send the user's answer to a question the maker (vendor) asked about a UFP order — get_order_status surfaces an open question when one is waiting. Confirm the answer with the user before sending. The network relays it: the maker sees plain text from the network account with the user's contact details and links stripped, so never include emails, phone numbers, or URLs the answer depends on.

NameRequiredDescriptionDefault
messageYesThe user's answer, in their words — it is relayed to the maker
order_idYesThe UFP order the maker asked about (ord_…)

TDQS

A4.7/5.0
Behavior4/5

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

Annotations already flag destructiveHint=true, so the agent knows this is a mutating, non-undoable send; the description goes further by disclosing the relay mechanics (maker sees plain text from the network account, contact details and links stripped) and derives a hard content constraint from it. It does not state delivery latency, failure modes, or whether a reply can be retracted, 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.

Conciseness5/5

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

Two dense sentences, front-loaded with the action and its trigger, then the user-confirmation requirement, then the relay constraint. No sentence restates the tool name or the schema, and the closing warning is placed where an agent will read it before composing the message.

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

Completeness5/5

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

For a two-parameter mutation with no output schema, the description supplies everything the agent lacks: when the tool applies, the confirmation gate, and the sanitization constraint on message content. Nothing required 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.

Parameters4/5

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

Schema coverage is 100%, so baseline is 3, but the description adds real semantic weight: 'message' must be the user's own words and must not contain emails, phone numbers, or URLs the answer depends on, which constrains what the agent may put in that parameter. order_id gets no added detail beyond the schema's ord_… hint.

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 (send) plus resource (the user's answer to a maker's question about a UFP order) and ties it to the sibling tool that surfaces the trigger condition (get_order_status). An agent can distinguish this from create_checkout, finalize_quote, and the rest of the order-flow siblings without opening any schema.

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

Usage Guidelines5/5

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

Explicitly names the condition that selects this tool ('get_order_status surfaces an open question when one is waiting') and the alternative path to discovery. It also imposes a prerequisite — confirm the answer with the user before sending — which is exactly the kind of routing/authorization guidance an agent needs.

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

Tool Schema Changelog

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

  1. 1 tool update
    • Changedcreate_checkout14 fields changed
      • removedInput schema / properties / billing_city
        Removed value: -{
        -  "type": "string"
        -}
      • removedInput schema / properties / billing_name
        Removed value: -{
        -  "description": "Billing address, only when the buyer answered the billing question (e.g. said it differs from shipping, or a checkout UI's 'same as shipping' checkbox — then send the shipping values verbatim). Never ask for it; omit and the payment page handles billing.",
        -  "type": "string"
        -}
      • removedInput schema / properties / billing_state
        Removed value: -{
        -  "description": "Two-letter US state",
        -  "maxLength": 2,
        -  "minLength": 2,
        -  "type": "string"
        -}
      • removedInput schema / properties / billing_street1
        Removed value: -{
        -  "type": "string"
        -}
      • removedInput schema / properties / billing_street2
        Removed value: -{
        -  "type": "string"
        -}
      • removedInput schema / properties / billing_zip
        Removed value: -{
        -  "type": "string"
        -}
      • removedInput schema / properties / city
        Removed value: -{
        -  "type": "string"
        -}
      • removedInput schema / properties / email
        Removed value: -{
        -  "description": "Buyer email (only if the user provided it)",
        -  "format": "email",
        -  "type": "string"
        -}
      • removedInput schema / properties / name
        Removed value: -{
        -  "description": "Recipient full name (only if the user provided it)",
        -  "type": "string"
        -}
      • removedInput schema / properties / phone
        Removed value: -{
        -  "type": "string"
        -}
      • removedInput schema / properties / state
        Removed value: -{
        -  "description": "Two-letter US state",
        -  "maxLength": 2,
        -  "minLength": 2,
        -  "type": "string"
        -}
      • removedInput schema / properties / street1
        Removed value: -{
        -  "description": "Street address (only if the user provided it)",
        -  "type": "string"
        -}
      • removedInput schema / properties / street2
        Removed value: -{
        -  "type": "string"
        -}
      • removedInput schema / properties / zip
        Removed value: -{
        -  "type": "string"
        -}
  2. 1 tool update
    • Addedget_shop_gauges
  3. 2 tool updates
    • Changedpreview_quote2 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."
        +}
    • Changedrefine_quote2 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."
        +}
  4. 3 tool updates
    • Changedget_fabrication_quote1 field changed
      • changedInput schema / properties / color / description
        Previous value: -"ONLY a color the user actually asked for — NEVER pick one for them. fdm_print: Filament color for fdm_print (e.g. black, red); resin_print: Resin color for resin_print (e.g. gray, white, black); powder_print: Powder part color: raw gray/white, or a dye (\"black\", \"dark blue\") — vendor-resolved; elastomer_print: Elastomer part color — VCJ parts ship raw; asks resolve with an honest substitution note; print: Print color ask (\"full color\", \"black and white\"). Vendors that only price full color note the substitution; apparel: Garment color for apparel (\"black\", \"heather gray\") — vendor-resolved"New value: +"ONLY a color the user actually asked for — NEVER pick one for them. fdm_print: Filament color for fdm_print (e.g. black, red); resin_print: Resin color for resin_print (e.g. gray, white, black); powder_print: Powder part color: raw gray/white, or a dye (\"black\", \"dark blue\") — vendor-resolved; elastomer_print: Elastomer part color — VCJ parts ship raw; asks resolve with an honest substitution note; cnc: Colour for cnc: with finish anodized it is the anodize colour, otherwise the stock's own colour (black Delrin, clear acrylic). Colour WORDS only; each maker resolves the shade and says what it landed on; laser_cut: Colour of the flat stock for laser_cut (black, clear, natural…). Colour WORDS only; each maker quotes the materials it stocks in that colour and drops the ones that cannot be it; print: Print color ask (\"full color\", \"black and white\"). Vendors that only price full color note the substitution; apparel: Garment color for apparel (\"black\", \"heather gray\") — vendor-resolved"
    • Changedpreview_quote1 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"
    • Changedrefine_quote1 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"
  5. 3 tool updates
    • Changedget_fabrication_quote2 fields changed
      • addedInput schema / properties / bends / items / properties / face_id
        Added value: +{
        +  "type": "integer"
        +}
      • addedInput schema / properties / bends / items / properties / source
        Added value: +{
        +  "enum": [
        +    "detected",
        +    "user"
        +  ],
        +  "type": "string"
        +}
    • Addedpreview_quote
    • Changedrefine_quote1 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"
        +  }
        +]
  6. 3 tool updates
    • Changedget_fabrication_quote4 fields changed
      • addedInput schema / properties / bends
        Added value: +{
        +  "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.",
        +  "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"
        +}
      • changedInput schema / properties / finish / description
        Previous value: -"cnc: CNC surface finish: standard|anodized|polished|bead_blasted (default standard); sheetmetal: as_cut (default) | deburred | powder_coat — powder coat protects mild steel for outdoor use"New value: +"cnc: CNC surface finish: standard|anodized|polished|bead_blasted (default standard); sheetmetal: as_cut (default) | deburred | anodized | powder_coat — anodized is aluminum-only; powder coat protects mild steel for outdoor use"
      • addedInput schema / properties / inserts
        Added value: +{
        +  "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.",
        +  "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"
        +}
      • addedInput schema / properties / tapping
        Added value: +{
        +  "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.",
        +  "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"
        +}
    • Addedget_network_capabilities
    • Changedrefine_quote16 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"
        +}
  7. 1 tool update
    • Changedcreate_checkout1 field changed
      • addedInput schema / properties / coupon_code
        Added value: +{
        +  "description": "Coupon code, only if the user provided one (early-adopter codes from the AFN team). Case-insensitive. The discount appears on the payment page; a 100%-off code makes the total $0 with no card required. Never invent or guess a code.",
        +  "type": "string"
        +}
  8. 1 tool update
    • Changedrefine_quote3 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"
        +}
  9. 1 tool update
    • Changedget_fabrication_quote6 fields changed
      • changedInput schema / properties / color / description
        Previous value: -"ONLY a color the user actually asked for — NEVER pick one for them. fdm_print: Filament color for fdm_print (e.g. black, red); resin_print: Resin color for resin_print (e.g. gray, white, black); powder_print: Powder part color: raw gray/white, or a dye (\"black\", \"dark blue\") — vendor-resolved; print: Print color ask (\"full color\", \"black and white\"). Vendors that only price full color note the substitution; apparel: Garment color for apparel (\"black\", \"heather gray\") — vendor-resolved"New value: +"ONLY a color the user actually asked for — NEVER pick one for them. fdm_print: Filament color for fdm_print (e.g. black, red); resin_print: Resin color for resin_print (e.g. gray, white, black); powder_print: Powder part color: raw gray/white, or a dye (\"black\", \"dark blue\") — vendor-resolved; elastomer_print: Elastomer part color — VCJ parts ship raw; asks resolve with an honest substitution note; print: Print color ask (\"full color\", \"black and white\"). Vendors that only price full color note the substitution; apparel: Garment color for apparel (\"black\", \"heather gray\") — vendor-resolved"
      • addedInput schema / properties / elastomer_finish
        Added value: +{
        +  "description": "Elastomer post-processing: as_printed (VCJ parts ship raw — the whole lane today)",
        +  "type": "string"
        +}
      • addedInput schema / properties / elastomer_technology
        Added value: +{
        +  "description": "Elastomer process: vapor_cure_jetting (VCJ). Omit to let the vendor pick its default lane for the material",
        +  "type": "string"
        +}
      • changedInput schema / properties / material / description
        Previous value: -"ONLY a material the user actually asked for — NEVER guess or default one (a silent \"pla\" on a bare file drop prunes every maker that does not stock it; OMIT instead and each process quotes across its stocked materials so every maker can bid). fdm_print: pla|petg|asa (free-form — \"abs\", \"polycarbonate\" asks resolve to the closest stocked filament with a substitution note); resin_print: standard|tough|high_temp|high_detail resin (free-form asks resolve to the closest supported resin); powder_print: Powder-bed nylon: nylon_12|nylon_12_smooth|nylon_11|nylon_12_gf|nylon_12_esd|tpu (free-form — \"PA12\", \"glass filled\" resolve to the closest stocked powder); cnc: aluminum_6061|aluminum_7075|stainless_304|titanium|brass|acetal|delrin|abs|nylon_pa6|peek|acrylic (free-form asks resolve to the closest supported stock); sheetmetal: mild_steel|aluminum_5052|stainless_304 (free-form — \"steel\", \"5052\", \"stainless\" resolve; unknown asks get closest-match offers). Omit to compare the defaults; laser_cut: acrylic|plywood|mdf|delrin|uhmw|hdpe|g10|carbon_fiber|mild_steel|aluminum_5052|stainless_304 (free-form — \"plexiglass\", \"birch\" resolve; unknown asks get closest-match offers); decal: vinyl|holographic|transparent|glitter (free-form — \"chrome\" etc. gets closest matches)"New value: +"ONLY a material the user actually asked for — NEVER guess or default one (a silent \"pla\" on a bare file drop prunes every maker that does not stock it; OMIT instead and each process quotes across its stocked materials so every maker can bid). fdm_print: pla|petg|asa (free-form — \"abs\", \"polycarbonate\" asks resolve to the closest stocked filament with a substitution note); resin_print: standard|tough|high_temp|high_detail resin (free-form asks resolve to the closest supported resin); powder_print: Powder-bed nylon: nylon_12|nylon_12_smooth|nylon_11|nylon_12_gf|nylon_12_esd|nylon_12_white|nylon_pa2200|nylon_12_sls|tpu (free-form — \"PA12\", \"glass filled\" resolve to the closest stocked powder); elastomer_print: Jetted elastomer: tepu_30a|tepu_50a (free-form — \"TPU\", \"soft rubber\" resolve to the closest stocked durometer); cnc: aluminum_6061|aluminum_7075|stainless_304|titanium|brass|acetal|delrin|abs|nylon_pa6|peek|acrylic (free-form asks resolve to the closest supported stock); sheetmetal: mild_steel|aluminum_5052|stainless_304 (free-form — \"steel\", \"5052\", \"stainless\" resolve; unknown asks get closest-match offers). Omit to compare the defaults; laser_cut: acrylic|plywood|mdf|delrin|uhmw|hdpe|g10|carbon_fiber|mild_steel|aluminum_5052|stainless_304 (free-form — \"plexiglass\", \"birch\" resolve; unknown asks get closest-match offers); decal: vinyl|holographic|transparent|glitter (free-form — \"chrome\" etc. gets closest matches)"
      • changedInput schema / properties / process / enum
        Previous value: -[
        -  "fdm_print",
        -  "resin_print",
        -  "powder_print",
        -  "metal_print",
        -  "cnc",
        -  "sheetmetal",
        -  "laser_cut",
        -  "decal",
        -  "print",
        -  "apparel"
        -]New value: +[
        +  "fdm_print",
        +  "resin_print",
        +  "powder_print",
        +  "metal_print",
        +  "elastomer_print",
        +  "cnc",
        +  "sheetmetal",
        +  "laser_cut",
        +  "decal",
        +  "print",
        +  "apparel"
        +]
      • addedInput schema / properties / shore_a
        Added value: +{
        +  "description": "Numeric Shore A durometer ask (10-95, e.g. 40). Resolved to the NEAREST stocked durometer with a substitution note — never a silent swap",
        +  "exclusiveMinimum": 0,
        +  "type": "number"
        +}
  10. 1 tool update
    • Changedget_fabrication_quote2 fields changed
      • changedInput schema / properties / color / description
        Previous value: -"fdm_print: Filament color for fdm_print (e.g. black, red); resin_print: Resin color for resin_print (e.g. gray, white, black); powder_print: Powder part color: raw gray/white, or a dye (\"black\", \"dark blue\") — vendor-resolved; print: Print color ask (\"full color\", \"black and white\"). Vendors that only price full color note the substitution; apparel: Garment color for apparel (\"black\", \"heather gray\") — vendor-resolved"New value: +"ONLY a color the user actually asked for — NEVER pick one for them. fdm_print: Filament color for fdm_print (e.g. black, red); resin_print: Resin color for resin_print (e.g. gray, white, black); powder_print: Powder part color: raw gray/white, or a dye (\"black\", \"dark blue\") — vendor-resolved; print: Print color ask (\"full color\", \"black and white\"). Vendors that only price full color note the substitution; apparel: Garment color for apparel (\"black\", \"heather gray\") — vendor-resolved"
      • changedInput schema / properties / material / description
        Previous value: -"fdm_print: pla|petg|asa (free-form — \"abs\", \"polycarbonate\" asks resolve to the closest stocked filament with a substitution note); resin_print: standard|tough|high_temp|high_detail resin (free-form asks resolve to the closest supported resin); powder_print: Powder-bed nylon: nylon_12|nylon_12_smooth|nylon_11|nylon_12_gf|nylon_12_esd|tpu (free-form — \"PA12\", \"glass filled\" resolve to the closest stocked powder); cnc: aluminum_6061|aluminum_7075|stainless_304|titanium|brass|acetal|delrin|abs|nylon_pa6|peek|acrylic (free-form asks resolve to the closest supported stock); sheetmetal: mild_steel|aluminum_5052|stainless_304 (free-form — \"steel\", \"5052\", \"stainless\" resolve; unknown asks get closest-match offers). Omit to compare the defaults; laser_cut: acrylic|plywood|mdf|delrin|uhmw|hdpe|g10|carbon_fiber|mild_steel|aluminum_5052|stainless_304 (free-form — \"plexiglass\", \"birch\" resolve; unknown asks get closest-match offers); decal: vinyl|holographic|transparent|glitter (free-form — \"chrome\" etc. gets closest matches)"New value: +"ONLY a material the user actually asked for — NEVER guess or default one (a silent \"pla\" on a bare file drop prunes every maker that does not stock it; OMIT instead and each process quotes across its stocked materials so every maker can bid). fdm_print: pla|petg|asa (free-form — \"abs\", \"polycarbonate\" asks resolve to the closest stocked filament with a substitution note); resin_print: standard|tough|high_temp|high_detail resin (free-form asks resolve to the closest supported resin); powder_print: Powder-bed nylon: nylon_12|nylon_12_smooth|nylon_11|nylon_12_gf|nylon_12_esd|tpu (free-form — \"PA12\", \"glass filled\" resolve to the closest stocked powder); cnc: aluminum_6061|aluminum_7075|stainless_304|titanium|brass|acetal|delrin|abs|nylon_pa6|peek|acrylic (free-form asks resolve to the closest supported stock); sheetmetal: mild_steel|aluminum_5052|stainless_304 (free-form — \"steel\", \"5052\", \"stainless\" resolve; unknown asks get closest-match offers). Omit to compare the defaults; laser_cut: acrylic|plywood|mdf|delrin|uhmw|hdpe|g10|carbon_fiber|mild_steel|aluminum_5052|stainless_304 (free-form — \"plexiglass\", \"birch\" resolve; unknown asks get closest-match offers); decal: vinyl|holographic|transparent|glitter (free-form — \"chrome\" etc. gets closest matches)"
  11. 1 tool update
    • Changedget_fabrication_quote5 fields changed
      • changedInput schema / properties / color / description
        Previous value: -"fdm_print: Filament color for fdm_print (e.g. black, red); resin_print: Resin color for resin_print (e.g. gray, white, black); print: Print color ask (\"full color\", \"black and white\"). Vendors that only price full color note the substitution; apparel: Garment color for apparel (\"black\", \"heather gray\") — vendor-resolved"New value: +"fdm_print: Filament color for fdm_print (e.g. black, red); resin_print: Resin color for resin_print (e.g. gray, white, black); powder_print: Powder part color: raw gray/white, or a dye (\"black\", \"dark blue\") — vendor-resolved; print: Print color ask (\"full color\", \"black and white\"). Vendors that only price full color note the substitution; apparel: Garment color for apparel (\"black\", \"heather gray\") — vendor-resolved"
      • changedInput schema / properties / material / description
        Previous value: -"fdm_print: pla|petg|asa (free-form — \"abs\", \"polycarbonate\" asks resolve to the closest stocked filament with a substitution note); resin_print: standard|tough|high_temp|high_detail resin (free-form asks resolve to the closest supported resin); cnc: aluminum_6061|aluminum_7075|stainless_304|titanium|brass|acetal|delrin|abs|nylon_pa6|peek|acrylic (free-form asks resolve to the closest supported stock); sheetmetal: mild_steel|aluminum_5052|stainless_304 (free-form — \"steel\", \"5052\", \"stainless\" resolve; unknown asks get closest-match offers). Omit to compare the defaults; laser_cut: acrylic|plywood|mdf|delrin|uhmw|hdpe|g10|carbon_fiber|mild_steel|aluminum_5052|stainless_304 (free-form — \"plexiglass\", \"birch\" resolve; unknown asks get closest-match offers); decal: vinyl|holographic|transparent|glitter (free-form — \"chrome\" etc. gets closest matches)"New value: +"fdm_print: pla|petg|asa (free-form — \"abs\", \"polycarbonate\" asks resolve to the closest stocked filament with a substitution note); resin_print: standard|tough|high_temp|high_detail resin (free-form asks resolve to the closest supported resin); powder_print: Powder-bed nylon: nylon_12|nylon_12_smooth|nylon_11|nylon_12_gf|nylon_12_esd|tpu (free-form — \"PA12\", \"glass filled\" resolve to the closest stocked powder); cnc: aluminum_6061|aluminum_7075|stainless_304|titanium|brass|acetal|delrin|abs|nylon_pa6|peek|acrylic (free-form asks resolve to the closest supported stock); sheetmetal: mild_steel|aluminum_5052|stainless_304 (free-form — \"steel\", \"5052\", \"stainless\" resolve; unknown asks get closest-match offers). Omit to compare the defaults; laser_cut: acrylic|plywood|mdf|delrin|uhmw|hdpe|g10|carbon_fiber|mild_steel|aluminum_5052|stainless_304 (free-form — \"plexiglass\", \"birch\" resolve; unknown asks get closest-match offers); decal: vinyl|holographic|transparent|glitter (free-form — \"chrome\" etc. gets closest matches)"
      • addedInput schema / properties / powder_finish
        Added value: +{
        +  "description": "Powder post-processing: as_printed (raw powder surface) | vapor_polished | polished",
        +  "type": "string"
        +}
      • addedInput schema / properties / powder_technology
        Added value: +{
        +  "description": "Powder process: mjf (HP Multi Jet Fusion) | sls (laser sintering). Omit to let the vendor pick its default lane for the material",
        +  "type": "string"
        +}
      • changedInput schema / properties / process / enum
        Previous value: -[
        -  "fdm_print",
        -  "resin_print",
        -  "metal_print",
        -  "cnc",
        -  "sheetmetal",
        -  "laser_cut",
        -  "decal",
        -  "print",
        -  "apparel"
        -]New value: +[
        +  "fdm_print",
        +  "resin_print",
        +  "powder_print",
        +  "metal_print",
        +  "cnc",
        +  "sheetmetal",
        +  "laser_cut",
        +  "decal",
        +  "print",
        +  "apparel"
        +]
  12. 3 tool updates
    • Changedget_fabrication_quote1 field changed
      • addedInput schema / properties / vendors
        Added value: +{
        +  "description": "Only these specific vendors/makers (\"just quote Slant 3D\") — an INCLUDE list of vendor names as they appear on offers. Friendly names accepted (\"A3D\", \"slant 3d\"); unmatched names are reported, never an error. Usually OMIT: pass it only when the user explicitly names the vendors they want",
        +  "items": {
        +    "minLength": 1,
        +    "type": "string"
        +  },
        +  "maxItems": 16,
        +  "type": "array"
        +}
    • Changedrefine_quote1 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"
        +}
    • Addedreply_to_maker
  13. 2 tool updates
    • Changedget_fabrication_quote1 field changed
      • addedInput schema / properties / ships_from
        Added value: +{
        +  "description": "Only vendors that ship from these countries/regions (\"only US vendors\", \"keep it domestic\") — an INCLUDE list. Friendly terms accepted (\"US\", \"Europe\", \"Germany\", \"China\", \"UK\"); unmappable terms are reported, never an error. Vendors whose origin is unknown or whose network is worldwide (origin not guaranteed) are excluded, each with a note saying why. Usually OMIT: pass it only when the user explicitly limits where vendors ship from",
        +  "items": {
        +    "minLength": 1,
        +    "type": "string"
        +  },
        +  "maxItems": 8,
        +  "type": "array"
        +}
    • Changedrefine_quote1 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"
        +}

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    B
    maintenance
    Get live UK 3D printing prices for your own STL/3MF/STEP files or Printables and Thingiverse models, with a checkout link. Also finds mail-in electronics repair prices and checks order or repair progress.
    9
    MIT
  • A
    license
    A
    quality
    C
    maintenance
    Enables users to design flat-pack furniture such as bookcases, cabinets, cubes and desks through natural-language conversation, then generates CNC-ready DXFs, cut and hardware lists, printable assembly instructions and a quote request for a fabricator.
    6
    10
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables AI clients to submit material specifications, machine, and quantity and receive a single final quote in CNY/kg with MOQ status and human-verification hints, while raw material prices and pricing formulas stay locked server-side. Also exposes machine options and a fiber/spec/process vocabulary that can be passed straight into quote requests.
    MIT
Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources