@evref-bl/plexus-gateway 0.1.0-alpha.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.
- package/dist/gateway.d.ts +107 -0
- package/dist/gateway.d.ts.map +1 -0
- package/dist/gateway.js +445 -0
- package/dist/gateway.js.map +1 -0
- package/dist/imageMcpRouter.d.ts +25 -0
- package/dist/imageMcpRouter.d.ts.map +1 -0
- package/dist/imageMcpRouter.js +90 -0
- package/dist/imageMcpRouter.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +28 -0
- package/dist/index.js.map +1 -0
- package/dist/pharoFacade.d.ts +12 -0
- package/dist/pharoFacade.d.ts.map +1 -0
- package/dist/pharoFacade.js +67 -0
- package/dist/pharoFacade.js.map +1 -0
- package/dist/routingTable.d.ts +84 -0
- package/dist/routingTable.d.ts.map +1 -0
- package/dist/routingTable.js +166 -0
- package/dist/routingTable.js.map +1 -0
- package/dist/server.d.ts +133 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +394 -0
- package/dist/server.js.map +1 -0
- package/package.json +36 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import http from "node:http";
|
|
2
|
+
export class StreamableHttpImageMcpToolRouter {
|
|
3
|
+
host;
|
|
4
|
+
path;
|
|
5
|
+
timeoutMs;
|
|
6
|
+
constructor(options = {}) {
|
|
7
|
+
this.host = options.host ?? "127.0.0.1";
|
|
8
|
+
this.path = options.path ?? "/";
|
|
9
|
+
this.timeoutMs = options.timeoutMs ?? 60_000;
|
|
10
|
+
}
|
|
11
|
+
async callTool(route, toolName, argumentsValue) {
|
|
12
|
+
const response = await this.postJsonRpc(route.port, {
|
|
13
|
+
jsonrpc: "2.0",
|
|
14
|
+
id: `plexus-${route.targetId}-${route.imageId}-${Date.now()}`,
|
|
15
|
+
method: "tools/call",
|
|
16
|
+
params: {
|
|
17
|
+
name: toolName,
|
|
18
|
+
arguments: argumentsValue,
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
if ("error" in response) {
|
|
22
|
+
throw new Error(`MCP error ${jsonRpcErrorText(response.error)}`);
|
|
23
|
+
}
|
|
24
|
+
if (!("result" in response)) {
|
|
25
|
+
throw new Error("MCP response did not include a result");
|
|
26
|
+
}
|
|
27
|
+
return response.result;
|
|
28
|
+
}
|
|
29
|
+
async postJsonRpc(port, payload) {
|
|
30
|
+
const body = JSON.stringify(payload);
|
|
31
|
+
return new Promise((resolve, reject) => {
|
|
32
|
+
const request = http.request({
|
|
33
|
+
hostname: this.host,
|
|
34
|
+
port,
|
|
35
|
+
path: this.path,
|
|
36
|
+
method: "POST",
|
|
37
|
+
headers: {
|
|
38
|
+
accept: "application/json, text/event-stream",
|
|
39
|
+
"content-type": "application/json",
|
|
40
|
+
"content-length": Buffer.byteLength(body),
|
|
41
|
+
connection: "close",
|
|
42
|
+
},
|
|
43
|
+
timeout: this.timeoutMs,
|
|
44
|
+
}, (response) => {
|
|
45
|
+
const chunks = [];
|
|
46
|
+
response.on("data", (chunk) => {
|
|
47
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
48
|
+
});
|
|
49
|
+
response.on("end", () => {
|
|
50
|
+
if (response.statusCode === undefined ||
|
|
51
|
+
response.statusCode < 200 ||
|
|
52
|
+
response.statusCode >= 300) {
|
|
53
|
+
reject(new Error(`HTTP ${response.statusCode ?? "unknown"} ${response.statusMessage ?? ""}`.trim()));
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
let data;
|
|
57
|
+
try {
|
|
58
|
+
data = JSON.parse(Buffer.concat(chunks).toString("utf8"));
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
reject(new Error(`MCP response was not valid JSON: ${error instanceof Error ? error.message : String(error)}`));
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
if (!isRecord(data)) {
|
|
65
|
+
reject(new Error("MCP response was not a JSON object"));
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
resolve(data);
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
request.on("timeout", () => {
|
|
72
|
+
request.destroy(new Error(`MCP request timed out after ${this.timeoutMs}ms`));
|
|
73
|
+
});
|
|
74
|
+
request.on("error", reject);
|
|
75
|
+
request.end(body);
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
function isRecord(value) {
|
|
80
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
81
|
+
}
|
|
82
|
+
function jsonRpcErrorText(value) {
|
|
83
|
+
if (!isRecord(value)) {
|
|
84
|
+
return JSON.stringify(value);
|
|
85
|
+
}
|
|
86
|
+
const code = typeof value.code === "number" ? value.code : undefined;
|
|
87
|
+
const message = typeof value.message === "string" ? value.message : JSON.stringify(value);
|
|
88
|
+
return code === undefined ? message : `${code}: ${message}`;
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=imageMcpRouter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"imageMcpRouter.js","sourceRoot":"","sources":["../src/imageMcpRouter.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAKA,cAAc,cAAc,CAAC;AAC7B,cAAc,qBAAqB,CAAC;AACpC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,aAAa,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
export * from "./gateway.js";
|
|
6
|
+
export * from "./imageMcpRouter.js";
|
|
7
|
+
export * from "./pharoFacade.js";
|
|
8
|
+
export * from "./routingTable.js";
|
|
9
|
+
export * from "./server.js";
|
|
10
|
+
import { startGatewayServerFromCli } from "./server.js";
|
|
11
|
+
function comparablePath(filePath) {
|
|
12
|
+
const resolvedPath = path.resolve(filePath);
|
|
13
|
+
const realPath = fs.existsSync(resolvedPath)
|
|
14
|
+
? fs.realpathSync.native(resolvedPath)
|
|
15
|
+
: resolvedPath;
|
|
16
|
+
return process.platform === "win32" ? realPath.toLowerCase() : realPath;
|
|
17
|
+
}
|
|
18
|
+
const entrypointPath = process.argv[1]
|
|
19
|
+
? comparablePath(process.argv[1])
|
|
20
|
+
: undefined;
|
|
21
|
+
const modulePath = comparablePath(fileURLToPath(import.meta.url));
|
|
22
|
+
if (entrypointPath && modulePath === entrypointPath) {
|
|
23
|
+
startGatewayServerFromCli().catch((error) => {
|
|
24
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
25
|
+
process.exitCode = 1;
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,cAAc,cAAc,CAAC;AAC7B,cAAc,qBAAqB,CAAC;AACpC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,aAAa,CAAC;AAE5B,OAAO,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AAExD,SAAS,cAAc,CAAC,QAAgB;IACtC,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC5C,MAAM,QAAQ,GAAG,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC;QAC1C,CAAC,CAAC,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,YAAY,CAAC;QACtC,CAAC,CAAC,YAAY,CAAC;IAEjB,OAAO,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC;AAC1E,CAAC;AAED,MAAM,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IACpC,CAAC,CAAC,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACjC,CAAC,CAAC,SAAS,CAAC;AACd,MAAM,UAAU,GAAG,cAAc,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAElE,IAAI,cAAc,IAAI,UAAU,KAAK,cAAc,EAAE,CAAC;IACpD,yBAAyB,EAAE,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;QACnD,OAAO,CAAC,KAAK,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QACtE,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;IACvB,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Tool } from "@modelcontextprotocol/sdk/types.js";
|
|
2
|
+
export declare function buildPharoFacadeTool(tool: Tool): Tool;
|
|
3
|
+
export declare function buildPharoFacadeTools(tools: readonly Tool[]): Tool[];
|
|
4
|
+
export interface PharoFacadeArguments {
|
|
5
|
+
imageId: string;
|
|
6
|
+
argumentsValue: Record<string, unknown>;
|
|
7
|
+
}
|
|
8
|
+
export declare class PharoFacadeInputError extends Error {
|
|
9
|
+
constructor(message: string);
|
|
10
|
+
}
|
|
11
|
+
export declare function parsePharoFacadeArguments(input: unknown): PharoFacadeArguments;
|
|
12
|
+
//# sourceMappingURL=pharoFacade.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pharoFacade.d.ts","sourceRoot":"","sources":["../src/pharoFacade.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,oCAAoC,CAAC;AAoC/D,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,CAiBrD;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,SAAS,IAAI,EAAE,GAAG,IAAI,EAAE,CAEpE;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACzC;AAED,qBAAa,qBAAsB,SAAQ,KAAK;gBAClC,OAAO,EAAE,MAAM;CAI5B;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,OAAO,GAAG,oBAAoB,CAe9E"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
const imageIdSchema = {
|
|
2
|
+
type: "string",
|
|
3
|
+
minLength: 1,
|
|
4
|
+
description: "PLexus workspace-scoped image handle to route this Pharo tool call to.",
|
|
5
|
+
};
|
|
6
|
+
function isObject(value) {
|
|
7
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
8
|
+
}
|
|
9
|
+
function schemaObject(value) {
|
|
10
|
+
return isObject(value) ? value : {};
|
|
11
|
+
}
|
|
12
|
+
function schemaProperties(value) {
|
|
13
|
+
if (!isObject(value)) {
|
|
14
|
+
return {};
|
|
15
|
+
}
|
|
16
|
+
return { ...value };
|
|
17
|
+
}
|
|
18
|
+
function schemaRequired(value) {
|
|
19
|
+
if (!Array.isArray(value)) {
|
|
20
|
+
return [];
|
|
21
|
+
}
|
|
22
|
+
return value.filter((item) => typeof item === "string");
|
|
23
|
+
}
|
|
24
|
+
function unique(values) {
|
|
25
|
+
return [...new Set(values)];
|
|
26
|
+
}
|
|
27
|
+
export function buildPharoFacadeTool(tool) {
|
|
28
|
+
const inputSchema = schemaObject(tool.inputSchema);
|
|
29
|
+
const properties = schemaProperties(inputSchema.properties);
|
|
30
|
+
const required = unique(["imageId", ...schemaRequired(inputSchema.required)]);
|
|
31
|
+
return {
|
|
32
|
+
...tool,
|
|
33
|
+
inputSchema: {
|
|
34
|
+
...inputSchema,
|
|
35
|
+
type: "object",
|
|
36
|
+
properties: {
|
|
37
|
+
...properties,
|
|
38
|
+
imageId: imageIdSchema,
|
|
39
|
+
},
|
|
40
|
+
required,
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
export function buildPharoFacadeTools(tools) {
|
|
45
|
+
return tools.map((tool) => buildPharoFacadeTool(tool));
|
|
46
|
+
}
|
|
47
|
+
export class PharoFacadeInputError extends Error {
|
|
48
|
+
constructor(message) {
|
|
49
|
+
super(message);
|
|
50
|
+
this.name = "PharoFacadeInputError";
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
export function parsePharoFacadeArguments(input) {
|
|
54
|
+
if (!isObject(input)) {
|
|
55
|
+
throw new PharoFacadeInputError("Pharo facade input must be an object");
|
|
56
|
+
}
|
|
57
|
+
const imageId = input.imageId;
|
|
58
|
+
if (typeof imageId !== "string" || imageId.length === 0) {
|
|
59
|
+
throw new PharoFacadeInputError("imageId is required");
|
|
60
|
+
}
|
|
61
|
+
const { imageId: _imageId, ...argumentsValue } = input;
|
|
62
|
+
return {
|
|
63
|
+
imageId,
|
|
64
|
+
argumentsValue,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=pharoFacade.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pharoFacade.js","sourceRoot":"","sources":["../src/pharoFacade.ts"],"names":[],"mappings":"AAEA,MAAM,aAAa,GAAG;IACpB,IAAI,EAAE,QAAQ;IACd,SAAS,EAAE,CAAC;IACZ,WAAW,EAAE,wEAAwE;CAC7E,CAAC;AAEX,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,CAAC,KAAK,CAAC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC9E,CAAC;AAED,SAAS,YAAY,CAAC,KAAc;IAClC,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;AACtC,CAAC;AAED,SAAS,gBAAgB,CAAC,KAAc;IACtC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACrB,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,OAAO,EAAE,GAAG,KAAK,EAAE,CAAC;AACtB,CAAC;AAED,SAAS,cAAc,CAAC,KAAc;IACpC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAkB,EAAE,CAAC,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC;AAC1E,CAAC;AAED,SAAS,MAAM,CAAC,MAAgB;IAC9B,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,IAAU;IAC7C,MAAM,WAAW,GAAG,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACnD,MAAM,UAAU,GAAG,gBAAgB,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;IAC5D,MAAM,QAAQ,GAAG,MAAM,CAAC,CAAC,SAAS,EAAE,GAAG,cAAc,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IAE9E,OAAO;QACL,GAAG,IAAI;QACP,WAAW,EAAE;YACX,GAAG,WAAW;YACd,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,GAAG,UAAU;gBACb,OAAO,EAAE,aAAa;aACvB;YACD,QAAQ;SACT;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,KAAsB;IAC1D,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,oBAAoB,CAAC,IAAI,CAAC,CAAC,CAAC;AACzD,CAAC;AAOD,MAAM,OAAO,qBAAsB,SAAQ,KAAK;IAC9C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;IACtC,CAAC;CACF;AAED,MAAM,UAAU,yBAAyB,CAAC,KAAc;IACtD,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACrB,MAAM,IAAI,qBAAqB,CAAC,sCAAsC,CAAC,CAAC;IAC1E,CAAC;IAED,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;IAC9B,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxD,MAAM,IAAI,qBAAqB,CAAC,qBAAqB,CAAC,CAAC;IACzD,CAAC;IAED,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,cAAc,EAAE,GAAG,KAAK,CAAC;IACvD,OAAO;QACL,OAAO;QACP,cAAc;KACf,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
export type GatewayProjectImageStatus = "starting" | "running" | "stopped" | "failed";
|
|
2
|
+
export type GatewayPharoMcpContractStatus = "unknown" | "matching" | "mismatched";
|
|
3
|
+
export interface GatewayPharoMcpContractReference {
|
|
4
|
+
id?: string;
|
|
5
|
+
hash?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface GatewayProjectImagePharoMcpContractState extends GatewayPharoMcpContractReference {
|
|
8
|
+
status?: GatewayPharoMcpContractStatus;
|
|
9
|
+
expectedId?: string;
|
|
10
|
+
expectedHash?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface GatewayProjectImageState {
|
|
13
|
+
id: string;
|
|
14
|
+
imageName: string;
|
|
15
|
+
assignedPort: number;
|
|
16
|
+
pid?: number;
|
|
17
|
+
status: GatewayProjectImageStatus;
|
|
18
|
+
pharoMcpContract?: GatewayProjectImagePharoMcpContractState;
|
|
19
|
+
}
|
|
20
|
+
export interface GatewayProjectState {
|
|
21
|
+
projectId: string;
|
|
22
|
+
projectName: string;
|
|
23
|
+
workspaceId: string;
|
|
24
|
+
targetId: string;
|
|
25
|
+
pharoMcpContract?: GatewayPharoMcpContractReference;
|
|
26
|
+
images: GatewayProjectImageState[];
|
|
27
|
+
updatedAt: string;
|
|
28
|
+
}
|
|
29
|
+
export type GatewayImageHealth = "unknown" | "healthy" | "unhealthy";
|
|
30
|
+
export type GatewayImageRoutabilityCode = "ready" | "image_unavailable" | "contract_unknown" | "contract_mismatch";
|
|
31
|
+
export interface GatewayImageRoutability {
|
|
32
|
+
ok: boolean;
|
|
33
|
+
code: GatewayImageRoutabilityCode;
|
|
34
|
+
message: string;
|
|
35
|
+
}
|
|
36
|
+
export interface GatewayImageRouteMetadata {
|
|
37
|
+
serverName: "gateway";
|
|
38
|
+
requiredArgument: "imageId";
|
|
39
|
+
imageId: string;
|
|
40
|
+
routeReference: {
|
|
41
|
+
projectId: string;
|
|
42
|
+
workspaceId: string;
|
|
43
|
+
targetId: string;
|
|
44
|
+
};
|
|
45
|
+
imageIdSource: string;
|
|
46
|
+
recordHint: string;
|
|
47
|
+
}
|
|
48
|
+
export interface GatewayImageRoute {
|
|
49
|
+
id: string;
|
|
50
|
+
imageName: string;
|
|
51
|
+
port: number;
|
|
52
|
+
pid?: number;
|
|
53
|
+
status: GatewayProjectImageStatus;
|
|
54
|
+
health: GatewayImageHealth;
|
|
55
|
+
routable: GatewayImageRoutability;
|
|
56
|
+
routeMetadata: GatewayImageRouteMetadata;
|
|
57
|
+
pharoMcpContract?: GatewayProjectImagePharoMcpContractState;
|
|
58
|
+
updatedAt: string;
|
|
59
|
+
}
|
|
60
|
+
export interface GatewayProjectRoute {
|
|
61
|
+
projectId: string;
|
|
62
|
+
projectName: string;
|
|
63
|
+
workspaceId: string;
|
|
64
|
+
targetId: string;
|
|
65
|
+
projectRoot: string;
|
|
66
|
+
statePath: string;
|
|
67
|
+
pharoMcpContract?: GatewayPharoMcpContractReference;
|
|
68
|
+
images: GatewayImageRoute[];
|
|
69
|
+
updatedAt: string;
|
|
70
|
+
}
|
|
71
|
+
export declare class PlexusRoutingTable {
|
|
72
|
+
private readonly targets;
|
|
73
|
+
upsertProject(projectRoot: string, statePath: string, state: GatewayProjectState): GatewayProjectRoute;
|
|
74
|
+
getTarget(targetId: string): GatewayProjectRoute | undefined;
|
|
75
|
+
removeTarget(targetId: string): GatewayProjectRoute | undefined;
|
|
76
|
+
removeProjectWorkspace(projectId: string, workspaceId: string): GatewayProjectRoute | undefined;
|
|
77
|
+
removeRoutesWithMissingStatePaths(statePathExists?: (statePath: string) => boolean): GatewayProjectRoute[];
|
|
78
|
+
getProjectWorkspace(projectId: string, workspaceId: string): GatewayProjectRoute | undefined;
|
|
79
|
+
listProjectTargets(projectId: string): GatewayProjectRoute[];
|
|
80
|
+
listTargets(): GatewayProjectRoute[];
|
|
81
|
+
findImageOutsideTarget(projectId: string, targetId: string, imageId: string): GatewayProjectRoute | undefined;
|
|
82
|
+
updateImageHealth(targetId: string, imageId: string, health: GatewayImageHealth): void;
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=routingTable.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routingTable.d.ts","sourceRoot":"","sources":["../src/routingTable.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
function contractLabel(contract) {
|
|
4
|
+
if (!contract) {
|
|
5
|
+
return "none";
|
|
6
|
+
}
|
|
7
|
+
return contract.hash ?? contract.id ?? "unknown";
|
|
8
|
+
}
|
|
9
|
+
function requiredProjectContractFields(contract) {
|
|
10
|
+
if (!contract) {
|
|
11
|
+
return [];
|
|
12
|
+
}
|
|
13
|
+
return ["id", "hash"].filter((key) => contract[key] !== undefined);
|
|
14
|
+
}
|
|
15
|
+
function contractRoutability(projectContract, imageContract, imageId) {
|
|
16
|
+
if (imageContract?.status === "mismatched") {
|
|
17
|
+
return {
|
|
18
|
+
ok: false,
|
|
19
|
+
code: "contract_mismatch",
|
|
20
|
+
message: `Image ${imageId} Pharo MCP contract is marked as mismatched`,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
const requiredFields = requiredProjectContractFields(projectContract);
|
|
24
|
+
if (requiredFields.length === 0) {
|
|
25
|
+
return {
|
|
26
|
+
ok: true,
|
|
27
|
+
code: "ready",
|
|
28
|
+
message: "Image is routable",
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
if (!imageContract || imageContract.status === "unknown") {
|
|
32
|
+
return {
|
|
33
|
+
ok: false,
|
|
34
|
+
code: "contract_unknown",
|
|
35
|
+
message: `Image ${imageId} Pharo MCP contract is unknown; expected ${contractLabel(projectContract)}`,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
for (const field of requiredFields) {
|
|
39
|
+
if (imageContract[field] === undefined) {
|
|
40
|
+
return {
|
|
41
|
+
ok: false,
|
|
42
|
+
code: "contract_unknown",
|
|
43
|
+
message: `Image ${imageId} Pharo MCP contract is missing ${String(field)}; expected ${contractLabel(projectContract)}`,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
if (imageContract[field] !== projectContract?.[field]) {
|
|
47
|
+
return {
|
|
48
|
+
ok: false,
|
|
49
|
+
code: "contract_mismatch",
|
|
50
|
+
message: `Image ${imageId} Pharo MCP contract does not match project contract`,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
ok: true,
|
|
56
|
+
code: "ready",
|
|
57
|
+
message: "Image is routable",
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
function imageRoutability(projectContract, image) {
|
|
61
|
+
if (image.status !== "running") {
|
|
62
|
+
return {
|
|
63
|
+
ok: false,
|
|
64
|
+
code: "image_unavailable",
|
|
65
|
+
message: `Image ${image.id} is not running; current status is ${image.status}`,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
return contractRoutability(projectContract, image.pharoMcpContract, image.id);
|
|
69
|
+
}
|
|
70
|
+
function imageRouteMetadata(state, imageId) {
|
|
71
|
+
return {
|
|
72
|
+
serverName: "gateway",
|
|
73
|
+
requiredArgument: "imageId",
|
|
74
|
+
imageId,
|
|
75
|
+
routeReference: {
|
|
76
|
+
projectId: state.projectId,
|
|
77
|
+
workspaceId: state.workspaceId,
|
|
78
|
+
targetId: state.targetId,
|
|
79
|
+
},
|
|
80
|
+
imageIdSource: "Read images[].imageId from PLexus scoped context, pharo-launcher image list, or gateway status",
|
|
81
|
+
recordHint: "Record the selected imageId with the scoped project/workspace/target before calling gateway tools",
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
export class PlexusRoutingTable {
|
|
85
|
+
targets = new Map();
|
|
86
|
+
upsertProject(projectRoot, statePath, state) {
|
|
87
|
+
const existing = this.targets.get(state.targetId);
|
|
88
|
+
const existingHealth = new Map(existing?.images.map((image) => [image.id, image.health]) ?? []);
|
|
89
|
+
const route = {
|
|
90
|
+
projectId: state.projectId,
|
|
91
|
+
projectName: state.projectName,
|
|
92
|
+
workspaceId: state.workspaceId,
|
|
93
|
+
targetId: state.targetId,
|
|
94
|
+
projectRoot: path.resolve(projectRoot),
|
|
95
|
+
statePath,
|
|
96
|
+
...(state.pharoMcpContract
|
|
97
|
+
? { pharoMcpContract: state.pharoMcpContract }
|
|
98
|
+
: {}),
|
|
99
|
+
updatedAt: state.updatedAt,
|
|
100
|
+
images: state.images.map((image) => ({
|
|
101
|
+
id: image.id,
|
|
102
|
+
imageName: image.imageName,
|
|
103
|
+
port: image.assignedPort,
|
|
104
|
+
...(image.pid ? { pid: image.pid } : {}),
|
|
105
|
+
status: image.status,
|
|
106
|
+
health: existingHealth.get(image.id) ?? "unknown",
|
|
107
|
+
routable: imageRoutability(state.pharoMcpContract, image),
|
|
108
|
+
routeMetadata: imageRouteMetadata(state, image.id),
|
|
109
|
+
...(image.pharoMcpContract
|
|
110
|
+
? { pharoMcpContract: image.pharoMcpContract }
|
|
111
|
+
: {}),
|
|
112
|
+
updatedAt: state.updatedAt,
|
|
113
|
+
})),
|
|
114
|
+
};
|
|
115
|
+
this.targets.set(route.targetId, route);
|
|
116
|
+
return route;
|
|
117
|
+
}
|
|
118
|
+
getTarget(targetId) {
|
|
119
|
+
return this.targets.get(targetId);
|
|
120
|
+
}
|
|
121
|
+
removeTarget(targetId) {
|
|
122
|
+
const route = this.targets.get(targetId);
|
|
123
|
+
if (route) {
|
|
124
|
+
this.targets.delete(targetId);
|
|
125
|
+
}
|
|
126
|
+
return route;
|
|
127
|
+
}
|
|
128
|
+
removeProjectWorkspace(projectId, workspaceId) {
|
|
129
|
+
const route = this.getProjectWorkspace(projectId, workspaceId);
|
|
130
|
+
return route ? this.removeTarget(route.targetId) : undefined;
|
|
131
|
+
}
|
|
132
|
+
removeRoutesWithMissingStatePaths(statePathExists = fs.existsSync) {
|
|
133
|
+
const removed = [];
|
|
134
|
+
for (const route of this.listTargets()) {
|
|
135
|
+
if (!statePathExists(route.statePath)) {
|
|
136
|
+
const deleted = this.removeTarget(route.targetId);
|
|
137
|
+
if (deleted) {
|
|
138
|
+
removed.push(deleted);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return removed;
|
|
143
|
+
}
|
|
144
|
+
getProjectWorkspace(projectId, workspaceId) {
|
|
145
|
+
return this.listProjectTargets(projectId).find((route) => route.workspaceId === workspaceId);
|
|
146
|
+
}
|
|
147
|
+
listProjectTargets(projectId) {
|
|
148
|
+
return this.listTargets().filter((route) => route.projectId === projectId);
|
|
149
|
+
}
|
|
150
|
+
listTargets() {
|
|
151
|
+
return [...this.targets.values()];
|
|
152
|
+
}
|
|
153
|
+
findImageOutsideTarget(projectId, targetId, imageId) {
|
|
154
|
+
return this.listProjectTargets(projectId).find((route) => route.targetId !== targetId &&
|
|
155
|
+
route.images.some((image) => image.id === imageId));
|
|
156
|
+
}
|
|
157
|
+
updateImageHealth(targetId, imageId, health) {
|
|
158
|
+
const project = this.targets.get(targetId);
|
|
159
|
+
const image = project?.images.find((candidate) => candidate.id === imageId);
|
|
160
|
+
if (image) {
|
|
161
|
+
image.health = health;
|
|
162
|
+
image.updatedAt = new Date().toISOString();
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
//# sourceMappingURL=routingTable.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routingTable.js","sourceRoot":"","sources":["../src/routingTable.ts"],"names":[],"mappings":"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"}
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import http from "node:http";
|
|
2
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
3
|
+
import { type Tool } from "@modelcontextprotocol/sdk/types.js";
|
|
4
|
+
import { PlexusGateway, type GatewayRouteReferenceInput } from "./gateway.js";
|
|
5
|
+
export declare const gatewayTools: readonly [{
|
|
6
|
+
readonly name: "plexus_gateway_register_target";
|
|
7
|
+
readonly description: "Register or update one gateway target route from PLexus runtime state.";
|
|
8
|
+
readonly inputSchema: {
|
|
9
|
+
readonly type: "object";
|
|
10
|
+
readonly properties: Record<string, unknown>;
|
|
11
|
+
readonly required: string[];
|
|
12
|
+
readonly additionalProperties: false;
|
|
13
|
+
};
|
|
14
|
+
}, {
|
|
15
|
+
readonly name: "plexus_gateway_unregister_target";
|
|
16
|
+
readonly description: "Remove a registered gateway target route without opening or closing project images.";
|
|
17
|
+
readonly inputSchema: {
|
|
18
|
+
readonly type: "object";
|
|
19
|
+
readonly properties: Record<string, unknown>;
|
|
20
|
+
readonly required: string[];
|
|
21
|
+
readonly additionalProperties: false;
|
|
22
|
+
};
|
|
23
|
+
}, {
|
|
24
|
+
readonly name: "plexus_gateway_status";
|
|
25
|
+
readonly description: "Return gateway route status for registered targets/images.";
|
|
26
|
+
readonly inputSchema: {
|
|
27
|
+
readonly type: "object";
|
|
28
|
+
readonly properties: Record<string, unknown>;
|
|
29
|
+
readonly required: string[];
|
|
30
|
+
readonly additionalProperties: false;
|
|
31
|
+
};
|
|
32
|
+
}, {
|
|
33
|
+
readonly name: "plexus_gateway_cleanup_stale_routes";
|
|
34
|
+
readonly description: "Remove registered gateway target routes whose runtime state files are gone.";
|
|
35
|
+
readonly inputSchema: {
|
|
36
|
+
readonly type: "object";
|
|
37
|
+
readonly properties: Record<string, unknown>;
|
|
38
|
+
readonly required: string[];
|
|
39
|
+
readonly additionalProperties: false;
|
|
40
|
+
};
|
|
41
|
+
}];
|
|
42
|
+
export declare const rawRoutingTool: {
|
|
43
|
+
readonly name: "plexus_route_to_image";
|
|
44
|
+
readonly description: "Route a Pharo MCP tool call to the MCP server running inside a selected image.";
|
|
45
|
+
readonly inputSchema: {
|
|
46
|
+
readonly type: "object";
|
|
47
|
+
readonly properties: Record<string, unknown>;
|
|
48
|
+
readonly required: string[];
|
|
49
|
+
readonly additionalProperties: false;
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
declare const legacyGatewaySurface = "pharo";
|
|
53
|
+
export type GatewaySurface = "combined" | "admin" | "gateway" | typeof legacyGatewaySurface;
|
|
54
|
+
export interface GatewayServerOptions {
|
|
55
|
+
surface?: GatewaySurface;
|
|
56
|
+
exposeRawRoutingTool?: boolean;
|
|
57
|
+
}
|
|
58
|
+
export interface GatewayEnvironmentOptions {
|
|
59
|
+
surface: GatewaySurface;
|
|
60
|
+
exposeRawRoutingTool: boolean;
|
|
61
|
+
pharoTools: Tool[];
|
|
62
|
+
pharoScope: GatewayRouteReferenceInput;
|
|
63
|
+
}
|
|
64
|
+
export declare const legacyGatewayTools: readonly [{
|
|
65
|
+
readonly name: "plexus_gateway_register_target";
|
|
66
|
+
readonly description: "Register or update one gateway target route from PLexus runtime state.";
|
|
67
|
+
readonly inputSchema: {
|
|
68
|
+
readonly type: "object";
|
|
69
|
+
readonly properties: Record<string, unknown>;
|
|
70
|
+
readonly required: string[];
|
|
71
|
+
readonly additionalProperties: false;
|
|
72
|
+
};
|
|
73
|
+
}, {
|
|
74
|
+
readonly name: "plexus_gateway_unregister_target";
|
|
75
|
+
readonly description: "Remove a registered gateway target route without opening or closing project images.";
|
|
76
|
+
readonly inputSchema: {
|
|
77
|
+
readonly type: "object";
|
|
78
|
+
readonly properties: Record<string, unknown>;
|
|
79
|
+
readonly required: string[];
|
|
80
|
+
readonly additionalProperties: false;
|
|
81
|
+
};
|
|
82
|
+
}, {
|
|
83
|
+
readonly name: "plexus_gateway_status";
|
|
84
|
+
readonly description: "Return gateway route status for registered targets/images.";
|
|
85
|
+
readonly inputSchema: {
|
|
86
|
+
readonly type: "object";
|
|
87
|
+
readonly properties: Record<string, unknown>;
|
|
88
|
+
readonly required: string[];
|
|
89
|
+
readonly additionalProperties: false;
|
|
90
|
+
};
|
|
91
|
+
}, {
|
|
92
|
+
readonly name: "plexus_gateway_cleanup_stale_routes";
|
|
93
|
+
readonly description: "Remove registered gateway target routes whose runtime state files are gone.";
|
|
94
|
+
readonly inputSchema: {
|
|
95
|
+
readonly type: "object";
|
|
96
|
+
readonly properties: Record<string, unknown>;
|
|
97
|
+
readonly required: string[];
|
|
98
|
+
readonly additionalProperties: false;
|
|
99
|
+
};
|
|
100
|
+
}, {
|
|
101
|
+
readonly name: "plexus_route_to_image";
|
|
102
|
+
readonly description: "Route a Pharo MCP tool call to the MCP server running inside a selected image.";
|
|
103
|
+
readonly inputSchema: {
|
|
104
|
+
readonly type: "object";
|
|
105
|
+
readonly properties: Record<string, unknown>;
|
|
106
|
+
readonly required: string[];
|
|
107
|
+
readonly additionalProperties: false;
|
|
108
|
+
};
|
|
109
|
+
}];
|
|
110
|
+
export interface GatewayHttpServerOptions {
|
|
111
|
+
host?: string;
|
|
112
|
+
port: number;
|
|
113
|
+
healthPath?: string;
|
|
114
|
+
mcpPath?: string;
|
|
115
|
+
}
|
|
116
|
+
export interface GatewayCliOptions {
|
|
117
|
+
transport: "stdio" | "http";
|
|
118
|
+
host: string;
|
|
119
|
+
port: number;
|
|
120
|
+
}
|
|
121
|
+
export declare function createGatewayServer(gateway?: PlexusGateway): Server;
|
|
122
|
+
export declare function createGatewayServerWithOptions(gateway?: PlexusGateway, options?: GatewayServerOptions): Server;
|
|
123
|
+
export declare function parseGatewayEnvironmentOptions(env?: NodeJS.ProcessEnv): GatewayEnvironmentOptions;
|
|
124
|
+
export declare function createGatewayFromEnvironment(env?: NodeJS.ProcessEnv): {
|
|
125
|
+
gateway: PlexusGateway;
|
|
126
|
+
serverOptions: GatewayServerOptions;
|
|
127
|
+
};
|
|
128
|
+
export declare function startGatewayServer(): Promise<void>;
|
|
129
|
+
export declare function startGatewayHttpServer(options: GatewayHttpServerOptions): Promise<http.Server>;
|
|
130
|
+
export declare function parseGatewayServerCliOptions(args?: string[], env?: NodeJS.ProcessEnv): GatewayCliOptions;
|
|
131
|
+
export declare function startGatewayServerFromCli(options?: GatewayCliOptions): Promise<void>;
|
|
132
|
+
export {};
|
|
133
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAGnE,OAAO,EAIL,KAAK,IAAI,EACV,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,KAAK,0BAA0B,EAAE,MAAM,cAAc,CAAC;AA4B9E,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmCf,CAAC;AAEX,eAAO,MAAM,cAAc;;;;;;;;;CAgBjB,CAAC;AAEX,QAAA,MAAM,oBAAoB,UAAU,CAAC;AAErC,MAAM,MAAM,cAAc,GACtB,UAAU,GACV,OAAO,GACP,SAAS,GACT,OAAO,oBAAoB,CAAC;AAEhC,MAAM,WAAW,oBAAoB;IACnC,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAED,MAAM,WAAW,yBAAyB;IACxC,OAAO,EAAE,cAAc,CAAC;IACxB,oBAAoB,EAAE,OAAO,CAAC;IAC9B,UAAU,EAAE,IAAI,EAAE,CAAC;IACnB,UAAU,EAAE,0BAA0B,CAAC;CACxC;AA0DD,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAA6C,CAAC;AAuB7E,MAAM,WAAW,wBAAwB;IACvC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,OAAO,GAAG,MAAM,CAAC;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AA+CD,wBAAgB,mBAAmB,CAAC,OAAO,gBAAsB,GAAG,MAAM,CAEzE;AAED,wBAAgB,8BAA8B,CAC5C,OAAO,gBAAsB,EAC7B,OAAO,GAAE,oBAAyB,GACjC,MAAM,CAmFR;AAeD,wBAAgB,8BAA8B,CAC5C,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,yBAAyB,CAiB3B;AAED,wBAAgB,4BAA4B,CAC1C,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC;IAAE,OAAO,EAAE,aAAa,CAAC;IAAC,aAAa,EAAE,oBAAoB,CAAA;CAAE,CAYjE;AAED,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC,CAQxD;AA2CD,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,wBAAwB,GAChC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAqFtB;AAED,wBAAgB,4BAA4B,CAC1C,IAAI,GAAE,MAAM,EAA0B,EACtC,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,iBAAiB,CAgDnB;AAED,wBAAsB,yBAAyB,CAC7C,OAAO,oBAAiC,GACvC,OAAO,CAAC,IAAI,CAAC,CAUf"}
|