@jlcpcb/mcp 0.3.0 → 0.3.1
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/CHANGELOG.md +13 -0
- package/dist/index.js +71 -18
- package/package.json +2 -1
- package/src/tools/index.test.ts +13 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# @jlcpcb/mcp
|
|
2
2
|
|
|
3
|
+
## 0.3.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- d5a74c2: Fix EasyEDA 3D model transform import so KiCad footprints preserve model offsets and rotations.
|
|
8
|
+
|
|
9
|
+
Improve CLI table formatting so search and library rows keep aligned columns, including with wide characters.
|
|
10
|
+
|
|
11
|
+
Add workspace lint scripts and ESLint configuration so `bun run lint` works across packages.
|
|
12
|
+
|
|
13
|
+
- Updated dependencies [d5a74c2]
|
|
14
|
+
- @jlcpcb/core@0.3.1
|
|
15
|
+
|
|
3
16
|
## 0.3.0
|
|
4
17
|
|
|
5
18
|
### Minor Changes
|
package/dist/index.js
CHANGED
|
@@ -4,25 +4,43 @@ var __getProtoOf = Object.getPrototypeOf;
|
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
5
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
6
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
function __accessProp(key) {
|
|
8
|
+
return this[key];
|
|
9
|
+
}
|
|
10
|
+
var __toESMCache_node;
|
|
11
|
+
var __toESMCache_esm;
|
|
7
12
|
var __toESM = (mod, isNodeMode, target) => {
|
|
13
|
+
var canCache = mod != null && typeof mod === "object";
|
|
14
|
+
if (canCache) {
|
|
15
|
+
var cache = isNodeMode ? __toESMCache_node ??= new WeakMap : __toESMCache_esm ??= new WeakMap;
|
|
16
|
+
var cached = cache.get(mod);
|
|
17
|
+
if (cached)
|
|
18
|
+
return cached;
|
|
19
|
+
}
|
|
8
20
|
target = mod != null ? __create(__getProtoOf(mod)) : {};
|
|
9
21
|
const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
|
|
10
22
|
for (let key of __getOwnPropNames(mod))
|
|
11
23
|
if (!__hasOwnProp.call(to, key))
|
|
12
24
|
__defProp(to, key, {
|
|
13
|
-
get: (
|
|
25
|
+
get: __accessProp.bind(mod, key),
|
|
14
26
|
enumerable: true
|
|
15
27
|
});
|
|
28
|
+
if (canCache)
|
|
29
|
+
cache.set(mod, to);
|
|
16
30
|
return to;
|
|
17
31
|
};
|
|
18
32
|
var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
33
|
+
var __returnValue = (v) => v;
|
|
34
|
+
function __exportSetter(name, newValue) {
|
|
35
|
+
this[name] = __returnValue.bind(null, newValue);
|
|
36
|
+
}
|
|
19
37
|
var __export = (target, all) => {
|
|
20
38
|
for (var name in all)
|
|
21
39
|
__defProp(target, name, {
|
|
22
40
|
get: all[name],
|
|
23
41
|
enumerable: true,
|
|
24
42
|
configurable: true,
|
|
25
|
-
set: (
|
|
43
|
+
set: __exportSetter.bind(all, name)
|
|
26
44
|
});
|
|
27
45
|
};
|
|
28
46
|
|
|
@@ -6276,7 +6294,7 @@ var require_formats = __commonJS((exports) => {
|
|
|
6276
6294
|
}
|
|
6277
6295
|
var TIME = /^(\d\d):(\d\d):(\d\d(?:\.\d+)?)(z|([+-])(\d\d)(?::?(\d\d))?)?$/i;
|
|
6278
6296
|
function getTime(strictTimeZone) {
|
|
6279
|
-
return function
|
|
6297
|
+
return function time3(str) {
|
|
6280
6298
|
const matches = TIME.exec(str);
|
|
6281
6299
|
if (!matches)
|
|
6282
6300
|
return false;
|
|
@@ -21912,13 +21930,17 @@ import { readFileSync } from "fs";
|
|
|
21912
21930
|
import { join as join6, dirname as dirname3 } from "path";
|
|
21913
21931
|
import { fileURLToPath } from "url";
|
|
21914
21932
|
var __defProp2 = Object.defineProperty;
|
|
21933
|
+
var __returnValue2 = (v) => v;
|
|
21934
|
+
function __exportSetter2(name, newValue) {
|
|
21935
|
+
this[name] = __returnValue2.bind(null, newValue);
|
|
21936
|
+
}
|
|
21915
21937
|
var __export2 = (target, all) => {
|
|
21916
21938
|
for (var name in all)
|
|
21917
21939
|
__defProp2(target, name, {
|
|
21918
21940
|
get: all[name],
|
|
21919
21941
|
enumerable: true,
|
|
21920
21942
|
configurable: true,
|
|
21921
|
-
set: (
|
|
21943
|
+
set: __exportSetter2.bind(all, name)
|
|
21922
21944
|
});
|
|
21923
21945
|
};
|
|
21924
21946
|
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
@@ -27150,6 +27172,34 @@ function safeParseInt(value, defaultValue = 0) {
|
|
|
27150
27172
|
const parsed = parseInt(value, 10);
|
|
27151
27173
|
return isNaN(parsed) ? defaultValue : parsed;
|
|
27152
27174
|
}
|
|
27175
|
+
function parse3DModelNode(data) {
|
|
27176
|
+
try {
|
|
27177
|
+
const jsonStr = data.slice("SVGNODE~".length);
|
|
27178
|
+
const svgData = JSON.parse(jsonStr);
|
|
27179
|
+
const attrs = svgData?.attrs;
|
|
27180
|
+
if (!attrs?.uuid) {
|
|
27181
|
+
return;
|
|
27182
|
+
}
|
|
27183
|
+
const [translationX, translationY] = String(attrs.c_origin ?? "0,0").split(",").map((value) => safeParseFloat(value));
|
|
27184
|
+
const [rotationX, rotationY, rotationZ] = String(attrs.c_rotation ?? "0,0,0").split(",").map((value) => safeParseFloat(value));
|
|
27185
|
+
return {
|
|
27186
|
+
name: attrs.title || "3D Model",
|
|
27187
|
+
uuid: attrs.uuid,
|
|
27188
|
+
translation: {
|
|
27189
|
+
x: translationX,
|
|
27190
|
+
y: translationY,
|
|
27191
|
+
z: safeParseFloat(String(attrs.z ?? "0"))
|
|
27192
|
+
},
|
|
27193
|
+
rotation: {
|
|
27194
|
+
x: rotationX,
|
|
27195
|
+
y: rotationY,
|
|
27196
|
+
z: rotationZ
|
|
27197
|
+
}
|
|
27198
|
+
};
|
|
27199
|
+
} catch {
|
|
27200
|
+
return;
|
|
27201
|
+
}
|
|
27202
|
+
}
|
|
27153
27203
|
function parseSymbolPin(pinData) {
|
|
27154
27204
|
try {
|
|
27155
27205
|
const segments = pinData.split("^^");
|
|
@@ -27629,16 +27679,10 @@ function parseFootprintShapes(shapes) {
|
|
|
27629
27679
|
break;
|
|
27630
27680
|
}
|
|
27631
27681
|
case "SVGNODE": {
|
|
27632
|
-
|
|
27633
|
-
|
|
27634
|
-
|
|
27635
|
-
|
|
27636
|
-
model3d = {
|
|
27637
|
-
name: svgData.attrs.title || "3D Model",
|
|
27638
|
-
uuid: svgData.attrs.uuid
|
|
27639
|
-
};
|
|
27640
|
-
}
|
|
27641
|
-
} catch {}
|
|
27682
|
+
const parsedModel3d = parse3DModelNode(line);
|
|
27683
|
+
if (parsedModel3d) {
|
|
27684
|
+
model3d = parsedModel3d;
|
|
27685
|
+
}
|
|
27642
27686
|
break;
|
|
27643
27687
|
}
|
|
27644
27688
|
case "SOLIDREGION": {
|
|
@@ -29746,6 +29790,9 @@ var KI_PAD_SHAPE = {
|
|
|
29746
29790
|
OVAL: "oval",
|
|
29747
29791
|
POLYGON: "custom"
|
|
29748
29792
|
};
|
|
29793
|
+
function normalize3DModelRotation(rotation) {
|
|
29794
|
+
return ((360 - rotation) % 360 + 360) % 360;
|
|
29795
|
+
}
|
|
29749
29796
|
function calculatePadCenter(pads) {
|
|
29750
29797
|
if (pads.length === 0) {
|
|
29751
29798
|
return { x: 0, y: 0 };
|
|
@@ -29874,7 +29921,7 @@ class FootprintConverter {
|
|
|
29874
29921
|
output += ` (embedded_fonts no)
|
|
29875
29922
|
`;
|
|
29876
29923
|
if (include3DModel && model3d && options.modelPath) {
|
|
29877
|
-
output += this.generate3DModel(options.modelPath);
|
|
29924
|
+
output += this.generate3DModel(options.modelPath, model3d, origin);
|
|
29878
29925
|
}
|
|
29879
29926
|
output += `)`;
|
|
29880
29927
|
return output;
|
|
@@ -30463,16 +30510,22 @@ ${justify ? ` (justify ${justify})
|
|
|
30463
30510
|
}
|
|
30464
30511
|
return output;
|
|
30465
30512
|
}
|
|
30466
|
-
generate3DModel(modelPath) {
|
|
30513
|
+
generate3DModel(modelPath, model3d, origin) {
|
|
30514
|
+
const offsetX = roundTo(toMM(model3d.translation.x - origin.x), 3);
|
|
30515
|
+
const offsetY = roundTo(-toMM(model3d.translation.y - origin.y), 3);
|
|
30516
|
+
const offsetZ = roundTo(-toMM(model3d.translation.z), 3);
|
|
30517
|
+
const rotateX = normalize3DModelRotation(model3d.rotation.x);
|
|
30518
|
+
const rotateY = normalize3DModelRotation(model3d.rotation.y);
|
|
30519
|
+
const rotateZ = normalize3DModelRotation(model3d.rotation.z);
|
|
30467
30520
|
return ` (model "${modelPath}"
|
|
30468
30521
|
(offset
|
|
30469
|
-
(xyz
|
|
30522
|
+
(xyz ${offsetX} ${offsetY} ${offsetZ})
|
|
30470
30523
|
)
|
|
30471
30524
|
(scale
|
|
30472
30525
|
(xyz 1 1 1)
|
|
30473
30526
|
)
|
|
30474
30527
|
(rotate
|
|
30475
|
-
(xyz
|
|
30528
|
+
(xyz ${rotateX} ${rotateY} ${rotateZ})
|
|
30476
30529
|
)
|
|
30477
30530
|
)
|
|
30478
30531
|
`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jlcpcb/mcp",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "MCP server for JLC/EasyEDA component sourcing, library fetching, and conversion to KiCad format",
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
"build": "bun build ./src/index.ts --outdir ./dist --target node",
|
|
22
22
|
"start": "bun run ./src/index.ts",
|
|
23
23
|
"dev": "bun --watch ./src/index.ts",
|
|
24
|
+
"lint": "eslint src --ext .ts",
|
|
24
25
|
"typecheck": "tsc --noEmit",
|
|
25
26
|
"test": "bun test",
|
|
26
27
|
"clean": "rm -rf dist"
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { describe, expect, it } from 'bun:test';
|
|
2
|
+
|
|
3
|
+
import { toolHandlers, tools } from './index.js';
|
|
4
|
+
|
|
5
|
+
describe('tools', () => {
|
|
6
|
+
it('exposes a handler for every registered tool', () => {
|
|
7
|
+
expect(tools.length).toBeGreaterThan(0);
|
|
8
|
+
|
|
9
|
+
for (const tool of tools) {
|
|
10
|
+
expect(toolHandlers[tool.name]).toBeDefined();
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
});
|