mcp-3d-printer-server 1.0.0 → 1.0.2

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.
Files changed (42) hide show
  1. package/dist/3mf_parser.d.ts +3 -0
  2. package/dist/3mf_parser.js +216 -0
  3. package/dist/index.d.ts +2 -0
  4. package/dist/index.js +1018 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/printers/bambu.d.ts +42 -0
  7. package/dist/printers/bambu.js +284 -0
  8. package/dist/printers/creality.d.ts +10 -0
  9. package/dist/printers/creality.js +90 -0
  10. package/dist/printers/duet.d.ts +10 -0
  11. package/dist/printers/duet.js +66 -0
  12. package/dist/printers/klipper.d.ts +10 -0
  13. package/dist/printers/klipper.js +62 -0
  14. package/dist/printers/octoprint.d.ts +10 -0
  15. package/dist/printers/octoprint.js +97 -0
  16. package/dist/printers/printer-factory.d.ts +9 -0
  17. package/dist/printers/printer-factory.js +33 -0
  18. package/dist/printers/prusa.d.ts +10 -0
  19. package/dist/printers/prusa.js +93 -0
  20. package/dist/printers/repetier.d.ts +10 -0
  21. package/dist/printers/repetier.js +59 -0
  22. package/dist/stl/stl-manipulator.d.ts +140 -0
  23. package/dist/stl/stl-manipulator.js +1081 -0
  24. package/dist/test/stl-manipulator-test.d.ts +2 -0
  25. package/dist/test/stl-manipulator-test.js +91 -0
  26. package/dist/types.d.ts +75 -0
  27. package/dist/types.js +26 -0
  28. package/package.json +9 -3
  29. package/src/printers/bambu.ts +8 -3
  30. package/.dockerignore +0 -52
  31. package/.env.example +0 -17
  32. package/Dockerfile +0 -31
  33. package/docker-compose.yml +0 -31
  34. package/scripts/docker-run.sh +0 -25
  35. package/scripts/mcp-inspector.js +0 -49
  36. package/test/sample_cube.stl +0 -86
  37. package/test/sample_cube_extended.stl +0 -172
  38. package/test/sample_cube_modified.stl +0 -86
  39. package/test/sample_cube_rotated.stl +0 -86
  40. package/test/sample_cube_scaled.stl +0 -86
  41. package/test/sample_cube_translated.stl +0 -86
  42. package/tsconfig.json +0 -16
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,91 @@
1
+ #!/usr/bin/env node
2
+ import { STLManipulator } from '../stl/stl-manipulator.js';
3
+ import fs from 'fs';
4
+ import path from 'path';
5
+ import * as THREE from 'three';
6
+ // Create a test directory
7
+ const TEST_DIR = path.join(process.cwd(), 'test');
8
+ if (!fs.existsSync(TEST_DIR)) {
9
+ fs.mkdirSync(TEST_DIR, { recursive: true });
10
+ }
11
+ // Path for a sample STL file
12
+ const sampleStlPath = path.join(TEST_DIR, 'sample_cube.stl');
13
+ // Create a simple cube STL for testing if it doesn't exist
14
+ async function createSampleCube() {
15
+ if (fs.existsSync(sampleStlPath)) {
16
+ console.log('Sample STL already exists, skipping creation');
17
+ return sampleStlPath;
18
+ }
19
+ console.log('Creating sample cube STL...');
20
+ // Create a simple cube geometry
21
+ const geometry = new THREE.BoxGeometry(10, 10, 10);
22
+ const material = new THREE.MeshStandardMaterial();
23
+ const mesh = new THREE.Mesh(geometry, material);
24
+ // Import STLExporter
25
+ const { STLExporter } = await import('three/examples/jsm/exporters/STLExporter.js');
26
+ const exporter = new STLExporter();
27
+ // Export as STL
28
+ const stlString = exporter.parse(mesh);
29
+ // Write to file
30
+ fs.writeFileSync(sampleStlPath, stlString);
31
+ console.log(`Sample cube saved to ${sampleStlPath}`);
32
+ return sampleStlPath;
33
+ }
34
+ // Test the STL manipulator
35
+ async function testSTLManipulator() {
36
+ try {
37
+ // Create a sample STL for testing
38
+ const stlPath = await createSampleCube();
39
+ // Create an instance of the STL manipulator with the test directory
40
+ const manipulator = new STLManipulator(TEST_DIR);
41
+ // Listen for events from the manipulator
42
+ manipulator.on('operationComplete', (data) => {
43
+ console.log('Operation complete:', data);
44
+ });
45
+ manipulator.on('operationError', (data) => {
46
+ console.error('Operation error:', data);
47
+ });
48
+ // Test progress callback
49
+ const progressCallback = (progress, message) => {
50
+ console.log(`Progress: ${progress}% - ${message || ''}`);
51
+ };
52
+ // Test 1: Get information about the STL file
53
+ console.log('\n=== Test 1: Get STL Info ===');
54
+ const stlInfo = await manipulator.getSTLInfo(stlPath);
55
+ console.log('STL Info:', stlInfo);
56
+ // Test 2: Scale the STL file
57
+ console.log('\n=== Test 2: Scale STL ===');
58
+ const scaledStlPath = await manipulator.scaleSTL(stlPath, 2.0, progressCallback);
59
+ console.log(`Scaled STL saved to: ${scaledStlPath}`);
60
+ // Test 3: Rotate the STL file
61
+ console.log('\n=== Test 3: Rotate STL ===');
62
+ const rotatedStlPath = await manipulator.rotateSTL(stlPath, [45, 0, 0], progressCallback);
63
+ console.log(`Rotated STL saved to: ${rotatedStlPath}`);
64
+ // Test 4: Translate the STL file
65
+ console.log('\n=== Test 4: Translate STL ===');
66
+ const translatedStlPath = await manipulator.translateSTL(stlPath, [5, 10, 0], progressCallback);
67
+ console.log(`Translated STL saved to: ${translatedStlPath}`);
68
+ // Test 5: Extend the base of the STL file
69
+ console.log('\n=== Test 5: Extend Base ===');
70
+ const extendedStlPath = await manipulator.extendBase(stlPath, 0.5, progressCallback);
71
+ console.log(`Extended STL saved to: ${extendedStlPath}`);
72
+ // Test 6: Modify a section of the STL file
73
+ console.log('\n=== Test 6: Modify Section (Top) ===');
74
+ const modifiedStlPath = await manipulator.modifySection(stlPath, 'top', {
75
+ type: 'scale',
76
+ value: [1.5, 1.5, 1.5]
77
+ }, progressCallback);
78
+ console.log(`Modified STL saved to: ${modifiedStlPath}`);
79
+ // Test 7: Generate visualization of the STL file
80
+ console.log('\n=== Test 7: Generate Visualization ===');
81
+ const visualizationPath = await manipulator.generateVisualization(stlPath, 400, 400, progressCallback);
82
+ console.log(`Visualization saved to: ${visualizationPath}`);
83
+ console.log('\nAll tests completed successfully!');
84
+ }
85
+ catch (error) {
86
+ console.error('An error occurred during testing:', error);
87
+ process.exit(1);
88
+ }
89
+ }
90
+ // Run the tests
91
+ testSTLManipulator().catch(console.error);
@@ -0,0 +1,75 @@
1
+ import { AxiosInstance } from "axios";
2
+ import { BambuPrinter } from "bambu-js";
3
+ export type BambuFTP = {
4
+ readDir: (path: string) => Promise<string[]>;
5
+ sendFile: (sourcePath: string, destinationPath: string, progressCallback?: (progress: number) => void) => Promise<void>;
6
+ removeFile: (path: string) => Promise<void>;
7
+ };
8
+ export declare abstract class PrinterImplementation {
9
+ protected apiClient: AxiosInstance;
10
+ constructor(apiClient: AxiosInstance);
11
+ abstract getStatus(host: string, port: string, apiKey: string): Promise<any>;
12
+ abstract getFiles(host: string, port: string, apiKey: string): Promise<any>;
13
+ abstract getFile(host: string, port: string, apiKey: string, filename: string): Promise<any>;
14
+ abstract uploadFile(host: string, port: string, apiKey: string, filePath: string, filename: string, print: boolean): Promise<any>;
15
+ abstract startJob(host: string, port: string, apiKey: string, filename: string): Promise<any>;
16
+ abstract cancelJob(host: string, port: string, apiKey: string): Promise<any>;
17
+ abstract setTemperature(host: string, port: string, apiKey: string, component: string, temperature: number): Promise<any>;
18
+ }
19
+ export declare class BambuPrinterStore {
20
+ private printers;
21
+ get(host: string, serial: string, token: string): InstanceType<typeof BambuPrinter>;
22
+ disconnectAll(): Promise<void>;
23
+ }
24
+ export interface SectionBounds {
25
+ minX: number;
26
+ minY: number;
27
+ minZ: number;
28
+ maxX: number;
29
+ maxY: number;
30
+ maxZ: number;
31
+ }
32
+ export interface ThreeMFMetadata {
33
+ [key: string]: string;
34
+ }
35
+ export interface ThreeMFObject {
36
+ id: string;
37
+ name?: string;
38
+ type?: string;
39
+ mesh?: any;
40
+ }
41
+ export interface ThreeMFBuildItem {
42
+ objectId: string;
43
+ transform?: string;
44
+ }
45
+ export interface AMSFilamentMapping {
46
+ [filamentId: string]: number;
47
+ }
48
+ export interface BambuSlicerConfig {
49
+ layer_height?: number;
50
+ first_layer_height?: number;
51
+ sparse_infill_density?: number;
52
+ sparse_infill_pattern?: string;
53
+ support_enabled?: boolean;
54
+ support_type?: string;
55
+ support_threshold_angle?: number;
56
+ raft_layers?: number;
57
+ brim_width?: number;
58
+ wall_loops?: number;
59
+ top_shell_layers?: number;
60
+ bottom_shell_layers?: number;
61
+ nozzle_temperature?: number[];
62
+ bed_temperature?: number;
63
+ filament_type?: string[];
64
+ flow_ratio?: number[];
65
+ ams_mapping?: AMSFilamentMapping;
66
+ [key: string]: any;
67
+ }
68
+ export interface ThreeMFData {
69
+ metadata: ThreeMFMetadata;
70
+ objects: ThreeMFObject[];
71
+ build: {
72
+ items: ThreeMFBuildItem[];
73
+ };
74
+ slicerConfig?: Partial<BambuSlicerConfig>;
75
+ }
package/dist/types.js ADDED
@@ -0,0 +1,26 @@
1
+ import { BambuPrinter } from "bambu-js";
2
+ // Base class for printer implementations
3
+ export class PrinterImplementation {
4
+ constructor(apiClient) {
5
+ this.apiClient = apiClient;
6
+ }
7
+ }
8
+ // Store for Bambu printers
9
+ export class BambuPrinterStore {
10
+ constructor() {
11
+ this.printers = new Map();
12
+ }
13
+ get(host, serial, token) {
14
+ const key = `${host}-${serial}`;
15
+ if (!this.printers.has(key)) {
16
+ const printer = new BambuPrinter(host, serial, token);
17
+ this.printers.set(key, printer);
18
+ }
19
+ return this.printers.get(key);
20
+ }
21
+ async disconnectAll() {
22
+ for (const printer of this.printers.values()) {
23
+ await printer.disconnect();
24
+ }
25
+ }
26
+ }
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "mcp-3d-printer-server",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "MCP server for connecting Claude with 3D printer management systems",
5
- "main": "src/index.js",
5
+ "main": "dist/index.js",
6
6
  "repository": "https://github.com/DMontgomery40/mcp-3D-printer-server",
