machine-bridge-mcp 0.5.0 → 0.6.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/CHANGELOG.md +27 -0
- package/README.md +93 -5
- package/SECURITY.md +33 -3
- package/docs/ARCHITECTURE.md +41 -8
- package/docs/CLIENTS.md +13 -2
- package/docs/LOGGING.md +3 -1
- package/docs/MANAGED_JOBS.md +274 -0
- package/docs/OPERATIONS.md +55 -4
- package/docs/TESTING.md +6 -1
- package/package.json +5 -4
- package/src/local/cli.mjs +192 -5
- package/src/local/daemon.mjs +101 -1
- package/src/local/job-runner.mjs +470 -0
- package/src/local/managed-jobs.mjs +854 -0
- package/src/local/state.mjs +51 -8
- package/src/local/stdio.mjs +2 -2
- package/src/shared/server-metadata.json +8 -1
- package/src/shared/tool-catalog.json +498 -0
- package/src/worker/index.ts +1 -1
package/src/local/state.mjs
CHANGED
|
@@ -20,7 +20,7 @@ export function expandHome(input = "") {
|
|
|
20
20
|
|
|
21
21
|
export function resolveWorkspace(input = process.cwd()) {
|
|
22
22
|
const resolved = path.resolve(expandHome(input));
|
|
23
|
-
return realpathSync(resolved);
|
|
23
|
+
return realpathSync.native ? realpathSync.native(resolved) : realpathSync(resolved);
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
export function defaultStateRoot() {
|
|
@@ -52,9 +52,10 @@ export function saveGlobalConfig(config, stateRoot = defaultStateRoot()) {
|
|
|
52
52
|
|
|
53
53
|
export function setSelectedWorkspace(workspace, stateRoot = defaultStateRoot()) {
|
|
54
54
|
const root = expandHome(stateRoot);
|
|
55
|
+
const canonicalWorkspace = resolveWorkspace(workspace);
|
|
55
56
|
const config = loadGlobalConfig(root);
|
|
56
|
-
config.selectedWorkspace =
|
|
57
|
-
config.selectedWorkspaceHash = workspaceHash(
|
|
57
|
+
config.selectedWorkspace = canonicalWorkspace;
|
|
58
|
+
config.selectedWorkspaceHash = workspaceHash(canonicalWorkspace);
|
|
58
59
|
saveGlobalConfig(config, root);
|
|
59
60
|
return config;
|
|
60
61
|
}
|
|
@@ -79,7 +80,9 @@ export function removeStateRoot(stateRoot = defaultStateRoot()) {
|
|
|
79
80
|
}
|
|
80
81
|
|
|
81
82
|
export function workspaceHash(workspace) {
|
|
82
|
-
|
|
83
|
+
const canonical = resolveWorkspace(workspace);
|
|
84
|
+
const identity = process.platform === "win32" ? canonical.toLowerCase() : canonical;
|
|
85
|
+
return createHash("sha256").update(identity).digest("hex").slice(0, 24);
|
|
83
86
|
}
|
|
84
87
|
|
|
85
88
|
function profileDirForWorkspace(workspace, stateRoot = defaultStateRoot()) {
|
|
@@ -87,9 +90,43 @@ function profileDirForWorkspace(workspace, stateRoot = defaultStateRoot()) {
|
|
|
87
90
|
}
|
|
88
91
|
|
|
89
92
|
|
|
93
|
+
function matchingLegacyProfileDir(canonicalWorkspace, stateRoot) {
|
|
94
|
+
const profilesRoot = path.join(stateRoot, "profiles");
|
|
95
|
+
if (!existsSync(profilesRoot)) return "";
|
|
96
|
+
const matches = [];
|
|
97
|
+
for (const entry of readdirSync(profilesRoot, { withFileTypes: true })) {
|
|
98
|
+
if (!entry.isDirectory() || !/^[a-f0-9]{24}$/.test(entry.name)) continue;
|
|
99
|
+
const profileDir = path.join(profilesRoot, entry.name);
|
|
100
|
+
const stateFile = path.join(profileDir, "state.json");
|
|
101
|
+
if (!existsSync(stateFile)) continue;
|
|
102
|
+
try {
|
|
103
|
+
const value = JSON.parse(readBoundedUtf8(stateFile, MAX_STATE_JSON_BYTES, "state JSON"));
|
|
104
|
+
const storedWorkspace = value?.workspace?.path;
|
|
105
|
+
if (typeof storedWorkspace !== "string") continue;
|
|
106
|
+
if (sameWorkspaceIdentity(storedWorkspace, canonicalWorkspace)) matches.push(profileDir);
|
|
107
|
+
} catch {}
|
|
108
|
+
}
|
|
109
|
+
if (matches.length > 1) throw new Error("multiple Machine Bridge profiles refer to the same canonical workspace; remove or merge the duplicate state profiles");
|
|
110
|
+
return matches[0] || "";
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function sameWorkspaceIdentity(left, right) {
|
|
114
|
+
try {
|
|
115
|
+
const a = resolveWorkspace(left);
|
|
116
|
+
const b = resolveWorkspace(right);
|
|
117
|
+
return process.platform === "win32" ? a.toLowerCase() === b.toLowerCase() : a === b;
|
|
118
|
+
} catch {
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
90
123
|
export function loadState(workspace, options = {}) {
|
|
124
|
+
const canonicalWorkspace = resolveWorkspace(workspace);
|
|
91
125
|
const stateRoot = ensureStateRoot(options.stateDir ? expandHome(options.stateDir) : defaultStateRoot());
|
|
92
|
-
const
|
|
126
|
+
const canonicalProfileDir = profileDirForWorkspace(canonicalWorkspace, stateRoot);
|
|
127
|
+
const profileDir = existsSync(canonicalProfileDir)
|
|
128
|
+
? canonicalProfileDir
|
|
129
|
+
: matchingLegacyProfileDir(canonicalWorkspace, stateRoot) || canonicalProfileDir;
|
|
93
130
|
const statePath = path.join(profileDir, "state.json");
|
|
94
131
|
ensureOwnerOnlyDir(profileDir);
|
|
95
132
|
let state = {};
|
|
@@ -97,15 +134,16 @@ export function loadState(workspace, options = {}) {
|
|
|
97
134
|
ownerOnlyFile(statePath);
|
|
98
135
|
state = readJsonObjectOrBackup(statePath);
|
|
99
136
|
}
|
|
100
|
-
state.schemaVersion =
|
|
137
|
+
state.schemaVersion = 5;
|
|
101
138
|
state.workspace = {
|
|
102
|
-
path:
|
|
103
|
-
hash:
|
|
139
|
+
path: canonicalWorkspace,
|
|
140
|
+
hash: path.basename(profileDir),
|
|
104
141
|
updatedAt: new Date().toISOString(),
|
|
105
142
|
};
|
|
106
143
|
state.paths = { stateRoot, profileDir, statePath };
|
|
107
144
|
state.worker ||= {};
|
|
108
145
|
state.policy ||= {};
|
|
146
|
+
state.resources ||= {};
|
|
109
147
|
delete state.localApi;
|
|
110
148
|
return state;
|
|
111
149
|
}
|
|
@@ -467,6 +505,11 @@ export function redactState(state) {
|
|
|
467
505
|
if (clone.worker?.oauthPassword) clone.worker.oauthPassword = "<redacted>";
|
|
468
506
|
if (clone.worker?.daemonSecret) clone.worker.daemonSecret = "<redacted>";
|
|
469
507
|
if (clone.worker?.oauthTokenVersion) clone.worker.oauthTokenVersion = "<redacted>";
|
|
508
|
+
if (clone.resources && typeof clone.resources === "object") {
|
|
509
|
+
for (const value of Object.values(clone.resources)) {
|
|
510
|
+
if (value && typeof value === "object" && value.path) value.path = "<local-resource-path>";
|
|
511
|
+
}
|
|
512
|
+
}
|
|
470
513
|
return clone;
|
|
471
514
|
}
|
|
472
515
|
|
package/src/local/stdio.mjs
CHANGED
|
@@ -18,9 +18,9 @@ const MAX_LINE_BYTES = 8 * 1024 * 1024;
|
|
|
18
18
|
const SLOW_TOOL_CALL_MS = 30_000;
|
|
19
19
|
const PACKAGE_VERSION = String(JSON.parse(readFileSync(new URL("../../package.json", import.meta.url), "utf8")).version);
|
|
20
20
|
|
|
21
|
-
export async function runStdioServer({ workspace, policy, logLevel = "info" }) {
|
|
21
|
+
export async function runStdioServer({ workspace, policy, logLevel = "info", jobRoot = "", resources = {}, resourceStatePath = "" }) {
|
|
22
22
|
const logger = createLogger({ component: "stdio", level: logLevel, stderrOnly: true, color: false });
|
|
23
|
-
const runtime = new LocalDaemon({ workspace, policy, logger });
|
|
23
|
+
const runtime = new LocalDaemon({ workspace, policy, logger, jobRoot, resources, resourceStatePath });
|
|
24
24
|
const pending = new Map();
|
|
25
25
|
let negotiatedVersion = MCP_PROTOCOL_VERSION;
|
|
26
26
|
let initialized = false;
|
|
@@ -10,7 +10,14 @@
|
|
|
10
10
|
"You are connected to a local workspace through machine-bridge-mcp.",
|
|
11
11
|
"Remote mode uses a Cloudflare relay; stdio mode runs on the local machine. File and command operations execute on the user's local runtime, not in the Worker.",
|
|
12
12
|
"Filesystem scope and path display follow the active local policy; the default full profile is unrestricted.",
|
|
13
|
-
"Filename sensitivity is not classified by this server; the MCP host may enforce additional independent rules.",
|
|
13
|
+
"Filename sensitivity is not classified by this server; the MCP host, connector gateway, local OS, or endpoint-security software may enforce additional independent rules.",
|
|
14
|
+
"Use diagnose_runtime to distinguish a request that reached the daemon from local filesystem, process-spawn, shell, managed-job-storage, and resource failures. A tool call blocked before any response cannot be diagnosed by the server.",
|
|
15
|
+
"Never request or return secret-file contents when a local resource alias can be used. Resources are registered only through the local machine-mcp CLI and may be injected by path, stdin, or environment without entering MCP arguments.",
|
|
16
|
+
"If execution-class tools are unavailable but write access remains, use stage_job to persist a reviewed plan without running it; the operator can launch it locally with machine-mcp job approve JOB_ID.",
|
|
17
|
+
"For multi-step, remote, long-running, or cleanup-sensitive work, prefer one start_job call with argv steps, job-scoped temporary_files, and idempotent finally_steps. The detached runner continues after MCP disconnects; inspect it with read_job or the local machine-mcp job CLI.",
|
|
18
|
+
"Prefer sending remote shell programs through a process stdin rather than creating remote helper files. If temporary files are necessary, use {{temp:name}} or explicit finally_steps.",
|
|
19
|
+
"Managed-job resource redaction is defense in depth, not a guarantee against transformed or partial secret output. Use capture_output=discard for steps that may echo credentials.",
|
|
20
|
+
"Do not use shell encoding, renaming, or alternate tools to bypass host or platform safety policy.",
|
|
14
21
|
"run_process avoids shell parsing but is not an OS sandbox. exec_command is exposed only in shell mode and has the local user's authority.",
|
|
15
22
|
"Inspect before editing, prefer read_file line ranges, edit_file, or apply_patch over whole-file replacement, and report commands that were run."
|
|
16
23
|
]
|
|
@@ -603,6 +603,504 @@
|
|
|
603
603
|
"additionalProperties": false
|
|
604
604
|
}
|
|
605
605
|
},
|
|
606
|
+
{
|
|
607
|
+
"name": "diagnose_runtime",
|
|
608
|
+
"title": "Diagnose runtime layers",
|
|
609
|
+
"description": "Run fixed, non-user-controlled local probes to distinguish MCP policy, local filesystem, process-spawn, shell, managed-job storage, and registered-resource failures. A successful response proves the request reached the local daemon; it cannot diagnose a host refusal that blocks the tool call itself.",
|
|
610
|
+
"availability": "always",
|
|
611
|
+
"annotations": {
|
|
612
|
+
"readOnlyHint": true,
|
|
613
|
+
"destructiveHint": false,
|
|
614
|
+
"idempotentHint": true,
|
|
615
|
+
"openWorldHint": false
|
|
616
|
+
},
|
|
617
|
+
"inputSchema": {
|
|
618
|
+
"type": "object",
|
|
619
|
+
"additionalProperties": false
|
|
620
|
+
}
|
|
621
|
+
},
|
|
622
|
+
{
|
|
623
|
+
"name": "list_local_resources",
|
|
624
|
+
"title": "List local resource aliases",
|
|
625
|
+
"description": "List names and validation status for locally registered file resources without returning their paths or contents. Resources are registered only through the local machine-mcp CLI.",
|
|
626
|
+
"availability": "write",
|
|
627
|
+
"annotations": {
|
|
628
|
+
"readOnlyHint": true,
|
|
629
|
+
"destructiveHint": false,
|
|
630
|
+
"idempotentHint": true,
|
|
631
|
+
"openWorldHint": false
|
|
632
|
+
},
|
|
633
|
+
"inputSchema": {
|
|
634
|
+
"type": "object",
|
|
635
|
+
"additionalProperties": false
|
|
636
|
+
}
|
|
637
|
+
},
|
|
638
|
+
{
|
|
639
|
+
"name": "stage_job",
|
|
640
|
+
"title": "Stage managed job for local approval",
|
|
641
|
+
"description": "Validate and persist a managed-job plan without starting any process. Use this when execution tools are unavailable or local operator review is required; launch later with machine-mcp job approve JOB_ID.",
|
|
642
|
+
"availability": "write",
|
|
643
|
+
"annotations": {
|
|
644
|
+
"readOnlyHint": false,
|
|
645
|
+
"destructiveHint": false,
|
|
646
|
+
"idempotentHint": false,
|
|
647
|
+
"openWorldHint": false
|
|
648
|
+
},
|
|
649
|
+
"inputSchema": {
|
|
650
|
+
"type": "object",
|
|
651
|
+
"properties": {
|
|
652
|
+
"name": {
|
|
653
|
+
"type": "string",
|
|
654
|
+
"maxLength": 128
|
|
655
|
+
},
|
|
656
|
+
"steps": {
|
|
657
|
+
"type": "array",
|
|
658
|
+
"minItems": 1,
|
|
659
|
+
"maxItems": 16,
|
|
660
|
+
"items": {
|
|
661
|
+
"type": "object",
|
|
662
|
+
"properties": {
|
|
663
|
+
"name": {
|
|
664
|
+
"type": "string",
|
|
665
|
+
"maxLength": 128
|
|
666
|
+
},
|
|
667
|
+
"argv": {
|
|
668
|
+
"type": "array",
|
|
669
|
+
"minItems": 1,
|
|
670
|
+
"maxItems": 256,
|
|
671
|
+
"items": {
|
|
672
|
+
"type": "string",
|
|
673
|
+
"maxLength": 16384
|
|
674
|
+
}
|
|
675
|
+
},
|
|
676
|
+
"cwd": {
|
|
677
|
+
"type": "string",
|
|
678
|
+
"maxLength": 4096
|
|
679
|
+
},
|
|
680
|
+
"env": {
|
|
681
|
+
"type": "object",
|
|
682
|
+
"maxProperties": 64,
|
|
683
|
+
"additionalProperties": {
|
|
684
|
+
"type": "string",
|
|
685
|
+
"maxLength": 16384
|
|
686
|
+
}
|
|
687
|
+
},
|
|
688
|
+
"env_resources": {
|
|
689
|
+
"type": "object",
|
|
690
|
+
"maxProperties": 32,
|
|
691
|
+
"additionalProperties": {
|
|
692
|
+
"type": "string",
|
|
693
|
+
"pattern": "^[a-z][a-z0-9._-]{0,63}$"
|
|
694
|
+
}
|
|
695
|
+
},
|
|
696
|
+
"stdin": {
|
|
697
|
+
"type": "string",
|
|
698
|
+
"maxLength": 262144
|
|
699
|
+
},
|
|
700
|
+
"stdin_resource": {
|
|
701
|
+
"type": "string",
|
|
702
|
+
"pattern": "^[a-z][a-z0-9._-]{0,63}$"
|
|
703
|
+
},
|
|
704
|
+
"timeout_seconds": {
|
|
705
|
+
"type": "integer",
|
|
706
|
+
"minimum": 1,
|
|
707
|
+
"maximum": 3600,
|
|
708
|
+
"default": 600
|
|
709
|
+
},
|
|
710
|
+
"allow_failure": {
|
|
711
|
+
"type": "boolean",
|
|
712
|
+
"default": false
|
|
713
|
+
},
|
|
714
|
+
"capture_output": {
|
|
715
|
+
"type": "string",
|
|
716
|
+
"enum": [
|
|
717
|
+
"redacted",
|
|
718
|
+
"discard"
|
|
719
|
+
],
|
|
720
|
+
"default": "redacted"
|
|
721
|
+
}
|
|
722
|
+
},
|
|
723
|
+
"required": [
|
|
724
|
+
"argv"
|
|
725
|
+
],
|
|
726
|
+
"additionalProperties": false
|
|
727
|
+
}
|
|
728
|
+
},
|
|
729
|
+
"finally_steps": {
|
|
730
|
+
"type": "array",
|
|
731
|
+
"maxItems": 16,
|
|
732
|
+
"items": {
|
|
733
|
+
"type": "object",
|
|
734
|
+
"properties": {
|
|
735
|
+
"name": {
|
|
736
|
+
"type": "string",
|
|
737
|
+
"maxLength": 128
|
|
738
|
+
},
|
|
739
|
+
"argv": {
|
|
740
|
+
"type": "array",
|
|
741
|
+
"minItems": 1,
|
|
742
|
+
"maxItems": 256,
|
|
743
|
+
"items": {
|
|
744
|
+
"type": "string",
|
|
745
|
+
"maxLength": 16384
|
|
746
|
+
}
|
|
747
|
+
},
|
|
748
|
+
"cwd": {
|
|
749
|
+
"type": "string",
|
|
750
|
+
"maxLength": 4096
|
|
751
|
+
},
|
|
752
|
+
"env": {
|
|
753
|
+
"type": "object",
|
|
754
|
+
"maxProperties": 64,
|
|
755
|
+
"additionalProperties": {
|
|
756
|
+
"type": "string",
|
|
757
|
+
"maxLength": 16384
|
|
758
|
+
}
|
|
759
|
+
},
|
|
760
|
+
"env_resources": {
|
|
761
|
+
"type": "object",
|
|
762
|
+
"maxProperties": 32,
|
|
763
|
+
"additionalProperties": {
|
|
764
|
+
"type": "string",
|
|
765
|
+
"pattern": "^[a-z][a-z0-9._-]{0,63}$"
|
|
766
|
+
}
|
|
767
|
+
},
|
|
768
|
+
"stdin": {
|
|
769
|
+
"type": "string",
|
|
770
|
+
"maxLength": 262144
|
|
771
|
+
},
|
|
772
|
+
"stdin_resource": {
|
|
773
|
+
"type": "string",
|
|
774
|
+
"pattern": "^[a-z][a-z0-9._-]{0,63}$"
|
|
775
|
+
},
|
|
776
|
+
"timeout_seconds": {
|
|
777
|
+
"type": "integer",
|
|
778
|
+
"minimum": 1,
|
|
779
|
+
"maximum": 3600,
|
|
780
|
+
"default": 600
|
|
781
|
+
},
|
|
782
|
+
"allow_failure": {
|
|
783
|
+
"type": "boolean",
|
|
784
|
+
"default": false
|
|
785
|
+
},
|
|
786
|
+
"capture_output": {
|
|
787
|
+
"type": "string",
|
|
788
|
+
"enum": [
|
|
789
|
+
"redacted",
|
|
790
|
+
"discard"
|
|
791
|
+
],
|
|
792
|
+
"default": "redacted"
|
|
793
|
+
}
|
|
794
|
+
},
|
|
795
|
+
"required": [
|
|
796
|
+
"argv"
|
|
797
|
+
],
|
|
798
|
+
"additionalProperties": false
|
|
799
|
+
}
|
|
800
|
+
},
|
|
801
|
+
"temporary_files": {
|
|
802
|
+
"type": "array",
|
|
803
|
+
"maxItems": 16,
|
|
804
|
+
"items": {
|
|
805
|
+
"type": "object",
|
|
806
|
+
"properties": {
|
|
807
|
+
"name": {
|
|
808
|
+
"type": "string",
|
|
809
|
+
"pattern": "^[a-z][a-z0-9._-]{0,63}$"
|
|
810
|
+
},
|
|
811
|
+
"content": {
|
|
812
|
+
"type": "string",
|
|
813
|
+
"maxLength": 262144
|
|
814
|
+
},
|
|
815
|
+
"executable": {
|
|
816
|
+
"type": "boolean",
|
|
817
|
+
"default": false
|
|
818
|
+
}
|
|
819
|
+
},
|
|
820
|
+
"required": [
|
|
821
|
+
"name",
|
|
822
|
+
"content"
|
|
823
|
+
],
|
|
824
|
+
"additionalProperties": false
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
},
|
|
828
|
+
"required": [
|
|
829
|
+
"steps"
|
|
830
|
+
],
|
|
831
|
+
"additionalProperties": false
|
|
832
|
+
}
|
|
833
|
+
},
|
|
834
|
+
{
|
|
835
|
+
"name": "start_job",
|
|
836
|
+
"title": "Start managed job",
|
|
837
|
+
"description": "Durably accept a detached argv-based job with ordered steps, job-scoped temporary files, and guaranteed-attempt finally steps. The independent local runner continues if the MCP connection disappears. Use {{temp:name}}, {{resource:name}}, env_resources, or stdin_resource; registered resource contents never enter MCP arguments.",
|
|
838
|
+
"availability": "direct-exec",
|
|
839
|
+
"annotations": {
|
|
840
|
+
"readOnlyHint": false,
|
|
841
|
+
"destructiveHint": true,
|
|
842
|
+
"idempotentHint": false,
|
|
843
|
+
"openWorldHint": true
|
|
844
|
+
},
|
|
845
|
+
"inputSchema": {
|
|
846
|
+
"type": "object",
|
|
847
|
+
"properties": {
|
|
848
|
+
"name": {
|
|
849
|
+
"type": "string",
|
|
850
|
+
"maxLength": 128
|
|
851
|
+
},
|
|
852
|
+
"steps": {
|
|
853
|
+
"type": "array",
|
|
854
|
+
"minItems": 1,
|
|
855
|
+
"maxItems": 16,
|
|
856
|
+
"items": {
|
|
857
|
+
"type": "object",
|
|
858
|
+
"properties": {
|
|
859
|
+
"name": {
|
|
860
|
+
"type": "string",
|
|
861
|
+
"maxLength": 128
|
|
862
|
+
},
|
|
863
|
+
"argv": {
|
|
864
|
+
"type": "array",
|
|
865
|
+
"minItems": 1,
|
|
866
|
+
"maxItems": 256,
|
|
867
|
+
"items": {
|
|
868
|
+
"type": "string",
|
|
869
|
+
"maxLength": 16384
|
|
870
|
+
}
|
|
871
|
+
},
|
|
872
|
+
"cwd": {
|
|
873
|
+
"type": "string",
|
|
874
|
+
"maxLength": 4096
|
|
875
|
+
},
|
|
876
|
+
"env": {
|
|
877
|
+
"type": "object",
|
|
878
|
+
"maxProperties": 64,
|
|
879
|
+
"additionalProperties": {
|
|
880
|
+
"type": "string",
|
|
881
|
+
"maxLength": 16384
|
|
882
|
+
}
|
|
883
|
+
},
|
|
884
|
+
"env_resources": {
|
|
885
|
+
"type": "object",
|
|
886
|
+
"maxProperties": 32,
|
|
887
|
+
"additionalProperties": {
|
|
888
|
+
"type": "string",
|
|
889
|
+
"pattern": "^[a-z][a-z0-9._-]{0,63}$"
|
|
890
|
+
}
|
|
891
|
+
},
|
|
892
|
+
"stdin": {
|
|
893
|
+
"type": "string",
|
|
894
|
+
"maxLength": 262144
|
|
895
|
+
},
|
|
896
|
+
"stdin_resource": {
|
|
897
|
+
"type": "string",
|
|
898
|
+
"pattern": "^[a-z][a-z0-9._-]{0,63}$"
|
|
899
|
+
},
|
|
900
|
+
"timeout_seconds": {
|
|
901
|
+
"type": "integer",
|
|
902
|
+
"minimum": 1,
|
|
903
|
+
"maximum": 3600,
|
|
904
|
+
"default": 600
|
|
905
|
+
},
|
|
906
|
+
"allow_failure": {
|
|
907
|
+
"type": "boolean",
|
|
908
|
+
"default": false
|
|
909
|
+
},
|
|
910
|
+
"capture_output": {
|
|
911
|
+
"type": "string",
|
|
912
|
+
"enum": [
|
|
913
|
+
"redacted",
|
|
914
|
+
"discard"
|
|
915
|
+
],
|
|
916
|
+
"default": "redacted"
|
|
917
|
+
}
|
|
918
|
+
},
|
|
919
|
+
"required": [
|
|
920
|
+
"argv"
|
|
921
|
+
],
|
|
922
|
+
"additionalProperties": false
|
|
923
|
+
}
|
|
924
|
+
},
|
|
925
|
+
"finally_steps": {
|
|
926
|
+
"type": "array",
|
|
927
|
+
"maxItems": 16,
|
|
928
|
+
"items": {
|
|
929
|
+
"type": "object",
|
|
930
|
+
"properties": {
|
|
931
|
+
"name": {
|
|
932
|
+
"type": "string",
|
|
933
|
+
"maxLength": 128
|
|
934
|
+
},
|
|
935
|
+
"argv": {
|
|
936
|
+
"type": "array",
|
|
937
|
+
"minItems": 1,
|
|
938
|
+
"maxItems": 256,
|
|
939
|
+
"items": {
|
|
940
|
+
"type": "string",
|
|
941
|
+
"maxLength": 16384
|
|
942
|
+
}
|
|
943
|
+
},
|
|
944
|
+
"cwd": {
|
|
945
|
+
"type": "string",
|
|
946
|
+
"maxLength": 4096
|
|
947
|
+
},
|
|
948
|
+
"env": {
|
|
949
|
+
"type": "object",
|
|
950
|
+
"maxProperties": 64,
|
|
951
|
+
"additionalProperties": {
|
|
952
|
+
"type": "string",
|
|
953
|
+
"maxLength": 16384
|
|
954
|
+
}
|
|
955
|
+
},
|
|
956
|
+
"env_resources": {
|
|
957
|
+
"type": "object",
|
|
958
|
+
"maxProperties": 32,
|
|
959
|
+
"additionalProperties": {
|
|
960
|
+
"type": "string",
|
|
961
|
+
"pattern": "^[a-z][a-z0-9._-]{0,63}$"
|
|
962
|
+
}
|
|
963
|
+
},
|
|
964
|
+
"stdin": {
|
|
965
|
+
"type": "string",
|
|
966
|
+
"maxLength": 262144
|
|
967
|
+
},
|
|
968
|
+
"stdin_resource": {
|
|
969
|
+
"type": "string",
|
|
970
|
+
"pattern": "^[a-z][a-z0-9._-]{0,63}$"
|
|
971
|
+
},
|
|
972
|
+
"timeout_seconds": {
|
|
973
|
+
"type": "integer",
|
|
974
|
+
"minimum": 1,
|
|
975
|
+
"maximum": 3600,
|
|
976
|
+
"default": 600
|
|
977
|
+
},
|
|
978
|
+
"allow_failure": {
|
|
979
|
+
"type": "boolean",
|
|
980
|
+
"default": false
|
|
981
|
+
},
|
|
982
|
+
"capture_output": {
|
|
983
|
+
"type": "string",
|
|
984
|
+
"enum": [
|
|
985
|
+
"redacted",
|
|
986
|
+
"discard"
|
|
987
|
+
],
|
|
988
|
+
"default": "redacted"
|
|
989
|
+
}
|
|
990
|
+
},
|
|
991
|
+
"required": [
|
|
992
|
+
"argv"
|
|
993
|
+
],
|
|
994
|
+
"additionalProperties": false
|
|
995
|
+
}
|
|
996
|
+
},
|
|
997
|
+
"temporary_files": {
|
|
998
|
+
"type": "array",
|
|
999
|
+
"maxItems": 16,
|
|
1000
|
+
"items": {
|
|
1001
|
+
"type": "object",
|
|
1002
|
+
"properties": {
|
|
1003
|
+
"name": {
|
|
1004
|
+
"type": "string",
|
|
1005
|
+
"pattern": "^[a-z][a-z0-9._-]{0,63}$"
|
|
1006
|
+
},
|
|
1007
|
+
"content": {
|
|
1008
|
+
"type": "string",
|
|
1009
|
+
"maxLength": 262144
|
|
1010
|
+
},
|
|
1011
|
+
"executable": {
|
|
1012
|
+
"type": "boolean",
|
|
1013
|
+
"default": false
|
|
1014
|
+
}
|
|
1015
|
+
},
|
|
1016
|
+
"required": [
|
|
1017
|
+
"name",
|
|
1018
|
+
"content"
|
|
1019
|
+
],
|
|
1020
|
+
"additionalProperties": false
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
},
|
|
1024
|
+
"required": [
|
|
1025
|
+
"steps"
|
|
1026
|
+
],
|
|
1027
|
+
"additionalProperties": false
|
|
1028
|
+
}
|
|
1029
|
+
},
|
|
1030
|
+
{
|
|
1031
|
+
"name": "list_jobs",
|
|
1032
|
+
"title": "List managed jobs",
|
|
1033
|
+
"description": "List recent detached managed jobs and their lifecycle status without returning step output.",
|
|
1034
|
+
"availability": "write",
|
|
1035
|
+
"annotations": {
|
|
1036
|
+
"readOnlyHint": true,
|
|
1037
|
+
"destructiveHint": false,
|
|
1038
|
+
"idempotentHint": true,
|
|
1039
|
+
"openWorldHint": false
|
|
1040
|
+
},
|
|
1041
|
+
"inputSchema": {
|
|
1042
|
+
"type": "object",
|
|
1043
|
+
"properties": {
|
|
1044
|
+
"limit": {
|
|
1045
|
+
"type": "integer",
|
|
1046
|
+
"minimum": 1,
|
|
1047
|
+
"maximum": 50,
|
|
1048
|
+
"default": 20
|
|
1049
|
+
}
|
|
1050
|
+
},
|
|
1051
|
+
"additionalProperties": false
|
|
1052
|
+
}
|
|
1053
|
+
},
|
|
1054
|
+
{
|
|
1055
|
+
"name": "read_job",
|
|
1056
|
+
"title": "Read managed job",
|
|
1057
|
+
"description": "Return one managed job status plus bounded, resource-redacted step results. Registered resource paths and contents are never returned.",
|
|
1058
|
+
"availability": "direct-exec",
|
|
1059
|
+
"annotations": {
|
|
1060
|
+
"readOnlyHint": true,
|
|
1061
|
+
"destructiveHint": false,
|
|
1062
|
+
"idempotentHint": true,
|
|
1063
|
+
"openWorldHint": false
|
|
1064
|
+
},
|
|
1065
|
+
"inputSchema": {
|
|
1066
|
+
"type": "object",
|
|
1067
|
+
"properties": {
|
|
1068
|
+
"job_id": {
|
|
1069
|
+
"type": "string",
|
|
1070
|
+
"pattern": "^job_[A-Za-z0-9_-]{24,}$"
|
|
1071
|
+
}
|
|
1072
|
+
},
|
|
1073
|
+
"required": [
|
|
1074
|
+
"job_id"
|
|
1075
|
+
],
|
|
1076
|
+
"additionalProperties": false
|
|
1077
|
+
}
|
|
1078
|
+
},
|
|
1079
|
+
{
|
|
1080
|
+
"name": "cancel_job",
|
|
1081
|
+
"title": "Cancel managed job",
|
|
1082
|
+
"description": "Request cancellation of a detached managed job. The runner terminates the active process tree and still attempts declared finally steps and local resource cleanup.",
|
|
1083
|
+
"availability": "write",
|
|
1084
|
+
"annotations": {
|
|
1085
|
+
"readOnlyHint": false,
|
|
1086
|
+
"destructiveHint": true,
|
|
1087
|
+
"idempotentHint": true,
|
|
1088
|
+
"openWorldHint": true
|
|
1089
|
+
},
|
|
1090
|
+
"inputSchema": {
|
|
1091
|
+
"type": "object",
|
|
1092
|
+
"properties": {
|
|
1093
|
+
"job_id": {
|
|
1094
|
+
"type": "string",
|
|
1095
|
+
"pattern": "^job_[A-Za-z0-9_-]{24,}$"
|
|
1096
|
+
}
|
|
1097
|
+
},
|
|
1098
|
+
"required": [
|
|
1099
|
+
"job_id"
|
|
1100
|
+
],
|
|
1101
|
+
"additionalProperties": false
|
|
1102
|
+
}
|
|
1103
|
+
},
|
|
606
1104
|
{
|
|
607
1105
|
"name": "exec_command",
|
|
608
1106
|
"title": "Execute shell command",
|
package/src/worker/index.ts
CHANGED
|
@@ -3,7 +3,7 @@ import toolCatalog from "../shared/tool-catalog.json";
|
|
|
3
3
|
import serverMetadata from "../shared/server-metadata.json";
|
|
4
4
|
|
|
5
5
|
const SERVER_NAME = String(serverMetadata.name);
|
|
6
|
-
const SERVER_VERSION = "0.
|
|
6
|
+
const SERVER_VERSION = "0.6.0";
|
|
7
7
|
const MCP_PROTOCOL_VERSION = String(serverMetadata.protocolVersion);
|
|
8
8
|
const MCP_SUPPORTED_PROTOCOL_VERSIONS = serverMetadata.supportedProtocolVersions.map((value) => String(value));
|
|
9
9
|
const JSONRPC_VERSION = "2.0";
|