mcp-3d-printer-server 0.1.0

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.
@@ -0,0 +1,66 @@
1
+ import { PrinterImplementation } from "../types.js";
2
+ import fs from "fs";
3
+ import FormData from "form-data";
4
+ export class DuetImplementation extends PrinterImplementation {
5
+ async getStatus(host, port, apiKey) {
6
+ const url = `http://${host}:${port}/machine/status`;
7
+ const response = await this.apiClient.get(url);
8
+ return response.data;
9
+ }
10
+ async getFiles(host, port, apiKey) {
11
+ const url = `http://${host}:${port}/machine/file-list`;
12
+ const response = await this.apiClient.get(url);
13
+ return response.data;
14
+ }
15
+ async getFile(host, port, apiKey, filename) {
16
+ const url = `http://${host}:${port}/machine/file/${encodeURIComponent(filename)}`;
17
+ const response = await this.apiClient.get(url);
18
+ return response.data;
19
+ }
20
+ async uploadFile(host, port, apiKey, filePath, filename, print) {
21
+ const url = `http://${host}:${port}/machine/file-upload`;
22
+ const formData = new FormData();
23
+ formData.append("file", fs.createReadStream(filePath));
24
+ formData.append("filename", filename);
25
+ const response = await this.apiClient.post(url, formData, {
26
+ headers: {
27
+ ...formData.getHeaders()
28
+ }
29
+ });
30
+ if (print && response.data.err === 0) {
31
+ await this.startJob(host, port, apiKey, filename);
32
+ }
33
+ return response.data;
34
+ }
35
+ async startJob(host, port, apiKey, filename) {
36
+ const url = `http://${host}:${port}/machine/code`;
37
+ const response = await this.apiClient.post(url, {
38
+ code: `M32 "${filename}"`
39
+ });
40
+ return response.data;
41
+ }
42
+ async cancelJob(host, port, apiKey) {
43
+ const url = `http://${host}:${port}/machine/code`;
44
+ const response = await this.apiClient.post(url, {
45
+ code: "M0"
46
+ });
47
+ return response.data;
48
+ }
49
+ async setTemperature(host, port, apiKey, component, temperature) {
50
+ const url = `http://${host}:${port}/machine/code`;
51
+ let gcode;
52
+ if (component === "bed") {
53
+ gcode = `M140 S${temperature}`;
54
+ }
55
+ else if (component === "extruder") {
56
+ gcode = `M104 S${temperature}`;
57
+ }
58
+ else {
59
+ throw new Error(`Unsupported component: ${component}`);
60
+ }
61
+ const response = await this.apiClient.post(url, {
62
+ code: gcode
63
+ });
64
+ return response.data;
65
+ }
66
+ }
@@ -0,0 +1,10 @@
1
+ import { PrinterImplementation } from "../types.js";
2
+ export declare class KlipperImplementation extends PrinterImplementation {
3
+ getStatus(host: string, port: string, apiKey: string): Promise<any>;
4
+ getFiles(host: string, port: string, apiKey: string): Promise<any>;
5
+ getFile(host: string, port: string, apiKey: string, filename: string): Promise<any>;
6
+ uploadFile(host: string, port: string, apiKey: string, filePath: string, filename: string, print: boolean): Promise<any>;
7
+ startJob(host: string, port: string, apiKey: string, filename: string): Promise<any>;
8
+ cancelJob(host: string, port: string, apiKey: string): Promise<any>;
9
+ setTemperature(host: string, port: string, apiKey: string, component: string, temperature: number): Promise<any>;
10
+ }
@@ -0,0 +1,62 @@
1
+ import { PrinterImplementation } from "../types.js";
2
+ import fs from "fs";
3
+ import FormData from "form-data";
4
+ export class KlipperImplementation extends PrinterImplementation {
5
+ async getStatus(host, port, apiKey) {
6
+ const url = `http://${host}:${port}/printer/info`;
7
+ const response = await this.apiClient.get(url);
8
+ return response.data;
9
+ }
10
+ async getFiles(host, port, apiKey) {
11
+ const url = `http://${host}:${port}/server/files/list`;
12
+ const response = await this.apiClient.get(url);
13
+ return response.data;
14
+ }
15
+ async getFile(host, port, apiKey, filename) {
16
+ const url = `http://${host}:${port}/server/files/metadata?filename=${encodeURIComponent(filename)}`;
17
+ const response = await this.apiClient.get(url);
18
+ return response.data;
19
+ }
20
+ async uploadFile(host, port, apiKey, filePath, filename, print) {
21
+ const url = `http://${host}:${port}/server/files/upload`;
22
+ const formData = new FormData();
23
+ formData.append("file", fs.createReadStream(filePath));
24
+ formData.append("filename", filename);
25
+ const response = await this.apiClient.post(url, formData, {
26
+ headers: {
27
+ ...formData.getHeaders()
28
+ }
29
+ });
30
+ if (print && response.data.result === "success") {
31
+ await this.startJob(host, port, apiKey, filename);
32
+ }
33
+ return response.data;
34
+ }
35
+ async startJob(host, port, apiKey, filename) {
36
+ const url = `http://${host}:${port}/printer/print/start`;
37
+ const response = await this.apiClient.post(url, { filename });
38
+ return response.data;
39
+ }
40
+ async cancelJob(host, port, apiKey) {
41
+ const url = `http://${host}:${port}/printer/print/cancel`;
42
+ const response = await this.apiClient.post(url, null);
43
+ return response.data;
44
+ }
45
+ async setTemperature(host, port, apiKey, component, temperature) {
46
+ const url = `http://${host}:${port}/printer/gcode/script`;
47
+ let gcode;
48
+ if (component === "bed") {
49
+ gcode = `SET_HEATER_TEMPERATURE HEATER=heater_bed TARGET=${temperature}`;
50
+ }
51
+ else if (component === "extruder") {
52
+ gcode = `SET_HEATER_TEMPERATURE HEATER=extruder TARGET=${temperature}`;
53
+ }
54
+ else {
55
+ throw new Error(`Unsupported component: ${component}`);
56
+ }
57
+ const response = await this.apiClient.post(url, {
58
+ script: gcode
59
+ });
60
+ return response.data;
61
+ }
62
+ }
@@ -0,0 +1,10 @@
1
+ import { PrinterImplementation } from "../types.js";
2
+ export declare class OctoPrintImplementation extends PrinterImplementation {
3
+ getStatus(host: string, port: string, apiKey: string): Promise<any>;
4
+ getFiles(host: string, port: string, apiKey: string): Promise<any>;
5
+ getFile(host: string, port: string, apiKey: string, filename: string): Promise<any>;
6
+ uploadFile(host: string, port: string, apiKey: string, filePath: string, filename: string, print: boolean): Promise<any>;
7
+ startJob(host: string, port: string, apiKey: string, filename: string): Promise<any>;
8
+ cancelJob(host: string, port: string, apiKey: string): Promise<any>;
9
+ setTemperature(host: string, port: string, apiKey: string, component: string, temperature: number): Promise<any>;
10
+ }
@@ -0,0 +1,97 @@
1
+ import { PrinterImplementation } from "../types.js";
2
+ import fs from "fs";
3
+ import FormData from "form-data";
4
+ export class OctoPrintImplementation extends PrinterImplementation {
5
+ async getStatus(host, port, apiKey) {
6
+ const url = `http://${host}:${port}/api/printer`;
7
+ const response = await this.apiClient.get(url, {
8
+ headers: {
9
+ "X-Api-Key": apiKey
10
+ }
11
+ });
12
+ return response.data;
13
+ }
14
+ async getFiles(host, port, apiKey) {
15
+ const url = `http://${host}:${port}/api/files`;
16
+ const response = await this.apiClient.get(url, {
17
+ headers: {
18
+ "X-Api-Key": apiKey
19
+ }
20
+ });
21
+ return response.data;
22
+ }
23
+ async getFile(host, port, apiKey, filename) {
24
+ const url = `http://${host}:${port}/api/files/local/${filename}`;
25
+ const response = await this.apiClient.get(url, {
26
+ headers: {
27
+ "X-Api-Key": apiKey
28
+ }
29
+ });
30
+ return response.data;
31
+ }
32
+ async uploadFile(host, port, apiKey, filePath, filename, print) {
33
+ const url = `http://${host}:${port}/api/files/local`;
34
+ const formData = new FormData();
35
+ formData.append("file", fs.createReadStream(filePath));
36
+ formData.append("filename", filename);
37
+ if (print) {
38
+ formData.append("print", "true");
39
+ }
40
+ const response = await this.apiClient.post(url, formData, {
41
+ headers: {
42
+ "X-Api-Key": apiKey,
43
+ ...formData.getHeaders()
44
+ }
45
+ });
46
+ return response.data;
47
+ }
48
+ async startJob(host, port, apiKey, filename) {
49
+ const url = `http://${host}:${port}/api/files/local/${filename}`;
50
+ const response = await this.apiClient.post(url, {
51
+ command: "select",
52
+ print: true
53
+ }, {
54
+ headers: {
55
+ "X-Api-Key": apiKey,
56
+ "Content-Type": "application/json"
57
+ }
58
+ });
59
+ return response.data;
60
+ }
61
+ async cancelJob(host, port, apiKey) {
62
+ const url = `http://${host}:${port}/api/job`;
63
+ const response = await this.apiClient.post(url, {
64
+ command: "cancel"
65
+ }, {
66
+ headers: {
67
+ "X-Api-Key": apiKey,
68
+ "Content-Type": "application/json"
69
+ }
70
+ });
71
+ return response.data;
72
+ }
73
+ async setTemperature(host, port, apiKey, component, temperature) {
74
+ let url = `http://${host}:${port}/api/printer/tool`;
75
+ const data = {};
76
+ if (component === "bed") {
77
+ data.command = "target";
78
+ data.target = temperature;
79
+ url = `http://${host}:${port}/api/printer/bed`;
80
+ }
81
+ else if (component.startsWith("extruder")) {
82
+ data.command = "target";
83
+ data.targets = {};
84
+ data.targets[component] = temperature;
85
+ }
86
+ else {
87
+ throw new Error(`Unsupported component: ${component}`);
88
+ }
89
+ const response = await this.apiClient.post(url, data, {
90
+ headers: {
91
+ "X-Api-Key": apiKey,
92
+ "Content-Type": "application/json"
93
+ }
94
+ });
95
+ return response.data;
96
+ }
97
+ }
@@ -0,0 +1,9 @@
1
+ import { PrinterImplementation } from "../types.js";
2
+ export declare class PrinterFactory {
3
+ private implementations;
4
+ private bambuPrinterStore;
5
+ private apiClient;
6
+ constructor();
7
+ getImplementation(type: string): PrinterImplementation;
8
+ disconnectAll(): Promise<void>;
9
+ }
@@ -0,0 +1,33 @@
1
+ import { BambuPrinterStore } from "../types.js";
2
+ import { OctoPrintImplementation } from "./octoprint.js";
3
+ import { KlipperImplementation } from "./klipper.js";
4
+ import { DuetImplementation } from "./duet.js";
5
+ import { RepetierImplementation } from "./repetier.js";
6
+ import { BambuImplementation } from "./bambu.js";
7
+ import { PrusaImplementation } from "./prusa.js";
8
+ import { CrealityImplementation } from "./creality.js";
9
+ import axios from "axios";
10
+ export class PrinterFactory {
11
+ constructor() {
12
+ this.implementations = new Map();
13
+ this.bambuPrinterStore = new BambuPrinterStore();
14
+ this.apiClient = axios.create({ timeout: 10000 });
15
+ this.implementations.set("octoprint", new OctoPrintImplementation(this.apiClient));
16
+ this.implementations.set("klipper", new KlipperImplementation(this.apiClient));
17
+ this.implementations.set("duet", new DuetImplementation(this.apiClient));
18
+ this.implementations.set("repetier", new RepetierImplementation(this.apiClient));
19
+ this.implementations.set("bambu", new BambuImplementation(this.apiClient, this.bambuPrinterStore));
20
+ this.implementations.set("prusa", new PrusaImplementation(this.apiClient));
21
+ this.implementations.set("creality", new CrealityImplementation(this.apiClient));
22
+ }
23
+ getImplementation(type) {
24
+ const implementation = this.implementations.get(type.toLowerCase());
25
+ if (!implementation) {
26
+ throw new Error(`Unsupported printer type: ${type}`);
27
+ }
28
+ return implementation;
29
+ }
30
+ async disconnectAll() {
31
+ await this.bambuPrinterStore.disconnectAll();
32
+ }
33
+ }
@@ -0,0 +1,10 @@
1
+ import { PrinterImplementation } from "../types.js";
2
+ export declare class PrusaImplementation extends PrinterImplementation {
3
+ getStatus(host: string, port: string, apiKey: string): Promise<any>;
4
+ getFiles(host: string, port: string, apiKey: string): Promise<any>;
5
+ getFile(host: string, port: string, apiKey: string, filename: string): Promise<any>;
6
+ uploadFile(host: string, port: string, apiKey: string, filePath: string, filename: string, print: boolean): Promise<any>;
7
+ startJob(host: string, port: string, apiKey: string, filename: string): Promise<any>;
8
+ cancelJob(host: string, port: string, apiKey: string): Promise<any>;
9
+ setTemperature(host: string, port: string, apiKey: string, component: string, temperature: number): Promise<any>;
10
+ }
@@ -0,0 +1,93 @@
1
+ import { PrinterImplementation } from "../types.js";
2
+ import fs from "fs";
3
+ import FormData from "form-data";
4
+ export class PrusaImplementation extends PrinterImplementation {
5
+ async getStatus(host, port, apiKey) {
6
+ const url = `http://${host}:${port}/api/v1/printer`;
7
+ const response = await this.apiClient.get(url, {
8
+ headers: {
9
+ "X-Api-Key": apiKey
10
+ }
11
+ });
12
+ return response.data;
13
+ }
14
+ async getFiles(host, port, apiKey) {
15
+ const url = `http://${host}:${port}/api/v1/storage`;
16
+ const response = await this.apiClient.get(url, {
17
+ headers: {
18
+ "X-Api-Key": apiKey
19
+ }
20
+ });
21
+ return response.data;
22
+ }
23
+ async getFile(host, port, apiKey, filename) {
24
+ const url = `http://${host}:${port}/api/v1/storage/${encodeURIComponent(filename)}`;
25
+ const response = await this.apiClient.get(url, {
26
+ headers: {
27
+ "X-Api-Key": apiKey
28
+ }
29
+ });
30
+ return response.data;
31
+ }
32
+ async uploadFile(host, port, apiKey, filePath, filename, print) {
33
+ const url = `http://${host}:${port}/api/v1/storage`;
34
+ const formData = new FormData();
35
+ formData.append("file", fs.createReadStream(filePath));
36
+ formData.append("filename", filename);
37
+ const response = await this.apiClient.post(url, formData, {
38
+ headers: {
39
+ "X-Api-Key": apiKey,
40
+ ...formData.getHeaders()
41
+ }
42
+ });
43
+ if (print && response.data.success) {
44
+ await this.startJob(host, port, apiKey, filename);
45
+ }
46
+ return response.data;
47
+ }
48
+ async startJob(host, port, apiKey, filename) {
49
+ const url = `http://${host}:${port}/api/v1/job`;
50
+ const response = await this.apiClient.post(url, {
51
+ command: "start",
52
+ file: filename
53
+ }, {
54
+ headers: {
55
+ "X-Api-Key": apiKey,
56
+ "Content-Type": "application/json"
57
+ }
58
+ });
59
+ return response.data;
60
+ }
61
+ async cancelJob(host, port, apiKey) {
62
+ const url = `http://${host}:${port}/api/v1/job`;
63
+ const response = await this.apiClient.post(url, {
64
+ command: "cancel"
65
+ }, {
66
+ headers: {
67
+ "X-Api-Key": apiKey,
68
+ "Content-Type": "application/json"
69
+ }
70
+ });
71
+ return response.data;
72
+ }
73
+ async setTemperature(host, port, apiKey, component, temperature) {
74
+ const url = `http://${host}:${port}/api/v1/printer/temperature`;
75
+ let data = { command: "set" };
76
+ if (component === "bed") {
77
+ data.target = { bed: temperature };
78
+ }
79
+ else if (component.startsWith("extruder")) {
80
+ data.target = { tool0: temperature }; // Prusa typically uses tool0 for the extruder
81
+ }
82
+ else {
83
+ throw new Error(`Unsupported component: ${component}`);
84
+ }
85
+ const response = await this.apiClient.post(url, data, {
86
+ headers: {
87
+ "X-Api-Key": apiKey,
88
+ "Content-Type": "application/json"
89
+ }
90
+ });
91
+ return response.data;
92
+ }
93
+ }
@@ -0,0 +1,10 @@
1
+ import { PrinterImplementation } from "../types.js";
2
+ export declare class RepetierImplementation extends PrinterImplementation {
3
+ getStatus(host: string, port: string, apiKey: string): Promise<any>;
4
+ getFiles(host: string, port: string, apiKey: string): Promise<any>;
5
+ getFile(host: string, port: string, apiKey: string, filename: string): Promise<any>;
6
+ uploadFile(host: string, port: string, apiKey: string, filePath: string, filename: string, print: boolean): Promise<any>;
7
+ startJob(host: string, port: string, apiKey: string, filename: string): Promise<any>;
8
+ cancelJob(host: string, port: string, apiKey: string): Promise<any>;
9
+ setTemperature(host: string, port: string, apiKey: string, component: string, temperature: number): Promise<any>;
10
+ }
@@ -0,0 +1,59 @@
1
+ import { PrinterImplementation } from "../types.js";
2
+ import fs from "fs";
3
+ import FormData from "form-data";
4
+ export class RepetierImplementation extends PrinterImplementation {
5
+ async getStatus(host, port, apiKey) {
6
+ const url = `http://${host}:${port}/printer/api/?a=getPrinterInfo&apikey=${apiKey}`;
7
+ const response = await this.apiClient.get(url);
8
+ return response.data;
9
+ }
10
+ async getFiles(host, port, apiKey) {
11
+ const url = `http://${host}:${port}/printer/api/?a=ls&apikey=${apiKey}`;
12
+ const response = await this.apiClient.get(url);
13
+ return response.data;
14
+ }
15
+ async getFile(host, port, apiKey, filename) {
16
+ const url = `http://${host}:${port}/printer/api/?a=getFileInfo&apikey=${apiKey}&filename=${encodeURIComponent(filename)}`;
17
+ const response = await this.apiClient.get(url);
18
+ return response.data;
19
+ }
20
+ async uploadFile(host, port, apiKey, filePath, filename, print) {
21
+ const url = `http://${host}:${port}/printer/api/`;
22
+ const formData = new FormData();
23
+ formData.append("a", "upload");
24
+ formData.append("apikey", apiKey);
25
+ formData.append("filename", filename);
26
+ formData.append("print", print ? "1" : "0");
27
+ formData.append("file", fs.createReadStream(filePath));
28
+ const response = await this.apiClient.post(url, formData, {
29
+ headers: {
30
+ ...formData.getHeaders()
31
+ }
32
+ });
33
+ return response.data;
34
+ }
35
+ async startJob(host, port, apiKey, filename) {
36
+ const url = `http://${host}:${port}/printer/api/?a=startJob&apikey=${apiKey}&filename=${encodeURIComponent(filename)}`;
37
+ const response = await this.apiClient.get(url);
38
+ return response.data;
39
+ }
40
+ async cancelJob(host, port, apiKey) {
41
+ const url = `http://${host}:${port}/printer/api/?a=stopJob&apikey=${apiKey}`;
42
+ const response = await this.apiClient.get(url);
43
+ return response.data;
44
+ }
45
+ async setTemperature(host, port, apiKey, component, temperature) {
46
+ let url;
47
+ if (component === "bed") {
48
+ url = `http://${host}:${port}/printer/api/?a=setBedTemp&apikey=${apiKey}&temp=${temperature}`;
49
+ }
50
+ else if (component === "extruder") {
51
+ url = `http://${host}:${port}/printer/api/?a=setExtruderTemp&apikey=${apiKey}&temp=${temperature}`;
52
+ }
53
+ else {
54
+ throw new Error(`Unsupported component: ${component}`);
55
+ }
56
+ const response = await this.apiClient.get(url);
57
+ return response.data;
58
+ }
59
+ }
@@ -0,0 +1,23 @@
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
+ }
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 ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "mcp-3d-printer-server",
3
+ "version": "0.1.0",
4
+ "description": "MCP server for connecting Claude with 3D printer management systems",
5
+ "main": "src/index.js",
6
+ "type": "module",
7
+ "scripts": {
8
+ "start": "node src/index.js",
9
+ "dev": "nodemon src/index.js",
10
+ "test": "echo \"Error: no test specified\" && exit 1"
11
+ },
12
+ "bin": {
13
+ "mcp-3d-printer-server": "./src/index.js"
14
+ },
15
+ "keywords": [
16
+ "mcp",
17
+ "3d-printer",
18
+ "octoprint",
19
+ "klipper",
20
+ "duet",
21
+ "repetier",
22
+ "bambu",
23
+ "prusa",
24
+ "creality",
25
+ "ender"
26
+ ],
27
+ "author": "David Montgomery",
28
+ "license": "GPL-2.0",
29
+ "dependencies": {
30
+ "@modelcontextprotocol/sdk": "^1.6.0",
31
+ "axios": "^1.6.2",
32
+ "bambu-js": "^2.2.2",
33
+ "dotenv": "^16.3.1",
34
+ "form-data": "^4.0.0"
35
+ },
36
+ "devDependencies": {
37
+ "@types/node": "^18.0.0",
38
+ "nodemon": "^2.0.22"
39
+ }
40
+ }
@@ -0,0 +1,49 @@
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();