7
7
  "type": "module",
8
8
  "scripts": {
@@ -12,8 +12,14 @@
12
12
  "test": "npm run build && node dist/test/stl-manipulator-test.js"
13
13
  },
14
14
  "bin": {
15
- "mcp-3d-printer-server": "./src/index.js"
15
+ "mcp-3d-printer-server": "./dist/index.js"
16
16
  },
17
+ "files": [
18
+ "dist",
19
+ "src",
20
+ "README.md",
21
+ "LICENSE"
22
+ ],
17
23
  "keywords": [
18
24
  "mcp",
19
25
  "3d-printer",
@@ -194,10 +194,15 @@ export class BambuImplementation extends PrinterImplementation {
194
194
 
195
195
  // 1. Connect FTP if necessary (via bambu-js helper)
196
196
  if (!printerFTP.isConnected) {
197
- console.log(`Connecting Bambu FTP ${host} (${serial}) before uploading...`);
198
- await printerFTP.connect(); // Connects MQTT and FTP
197
+ console.log(`Connecting Bambu FTP ${host} (${serial}) on port 990 (assumed) before uploading...`);
198
+ try {
199
+ await printerFTP.connect(); // Connects MQTT and FTP
200
+ console.log(`Connected Bambu FTP successfully.`);
201
+ } catch (ftpConnectError) {
202
+ console.error(`Bambu FTP Connection Error:`, ftpConnectError);
203
+ throw new Error(`Failed to connect to Bambu FTP: ${(ftpConnectError as Error).message}`);
204
+ }
199
205
  // await printerFTP.awaitInitialState(10000); // Might not be needed just for FTP
200
- console.log(`Connected Bambu FTP.`);
201
206
  }
202
207
 
203
208
  // 2. Upload the file via FTP
package/.dockerignore DELETED
@@ -1,52 +0,0 @@
1
- # Ignore Git directory
2
- .git
3
-
4
- # Ignore Node dependencies
5
- node_modules/
6
-
7
- # Ignore build output
8
- dist/
9
- build/
10
- *.tsbuildinfo
11
-
12
- # Ignore environment files
13
- .env
14
- .env.*
15
- !.env.example
16
-
17
- # Ignore temporary files and directories
18
- temp/
19
- tmp/
20
- *.tmp
21
- *.temp
22
-
23
- # Ignore OS specific files
24
- .DS_Store
25
- .DS_Store?
26
- ._*
27
- .Spotlight-V100
28
- .Trashes
29
- ehthumbs.db
30
- Thumbs.db
31
-
32
- # Ignore Editor directories and files
33
- .idea/
34
- .vscode/
35
- *.swp
36
- *.swo
37
- *~
38
-
39
- # Ignore Logs
40
- logs/
41
- *.log
42
- npm-debug.log*
43
- yarn-debug.log*
44
- yarn-error.log*
45
-
46
- # Ignore test and coverage output
47
- coverage/
48
-
49
- # Ignore Docker specific files if not needed inside the image itself
50
- Dockerfile
51
- docker-compose.yml
52
- .dockerignore
package/.env.example DELETED
@@ -1,17 +0,0 @@
1
- # Printer configuration
2
- PRINTER_HOST=localhost
3
- PRINTER_PORT=80
4
- PRINTER_TYPE=octoprint
5
- API_KEY=your_api_key_here
6
-
7
- # Bambu-specific configuration
8
- BAMBU_SERIAL=your_bambu_serial_here
9
- BAMBU_TOKEN=your_bambu_token_here
10
-
11
- # Temp directory for file processing
12
- TEMP_DIR=./temp
13
-
14
- # Slicer configuration
15
- SLICER_TYPE=prusaslicer # Options: prusaslicer, cura, slic3r, orcaslicer
16
- SLICER_PATH=/path/to/slicer/executable
17
- SLICER_PROFILE=/path/to/slicer/profile
package/Dockerfile DELETED
@@ -1,31 +0,0 @@
1
- FROM node:18-alpine
2
-
3
- # Install build dependencies
4
- RUN apk add --no-cache make g++
5
-
6
- # Create app directory
7
- WORKDIR /app
8
-
9
- # Copy package.json and package-lock.json
10
- COPY package*.json ./
11
-
12
- # Install dependencies
13
- RUN npm ci
14
-
15
- # Copy source code
16
- COPY . .
17
-
18
- # Build the TypeScript code
19
- RUN npm run build
20
-
21
- # Create temp directory for file processing
22
- RUN mkdir -p temp
23
-
24
- # Expose any ports if needed (add if necessary)
25
- # EXPOSE 3000
26
-
27
- # Set environment variables (these can be overridden via docker-compose)
28
- ENV NODE_ENV=production
29
-
30
- # Run the application
31
- CMD ["node", "dist/index.js"]
@@ -1,31 +0,0 @@
1
- version: '3'
2
-
3
- services:
4
- mcp-3d-printer-server:
5
- build:
6
- context: .
7
- dockerfile: Dockerfile
8
- container_name: mcp-3d-printer-server
9
- volumes:
10
- - ./temp:/app/temp
11
- # Removed problematic host slicer mount - install slicer IN the Dockerfile
12
- # - ${SLICER_PATH:-/usr/local/bin}:${SLICER_PATH:-/usr/local/bin}:ro
13
- environment:
14
- - PRINTER_HOST=${PRINTER_HOST:-localhost}
15
- - PRINTER_PORT=${PRINTER_PORT:-80}
16
- - PRINTER_TYPE=${PRINTER_TYPE:-octoprint}
17
- - API_KEY=${API_KEY:-your_api_key_here}
18
- - BAMBU_SERIAL=${BAMBU_SERIAL:-}
19
- - BAMBU_TOKEN=${BAMBU_TOKEN:-}
20
- - TEMP_DIR=/app/temp
21
- - SLICER_TYPE=${SLICER_TYPE:-prusaslicer} # Options: prusaslicer, cura, slic3r, orcaslicer
22
- - SLICER_PATH=${SLICER_PATH:-} # Path INSIDE the container
23
- - SLICER_PROFILE=${SLICER_PROFILE:-}
24
- - BAMBU_STUDIO_CONFIG_PATH=${BAMBU_STUDIO_CONFIG_PATH:-} # Pass through preset path
25
- # If you want to provide stdin/stdout access (required for MCP)
26
- tty: true
27
- stdin_open: true
28
- # Restart policy
29
- restart: unless-stopped
30
- # Network configuration
31
- network_mode: host
@@ -1,25 +0,0 @@
1
- #!/bin/bash
2
-
3
- # Load environment variables from .env file if it exists
4
- if [ -f .env ]; then
5
- export $(grep -v '^#' .env | xargs)
6
- fi
7
-
8
- # Build the Docker image
9
- docker build -t mcp-3d-printer-server .
10
-
11
- # Run the Docker container
12
- docker run --rm -it \
13
- --network host \
14
- -e PRINTER_HOST="${PRINTER_HOST}" \
15
- -e PRINTER_PORT="${PRINTER_PORT}" \
16
- -e PRINTER_TYPE="${PRINTER_TYPE}" \
17
- -e API_KEY="${API_KEY}" \
18
- -e BAMBU_SERIAL="${BAMBU_SERIAL}" \
19
- -e BAMBU_TOKEN="${BAMBU_TOKEN}" \
20
- -e TEMP_DIR="/app/temp" \
21
- -e SLICER_TYPE="${SLICER_TYPE}" \
22
- -e SLICER_PATH="${SLICER_PATH}" \
23
- -e SLICER_PROFILE="${SLICER_PROFILE}" \
24
- -v "$(pwd)/temp:/app/temp" \
25
- mcp-3d-printer-server
@@ -1,49 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- import { MCP } from '@modelcontextprotocol/sdk';
4
- import dotenv from 'dotenv';
5
-
6
- dotenv.config();
7
-
8
- // Configuration from environment variables
9
- const MCP_PORT = process.env.MCP_PORT || 3000;
10
- const MCP_HOST = process.env.MCP_HOST || 'localhost';
11
-
12
- async function inspectMCP() {
13
- console.log('MCP Inspector Starting...');
14
- console.log(`Connecting to MCP server at ${MCP_HOST}:${MCP_PORT}`);
15
-
16
- try {
17
- const mcp = new MCP({
18
- port: MCP_PORT,
19
- host: MCP_HOST,
20
- });
21
-
22
- // Get available services
23
- const services = await mcp.getServices();
24
- console.log('\nAvailable Services:');
25
- console.table(services);
26
-
27
- // Test connection status
28
- const status = await mcp.getStatus();
29
- console.log('\nMCP Connection Status:');
30
- console.table(status);
31
-
32
- // Get capabilities if supported
33
- try {
34
- const capabilities = await mcp.getCapabilities();
35
- console.log('\nMCP Capabilities:');
36
- console.table(capabilities);
37
- } catch (e) {
38
- console.log('\nCapabilities endpoint not supported or error occurred');
39
- }
40
-
41
- console.log('\nMCP Inspection Complete');
42
- } catch (error) {
43
- console.error('\nError connecting to MCP server:');
44
- console.error(error.message);
45
- process.exit(1);
46
- }
47
- }
48
-
49
- inspectMCP();
@@ -1,86 +0,0 @@
1
- solid exported
2
- facet normal 1 0 0
3
- outer loop
4
- vertex 5 5 5
5
- vertex 5 -5 5
6
- vertex 5 5 -5
7
- endloop
8
- endfacet
9
- facet normal 1 0 0
10
- outer loop
11
- vertex 5 -5 5
12
- vertex 5 -5 -5
13
- vertex 5 5 -5
14
- endloop
15
- endfacet
16
- facet normal -1 0 0
17
- outer loop
18
- vertex -5 5 -5
19
- vertex -5 -5 -5
20
- vertex -5 5 5
21
- endloop
22
- endfacet
23
- facet normal -1 0 0
24
- outer loop
25
- vertex -5 -5 -5
26
- vertex -5 -5 5
27
- vertex -5 5 5
28
- endloop
29
- endfacet
30
- facet normal 0 1 0
31
- outer loop
32
- vertex -5 5 -5
33
- vertex -5 5 5
34
- vertex 5 5 -5
35
- endloop
36
- endfacet
37
- facet normal 0 1 0
38
- outer loop
39
- vertex -5 5 5
40
- vertex 5 5 5
41
- vertex 5 5 -5
42
- endloop
43
- endfacet
44
- facet normal 0 -1 0
45
- outer loop
46
- vertex -5 -5 5
47
- vertex -5 -5 -5
48
- vertex 5 -5 5
49
- endloop
50
- endfacet
51
- facet normal 0 -1 0
52
- outer loop
53
- vertex -5 -5 -5
54
- vertex 5 -5 -5
55
- vertex 5 -5 5
56
- endloop
57
- endfacet
58
- facet normal 0 0 1
59
- outer loop
60
- vertex -5 5 5
61
- vertex -5 -5 5
62
- vertex 5 5 5
63
- endloop
64
- endfacet
65
- facet normal 0 0 1
66
- outer loop
67
- vertex -5 -5 5
68
- vertex 5 -5 5
69
- vertex 5 5 5
70
- endloop
71
- endfacet
72
- facet normal 0 0 -1
73
- outer loop
74
- vertex 5 5 -5
75
- vertex 5 -5 -5
76
- vertex -5 5 -5
77
- endloop
78
- endfacet
79
- facet normal 0 0 -1
80
- outer loop
81
- vertex 5 -5 -5
82
- vertex -5 -5 -5
83
- vertex -5 5 -5
84
- endloop
85
- endfacet
86
- endsolid exported