@vcad/mcp 0.9.4-main.72 → 0.9.4-main.73

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -6,4 +6,4 @@ vcad's MCP server as a self-contained bundle (server + BRep kernel WASM).
6
6
  { "mcpServers": { "vcad": { "command": "npx", "args": ["-y", "@vcad/mcp"] } } }
7
7
  ```
8
8
 
9
- Built from 150875476b916d4e772bdeb33726c543ccf2756d at 2026-08-17T03:05:59.733Z. Source: https://github.com/ecto/vcad
9
+ Built from c94448044a725e430c38faf507027d5a10b2c68d at 2026-08-17T23:42:23.328Z. Source: https://github.com/ecto/vcad
package/index.mjs CHANGED
@@ -10874,6 +10874,46 @@ async function parseKicadPcb2(content) {
10874
10874
  return null;
10875
10875
  }
10876
10876
  }
10877
+ function importBindings(wasm3) {
10878
+ const mod = wasm3;
10879
+ const bind = (name) => {
10880
+ const fn = mod[name];
10881
+ if (typeof fn !== "function") {
10882
+ throw new Error(`Altium import is unavailable: this kernel WASM build predates ${name}. Rebuild the kernel WASM (npm run build -w vcad-kernel-wasm) or update @vcad/mcp.`);
10883
+ }
10884
+ return fn;
10885
+ };
10886
+ return {
10887
+ parseAltiumAsciiPcb: (content) => bind("parseAltiumAsciiPcb")(content),
10888
+ parseAltiumPcbDoc: (bytes) => bind("parseAltiumPcbDoc")(bytes),
10889
+ parseAltiumPcbLib: (bytes) => bind("parseAltiumPcbLib")(bytes),
10890
+ parseEagleBrd: (content) => bind("parseEagleBrd")(content)
10891
+ };
10892
+ }
10893
+ async function parseEagleBrd(content) {
10894
+ const wasm3 = await loadEcadWasm();
10895
+ if (!wasm3)
10896
+ return null;
10897
+ return importBindings(wasm3).parseEagleBrd(content);
10898
+ }
10899
+ async function parseAltiumAsciiPcb(content) {
10900
+ const wasm3 = await loadEcadWasm();
10901
+ if (!wasm3)
10902
+ return null;
10903
+ return importBindings(wasm3).parseAltiumAsciiPcb(content);
10904
+ }
10905
+ async function parseAltiumPcbDoc(bytes) {
10906
+ const wasm3 = await loadEcadWasm();
10907
+ if (!wasm3)
10908
+ return null;
10909
+ return importBindings(wasm3).parseAltiumPcbDoc(bytes);
10910
+ }
10911
+ async function parseAltiumPcbLib(bytes) {
10912
+ const wasm3 = await loadEcadWasm();
10913
+ if (!wasm3)
10914
+ return null;
10915
+ return importBindings(wasm3).parseAltiumPcbLib(bytes);
10916
+ }
10877
10917
  async function exportKicadPcb2(pcb) {
10878
10918
  const wasm3 = await loadEcadWasm();
10879
10919
  if (!wasm3)
@@ -11719,7 +11759,11 @@ __export(dist_exports, {
11719
11759
  mountingHolesFromPcb: () => mountingHolesFromPcb,
11720
11760
  netContinuity: () => netContinuity,
11721
11761
  outlineAabb: () => outlineAabb,
11762
+ parseAltiumAsciiPcb: () => parseAltiumAsciiPcb,
11763
+ parseAltiumPcbDoc: () => parseAltiumPcbDoc,
11764
+ parseAltiumPcbLib: () => parseAltiumPcbLib,
11722
11765
  parseBindingKey: () => parseBindingKey,
11766
+ parseEagleBrd: () => parseEagleBrd,
11723
11767
  parseExpression: () => parse,
11724
11768
  parseKicadPcb: () => parseKicadPcb2,
11725
11769
  parseXyz: () => parseXyz,
@@ -41547,6 +41591,26 @@ var init_CHANGELOG = __esm({
41547
41591
  CHANGELOG_default = {
41548
41592
  $schema: "./changelog.schema.json",
41549
41593
  entries: [
41594
+ {
41595
+ id: "2026-08-17-altium-pcb-import",
41596
+ version: "0.9.4",
41597
+ date: "2026-08-17",
41598
+ category: "feat",
41599
+ title: "Altium and Eagle PCB import",
41600
+ summary: "Import Altium .PcbDoc boards (native binary or ASCII) and .PcbLib libraries, plus Eagle .brd boards, straight into a live session.",
41601
+ features: [
41602
+ "pcb",
41603
+ "import",
41604
+ "ecad",
41605
+ "altium",
41606
+ "eagle"
41607
+ ],
41608
+ mcpTools: [
41609
+ "import_altium",
41610
+ "import_altium_library",
41611
+ "import_eagle"
41612
+ ]
41613
+ },
41550
41614
  {
41551
41615
  id: "2026-08-16-render-z-up",
41552
41616
  version: "0.9.4",
@@ -41559,6 +41623,48 @@ var init_CHANGELOG = __esm({
41559
41623
  "rendering"
41560
41624
  ]
41561
41625
  },
41626
+ {
41627
+ id: "2026-08-16-render-hidden-lines",
41628
+ version: "0.9.4",
41629
+ date: "2026-08-16",
41630
+ category: "fix",
41631
+ title: "SVG renders draw complete, actually-dashed hidden lines",
41632
+ summary: "Hidden edges on curved features were mostly deleted and the survivors drew solid, leaving a stray line across the part; they now run the full occluded length as proper dashes.",
41633
+ features: [
41634
+ "rendering",
41635
+ "drafting"
41636
+ ]
41637
+ },
41638
+ {
41639
+ id: "2026-08-16-render-annotation-scaling",
41640
+ version: "0.9.4",
41641
+ date: "2026-08-16",
41642
+ category: "fix",
41643
+ title: "Render overlays stay readable at any size",
41644
+ summary: "The axes gizmo, part labels and dimensions now scale with the canvas instead of staying 1024px-sized, dimension lines clear round parts, and labels no longer land on the geometry they name.",
41645
+ features: [
41646
+ "rendering",
41647
+ "drafting"
41648
+ ],
41649
+ mcpTools: [
41650
+ "render_view"
41651
+ ]
41652
+ },
41653
+ {
41654
+ id: "2026-08-16-render-aa-and-depth-cue",
41655
+ version: "0.9.4",
41656
+ date: "2026-08-16",
41657
+ category: "fix",
41658
+ title: "Smoother renders: anti-aliasing and a per-pixel depth cue",
41659
+ summary: "Isometric renders anti-alias their silhouettes and linework, flat faces no longer break into hard tonal wedges at triangle boundaries, and edge strokes sit on their geometry instead of half a stroke off.",
41660
+ features: [
41661
+ "rendering",
41662
+ "tessellation"
41663
+ ],
41664
+ mcpTools: [
41665
+ "render_view"
41666
+ ]
41667
+ },
41562
41668
  {
41563
41669
  id: "2026-08-16-loon-sheet-metal-bindings",
41564
41670
  version: "0.9.4",
@@ -41578,6 +41684,20 @@ var init_CHANGELOG = __esm({
41578
41684
  "flat_pattern_from_solid"
41579
41685
  ]
41580
41686
  },
41687
+ {
41688
+ id: "2026-08-16-cli-sheet-metal-fold",
41689
+ version: "0.9.4",
41690
+ date: "2026-08-16",
41691
+ category: "fix",
41692
+ title: "Sheet-metal parts export from the CLI again",
41693
+ summary: "vcad info/export and vcad-render now fold sheet-metal chains \u2014 including jogs and bend relief \u2014 instead of reporting zero triangles, and a root that fails to evaluate says why.",
41694
+ features: [
41695
+ "sheet-metal",
41696
+ "cli",
41697
+ "loon",
41698
+ "export"
41699
+ ]
41700
+ },
41581
41701
  {
41582
41702
  id: "2026-08-16-cli-loon-input-everywhere",
41583
41703
  version: "0.9.4",
@@ -55478,6 +55598,8 @@ var init_tool_metadata = __esm({
55478
55598
  import_step: { title: "Import STEP", annotations: RW },
55479
55599
  import_urdf: { title: "Import URDF", annotations: RW },
55480
55600
  import_kicad: { title: "Import KiCad", annotations: RW },
55601
+ import_altium: { title: "Import Altium", annotations: RW },
55602
+ import_altium_library: { title: "Import Altium Library", annotations: RO },
55481
55603
  import_eagle: { title: "Import EAGLE", annotations: RW },
55482
55604
  open_in_browser: { title: "Open in Browser", annotations: RW },
55483
55605
  // ── Physics gym ────────────────────────────────────────────────────────
@@ -78484,10 +78606,72 @@ function readSource(input, label) {
78484
78606
  }
78485
78607
  throw new Error("Provide either `filename` or `content_base64`");
78486
78608
  }
78609
+ function readSourceBytes(input, label) {
78610
+ const { filename, content_base64 } = input;
78611
+ if (content_base64) {
78612
+ const buf = Buffer.from(content_base64, "base64");
78613
+ if (buf.length === 0) throw new Error("content_base64 decoded to zero bytes");
78614
+ if (buf.length > MAX_PCB_BYTES) {
78615
+ throw new Error(`${label} content exceeds the ${MAX_PCB_BYTES} byte limit`);
78616
+ }
78617
+ return buf;
78618
+ }
78619
+ if (filename) {
78620
+ if (isRemoteDeployment()) {
78621
+ throw new Error(
78622
+ `This hosted server has no filesystem access \u2014 pass the ${label} contents as \`content_base64\` instead of \`filename\`.`
78623
+ );
78624
+ }
78625
+ const filepath = resolveWithinRoot(
78626
+ filename,
78627
+ process.env.VCAD_MCP_EXPORT_DIR ?? process.cwd()
78628
+ );
78629
+ if (!existsSync5(filepath)) throw new Error(`${label} file not found`);
78630
+ const stat = statSync3(filepath);
78631
+ if (!stat.isFile()) throw new Error(`${label} path is not a regular file`);
78632
+ if (stat.size > MAX_PCB_BYTES) {
78633
+ throw new Error(`${label} file exceeds the ${MAX_PCB_BYTES} byte limit`);
78634
+ }
78635
+ return readFileSync8(filepath);
78636
+ }
78637
+ throw new Error("Provide either `filename` or `content_base64`");
78638
+ }
78639
+ function registerBoard(pcb, name) {
78640
+ const doc = createDocument();
78641
+ doc.nodes["1"] = {
78642
+ id: 1,
78643
+ name,
78644
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
78645
+ op: { type: "PcbBoard", board: pcb }
78646
+ };
78647
+ doc.roots.push({ root: 1, material: "__pcb_fr4__" });
78648
+ doc.materials["__pcb_fr4__"] = {
78649
+ name: "__pcb_fr4__",
78650
+ color: [0.05, 0.35, 0.15],
78651
+ roughness: 0.6,
78652
+ metallic: 0
78653
+ };
78654
+ return registerSession(doc);
78655
+ }
78656
+ function boardSummary(pcb) {
78657
+ return {
78658
+ footprints: pcb.footprints.length,
78659
+ nets: pcb.nets.length,
78660
+ outline_vertices: pcb.outline?.vertices?.length ?? 0,
78661
+ traces: pcb.traces.length,
78662
+ vias: pcb.vias.length,
78663
+ zones: pcb.zones.length,
78664
+ design_rules: {
78665
+ trace_width: pcb.rules?.defaultRules?.traceWidth,
78666
+ clearance: pcb.rules?.defaultRules?.clearance,
78667
+ via_diameter: pcb.rules?.defaultRules?.viaDiameter
78668
+ }
78669
+ };
78670
+ }
78487
78671
  function boardName(input) {
78488
78672
  if (input.name) return input.name;
78489
78673
  if (input.filename) {
78490
- return input.filename.replace(/^.*[/\\]/, "").replace(/\.kicad_pcb$/i, "");
78674
+ return input.filename.replace(/^.*[/\\]/, "").replace(/\.(kicad_pcb|pcbdoc|pcblib|brd)$/i, "");
78491
78675
  }
78492
78676
  return "Imported board";
78493
78677
  }
