machine-bridge-mcp 0.5.0 → 0.6.2
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 +68 -0
- package/README.md +113 -8
- package/SECURITY.md +42 -6
- package/docs/ARCHITECTURE.md +50 -9
- package/docs/CLIENTS.md +24 -3
- package/docs/LOGGING.md +12 -19
- package/docs/MANAGED_JOBS.md +282 -0
- package/docs/OPERATIONS.md +79 -10
- package/docs/TESTING.md +11 -2
- package/package.json +13 -6
- package/src/local/atomic-fs.mjs +37 -0
- package/src/local/cli.mjs +254 -7
- package/src/local/daemon.mjs +168 -6
- package/src/local/full-access-test.mjs +206 -0
- package/src/local/job-runner.mjs +471 -0
- package/src/local/managed-jobs.mjs +855 -0
- package/src/local/resource-operations.mjs +66 -0
- package/src/local/ssh-key.mjs +125 -0
- package/src/local/state.mjs +56 -12
- package/src/local/stdio.mjs +4 -6
- package/src/local/tools.mjs +37 -3
- package/src/shared/server-metadata.json +10 -1
- package/src/shared/tool-catalog.json +531 -0
- package/src/worker/index.ts +7 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,73 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.6.2 - 2026-07-10
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- Retry atomic JSON file replacement with bounded backoff for transient Windows sharing failures (`EPERM`, `EACCES`, `EBUSY`, and `ENOTEMPTY`). State, managed-job manager, and detached runner commits now use one shared implementation.
|
|
8
|
+
- Prevent an intermittent Windows `runner_failed` result caused by a transient status-file replacement failure after the same commit had passed the protected pull-request checks.
|
|
9
|
+
- Preserve immediate failure for non-transient filesystem errors and keep temporary-file cleanup behavior unchanged.
|
|
10
|
+
- Restore corrupt-state backup creation through the shared replacement primitive, add collision-resistant backup names, and verify that recovery preserves the original corrupt bytes.
|
|
11
|
+
|
|
12
|
+
### Tests and diagnostics
|
|
13
|
+
|
|
14
|
+
- Add deterministic injected transient/non-transient atomic replacement tests.
|
|
15
|
+
- Run the full real-machine sandbox three consecutive times on Windows, exercising repeated detached runner, status, result, and finally-step commits.
|
|
16
|
+
- Include managed-job error and cleanup classifications in `full-test` output when a lifecycle check fails.
|
|
17
|
+
|
|
18
|
+
## 0.6.1 - 2026-07-10
|
|
19
|
+
|
|
20
|
+
### Full-profile contract and operator workflows
|
|
21
|
+
|
|
22
|
+
- Make named profiles canonical capability contracts. A stored `full` label is repaired to writes, shell execution, unrestricted paths, full parent environment, absolute path output, and the complete tool catalog; deliberate individual overrides remain `custom`. Advance the policy revision to 3 and expose the contract in `server_info` and `doctor`.
|
|
23
|
+
- Add `machine-mcp full-test`, a real local-machine acceptance suite using disposable directories. It verifies outside-workspace I/O, direct and shell execution, parent-environment inheritance, SSH key generation, sandbox `authorized_keys`, SSH client parsing, Google OS Login command availability, a non-mutating sudo probe, and detached finally cleanup without changing cloud or remote state.
|
|
24
|
+
- Add `machine-mcp resource generate-ssh-key NAME [PATH]` and the canonical-full-only MCP tool `generate_ssh_key_resource`. Both generate or reuse an Ed25519 pair locally, register the private file as a resource, and return only paths, modes, key type, and public fingerprint.
|
|
25
|
+
|
|
26
|
+
### Logging
|
|
27
|
+
|
|
28
|
+
- Remove every ordinary per-tool event from default `info`/`warn` logs. Starts, successes, failures, cancellations, durations, slow calls, tool names, coarse outcome classes, and call correlation are now debug-only in both remote daemon and stdio transports.
|
|
29
|
+
- Keep default logs focused on deployment, connection, protocol, relay, service, and infrastructure health. Tool arguments, command text, inputs, outputs, and results remain omitted at all levels.
|
|
30
|
+
|
|
31
|
+
### Security, correctness, and portability
|
|
32
|
+
|
|
33
|
+
- Verify that an existing SSH public key matches its private key and that the private key is usable non-interactively before reuse. Reject incomplete pairs and symbolic links, enforce owner-only private modes where supported, and never return private bytes.
|
|
34
|
+
- Fix the previously untested RSA key-generation argument order and add real RSA coverage.
|
|
35
|
+
- Centralize CLI and MCP key generation/registration in one locked state transaction. Roll back a newly created pair if state persistence fails, handle canonical path aliases, and reapply permissions after cross-filesystem installation.
|
|
36
|
+
- Validate the resource state layout before deriving its root and restrict the MCP key generator to the complete canonical `full` profile.
|
|
37
|
+
- Avoid reading user SSH configuration during `full-test`, canonicalize temporary path aliases, and report sudo/cloud prerequisites separately from core Machine Bridge capability.
|
|
38
|
+
|
|
39
|
+
### Tests and documentation
|
|
40
|
+
|
|
41
|
+
- Add real Ed25519/RSA generation, reuse, mismatch, incomplete-pair, symlink, mode, private-content, CLI, stdio, Worker-policy, and real-machine full-profile regression coverage.
|
|
42
|
+
- Update logging, architecture, operations, client, managed-job, security, and testing documentation to match the canonical-full and debug-only per-tool event contracts.
|
|
43
|
+
|
|
44
|
+
## 0.6.0 - 2026-07-10
|
|
45
|
+
|
|
46
|
+
### Added
|
|
47
|
+
|
|
48
|
+
- Add `diagnose_runtime`, a fixed-input layered diagnostic that distinguishes requests reaching the daemon from Machine Bridge policy, local filesystem, process-spawn, shell, managed-job storage, and registered-resource failures. `machine-mcp doctor` runs the same local probes.
|
|
49
|
+
- Add operator-registered local file resources. Credentials and other local-only files can be referenced by alias and injected into managed steps through a private copied path, stdin, or an environment variable without sending file contents or source paths through MCP.
|
|
50
|
+
- Add durable managed jobs with ordered argv steps, bounded output, job-scoped temporary files, detached execution, cancellation, idempotent `finally_steps`, dead-runner detection, bounded recovery, and local CLI inspection/cancellation.
|
|
51
|
+
- Add two-phase handoff: `stage_job` persists a validated non-running plan for operator review, and `machine-mcp job approve JOB_ID` provides explicit local authorization when a host blocks execution-class tools.
|
|
52
|
+
- Add a local JSON fallback with `machine-mcp job submit plan.json` for situations where the MCP host cannot deliver an execution request.
|
|
53
|
+
|
|
54
|
+
### Security and privacy
|
|
55
|
+
|
|
56
|
+
- Keep resource values out of MCP plans and results. Referenced files are reopened, bounded, hashed at acceptance, verified before use, copied with owner-only permissions, and removed after cleanup.
|
|
57
|
+
- Redact exact resource paths, exact UTF-8 values, and bounded exact base64/hex forms from retained output. Add `capture_output: "discard"` for credential-consuming commands where output must not be retained.
|
|
58
|
+
- Delete active job plans, runner PID files, temporary helper contents, argv, stdin, environment overrides, resource source paths, and hashes after terminal commit. Retain only bounded status/redacted results for up to seven days and 50 jobs.
|
|
59
|
+
- Enforce canonical managed-job cwd containment in restricted profiles, bounded per-job resources/temporary files/output, no-follow plan/resource reads, owner-only job state, bounded runner diagnostics, recovery mutual exclusion, and a three-attempt automatic recovery limit.
|
|
60
|
+
- Refuse uninstall while detached jobs remain active. Later profile changes affect new submissions; accepted running jobs require explicit cancellation.
|
|
61
|
+
- Clarify that managed jobs are durability and local-authorization mechanisms, not a bypass for MCP-host, operating-system, or endpoint-security policy.
|
|
62
|
+
|
|
63
|
+
### Operations and tests
|
|
64
|
+
|
|
65
|
+
- Add local resource commands: `resource add`, `list`, `check`, and `remove`.
|
|
66
|
+
- Add local managed-job commands: `job submit`, `inspect`, `approve`, `list`, `read`, and `cancel`. Approval is interactive by default; `--yes` is required for non-interactive JSON approval.
|
|
67
|
+
- Add state schema version 5 for resource registry metadata while redacting resource source paths from normal status output.
|
|
68
|
+
- Add regression coverage for staging/approval/cancel-before-start, stdio disconnect survival, resource replacement races and output redaction, job-scoped helper cleanup, failure/timeout/cancellation finally paths, concurrent recovery, corrupt plans, output budgets, local CLI fallback, uninstall refusal, and cross-profile tool exposure.
|
|
69
|
+
- Add a dedicated managed-jobs/resource operations and threat-model guide.
|
|
70
|
+
|
|
3
71
|
## 0.5.0 - 2026-07-10
|
|
4
72
|
|
|
5
73
|
### Changed
|
package/README.md
CHANGED
|
@@ -21,18 +21,18 @@ Local clients such as Claude Desktop, Cursor, and Codex CLI
|
|
|
21
21
|
local runtime
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
-
The remote Worker authenticates and relays calls. It cannot directly read local files or start local processes. File, Git, image, patch, and
|
|
24
|
+
The remote Worker authenticates and relays calls. It cannot directly read local files or start local processes. File, Git, image, patch, process, diagnostic, and managed-job operations execute in the local runtime.
|
|
25
25
|
|
|
26
26
|
## Default behavior and policy profiles
|
|
27
27
|
|
|
28
28
|
A newly selected workspace starts with the maximum-permission `full` profile for low-friction operation:
|
|
29
29
|
|
|
30
|
-
- all read, write, edit, patch, image, Git, direct-process, process-session, and shell tools are available;
|
|
30
|
+
- all read, write, edit, patch, image, Git, diagnostic, direct-process, process-session, managed-job, and shell tools are available;
|
|
31
31
|
- direct filesystem tools may use paths outside the selected workspace;
|
|
32
32
|
- tool results may return absolute paths;
|
|
33
33
|
- child processes inherit the complete parent environment.
|
|
34
34
|
|
|
35
|
-
Policy state records whether it came from the default, an explicit named profile, or custom overrides.
|
|
35
|
+
Policy state records whether it came from the default, an explicit named profile, or custom overrides. Named profiles are canonical contracts: a stored `full` profile is repaired on load to enable writes, shell execution, unrestricted paths, full parent environment, absolute path output, and the complete tool catalog. Any explicit per-capability narrowing is stored as `custom`. Policy revision 3 refreshes default/migrated state and preserves explicit restrictive/custom profiles.
|
|
36
36
|
|
|
37
37
|
| Profile | File edits | Direct argv processes | Shell commands | Filesystem scope | Process environment |
|
|
38
38
|
|---|---:|---:|---:|---|---|
|
|
@@ -134,6 +134,96 @@ Important distinctions:
|
|
|
134
134
|
- The server has no filename blacklist. Under `full`, direct read tools may read any UTF-8 regular file that the local OS user can access, including files outside the workspace and names such as `.env`, `passwords.txt`, or private-key files.
|
|
135
135
|
- Maximum local policy does not override operating-system permissions, macOS TCC/SIP, Windows ACLs, container boundaries, or independent safety rules imposed by the MCP host/platform. A host-generated “sensitive file” denial is outside this server's enforcement layer.
|
|
136
136
|
|
|
137
|
+
## Diagnose host, bridge, and local execution failures
|
|
138
|
+
|
|
139
|
+
A displayed `full` policy proves only that Machine Bridge has enabled its own capabilities. Execution can still be denied by the MCP host/connector, macOS TCC/SIP, Unix permissions, Windows ACLs, shell policy, or endpoint-security software.
|
|
140
|
+
|
|
141
|
+
Use:
|
|
142
|
+
|
|
143
|
+
```text
|
|
144
|
+
diagnose_runtime
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
or locally:
|
|
148
|
+
|
|
149
|
+
```sh
|
|
150
|
+
machine-mcp doctor
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
A successful `diagnose_runtime` response proves that request reached the local daemon. It then reports fixed probes for Machine Bridge policy, private filesystem access, direct process spawning, shell execution, managed-job storage, and registered resources. If the host blocks the tool call before any structured response, the server cannot diagnose that request because it never received it.
|
|
154
|
+
|
|
155
|
+
Run a real local acceptance test for the canonical `full` contract:
|
|
156
|
+
|
|
157
|
+
```sh
|
|
158
|
+
machine-mcp full-test --workspace /path/to/project
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
The test uses a temporary sandbox to perform an outside-workspace read/write, direct process, shell command, parent-environment inheritance, Ed25519 generation, temporary `authorized_keys` write, SSH client check, Google Cloud OS Login command availability check, non-mutating `sudo -n true` probe, and detached managed-job/finally lifecycle. It does not add a cloud key, contact a remote maintenance host, modify a user account, or retain the generated key.
|
|
162
|
+
|
|
163
|
+
## Managed jobs and local resources
|
|
164
|
+
|
|
165
|
+
Long, remote, multi-step, or cleanup-sensitive work should not depend on a sequence of later MCP calls remaining available. `start_job` durably accepts ordered argv steps plus `finally_steps`, then launches an independent local runner. It continues after MCP disconnects or later host-side tool refusals.
|
|
166
|
+
|
|
167
|
+
When the host blocks execution-class tools but still permits state mutation, `stage_job` stores the same validated plan without starting any process. The operator can review it with `machine-mcp job inspect JOB_ID` and explicitly authorize execution with `machine-mcp job approve JOB_ID`. Cancelling a staged plan does not run main or finally steps.
|
|
168
|
+
|
|
169
|
+
Register credential/key files locally without sending their contents through MCP:
|
|
170
|
+
|
|
171
|
+
```sh
|
|
172
|
+
chmod 600 ~/.ssh/racknerd_ed25519
|
|
173
|
+
machine-mcp resource add racknerd-key ~/.ssh/racknerd_ed25519
|
|
174
|
+
machine-mcp resource list
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Generate an Ed25519 key and register its private file in one operation:
|
|
178
|
+
|
|
179
|
+
```sh
|
|
180
|
+
machine-mcp resource generate-ssh-key racknerd-key ~/.ssh/ai-racknerd-maint-ed25519
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
Under canonical `full`, an authorized MCP host can invoke `generate_ssh_key_resource` with the same semantics. The tool is idempotent, verifies that existing public/private files match, enforces local file modes where supported, and returns only paths, public fingerprint, key type, and registration status—not private key bytes.
|
|
184
|
+
|
|
185
|
+
A job refers to the alias rather than the value:
|
|
186
|
+
|
|
187
|
+
```json
|
|
188
|
+
{
|
|
189
|
+
"name": "remote maintenance",
|
|
190
|
+
"steps": [
|
|
191
|
+
{
|
|
192
|
+
"argv": [
|
|
193
|
+
"ssh",
|
|
194
|
+
"-i",
|
|
195
|
+
"{{resource:racknerd-key}}",
|
|
196
|
+
"root@example",
|
|
197
|
+
"sh",
|
|
198
|
+
"-s"
|
|
199
|
+
],
|
|
200
|
+
"stdin": "set -eu\n# remote repair commands\n"
|
|
201
|
+
}
|
|
202
|
+
],
|
|
203
|
+
"finally_steps": [
|
|
204
|
+
{
|
|
205
|
+
"argv": ["ssh", "-i", "{{resource:racknerd-key}}", "root@example", "rm", "-f", "/tmp/helper"],
|
|
206
|
+
"allow_failure": true
|
|
207
|
+
}
|
|
208
|
+
]
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
Prefer sending a remote script through stdin so no remote helper file is created. For local helpers, use job-scoped `temporary_files` and `{{temp:name}}`; the private job runtime is removed after cleanup.
|
|
213
|
+
|
|
214
|
+
Resources can be injected by private copied path (`{{resource:name}}`), `stdin_resource`, or `env_resources`. Use `capture_output: "discard"` for commands that may echo credentials. Exact resource values and common exact encodings are redacted from retained results, but transformed or partial-secret detection is not guaranteed.
|
|
215
|
+
|
|
216
|
+
If the MCP host later blocks all execution tools, use the local fallback:
|
|
217
|
+
|
|
218
|
+
```sh
|
|
219
|
+
machine-mcp job list
|
|
220
|
+
machine-mcp job read JOB_ID
|
|
221
|
+
machine-mcp job cancel JOB_ID
|
|
222
|
+
machine-mcp job submit plan.json
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
Finally steps and restart recovery are best effort and should be idempotent. See [docs/MANAGED_JOBS.md](docs/MANAGED_JOBS.md) for lifecycle, security limits, plan format, and diagnosis guidance.
|
|
226
|
+
|
|
137
227
|
## Tools
|
|
138
228
|
|
|
139
229
|
The exact `tools/list` response reflects the active local policy. Definitions come from one shared catalog used by both Worker and stdio transports.
|
|
@@ -164,6 +254,19 @@ The exact `tools/list` response reflects the active local policy. Definitions co
|
|
|
164
254
|
|
|
165
255
|
Repository-configured external diff, text conversion, and filesystem-monitor helpers are disabled for bridge Git inspection.
|
|
166
256
|
|
|
257
|
+
### Diagnostics and durable work
|
|
258
|
+
|
|
259
|
+
- `diagnose_runtime` — fixed layered probes; no user-controlled command input
|
|
260
|
+
- `list_local_resources` — aliases and validation status without paths or values
|
|
261
|
+
- `generate_ssh_key_resource` — canonical-full-only Ed25519 generation and private-file resource registration without returning private content
|
|
262
|
+
- `stage_job` — persist a validated plan for later local approval without executing it
|
|
263
|
+
- `start_job` — detached ordered argv steps, private temporary files, and finally steps
|
|
264
|
+
- `list_jobs`
|
|
265
|
+
- `read_job`
|
|
266
|
+
- `cancel_job`
|
|
267
|
+
|
|
268
|
+
Managed jobs are non-interactive and persist independently of the MCP connection. Process sessions remain interactive and memory-only.
|
|
269
|
+
|
|
167
270
|
### Processes
|
|
168
271
|
|
|
169
272
|
- `run_process` — one-shot argv execution without a shell
|
|
@@ -194,6 +297,8 @@ machine-mcp service status|install|start|stop|uninstall
|
|
|
194
297
|
machine-mcp status
|
|
195
298
|
machine-mcp doctor
|
|
196
299
|
machine-mcp rotate-secrets
|
|
300
|
+
machine-mcp resource add|list|check|remove
|
|
301
|
+
machine-mcp job submit|inspect|approve|list|read|cancel
|
|
197
302
|
machine-mcp --print-mcp-credentials
|
|
198
303
|
machine-mcp uninstall [--keep-worker] [--yes]
|
|
199
304
|
```
|
|
@@ -208,7 +313,7 @@ Remote mode supports:
|
|
|
208
313
|
- Linux `systemd --user`, with best-effort lingering;
|
|
209
314
|
- Windows Scheduled Task at logon.
|
|
210
315
|
|
|
211
|
-
The service definition contains neither credentials nor a duplicate policy. It loads the selected policy from owner-only local state and uses the documented `full` default if policy state is absent. Background services run at log level `warn`:
|
|
316
|
+
The service definition contains neither credentials nor a duplicate policy. It loads the selected policy from owner-only local state and uses the documented `full` default if policy state is absent. Background services run at log level `warn`: relay, protocol, and service problems are retained, while all per-tool success/failure/cancellation/timing events remain debug-only. Logs are owner-only where supported and bounded by tail trimming.
|
|
212
317
|
|
|
213
318
|
## Secret rotation
|
|
214
319
|
|
|
@@ -227,9 +332,9 @@ Default state roots:
|
|
|
227
332
|
- Linux with `XDG_STATE_HOME`: `$XDG_STATE_HOME/machine-bridge-mcp`
|
|
228
333
|
- Windows: `%APPDATA%\machine-bridge-mcp`
|
|
229
334
|
|
|
230
|
-
State/config writes use owner-only temporary files, flushes, and atomic rename. Malformed state is retained as a bounded corrupt backup before reconstruction. Uninstall validates markers, canonical paths, active locks, workspace/source exclusions, and known contents before recursive deletion.
|
|
335
|
+
State/config writes use owner-only temporary files, flushes, and atomic rename. Malformed state is retained as a bounded corrupt backup before reconstruction. Resource source paths are redacted from `status` output. Active managed-job plans are owner-only and are deleted after a terminal result; bounded redacted results are retained temporarily. Uninstall validates markers, canonical paths, active locks, workspace/source exclusions, and known contents before recursive deletion.
|
|
231
336
|
|
|
232
|
-
Default foreground logs show startup/deployment transitions, relay connectivity, warnings/errors
|
|
337
|
+
Default foreground logs show startup/deployment transitions, relay connectivity, and infrastructure warnings/errors. Every per-tool event—including success, failure, cancellation, and slow-call timing—appears only at `--log-level debug` or `--verbose`. Background services use `warn`, so ordinary tool outcomes never fill daemon logs. Log messages and structured fields are bounded, secret-like keys and known token formats are redacted, and tool arguments/results are not written. See [docs/LOGGING.md](docs/LOGGING.md) and [docs/OPERATIONS.md](docs/OPERATIONS.md).
|
|
233
338
|
|
|
234
339
|
## Development and verification
|
|
235
340
|
|
|
@@ -242,9 +347,9 @@ npm audit --omit=dev --audit-level=high
|
|
|
242
347
|
npm pack --dry-run
|
|
243
348
|
```
|
|
244
349
|
|
|
245
|
-
`npm run check` covers generated Worker types, TypeScript, JavaScript syntax, the shared tool catalog, local path/write/process/state/log/service invariants, a live stdio MCP flow, and a live local OAuth/Worker/WebSocket/MCP flow. GitHub Actions runs the suite on Linux, macOS, and Windows with supported Node versions.
|
|
350
|
+
`npm run check` covers generated Worker types, TypeScript, JavaScript syntax, the shared tool catalog, local path/write/process/state/log/service invariants, Ed25519/RSA generation and key-pair validation, real-machine `full` sandbox acceptance, managed-job detachment/resource redaction/finally/cancellation/recovery, a live stdio MCP flow, and a live local OAuth/Worker/WebSocket/MCP flow. GitHub Actions runs the suite on Linux, macOS, and Windows with supported Node versions.
|
|
246
351
|
|
|
247
|
-
See [docs/TESTING.md](docs/TESTING.md), [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md), and [SECURITY.md](SECURITY.md).
|
|
352
|
+
See [docs/MANAGED_JOBS.md](docs/MANAGED_JOBS.md), [docs/TESTING.md](docs/TESTING.md), [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md), and [SECURITY.md](SECURITY.md).
|
|
248
353
|
|
|
249
354
|
## Uninstall
|
|
250
355
|
|
package/SECURITY.md
CHANGED
|
@@ -32,9 +32,9 @@ The Worker is a remote authentication and relay boundary. The local runtime is t
|
|
|
32
32
|
|
|
33
33
|
## Profiles are capability sets, not sandboxes
|
|
34
34
|
|
|
35
|
-
The default for newly selected workspaces is `full`, which prioritizes ease of use over least privilege.
|
|
35
|
+
The default for newly selected workspaces is `full`, which prioritizes ease of use over least privilege. Named profiles are canonical capability contracts. A stored `full` label is repaired on load to the complete maximum-permission field set and tool catalog; a deliberate per-capability override is represented as `custom`, not as a partially restricted `full`.
|
|
36
36
|
|
|
37
|
-
- `full` exposes all tools, unrestricted direct filesystem paths, absolute path output, and the complete parent process environment.
|
|
37
|
+
- `full` exposes all tools, unrestricted direct filesystem paths, absolute path output, shell execution, and the complete parent process environment.
|
|
38
38
|
- `agent` exposes file mutation, direct argv execution, and process sessions while keeping direct filesystem tools workspace-confined and the process environment isolated.
|
|
39
39
|
- `edit` exposes read and mutation tools without process execution.
|
|
40
40
|
- `review` exposes read-only workspace/Git/image tools.
|
|
@@ -53,10 +53,16 @@ The default `full` profile returns absolute paths. Narrower profiles return work
|
|
|
53
53
|
|
|
54
54
|
The server does not maintain a sensitive-filename blacklist. Under `full`, direct read tools may access any UTF-8 regular file available to the local OS user, including files outside the selected workspace and names such as `.env`, password stores, private keys, credentials, database dumps, and production configuration. Narrower profiles confine direct filesystem tools but do not classify names inside that boundary.
|
|
55
55
|
|
|
56
|
-
Maximum local policy does not bypass Unix permissions, Windows ACLs, macOS TCC/SIP, container/VM boundaries, or security decisions made by the MCP host/platform. A host-side
|
|
56
|
+
Maximum local policy does not bypass Unix permissions, Windows ACLs, macOS TCC/SIP, container/VM boundaries, endpoint-security controls, shell restrictions, or security decisions made by the MCP host/platform. A host-side refusal is independent of Machine Bridge and cannot be disabled by local policy configuration. `diagnose_runtime` and `machine-mcp doctor` use fixed probes to distinguish requests that reached the daemon from local filesystem/process/shell failures; they cannot inspect a call blocked before delivery.
|
|
57
57
|
|
|
58
58
|
Processes are not confined by the filesystem-tool resolver. They can access paths, networks, processes, credential stores, and devices available to the local user.
|
|
59
59
|
|
|
60
|
+
## Full-profile verification
|
|
61
|
+
|
|
62
|
+
`machine-mcp full-test` performs real local operations inside disposable temporary directories: unrestricted file access, direct and shell processes, inherited environment, SSH key generation/matching, a sandbox `authorized_keys` write, SSH client parsing, Google Cloud OS Login command discovery, a non-mutating sudo availability probe, and detached job cleanup. It makes no cloud or remote-server change and cannot prove that an MCP host will deliver a future request. The command verifies the Machine Bridge and local-machine portion of the authority chain only.
|
|
63
|
+
|
|
64
|
+
A canonical `full` profile guarantees that Machine Bridge itself will not reject a catalogued tool because of its local profile, path scope, environment mode, or shell mode. It cannot override the MCP host/connector, operating-system access controls, endpoint-security policy, remote authentication, cloud IAM, `sudo`, or service-side authorization.
|
|
65
|
+
|
|
60
66
|
## Mutation integrity
|
|
61
67
|
|
|
62
68
|
Writes are bounded, reject symbolic-link/non-regular destinations, use same-directory staging, and commit atomically per file. Create-only commit fails if a concurrent destination appears. Expected hashes and exact edits reduce accidental stale overwrites.
|
|
@@ -73,6 +79,32 @@ First-run or explicit reconnect output can intentionally display the MCP connect
|
|
|
73
79
|
|
|
74
80
|
The default `full` profile passes the complete parent environment. Narrower profiles replace HOME, temp, and common cache paths and do not pass arbitrary parent variables. The isolated mode reduces accidental environment-secret leakage; it does not prevent code from explicitly accessing known resources.
|
|
75
81
|
|
|
82
|
+
## Local resources and managed jobs
|
|
83
|
+
|
|
84
|
+
Local resources are registered through the operator-controlled CLI or, only under canonical `full`, through `generate_ssh_key_resource`. State stores canonical paths and metadata, not file contents. The SSH generator creates or reuses an unencrypted automation key, verifies that the public and private files match, rejects symbolic links/incomplete pairs, applies `0600`/`0644` modes where supported, and returns no private bytes. Unix-like registration rejects group/other-readable private resource files unless explicitly overridden. Portable mode checks do not fully describe Windows ACLs or extended Unix ACLs; the operator remains responsible for platform permissions.
|
|
85
|
+
|
|
86
|
+
At job acceptance, referenced resources are bounded and hashed. The detached runner reopens and verifies each hash before copying it to a private `0600` runtime file. Resource copies are removed after the finally phase. A changed or unavailable resource fails closed.
|
|
87
|
+
|
|
88
|
+
Resource injection modes have different exposure:
|
|
89
|
+
|
|
90
|
+
- private file-path substitution is generally preferred;
|
|
91
|
+
- stdin avoids process arguments and environment variables;
|
|
92
|
+
- environment injection can be visible to same-user process inspection and inherited child processes.
|
|
93
|
+
|
|
94
|
+
Managed jobs accept arbitrary argv and therefore retain local-user authority. They are a durability mechanism, not a sandbox or an authorization bypass. A running job snapshots execution authority and environment mode at acceptance. Later profile changes affect new jobs but do not silently revoke an accepted running job; explicitly cancel active jobs when revoking authority. The initial job submission remains subject to MCP-host approval and platform safety policy; each child remains subject to local OS and endpoint-security policy.
|
|
95
|
+
|
|
96
|
+
`stage_job` is non-executing and requires write capability. Local `machine-mcp job approve` is a separate operator authorization and may launch a staged plan even when the MCP profile itself has no execution capability. Operators must review the stored plan before approval. Cancelling before approval runs neither main nor finally steps.
|
|
97
|
+
|
|
98
|
+
Active plans are owner-only and may temporarily contain argv, non-secret stdin, temporary helper content, environment overrides, and resource source paths for crash recovery. A terminal runner deletes the full plan. Status and bounded results remain for up to seven days/50 jobs. If a runner crashes before terminal commit, the plan remains until recovery or retention cleanup.
|
|
99
|
+
|
|
100
|
+
Exact resource paths, exact resource bytes interpreted as text, and bounded exact base64/hex forms are redacted from retained output. This cannot detect partial, transformed, encrypted, compressed, or application-specific encodings. It also cannot redact unrelated secrets inherited through the full parent environment. Use `capture_output: "discard"` whenever a process may echo credentials, and never place a secret directly in argv, ordinary env, stdin, temporary-file content, or a JSON plan.
|
|
101
|
+
|
|
102
|
+
`finally_steps` run after ordinary success, failure, timeout, and cancellation. Cancellation uses an owner-only marker rather than signaling the runner process itself, so the coordinator remains alive to execute cleanup consistently across platforms. A dead runner is detected on the next daemon or local job-CLI start; stale private resource copies are removed and cleanup is retried. This is best effort. Power loss, disk failure, permanent loss of credentials/network access, SIGKILL without later recovery, or security software denying the cleanup executable can prevent cleanup. Finally steps must be idempotent and safe to repeat. Automatic recovery is capped at three attempts so persistent endpoint-security or executable-policy denial cannot create an endless launch loop. Uninstall refuses to remove local state while managed jobs are active; operators must inspect or cancel them first.
|
|
103
|
+
|
|
104
|
+
Job-scoped `temporary_files` should be used instead of loose helper scripts. They are materialized only below the private job runtime. Remote scripts should preferably be sent through a process stdin instead of written to the remote filesystem.
|
|
105
|
+
|
|
106
|
+
Runner diagnostic logs are owner-only and do not receive child stdout/stderr. Step output is stored only in bounded job results according to the selected capture mode.
|
|
107
|
+
|
|
76
108
|
## OAuth and public endpoints
|
|
77
109
|
|
|
78
110
|
Remote mode uses authorization code flow with PKCE S256, exact redirect/resource/client binding, expiring authorization codes and access tokens, hashed token storage, token-version revocation, and bounded dynamic client registration.
|
|
@@ -97,15 +129,17 @@ Process-session IDs are random and valid only inside one runtime. Output buffers
|
|
|
97
129
|
|
|
98
130
|
Sessions use pipes, not a PTY. Do not assume terminal-oriented programs will behave safely or correctly. Process output may contain secrets; it is returned to the authorized client but is not intentionally written to operational logs.
|
|
99
131
|
|
|
132
|
+
Process sessions are interactive and intentionally die with runtime disconnect/replacement. Managed jobs are separate detached processes with owner-only persistent state and best-effort finally/recovery semantics.
|
|
133
|
+
|
|
100
134
|
## Images and rich content
|
|
101
135
|
|
|
102
136
|
`view_image` accepts only signature-validated PNG, JPEG, GIF, and WebP under the size cap. SVG is intentionally excluded because it is active document content rather than a simple raster image. Image bytes pass through the Worker in remote mode and are visible to the authorized MCP client.
|
|
103
137
|
|
|
104
138
|
## Logs and privacy
|
|
105
139
|
|
|
106
|
-
Default operational logs record startup/
|
|
140
|
+
Default operational logs record startup/deployment, relay, protocol, service, and infrastructure transitions. Every ordinary per-tool event—start, success, failure, cancellation, and duration—is debug-only. Tool arguments, command text, stdin, file/patch contents, and outputs are omitted. Messages and fields are bounded; unexpected daemon and Worker infrastructure exceptions are reduced to error classes. Git author email is omitted from `git_log` unless explicitly requested.
|
|
107
141
|
|
|
108
|
-
No logging policy can prevent data from being returned to a client that explicitly invokes an enabled tool. The Worker necessarily relays remote tool arguments and results; this is not end-to-end encryption against the user's Cloudflare execution environment.
|
|
142
|
+
No logging policy can prevent data from being returned to a client that explicitly invokes an enabled tool. The Worker necessarily relays remote tool arguments and results; this is not end-to-end encryption against the user's Cloudflare execution environment. Managed-job result files may contain remote command output and are owner-only local data, not operational logs.
|
|
109
143
|
|
|
110
144
|
## Hardening checklist
|
|
111
145
|
|
|
@@ -130,9 +164,11 @@ Also:
|
|
|
130
164
|
- inspect client names and OAuth redirect URIs;
|
|
131
165
|
- rotate secrets after suspected disclosure;
|
|
132
166
|
- inspect `status`, `doctor`, and service status;
|
|
167
|
+
- register credential files as local resources instead of reading them into a model conversation;
|
|
168
|
+
- use `capture_output: "discard"` for credential-consuming steps and idempotent finally steps for cleanup;
|
|
133
169
|
- remove the Worker and state when remote access is no longer needed;
|
|
134
170
|
- use external OS isolation for untrusted code.
|
|
135
171
|
|
|
136
172
|
## Out of scope
|
|
137
173
|
|
|
138
|
-
The project cannot prevent an authorized client from requesting data accessible to enabled tools, make arbitrary local executables safe, identify all sensitive content, or neutralize model prompt injection. Operator approval and narrow capability selection remain primary controls.
|
|
174
|
+
The project cannot prevent an authorized client from requesting data accessible to enabled tools, make arbitrary local executables safe, identify all sensitive content, guarantee cleanup across every power/storage/security failure, override MCP-host or endpoint-security policy, or neutralize model prompt injection. Operator approval, local resource hygiene, idempotent cleanup, and narrow capability selection remain primary controls.
|
package/docs/ARCHITECTURE.md
CHANGED
|
@@ -20,7 +20,7 @@ No transport is treated as a sandbox. Both transports invoke the same local runt
|
|
|
20
20
|
|
|
21
21
|
The CLI canonicalizes workspaces, resolves policy profiles, maintains per-workspace state and credentials, serializes startup/deploy/rotation with locks, deploys the Worker, installs optional platform-native autostart, and starts either remote daemon or stdio mode.
|
|
22
22
|
|
|
23
|
-
A canonical workspace receives an independent profile, Worker name, secret set, daemon/startup locks, and state file. State schema version
|
|
23
|
+
A canonical workspace receives an independent profile, Worker name, secret set, resource registry, managed-job directory, daemon/startup locks, and state file. State schema version 5 records policy origin/revision and local resource metadata in addition to the capability fields.
|
|
24
24
|
|
|
25
25
|
### Local runtime
|
|
26
26
|
|
|
@@ -30,12 +30,42 @@ A canonical workspace receives an independent profile, Worker name, secret set,
|
|
|
30
30
|
- file, text search, image, patch, and Git operations;
|
|
31
31
|
- direct and shell process execution;
|
|
32
32
|
- process-session buffers and stdin lifecycle;
|
|
33
|
+
- layered fixed runtime diagnostics;
|
|
34
|
+
- local resource aliases and detached managed-job coordination;
|
|
33
35
|
- mutation serialization;
|
|
34
36
|
- child-process tracking and cancellation;
|
|
35
37
|
- output, traversal, concurrency, and time limits.
|
|
36
38
|
|
|
37
39
|
Remote mode attaches WebSocket connection/reconnect behavior. Stdio mode invokes the same runtime directly.
|
|
38
40
|
|
|
41
|
+
### Managed job runner
|
|
42
|
+
|
|
43
|
+
`ManagedJobManager` persists bounded per-workspace job envelopes below the owner-only profile directory. `start_job` validates the complete plan, snapshots referenced resource metadata/hashes, writes an owner-only plan/status, and launches `job-runner.mjs` as a detached process with runner-level logs redirected to owner-only files. `stage_job` performs the same acceptance validation but writes a non-running `staged` envelope; only local `job approve` transitions it to queued and launches the runner.
|
|
44
|
+
|
|
45
|
+
The runner:
|
|
46
|
+
|
|
47
|
+
- materializes registered resources as private `0600` copies after hash verification;
|
|
48
|
+
- materializes bounded job-scoped temporary files;
|
|
49
|
+
- substitutes resource/temp/runtime/workspace placeholders;
|
|
50
|
+
- executes ordered argv steps with bounded output and timeout/process-tree termination;
|
|
51
|
+
- polls an owner-only cancellation marker, terminates the current child tree, and keeps the runner alive for finally steps;
|
|
52
|
+
- attempts ordered finally steps after success, failure, timeout, or cancellation;
|
|
53
|
+
- removes private runtime copies;
|
|
54
|
+
- writes bounded redacted results and terminal status;
|
|
55
|
+
- deletes the full execution plan and runner PID file after terminal commit.
|
|
56
|
+
|
|
57
|
+
Running managed jobs do not belong to an MCP socket or daemon call ID and snapshot the accepted environment mode/resources. Later profile changes govern new direct submissions; accepted running jobs require explicit cancellation. Staged plans launch no process and require explicit local approval. Daemon disconnect/replacement does not terminate them. Dead runner PIDs are detected on the next daemon or local job-CLI start; stale private runtime data is removed and the finally phase is retried in recovery mode. Recovery deliberately reruns all finally steps, so cleanup must be idempotent.
|
|
58
|
+
|
|
59
|
+
Local resource registrations remain in owner-only state and are reloaded for every new job. MCP-visible resource inventory includes aliases and validation status but never source paths, hashes, or contents.
|
|
60
|
+
|
|
61
|
+
### Canonical policy contracts
|
|
62
|
+
|
|
63
|
+
Named profiles are normalized to their complete capability sets. In particular, `full` always means write enabled, shell execution, unrestricted paths, complete parent environment, absolute-path display, and every catalog tool. CLI flags that alter an individual capability deliberately change the profile identity to `custom`. Policy revision 3 repairs stale or manually edited named-profile fields rather than allowing a misleading partially restricted `full` label.
|
|
64
|
+
|
|
65
|
+
The full-only `generate_ssh_key_resource` operation is implemented locally. The Worker only filters and relays its shared catalog definition. Local generation uses `ssh-keygen`, verifies public/private correspondence, registers the private file through the same owner-only state transaction as the CLI, and rolls back a newly created pair if state persistence fails.
|
|
66
|
+
|
|
67
|
+
`full-test` constructs a local runtime with canonical full policy and executes real operations in disposable directories. It is an acceptance test for the local implementation, not a probe that changes remote systems or bypasses host policy.
|
|
68
|
+
|
|
39
69
|
### Stdio MCP server
|
|
40
70
|
|
|
41
71
|
The stdio server implements newline-delimited JSON-RPC over stdin/stdout. It negotiates supported MCP versions, advertises policy-filtered tools, returns text plus structured content, supports native image content, maps cancellation notifications to runtime call IDs, and sends level-filtered logs only to stderr.
|
|
@@ -66,8 +96,12 @@ flowchart LR
|
|
|
66
96
|
L[Local MCP client] -->|stdio JSON-RPC| R
|
|
67
97
|
R -->|canonical workspace tools| F[Selected workspace]
|
|
68
98
|
R -->|optional direct/shell processes| P[Local user / OS / network]
|
|
69
|
-
|
|
99
|
+
R -->|durable accepted plan| J[Detached managed-job runner]
|
|
100
|
+
J -->|private copies| LR[Local resource files]
|
|
101
|
+
J -->|argv/stdin/env| P
|
|
102
|
+
CLI[CLI + owner-only state] --> W
|
|
70
103
|
CLI --> R
|
|
104
|
+
CLI --> J
|
|
71
105
|
CLI --> S[Autostart provider]
|
|
72
106
|
```
|
|
73
107
|
|
|
@@ -86,7 +120,8 @@ Remote OAuth determines which client may call tools. Local stdio access relies o
|
|
|
86
120
|
9. `tools/call` receives a random relay call ID and is bound to the current socket and authenticated client request key.
|
|
87
121
|
10. The runtime validates policy and arguments, executes the tool, and returns a bounded result.
|
|
88
122
|
11. The Durable Object accepts a result only from the socket that received that call.
|
|
89
|
-
12. A matching cancellation notification removes the pending call, tells the daemon to cancel, and terminates any child processes bound to it.
|
|
123
|
+
12. A matching cancellation notification removes the pending call, tells the daemon to cancel, and terminates any ordinary child processes bound to it.
|
|
124
|
+
13. `start_job` is different: after durable acceptance, the detached runner is no longer bound to the relay call or socket. Later cancellation uses `cancel_job` or the local CLI.
|
|
90
125
|
|
|
91
126
|
Duplicate in-flight JSON-RPC IDs for the same access token are rejected so cancellation cannot ambiguously target multiple calls.
|
|
92
127
|
|
|
@@ -98,7 +133,7 @@ Duplicate in-flight JSON-RPC IDs for the same access token are rejected so cance
|
|
|
98
133
|
4. Each call receives an internal random call ID used only for cancellation and process tracking.
|
|
99
134
|
5. Results are emitted as JSON-RPC on stdout; logs remain on stderr.
|
|
100
135
|
6. Duplicate in-flight request IDs are rejected.
|
|
101
|
-
7. Closing stdin cancels pending calls, terminates active processes, and removes the
|
|
136
|
+
7. Closing stdin cancels pending calls, terminates ordinary active processes/process sessions, and removes the transport runtime directory. Previously accepted managed jobs continue in their persistent per-workspace job directories.
|
|
102
137
|
|
|
103
138
|
## Filesystem resolution and privacy
|
|
104
139
|
|
|
@@ -136,7 +171,9 @@ The default `full` profile passes the complete parent environment. Isolated envi
|
|
|
136
171
|
|
|
137
172
|
One-shot calls have bounded output and timeouts. Process sessions retain bounded byte buffers with monotonic offsets, accept bounded stdin, support short output/exit waits, and are capped per runtime. Valid UTF-8 is returned as text; byte slices that are not valid UTF-8 also include lossless base64 data. Session IDs are random. Sessions are memory-only and are killed on runtime stop, remote disconnect, or daemon replacement.
|
|
138
173
|
|
|
139
|
-
Child processes run in a separate process group where supported. Timeout, cancellation, disconnect, and replacement send termination to
|
|
174
|
+
Child processes run in a separate process group where supported. Timeout, cancellation, disconnect, and replacement send termination to ordinary process trees, with forced escalation for timeout/disconnect paths.
|
|
175
|
+
|
|
176
|
+
Managed jobs use the same argv/environment primitives but a different lifecycle. Each job is capped at 16 main and 16 finally steps, 50 retained jobs, 64 registered resources, 8 MiB of referenced resource bytes, 512 KiB of temporary-file content, and bounded per-step output. They are non-interactive. Resource paths/stdin/environment are injected only inside the runner. Exact resource output redaction is defense in depth; discard capture is the strong option when a command may echo credentials.
|
|
140
177
|
|
|
141
178
|
## Daemon reconnect and replacement
|
|
142
179
|
|
|
@@ -146,7 +183,9 @@ Pending calls retain their originating socket reference. A stale socket cannot c
|
|
|
146
183
|
|
|
147
184
|
## Persistence
|
|
148
185
|
|
|
149
|
-
Local state and global config are owner-only, versioned, size-bounded, and written through temporary files, flushes, and atomic rename. Reads reject symbolic links and use no-follow descriptors where supported. Malformed or oversized state becomes a bounded-count `.corrupt-*` backup. Custom roots are adopted only when empty or recognizable as legacy Machine Bridge state.
|
|
186
|
+
Local state and global config are owner-only, versioned, size-bounded, and written through temporary files, flushes, and atomic rename. State, managed-job manager, and detached runner commits share a bounded retrying atomic-replace primitive for transient Windows `EPERM`, `EACCES`, `EBUSY`, and `ENOTEMPTY` sharing failures. Reads reject symbolic links and use no-follow descriptors where supported. Malformed or oversized state becomes a bounded-count `.corrupt-*` backup. Resource paths are omitted from redacted status output. Custom roots are adopted only when empty or recognizable as legacy Machine Bridge state.
|
|
187
|
+
|
|
188
|
+
Active managed jobs persist an owner-only plan, status, runner PID, and bounded runner diagnostics. Terminal jobs delete the full plan and retain only bounded status/redacted results for up to seven days. This balances crash cleanup with minimization of scripts, stdin, argv, environment overrides, and resource source paths.
|
|
150
189
|
|
|
151
190
|
Removal validates the state marker, canonical target, known contents, active locks, filesystem root/home/current/package/workspace/source exclusions, and Worker deletion outcome before recursive deletion.
|
|
152
191
|
|
|
@@ -154,9 +193,9 @@ OAuth metadata is pruned on access. Expired codes/tokens, old throttling records
|
|
|
154
193
|
|
|
155
194
|
## Observability
|
|
156
195
|
|
|
157
|
-
Public health exposes only server identity and version. Authenticated `server_info` exposes bounded runtime status
|
|
196
|
+
Public health exposes only server identity and version. Authenticated `server_info` exposes bounded runtime status, policy origin/revision, managed-job counts, and resource alias names without paths or values. `diagnose_runtime` runs fixed local probes and explicitly reports that its own request reached the daemon.
|
|
158
197
|
|
|
159
|
-
Foreground logging defaults to `info`; autostart uses `warn`.
|
|
198
|
+
Foreground logging defaults to `info`; autostart uses `warn`. All per-tool starts, successes, failures, cancellations, durations, and shortened random correlation IDs are debug-only. Normal logs retain deployment, connection, protocol, service, and infrastructure events rather than duplicating MCP tool outcomes. Unexpected local and Worker infrastructure errors are reduced to classes. Messages, strings, arrays, object depth/key counts, and serialized fields are bounded.
|
|
160
199
|
|
|
161
200
|
Cloudflare sampling is size control rather than an audit log. The project intentionally does not claim complete forensic logging. See [LOGGING.md](LOGGING.md).
|
|
162
201
|
|
|
@@ -165,7 +204,9 @@ Cloudflare sampling is size control rather than an audit log. The project intent
|
|
|
165
204
|
- operating-system sandboxing of arbitrary executables;
|
|
166
205
|
- preventing an authorized client from requesting data available to enabled tools;
|
|
167
206
|
- automatically deciding which local files are sensitive or overriding MCP-host/platform safety policy;
|
|
168
|
-
- surviving daemon restart with process sessions;
|
|
207
|
+
- surviving daemon restart with process sessions (managed jobs are the separate durable mechanism);
|
|
208
|
+
- guaranteed finally cleanup across permanent power, disk, credential, network, or endpoint-security failure;
|
|
209
|
+
- bypassing MCP-host, connector, operating-system, or endpoint-security policy;
|
|
169
210
|
- PTY/terminal emulation;
|
|
170
211
|
- model-level prompt-injection prevention;
|
|
171
212
|
- multi-user tenancy in one Worker deployment.
|
package/docs/CLIENTS.md
CHANGED
|
@@ -35,7 +35,8 @@ The stdio mode exists for narrower cases:
|
|
|
35
35
|
2. **Transport parity.** The local client can use essentially the same Machine Bridge runtime that remote ChatGPT access uses, without maintaining a second implementation.
|
|
36
36
|
3. **No remote relay for same-machine use.** The host launches the server directly, so no Cloudflare Worker, public URL, OAuth flow, or network round trip is needed.
|
|
37
37
|
4. **Capabilities missing from a particular host.** Exact edit semantics, transactional multi-file patches, retained process sessions, image results, or the project's policy profiles may be useful even when the host has basic shell tools.
|
|
38
|
-
5. **
|
|
38
|
+
5. **Durable managed jobs.** The same detached job/resource/finally semantics are available to local and remote hosts, while local CLI remains an operator fallback.
|
|
39
|
+
6. **Testing and interoperability.** stdio is a standard MCP transport and provides a direct way to validate the runtime independently of the Worker.
|
|
39
40
|
|
|
40
41
|
It is therefore an optional compatibility and reuse surface, not a replacement for the native agent tooling in Claude Desktop, Cursor, or Codex.
|
|
41
42
|
|
|
@@ -117,15 +118,35 @@ Enter the printed `/mcp` URL in the remote MCP connector. During OAuth authoriza
|
|
|
117
118
|
|
|
118
119
|
## Profile guidance
|
|
119
120
|
|
|
120
|
-
- `full` is the default and prioritizes immediate usability. It
|
|
121
|
+
- `full` is the default and prioritizes immediate usability. It is a canonical contract exposing every catalog tool, shell execution, unrestricted direct filesystem paths, absolute path output, and the full parent environment. Any individual narrowing is represented as `custom`.
|
|
121
122
|
- `agent` retains file mutation and direct process execution but removes shell parsing, confines direct filesystem tools to the workspace, and isolates the process environment.
|
|
122
123
|
- `edit` permits deterministic file mutation without process execution.
|
|
123
124
|
- `review` is read-only and workspace-confined.
|
|
124
125
|
|
|
125
126
|
A client configuration is an authorization decision. Anyone who controls an authorized host can invoke every tool exposed by the selected profile.
|
|
126
127
|
|
|
128
|
+
Before connecting a host, verify the local implementation directly:
|
|
129
|
+
|
|
130
|
+
```sh
|
|
131
|
+
machine-mcp full-test --workspace /path/to/project
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
A passing result proves that Machine Bridge and the local OS allowed its temporary file/process/shell/key/job probes at that time. It does not prove that a hosted MCP connector will deliver a later request or that a cloud/remote account will authorize it.
|
|
135
|
+
|
|
136
|
+
For SSH automation, prefer `generate_ssh_key_resource` under canonical full, or `machine-mcp resource generate-ssh-key` from the terminal. The private key remains a local resource; only paths and the public fingerprint are returned. Installation of the public key into Google OS Login or a remote `authorized_keys` file remains an explicit external action.
|
|
137
|
+
|
|
127
138
|
## Host-side safety rules
|
|
128
139
|
|
|
129
140
|
The local `full` profile controls Machine Bridge's own tool catalog, path resolver, path display, process environment, and shell availability. It does not control the MCP host's model policy, approval UI, connector gateway, or platform execution filters.
|
|
130
141
|
|
|
131
|
-
Machine Bridge itself does not block files because their names look sensitive. If `server_info` reports `full` and a direct
|
|
142
|
+
Machine Bridge itself does not block files because their names look sensitive. If `server_info` reports `full` and a direct call is still rejected before a structured tool result, the host/connector may have blocked delivery. If `diagnose_runtime` responds but its fixed process or shell probe fails, the likely source is local OS policy, endpoint-security software, permissions, or shell configuration. Changing `--profile`, `--unrestricted-paths`, or `--absolute-paths` cannot override either layer.
|
|
143
|
+
|
|
144
|
+
Do not attempt to evade a host refusal by renaming, encoding, or switching to another arbitrary execution tool. Instead:
|
|
145
|
+
|
|
146
|
+
1. register credentials locally as resource aliases so their values never enter MCP arguments;
|
|
147
|
+
2. submit a complete `start_job` plan before the workflow depends on later cleanup calls, or use `stage_job` plus local `job approve` when execution-class tools are unavailable;
|
|
148
|
+
3. use job-scoped temporary files or remote stdin scripts;
|
|
149
|
+
4. put idempotent cleanup in `finally_steps`;
|
|
150
|
+
5. inspect/cancel through `machine-mcp job ...` if the host later denies tools.
|
|
151
|
+
|
|
152
|
+
The initial `start_job` request is still subject to host approval. If it is blocked, the operator can review and submit the same JSON plan locally with `machine-mcp job submit plan.json`. See [MANAGED_JOBS.md](MANAGED_JOBS.md).
|
package/docs/LOGGING.md
CHANGED
|
@@ -6,8 +6,8 @@ Operational logs should answer four questions without becoming a transcript of u
|
|
|
6
6
|
|
|
7
7
|
1. Did deployment and relay connection succeed?
|
|
8
8
|
2. Is the daemon reconnecting, superseded, or unhealthy?
|
|
9
|
-
3.
|
|
10
|
-
4.
|
|
9
|
+
3. Is an infrastructure, protocol, deployment, or relay failure occurring?
|
|
10
|
+
4. When debug logging is explicitly enabled, which bounded per-tool event should be correlated?
|
|
11
11
|
|
|
12
12
|
Logs are not a command history, content audit trail, or substitute for MCP client approvals.
|
|
13
13
|
|
|
@@ -26,24 +26,15 @@ The default foreground level is `info`. Platform autostart services use `warn`.
|
|
|
26
26
|
| Level | Intended events |
|
|
27
27
|
|---|---|
|
|
28
28
|
| `error` | Broken request handlers, relay transport errors, unrecoverable local failures |
|
|
29
|
-
| `warn` |
|
|
30
|
-
| `info` | Deployment/startup transitions
|
|
31
|
-
| `debug` |
|
|
29
|
+
| `warn` | Relay disconnections/send failures, malformed or oversized messages, superseded daemons, service/autostart problems |
|
|
30
|
+
| `info` | Deployment/startup transitions and successful relay connection |
|
|
31
|
+
| `debug` | Every per-tool start/success/failure/cancellation/timing event, shortened correlation IDs, reconnect timing |
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
All per-tool outcomes are deliberately absent from `info`, `warn`, and `error`. The MCP response already reports success or failure to the caller; duplicating ordinary failures in daemon logs creates noise without adding operational information. A normal sequence of hundreds of successful or failed tool invocations should not fill the user's terminal or service logs.
|
|
34
34
|
|
|
35
35
|
## Event fields
|
|
36
36
|
|
|
37
|
-
Default
|
|
38
|
-
|
|
39
|
-
- component;
|
|
40
|
-
- tool name;
|
|
41
|
-
- duration in milliseconds;
|
|
42
|
-
- coarse error class;
|
|
43
|
-
- relay close code;
|
|
44
|
-
- bounded reconnect delay.
|
|
45
|
-
|
|
46
|
-
Shortened random call identifiers are debug-only. They are useful only for correlating adjacent local events and are not stable audit identifiers.
|
|
37
|
+
Default operational events may include component, relay close code, bounded reconnect delay, provider name, or a coarse infrastructure error class. Per-tool fields—tool name, duration, outcome class, and shortened call identifier—are debug-only. Call identifiers are useful only for correlating adjacent local events and are not stable audit identifiers.
|
|
47
38
|
|
|
48
39
|
The implementation intentionally omits:
|
|
49
40
|
|
|
@@ -54,7 +45,7 @@ The implementation intentionally omits:
|
|
|
54
45
|
- OAuth request bodies;
|
|
55
46
|
- connection passwords, daemon secrets, authorization codes, and access tokens.
|
|
56
47
|
|
|
57
|
-
Unexpected daemon and Worker failures are reduced to coarse error classes in normal logs. Client-facing tool errors may contain more detail according to the active path-display policy, but those details are not copied into normal operational logs.
|
|
48
|
+
Unexpected daemon, service, and Worker infrastructure failures are reduced to coarse error classes in normal logs. Client-facing tool errors may contain more detail according to the active path-display policy, but ordinary tool failures and those details are not copied into normal operational logs.
|
|
58
49
|
|
|
59
50
|
## Bounding and redaction
|
|
60
51
|
|
|
@@ -71,10 +62,12 @@ logs/daemon.out.log
|
|
|
71
62
|
logs/daemon.err.log
|
|
72
63
|
```
|
|
73
64
|
|
|
74
|
-
They are owner-only where the platform supports Unix-style permissions. Existing files are tail-trimmed on UTF-8/line boundaries before daemon startup. Because background services use `warn
|
|
65
|
+
They are owner-only where the platform supports Unix-style permissions. Existing files are tail-trimmed on UTF-8/line boundaries before daemon startup. Because background services use `warn` and per-tool events are debug-only, neither successful nor failed ordinary tool traffic should cause sustained log growth.
|
|
66
|
+
|
|
67
|
+
Each managed job also has owner-only `runner.out.log` and `runner.err.log` files for runner startup/crash diagnostics. Child-step stdout and stderr are captured into bounded job results according to `capture_output`; they are not copied into runner or daemon operational logs. Runner logs are retained with the bounded job directory and removed by job retention cleanup.
|
|
75
68
|
|
|
76
69
|
## MCP host boundary
|
|
77
70
|
|
|
78
|
-
Machine Bridge does not classify filenames as sensitive and does not block `.env`, password, key, or credential-looking names. The active local policy and
|
|
71
|
+
Machine Bridge does not classify filenames as sensitive and does not block `.env`, password, key, or credential-looking names. The active local policy, local OS permissions, and endpoint-security controls determine what the server itself can read or execute.
|
|
79
72
|
|
|
80
73
|
An MCP host, model provider, desktop application, or platform execution layer may independently deny a request involving credentials or sensitive files. Such a denial occurs before or outside Machine Bridge's file resolver and cannot be disabled by selecting the local `full` profile. Use `server_info`, `machine-mcp status`, and `machine-mcp doctor` to distinguish the active local policy from host-side enforcement.
|