@calltelemetry/ct-lab-mcp 0.2.0 → 0.3.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 +29 -1
- package/dist/bin/ct-lab-mcp.js +26 -1
- package/dist/src/canonical/bridge.d.ts +28 -0
- package/dist/src/canonical/bridge.d.ts.map +1 -0
- package/dist/src/canonical/bridge.js +223 -0
- package/dist/src/canonical/bridge.js.map +1 -0
- package/dist/src/canonical/cli.d.ts +8 -0
- package/dist/src/canonical/cli.d.ts.map +1 -0
- package/dist/src/canonical/cli.js +9 -0
- package/dist/src/canonical/cli.js.map +1 -0
- package/dist/src/canonical/index.d.ts +4 -0
- package/dist/src/canonical/index.d.ts.map +1 -0
- package/dist/src/canonical/index.js +4 -0
- package/dist/src/canonical/index.js.map +1 -0
- package/dist/src/canonical/types.d.ts +32 -0
- package/dist/src/canonical/types.d.ts.map +1 -0
- package/dist/src/canonical/types.js +2 -0
- package/dist/src/canonical/types.js.map +1 -0
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/server.d.ts +2 -0
- package/dist/src/server.d.ts.map +1 -1
- package/dist/src/server.js +2 -0
- package/dist/src/server.js.map +1 -1
- package/dist/src/tools/canonical-guard.d.ts +7 -0
- package/dist/src/tools/canonical-guard.d.ts.map +1 -0
- package/dist/src/tools/canonical-guard.js +38 -0
- package/dist/src/tools/canonical-guard.js.map +1 -0
- package/dist/src/tools/index.d.ts +1 -0
- package/dist/src/tools/index.d.ts.map +1 -1
- package/dist/src/tools/index.js +57 -0
- package/dist/src/tools/index.js.map +1 -1
- package/dist/src/tools/lab-preflight.d.ts +21 -0
- package/dist/src/tools/lab-preflight.d.ts.map +1 -0
- package/dist/src/tools/lab-preflight.js +22 -0
- package/dist/src/tools/lab-preflight.js.map +1 -0
- package/dist/src/tools/list-hosts.d.ts +2 -0
- package/dist/src/tools/list-hosts.d.ts.map +1 -1
- package/dist/src/tools/list-hosts.js.map +1 -1
- package/dist/src/tools/list-inventory.d.ts.map +1 -1
- package/dist/src/tools/list-inventory.js +21 -0
- package/dist/src/tools/list-inventory.js.map +1 -1
- package/dist/src/tools/provision-tools.d.ts.map +1 -1
- package/dist/src/tools/provision-tools.js +7 -0
- package/dist/src/tools/provision-tools.js.map +1 -1
- package/dist/src/tools/purge-slots.d.ts.map +1 -1
- package/dist/src/tools/purge-slots.js +4 -0
- package/dist/src/tools/purge-slots.js.map +1 -1
- package/dist/src/tools/slot-tools.d.ts.map +1 -1
- package/dist/src/tools/slot-tools.js +7 -0
- package/dist/src/tools/slot-tools.js.map +1 -1
- package/dist/src/tools/vm-action.d.ts.map +1 -1
- package/dist/src/tools/vm-action.js +4 -0
- package/dist/src/tools/vm-action.js.map +1 -1
- package/package.json +4 -4
- package/dist/bin/ct-lab-mcp.d.ts +0 -60
- package/dist/bin/ct-lab-mcp.d.ts.map +0 -1
- package/dist/bin/ct-lab-mcp.js.map +0 -1
- package/dist/bin/proxmox-mcp.d.ts +0 -58
- package/dist/bin/proxmox-mcp.d.ts.map +0 -1
- package/dist/bin/proxmox-mcp.js +0 -257
- package/dist/bin/proxmox-mcp.js.map +0 -1
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
[](https://www.typescriptlang.org/)
|
|
8
8
|
[](https://nodejs.org/)
|
|
9
9
|
|
|
10
|
-
`@calltelemetry/ct-lab-mcp` exposes high-level multi-hypervisor management (Proxmox VE & VMware ESXi),
|
|
10
|
+
`@calltelemetry/ct-lab-mcp` is the single public MCP façade for Call Telemetry lab operations. It exposes high-level multi-hypervisor management (Proxmox VE & VMware ESXi), disposable VM workflows, and secure appliance diagnostics while delegating canonical asset identity, lease ownership, and release-line policy to the private `lab-inventory` CLI supplied by `ct-meta`.
|
|
11
11
|
|
|
12
12
|
---
|
|
13
13
|
|
|
@@ -47,6 +47,12 @@ AI Clients (Claude Desktop / Cursor / Web / AI Agents)
|
|
|
47
47
|
└── Tier 3: In-Memory Mock Fallback / Offline Dev
|
|
48
48
|
```
|
|
49
49
|
|
|
50
|
+
In a governed `ct-meta` installation there is only one registered MCP server:
|
|
51
|
+
`@calltelemetry/ct-lab-mcp`. The Python `lab-inventory` program remains a
|
|
52
|
+
private canonical policy engine behind the Node façade; it is not registered as
|
|
53
|
+
a second public MCP. Set `CT_LAB_CANONICAL_REQUIRED=1` to fail closed rather
|
|
54
|
+
than use the legacy Node VMID/name slot state when the bridge is unavailable.
|
|
55
|
+
|
|
50
56
|
---
|
|
51
57
|
|
|
52
58
|
## Key Features
|
|
@@ -104,6 +110,7 @@ ct-lab-mcp [options]
|
|
|
104
110
|
| `--doppler-config <name>` | Doppler environment / config | *None* | `DOPPLER_CONFIG` |
|
|
105
111
|
| `--force-mock` | Force in-memory mock hypervisor & appliance mode | `false` | `CT_LAB_MOCK_MODE` |
|
|
106
112
|
| `--redact-secrets` | Enforce strict secret redaction on all logs | `true` | *None* |
|
|
113
|
+
| `preflight --asset-id <id> --linear-issue <key>` | Validate canonical inventory, exact VM identity, and release-line qualification before guest commands | n/a | `CT_LAB_CANONICAL_CLI`, `LAB_INVENTORY_FILE`, `CT_LAB_CANONICAL_REQUIRED` |
|
|
107
114
|
| `-v, --version` | Output the current version | *None* | *None* |
|
|
108
115
|
| `-h, --help` | Display CLI help text | *None* | *None* |
|
|
109
116
|
|
|
@@ -121,8 +128,29 @@ ct-lab-mcp --doppler-token "dp.st.prd.xxx" --doppler-project "calltelemetry-lab"
|
|
|
121
128
|
|
|
122
129
|
# Offline mock mode for development / unit testing
|
|
123
130
|
ct-lab-mcp --force-mock
|
|
131
|
+
|
|
132
|
+
# Governed fixture qualification (the release is cut by ct-release; the lab
|
|
133
|
+
# only qualifies the exact fixture against that release)
|
|
134
|
+
ct-lab-mcp preflight --asset-id proxmox-vm-uat-01 --linear-issue UAT-1202
|
|
124
135
|
```
|
|
125
136
|
|
|
137
|
+
### Canonical lab mode
|
|
138
|
+
|
|
139
|
+
`ct-meta` starts the public MCP with these environment variables:
|
|
140
|
+
|
|
141
|
+
```text
|
|
142
|
+
CT_LAB_CANONICAL_CLI=/path/to/lab-inventory
|
|
143
|
+
CT_LAB_CANONICAL_REQUIRED=1
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
In this mode `lab_preflight` and `list_inventory` execute through the canonical
|
|
147
|
+
CLI. Legacy `claim_slot`, `release_slot`, `purge_slots`, VM provisioning, and
|
|
148
|
+
VMID/name `vm_action` calls return `CANONICAL_OPERATION_REQUIRES_BRIDGE` instead
|
|
149
|
+
of silently mutating a second in-memory lease or targeting an ambiguous VM.
|
|
150
|
+
Use the canonical inventory-bound workflow for claims, releases, power, and
|
|
151
|
+
provisioning until those operations are explicitly bridged with exact asset
|
|
152
|
+
identity and durable receipts.
|
|
153
|
+
|
|
126
154
|
---
|
|
127
155
|
|
|
128
156
|
## MCP Tools Reference
|
package/dist/bin/ct-lab-mcp.js
CHANGED
|
@@ -18,6 +18,7 @@ import { credentialResolver } from "../src/credentials/resolver.js";
|
|
|
18
18
|
import { CredentialResolutionError } from "../src/credentials/errors.js";
|
|
19
19
|
import { startStdioServer } from "../src/transports/stdio.js";
|
|
20
20
|
import { createSseServer } from "../src/transports/sse.js";
|
|
21
|
+
import { CanonicalLabBridge, runCanonicalPreflight } from "../src/canonical/index.js";
|
|
21
22
|
// Load environment variables from .env if present
|
|
22
23
|
dotenv.config();
|
|
23
24
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
@@ -30,6 +31,23 @@ try {
|
|
|
30
31
|
}
|
|
31
32
|
catch { }
|
|
32
33
|
export const VERSION = dynamicVersion;
|
|
34
|
+
export function buildPreflightCommand() {
|
|
35
|
+
return new Command("preflight")
|
|
36
|
+
.description("Qualify one claimed appliance against canonical inventory and a cut software release")
|
|
37
|
+
.requiredOption("--asset-id <id>", "Exact canonical lab asset ID")
|
|
38
|
+
.requiredOption("--linear-issue <key>", "Linear issue owning the qualification")
|
|
39
|
+
.option("--json", "Emit structured JSON (the default)", true);
|
|
40
|
+
}
|
|
41
|
+
export async function runPreflightCli(argv = process.argv, bridge = new CanonicalLabBridge({ required: true })) {
|
|
42
|
+
const program = buildPreflightCommand();
|
|
43
|
+
// `buildPreflightCommand` is the subcommand itself, so remove the root
|
|
44
|
+
// `preflight` token before Commander parses its options.
|
|
45
|
+
program.parse([argv[0] || "node", argv[1] || "ct-lab-mcp", ...argv.slice(3)]);
|
|
46
|
+
const options = program.opts();
|
|
47
|
+
const response = await runCanonicalPreflight({ assetId: options.assetId, linearIssue: options.linearIssue }, bridge);
|
|
48
|
+
process.stdout.write(`${JSON.stringify(response.result)}\n`);
|
|
49
|
+
return response.exitCode;
|
|
50
|
+
}
|
|
33
51
|
/**
|
|
34
52
|
* Builds the Commander CLI program definition.
|
|
35
53
|
*/
|
|
@@ -52,6 +70,7 @@ export function buildCli(exitOverride = false) {
|
|
|
52
70
|
if (exitOverride) {
|
|
53
71
|
program.exitOverride();
|
|
54
72
|
}
|
|
73
|
+
program.addCommand(buildPreflightCommand());
|
|
55
74
|
return program;
|
|
56
75
|
}
|
|
57
76
|
/**
|
|
@@ -275,7 +294,13 @@ export function isMainModule(metaUrl) {
|
|
|
275
294
|
}
|
|
276
295
|
// Auto-run if executed as CLI entrypoint
|
|
277
296
|
if (isMainModule(import.meta.url)) {
|
|
278
|
-
|
|
297
|
+
const command = process.argv[2] === "preflight" ? runPreflightCli() : runCli();
|
|
298
|
+
Promise.resolve(command)
|
|
299
|
+
.then((result) => {
|
|
300
|
+
if (typeof result === "number" && result !== 0)
|
|
301
|
+
process.exit(result);
|
|
302
|
+
})
|
|
303
|
+
.catch((err) => {
|
|
279
304
|
const msg = err instanceof Error ? err.message : String(err);
|
|
280
305
|
console.error(`[ct-lab-mcp] Fatal error: ${msg}`);
|
|
281
306
|
process.exit(1);
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { CanonicalCommandResult, LabPreflightInput, LabPreflightResult } from "./types.js";
|
|
2
|
+
export interface CanonicalLabBridgeOptions {
|
|
3
|
+
cliPath?: string;
|
|
4
|
+
inventoryFile?: string;
|
|
5
|
+
args?: string[];
|
|
6
|
+
timeoutMs?: number;
|
|
7
|
+
required?: boolean;
|
|
8
|
+
runner?: (args: string[]) => Promise<Pick<CanonicalCommandResult, "exitCode" | "stdout" | "stderr">>;
|
|
9
|
+
}
|
|
10
|
+
export declare class CanonicalBridgeError extends Error {
|
|
11
|
+
readonly code = "CANONICAL_INVENTORY_UNAVAILABLE";
|
|
12
|
+
constructor(message: string);
|
|
13
|
+
}
|
|
14
|
+
export declare class CanonicalLabBridge {
|
|
15
|
+
private readonly cliPath?;
|
|
16
|
+
private readonly inventoryFile?;
|
|
17
|
+
private readonly prefixArgs;
|
|
18
|
+
private readonly timeoutMs;
|
|
19
|
+
private readonly required;
|
|
20
|
+
private readonly runner?;
|
|
21
|
+
constructor(options?: CanonicalLabBridgeOptions);
|
|
22
|
+
get isConfigured(): boolean;
|
|
23
|
+
/** The canonical CLI owns identity and lease policy in this mode. */
|
|
24
|
+
get isRequired(): boolean;
|
|
25
|
+
run(args: string[]): Promise<CanonicalCommandResult>;
|
|
26
|
+
preflight(input: LabPreflightInput): Promise<LabPreflightResult>;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=bridge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../../../src/canonical/bridge.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAK3F,MAAM,WAAW,yBAAyB;IACxC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,sBAAsB,EAAE,UAAU,GAAG,QAAQ,GAAG,QAAQ,CAAC,CAAC,CAAC;CACtG;AAED,qBAAa,oBAAqB,SAAQ,KAAK;IAC7C,QAAQ,CAAC,IAAI,qCAAqC;gBAEtC,OAAO,EAAE,MAAM;CAI5B;AA2CD,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAW;IACtC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAU;IACnC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAsC;gBAElD,OAAO,GAAE,yBAA8B;IASnD,IAAI,YAAY,IAAI,OAAO,CAE1B;IAED,qEAAqE;IACrE,IAAI,UAAU,IAAI,OAAO,CAExB;IAEK,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,sBAAsB,CAAC;IA6CpD,SAAS,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC;CA2HvE"}
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
2
|
+
import { promisify } from "node:util";
|
|
3
|
+
import { defaultRedactor } from "../utils/redactor.js";
|
|
4
|
+
const execFileAsync = promisify(execFile);
|
|
5
|
+
export class CanonicalBridgeError extends Error {
|
|
6
|
+
code = "CANONICAL_INVENTORY_UNAVAILABLE";
|
|
7
|
+
constructor(message) {
|
|
8
|
+
super(message);
|
|
9
|
+
this.name = "CanonicalBridgeError";
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
const SECRET_KEY = /password|passwd|secret|token|ticket|cookie|csrf|private_key|privateKey|passphrase/i;
|
|
13
|
+
const IDENTITY_KEY = /^(?:uuid|.*(?:_uuid|uuid$)|instance(?:_?uuid)?|smbios(?:_?uuid)?|bios(?:_?uuid)?|durable(?:_?instance)?_uuid|vm(?:_?uuid)?)$/i;
|
|
14
|
+
function isSecretKey(key) {
|
|
15
|
+
return !/^(?:ticket_status|expiry_status)$/i.test(key) && SECRET_KEY.test(key);
|
|
16
|
+
}
|
|
17
|
+
function redactCanonicalValue(value, key) {
|
|
18
|
+
if (typeof value === "string") {
|
|
19
|
+
// UUIDs are identity evidence in canonical inventory output. Preserve
|
|
20
|
+
// them when the field is explicitly identity-shaped, while redacting all
|
|
21
|
+
// other string values with the shared secret engine.
|
|
22
|
+
return key && IDENTITY_KEY.test(key) ? value : defaultRedactor.redactString(value);
|
|
23
|
+
}
|
|
24
|
+
if (Array.isArray(value))
|
|
25
|
+
return value.map((item) => redactCanonicalValue(item));
|
|
26
|
+
if (value && typeof value === "object") {
|
|
27
|
+
const sanitized = {};
|
|
28
|
+
for (const [entryKey, entryValue] of Object.entries(value)) {
|
|
29
|
+
sanitized[entryKey] = isSecretKey(entryKey) && typeof entryValue === "string"
|
|
30
|
+
? "[REDACTED]"
|
|
31
|
+
: redactCanonicalValue(entryValue, entryKey);
|
|
32
|
+
}
|
|
33
|
+
return sanitized;
|
|
34
|
+
}
|
|
35
|
+
return value;
|
|
36
|
+
}
|
|
37
|
+
function redact(text) {
|
|
38
|
+
// Preserve machine-readable evidence while redacting JSON object keys
|
|
39
|
+
// recursively. Applying a text regex after serialization can produce
|
|
40
|
+
// invalid JSON (for example, an unquoted replacement in a password field).
|
|
41
|
+
try {
|
|
42
|
+
return JSON.stringify(redactCanonicalValue(JSON.parse(text)));
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
// Non-JSON CLI output is covered by the string redactor below.
|
|
46
|
+
return defaultRedactor.redactString(text)
|
|
47
|
+
.replace(/(["']?(?:DOPPLER_TOKEN|LAB_[A-Z0-9_]*(?:TOKEN|SECRET|PASSWORD)|password|passwd|token|secret|private_key|privateKey)["']?)\s*([:=])\s*(["']?)[^\s,"'}]+\3/gi, "$1$2[REDACTED]")
|
|
48
|
+
.replace(/(authorization\s*:\s*bearer\s+)["']?[^\s"']+["']?/gi, "$1[REDACTED]");
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
export class CanonicalLabBridge {
|
|
52
|
+
cliPath;
|
|
53
|
+
inventoryFile;
|
|
54
|
+
prefixArgs;
|
|
55
|
+
timeoutMs;
|
|
56
|
+
required;
|
|
57
|
+
runner;
|
|
58
|
+
constructor(options = {}) {
|
|
59
|
+
this.cliPath = options.cliPath || process.env.CT_LAB_CANONICAL_CLI;
|
|
60
|
+
this.inventoryFile = options.inventoryFile || process.env.LAB_INVENTORY_FILE;
|
|
61
|
+
this.prefixArgs = options.args || [];
|
|
62
|
+
this.timeoutMs = options.timeoutMs ?? Number(process.env.CT_LAB_CANONICAL_TIMEOUT_MS || 30_000);
|
|
63
|
+
this.required = options.required ?? process.env.CT_LAB_CANONICAL_REQUIRED === "1";
|
|
64
|
+
this.runner = options.runner;
|
|
65
|
+
}
|
|
66
|
+
get isConfigured() {
|
|
67
|
+
return Boolean(this.runner || this.cliPath);
|
|
68
|
+
}
|
|
69
|
+
/** The canonical CLI owns identity and lease policy in this mode. */
|
|
70
|
+
get isRequired() {
|
|
71
|
+
return this.required;
|
|
72
|
+
}
|
|
73
|
+
async run(args) {
|
|
74
|
+
if (!this.isConfigured) {
|
|
75
|
+
throw new CanonicalBridgeError("canonical lab CLI is not configured");
|
|
76
|
+
}
|
|
77
|
+
const command = [
|
|
78
|
+
...(this.inventoryFile ? ["--file", this.inventoryFile] : []),
|
|
79
|
+
...args,
|
|
80
|
+
];
|
|
81
|
+
if (this.runner) {
|
|
82
|
+
const result = await this.runner(command);
|
|
83
|
+
return {
|
|
84
|
+
command,
|
|
85
|
+
exitCode: result.exitCode,
|
|
86
|
+
stdout: redact(result.stdout),
|
|
87
|
+
stderr: redact(result.stderr),
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
try {
|
|
91
|
+
const result = await execFileAsync(this.cliPath, [...this.prefixArgs, ...command], {
|
|
92
|
+
env: process.env,
|
|
93
|
+
timeout: this.timeoutMs,
|
|
94
|
+
maxBuffer: 4 * 1024 * 1024,
|
|
95
|
+
encoding: "utf8",
|
|
96
|
+
});
|
|
97
|
+
return {
|
|
98
|
+
command,
|
|
99
|
+
exitCode: 0,
|
|
100
|
+
stdout: redact(result.stdout),
|
|
101
|
+
stderr: redact(result.stderr),
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
const exitCode = typeof error?.code === "number" ? error.code : 1;
|
|
106
|
+
return {
|
|
107
|
+
command,
|
|
108
|
+
exitCode,
|
|
109
|
+
stdout: redact(String(error?.stdout || "")),
|
|
110
|
+
stderr: redact(String(error?.stderr || error?.message || "")),
|
|
111
|
+
timedOut: Boolean(error?.killed),
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
async preflight(input) {
|
|
116
|
+
const base = {
|
|
117
|
+
assetId: input.assetId,
|
|
118
|
+
linearIssue: input.linearIssue,
|
|
119
|
+
evidence: {},
|
|
120
|
+
};
|
|
121
|
+
if (!this.isConfigured) {
|
|
122
|
+
if (this.required) {
|
|
123
|
+
return {
|
|
124
|
+
...base,
|
|
125
|
+
status: "blocked",
|
|
126
|
+
blockedAt: "configuration",
|
|
127
|
+
checks: { inventory: "blocked", identity: "not_run", ownership: "not_run", releaseLine: "not_run" },
|
|
128
|
+
message: "canonical lab CLI is not configured",
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
throw new CanonicalBridgeError("canonical lab CLI is not configured");
|
|
132
|
+
}
|
|
133
|
+
const inventory = await this.run(["validate"]);
|
|
134
|
+
base.evidence.inventory = inventory;
|
|
135
|
+
if (inventory.exitCode !== 0) {
|
|
136
|
+
return {
|
|
137
|
+
...base,
|
|
138
|
+
status: "blocked",
|
|
139
|
+
blockedAt: "inventory",
|
|
140
|
+
checks: { inventory: "blocked", identity: "not_run", ownership: "not_run", releaseLine: "not_run" },
|
|
141
|
+
message: inventory.stderr || inventory.stdout || "canonical inventory validation failed",
|
|
142
|
+
command: inventory.command,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
const identity = await this.run(["vm", "status", "--asset-id", input.assetId]);
|
|
146
|
+
base.evidence.identity = identity;
|
|
147
|
+
if (identity.exitCode !== 0) {
|
|
148
|
+
return {
|
|
149
|
+
...base,
|
|
150
|
+
status: "blocked",
|
|
151
|
+
blockedAt: "identity",
|
|
152
|
+
checks: { inventory: "passed", identity: "blocked", ownership: "not_run", releaseLine: "not_run" },
|
|
153
|
+
message: identity.stderr || identity.stdout || "canonical VM identity validation failed",
|
|
154
|
+
command: identity.command,
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
// `context` only reports catalog relationships. `claims show` is the
|
|
158
|
+
// canonical lease/Linear authority and is required to prove that this
|
|
159
|
+
// exact asset is currently claimed by the supplied active issue.
|
|
160
|
+
const ownership = await this.run([
|
|
161
|
+
"claims",
|
|
162
|
+
"show",
|
|
163
|
+
"--asset-id",
|
|
164
|
+
input.assetId,
|
|
165
|
+
"--include-ticket-status",
|
|
166
|
+
"--strict",
|
|
167
|
+
]);
|
|
168
|
+
base.evidence.ownership = ownership;
|
|
169
|
+
let ownsIssue = false;
|
|
170
|
+
try {
|
|
171
|
+
const payload = JSON.parse(ownership.stdout);
|
|
172
|
+
const claim = payload.claim;
|
|
173
|
+
const expiry = claim?.expires_at ? Date.parse(claim.expires_at) : Number.NaN;
|
|
174
|
+
ownsIssue = Boolean(claim
|
|
175
|
+
&& claim.asset_id === input.assetId
|
|
176
|
+
&& claim.linear_issue?.toUpperCase() === input.linearIssue.toUpperCase()
|
|
177
|
+
&& claim.lease_id
|
|
178
|
+
&& claim.expiry_status === "active"
|
|
179
|
+
&& Number.isFinite(expiry)
|
|
180
|
+
&& expiry > Date.now()
|
|
181
|
+
&& claim.ticket_status === "open"
|
|
182
|
+
&& ownership.exitCode === 0);
|
|
183
|
+
}
|
|
184
|
+
catch {
|
|
185
|
+
ownsIssue = false;
|
|
186
|
+
}
|
|
187
|
+
if (ownership.exitCode !== 0 || !ownsIssue) {
|
|
188
|
+
return {
|
|
189
|
+
...base,
|
|
190
|
+
status: "blocked",
|
|
191
|
+
blockedAt: "ownership",
|
|
192
|
+
checks: { inventory: "passed", identity: "passed", ownership: "blocked", releaseLine: "not_run" },
|
|
193
|
+
message: ownership.stderr || "canonical asset is not provably owned by the supplied Linear issue",
|
|
194
|
+
command: ownership.command,
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
const releaseLine = await this.run([
|
|
198
|
+
"fleet",
|
|
199
|
+
"versions",
|
|
200
|
+
"--asset-id",
|
|
201
|
+
input.assetId,
|
|
202
|
+
"--format",
|
|
203
|
+
"json",
|
|
204
|
+
]);
|
|
205
|
+
base.evidence.releaseLine = releaseLine;
|
|
206
|
+
if (releaseLine.exitCode !== 0) {
|
|
207
|
+
return {
|
|
208
|
+
...base,
|
|
209
|
+
status: "blocked",
|
|
210
|
+
blockedAt: "releaseLine",
|
|
211
|
+
checks: { inventory: "passed", identity: "passed", ownership: "passed", releaseLine: "blocked" },
|
|
212
|
+
message: releaseLine.stderr || releaseLine.stdout || "release-line qualification failed",
|
|
213
|
+
command: releaseLine.command,
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
return {
|
|
217
|
+
...base,
|
|
218
|
+
status: "passed",
|
|
219
|
+
checks: { inventory: "passed", identity: "passed", ownership: "passed", releaseLine: "passed" },
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
//# sourceMappingURL=bridge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bridge.js","sourceRoot":"","sources":["../../../src/canonical/bridge.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { CanonicalLabBridge } from "./bridge.js";
|
|
2
|
+
import { LabPreflightInput, LabPreflightResult } from "./types.js";
|
|
3
|
+
export interface CanonicalPreflightResponse {
|
|
4
|
+
exitCode: 0 | 2;
|
|
5
|
+
result: LabPreflightResult;
|
|
6
|
+
}
|
|
7
|
+
export declare function runCanonicalPreflight(input: LabPreflightInput, bridge?: CanonicalLabBridge): Promise<CanonicalPreflightResponse>;
|
|
8
|
+
//# sourceMappingURL=cli.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../../src/canonical/cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAEnE,MAAM,WAAW,0BAA0B;IACzC,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAC;IAChB,MAAM,EAAE,kBAAkB,CAAC;CAC5B;AAED,wBAAsB,qBAAqB,CACzC,KAAK,EAAE,iBAAiB,EACxB,MAAM,qBAA6C,GAClD,OAAO,CAAC,0BAA0B,CAAC,CAMrC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { CanonicalLabBridge } from "./bridge.js";
|
|
2
|
+
export async function runCanonicalPreflight(input, bridge = new CanonicalLabBridge({ required: true })) {
|
|
3
|
+
const result = await bridge.preflight(input);
|
|
4
|
+
return {
|
|
5
|
+
exitCode: result.status === "passed" ? 0 : 2,
|
|
6
|
+
result,
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../../src/canonical/cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAQjD,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,KAAwB,EACxB,MAAM,GAAG,IAAI,kBAAkB,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAEnD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAC7C,OAAO;QACL,QAAQ,EAAE,MAAM,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5C,MAAM;KACP,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/canonical/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/canonical/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export interface CanonicalCommandResult {
|
|
2
|
+
command: string[];
|
|
3
|
+
exitCode: number;
|
|
4
|
+
stdout: string;
|
|
5
|
+
stderr: string;
|
|
6
|
+
timedOut?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export interface LabPreflightInput {
|
|
9
|
+
assetId: string;
|
|
10
|
+
linearIssue: string;
|
|
11
|
+
}
|
|
12
|
+
export interface LabPreflightResult {
|
|
13
|
+
status: "passed" | "blocked";
|
|
14
|
+
assetId: string;
|
|
15
|
+
linearIssue: string;
|
|
16
|
+
checks: {
|
|
17
|
+
inventory: "passed" | "blocked";
|
|
18
|
+
identity: "passed" | "blocked" | "not_run";
|
|
19
|
+
ownership: "passed" | "blocked" | "not_run";
|
|
20
|
+
releaseLine: "passed" | "blocked" | "not_run";
|
|
21
|
+
};
|
|
22
|
+
blockedAt?: "inventory" | "identity" | "ownership" | "releaseLine" | "configuration";
|
|
23
|
+
message?: string;
|
|
24
|
+
command?: string[];
|
|
25
|
+
evidence: {
|
|
26
|
+
inventory?: CanonicalCommandResult;
|
|
27
|
+
identity?: CanonicalCommandResult;
|
|
28
|
+
ownership?: CanonicalCommandResult;
|
|
29
|
+
releaseLine?: CanonicalCommandResult;
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/canonical/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,QAAQ,GAAG,SAAS,CAAC;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE;QACN,SAAS,EAAE,QAAQ,GAAG,SAAS,CAAC;QAChC,QAAQ,EAAE,QAAQ,GAAG,SAAS,GAAG,SAAS,CAAC;QAC3C,SAAS,EAAE,QAAQ,GAAG,SAAS,GAAG,SAAS,CAAC;QAC5C,WAAW,EAAE,QAAQ,GAAG,SAAS,GAAG,SAAS,CAAC;KAC/C,CAAC;IACF,SAAS,CAAC,EAAE,WAAW,GAAG,UAAU,GAAG,WAAW,GAAG,aAAa,GAAG,eAAe,CAAC;IACrF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,EAAE;QACR,SAAS,CAAC,EAAE,sBAAsB,CAAC;QACnC,QAAQ,CAAC,EAAE,sBAAsB,CAAC;QAClC,SAAS,CAAC,EAAE,sBAAsB,CAAC;QACnC,WAAW,CAAC,EAAE,sBAAsB,CAAC;KACtC,CAAC;CACH"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/canonical/types.ts"],"names":[],"mappings":""}
|
package/dist/src/index.d.ts
CHANGED
|
@@ -14,6 +14,7 @@ export * from "./slot/index.js";
|
|
|
14
14
|
export * from "./appliance/index.js";
|
|
15
15
|
export * from "./tools/index.js";
|
|
16
16
|
export * from "./server.js";
|
|
17
|
+
export * from "./canonical/index.js";
|
|
17
18
|
export * from "./server/index.js";
|
|
18
19
|
export * from "./transports/index.js";
|
|
19
20
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/src/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,iBAAiB,CAAC;AAChC,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC;AAClC,cAAc,uBAAuB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,iBAAiB,CAAC;AAChC,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAC5B,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,uBAAuB,CAAC"}
|
package/dist/src/index.js
CHANGED
|
@@ -14,6 +14,7 @@ export * from "./slot/index.js";
|
|
|
14
14
|
export * from "./appliance/index.js";
|
|
15
15
|
export * from "./tools/index.js";
|
|
16
16
|
export * from "./server.js";
|
|
17
|
+
export * from "./canonical/index.js";
|
|
17
18
|
export * from "./server/index.js";
|
|
18
19
|
export * from "./transports/index.js";
|
|
19
20
|
//# sourceMappingURL=index.js.map
|
package/dist/src/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,iBAAiB,CAAC;AAChC,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC;AAClC,cAAc,uBAAuB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,iBAAiB,CAAC;AAChC,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAC5B,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,uBAAuB,CAAC"}
|
package/dist/src/server.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ import { SafetyGuardrailEngine } from "./guardrails/safety.js";
|
|
|
12
12
|
import { IApplianceExecutor } from "./appliance/types.js";
|
|
13
13
|
import { CredentialResolutionResult, ProxmoxHostConfig, EsxiHostConfig } from "./credentials/types.js";
|
|
14
14
|
import { TelemetryRegistry } from "./telemetry/index.js";
|
|
15
|
+
import { CanonicalLabBridge } from "./canonical/bridge.js";
|
|
15
16
|
export interface McpServerOptions {
|
|
16
17
|
name?: string;
|
|
17
18
|
version?: string;
|
|
@@ -28,6 +29,7 @@ export interface McpServerOptions {
|
|
|
28
29
|
esxiConfigs?: EsxiHostConfig[];
|
|
29
30
|
hostConfigs?: ProxmoxHostConfig[];
|
|
30
31
|
proxmoxManager?: MultiHostProxmoxManager;
|
|
32
|
+
canonicalBridge?: CanonicalLabBridge;
|
|
31
33
|
}
|
|
32
34
|
export declare const DEFAULT_SERVER_INSTRUCTIONS: string;
|
|
33
35
|
/**
|
package/dist/src/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/server.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,EAAE,qBAAqB,EAAgC,MAAM,wBAAwB,CAAC;AAE7F,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAG1D,OAAO,EAAE,0BAA0B,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACvG,OAAO,EAAa,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/server.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,EAAE,qBAAqB,EAAgC,MAAM,wBAAwB,CAAC;AAE7F,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAG1D,OAAO,EAAE,0BAA0B,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACvG,OAAO,EAAa,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAE3D,MAAM,WAAW,gBAAgB;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,iBAAiB,CAAC,EAAE,sBAAsB,CAAC;IAC3C,eAAe,CAAC,EAAE,qBAAqB,CAAC;IACxC,iBAAiB,CAAC,EAAE,kBAAkB,CAAC;IACvC,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IACtC,WAAW,CAAC,EAAE,0BAA0B,CAAC;IACzC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,cAAc,CAAC,EAAE,iBAAiB,EAAE,CAAC;IACrC,WAAW,CAAC,EAAE,cAAc,EAAE,CAAC;IAC/B,WAAW,CAAC,EAAE,iBAAiB,EAAE,CAAC;IAClC,cAAc,CAAC,EAAE,uBAAuB,CAAC;IACzC,eAAe,CAAC,EAAE,kBAAkB,CAAC;CACtC;AAED,eAAO,MAAM,2BAA2B,QAU8J,CAAC;AAEvM;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,GAAE,gBAAqB,GAAG,SAAS,CA4FzE"}
|
package/dist/src/server.js
CHANGED
|
@@ -12,6 +12,7 @@ import { registerAllTools } from "./tools/index.js";
|
|
|
12
12
|
import { applianceSshExecutor } from "./appliance/executor.js";
|
|
13
13
|
import { mockApplianceExecutor } from "./appliance/mock.js";
|
|
14
14
|
import { telemetry } from "./telemetry/index.js";
|
|
15
|
+
import { CanonicalLabBridge } from "./canonical/bridge.js";
|
|
15
16
|
export const DEFAULT_SERVER_INSTRUCTIONS = "You are connected to @calltelemetry/ct-lab-mcp, the unified Call Telemetry lab, fleet, and appliance management MCP server.\n\n" +
|
|
16
17
|
"Capabilities:\n" +
|
|
17
18
|
"- Multi-Hypervisor Capacity & Health: Query Proxmox VE (proxmox-lab, proxmox-mini) and VMware ESXi (esxi-intel-192-168-123-176) with 'list_hosts'.\n" +
|
|
@@ -93,6 +94,7 @@ export function createMcpServer(options = {}) {
|
|
|
93
94
|
proxmoxManager: options.proxmoxManager,
|
|
94
95
|
credentials: options.credentials,
|
|
95
96
|
mockPermitted: Boolean(options.forceMock || options.credentials?.tier === "mock_fallback"),
|
|
97
|
+
canonicalBridge: options.canonicalBridge || new CanonicalLabBridge(),
|
|
96
98
|
};
|
|
97
99
|
// 6. Register all MCP tools
|
|
98
100
|
registerAllTools(server, context);
|
package/dist/src/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/server.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAElE,OAAO,EAAyB,4BAA4B,EAAE,MAAM,wBAAwB,CAAC;AAC7F,OAAO,EAAE,gBAAgB,EAAe,MAAM,kBAAkB,CAAC;AAEjE,OAAO,EAAwB,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AACrF,OAAO,EAAyB,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAEnF,OAAO,EAAE,SAAS,EAAqB,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ToolContext } from "./list-hosts.js";
|
|
2
|
+
import { CanonicalLabBridge } from "../canonical/bridge.js";
|
|
3
|
+
import { CallToolResult } from "../types/mcp.js";
|
|
4
|
+
export declare function canonicalMode(context: ToolContext): boolean;
|
|
5
|
+
export declare function canonicalOperationBlocked(operation: string, hint: string): CallToolResult;
|
|
6
|
+
export declare function runCanonicalOperation(bridge: CanonicalLabBridge | undefined, operation: string, args: string[]): Promise<CallToolResult>;
|
|
7
|
+
//# sourceMappingURL=canonical-guard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canonical-guard.d.ts","sourceRoot":"","sources":["../../../src/tools/canonical-guard.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAkD,MAAM,iBAAiB,CAAC;AAEjG,wBAAgB,aAAa,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAE3D;AAED,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,cAAc,CAMzF;AAUD,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,kBAAkB,GAAG,SAAS,EACtC,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,EAAE,GACb,OAAO,CAAC,cAAc,CAAC,CA4BzB"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { createToolErrorResult, createToolSuccessResult } from "../types/mcp.js";
|
|
2
|
+
export function canonicalMode(context) {
|
|
3
|
+
return context.canonicalBridge?.isRequired === true;
|
|
4
|
+
}
|
|
5
|
+
export function canonicalOperationBlocked(operation, hint) {
|
|
6
|
+
return createToolErrorResult("CANONICAL_OPERATION_REQUIRES_BRIDGE", `${operation} is disabled in canonical lab mode: ${hint}`, { operation, canonicalAuthority: "plugins/ct-lab/skills/lab-inventory/scripts/lab-inventory" });
|
|
7
|
+
}
|
|
8
|
+
function parseJson(stdout) {
|
|
9
|
+
try {
|
|
10
|
+
return JSON.parse(stdout);
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
return stdout;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export async function runCanonicalOperation(bridge, operation, args) {
|
|
17
|
+
if (!bridge) {
|
|
18
|
+
return createToolErrorResult("CANONICAL_INVENTORY_UNAVAILABLE", "canonical lab bridge is not available", { operation });
|
|
19
|
+
}
|
|
20
|
+
try {
|
|
21
|
+
const result = await bridge.run(args);
|
|
22
|
+
const payload = {
|
|
23
|
+
success: result.exitCode === 0,
|
|
24
|
+
operation,
|
|
25
|
+
command: result.command,
|
|
26
|
+
result: parseJson(result.stdout),
|
|
27
|
+
...(result.stderr ? { stderr: result.stderr } : {}),
|
|
28
|
+
};
|
|
29
|
+
if (result.exitCode !== 0) {
|
|
30
|
+
return createToolErrorResult("CANONICAL_OPERATION_FAILED", result.stderr || result.stdout || `${operation} failed in canonical lab CLI`, payload);
|
|
31
|
+
}
|
|
32
|
+
return createToolSuccessResult(result.stdout || `${operation} completed in canonical lab CLI`, payload);
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
return createToolErrorResult("CANONICAL_INVENTORY_UNAVAILABLE", error instanceof Error ? error.message : String(error), { operation });
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=canonical-guard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canonical-guard.js","sourceRoot":"","sources":["../../../src/tools/canonical-guard.ts"],"names":[],"mappings":"AAEA,OAAO,EAAkB,qBAAqB,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAEjG,MAAM,UAAU,aAAa,CAAC,OAAoB;IAChD,OAAO,OAAO,CAAC,eAAe,EAAE,UAAU,KAAK,IAAI,CAAC;AACtD,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,SAAiB,EAAE,IAAY;IACvE,OAAO,qBAAqB,CAC1B,qCAAqC,EACrC,GAAG,SAAS,uCAAuC,IAAI,EAAE,EACzD,EAAE,SAAS,EAAE,kBAAkB,EAAE,2DAA2D,EAAE,CAC/F,CAAC;AACJ,CAAC;AAED,SAAS,SAAS,CAAC,MAAc;IAC/B,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,MAAM,CAAC;IAChB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,MAAsC,EACtC,SAAiB,EACjB,IAAc;IAEd,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,qBAAqB,CAAC,iCAAiC,EAAE,uCAAuC,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC;IAC1H,CAAC;IACD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACtC,MAAM,OAAO,GAAG;YACd,OAAO,EAAE,MAAM,CAAC,QAAQ,KAAK,CAAC;YAC9B,SAAS;YACT,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,MAAM,EAAE,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC;YAChC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACpD,CAAC;QACF,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;YAC1B,OAAO,qBAAqB,CAC1B,4BAA4B,EAC5B,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,IAAI,GAAG,SAAS,8BAA8B,EAC5E,OAAO,CACR,CAAC;QACJ,CAAC;QACD,OAAO,uBAAuB,CAAC,MAAM,CAAC,MAAM,IAAI,GAAG,SAAS,iCAAiC,EAAE,OAAO,CAAC,CAAC;IAC1G,CAAC;IAAC,OAAO,KAAc,EAAE,CAAC;QACxB,OAAO,qBAAqB,CAC1B,iCAAiC,EACjC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EACtD,EAAE,SAAS,EAAE,CACd,CAAC;IACJ,CAAC;AACH,CAAC"}
|
|
@@ -33,6 +33,7 @@ export * from "./cucm-trunk.js";
|
|
|
33
33
|
export * from "./server-management.js";
|
|
34
34
|
export * from "./cucm-emulator-tool.js";
|
|
35
35
|
export * from "./credential-status.js";
|
|
36
|
+
export * from "./lab-preflight.js";
|
|
36
37
|
/**
|
|
37
38
|
* Register all Call Telemetry Lab MCP tools onto an McpServer instance.
|
|
38
39
|
*/
|