@@ -78512,21 +78696,7 @@ async function importKicad(input) {
78512
78696
  "KiCad parsing is unavailable (kernel WASM is missing parseKicadPcb) or the file produced no board."
78513
78697
  );
78514
78698
  }
78515
- const doc = createDocument();
78516
- doc.nodes["1"] = {
78517
- id: 1,
78518
- name: boardName(args),
78519
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
78520
- op: { type: "PcbBoard", board: pcb }
78521
- };
78522
- doc.roots.push({ root: 1, material: "__pcb_fr4__" });
78523
- doc.materials["__pcb_fr4__"] = {
78524
- name: "__pcb_fr4__",
78525
- color: [0.05, 0.35, 0.15],
78526
- roughness: 0.6,
78527
- metallic: 0
78528
- };
78529
- const documentId = registerSession(doc);
78699
+ const documentId = registerBoard(pcb, boardName(args));
78530
78700
  const onlyPlacement = pcb.traces.length === 0 && pcb.vias.length === 0;
78531
78701
  return {
78532
78702
  content: [
@@ -78535,19 +78705,7 @@ async function importKicad(input) {
78535
78705
  text: JSON.stringify({
78536
78706
  success: true,
78537
78707
  document_id: documentId,
78538
- summary: {
78539
- footprints: pcb.footprints.length,
78540
- nets: pcb.nets.length,
78541
- outline_vertices: pcb.outline?.vertices?.length ?? 0,
78542
- traces: pcb.traces.length,
78543
- vias: pcb.vias.length,
78544
- zones: pcb.zones.length,
78545
- design_rules: {
78546
- trace_width: pcb.rules?.defaultRules?.traceWidth,
78547
- clearance: pcb.rules?.defaultRules?.clearance,
78548
- via_diameter: pcb.rules?.defaultRules?.viaDiameter
78549
- }
78550
- },
78708
+ summary: boardSummary(pcb),
78551
78709
  ...onlyPlacement ? {
78552
78710
  note: "Placement + netlist only \u2014 the file carried no routed copper."
78553
78711
  } : {}
@@ -78556,12 +78714,138 @@ async function importKicad(input) {
78556
78714
  ]
78557
78715
  };
78558
78716
  }
78559
- function importEagle(_input) {
78560
- return importError(
78561
- "Eagle (.brd) import is not yet supported. Export your board from Eagle as KiCad (File > Export > KiCad .kicad_pcb) and use import_kicad instead."
78562
- );
78717
+ function isCompoundFile(bytes) {
78718
+ return bytes.length >= 8 && bytes.subarray(0, 8).equals(Buffer.from([208, 207, 17, 224, 161, 177, 26, 225]));
78719
+ }
78720
+ async function importAltium(input) {
78721
+ const args = input ?? {};
78722
+ let bytes;
78723
+ try {
78724
+ bytes = readSourceBytes(args, "Altium");
78725
+ } catch (e) {
78726
+ return importError(e instanceof Error ? e.message : String(e));
78727
+ }
78728
+ const binary = isCompoundFile(bytes);
78729
+ let pcb;
78730
+ try {
78731
+ pcb = binary ? await parseAltiumPcbDoc(new Uint8Array(bytes)) : await parseAltiumAsciiPcb(bytes.toString("utf8"));
78732
+ } catch (e) {
78733
+ return importError(
78734
+ `Could not parse the Altium ${binary ? "binary" : "ASCII"} .PcbDoc: ` + (e instanceof Error ? e.message : String(e))
78735
+ );
78736
+ }
78737
+ if (!pcb) {
78738
+ return importError(
78739
+ "Altium parsing is unavailable (kernel WASM is missing parseAltiumPcbDoc)."
78740
+ );
78741
+ }
78742
+ const documentId = registerBoard(pcb, boardName(args));
78743
+ const onlyPlacement = pcb.traces.length === 0 && pcb.vias.length === 0;
78744
+ return {
78745
+ content: [
78746
+ {
78747
+ type: "text",
78748
+ text: JSON.stringify({
78749
+ success: true,
78750
+ document_id: documentId,
78751
+ source_format: binary ? "PcbDoc (binary)" : "PcbDoc (ASCII)",
78752
+ summary: boardSummary(pcb),
78753
+ ...onlyPlacement ? { note: "Placement + netlist only \u2014 the file carried no routed copper." } : {},
78754
+ ...binary ? {
78755
+ note_binary: "Binary .PcbDoc record layouts are reconstructed, not specified by Altium, and are validated against real open-hardware projects. Geometry that decoded implausibly fails the import outright rather than importing wrong, but spot-check with render_pcb before fabricating. Copper pours and text are not imported."
78756
+ } : {}
78757
+ })
78758
+ }
78759
+ ]
78760
+ };
78761
+ }
78762
+ async function importAltiumLibrary(input) {
78763
+ const args = input ?? {};
78764
+ let bytes;
78765
+ try {
78766
+ bytes = readSourceBytes(args, "Altium library");
78767
+ } catch (e) {
78768
+ return importError(e instanceof Error ? e.message : String(e));
78769
+ }
78770
+ let lib;
78771
+ try {
78772
+ lib = await parseAltiumPcbLib(new Uint8Array(bytes));
78773
+ } catch (e) {
78774
+ return importError(
78775
+ `Could not parse the Altium .PcbLib: ${e instanceof Error ? e.message : String(e)}`
78776
+ );
78777
+ }
78778
+ if (!lib) {
78779
+ return importError(
78780
+ "Altium parsing is unavailable (kernel WASM is missing parseAltiumPcbLib)."
78781
+ );
78782
+ }
78783
+ return {
78784
+ content: [
78785
+ {
78786
+ type: "text",
78787
+ text: JSON.stringify({
78788
+ success: true,
78789
+ footprint_count: lib.footprints.length,
78790
+ footprints: lib.footprints.map((f) => ({
78791
+ name: f.name,
78792
+ pad_count: f.pads.length,
78793
+ pads: f.pads.map((p) => ({
78794
+ number: p.number,
78795
+ type: p.pad_type,
78796
+ position: p.position,
78797
+ rotation: p.rotation,
78798
+ drill: p.drill?.diameter ?? null
78799
+ }))
78800
+ }))
78801
+ })
78802
+ }
78803
+ ]
78804
+ };
78805
+ }
78806
+ async function importEagle(input) {
78807
+ const args = input ?? {};
78808
+ let content;
78809
+ try {
78810
+ content = readSource(args, "Eagle");
78811
+ } catch (e) {
78812
+ return importError(e instanceof Error ? e.message : String(e));
78813
+ }
78814
+ if (!content.includes("<eagle") && !content.includes("<board")) {
78815
+ return importError(
78816
+ "This does not look like an Eagle XML .brd file. Eagle 5 and earlier wrote a binary .brd \u2014 open it in Eagle 6+ (which converts it to XML) and save, then import that."
78817
+ );
78818
+ }
78819
+ let pcb;
78820
+ try {
78821
+ pcb = await parseEagleBrd(content);
78822
+ } catch (e) {
78823
+ return importError(
78824
+ `Could not parse the Eagle .brd: ${e instanceof Error ? e.message : String(e)}`
78825
+ );
78826
+ }
78827
+ if (!pcb) {
78828
+ return importError(
78829
+ "Eagle parsing is unavailable (kernel WASM is missing parseEagleBrd)."
78830
+ );
78831
+ }
78832
+ const documentId = registerBoard(pcb, boardName(args));
78833
+ const onlyPlacement = pcb.traces.length === 0 && pcb.vias.length === 0;
78834
+ return {
78835
+ content: [
78836
+ {
78837
+ type: "text",
78838
+ text: JSON.stringify({
78839
+ success: true,
78840
+ document_id: documentId,
78841
+ summary: boardSummary(pcb),
78842
+ ...onlyPlacement ? { note: "Placement + netlist only \u2014 the file carried no routed copper." } : {}
78843
+ })
78844
+ }
78845
+ ]
78846
+ };
78563
78847
  }
78564
- var MAX_PCB_BYTES, importKicadSchema, importEagleSchema, toolDefs46;
78848
+ var MAX_PCB_BYTES, importKicadSchema, importAltiumSchema, importAltiumLibrarySchema, importEagleSchema, toolDefs46;
78565
78849
  var init_import_pcb = __esm({
78566
78850
  "src/tools/import-pcb.ts"() {
78567
78851
  "use strict";
@@ -78589,16 +78873,50 @@ var init_import_pcb = __esm({
78589
78873
  }
78590
78874
  }
78591
78875
  };
78876
+ importAltiumSchema = {
78877
+ type: "object",
78878
+ properties: {
78879
+ filename: {
78880
+ type: "string",
78881
+ description: "Path to a .PcbDoc file on the server filesystem (relative to VCAD_MCP_EXPORT_DIR or cwd). Native binary and ASCII exports are both accepted. On hosted servers pass content_base64 instead."
78882
+ },
78883
+ content_base64: {
78884
+ type: "string",
78885
+ description: "Base64-encoded .PcbDoc contents (preferred for hosted servers)."
78886
+ },
78887
+ name: {
78888
+ type: "string",
78889
+ description: "Board name for display (default: filename without extension)."
78890
+ }
78891
+ }
78892
+ };
78893
+ importAltiumLibrarySchema = {
78894
+ type: "object",
78895
+ properties: {
78896
+ filename: {
78897
+ type: "string",
78898
+ description: "Path to a .PcbLib footprint library (binary or ASCII)."
78899
+ },
78900
+ content_base64: {
78901
+ type: "string",
78902
+ description: "Base64-encoded .PcbLib contents."
78903
+ }
78904
+ }
78905
+ };
78592
78906
  importEagleSchema = {
78593
78907
  type: "object",
78594
78908
  properties: {
78595
78909
  filename: {
78596
78910
  type: "string",
78597
- description: "Path to a .brd file (Eagle XML format)."
78911
+ description: "Path to a .brd file (Eagle XML, Eagle 6+)."
78598
78912
  },
78599
78913
  content_base64: {
78600
78914
  type: "string",
78601
- description: "Base64-encoded .brd contents."
78915
+ description: "Base64-encoded .brd contents (preferred for hosted servers)."
78916
+ },
78917
+ name: {
78918
+ type: "string",
78919
+ description: "Board name for display (default: filename without extension)."
78602
78920
  }
78603
78921
  }
78604
78922
  };
@@ -78611,13 +78929,29 @@ var init_import_pcb = __esm({
78611
78929
  handler: async (a) => await importKicad(a),
78612
78930
  behavior: behavior({ writesDoc: true, geometry: true })
78613
78931
  },
78932
+ {
78933
+ name: "import_altium",
78934
+ pack: "ecad",
78935
+ description: "Import an Altium .PcbDoc board into a live session \u2014 board outline, footprints with pads + nets, design rules, and any routed traces/vias. Accepts both the native binary file and an ASCII export (detected automatically). Returns a document_id ready for render_pcb, run_drc, get_pad_positions, route_nets, and export_gerber. The binary path fails closed on record layouts it cannot decode rather than importing a partially-correct board. Pass content_base64 on hosted servers.",
78936
+ inputSchema: importAltiumSchema,
78937
+ handler: async (a) => await importAltium(a),
78938
+ behavior: behavior({ writesDoc: true, geometry: true })
78939
+ },
78940
+ {
78941
+ name: "import_altium_library",
78942
+ pack: "ecad",
78943
+ description: "Read an Altium .PcbLib footprint library (binary or ASCII) and return its footprint patterns with pads, shapes, and drills. A library is not a board, so no document_id is minted.",
78944
+ inputSchema: importAltiumLibrarySchema,
78945
+ handler: async (a) => await importAltiumLibrary(a),
78946
+ behavior: behavior({})
78947
+ },
78614
78948
  {
78615
78949
  name: "import_eagle",
78616
78950
  pack: "ecad",
78617
- description: "Import an Eagle .brd file (not yet supported). Export your board from Eagle as KiCad (.kicad_pcb) and use import_kicad instead.",
78951
+ description: "Import an Eagle .brd board (XML, Eagle 6+) into a live session \u2014 board outline, packages placed as footprints with pads, signals as nets, and any hand-routed traces/vias. Returns a document_id ready for render_pcb, run_drc, get_pad_positions, route_nets, and export_gerber. Pass content_base64 on hosted servers.",
78618
78952
  inputSchema: importEagleSchema,
78619
- handler: (a) => importEagle(a),
78620
- behavior: behavior({})
78953
+ handler: async (a) => await importEagle(a),
78954
+ behavior: behavior({ writesDoc: true, geometry: true })
78621
78955
  }
78622
78956
  ];
78623
78957
  }
@@ -83649,8 +83983,8 @@ var init_server3 = __esm({
83649
83983
  init_order_feed();
83650
83984
  init_animate();
83651
83985
  PKG_VERSION = (() => {
83652
- if ("0.9.4-main.72") {
83653
- return "0.9.4-main.72";
83986
+ if ("0.9.4-main.73") {
83987
+ return "0.9.4-main.73";
83654
83988
  }
83655
83989
  try {
83656
83990
  const req = createRequire2(import.meta.url);
@@ -83659,8 +83993,8 @@ var init_server3 = __esm({
83659
83993
  return "0.0.0";
83660
83994
  }
83661
83995
  })();
83662
- BUILD_SHA = "150875476b916d4e772bdeb33726c543ccf2756d";
83663
- BUILD_TIME = "2026-08-17T03:05:59.733Z";
83996
+ BUILD_SHA = "c94448044a725e430c38faf507027d5a10b2c68d";
83997
+ BUILD_TIME = "2026-08-17T23:42:23.328Z";
83664
83998
  SHORT_SHA = BUILD_SHA === "unknown" ? "unknown" : BUILD_SHA.slice(0, 7);
83665
83999
  VERSION_WITH_BUILD = SHORT_SHA === "unknown" ? PKG_VERSION : `${PKG_VERSION}+${SHORT_SHA}`;
83666
84000
  INSTANCE_ID = randomUUID7().slice(0, 8);
@@ -83856,6 +84190,8 @@ var init_server3 = __esm({
83856
84190
  "import_step",
83857
84191
  "import_urdf",
83858
84192
  "import_kicad",
84193
+ "import_altium",
84194
+ "import_altium_library",
83859
84195
  "import_eagle",
83860
84196
  "open_in_browser",
83861
84197
  // ── Physics gym ────────────────────────────────────────────
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vcad/mcp",
3
- "version": "0.9.4-main.72",
3
+ "version": "0.9.4-main.73",
4
4
  "description": "vcad MCP server — parametric CAD + PCB design tools for AI agents (self-contained: bundled server + kernel WASM)",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -19,7 +19,7 @@
19
19
  },
20
20
  "homepage": "https://vcad.io",
21
21
  "vcadBuild": {
22
- "sha": "150875476b916d4e772bdeb33726c543ccf2756d",
23
- "builtAt": "2026-08-17T03:05:59.733Z"
22
+ "sha": "c94448044a725e430c38faf507027d5a10b2c68d",
23
+ "builtAt": "2026-08-17T23:42:23.328Z"
24
24
  }
25
25
  }
Binary file