@hasna/machines 0.0.9 → 0.0.11
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/LICENSE +2 -1
- package/README.md +15 -0
- package/dist/agent/index.js +6 -20
- package/dist/cli/index.js +958 -31
- package/dist/commands/clipboard-daemon.d.ts +6 -0
- package/dist/commands/clipboard-daemon.d.ts.map +1 -0
- package/dist/commands/clipboard-server.d.ts +2 -0
- package/dist/commands/clipboard-server.d.ts.map +1 -1
- package/dist/commands/heal-daemon.d.ts +36 -0
- package/dist/commands/heal-daemon.d.ts.map +1 -0
- package/dist/commands/heal.d.ts +122 -0
- package/dist/commands/heal.d.ts.map +1 -0
- package/dist/index.js +15 -29
- package/dist/mcp/http.d.ts +12 -0
- package/dist/mcp/http.d.ts.map +1 -0
- package/dist/mcp/index.js +165 -75
- package/dist/mcp/server.d.ts +1 -0
- package/dist/mcp/server.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/mcp/index.js
CHANGED
|
@@ -1,26 +1,41 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
// @bun
|
|
3
3
|
var __defProp = Object.defineProperty;
|
|
4
|
-
var __returnValue = (v) => v;
|
|
5
|
-
function __exportSetter(name, newValue) {
|
|
6
|
-
this[name] = __returnValue.bind(null, newValue);
|
|
7
|
-
}
|
|
8
4
|
var __export = (target, all) => {
|
|
9
5
|
for (var name in all)
|
|
10
6
|
__defProp(target, name, {
|
|
11
7
|
get: all[name],
|
|
12
8
|
enumerable: true,
|
|
13
9
|
configurable: true,
|
|
14
|
-
set:
|
|
10
|
+
set: (newValue) => all[name] = () => newValue
|
|
15
11
|
});
|
|
16
12
|
};
|
|
17
13
|
|
|
18
14
|
// src/mcp/index.ts
|
|
19
|
-
import { readFileSync as readFileSync7 } from "fs";
|
|
20
|
-
import { dirname as dirname5, join as join9 } from "path";
|
|
21
|
-
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
22
15
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
23
16
|
|
|
17
|
+
// src/version.ts
|
|
18
|
+
import { existsSync, readFileSync } from "fs";
|
|
19
|
+
import { dirname, join } from "path";
|
|
20
|
+
import { fileURLToPath } from "url";
|
|
21
|
+
function getPackageVersion() {
|
|
22
|
+
try {
|
|
23
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
24
|
+
const candidates = [join(here, "..", "package.json"), join(here, "..", "..", "package.json")];
|
|
25
|
+
const pkgPath = candidates.find((candidate) => existsSync(candidate));
|
|
26
|
+
if (!pkgPath) {
|
|
27
|
+
return "0.0.0";
|
|
28
|
+
}
|
|
29
|
+
return JSON.parse(readFileSync(pkgPath, "utf8")).version || "0.0.0";
|
|
30
|
+
} catch {
|
|
31
|
+
return "0.0.0";
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// src/mcp/http.ts
|
|
36
|
+
import { createServer } from "http";
|
|
37
|
+
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
38
|
+
|
|
24
39
|
// src/mcp/server.ts
|
|
25
40
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
26
41
|
|
|
@@ -3999,20 +4014,20 @@ var coerce = {
|
|
|
3999
4014
|
var NEVER = INVALID;
|
|
4000
4015
|
// src/commands/backup.ts
|
|
4001
4016
|
import { homedir } from "os";
|
|
4002
|
-
import { join } from "path";
|
|
4017
|
+
import { join as join2 } from "path";
|
|
4003
4018
|
function quote(value) {
|
|
4004
4019
|
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
4005
4020
|
}
|
|
4006
4021
|
function defaultBackupSources() {
|
|
4007
4022
|
const home = homedir();
|
|
4008
4023
|
return [
|
|
4009
|
-
|
|
4010
|
-
|
|
4011
|
-
|
|
4024
|
+
join2(home, ".hasna"),
|
|
4025
|
+
join2(home, ".ssh"),
|
|
4026
|
+
join2(home, ".secrets")
|
|
4012
4027
|
];
|
|
4013
4028
|
}
|
|
4014
4029
|
function buildBackupPlan(bucket, prefix = "machines") {
|
|
4015
|
-
const archivePath =
|
|
4030
|
+
const archivePath = join2(homedir(), ".hasna", "machines", "backup.tgz");
|
|
4016
4031
|
const sources = defaultBackupSources();
|
|
4017
4032
|
const steps = [
|
|
4018
4033
|
{
|
|
@@ -4063,33 +4078,33 @@ function runBackup(bucket, prefix = "machines", options = {}) {
|
|
|
4063
4078
|
}
|
|
4064
4079
|
|
|
4065
4080
|
// src/manifests.ts
|
|
4066
|
-
import { existsSync as
|
|
4081
|
+
import { existsSync as existsSync3, readFileSync as readFileSync2, writeFileSync } from "fs";
|
|
4067
4082
|
import { arch, homedir as homedir2, hostname, platform, userInfo } from "os";
|
|
4068
|
-
import { dirname as
|
|
4083
|
+
import { dirname as dirname3 } from "path";
|
|
4069
4084
|
|
|
4070
4085
|
// src/paths.ts
|
|
4071
|
-
import { existsSync, mkdirSync } from "fs";
|
|
4072
|
-
import { dirname, join as
|
|
4086
|
+
import { existsSync as existsSync2, mkdirSync } from "fs";
|
|
4087
|
+
import { dirname as dirname2, join as join3, resolve } from "path";
|
|
4073
4088
|
function homeDir() {
|
|
4074
4089
|
return process.env["HOME"] || process.env["USERPROFILE"] || "~";
|
|
4075
4090
|
}
|
|
4076
4091
|
function getDataDir() {
|
|
4077
|
-
return process.env["HASNA_MACHINES_DIR"] ||
|
|
4092
|
+
return process.env["HASNA_MACHINES_DIR"] || join3(homeDir(), ".hasna", "machines");
|
|
4078
4093
|
}
|
|
4079
4094
|
function getDbPath() {
|
|
4080
|
-
return process.env["HASNA_MACHINES_DB_PATH"] ||
|
|
4095
|
+
return process.env["HASNA_MACHINES_DB_PATH"] || join3(getDataDir(), "machines.db");
|
|
4081
4096
|
}
|
|
4082
4097
|
function getManifestPath() {
|
|
4083
|
-
return process.env["HASNA_MACHINES_MANIFEST_PATH"] ||
|
|
4098
|
+
return process.env["HASNA_MACHINES_MANIFEST_PATH"] || join3(getDataDir(), "machines.json");
|
|
4084
4099
|
}
|
|
4085
4100
|
function getNotificationsPath() {
|
|
4086
|
-
return process.env["HASNA_MACHINES_NOTIFICATIONS_PATH"] ||
|
|
4101
|
+
return process.env["HASNA_MACHINES_NOTIFICATIONS_PATH"] || join3(getDataDir(), "notifications.json");
|
|
4087
4102
|
}
|
|
4088
4103
|
function ensureParentDir(filePath) {
|
|
4089
4104
|
if (filePath === ":memory:")
|
|
4090
4105
|
return;
|
|
4091
|
-
const dir =
|
|
4092
|
-
if (!
|
|
4106
|
+
const dir = dirname2(resolve(filePath));
|
|
4107
|
+
if (!existsSync2(dir)) {
|
|
4093
4108
|
mkdirSync(dir, { recursive: true });
|
|
4094
4109
|
}
|
|
4095
4110
|
}
|
|
@@ -4154,10 +4169,10 @@ function getDefaultManifest() {
|
|
|
4154
4169
|
};
|
|
4155
4170
|
}
|
|
4156
4171
|
function readManifest(path = getManifestPath()) {
|
|
4157
|
-
if (!
|
|
4172
|
+
if (!existsSync3(path)) {
|
|
4158
4173
|
return getDefaultManifest();
|
|
4159
4174
|
}
|
|
4160
|
-
const raw = JSON.parse(
|
|
4175
|
+
const raw = JSON.parse(readFileSync2(path, "utf8"));
|
|
4161
4176
|
return fleetSchema.parse(raw);
|
|
4162
4177
|
}
|
|
4163
4178
|
function validateManifest(path = getManifestPath()) {
|
|
@@ -4181,7 +4196,7 @@ function getManifestMachine(machineId, path = getManifestPath()) {
|
|
|
4181
4196
|
function detectCurrentMachineManifest() {
|
|
4182
4197
|
const machineId = process.env["HASNA_MACHINES_MACHINE_ID"] || hostname();
|
|
4183
4198
|
const user = userInfo().username;
|
|
4184
|
-
const bunDir =
|
|
4199
|
+
const bunDir = dirname3(process.execPath);
|
|
4185
4200
|
return {
|
|
4186
4201
|
id: machineId,
|
|
4187
4202
|
hostname: hostname(),
|
|
@@ -4207,22 +4222,22 @@ import { hostname as hostname2 } from "os";
|
|
|
4207
4222
|
import { createRequire } from "module";
|
|
4208
4223
|
import { Database } from "bun:sqlite";
|
|
4209
4224
|
import {
|
|
4210
|
-
existsSync as
|
|
4225
|
+
existsSync as existsSync4,
|
|
4211
4226
|
mkdirSync as mkdirSync2,
|
|
4212
4227
|
readdirSync,
|
|
4213
4228
|
copyFileSync
|
|
4214
4229
|
} from "fs";
|
|
4215
4230
|
import { homedir as homedir3 } from "os";
|
|
4216
|
-
import { join as
|
|
4217
|
-
import { existsSync as existsSync22, mkdirSync as mkdirSync22, readFileSync as
|
|
4231
|
+
import { join as join4, relative } from "path";
|
|
4232
|
+
import { existsSync as existsSync22, mkdirSync as mkdirSync22, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "fs";
|
|
4218
4233
|
import { homedir as homedir22 } from "os";
|
|
4219
4234
|
import { join as join22 } from "path";
|
|
4220
4235
|
import { readdirSync as readdirSync2, existsSync as existsSync32 } from "fs";
|
|
4221
4236
|
import { join as join32 } from "path";
|
|
4222
4237
|
import { homedir as homedir32 } from "os";
|
|
4223
4238
|
import { homedir as homedir4 } from "os";
|
|
4224
|
-
import { join as
|
|
4225
|
-
import { join as join6, dirname as
|
|
4239
|
+
import { join as join42 } from "path";
|
|
4240
|
+
import { join as join6, dirname as dirname4 } from "path";
|
|
4226
4241
|
import { homedir as homedir5, platform as platform2 } from "os";
|
|
4227
4242
|
var __create = Object.create;
|
|
4228
4243
|
var __getProtoOf = Object.getPrototypeOf;
|
|
@@ -4255,9 +4270,9 @@ var __toESM = (mod, isNodeMode, target) => {
|
|
|
4255
4270
|
return to;
|
|
4256
4271
|
};
|
|
4257
4272
|
var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
4258
|
-
var
|
|
4259
|
-
function
|
|
4260
|
-
this[name] =
|
|
4273
|
+
var __returnValue = (v) => v;
|
|
4274
|
+
function __exportSetter(name, newValue) {
|
|
4275
|
+
this[name] = __returnValue.bind(null, newValue);
|
|
4261
4276
|
}
|
|
4262
4277
|
var __export2 = (target, all) => {
|
|
4263
4278
|
for (var name in all)
|
|
@@ -4265,7 +4280,7 @@ var __export2 = (target, all) => {
|
|
|
4265
4280
|
get: all[name],
|
|
4266
4281
|
enumerable: true,
|
|
4267
4282
|
configurable: true,
|
|
4268
|
-
set:
|
|
4283
|
+
set: __exportSetter.bind(all, name)
|
|
4269
4284
|
});
|
|
4270
4285
|
};
|
|
4271
4286
|
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
@@ -13387,17 +13402,17 @@ var init_zod = __esm(() => {
|
|
|
13387
13402
|
init_external();
|
|
13388
13403
|
});
|
|
13389
13404
|
function getDataDir2(serviceName) {
|
|
13390
|
-
const dir =
|
|
13405
|
+
const dir = join4(HASNA_DIR, serviceName);
|
|
13391
13406
|
mkdirSync2(dir, { recursive: true });
|
|
13392
13407
|
return dir;
|
|
13393
13408
|
}
|
|
13394
13409
|
function getDbPath2(serviceName) {
|
|
13395
13410
|
const dir = getDataDir2(serviceName);
|
|
13396
|
-
return
|
|
13411
|
+
return join4(dir, `${serviceName}.db`);
|
|
13397
13412
|
}
|
|
13398
13413
|
var HASNA_DIR;
|
|
13399
13414
|
var init_dotfile = __esm(() => {
|
|
13400
|
-
HASNA_DIR =
|
|
13415
|
+
HASNA_DIR = join4(homedir3(), ".hasna");
|
|
13401
13416
|
});
|
|
13402
13417
|
var exports_config = {};
|
|
13403
13418
|
__export2(exports_config, {
|
|
@@ -13420,7 +13435,7 @@ function getCloudConfig() {
|
|
|
13420
13435
|
return CloudConfigSchema.parse({});
|
|
13421
13436
|
}
|
|
13422
13437
|
try {
|
|
13423
|
-
const raw =
|
|
13438
|
+
const raw = readFileSync3(CONFIG_PATH, "utf-8");
|
|
13424
13439
|
return CloudConfigSchema.parse(JSON.parse(raw));
|
|
13425
13440
|
} catch {
|
|
13426
13441
|
return CloudConfigSchema.parse({});
|
|
@@ -13711,7 +13726,7 @@ class SyncProgressTracker {
|
|
|
13711
13726
|
init_adapter();
|
|
13712
13727
|
init_config();
|
|
13713
13728
|
init_discover();
|
|
13714
|
-
var AUTO_SYNC_CONFIG_PATH =
|
|
13729
|
+
var AUTO_SYNC_CONFIG_PATH = join42(homedir4(), ".hasna", "cloud", "config.json");
|
|
13715
13730
|
init_config();
|
|
13716
13731
|
init_adapter();
|
|
13717
13732
|
init_dotfile();
|
|
@@ -14089,16 +14104,16 @@ function runCertPlan(domains, options = {}) {
|
|
|
14089
14104
|
}
|
|
14090
14105
|
|
|
14091
14106
|
// src/commands/dns.ts
|
|
14092
|
-
import { existsSync as
|
|
14107
|
+
import { existsSync as existsSync5, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "fs";
|
|
14093
14108
|
import { join as join7 } from "path";
|
|
14094
14109
|
function getDnsPath() {
|
|
14095
14110
|
return join7(getDataDir(), "dns.json");
|
|
14096
14111
|
}
|
|
14097
14112
|
function readMappings() {
|
|
14098
14113
|
const path = getDnsPath();
|
|
14099
|
-
if (!
|
|
14114
|
+
if (!existsSync5(path))
|
|
14100
14115
|
return [];
|
|
14101
|
-
return JSON.parse(
|
|
14116
|
+
return JSON.parse(readFileSync4(path, "utf8"));
|
|
14102
14117
|
}
|
|
14103
14118
|
function writeMappings(mappings) {
|
|
14104
14119
|
const path = getDnsPath();
|
|
@@ -14400,7 +14415,7 @@ function runTailscaleInstall(machineId, options = {}) {
|
|
|
14400
14415
|
}
|
|
14401
14416
|
|
|
14402
14417
|
// src/commands/notifications.ts
|
|
14403
|
-
import { existsSync as
|
|
14418
|
+
import { existsSync as existsSync6, readFileSync as readFileSync5, writeFileSync as writeFileSync4 } from "fs";
|
|
14404
14419
|
var notificationChannelSchema = exports_external.object({
|
|
14405
14420
|
id: exports_external.string(),
|
|
14406
14421
|
type: exports_external.enum(["email", "webhook", "command"]),
|
|
@@ -14556,10 +14571,10 @@ function getDefaultNotificationConfig() {
|
|
|
14556
14571
|
};
|
|
14557
14572
|
}
|
|
14558
14573
|
function readNotificationConfig(path = getNotificationsPath()) {
|
|
14559
|
-
if (!
|
|
14574
|
+
if (!existsSync6(path)) {
|
|
14560
14575
|
return getDefaultNotificationConfig();
|
|
14561
14576
|
}
|
|
14562
|
-
return notificationConfigSchema.parse(JSON.parse(
|
|
14577
|
+
return notificationConfigSchema.parse(JSON.parse(readFileSync5(path, "utf8")));
|
|
14563
14578
|
}
|
|
14564
14579
|
function writeNotificationConfig(config, path = getNotificationsPath()) {
|
|
14565
14580
|
ensureParentDir(path);
|
|
@@ -14731,24 +14746,6 @@ function manifestValidate() {
|
|
|
14731
14746
|
return validateManifest(getManifestPath());
|
|
14732
14747
|
}
|
|
14733
14748
|
|
|
14734
|
-
// src/version.ts
|
|
14735
|
-
import { existsSync as existsSync6, readFileSync as readFileSync5 } from "fs";
|
|
14736
|
-
import { dirname as dirname4, join as join8 } from "path";
|
|
14737
|
-
import { fileURLToPath } from "url";
|
|
14738
|
-
function getPackageVersion() {
|
|
14739
|
-
try {
|
|
14740
|
-
const here = dirname4(fileURLToPath(import.meta.url));
|
|
14741
|
-
const candidates = [join8(here, "..", "package.json"), join8(here, "..", "..", "package.json")];
|
|
14742
|
-
const pkgPath = candidates.find((candidate) => existsSync6(candidate));
|
|
14743
|
-
if (!pkgPath) {
|
|
14744
|
-
return "0.0.0";
|
|
14745
|
-
}
|
|
14746
|
-
return JSON.parse(readFileSync5(pkgPath, "utf8")).version || "0.0.0";
|
|
14747
|
-
} catch {
|
|
14748
|
-
return "0.0.0";
|
|
14749
|
-
}
|
|
14750
|
-
}
|
|
14751
|
-
|
|
14752
14749
|
// src/commands/status.ts
|
|
14753
14750
|
function getStatus() {
|
|
14754
14751
|
const manifest = readManifest();
|
|
@@ -15268,6 +15265,9 @@ function getAgentStatus(machineId = getLocalMachineId()) {
|
|
|
15268
15265
|
}
|
|
15269
15266
|
|
|
15270
15267
|
// src/mcp/server.ts
|
|
15268
|
+
function buildServer(version = getPackageVersion()) {
|
|
15269
|
+
return createMcpServer(version);
|
|
15270
|
+
}
|
|
15271
15271
|
function createMcpServer(version) {
|
|
15272
15272
|
const server = new McpServer({ name: "machines", version });
|
|
15273
15273
|
server.tool("machines_status", "Return local machine fleet status paths and machine identity.", {}, async () => ({
|
|
@@ -15364,21 +15364,107 @@ function createMcpServer(version) {
|
|
|
15364
15364
|
return server;
|
|
15365
15365
|
}
|
|
15366
15366
|
|
|
15367
|
-
// src/mcp/
|
|
15368
|
-
|
|
15367
|
+
// src/mcp/http.ts
|
|
15368
|
+
var DEFAULT_HTTP_PORT = 8821;
|
|
15369
|
+
var HTTP_NAME = "machines";
|
|
15370
|
+
function isHttpMode(args = process.argv.slice(2)) {
|
|
15371
|
+
return args.includes("--http") || process.env.MCP_HTTP === "1";
|
|
15372
|
+
}
|
|
15373
|
+
function resolveHttpPort(args = process.argv.slice(2)) {
|
|
15374
|
+
for (let i = 0;i < args.length; i++) {
|
|
15375
|
+
const arg = args[i];
|
|
15376
|
+
if (arg === "--port" && args[i + 1]) {
|
|
15377
|
+
return parsePort(args[i + 1]);
|
|
15378
|
+
}
|
|
15379
|
+
if (arg.startsWith("--port=")) {
|
|
15380
|
+
return parsePort(arg.slice("--port=".length));
|
|
15381
|
+
}
|
|
15382
|
+
}
|
|
15383
|
+
const envPort = process.env.MCP_HTTP_PORT;
|
|
15384
|
+
if (envPort) {
|
|
15385
|
+
return parsePort(envPort);
|
|
15386
|
+
}
|
|
15387
|
+
return DEFAULT_HTTP_PORT;
|
|
15388
|
+
}
|
|
15389
|
+
function parsePort(raw) {
|
|
15390
|
+
const port = Number.parseInt(raw, 10);
|
|
15391
|
+
if (!Number.isInteger(port) || port < 1 || port > 65535) {
|
|
15392
|
+
throw new Error(`Invalid port: ${raw}`);
|
|
15393
|
+
}
|
|
15394
|
+
return port;
|
|
15395
|
+
}
|
|
15396
|
+
function pathnameFromRequest(req) {
|
|
15397
|
+
return new URL(req.url ?? "/", "http://127.0.0.1").pathname;
|
|
15398
|
+
}
|
|
15399
|
+
async function readRequestBody(req) {
|
|
15400
|
+
if (req.method !== "POST" && req.method !== "DELETE") {
|
|
15401
|
+
return;
|
|
15402
|
+
}
|
|
15403
|
+
const chunks = [];
|
|
15404
|
+
for await (const chunk of req) {
|
|
15405
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
15406
|
+
}
|
|
15407
|
+
const text = Buffer.concat(chunks).toString("utf8");
|
|
15408
|
+
if (!text) {
|
|
15409
|
+
return;
|
|
15410
|
+
}
|
|
15411
|
+
return JSON.parse(text);
|
|
15412
|
+
}
|
|
15413
|
+
async function handleMcpRequest(req, res) {
|
|
15414
|
+
const server = buildServer();
|
|
15415
|
+
const transport = new StreamableHTTPServerTransport({
|
|
15416
|
+
sessionIdGenerator: undefined
|
|
15417
|
+
});
|
|
15418
|
+
await server.connect(transport);
|
|
15369
15419
|
try {
|
|
15370
|
-
const
|
|
15371
|
-
|
|
15372
|
-
}
|
|
15373
|
-
|
|
15420
|
+
const body = await readRequestBody(req);
|
|
15421
|
+
await transport.handleRequest(req, res, body);
|
|
15422
|
+
} finally {
|
|
15423
|
+
res.on("close", () => {
|
|
15424
|
+
transport.close().catch(() => {
|
|
15425
|
+
return;
|
|
15426
|
+
});
|
|
15427
|
+
server.close().catch(() => {
|
|
15428
|
+
return;
|
|
15429
|
+
});
|
|
15430
|
+
});
|
|
15374
15431
|
}
|
|
15375
15432
|
}
|
|
15433
|
+
function startHttpServer(options = {}) {
|
|
15434
|
+
const host = options.host ?? "127.0.0.1";
|
|
15435
|
+
const port = options.port ?? resolveHttpPort();
|
|
15436
|
+
const name = options.name ?? HTTP_NAME;
|
|
15437
|
+
const httpServer = createServer(async (req, res) => {
|
|
15438
|
+
const path = pathnameFromRequest(req);
|
|
15439
|
+
if (req.method === "GET" && path === "/health") {
|
|
15440
|
+
res.writeHead(200, { "content-type": "application/json" });
|
|
15441
|
+
res.end(JSON.stringify({ status: "ok", name }));
|
|
15442
|
+
return;
|
|
15443
|
+
}
|
|
15444
|
+
if (path === "/mcp") {
|
|
15445
|
+
await handleMcpRequest(req, res);
|
|
15446
|
+
return;
|
|
15447
|
+
}
|
|
15448
|
+
res.writeHead(404, { "content-type": "application/json" });
|
|
15449
|
+
res.end(JSON.stringify({ error: "Not found" }));
|
|
15450
|
+
});
|
|
15451
|
+
httpServer.listen(port, host, () => {
|
|
15452
|
+
const address = httpServer.address();
|
|
15453
|
+
const boundPort = typeof address === "object" && address ? address.port : port;
|
|
15454
|
+
console.error(`machines-mcp HTTP listening on http://${host}:${boundPort}`);
|
|
15455
|
+
});
|
|
15456
|
+
return httpServer;
|
|
15457
|
+
}
|
|
15458
|
+
|
|
15459
|
+
// src/mcp/index.ts
|
|
15376
15460
|
function printHelp() {
|
|
15377
15461
|
console.log(`Usage: machines-mcp [options]
|
|
15378
15462
|
|
|
15379
|
-
MCP server for machine fleet management tools (stdio transport)
|
|
15463
|
+
MCP server for machine fleet management tools (stdio transport by default)
|
|
15380
15464
|
|
|
15381
15465
|
Options:
|
|
15466
|
+
--http Start Streamable HTTP transport on 127.0.0.1 (or MCP_HTTP=1)
|
|
15467
|
+
--port <n> HTTP port (default: 8821, or MCP_HTTP_PORT env)
|
|
15382
15468
|
-V, --version output the version number
|
|
15383
15469
|
-h, --help display help for command`);
|
|
15384
15470
|
}
|
|
@@ -15388,9 +15474,13 @@ if (args.includes("--help") || args.includes("-h")) {
|
|
|
15388
15474
|
process.exit(0);
|
|
15389
15475
|
}
|
|
15390
15476
|
if (args.includes("--version") || args.includes("-V")) {
|
|
15391
|
-
console.log(
|
|
15477
|
+
console.log(getPackageVersion());
|
|
15392
15478
|
process.exit(0);
|
|
15393
15479
|
}
|
|
15394
|
-
|
|
15395
|
-
|
|
15396
|
-
|
|
15480
|
+
if (isHttpMode(args)) {
|
|
15481
|
+
startHttpServer({ port: resolveHttpPort(args) });
|
|
15482
|
+
} else {
|
|
15483
|
+
const server = buildServer();
|
|
15484
|
+
const transport = new StdioServerTransport;
|
|
15485
|
+
await server.connect(transport);
|
|
15486
|
+
}
|
package/dist/mcp/server.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
2
|
export declare const MACHINE_MCP_TOOL_NAMES: readonly ["machines_status", "machines_doctor", "machines_self_test", "machines_apps_list", "machines_apps_status", "machines_apps_diff", "machines_apps_plan", "machines_apps_apply", "machines_manifest", "machines_manifest_validate", "machines_manifest_bootstrap", "machines_manifest_get", "machines_manifest_remove", "machines_agent_status", "machines_setup_preview", "machines_setup_apply", "machines_sync_preview", "machines_sync_apply", "machines_diff", "machines_install_tailscale_preview", "machines_install_tailscale_apply", "machines_install_claude_status", "machines_install_claude_diff", "machines_install_claude_preview", "machines_install_claude_apply", "machines_ssh_resolve", "machines_ports", "machines_backup_preview", "machines_backup_apply", "machines_cert_preview", "machines_cert_apply", "machines_dns_add", "machines_dns_list", "machines_dns_render", "machines_notifications_add", "machines_notifications_list", "machines_notifications_test", "machines_notifications_dispatch", "machines_notifications_remove", "machines_serve_info", "machines_serve_dashboard"];
|
|
3
|
+
export declare function buildServer(version?: string): McpServer;
|
|
3
4
|
export declare function createMcpServer(version: string): McpServer;
|
|
4
5
|
//# sourceMappingURL=server.d.ts.map
|
package/dist/mcp/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AA4BpE,eAAO,MAAM,sBAAsB,4jCA0CzB,CAAC;AAEX,wBAAgB,WAAW,CAAC,OAAO,GAAE,MAA4B,GAAG,SAAS,CAE5E;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CA6R1D"}
|