machine-bridge-mcp 0.8.2 → 0.9.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.
@@ -14,6 +14,7 @@ import { classifyOperationalError } from "./log.mjs";
14
14
  import { ManagedJobManager } from "./managed-jobs.mjs";
15
15
  import { generateRegisteredSshKey } from "./resource-operations.mjs";
16
16
  import { expandHome } from "./state.mjs";
17
+ import { AgentContextManager } from "./agent-context.mjs";
17
18
 
18
19
  export const MAX_WRITE_BYTES = 5 * 1024 * 1024;
19
20
  const MAX_WS_MESSAGE_BYTES = 8 * 1024 * 1024;
@@ -27,6 +28,11 @@ const SLOW_TOOL_CALL_MS = 30_000;
27
28
  const RUNTIME_TOOL_HANDLERS = Object.freeze({
28
29
  server_info: (runtime) => runtime.runtimeInfo(),
29
30
  project_overview: (runtime, _args, context) => runtime.projectOverview(context),
31
+ agent_context: (runtime, args, context) => runtime.agentContextManager.agentContext(args, context),
32
+ list_local_skills: (runtime, args, context) => runtime.agentContextManager.listLocalSkills(args, context),
33
+ load_local_skill: (runtime, args, context) => runtime.agentContextManager.loadLocalSkill(args, context),
34
+ list_local_commands: (runtime, args, context) => runtime.agentContextManager.listLocalCommands(args, context),
35
+ run_local_command: (runtime, args, context) => runtime.runLocalCommand(args, context),
30
36
  list_roots: (runtime) => runtime.listRoots(),
31
37
  list_dir: (runtime, args, context) => runtime.listDir(args.path || ".", context),
32
38
  list_files: (runtime, args, context) => runtime.listFiles(args.path || ".", clampInt(args.max_files, 1000, 1, 10000), context),
@@ -101,6 +107,13 @@ export class LocalRuntime {
101
107
  displayPath: (value) => this.displayPath(value),
102
108
  throwIfCancelled: (context) => this.throwIfCancelled(context),
103
109
  });
110
+ this.agentContextManager = new AgentContextManager({
111
+ workspace: this.workspace,
112
+ policy: this.policy,
113
+ displayPath: (value) => this.displayPath(value),
114
+ resolveExistingPath: (value) => this.resolveExistingPath(value),
115
+ throwIfCancelled: (context) => this.throwIfCancelled(context),
116
+ });
104
117
  this.relay = createRelayConnection(this, {
105
118
  workerUrl: remoteWorkerUrl,
106
119
  secret: remoteSecret,
@@ -733,6 +746,25 @@ export class LocalRuntime {
733
746
  return this.runProcess(argv[0], argv.slice(1), clampInt(args.timeout_seconds, 120, 1, 600) * 1000, false, 512 * 1024, context, cwd);
734
747
  }
735
748
 
749
+ async runLocalCommand(args, context = {}) {
750
+ if (this.policy.execMode !== "direct" && this.policy.execMode !== "shell") throw new Error("run_local_command is disabled by daemon policy");
751
+ const command = await this.agentContextManager.resolveLocalCommand(args, context);
752
+ const argv = validateArgv(command.argv);
753
+ const cwd = await this.resolveExistingPath(command.cwd);
754
+ if (!(await stat(cwd)).isDirectory()) throw new Error("registered command cwd is not a directory");
755
+ const requestedTimeout = args.timeout_seconds === undefined
756
+ ? command.timeoutSeconds
757
+ : clampInt(args.timeout_seconds, command.timeoutSeconds, 1, 600);
758
+ const timeoutSeconds = Math.min(requestedTimeout, command.timeoutSeconds);
759
+ const result = await this.runProcess(argv[0], argv.slice(1), timeoutSeconds * 1000, false, 512 * 1024, context, cwd);
760
+ return {
761
+ name: command.name,
762
+ cwd: this.displayPath(cwd),
763
+ timeout_seconds: timeoutSeconds,
764
+ ...result,
765
+ };
766
+ }
767
+
736
768
  async execCommand(command, timeoutSeconds, context = {}) {
737
769
  if (this.policy.execMode !== "shell") throw new Error("exec_command requires shell execution mode");
738
770
  if (!command || typeof command !== "string") throw new Error("command is required");
@@ -8,6 +8,7 @@
8
8
  ],
9
9
  "instructions": [
10
10
  "You are connected to a local workspace through machine-bridge-mcp.",
11
+ "For substantive workspace tasks, call agent_context for the relevant target path before editing or executing. Apply returned instruction files in precedence order, load only relevant local skills, and prefer registered local commands for repeatable workflows.",
11
12
  "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
13
  "Filesystem scope and path display follow the active local policy; the default full profile is unrestricted.",
13
14
  "Filename sensitivity is not classified by this server; the MCP host, connector gateway, local OS, or endpoint-security software may enforce additional independent rules.",
@@ -31,6 +31,178 @@
31
31
  "additionalProperties": false
32
32
  }
33
33
  },
34
+ {
35
+ "name": "agent_context",
36
+ "title": "Load agent context",
37
+ "description": "Discover Codex-compatible global and root-to-target instruction precedence, progressively disclosed local skills, and registered commands for a target path.",
38
+ "availability": "always",
39
+ "annotations": {
40
+ "readOnlyHint": true,
41
+ "destructiveHint": false,
42
+ "idempotentHint": true,
43
+ "openWorldHint": false
44
+ },
45
+ "inputSchema": {
46
+ "type": "object",
47
+ "properties": {
48
+ "path": {
49
+ "type": "string",
50
+ "default": ".",
51
+ "maxLength": 32768
52
+ },
53
+ "include_instruction_content": {
54
+ "type": "boolean",
55
+ "default": true
56
+ },
57
+ "max_skills": {
58
+ "type": "integer",
59
+ "minimum": 1,
60
+ "maximum": 500,
61
+ "default": 100
62
+ }
63
+ },
64
+ "additionalProperties": false
65
+ }
66
+ },
67
+ {
68
+ "name": "list_local_skills",
69
+ "title": "List local skills",
70
+ "description": "Search bounded SKILL.md or skill.md bundles from Codex-compatible and explicitly configured skill roots without executing them.",
71
+ "availability": "always",
72
+ "annotations": {
73
+ "readOnlyHint": true,
74
+ "destructiveHint": false,
75
+ "idempotentHint": true,
76
+ "openWorldHint": false
77
+ },
78
+ "inputSchema": {
79
+ "type": "object",
80
+ "properties": {
81
+ "path": {
82
+ "type": "string",
83
+ "default": ".",
84
+ "maxLength": 32768
85
+ },
86
+ "query": {
87
+ "type": "string",
88
+ "default": "",
89
+ "maxLength": 1000
90
+ },
91
+ "max_results": {
92
+ "type": "integer",
93
+ "minimum": 1,
94
+ "maximum": 500,
95
+ "default": 100
96
+ }
97
+ },
98
+ "additionalProperties": false
99
+ }
100
+ },
101
+ {
102
+ "name": "load_local_skill",
103
+ "title": "Load local skill",
104
+ "description": "Load one discovered local skill entrypoint and a bounded relative file inventory. Loading returns instructions and never executes skill files implicitly.",
105
+ "availability": "always",
106
+ "annotations": {
107
+ "readOnlyHint": true,
108
+ "destructiveHint": false,
109
+ "idempotentHint": true,
110
+ "openWorldHint": false
111
+ },
112
+ "inputSchema": {
113
+ "type": "object",
114
+ "properties": {
115
+ "skill": {
116
+ "type": "string",
117
+ "minLength": 1,
118
+ "maxLength": 32768
119
+ },
120
+ "path": {
121
+ "type": "string",
122
+ "default": ".",
123
+ "maxLength": 32768
124
+ },
125
+ "max_files": {
126
+ "type": "integer",
127
+ "minimum": 1,
128
+ "maximum": 500,
129
+ "default": 200
130
+ }
131
+ },
132
+ "required": [
133
+ "skill"
134
+ ],
135
+ "additionalProperties": false
136
+ }
137
+ },
138
+ {
139
+ "name": "list_local_commands",
140
+ "title": "List registered local commands",
141
+ "description": "List commands registered by hierarchical .machine-bridge/agent.json manifests for the selected target path.",
142
+ "availability": "always",
143
+ "annotations": {
144
+ "readOnlyHint": true,
145
+ "destructiveHint": false,
146
+ "idempotentHint": true,
147
+ "openWorldHint": false
148
+ },
149
+ "inputSchema": {
150
+ "type": "object",
151
+ "properties": {
152
+ "path": {
153
+ "type": "string",
154
+ "default": ".",
155
+ "maxLength": 32768
156
+ }
157
+ },
158
+ "additionalProperties": false
159
+ }
160
+ },
161
+ {
162
+ "name": "run_local_command",
163
+ "title": "Run registered local command",
164
+ "description": "Execute a named command registered in .machine-bridge/agent.json as a direct argv process without shell parsing. Manifest timeout and argument policy remain authoritative.",
165
+ "availability": "direct-exec",
166
+ "annotations": {
167
+ "readOnlyHint": false,
168
+ "destructiveHint": true,
169
+ "idempotentHint": false,
170
+ "openWorldHint": true
171
+ },
172
+ "inputSchema": {
173
+ "type": "object",
174
+ "properties": {
175
+ "name": {
176
+ "type": "string",
177
+ "minLength": 1,
178
+ "maxLength": 64
179
+ },
180
+ "path": {
181
+ "type": "string",
182
+ "default": ".",
183
+ "maxLength": 32768
184
+ },
185
+ "args": {
186
+ "type": "array",
187
+ "items": {
188
+ "type": "string",
189
+ "maxLength": 65536
190
+ },
191
+ "maxItems": 64,
192
+ "default": []
193
+ },
194
+ "timeout_seconds": {
195
+ "type": "integer",
196
+ "minimum": 1,
197
+ "maximum": 600
198
+ }
199
+ },
200
+ "required": [
201
+ "name"
202
+ ],
203
+ "additionalProperties": false
204
+ }
205
+ },
34
206
  {
35
207
  "name": "list_roots",
36
208
  "title": "List workspace roots",
@@ -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.8.2";
6
+ const SERVER_VERSION = "0.9.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";