mcp-3d-printer-server 1.0.2 → 1.2.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/README.md CHANGED
@@ -1,3 +1,5 @@
1
+
2
+
1
3
  # MCP 3D Printer Server
2
4
 
3
5
  [![npm version](https://img.shields.io/npm/v/mcp-3d-printer-server.svg)](https://www.npmjs.com/package/mcp-3d-printer-server)
@@ -9,17 +11,19 @@
9
11
  [![Downloads](https://img.shields.io/npm/dm/mcp-3d-printer-server.svg)](https://www.npmjs.com/package/mcp-3d-printer-server)
10
12
  [![GitHub stars](https://img.shields.io/github/stars/dmontgomery40/mcp-3d-printer-server.svg?style=social&label=Star)](https://github.com/yourusername/mcp-3d-printer-server)
11
13
 
14
+
15
+ <a href="https://glama.ai/mcp/servers/7f6v2enbgk">
16
+ <img width="380" height="200" src="https://glama.ai/mcp/servers/7f6v2enbgk/badge" alt="3D Printer Server MCP server" />
17
+ </a>
18
+
12
19
  <details>
13
20
  <summary><strong>✨ What's New / Significant Updates (as of last session)</strong></summary>
14
21
 
15
- - **Bambu `.3mf` Printing:** Added the `print_3mf` tool specifically for Bambu Lab printers. This uploads the `.3mf` file and sends the print command directly via MQTT based on OpenBambuAPI specs.
16
- - **Direct MQTT Communication (Bambu):** Refactored Bambu command handling (`print_3mf`, `cancelJob`) to use direct MQTT (TLS port 8883) instead of relying solely on `bambu-js` for commands.
17
- - **`.3mf` File Parsing:** Implemented a parser (`src/3mf_parser.ts`) to read metadata and Bambu-specific slicer settings (from `project_settings.config`) within `.3mf` files.
18
- - **Bambu Preset Resources:** Added support for reading Bambu Studio preset files (`machine`, `filament`, `process`) as MCP resources (e.g., `preset://bambu/process/MyPreset`) if `BAMBU_STUDIO_CONFIG_PATH` is set.
19
- - **OrcaSlicer Integration:** Added support for using OrcaSlicer via its command-line interface for the `slice_stl` tool.
20
- - **New STL Manipulation Tools:** Added `merge_vertices`, `center_model`, and `lay_flat` tools for basic model preparation using `three.js`.
21
- - **Configuration Update:** Added `BAMBU_STUDIO_CONFIG_PATH` environment variable for preset loading.
22
- - **FTP Usage Note:** Acknowledged in documentation that file operations for Bambu currently use potentially unsecured FTP via `bambu-js`.
22
+ - **Dual Local Transports:** Added explicit `stdio` and `streamable-http` runtime modes with environment-based transport selection.
23
+ - **Bambu Reliability Pass:** Fixed Bambu argument wiring bugs, added FTP-backed file operations, improved status refresh behavior, and implemented practical command paths for `startJob`, `setTemperature`, and `print_3mf`.
24
+ - **Blender Bridge Tooling:** Added `blender_mcp_edit_model` with optional execution mode for model-edit collaboration workflows.
25
+ - **Transport Behavior Tests:** Added real behavior tests for both transports (`initialize`, `tools/list`, success + failing `tools/call`, origin rejection).
26
+ - **Docker Modernization:** Updated Docker build flow to work without BuildKit-specific features and verified streamable HTTP initialization in container smoke testing.
23
27
 
24
28
  </details>
25
29
 
@@ -81,6 +85,7 @@
81
85
  - [Visualization Limitations](#visualization-limitations)
82
86
  - [Performance Considerations](#performance-considerations)
83
87
  - [Testing Recommendations](#testing-recommendations)
88
+ - [Appendix: MCP in Practice (Code Execution, Scale, and Safety)](#appendix-mcp-in-practice-code-execution-scale-and-safety)
84
89
  - [Badges](#badges)
85
90
  - [License](#license)
86
91
 
@@ -206,9 +211,12 @@ TEMP_DIR=/path/to/temp/dir
206
211
  # Bambu Labs specific configuration
207
212
  BAMBU_SERIAL=your_printer_serial # REQUIRED for Bambu
208
213
  BAMBU_TOKEN=your_access_token # REQUIRED for Bambu
214
+ BAMBU_MODEL=p1s # REQUIRED for Bambu: p1s, p1p, x1c, x1e, a1, a1mini, h2d
215
+ BED_TYPE=textured_plate # Bed plate: textured_plate, cool_plate, engineering_plate, hot_plate
216
+ NOZZLE_DIAMETER=0.4 # Nozzle diameter in mm (default: 0.4)
209
217
 
210
218
  # Slicer configuration (for slice_stl tool)
211
- SLICER_TYPE=prusaslicer # Options: prusaslicer, cura, slic3r, orcaslicer
219
+ SLICER_TYPE=prusaslicer # Options: prusaslicer, cura, slic3r, orcaslicer, bambustudio
212
220
  SLICER_PATH=/path/to/slicer/executable
213
221
  SLICER_PROFILE=/path/to/slicer/profile
214
222
 
@@ -217,6 +225,18 @@ SLICER_PROFILE=/path/to/slicer/profile
217
225
  # Example Windows: C:\Users\your_user\AppData\Roaming\BambuStudio\user\YOUR_USER_ID
218
226
  # Example Linux: /home/your_user/.config/BambuStudio/user/YOUR_USER_ID
219
227
  BAMBU_STUDIO_CONFIG_PATH=
228
+
229
+ # MCP transport configuration
230
+ MCP_TRANSPORT=stdio # Options: stdio, streamable-http
231
+ MCP_HTTP_HOST=127.0.0.1
232
+ MCP_HTTP_PORT=3000
233
+ MCP_HTTP_PATH=/mcp
234
+ MCP_HTTP_STATEFUL=true
235
+ MCP_HTTP_JSON_RESPONSE=true
236
+ MCP_HTTP_ALLOWED_ORIGINS=http://localhost
237
+
238
+ # Optional bridge command for blender_mcp_edit_model execute=true mode
239
+ BLENDER_MCP_BRIDGE_COMMAND=
220
240
  ```
221
241
 
222
242
  ## Usage with Claude Desktop
@@ -249,7 +269,8 @@ BAMBU_STUDIO_CONFIG_PATH=
249
269
  "PRINTER_HOST": "your_printer_ip",
250
270
  "PRINTER_TYPE": "bambu",
251
271
  "BAMBU_SERIAL": "your_printer_serial",
252
- "BAMBU_TOKEN": "your_access_token"
272
+ "BAMBU_TOKEN": "your_access_token",
273
+ "BAMBU_MODEL": "p1s"
253
274
  }
254
275
  }
255
276
  }
@@ -294,8 +315,9 @@ Repetier-Server is a host software for 3D printers.
294
315
  Bambu Lab printers use MQTT for status and control and FTP for file operations.
295
316
 
296
317
  - Authentication: Serial number and access token required (set `BAMBU_SERIAL` and `BAMBU_TOKEN`)
297
- - Requirements: Printer must be on the same network or have cloud connection enabled
298
- - Compatible with: X1C, P1S, P1P, A1, and other Bambu Lab printers
318
+ - Printer model: **Required** (set `BAMBU_MODEL`). Valid values: `p1s`, `p1p`, `x1c`, `x1e`, `a1`, `a1mini`, `h2d`. This ensures the slicer generates correct G-code for your specific printer.
319
+ - Requirements: Printer must be on the same network with Developer Mode and LAN Only Mode enabled
320
+ - Compatible with: X1C, X1E, P1S, P1P, A1, A1 Mini, H2D
299
321
 
300
322
  #### Finding Your Bambu Printer's Serial Number and Access Token
301
323
 
@@ -654,19 +676,22 @@ Set the temperature of a printer component.
654
676
 
655
677
  Uploads a `.3mf` file to a Bambu printer via FTP and initiates the print job via an MQTT command. Allows overriding some print parameters like AMS mapping.
656
678
 
679
+ **`bambu_model` is required** -- it ensures the slicer generates G-code for the correct printer. Using the wrong model can cause the bed to crash into the nozzle and damage the printer. If not provided in the tool call and `BAMBU_MODEL` is not set in the environment, the server will ask interactively via MCP elicitation (if supported by your client) or return a clear error.
680
+
657
681
  ```json
658
682
  {
659
683
  "three_mf_path": "/path/to/your_model.3mf",
660
- "host": "your_bambu_ip", // Optional if default is set
661
- "bambu_serial": "YOUR_SERIAL", // Optional if default is set
662
- "bambu_token": "YOUR_TOKEN", // Optional if default is set
663
- // Optional Overrides:
664
- "use_ams": true, // Default: true
665
- "ams_mapping": [0, 1, 2, 3], // Array of AMS slot indices to use
666
- "bed_leveling": true, // Default: true
667
- "flow_calibration": false, // Default: false
668
- "vibration_calibration": false, // Default: false
669
- "timelapse": false // Default: false
684
+ "bambu_model": "p1s",
685
+ "bed_type": "textured_plate",
686
+ "host": "your_bambu_ip",
687
+ "bambu_serial": "YOUR_SERIAL",
688
+ "bambu_token": "YOUR_TOKEN",
689
+ "use_ams": true,
690
+ "ams_mapping": [0, 1, 2, 3],
691
+ "bed_leveling": true,
692
+ "flow_calibration": false,
693
+ "vibration_calibration": false,
694
+ "timelapse": false
670
695
  }
671
696
  ```
672
697
 
@@ -742,17 +767,17 @@ Here are some example commands you can give to Claude after connecting the MCP s
742
767
 
743
768
  Due to the nature of the Bambu Lab printer API, there are some limitations:
744
769
 
745
- 1. **Starting prints**: Starting a print requires the 3MF project file path, gcode file name, print name, and MD5 hash. The simplified API in this server doesn't support this fully yet.
770
+ 1. **Printable 3MF requirement:** `print_3mf` requires a sliced 3MF that includes at least one `Metadata/plate_<n>.gcode` entry so the server can compute MD5 and start the job correctly.
746
771
 
747
- 2. **Temperature control**: The Bambu API doesn't provide direct methods to set temperatures. This would require custom G-code commands.
772
+ 2. **AMS behavior caveat:** The current `bambu-js` project-file command path always sends `use_ams=true`; passing `use_ams=false` is treated as best-effort and surfaced with a warning.
748
773
 
749
- 3. **File management**: Files must be uploaded to the "gcodes" directory on the printer.
774
+ 3. **Temperature control path:** Temperature updates are implemented through G-code command dispatch (`M104`/`M140`) over MQTT, so effective behavior still depends on printer firmware acceptance and current printer state.
750
775
 
751
- 4. **FTP Security:** File operations currently use the printer's FTP server, which may be unsecured (plain FTP).
776
+ 4. **File transfer channel:** File operations use Bambu's FTPS path (port 990) via `bambu-js`. This is more secure than plain FTP, but still assumes a trusted local network environment and library-managed TLS behavior.
752
777
 
753
- 5. **Parameter Overrides:** Only parameters supported by the MQTT `project_file` command can be overridden via the `print_3mf` tool (e.g., AMS usage, calibration flags). Slicer settings like layer height or temperature cannot be changed at print time via this command.
778
+ 5. **Direct start path scope:** `startJob` currently targets `.gcode` files on printer storage; `.3mf` jobs should be initiated through `print_3mf` so metadata and plate selection are handled.
754
779
 
755
- 6. **Status Updates:** Full real-time status monitoring via MQTT needs further implementation.
780
+ 6. **Status consistency:** Status reads force a `pushall` refresh when possible, but complete real-time, event-stream status semantics across all Bambu models still need deeper hardening.
756
781
 
757
782
  ## Limitations and Considerations
758
783
 
@@ -780,6 +805,57 @@ Due to the nature of the Bambu Lab printer API, there are some limitations:
780
805
  - Test modifications on simple geometries before attempting complex ones
781
806
  - Consider running on a system with at least 4GB of available RAM for larger operations
782
807
 
808
+ ## Appendix: MCP in Practice (Code Execution, Scale, and Safety)
809
+
810
+ Last updated: 2026-02-24
811
+
812
+ ### State of MCP Right Now
813
+ MCP remains a high-value protocol for interoperability, but large tool surfaces have a real downside: tool schemas, retries, and tool-call traces can flood the context window. More tools often means more token overhead unless the execution model is disciplined.
814
+
815
+ ### Why Code Mode / Code Execution Has Become Important
816
+ Recent production workflows increasingly move orchestration out of conversational turns and into executable code loops. This keeps context leaner, makes behavior easier to audit, and improves reproducibility.
817
+
818
+ Core reading:
819
+ - Cloudflare: https://blog.cloudflare.com/code-mode/
820
+ - Cloudflare: https://blog.cloudflare.com/code-execution-with-mcp/
821
+ - Anthropic: https://www.anthropic.com/engineering/code-execution-with-mcp
822
+
823
+ ### Setup Guidance for Users
824
+ For practical day-to-day use, start with a codemode-oriented gateway and keep direct tool exposure narrow:
825
+ - `codemode-mcp`: https://github.com/jx-codes/codemode-mcp
826
+ - UTCP routing guidance: https://www.utcp.io
827
+
828
+ Even with strong setup, model/tool usage can still be inconsistent across client versions and model releases, so retries and deterministic fallbacks are still required.
829
+
830
+ ### Peter Steinberger Workflow Pattern
831
+ A high-signal pattern is converting broad MCP toolsets into targeted CLIs so the model calls fewer, better-defined commands:
832
+ - MCPorter: https://github.com/steipete/mcporter
833
+ - OpenClaw: https://github.com/steipete/openclaw
834
+
835
+ ### What Works Best With Which Clients
836
+ - Claude Code, Codex CLI, and Cursor agent modes: strong fit for direct MCP and code-execution workflows.
837
+ - Thin hosted chat clients: usually better when MCP servers are wrapped behind narrower CLIs/gateways.
838
+ - Large multi-tool servers: best when grouped into task-specific wrappers instead of exposing every tool directly.
839
+
840
+ This ecosystem changes quickly; if you are reading this later, parts of this section may already be stale.
841
+
842
+ ### Prompt Injection: Risks, Consequences, and Mitigations
843
+ Prompt injection is still an open problem for tool-using agents. It is manageable, but not solved.
844
+
845
+ Primary risks:
846
+ - Hidden malicious instructions in remote content or tool output.
847
+ - Secret exfiltration via unintended network/tool calls.
848
+ - Unauthorized state changes (filesystem, infrastructure, or printer actions).
849
+
850
+ Practical mitigations:
851
+ - Least-privilege credentials and short-lived tokens.
852
+ - Strict schema validation and explicit allowlists for actions/hosts.
853
+ - Human confirmation gates for destructive operations.
854
+ - Execution sandboxing with resource/time limits.
855
+ - Structured logs and replayable runs for incident response.
856
+
857
+ Treat tool output as untrusted input by default.
858
+
783
859
  ## Badges
784
860
 
785
861
  | Badge | Description |
@@ -795,4 +871,4 @@ Due to the nature of the Bambu Lab printer API, there are some limitations:
795
871
 
796
872
  ## License
797
873
 
798
- GPL-2.0
874
+ GPL-2.0
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env node
2
+ declare class ThreeDPrinterMCPServerHTTP {
3
+ private server;
4
+ private printerFactory;
5
+ private stlManipulator;
6
+ private app;
7
+ constructor();
8
+ private setupExpressApp;
9
+ private handleJSONRPCRequest;
10
+ setupErrorHandling(): void;
11
+ setupHandlers(): void;
12
+ setupResourceHandlers(): void;
13
+ setupToolHandlers(): void;
14
+ run(): Promise<void>;
15
+ }
16
+ export default ThreeDPrinterMCPServerHTTP;
@@ -0,0 +1,268 @@
1
+ #!/usr/bin/env node
2
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
3
+ import express from 'express';
4
+ import cors from 'cors';
5
+ import dotenv from "dotenv";
6
+ import fs from "fs";
7
+ import path from "path";
8
+ import { PrinterFactory } from "./printers/printer-factory.js";
9
+ import { STLManipulator } from "./stl/stl-manipulator.js";
10
+ // Load environment variables from .env file
11
+ dotenv.config();
12
+ // Default values
13
+ const DEFAULT_HOST = process.env.PRINTER_HOST || "localhost";
14
+ const DEFAULT_PORT = process.env.PRINTER_PORT || "80";
15
+ const DEFAULT_API_KEY = process.env.API_KEY || "";
16
+ const DEFAULT_TYPE = process.env.PRINTER_TYPE || "octoprint";
17
+ const TEMP_DIR = process.env.TEMP_DIR || path.join(process.cwd(), "temp");
18
+ // HTTP Server configuration
19
+ const HTTP_PORT = parseInt(process.env.HTTP_PORT || "3001");
20
+ // Slicer configuration
21
+ const DEFAULT_SLICER_TYPE = process.env.SLICER_TYPE || "prusaslicer";
22
+ const DEFAULT_SLICER_PATH = process.env.SLICER_PATH || "";
23
+ const DEFAULT_SLICER_PROFILE = process.env.SLICER_PROFILE || "";
24
+ // Bambu-specific default values
25
+ const DEFAULT_BAMBU_SERIAL = process.env.BAMBU_SERIAL || "";
26
+ const DEFAULT_BAMBU_TOKEN = process.env.BAMBU_TOKEN || "";
27
+ // Ensure temp directory exists
28
+ if (!fs.existsSync(TEMP_DIR)) {
29
+ fs.mkdirSync(TEMP_DIR, { recursive: true });
30
+ }
31
+ class ThreeDPrinterMCPServerHTTP {
32
+ constructor() {
33
+ this.server = new Server({
34
+ name: "mcp-3d-printer-server",
35
+ version: "1.0.0"
36
+ }, {
37
+ capabilities: {
38
+ resources: {},
39
+ tools: {},
40
+ prompts: {}
41
+ }
42
+ });
43
+ this.printerFactory = new PrinterFactory();
44
+ this.stlManipulator = new STLManipulator(TEMP_DIR);
45
+ this.app = express();
46
+ this.setupExpressApp();
47
+ this.setupHandlers();
48
+ this.setupErrorHandling();
49
+ }
50
+ setupExpressApp() {
51
+ // Enable CORS for all origins
52
+ this.app.use(cors({
53
+ origin: '*',
54
+ methods: ['GET', 'POST', 'OPTIONS'],
55
+ allowedHeaders: ['Content-Type', 'Accept'],
56
+ credentials: true
57
+ }));
58
+ // Parse JSON bodies
59
+ this.app.use(express.json({ limit: '50mb' }));
60
+ // Main MCP endpoint - supports both standard and streaming responses
61
+ this.app.post('/mcp', async (req, res) => {
62
+ const acceptHeader = req.get('Accept') || '';
63
+ const wantsStream = acceptHeader.includes('text/event-stream');
64
+ try {
65
+ const requests = Array.isArray(req.body) ? req.body : [req.body];
66
+ const responses = [];
67
+ for (const request of requests) {
68
+ const response = await this.handleJSONRPCRequest(request);
69
+ if (response) {
70
+ responses.push(response);
71
+ }
72
+ }
73
+ // If client wants streaming and we have responses, use SSE format
74
+ if (wantsStream && responses.length > 0) {
75
+ res.setHeader('Content-Type', 'text/event-stream');
76
+ res.setHeader('Cache-Control', 'no-cache');
77
+ res.setHeader('Connection', 'keep-alive');
78
+ for (const response of responses) {
79
+ res.write(`data: ${JSON.stringify(response)}\n\n`);
80
+ }
81
+ res.end();
82
+ }
83
+ else if (responses.length > 0) {
84
+ // Standard JSON response
85
+ res.json(responses.length === 1 ? responses[0] : responses);
86
+ }
87
+ else {
88
+ // No responses (notifications)
89
+ res.status(202).send();
90
+ }
91
+ }
92
+ catch (error) {
93
+ console.error('Error handling request:', error);
94
+ res.status(500).json({
95
+ jsonrpc: "2.0",
96
+ error: {
97
+ code: -32603,
98
+ message: "Internal error",
99
+ data: error instanceof Error ? error.message : String(error)
100
+ }
101
+ });
102
+ }
103
+ });
104
+ // GET endpoint for establishing SSE stream (Streamable HTTP)
105
+ this.app.get('/mcp', async (req, res) => {
106
+ const acceptHeader = req.get('Accept') || '';
107
+ if (!acceptHeader.includes('text/event-stream')) {
108
+ res.status(405).json({
109
+ error: 'Method not allowed. Use POST for non-streaming requests.'
110
+ });
111
+ return;
112
+ }
113
+ // Set SSE headers
114
+ res.setHeader('Content-Type', 'text/event-stream');
115
+ res.setHeader('Cache-Control', 'no-cache');
116
+ res.setHeader('Connection', 'keep-alive');
117
+ res.setHeader('X-Accel-Buffering', 'no');
118
+ // Send initial connection event
119
+ res.write(`event: open\ndata: {"type": "connection", "status": "connected"}\n\n`);
120
+ // Keep connection alive with periodic pings
121
+ const pingInterval = setInterval(() => {
122
+ if (!res.writableEnded) {
123
+ res.write(`event: ping\ndata: ${new Date().toISOString()}\n\n`);
124
+ }
125
+ }, 30000);
126
+ // Handle client disconnect
127
+ req.on('close', () => {
128
+ clearInterval(pingInterval);
129
+ res.end();
130
+ });
131
+ });
132
+ // Health check endpoint
133
+ this.app.get('/health', (req, res) => {
134
+ res.json({
135
+ status: 'ok',
136
+ server: 'mcp-3d-printer-server',
137
+ transport: 'streamable-http',
138
+ version: '1.0.0'
139
+ });
140
+ });
141
+ // Root endpoint
142
+ this.app.get('/', (req, res) => {
143
+ res.json({
144
+ name: 'MCP 3D Printer Server (HTTP)',
145
+ version: '1.0.0',
146
+ endpoints: {
147
+ mcp: '/mcp',
148
+ health: '/health'
149
+ },
150
+ transport: 'streamable-http',
151
+ features: ['stdio', 'sse', 'http'],
152
+ documentation: 'https://github.com/DMontgomery40/mcp-3D-printer-server'
153
+ });
154
+ });
155
+ }
156
+ async handleJSONRPCRequest(request) {
157
+ try {
158
+ // Route based on method
159
+ switch (request.method) {
160
+ case 'initialize':
161
+ return {
162
+ jsonrpc: "2.0",
163
+ id: request.id,
164
+ result: {
165
+ protocolVersion: "2025-03-26",
166
+ capabilities: this.server.capabilities,
167
+ serverInfo: {
168
+ name: "mcp-3d-printer-server",
169
+ version: "1.0.0"
170
+ }
171
+ }
172
+ };
173
+ case 'resources/list':
174
+ const resourcesResult = await this.server.handleRequest(request);
175
+ return {
176
+ jsonrpc: "2.0",
177
+ id: request.id,
178
+ result: resourcesResult
179
+ };
180
+ case 'resources/read':
181
+ const readResult = await this.server.handleRequest(request);
182
+ return {
183
+ jsonrpc: "2.0",
184
+ id: request.id,
185
+ result: readResult
186
+ };
187
+ case 'tools/list':
188
+ const toolsResult = await this.server.handleRequest(request);
189
+ return {
190
+ jsonrpc: "2.0",
191
+ id: request.id,
192
+ result: toolsResult
193
+ };
194
+ case 'tools/call':
195
+ const callResult = await this.server.handleRequest(request);
196
+ return {
197
+ jsonrpc: "2.0",
198
+ id: request.id,
199
+ result: callResult
200
+ };
201
+ default:
202
+ if (request.id) {
203
+ return {
204
+ jsonrpc: "2.0",
205
+ id: request.id,
206
+ error: {
207
+ code: -32601,
208
+ message: `Method not found: ${request.method}`
209
+ }
210
+ };
211
+ }
212
+ return null; // Notification
213
+ }
214
+ }
215
+ catch (error) {
216
+ if (request.id) {
217
+ return {
218
+ jsonrpc: "2.0",
219
+ id: request.id,
220
+ error: {
221
+ code: -32603,
222
+ message: "Internal error",
223
+ data: error instanceof Error ? error.message : String(error)
224
+ }
225
+ };
226
+ }
227
+ return null;
228
+ }
229
+ }
230
+ setupErrorHandling() {
231
+ this.server.onerror = (error) => {
232
+ console.error("[MCP Error]", error);
233
+ };
234
+ process.on("SIGINT", async () => {
235
+ console.log("\nShutting down HTTP server...");
236
+ await this.printerFactory.disconnectAll();
237
+ await this.server.close();
238
+ process.exit(0);
239
+ });
240
+ }
241
+ setupHandlers() {
242
+ this.setupResourceHandlers();
243
+ this.setupToolHandlers();
244
+ }
245
+ // Copy all handlers from original index.ts
246
+ setupResourceHandlers() {
247
+ // ... (copy from original)
248
+ }
249
+ setupToolHandlers() {
250
+ // ... (copy from original)
251
+ }
252
+ // Copy all delegating methods from original index.ts
253
+ // ... (copy all printer methods)
254
+ async run() {
255
+ // Start Express server
256
+ this.app.listen(HTTP_PORT, () => {
257
+ console.log(`🚀 MCP 3D Printer Server (HTTP) running on http://localhost:${HTTP_PORT}`);
258
+ console.log(`📡 MCP endpoint: http://localhost:${HTTP_PORT}/mcp`);
259
+ console.log(`✨ Supports both standard HTTP and Server-Sent Events`);
260
+ });
261
+ }
262
+ }
263
+ // Check if running as main module
264
+ if (import.meta.url === `file://${process.argv[1]}`) {
265
+ const server = new ThreeDPrinterMCPServerHTTP();
266
+ server.run().catch(console.error);
267
+ }
268
+ export default ThreeDPrinterMCPServerHTTP;