@skilder-ai/runtime 0.9.24 → 0.9.25
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 +5 -2
- package/dist/index.js +54 -12
- package/dist/index.js.map +3 -3
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -45,7 +45,9 @@ When `REMOTE_PORT` is set, the runtime exposes `GET /health`:
|
|
|
45
45
|
- **`200 { status: 'ok' }`** — NATS connected, an active round-trip probe (`flush`, 2s timeout) succeeded, and the runtime is authenticated
|
|
46
46
|
- **`503 { status: 'error', message: '...' }`** — NATS disconnected, NATS unreachable (flush timed out), not authenticated, or an unexpected error occurred
|
|
47
47
|
|
|
48
|
-
|
|
48
|
+
Health is independent of the remote MCP endpoints: a runtime that serves no MCP endpoint (no `MCP_REMOTE_ENABLED`) is still healthcheckable. The container image defaults `REMOTE_PORT` to `3001`, so every runtime container has a working healthcheck out of the box.
|
|
49
|
+
|
|
50
|
+
> **Note:** `npx`-installed runtimes bind no port unless you set `REMOTE_PORT` yourself, and stdio mode (`USER_KEY`) never starts an HTTP server — it is spawned per client, so a shared port would collide.
|
|
49
51
|
|
|
50
52
|
### Docker Compose setup
|
|
51
53
|
|
|
@@ -54,7 +56,8 @@ services:
|
|
|
54
56
|
runtime:
|
|
55
57
|
image: your-runtime-image
|
|
56
58
|
environment:
|
|
57
|
-
REMOTE_PORT: "3001"
|
|
59
|
+
REMOTE_PORT: "3001" # web service (health); the image defaults this
|
|
60
|
+
MCP_REMOTE_ENABLED: "true" # also serve the remote MCP endpoints on it
|
|
58
61
|
RUNTIME_KEY: "<RUNTIME_API_KEY>"
|
|
59
62
|
NATS_SERVERS: "nats:4222"
|
|
60
63
|
healthcheck:
|
package/dist/index.js
CHANGED
|
@@ -87816,6 +87816,23 @@ function parsePositiveIntEnv(name21, fallback) {
|
|
|
87816
87816
|
}
|
|
87817
87817
|
return parsed;
|
|
87818
87818
|
}
|
|
87819
|
+
function parseOptionalPositiveIntEnv(name21) {
|
|
87820
|
+
const raw = process.env[name21];
|
|
87821
|
+
if (raw === void 0 || raw === "") return void 0;
|
|
87822
|
+
return parsePositiveIntEnv(name21, 0);
|
|
87823
|
+
}
|
|
87824
|
+
var TRUE_VALUES = ["true", "1", "yes", "on"];
|
|
87825
|
+
var FALSE_VALUES = ["false", "0", "no", "off"];
|
|
87826
|
+
function parseBooleanEnv(name21, fallback) {
|
|
87827
|
+
const raw = process.env[name21];
|
|
87828
|
+
if (raw === void 0 || raw === "") return fallback;
|
|
87829
|
+
const normalized = raw.trim().toLowerCase();
|
|
87830
|
+
if (TRUE_VALUES.includes(normalized)) return true;
|
|
87831
|
+
if (FALSE_VALUES.includes(normalized)) return false;
|
|
87832
|
+
throw new Error(
|
|
87833
|
+
`Invalid ${name21}: "${raw}". Must be one of ${[...TRUE_VALUES, ...FALSE_VALUES].join(", ")}.`
|
|
87834
|
+
);
|
|
87835
|
+
}
|
|
87819
87836
|
|
|
87820
87837
|
// ../common/src/constants.node.ts
|
|
87821
87838
|
var MCP_TOOL_EXECUTION_TIMEOUT = parseInt(process.env.MCP_TOOL_EXECUTION_TIMEOUT ?? "60000", 10);
|
|
@@ -152767,6 +152784,16 @@ McpStdioService = __decorate15([
|
|
|
152767
152784
|
// src/services/fastify.manager.service.ts
|
|
152768
152785
|
var import_fastify = __toESM(require_fastify());
|
|
152769
152786
|
var import_cors = __toESM(require_cors());
|
|
152787
|
+
|
|
152788
|
+
// src/config/server.ts
|
|
152789
|
+
function remotePort() {
|
|
152790
|
+
return parseOptionalPositiveIntEnv("REMOTE_PORT");
|
|
152791
|
+
}
|
|
152792
|
+
function mcpRemoteEnabled() {
|
|
152793
|
+
return parseBooleanEnv("MCP_REMOTE_ENABLED", false);
|
|
152794
|
+
}
|
|
152795
|
+
|
|
152796
|
+
// src/services/fastify.manager.service.ts
|
|
152770
152797
|
var __decorate16 = function(decorators, target, key, desc) {
|
|
152771
152798
|
var c3 = arguments.length, r2 = c3 < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d2;
|
|
152772
152799
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r2 = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -152796,14 +152823,14 @@ var FastifyManagerService = class FastifyManagerService2 extends LifecycleServic
|
|
|
152796
152823
|
this.logger = this.loggerService.getLogger(this.name);
|
|
152797
152824
|
}
|
|
152798
152825
|
async initialize() {
|
|
152799
|
-
const
|
|
152800
|
-
if (!
|
|
152826
|
+
const port = remotePort();
|
|
152827
|
+
if (!port) {
|
|
152801
152828
|
this.logger.warn("REMOTE_PORT is not set, Fastify manager will not start");
|
|
152802
152829
|
return;
|
|
152803
152830
|
}
|
|
152804
152831
|
this.logger.info("Starting Fastify manager service");
|
|
152805
152832
|
await this.setupFastifyInstance();
|
|
152806
|
-
this.port =
|
|
152833
|
+
this.port = port;
|
|
152807
152834
|
}
|
|
152808
152835
|
/**
|
|
152809
152836
|
* Start listening on the configured port.
|
|
@@ -152825,6 +152852,10 @@ var FastifyManagerService = class FastifyManagerService2 extends LifecycleServic
|
|
|
152825
152852
|
this.isListening = true;
|
|
152826
152853
|
this.logger.info(`Fastify server listening on port ${this.port}`);
|
|
152827
152854
|
} catch (error48) {
|
|
152855
|
+
if (error48?.code === "EADDRINUSE") {
|
|
152856
|
+
this.logger.error({ event: "fastify_listen_failed", reason: "port_in_use", port: this.port }, `Port ${this.port} is already in use. Set REMOTE_PORT to a free port, or unset it to run without a web service.`);
|
|
152857
|
+
throw error48;
|
|
152858
|
+
}
|
|
152828
152859
|
this.logger.error(`Failed to start Fastify server: ${error48}`);
|
|
152829
152860
|
throw error48;
|
|
152830
152861
|
}
|
|
@@ -152835,6 +152866,7 @@ var FastifyManagerService = class FastifyManagerService2 extends LifecycleServic
|
|
|
152835
152866
|
await this.fastifyInstance.close();
|
|
152836
152867
|
this.fastifyInstance = void 0;
|
|
152837
152868
|
}
|
|
152869
|
+
this.isListening = false;
|
|
152838
152870
|
}
|
|
152839
152871
|
/**
|
|
152840
152872
|
* Returns the shared Fastify instance for route registration
|
|
@@ -162087,7 +162119,8 @@ function validateAndDetectMode() {
|
|
|
162087
162119
|
const userKey = process.env.USER_KEY;
|
|
162088
162120
|
const runtimeKey = process.env.RUNTIME_KEY;
|
|
162089
162121
|
const runtimeName = process.env.RUNTIME_NAME;
|
|
162090
|
-
const
|
|
162122
|
+
const mcpRemote = mcpRemoteEnabled();
|
|
162123
|
+
const port = userKey ? void 0 : remotePort();
|
|
162091
162124
|
const keyVariables = [systemKey, userKey, runtimeKey];
|
|
162092
162125
|
const keyVariablesSet = keyVariables.filter((key) => !!key);
|
|
162093
162126
|
if (keyVariablesSet.length > 1) {
|
|
@@ -162100,26 +162133,32 @@ function validateAndDetectMode() {
|
|
|
162100
162133
|
throw new Error("Invalid configuration: SYSTEM_KEY requires RUNTIME_NAME");
|
|
162101
162134
|
}
|
|
162102
162135
|
}
|
|
162103
|
-
if (
|
|
162136
|
+
if (mcpRemote && userKey) {
|
|
162104
162137
|
throw new Error(
|
|
162105
|
-
"Invalid configuration:
|
|
162138
|
+
"Invalid configuration: MCP_REMOTE_ENABLED is mutually exclusive with USER_KEY. USER_KEY serves MCP over stdio; use RUNTIME_KEY or RUNTIME_NAME for remote MCP."
|
|
162106
162139
|
);
|
|
162107
162140
|
}
|
|
162141
|
+
if (mcpRemote && !port) {
|
|
162142
|
+
throw new Error("Invalid configuration: MCP_REMOTE_ENABLED requires REMOTE_PORT, which is where the MCP endpoints are served.");
|
|
162143
|
+
}
|
|
162108
162144
|
if ((runtimeName || runtimeKey) && userKey) {
|
|
162109
162145
|
throw new Error("Invalid configuration: trying to start both a runtime and a user, this is not supported");
|
|
162110
162146
|
}
|
|
162147
|
+
if (userKey && process.env.REMOTE_PORT) {
|
|
162148
|
+
console.warn("REMOTE_PORT is ignored in stdio mode (USER_KEY): stdio runtimes do not start a web service");
|
|
162149
|
+
}
|
|
162111
162150
|
if (userKey) {
|
|
162112
162151
|
return "MCP_STDIO";
|
|
162113
162152
|
} else if (runtimeName || runtimeKey) {
|
|
162114
|
-
if (
|
|
162153
|
+
if (mcpRemote) {
|
|
162115
162154
|
return "EDGE_MCP_STREAM";
|
|
162116
162155
|
}
|
|
162117
162156
|
return "EDGE";
|
|
162118
|
-
} else if (
|
|
162157
|
+
} else if (mcpRemote) {
|
|
162119
162158
|
return "STANDALONE_MCP_STREAM";
|
|
162120
162159
|
} else {
|
|
162121
162160
|
throw new Error(
|
|
162122
|
-
"Invalid configuration: At least one of USER_KEY, RUNTIME_NAME, RUNTIME_KEY, or
|
|
162161
|
+
"Invalid configuration: At least one of USER_KEY, RUNTIME_NAME, RUNTIME_KEY, or MCP_REMOTE_ENABLED must be set. See documentation for valid operational modes."
|
|
162123
162162
|
);
|
|
162124
162163
|
}
|
|
162125
162164
|
}
|
|
@@ -162129,19 +162168,22 @@ var start = () => {
|
|
|
162129
162168
|
const runtimeExecutionId = (0, import_crypto3.randomBytes)(16).toString("hex");
|
|
162130
162169
|
container.bind(RUNTIME_EXECUTION_ID).toConstantValue(runtimeExecutionId);
|
|
162131
162170
|
container.bind(AuthService).toSelf().inSingletonScope();
|
|
162171
|
+
const webService = mode !== "MCP_STDIO" && remotePort() !== void 0;
|
|
162172
|
+
if (webService) {
|
|
162173
|
+
container.bind(FastifyManagerService).toSelf().inSingletonScope();
|
|
162174
|
+
} else {
|
|
162175
|
+
container.bind(FastifyManagerService).toConstantValue(void 0);
|
|
162176
|
+
}
|
|
162132
162177
|
if (mode === "MCP_STDIO") {
|
|
162133
162178
|
container.bind(McpStdioService).toSelf().inSingletonScope();
|
|
162134
|
-
container.bind(FastifyManagerService).toConstantValue(void 0);
|
|
162135
162179
|
container.bind(McpSseService).toConstantValue(void 0);
|
|
162136
162180
|
container.bind(McpStreamableService).toConstantValue(void 0);
|
|
162137
162181
|
} else if (mode === "EDGE_MCP_STREAM" || mode === "STANDALONE_MCP_STREAM") {
|
|
162138
|
-
container.bind(FastifyManagerService).toSelf().inSingletonScope();
|
|
162139
162182
|
container.bind(McpSseService).toSelf().inSingletonScope();
|
|
162140
162183
|
container.bind(McpStreamableService).toSelf().inSingletonScope();
|
|
162141
162184
|
container.bind(McpStdioService).toConstantValue(void 0);
|
|
162142
162185
|
} else {
|
|
162143
162186
|
container.bind(McpStdioService).toConstantValue(void 0);
|
|
162144
|
-
container.bind(FastifyManagerService).toConstantValue(void 0);
|
|
162145
162187
|
container.bind(McpSseService).toConstantValue(void 0);
|
|
162146
162188
|
container.bind(McpStreamableService).toConstantValue(void 0);
|
|
162147
162189
|
}
|