McMaster-Carr parts
Bought hardware is a real part: a part number, its manufacturer's model, its specification. McMaster-Carr publishes a STEP model and a full specification table (material, finish, strength class, thread, dimensions and tolerances, load and speed ratings, temperature range, compliance) for almost everything it sells. Use them.
The tools: cadagent.mcmaster (Python) and cad-agent mcmaster (CLI). They read one product page at a time in the
system Chrome (Playwright), with a pause between pages. That is the same traffic as an engineer choosing parts, and
it must stay that way.
Rules
Download like an engineer, not a crawler. One part at a time, a pause between pages (default 3 s; the tool never goes below 2 s), only the product pages of the parts you are choosing. The tool accepts only McMaster part numbers (
PN_RE, e.g. 91290A242), never a category, search or other URL. No bulk downloads, no parallel sessions. A part already downloaded is reused offline (no browser); download it again only when you need to (--force).Keep the files local. McMaster-Carr CAD is for design use; do not redistribute it. Gitignore the vendor folder and track only
SOURCE.txt:references/vendor/** !references/vendor/**/ !references/vendor/**/SOURCE.txtStrong, but few parts. Prefer one family per fastener type: for example, black-oxide alloy steel class 12.9 socket head screws (91290A) with a minimal set of lengths; 18-8 stainless where corrosion matters; class 10 nyloc nuts; one washer family per size. When a computed length is not stocked, move the seat or the pilot depth so a stocked length fits (lesson 04) before adding another SKU. Report the number of distinct SKUs and the total part count.
Size from the CAD, then check against the page. The stack comes from the CAD: grip, thread depth, insert pilot depth. Thread engagement is length minus grip. Check the chosen length against the depth actually available, and check the normalised model's bounding box against the catalogue dimensions.
Report what McMaster does not stock, with the closest stocked alternative (for example, a 61812-2RS is not stocked; 6812-2Z is), and any CAD dimension that should move to a stocked size.
Process
Pick the part like an engineer. Open the category page (e.g.
https://www.mcmaster.com/products/ball-bearings/), filter it (System of Measurement → Metric, then size, material, thread) and read the table. Choose by function (load, fit, material, strength class) and by the SKUs you already use. Only then open the product pagehttps://www.mcmaster.com/<PN>/.Download and normalise.
cad-agent mcmaster 91290A242 --kind screw --out references/vendor/mcmaster \ --catalog catalog/hardware.json --key screw_m5x20This writes
OUT/<PN>/<PN>.step(the download, kept only if it is a STEP file),<PN>.page.json(title, price, pack quantity, every spec row, option choices),<PN>.norm.step,<PN>.norm.json(axis found, how it was seated, bbox, volume, mass) and an entry inSOURCE.txt. Kinds and their frames (cadagent.mcmaster.FRAMES) all put the axis on +Z, through the origin (the cylinders' axis line, not the centre of mass); which end goes down is decided from the part's shape, not from how the vendor modelled it:bearing,washer,nut,insert,standoff,spacer,pin,grommet,rod: the larger end (flange, collar, head) at z = 0 and the part on +z; when both ends are the same size, the heavier end down (info["end_down"]says which rule decided).screw: head on +z, shank towards -z. z = 0 is the underside of the head for socket, button, pan, hex and flanged heads, and the top face for a countersunk (flat) head (info["head"]). A part with no head wider than its shank (set screw, stud) is refused: usepinorrod.shoulder_screw: the underside of the head at z = 0, head on +z, shoulder and thread towards -z.rod_end: the ball centre at the origin, ball bore along +Y, threaded shank along -Z (without a modelled ball, the middle of the bore).
A part with variants (a rod end's thread direction, a choice of finish) offers its CAD only after the choice. Give the option text after the part numbers, one
--chooseper option, prefixed with the part it is for:cad-agent mcmaster 59935K53 91290A242 --choose "59935K53:Right Hand" --out references/vendor/mcmaster(the
PN:prefix may be left out when there is one part number). In Python:Session.fetch(pn, out, choose=["Right Hand"]). The page data records what was offered and what was chosen.Playwright:
pip install playwrightinto the environment that runs it, plus Google Chrome (then nothing else is needed; without Chrome the command stops with an install hint).Record the catalogue entry.
catalog_entry()/--cataloggives:mcmaster(PN),description,url,price_usd,pack_qty,dims_mm,material,mass_gwithmass_basis(McMaster's listed weight when the page gives one, otherwise CAD volume x density, which it says),cad(the normalised STEP path),frame, andspecs.raw(label → value) withspecs.parsed(mm, g, N, MPa, deg C). Add what only the project knows:used_for, the quantity, and notes (stack and engagement arithmetic, CAD changes needed). Fields you add are kept when the entry is refreshed.Check the model. Compare
bbox_mmwith the page's dimensions (a bearing's OD and width, a screw's length below the head, a rod end's centre-to-end length). A mismatch means the wrong frame or the wrong part.Place it in the assembly. Import
<PN>.norm.stepand move it to the seat: for a screw, origin on the seat face and +Z out of the hole; for a bearing, the bottom face on the shoulder. Run the clash and tool-access checks (lesson 04) with the real heads, nuts and washers in place, not envelopes.
Python
import json
from cadagent import mcmaster as mc
with mc.Session(delay_s=3) as s: # one browser, one page at a time
step = s.fetch("5972K82", "references/vendor/mcmaster/5972K82")
norm, info = mc.normalise(step, "bearing", material="Steel")
page = json.loads((step.parent / "5972K82.page.json").read_text())
mc.update_catalog("catalog/hardware.json", "bearing_6001",
mc.catalog_entry(page, info, cad=str(norm)) | {"used_for": "knee", "qty": 4})