bambu-printer-mcp 1.1.14 → 1.1.15

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/CONTRIBUTORS.md CHANGED
@@ -15,7 +15,7 @@ Thank you to everyone who builds, tests, reports problems, and shares real print
15
15
  | [John Randall (johntrandall)](https://github.com/johntrandall) | Captures A1 job manifests and contributes the SD-root/project-file fix in [#14](https://github.com/DMontgomery40/bambu-printer-mcp/pull/14). |
16
16
  | [Kyle Taylor (kyletaylored)](https://github.com/kyletaylored) | Contributes Claude Desktop extension packaging, prompted setup, and the writable-temp-directory fix in [#11](https://github.com/DMontgomery40/bambu-printer-mcp/pull/11). |
17
17
  | [Quinn (quinnpertuit)](https://github.com/quinnpertuit) | Investigates P2S transfer routing and contributes model-capability and serial-prefix analysis in [#9](https://github.com/DMontgomery40/bambu-printer-mcp/pull/9). The release uses the alternative P2S implementation from #15. |
18
- | [Vail (VailElla)](https://github.com/VailElla) | Contributes the native X2D transport, local eMMC investigation, and hardware evidence in [#10](https://github.com/DMontgomery40/bambu-printer-mcp/pull/10). The optional macOS native route is integrated with shared file/state/preflight checks, complete AMS mappings, helper cancellation, and clean-install coverage. Prior hardware evidence is credited separately from this release's mocked tests. |
18
+ | [Vail (VailElla)](https://github.com/VailElla) | Contributes the native X2D transport, local eMMC investigation, and hardware evidence in [#10](https://github.com/DMontgomery40/bambu-printer-mcp/pull/10). The optional macOS native route is integrated with shared file/state/preflight checks, complete AMS mappings, helper cancellation, and clean-install coverage. In [#26](https://github.com/DMontgomery40/bambu-printer-mcp/pull/26), replaces misleading partial FTPS listings with read-only, failure-reporting queries and verifies a real X2D empty-root listing; nonempty directories and failure paths use mocked coverage. |
19
19
 
20
20
  ## Project contributors
21
21
 
package/README.md CHANGED
@@ -603,6 +603,8 @@ High-signal fields:
603
603
 
604
604
  List files stored on the printer's SD card. Scans the `cache/`, `timelapse/`, and `logs/` directories and returns both a flat list and a directory-grouped breakdown.
605
605
 
606
+ This is a read-only query: it never creates directories. Optional directories absent from a successful root listing return empty lists. Authentication, TLS, permission, and transfer failures are reported as errors rather than empty or partial results.
607
+
606
608
  ```json
607
609
  {
608
610
  "host": "192.168.1.100",
@@ -1065,19 +1065,32 @@ export class BambuImplementation {
1065
1065
  };
1066
1066
  }
1067
1067
  async getFiles(host, serial, token) {
1068
- const printer = new BambuPrinter(host, serial, token);
1068
+ const client = new FTPClient(15000);
1069
1069
  const directories = ["cache", "timelapse", "logs"];
1070
1070
  const filesByDirectory = {};
1071
- await printer.manipulateFiles(async (context) => {
1071
+ try {
1072
+ await client.access({
1073
+ host,
1074
+ port: 990,
1075
+ user: "bblp",
1076
+ password: token,
1077
+ secure: "implicit",
1078
+ secureOptions: ftpsSecureOptions(host),
1079
+ });
1080
+ await this.waitForTlsSession(client);
1081
+ // Discover absent optional directories without creating them or treating
1082
+ // ambiguous FTP 550 responses (including permission errors) as emptiness.
1083
+ const root = await client.list("/");
1072
1084
  for (const directory of directories) {
1073
- try {
1074
- filesByDirectory[directory] = await context.readDir(directory);
1075
- }
1076
- catch {
1077
- filesByDirectory[directory] = [];
1078
- }
1085
+ const present = root.some(entry => entry.name === directory && (entry.isDirectory || entry.isSymbolicLink));
1086
+ filesByDirectory[directory] = present
1087
+ ? (await client.list(`/${directory}`)).map(entry => entry.name)
1088
+ : [];
1079
1089
  }
1080
- });
1090
+ }
1091
+ finally {
1092
+ client.close();
1093
+ }
1081
1094
  const files = Object.entries(filesByDirectory).flatMap(([directory, names]) => names.map((name) => `${directory}/${name}`));
1082
1095
  return {
1083
1096
  files,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bambu-printer-mcp",
3
- "version": "1.1.14",
3
+ "version": "1.1.15",
4
4
  "description": "MCP server for Bambu Lab 3D printers with STL manipulation, slicing, and print management",
5
5
  "main": "dist/index.js",
6
6
  "repository": {
@@ -1257,19 +1257,32 @@ export class BambuImplementation {
1257
1257
  }
1258
1258
 
1259
1259
  async getFiles(host: string, serial: string, token: string) {
1260
- const printer = new BambuPrinter(host, serial, token);
1260
+ const client = new FTPClient(15_000);
1261
1261
  const directories = ["cache", "timelapse", "logs"];
1262
1262
  const filesByDirectory: Record<string, string[]> = {};
1263
1263
 
1264
- await printer.manipulateFiles(async (context) => {
1264
+ try {
1265
+ await client.access({
1266
+ host,
1267
+ port: 990,
1268
+ user: "bblp",
1269
+ password: token,
1270
+ secure: "implicit",
1271
+ secureOptions: ftpsSecureOptions(host),
1272
+ });
1273
+ await this.waitForTlsSession(client);
1274
+ // Discover absent optional directories without creating them or treating
1275
+ // ambiguous FTP 550 responses (including permission errors) as emptiness.
1276
+ const root = await client.list("/");
1265
1277
  for (const directory of directories) {
1266
- try {
1267
- filesByDirectory[directory] = await context.readDir(directory);
1268
- } catch {
1269
- filesByDirectory[directory] = [];
1270
- }
1278
+ const present = root.some(entry => entry.name === directory && (entry.isDirectory || entry.isSymbolicLink));
1279
+ filesByDirectory[directory] = present
1280
+ ? (await client.list(`/${directory}`)).map(entry => entry.name)
1281
+ : [];
1271
1282
  }
1272
- });
1283
+ } finally {
1284
+ client.close();
1285
+ }
1273
1286
 
1274
1287
  const files = Object.entries(filesByDirectory).flatMap(([directory, names]) =>
1275
1288
  names.map((name) => `${directory}/${name}`)