machine-bridge-mcp 0.4.0 → 0.5.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 +51 -0
- package/README.md +48 -39
- package/SECURITY.md +14 -10
- package/docs/ARCHITECTURE.md +14 -12
- package/docs/CLIENTS.md +82 -23
- package/docs/LOGGING.md +80 -0
- package/docs/OPERATIONS.md +25 -17
- package/docs/TESTING.md +7 -4
- package/package.json +4 -4
- package/src/local/cli.mjs +157 -79
- package/src/local/daemon.mjs +83 -48
- package/src/local/log.mjs +56 -15
- package/src/local/service.mjs +40 -21
- package/src/local/state.mjs +45 -20
- package/src/local/stdio.mjs +13 -37
- package/src/local/tools.mjs +28 -13
- package/src/shared/server-metadata.json +17 -0
- package/src/shared/tool-catalog.json +2 -2
- package/src/worker/index.ts +13 -11
- package/docs/examples/github-actions-ci.yml +0 -53
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,56 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.5.0 - 2026-07-10
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- Replace routine per-tool success chatter with explicit log levels. Foreground mode defaults to `info`, autostart uses `warn`, fast successful calls are debug-only, and successful calls over 30 seconds remain visible as slow-call events. `--verbose` maps to `debug`; `--quiet` maps to `error`; `--log-level` accepts `error`, `warn`, `info`, or `debug`.
|
|
8
|
+
- Record policy origin and revision in state and daemon metadata. The exact legacy implicit-default policy shape is migrated once to the current maximum-permission `full` profile, while explicit named profiles and identified custom policies are preserved.
|
|
9
|
+
- Redact JSON connection credentials and standalone secret-rotation output by default. Printing the client connection password now requires the explicit reconnect flag; the daemon secret is never printed in full.
|
|
10
|
+
- Centralize server name, MCP protocol versions, and instructions in shared metadata consumed by both Worker and local transports.
|
|
11
|
+
- Reject obsolete removed-local-API flags instead of silently accepting them.
|
|
12
|
+
|
|
13
|
+
### Security and privacy
|
|
14
|
+
|
|
15
|
+
- Upgrade and pin `ws` to 8.21.0 to address current memory-disclosure and denial-of-service advisories; pin the reviewed Wrangler runtime version.
|
|
16
|
+
- Bind text, image, and search reads to an opened file handle, enforce limits against that handle, and avoid `stat`/read growth races.
|
|
17
|
+
- Bound state, configuration, marker, lock, service-command, log-message, and structured-log sizes. Reject symbolic-link state files, use no-follow reads where supported, and make service-log tail trimming UTF-8 and line safe.
|
|
18
|
+
- Remove stale temporary Worker secret files when their owner process is gone, not only after an age threshold.
|
|
19
|
+
- Document and expose that Machine Bridge has no sensitive-filename blacklist. Local `full` permits any OS-readable UTF-8 regular file, but cannot override operating-system or independent MCP-host/platform policy.
|
|
20
|
+
|
|
21
|
+
### Tests and operations
|
|
22
|
+
|
|
23
|
+
- Add regression coverage for legacy policy migration, sensitive-looking files outside the workspace, inherited full-profile environment, default daemon/stdio log suppression, log bounding, state write bounds, service warning-level configuration, and shared metadata drift.
|
|
24
|
+
- Audit both complete and production-only dependency graphs in GitHub Actions.
|
|
25
|
+
- Document npm's scoped install-script approval for Wrangler native dependencies and add a dedicated logging/observability reference.
|
|
26
|
+
|
|
27
|
+
## 0.4.2 - 2026-07-10
|
|
28
|
+
|
|
29
|
+
### Fixed
|
|
30
|
+
|
|
31
|
+
- Canonicalize the configured workspace and requested targets through the same asynchronous `realpath` path on Windows, while retaining a native synchronous initial value. This prevents Windows short-path/long-path aliases for the same temporary directory from being misclassified as a workspace escape.
|
|
32
|
+
- Keep workspace confinement unchanged: only the representation comparison changed, and targets outside the canonical workspace remain rejected in restricted profiles.
|
|
33
|
+
|
|
34
|
+
### Verification
|
|
35
|
+
|
|
36
|
+
- Preserve the existing cross-platform path-boundary regression, which exposed the issue on the Windows GitHub Actions runner while Linux and macOS passed.
|
|
37
|
+
- Make the minimal-environment shell regression use a cross-platform Node command instead of POSIX parameter-expansion syntax under PowerShell.
|
|
38
|
+
- Convert test entry-point file URLs with `fileURLToPath()` so Windows does not interpret `/D:/...` URL paths as `C:\D:\...` filesystem paths.
|
|
39
|
+
- Launch Wrangler's JavaScript entry point through the active Node executable in integration tests instead of directly spawning the Windows `.cmd` shim.
|
|
40
|
+
|
|
41
|
+
## 0.4.1 - 2026-07-10
|
|
42
|
+
|
|
43
|
+
### Changed
|
|
44
|
+
|
|
45
|
+
- Make `full` the default policy for newly selected workspaces and generated client configurations, prioritizing immediate usability. The default now enables all tools, unrestricted direct filesystem paths, absolute path output, shell execution, process sessions, and the complete parent environment; existing saved workspace policies remain unchanged.
|
|
46
|
+
- Reframe stdio as an optional local transport rather than a model provider or a replacement for native Claude, Cursor, Codex, or ChatGPT Desktop tooling. Expand client documentation to distinguish the MCP host/model from the Machine Bridge tool server and explain when stdio is redundant or useful.
|
|
47
|
+
- Activate cross-platform GitHub Actions checks on Linux, macOS, and Windows, update official actions to the current major releases, disable checkout credential persistence, and retain production dependency/package auditing.
|
|
48
|
+
|
|
49
|
+
### Tests and documentation
|
|
50
|
+
|
|
51
|
+
- Add regression coverage for the maximum-permission default and for `client-config` emitting `full` when no profile is supplied.
|
|
52
|
+
- Update architecture, operations, security, and client guidance for profile-dependent path display, filesystem scope, and environment inheritance.
|
|
53
|
+
|
|
3
54
|
## 0.4.0 - 2026-07-10
|
|
4
55
|
|
|
5
56
|
### Architecture and compatibility
|
package/README.md
CHANGED
|
@@ -23,37 +23,37 @@ Local clients such as Claude Desktop, Cursor, and Codex CLI
|
|
|
23
23
|
|
|
24
24
|
The remote Worker authenticates and relays calls. It cannot directly read local files or start local processes. File, Git, image, patch, and process operations execute in the local runtime.
|
|
25
25
|
|
|
26
|
-
##
|
|
26
|
+
## Default behavior and policy profiles
|
|
27
27
|
|
|
28
|
-
A
|
|
28
|
+
A newly selected workspace starts with the maximum-permission `full` profile for low-friction operation:
|
|
29
29
|
|
|
30
|
-
- read-
|
|
31
|
-
-
|
|
32
|
-
-
|
|
33
|
-
-
|
|
34
|
-
- relative paths in tool results;
|
|
35
|
-
- no parent shell environment inherited by commands.
|
|
30
|
+
- all read, write, edit, patch, image, Git, direct-process, process-session, and shell tools are available;
|
|
31
|
+
- direct filesystem tools may use paths outside the selected workspace;
|
|
32
|
+
- tool results may return absolute paths;
|
|
33
|
+
- child processes inherit the complete parent environment.
|
|
36
34
|
|
|
37
|
-
|
|
35
|
+
Policy state records whether it came from the default, an explicit named profile, or custom overrides. Version 0.5 migrates the exact pre-0.4 implicit-default shape to `full` once; explicit restrictive profiles and identified custom policies remain unchanged.
|
|
38
36
|
|
|
39
|
-
| Profile | File edits | Direct argv processes | Shell commands |
|
|
40
|
-
|
|
41
|
-
| `
|
|
42
|
-
| `
|
|
43
|
-
| `
|
|
44
|
-
| `
|
|
37
|
+
| Profile | File edits | Direct argv processes | Shell commands | Filesystem scope | Process environment |
|
|
38
|
+
|---|---:|---:|---:|---|---|
|
|
39
|
+
| `full` | Yes | Yes | Yes | Unrestricted | Full parent environment |
|
|
40
|
+
| `agent` | Yes | Yes | No | Selected workspace | Isolated environment |
|
|
41
|
+
| `edit` | Yes | No | No | Selected workspace | Isolated environment |
|
|
42
|
+
| `review` | No | No | No | Selected workspace | Isolated environment |
|
|
45
43
|
|
|
46
|
-
`run_process` and process sessions avoid command-shell parsing, but they are **not an operating-system sandbox**.
|
|
44
|
+
This default prioritizes usability, not least privilege. `run_process` and process sessions avoid command-shell parsing, but they are **not an operating-system sandbox**. `exec_command` additionally permits shell syntax and expansion. Use `--profile review`, `edit`, or `agent`, or use a container, VM, or dedicated low-privilege OS account when the client, repository, or instructions are not fully trusted.
|
|
47
45
|
|
|
48
46
|
## Install
|
|
49
47
|
|
|
50
48
|
Node.js 22 or newer is required.
|
|
51
49
|
|
|
52
50
|
```sh
|
|
53
|
-
npm install -g machine-bridge-mcp@latest
|
|
51
|
+
npm install -g --allow-scripts=esbuild,workerd,sharp machine-bridge-mcp@latest
|
|
54
52
|
```
|
|
55
53
|
|
|
56
|
-
|
|
54
|
+
Recent npm releases may otherwise warn that Wrangler's native dependencies (`esbuild`, `workerd`, and `sharp`) have install scripts awaiting approval. The scoped command above approves only those packages for this installation; it does not change the user's global npm policy. A plain install can still work when compatible prebuilt artifacts are already available, but `machine-mcp doctor` is the authoritative runtime check.
|
|
55
|
+
|
|
56
|
+
From a source checkout, the checked-in exact-version `allowScripts` policy approves the reviewed native dependencies:
|
|
57
57
|
|
|
58
58
|
```sh
|
|
59
59
|
npm install
|
|
@@ -66,7 +66,7 @@ npm install
|
|
|
66
66
|
Start the bridge from the project directory or select a workspace explicitly:
|
|
67
67
|
|
|
68
68
|
```sh
|
|
69
|
-
machine-mcp --workspace /path/to/project
|
|
69
|
+
machine-mcp --workspace /path/to/project
|
|
70
70
|
```
|
|
71
71
|
|
|
72
72
|
On first remote start, the CLI:
|
|
@@ -88,44 +88,51 @@ MCP connection password: mcp_password_...
|
|
|
88
88
|
|
|
89
89
|
The remote authorization flow uses an authorization code, PKCE S256, exact redirect/resource binding, expiring access tokens stored as hashes, and a token-version value for bulk revocation.
|
|
90
90
|
|
|
91
|
-
##
|
|
91
|
+
## Optional local stdio MCP
|
|
92
|
+
|
|
93
|
+
stdio is a local transport, not a model provider. Claude Desktop, Cursor, Codex CLI, ChatGPT Desktop, or another MCP host supplies its own model/session and launches `machine-bridge-mcp` as a subprocess. The MCP server only exposes tools and returns their results; it does not borrow the model running in ChatGPT web.
|
|
94
|
+
|
|
95
|
+
Many coding clients already have strong native filesystem and terminal tools, so configuring this stdio server is optional. It is useful when you want the same Machine Bridge tool schemas, patch behavior, process sessions, policy profiles, and logs across several clients, or when you want local access without deploying Cloudflare. If the client's built-in tools already meet your needs, there is no reason to add this server.
|
|
92
96
|
|
|
93
97
|
Generate ready-to-paste configuration:
|
|
94
98
|
|
|
95
99
|
```sh
|
|
96
|
-
machine-mcp client-config --client all --workspace /path/to/project
|
|
100
|
+
machine-mcp client-config --client all --workspace /path/to/project
|
|
97
101
|
```
|
|
98
102
|
|
|
99
103
|
Or run stdio directly:
|
|
100
104
|
|
|
101
105
|
```sh
|
|
102
|
-
machine-mcp stdio --workspace /path/to/project
|
|
106
|
+
machine-mcp stdio --workspace /path/to/project
|
|
103
107
|
```
|
|
104
108
|
|
|
105
|
-
The stdio server writes only JSON-RPC messages to stdout
|
|
106
|
-
|
|
107
|
-
See [docs/CLIENTS.md](docs/CLIENTS.md) for client-specific configuration and remote/local trade-offs.
|
|
109
|
+
The stdio server writes only JSON-RPC messages to stdout and operational logs to stderr. See [docs/CLIENTS.md](docs/CLIENTS.md) for the host/model distinction and transport trade-offs.
|
|
108
110
|
|
|
109
111
|
## Policy controls
|
|
110
112
|
|
|
111
|
-
|
|
113
|
+
The default is `full`. Narrow or customize it with explicit flags:
|
|
112
114
|
|
|
113
115
|
```text
|
|
114
|
-
--profile
|
|
116
|
+
--profile full|agent|edit|review
|
|
115
117
|
--exec-mode off|direct|shell
|
|
116
118
|
--no-write
|
|
117
119
|
--no-exec
|
|
118
120
|
--full-env
|
|
119
121
|
--unrestricted-paths
|
|
120
122
|
--absolute-paths
|
|
123
|
+
--log-level error|warn|info|debug
|
|
124
|
+
--verbose
|
|
125
|
+
--quiet
|
|
121
126
|
```
|
|
122
127
|
|
|
123
128
|
Important distinctions:
|
|
124
129
|
|
|
125
|
-
-
|
|
126
|
-
- `--absolute-paths
|
|
127
|
-
- `--
|
|
128
|
-
-
|
|
130
|
+
- The default `full` profile already enables unrestricted paths, absolute path output, and the complete parent environment.
|
|
131
|
+
- `--unrestricted-paths=false`, `--absolute-paths=false`, and `--full-env=false` can narrow those individual settings.
|
|
132
|
+
- `--absolute-paths` changes returned path metadata; it does not independently grant additional access.
|
|
133
|
+
- In isolated-environment profiles, commands receive private HOME, temp, and cache directories plus a small set of platform variables.
|
|
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
|
+
- 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.
|
|
129
136
|
|
|
130
137
|
## Tools
|
|
131
138
|
|
|
@@ -170,11 +177,11 @@ Process sessions retain bounded stdout/stderr, support offsets and short waits,
|
|
|
170
177
|
|
|
171
178
|
## Path and write behavior
|
|
172
179
|
|
|
173
|
-
|
|
180
|
+
When workspace confinement is enabled (`agent`, `edit`, `review`, or an explicit override), existing paths are resolved with `realpath` and must remain inside the canonical workspace. New write paths validate the nearest existing ancestor, preventing missing-path writes through escaping symbolic-link directories. The default `full` profile permits direct filesystem paths outside the workspace.
|
|
174
181
|
|
|
175
182
|
Writes use same-directory temporary files and atomic commit. Create-only writes use an atomic hard-link commit so a concurrent file cannot be silently overwritten. Patch operations are prevalidated, serialized, staged, rechecked, committed with backups, and rolled back on failure.
|
|
176
183
|
|
|
177
|
-
|
|
184
|
+
The default `full` profile returns absolute paths. The `agent`, `edit`, and `review` profiles return workspace-relative paths to reduce unnecessary disclosure of usernames and local directory layouts.
|
|
178
185
|
|
|
179
186
|
## Commands
|
|
180
187
|
|
|
@@ -187,6 +194,7 @@ machine-mcp service status|install|start|stop|uninstall
|
|
|
187
194
|
machine-mcp status
|
|
188
195
|
machine-mcp doctor
|
|
189
196
|
machine-mcp rotate-secrets
|
|
197
|
+
machine-mcp --print-mcp-credentials
|
|
190
198
|
machine-mcp uninstall [--keep-worker] [--yes]
|
|
191
199
|
```
|
|
192
200
|
|
|
@@ -200,16 +208,16 @@ Remote mode supports:
|
|
|
200
208
|
- Linux `systemd --user`, with best-effort lingering;
|
|
201
209
|
- Windows Scheduled Task at logon.
|
|
202
210
|
|
|
203
|
-
The service definition contains neither credentials nor a duplicate policy. It loads the selected policy from owner-only local state and
|
|
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`: failures and connection problems are retained, while routine successful tool calls are omitted. Logs are owner-only where supported and bounded by tail trimming.
|
|
204
212
|
|
|
205
213
|
## Secret rotation
|
|
206
214
|
|
|
207
215
|
```sh
|
|
208
|
-
machine-mcp rotate-secrets
|
|
209
|
-
machine-mcp
|
|
216
|
+
machine-mcp rotate-secrets
|
|
217
|
+
machine-mcp --print-mcp-credentials
|
|
210
218
|
```
|
|
211
219
|
|
|
212
|
-
Rotation stops the installed service, refuses to proceed while another foreground daemon owns the workspace lock, rotates the MCP password, daemon secret, and OAuth token version, and requires redeployment. Previously issued access tokens then fail validation.
|
|
220
|
+
Rotation stops the installed service, refuses to proceed while another foreground daemon owns the workspace lock, rotates the MCP password, daemon secret, and OAuth token version, and requires redeployment. Rotated values are redacted by default; only the client connection password can be printed through the explicit reconnect flag. Previously issued access tokens then fail validation.
|
|
213
221
|
|
|
214
222
|
## State and observability
|
|
215
223
|
|
|
@@ -221,7 +229,7 @@ Default state roots:
|
|
|
221
229
|
|
|
222
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.
|
|
223
231
|
|
|
224
|
-
|
|
232
|
+
Default foreground logs show startup/deployment transitions, relay connectivity, warnings/errors, and successful calls that exceed 30 seconds. Routine successful tool calls and correlation IDs appear only at `--log-level debug` or `--verbose`. Background services use `warn`. 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).
|
|
225
233
|
|
|
226
234
|
## Development and verification
|
|
227
235
|
|
|
@@ -229,11 +237,12 @@ Operational logs record bounded metadata such as component, tool name, shortened
|
|
|
229
237
|
npm ci
|
|
230
238
|
npm run check
|
|
231
239
|
npm run worker:dry-run
|
|
240
|
+
npm audit --audit-level=high
|
|
232
241
|
npm audit --omit=dev --audit-level=high
|
|
233
242
|
npm pack --dry-run
|
|
234
243
|
```
|
|
235
244
|
|
|
236
|
-
`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.
|
|
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.
|
|
237
246
|
|
|
238
247
|
See [docs/TESTING.md](docs/TESTING.md), [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md), and [SECURITY.md](SECURITY.md).
|
|
239
248
|
|
package/SECURITY.md
CHANGED
|
@@ -32,10 +32,12 @@ 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.
|
|
36
|
+
|
|
37
|
+
- `full` exposes all tools, unrestricted direct filesystem paths, absolute path output, and the complete parent process environment.
|
|
38
|
+
- `agent` exposes file mutation, direct argv execution, and process sessions while keeping direct filesystem tools workspace-confined and the process environment isolated.
|
|
39
|
+
- `edit` exposes read and mutation tools without process execution.
|
|
35
40
|
- `review` exposes read-only workspace/Git/image tools.
|
|
36
|
-
- `edit` additionally exposes write, exact edit, and patch tools.
|
|
37
|
-
- `agent` additionally exposes direct argv execution and process sessions.
|
|
38
|
-
- `full` additionally exposes arbitrary shell commands.
|
|
39
41
|
|
|
40
42
|
`run_process` avoids shell parsing, which removes one injection class, but an executable such as `node`, `python`, a package manager, compiler, test runner, or repository script can execute arbitrary code. Direct mode therefore has effectively broad local-user authority once an attacker controls argv or executed code.
|
|
41
43
|
|
|
@@ -45,11 +47,13 @@ For untrusted repositories or instructions, run the bridge inside a disposable V
|
|
|
45
47
|
|
|
46
48
|
## Filesystem exposure
|
|
47
49
|
|
|
48
|
-
Direct filesystem
|
|
50
|
+
Direct filesystem scope is profile-dependent. The default `full` profile is unrestricted. The `agent`, `edit`, and `review` profiles confine direct filesystem tools to the canonical selected workspace, including symbolic-link resolution.
|
|
51
|
+
|
|
52
|
+
The default `full` profile returns absolute paths. Narrower profiles return workspace-relative paths to reduce username and directory-layout disclosure. Path display and access scope remain separate controls.
|
|
49
53
|
|
|
50
|
-
|
|
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.
|
|
51
55
|
|
|
52
|
-
|
|
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 “sensitive file” refusal is independent of Machine Bridge and cannot be disabled by local policy configuration.
|
|
53
57
|
|
|
54
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.
|
|
55
59
|
|
|
@@ -65,9 +69,9 @@ These controls do not defend against a malicious process running under the same
|
|
|
65
69
|
|
|
66
70
|
Local state contains the MCP connection password and daemon secret. State, lock, temporary secret, runtime, and service-log files use owner-only permissions where supported. State writes are atomic. Logs recursively redact known credential fields and token formats and neutralize control characters.
|
|
67
71
|
|
|
68
|
-
First-run or explicit
|
|
72
|
+
First-run or explicit reconnect output can intentionally display the MCP connection password. JSON output and standalone secret rotation redact credentials by default; printing requires the explicit reconnect flag. The daemon secret is never printed in full. Avoid shared terminal logs, shell recordings, screenshots, CI output, or support tickets.
|
|
69
73
|
|
|
70
|
-
|
|
74
|
+
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.
|
|
71
75
|
|
|
72
76
|
## OAuth and public endpoints
|
|
73
77
|
|
|
@@ -99,7 +103,7 @@ Sessions use pipes, not a PTY. Do not assume terminal-oriented programs will beh
|
|
|
99
103
|
|
|
100
104
|
## Logs and privacy
|
|
101
105
|
|
|
102
|
-
|
|
106
|
+
Default operational logs record startup/connection transitions, failed calls, slow-call duration, and coarse error classes. Routine successful calls and shortened correlation IDs are debug-only. Tool arguments, command text, stdin, file/patch contents, and outputs are omitted. Messages and fields are bounded; unexpected daemon and Worker exceptions are reduced to error classes. Git author email is omitted from `git_log` unless explicitly requested.
|
|
103
107
|
|
|
104
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.
|
|
105
109
|
|
|
@@ -122,7 +126,7 @@ Also:
|
|
|
122
126
|
- patch the OS and use supported Node.js releases;
|
|
123
127
|
- enable MFA on Cloudflare, GitHub, and npm accounts;
|
|
124
128
|
- do not configure broad CORS origins;
|
|
125
|
-
-
|
|
129
|
+
- select `agent`, `edit`, or `review` instead of the default `full` when broad authority is unnecessary;
|
|
126
130
|
- inspect client names and OAuth redirect URIs;
|
|
127
131
|
- rotate secrets after suspected disclosure;
|
|
128
132
|
- inspect `status`, `doctor`, and service status;
|
package/docs/ARCHITECTURE.md
CHANGED
|
@@ -12,15 +12,15 @@ No transport is treated as a sandbox. Both transports invoke the same local runt
|
|
|
12
12
|
|
|
13
13
|
## Components
|
|
14
14
|
|
|
15
|
-
### Shared tool catalog
|
|
15
|
+
### Shared protocol metadata and tool catalog
|
|
16
16
|
|
|
17
|
-
`src/shared/tool-catalog.json` is the single source of truth for tool names, descriptions, input schemas, annotations, and policy availability. The Worker and
|
|
17
|
+
`src/shared/server-metadata.json` is the single source of truth for server identity, MCP protocol versions, and host instructions. `src/shared/tool-catalog.json` is the single source of truth for tool names, descriptions, input schemas, annotations, and policy availability. The Worker and local runtime import both directly. Catalog tests reject metadata drift, duplicate names, unknown availability classes, open schemas, missing annotations, profile drift, and second hand-maintained Worker definitions.
|
|
18
18
|
|
|
19
19
|
### CLI and state layer
|
|
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, daemon/startup locks, and state file. State schema version 4 records policy origin/revision in addition to the capability fields and retains removal of obsolete local API state.
|
|
24
24
|
|
|
25
25
|
### Local runtime
|
|
26
26
|
|
|
@@ -38,7 +38,7 @@ Remote mode attaches WebSocket connection/reconnect behavior. Stdio mode invokes
|
|
|
38
38
|
|
|
39
39
|
### Stdio MCP server
|
|
40
40
|
|
|
41
|
-
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 logs only to stderr.
|
|
41
|
+
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.
|
|
42
42
|
|
|
43
43
|
### Cloudflare Worker and Durable Object
|
|
44
44
|
|
|
@@ -55,7 +55,7 @@ The daemon attachment deliberately omits workspace path/name/hash and process ID
|
|
|
55
55
|
|
|
56
56
|
### Autostart layer
|
|
57
57
|
|
|
58
|
-
The service layer emits launchd, systemd-user, or Windows Scheduled Task definitions. Credentials are not embedded in service definitions; the daemon loads owner-only state. The exact policy is stored in owner-only state; platform service definitions contain only the workspace and
|
|
58
|
+
The service layer emits launchd, systemd-user, or Windows Scheduled Task definitions. Credentials are not embedded in service definitions; the daemon loads owner-only state. The exact policy is stored in owner-only state; platform service definitions contain only the workspace/state-root selectors and a `warn` log-level setting.
|
|
59
59
|
|
|
60
60
|
## Trust boundaries
|
|
61
61
|
|
|
@@ -102,9 +102,9 @@ Duplicate in-flight JSON-RPC IDs for the same access token are rejected so cance
|
|
|
102
102
|
|
|
103
103
|
## Filesystem resolution and privacy
|
|
104
104
|
|
|
105
|
-
The workspace is canonicalized
|
|
105
|
+
The workspace is canonicalized and compared with targets through consistent platform-native/async `realpath` representations. Existing targets must remain inside the workspace unless the active policy is unrestricted. New targets walk to the nearest existing ancestor, validate its canonical path, and reconstruct the destination below that canonical ancestor.
|
|
106
106
|
|
|
107
|
-
|
|
107
|
+
Path behavior is profile-dependent. The default `full` profile permits unrestricted direct filesystem paths and returns absolute paths. The `agent`, `edit`, and `review` profiles enforce canonical workspace containment and return workspace-relative paths. Error strings redact canonical and common platform-alias forms of workspace, runtime, and home paths whenever absolute path display is disabled.
|
|
108
108
|
|
|
109
109
|
Symbolic-link destinations and non-regular write targets are rejected. Recursive walkers do not follow symbolic-link directories.
|
|
110
110
|
|
|
@@ -132,7 +132,7 @@ This is a process-level transaction, not a filesystem-wide atomic transaction ac
|
|
|
132
132
|
|
|
133
133
|
`run_process` and process sessions use argv arrays and do not invoke a shell. `exec_command` invokes the platform shell and is available only in `shell` mode. Both inherit local-user OS authority.
|
|
134
134
|
|
|
135
|
-
|
|
135
|
+
The default `full` profile passes the complete parent environment. Isolated environment mode, used by the narrower named profiles unless overridden, creates private runtime HOME, temporary, and cache directories and passes only a small set of path/locale/platform variables. It reduces accidental credential inheritance but cannot prevent explicit access to known filesystem paths, credential stores, network services, or other user resources.
|
|
136
136
|
|
|
137
137
|
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
138
|
|
|
@@ -146,7 +146,7 @@ Pending calls retain their originating socket reference. A stale socket cannot c
|
|
|
146
146
|
|
|
147
147
|
## Persistence
|
|
148
148
|
|
|
149
|
-
Local state and global config are owner-only, versioned, and written through temporary files, flushes, and atomic rename. Malformed state becomes a bounded `.corrupt-*` backup. Custom roots are adopted only when empty or recognizable as legacy Machine Bridge state.
|
|
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.
|
|
150
150
|
|
|
151
151
|
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
152
|
|
|
@@ -154,15 +154,17 @@ OAuth metadata is pruned on access. Expired codes/tokens, old throttling records
|
|
|
154
154
|
|
|
155
155
|
## Observability
|
|
156
156
|
|
|
157
|
-
Public health exposes only server identity and version. Authenticated `server_info` exposes bounded runtime status
|
|
157
|
+
Public health exposes only server identity and version. Authenticated `server_info` exposes bounded runtime status and policy origin/revision.
|
|
158
158
|
|
|
159
|
-
|
|
159
|
+
Foreground logging defaults to `info`; autostart uses `warn`. Routine successful calls and shortened random correlation IDs are debug-only. `info` retains deployment/connection transitions and successful calls slower than 30 seconds. Failures log tool name, duration, and coarse error class without arguments or outputs. Unexpected local and Worker errors are reduced to classes in normal logs. Messages, strings, arrays, object depth/key counts, and serialized fields are bounded.
|
|
160
|
+
|
|
161
|
+
Cloudflare sampling is size control rather than an audit log. The project intentionally does not claim complete forensic logging. See [LOGGING.md](LOGGING.md).
|
|
160
162
|
|
|
161
163
|
## Explicit non-goals
|
|
162
164
|
|
|
163
165
|
- operating-system sandboxing of arbitrary executables;
|
|
164
166
|
- preventing an authorized client from requesting data available to enabled tools;
|
|
165
|
-
- automatically deciding which
|
|
167
|
+
- automatically deciding which local files are sensitive or overriding MCP-host/platform safety policy;
|
|
166
168
|
- surviving daemon restart with process sessions;
|
|
167
169
|
- PTY/terminal emulation;
|
|
168
170
|
- model-level prompt-injection prevention;
|
package/docs/CLIENTS.md
CHANGED
|
@@ -1,24 +1,73 @@
|
|
|
1
|
-
# Client configuration
|
|
1
|
+
# Client configuration and model ownership
|
|
2
|
+
|
|
3
|
+
## The central distinction
|
|
4
|
+
|
|
5
|
+
An MCP server is not a model provider. It exposes tools, resources, or prompts. The MCP host is the AI application that owns the conversation, chooses or supplies the model, decides when a tool should be called, sends the tool request, and adds the result back to the model context.
|
|
6
|
+
|
|
7
|
+
For this project:
|
|
8
|
+
|
|
9
|
+
```text
|
|
10
|
+
Claude Desktop / Cursor / Codex / ChatGPT Desktop / another MCP host
|
|
11
|
+
owns the model, account, conversation, approvals, and tool-selection loop
|
|
12
|
+
|
|
|
13
|
+
| stdio or Streamable HTTP
|
|
14
|
+
v
|
|
15
|
+
machine-bridge-mcp
|
|
16
|
+
exposes local file, Git, image, patch, and process tools
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
A local stdio connection does **not** use the model running in a separate ChatGPT web conversation. It uses whatever model/session the local host is configured to use:
|
|
20
|
+
|
|
21
|
+
- Claude Desktop uses the Claude account/model available to that application.
|
|
22
|
+
- Cursor uses the model/provider configured in Cursor.
|
|
23
|
+
- Codex CLI and the Codex IDE integration use their own authenticated Codex/OpenAI configuration.
|
|
24
|
+
- ChatGPT Desktop can use its signed-in ChatGPT/Codex host session and can launch local stdio servers on supported hosts.
|
|
25
|
+
|
|
26
|
+
The MCP protocol itself intentionally does not dictate how the host obtains an LLM. The optional MCP sampling primitive can let a server ask a capable host for a completion, but `machine-bridge-mcp` does not depend on sampling and does not bundle a model SDK.
|
|
27
|
+
|
|
28
|
+
## Why keep stdio when coding clients already have tools?
|
|
29
|
+
|
|
30
|
+
For many users, the client's native filesystem, patch, terminal, and approval system is sufficient. In that case, adding Machine Bridge over stdio is redundant and should be skipped.
|
|
31
|
+
|
|
32
|
+
The stdio mode exists for narrower cases:
|
|
33
|
+
|
|
34
|
+
1. **One tool contract across several clients.** The same tool names, schemas, patch behavior, Git handling, process sessions, result formats, and logging work in Claude Desktop, Cursor, Codex, ChatGPT Desktop, and other MCP hosts.
|
|
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
|
+
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
|
+
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. **Testing and interoperability.** stdio is a standard MCP transport and provides a direct way to validate the runtime independently of the Worker.
|
|
39
|
+
|
|
40
|
+
It is therefore an optional compatibility and reuse surface, not a replacement for the native agent tooling in Claude Desktop, Cursor, or Codex.
|
|
2
41
|
|
|
3
42
|
## Choosing a transport
|
|
4
43
|
|
|
5
|
-
|
|
44
|
+
| Situation | Recommended path |
|
|
45
|
+
|---|---|
|
|
46
|
+
| ChatGPT web or another service must reach this computer remotely | Remote Worker with HTTPS/OAuth |
|
|
47
|
+
| A local MCP host needs Machine Bridge-specific tools | stdio |
|
|
48
|
+
| The local coding client already provides everything needed | Use the client's native tools; do not configure Machine Bridge stdio |
|
|
49
|
+
| Several local clients should share identical tool semantics | stdio |
|
|
50
|
+
| Access is required from another device or hosted agent | Remote Worker |
|
|
6
51
|
|
|
7
|
-
|
|
8
|
-
|---|---|---|
|
|
9
|
-
| ChatGPT remote connector / Developer Mode | Remote Worker | Public HTTPS endpoint and OAuth authorization |
|
|
10
|
-
| Claude Desktop | stdio | Local process transport; no cloud relay required |
|
|
11
|
-
| Cursor | stdio | Local process transport and direct workspace lifecycle |
|
|
12
|
-
| Codex CLI | stdio | Local MCP server configuration |
|
|
13
|
-
| Other MCP clients | stdio when local; remote when necessary | Minimize the trust and network boundary |
|
|
52
|
+
The MCP specification defines stdio and Streamable HTTP as standard transports. In stdio, the host launches the server as a subprocess and exchanges newline-delimited JSON-RPC through stdin/stdout. Streamable HTTP runs the server independently behind an HTTP endpoint.
|
|
14
53
|
|
|
15
|
-
## Generate configuration
|
|
54
|
+
## Generate local configuration
|
|
55
|
+
|
|
56
|
+
The default profile is `full`:
|
|
16
57
|
|
|
17
58
|
```sh
|
|
18
|
-
machine-mcp client-config --client all --workspace /path/to/project
|
|
59
|
+
machine-mcp client-config --client all --workspace /path/to/project
|
|
19
60
|
```
|
|
20
61
|
|
|
21
|
-
The generated command uses the current Node executable and installed entry script as absolute paths so it does not depend on GUI application PATH
|
|
62
|
+
The generated command uses the current Node executable and installed entry script as absolute paths so it does not depend on a GUI application's `PATH`.
|
|
63
|
+
|
|
64
|
+
To reduce authority:
|
|
65
|
+
|
|
66
|
+
```sh
|
|
67
|
+
machine-mcp client-config --client all --workspace /path/to/project --profile agent
|
|
68
|
+
machine-mcp client-config --client all --workspace /path/to/project --profile edit
|
|
69
|
+
machine-mcp client-config --client all --workspace /path/to/project --profile review
|
|
70
|
+
```
|
|
22
71
|
|
|
23
72
|
## JSON stdio configuration
|
|
24
73
|
|
|
@@ -35,38 +84,48 @@ Claude Desktop, Cursor, and many generic clients use a shape similar to:
|
|
|
35
84
|
"--workspace",
|
|
36
85
|
"/path/to/project",
|
|
37
86
|
"--profile",
|
|
38
|
-
"
|
|
87
|
+
"full"
|
|
39
88
|
]
|
|
40
89
|
}
|
|
41
90
|
}
|
|
42
91
|
}
|
|
43
92
|
```
|
|
44
93
|
|
|
45
|
-
Use the exact output of `client-config`; application-specific configuration locations
|
|
94
|
+
Use the exact output of `client-config`; application-specific configuration locations and UI flows can change.
|
|
95
|
+
|
|
96
|
+
## Codex configuration
|
|
46
97
|
|
|
47
|
-
|
|
98
|
+
Codex supports both local stdio servers and Streamable HTTP servers. A local configuration is:
|
|
48
99
|
|
|
49
100
|
```toml
|
|
50
101
|
[mcp_servers.machine_bridge]
|
|
51
102
|
command = "/absolute/path/to/node"
|
|
52
|
-
args = ["/absolute/path/to/machine-mcp.mjs", "stdio", "--workspace", "/path/to/project", "--profile", "
|
|
103
|
+
args = ["/absolute/path/to/machine-mcp.mjs", "stdio", "--workspace", "/path/to/project", "--profile", "full"]
|
|
53
104
|
```
|
|
54
105
|
|
|
55
|
-
|
|
106
|
+
Codex CLI, the Codex IDE extension, and supported ChatGPT Desktop Codex hosts can share MCP configuration on the same Codex host. ChatGPT web does not read local Codex configuration files; web use requires a hosted plugin/connector or a reachable remote MCP endpoint.
|
|
107
|
+
|
|
108
|
+
## Remote ChatGPT connection
|
|
56
109
|
|
|
57
110
|
Run:
|
|
58
111
|
|
|
59
112
|
```sh
|
|
60
|
-
machine-mcp --workspace /path/to/project
|
|
113
|
+
machine-mcp --workspace /path/to/project
|
|
61
114
|
```
|
|
62
115
|
|
|
63
116
|
Enter the printed `/mcp` URL in the remote MCP connector. During OAuth authorization, verify the displayed client name and redirect URI before entering the connection password.
|
|
64
117
|
|
|
65
118
|
## Profile guidance
|
|
66
119
|
|
|
67
|
-
-
|
|
68
|
-
-
|
|
69
|
-
-
|
|
70
|
-
-
|
|
120
|
+
- `full` is the default and prioritizes immediate usability. It exposes shell execution, unrestricted direct filesystem paths, absolute path output, and the full parent environment.
|
|
121
|
+
- `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
|
+
- `edit` permits deterministic file mutation without process execution.
|
|
123
|
+
- `review` is read-only and workspace-confined.
|
|
124
|
+
|
|
125
|
+
A client configuration is an authorization decision. Anyone who controls an authorized host can invoke every tool exposed by the selected profile.
|
|
126
|
+
|
|
127
|
+
## Host-side safety rules
|
|
128
|
+
|
|
129
|
+
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.
|
|
71
130
|
|
|
72
|
-
|
|
131
|
+
Machine Bridge itself does not block files because their names look sensitive. If `server_info` reports `full` and a direct `read_file` request is still rejected as a “sensitive file” by the execution layer, that refusal comes from the host/platform rather than this server. Changing `--profile`, `--unrestricted-paths`, or `--absolute-paths` cannot override it. Use a trusted local client or an operator-controlled local command only where doing so is consistent with the host's terms and the user's security intent.
|