machine-bridge-mcp 0.3.3 → 0.4.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 CHANGED
@@ -1,5 +1,38 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.4.0 - 2026-07-10
4
+
5
+ ### Architecture and compatibility
6
+
7
+ - Refactor the project into one transport-independent local runtime shared by the existing OAuth-protected Cloudflare relay and a new local MCP stdio server.
8
+ - Update MCP negotiation to `2025-11-25` while retaining compatibility with `2025-06-18` and `2025-03-26`; validate protocol-version headers and implement cancellation in both transports.
9
+ - Add ready-to-paste stdio configuration generation for Claude Desktop, Cursor, Codex CLI, and generic MCP clients.
10
+ - Replace duplicated Worker/runtime tool declarations with one schema-and-annotation catalog, tested for drift and policy consistency.
11
+
12
+ ### Security and privacy
13
+
14
+ - Make the least-privilege `review` profile the default for newly selected workspaces; preserve stored pre-0.4 permissions during upgrade.
15
+ - Add explicit `review`, `edit`, `agent`, and `full` profiles plus `off`, direct-argv, and shell execution modes.
16
+ - Return workspace-relative paths by default, redact canonical/platform-alias paths from tool errors, omit Git author email unless requested, and reduce operational failures to coarse error classes.
17
+ - Replace the previous minimal environment with isolated HOME, temp, and cache directories; retain full parent environment only through explicit opt-in.
18
+ - Reject duplicate in-flight JSON-RPC IDs, canonical patch-path collisions, stale edits, unsupported image signatures, oversized session data, and ambiguous patch context.
19
+ - Make create-only writes atomic against concurrent destination creation and strengthen multi-file patch staging, revalidation, rollback, and mutation serialization.
20
+
21
+ ### Tools and runtime
22
+
23
+ - Add bounded line-range reads, native MCP raster-image results, exact text editing, and structured multi-file add/update/move/delete patches.
24
+ - Add staged diffs, structured Git log, bounded Git show, and privacy-aware author metadata.
25
+ - Add direct argv execution and bounded interactive process sessions with retained offsets, stdin, output/exit waits, cancellation, tree termination, and disconnect cleanup.
26
+ - Return structured tool content alongside text compatibility output and expose tool annotations for client planning.
27
+
28
+ ### Reliability, testing, and operations
29
+
30
+ - Add live stdio integration coverage for initialization, tool discovery, structured/image content, edits, patches, direct execution, sessions, cancellation, and post-cancellation health.
31
+ - Expand Worker integration coverage for latest protocol negotiation, disconnected tool advertisement, rich content, exact daemon tool sets, and remote cancellation.
32
+ - Add catalog, policy-profile, canonical-collision, no-partial-patch, Git privacy, path-redaction, isolated-environment, and session tests.
33
+ - Add a Linux/macOS/Windows GitHub Actions template, Node 22/24 coverage, package/audit checks, and Dependabot configuration.
34
+ - Rewrite architecture, security, client, operations, and testing documentation around explicit trust boundaries and non-goals.
35
+
3
36
  ## 0.3.3 - 2026-07-10
4
37
 
5
38
  ### Security
@@ -9,6 +42,7 @@
9
42
  ### Changed
10
43
 
11
44
  - Exclude the development-only Worker integration test from the published npm package while retaining it in the repository and CI.
45
+ - Add a fail-closed release command that synchronizes `main`, the version tag, the GitHub Release, and its npm tarball; block `npm publish` when those artifacts do not match.
12
46
 
13
47
  ## 0.3.2 - 2026-07-10
14
48
 
package/README.md CHANGED
@@ -1,265 +1,251 @@
1
1
  # machine-bridge-mcp
2
2
 
3
- `machine-bridge-mcp` exposes a selected local workspace to Remote MCP clients through a Cloudflare Worker relay and an outbound-only local daemon.
3
+ `machine-bridge-mcp` exposes a selected local workspace to MCP clients through one shared, policy-controlled runtime.
4
+
5
+ It supports two transports:
4
6
 
5
7
  ```text
6
- Remote MCP client -> HTTPS/OAuth -> Cloudflare Worker + Durable Object
7
- ^
8
- | outbound WebSocket
9
- |
10
- local daemon -> workspace/files/shell
8
+ Remote clients such as ChatGPT
9
+ HTTPS + OAuth 2.1 / PKCE
10
+ |
11
+ Cloudflare Worker + Durable Object
12
+ ^
13
+ | outbound authenticated WebSocket
14
+ |
15
+ local runtime
16
+
17
+ Local clients such as Claude Desktop, Cursor, and Codex CLI
18
+ |
19
+ stdio
20
+ |
21
+ local runtime
11
22
  ```
12
23
 
13
- No inbound port is opened on the local machine. The Worker does not read local files or execute commands; it authenticates MCP clients and relays bounded tool calls to the daemon.
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.
14
25
 
15
- ## Install and start
26
+ ## Security posture first
16
27
 
17
- Recommended global installation:
28
+ A new workspace starts with the `review` profile:
18
29
 
19
- ```zsh
20
- npm install -g machine-bridge-mcp@latest
21
- machine-mcp
22
- ```
30
+ - read-only filesystem and Git tools;
31
+ - no file mutation;
32
+ - no process execution;
33
+ - workspace-confined filesystem access;
34
+ - relative paths in tool results;
35
+ - no parent shell environment inherited by commands.
23
36
 
24
- Without a global installation:
37
+ Existing pre-0.4 workspace profiles keep their saved permissions during upgrade. Select a profile explicitly to change them.
25
38
 
26
- ```zsh
27
- npx machine-bridge-mcp@latest
39
+ | Profile | File edits | Direct argv processes | Shell commands | Intended use |
40
+ |---|---:|---:|---:|---|
41
+ | `review` | No | No | No | Inspection and review |
42
+ | `edit` | Yes | No | No | Controlled file changes |
43
+ | `agent` | Yes | Yes | No | Coding agents and test commands |
44
+ | `full` | Yes | Yes | Yes | Deliberate full local automation |
45
+
46
+ `run_process` and process sessions avoid command-shell parsing, but they are **not an operating-system sandbox**. An allowed executable can still access anything available to the local user. `exec_command` is more exposed because it additionally permits shell syntax and expansion. Use a container, VM, or dedicated low-privilege OS account for hostile repositories or untrusted instructions.
47
+
48
+ ## Install
49
+
50
+ Node.js 22 or newer is required.
51
+
52
+ ```sh
53
+ npm install -g machine-bridge-mcp@latest
28
54
  ```
29
55
 
30
56
  From a source checkout:
31
57
 
32
- ```zsh
58
+ ```sh
33
59
  npm install
34
- ./mbm # macOS/Linux
35
- .\mbm.cmd # Windows cmd
60
+ ./mbm # macOS/Linux
61
+ .\mbm.cmd # Windows cmd
36
62
  ```
37
63
 
38
- On first run, the CLI:
64
+ ## Remote MCP for ChatGPT
39
65
 
40
- 1. Selects and remembers a workspace.
41
- 2. Generates an MCP connection password, daemon secret, and OAuth token version.
42
- 3. Authenticates Wrangler if required.
43
- 4. Deploys a per-workspace Worker.
44
- 5. Installs a login autostart entry unless `--no-autostart` is used.
45
- 6. Starts the outbound local daemon.
46
- 7. Prints the Remote MCP URL and connection password.
66
+ Start the bridge from the project directory or select a workspace explicitly:
47
67
 
48
- Keep the foreground process running for the current session. The installed service handles later logins.
68
+ ```sh
69
+ machine-mcp --workspace /path/to/project --profile review
70
+ ```
71
+
72
+ On first remote start, the CLI:
49
73
 
50
- ## Connect an MCP client
74
+ 1. canonicalizes and remembers the workspace;
75
+ 2. creates independent credentials and state for that workspace;
76
+ 3. signs in to Cloudflare Wrangler when needed;
77
+ 4. deploys a per-workspace Worker;
78
+ 5. installs a platform-native login service unless `--no-autostart` is used;
79
+ 6. starts an outbound-only daemon connection;
80
+ 7. prints the Remote MCP URL and connection password.
51
81
 
52
- Use the values printed by `machine-mcp`:
82
+ Use the printed values in the MCP client:
53
83
 
54
84
  ```text
55
85
  MCP Server URL: https://<worker>.<account>.workers.dev/mcp
56
86
  MCP connection password: mcp_password_...
57
87
  ```
58
88
 
59
- The password is shown on first setup, after secret rotation, when the MCP URL changes, or with `--print-mcp-credentials`. Use `--no-print-credentials` to redact it in terminal output.
60
-
61
- The former experimental local OpenAI-compatible `/v1` API has been removed. Use the Remote MCP endpoint directly.
62
-
63
- ## Security defaults
64
-
65
- Version 0.3.0 changes the default filesystem boundary:
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.
66
90
 
67
- - Relative paths are resolved from the selected workspace.
68
- - Reads, writes, directory traversal, searches, and Git operations are confined to that workspace by default.
69
- - Symbolic links cannot be used to escape the workspace boundary.
70
- - `write_file` and `exec_command` remain enabled by default.
71
- - Shell commands receive a minimal environment by default.
72
- - `write_file` is limited to 5 MiB, writes atomically, and refuses to overwrite symbolic links.
73
- - Files that look sensitive, including `.env` and key files, are readable when they are inside the selected workspace. The bridge does not infer sensitivity from filenames.
91
+ ## Local stdio MCP for Claude, Cursor, Codex, and compatible clients
74
92
 
75
- A narrower session:
93
+ Generate ready-to-paste configuration:
76
94
 
77
- ```zsh
78
- machine-mcp --no-write --no-exec
95
+ ```sh
96
+ machine-mcp client-config --client all --workspace /path/to/project --profile agent
79
97
  ```
80
98
 
81
- Explicitly permit filesystem paths outside the workspace:
99
+ Or run stdio directly:
82
100
 
83
- ```zsh
84
- machine-mcp --unrestricted-paths
101
+ ```sh
102
+ machine-mcp stdio --workspace /path/to/project --profile agent
85
103
  ```
86
104
 
87
- Pass the complete parent process environment to shell commands only when required:
105
+ The stdio server writes only JSON-RPC messages to stdout. Operational logs go to stderr. It supports MCP initialization/version negotiation, tool discovery, calls, cancellation, structured tool output, native image content, and process sessions.
88
106
 
89
- ```zsh
90
- machine-mcp --full-env
91
- ```
92
-
93
- `--unrestricted-paths` and `--full-env` materially increase the data-exposure boundary. See [SECURITY.md](SECURITY.md) before enabling them.
107
+ See [docs/CLIENTS.md](docs/CLIENTS.md) for client-specific configuration and remote/local trade-offs.
94
108
 
95
- ## Commands
96
-
97
- ```text
98
- machine-mcp [start options]
99
- machine-mcp workspace show
100
- machine-mcp workspace set [PATH]
101
- machine-mcp service status|install|start|stop|uninstall
102
- machine-mcp status
103
- machine-mcp doctor
104
- machine-mcp rotate-secrets
105
- machine-mcp uninstall [--keep-worker] [--yes]
106
- ```
109
+ ## Policy controls
107
110
 
108
- Important start options:
111
+ Profiles can be narrowed with explicit flags:
109
112
 
110
113
  ```text
111
- --workspace PATH
112
- --worker-name NAME
113
- --force-worker
114
- --rotate-secrets
115
- --daemon-only
116
- --no-autostart
117
- --no-print-credentials
118
- --print-mcp-credentials
114
+ --profile review|edit|agent|full
115
+ --exec-mode off|direct|shell
119
116
  --no-write
120
117
  --no-exec
121
118
  --full-env
122
119
  --unrestricted-paths
123
- --state-dir DIR
124
- --json
125
- ```
126
-
127
- Unknown, duplicate, malformed, and command-inapplicable options are rejected. Boolean options do not consume a following positional workspace path; use `--option=false` when an explicit false value is needed.
128
-
129
- ## Workspace selection
130
-
131
- ```zsh
132
- machine-mcp workspace set
133
- machine-mcp workspace set /path/to/project
134
- machine-mcp workspace show
135
- machine-mcp workspace reset
136
- ```
137
-
138
- Each canonical workspace path receives an independent profile, Worker name, secret set, and daemon lock.
139
-
140
- ## Autostart
141
-
142
- Supported providers:
143
-
144
- - macOS: user LaunchAgent
145
- - Linux: `systemd --user`, with best-effort user lingering
146
- - Windows: Scheduled Task at logon
147
-
148
- ```zsh
149
- machine-mcp service status
150
- machine-mcp service install
151
- machine-mcp service start
152
- machine-mcp service stop
153
- machine-mcp service uninstall
120
+ --absolute-paths
154
121
  ```
155
122
 
156
- Autostart runs `--daemon-only --no-print-credentials --quiet`. The selected write, execution, environment, and path-boundary policies are persisted in the service definition. Service log files are owner-only where supported and are trimmed at daemon startup to prevent unbounded growth.
123
+ Important distinctions:
157
124
 
158
- ## Secret rotation
125
+ - `--unrestricted-paths` expands direct filesystem tools beyond the selected workspace.
126
+ - `--absolute-paths` changes returned path metadata; it does not grant additional access.
127
+ - `--full-env` passes the complete parent environment to processes. Without it, commands receive an isolated HOME, temp directory, and cache directories plus a small set of platform variables.
128
+ - Files with sensitive-looking names are not automatically blocked inside the workspace. A workspace `.env` remains readable when read tools are enabled.
159
129
 
160
- ```zsh
161
- machine-mcp rotate-secrets
162
- machine-mcp
163
- ```
130
+ ## Tools
164
131
 
165
- The first command stops the installed autostart service, refuses to proceed if another foreground daemon remains active, and then rotates the MCP password, daemon secret, and OAuth token version in local state. The second redeploys the Worker; previously issued OAuth access tokens then fail validation.
132
+ The exact `tools/list` response reflects the active local policy. Definitions come from one shared catalog used by both Worker and stdio transports.
166
133
 
167
- ## MCP tools
134
+ ### Workspace and content
168
135
 
169
136
  - `server_info`
170
137
  - `project_overview`
171
138
  - `list_roots`
172
139
  - `list_dir`
173
140
  - `list_files`
174
- - `read_file`
175
- - `write_file`
141
+ - `read_file` — whole UTF-8 files or bounded line ranges
142
+ - `view_image` — bounded PNG, JPEG, GIF, or WebP as native MCP image content
176
143
  - `search_text`
177
- - `git_status`
178
- - `git_diff`
179
- - `exec_command`
180
144
 
181
- Tool availability reflects daemon policy after the daemon handshake. `git_status` and `git_diff` detect the repository containing the requested path, including nested repositories.
145
+ ### Mutation
182
146
 
183
- ## State and logs
147
+ - `write_file` — atomic whole-file write with create-only and SHA-256 checks
148
+ - `edit_file` — exact text replacement with ambiguity rejection
149
+ - `apply_patch` — bounded multi-file add/update/move/delete transaction with rollback
184
150
 
185
- Default state roots:
151
+ ### Git
186
152
 
187
- - macOS/Linux: `~/.local/state/machine-bridge-mcp`
188
- - Linux with `XDG_STATE_HOME`: `$XDG_STATE_HOME/machine-bridge-mcp`
189
- - Windows: `%APPDATA%\machine-bridge-mcp`
153
+ - `git_status`
154
+ - `git_diff` working tree or staged
155
+ - `git_log` — structured commits; author email omitted unless explicitly requested
156
+ - `git_show`
190
157
 
191
- Override the root with `--state-dir DIR`. A new custom root must be empty; a non-empty unmarked root must contain recognizable legacy Machine Bridge state before it is adopted. Legacy text markers are migrated to the current structured marker. Uninstall refuses to recursively delete filesystem roots, the home directory, the current/package directory, source trees, recorded workspaces, unrelated files, or an unrecognized state root.
158
+ Repository-configured external diff, text conversion, and filesystem-monitor helpers are disabled for bridge Git inspection.
192
159
 
193
- State contains credentials and therefore uses owner-only permissions where supported. State/config writes use temporary files, `fsync`, and atomic rename. Corrupt state files are retained as bounded `.corrupt-*` backups rather than silently overwritten. Status and doctor output redact secrets and personal Wrangler output; structured logs fully redact credential-like fields and neutralize control characters.
160
+ ### Processes
194
161
 
195
- Temporary Wrangler secret files are created under the owner-only profile directory and removed in a `finally` block. Stale files older than one hour are cleaned before deployment.
162
+ - `run_process` one-shot argv execution without a shell
163
+ - `start_process`
164
+ - `read_process`
165
+ - `write_process`
166
+ - `kill_process`
167
+ - `exec_command` — shell execution, available only in `shell` mode
196
168
 
197
- ## Worker protections
169
+ Process sessions retain bounded stdout/stderr, support offsets and short waits, accept stdin, and are killed when the daemon connection is lost or replaced. They are pipe-based and do not emulate a terminal/PTY.
198
170
 
199
- The Worker currently enforces:
171
+ ## Path and write behavior
200
172
 
201
- - OAuth authorization code flow with PKCE S256.
202
- - Hashed access-token storage and token-version revocation.
203
- - Exact resource, client, and redirect URI binding.
204
- - Bounded registration metadata, clients, authorization codes, tokens, and failed-login records.
205
- - Per-source dynamic-client registration limits and password-failure throttling.
206
- - A consent page that displays the validated client and redirect URI.
207
- - Request-body and concurrent daemon-call limits.
208
- - Same-origin browser access by default, exact configured-origin CORS/preflight support, and rejection of unlisted cross-origin requests.
209
- - `no-store`, content-type protection, CSP, frame denial, and referrer suppression on authorization responses.
210
- - Minimal public health output; live daemon/workspace details require an authenticated MCP call.
173
+ By default, 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.
211
174
 
212
- Browser requests are same-origin by default. Additional browser origins can be listed exactly in `MBM_ALLOWED_ORIGINS`; the Worker then returns matching CORS preflight and response headers. Loopback OAuth redirect URIs do not implicitly authorize loopback browser origins. Do not use wildcards or `null`.
175
+ 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.
213
176
 
214
- ## Uninstall
177
+ Returned paths are workspace-relative by default. This reduces unnecessary disclosure of usernames and local directory layouts. Enable `--absolute-paths` only when a client genuinely needs absolute paths.
215
178
 
216
- Delete known Workers, autostart entries, and local state:
179
+ ## Commands
217
180
 
218
- ```zsh
219
- machine-mcp uninstall
181
+ ```text
182
+ machine-mcp [start options]
183
+ machine-mcp stdio [options]
184
+ machine-mcp client-config [all|claude|cursor|codex|generic]
185
+ machine-mcp workspace show|set|reset
186
+ machine-mcp service status|install|start|stop|uninstall
187
+ machine-mcp status
188
+ machine-mcp doctor
189
+ machine-mcp rotate-secrets
190
+ machine-mcp uninstall [--keep-worker] [--yes]
220
191
  ```
221
192
 
222
- Non-interactive:
193
+ Each canonical workspace has an independent profile, Worker name, credential set, state file, startup lock, and daemon lock.
223
194
 
224
- ```zsh
225
- machine-mcp uninstall --yes
226
- ```
195
+ ## Autostart
227
196
 
228
- Keep deployed Workers while removing local state and autostart:
197
+ Remote mode supports:
229
198
 
230
- ```zsh
231
- machine-mcp uninstall --keep-worker
232
- ```
199
+ - macOS user LaunchAgent;
200
+ - Linux `systemd --user`, with best-effort lingering;
201
+ - Windows Scheduled Task at logon.
233
202
 
234
- Remove a global npm installation separately:
203
+ The service definition contains neither credentials nor a duplicate policy. It loads the selected policy from owner-only local state and fails closed to the `review` profile if policy state is absent. Service logs are owner-only where supported and trimmed before daemon startup.
235
204
 
236
- ```zsh
237
- npm uninstall -g machine-bridge-mcp
205
+ ## Secret rotation
206
+
207
+ ```sh
208
+ machine-mcp rotate-secrets --no-print-credentials
209
+ machine-mcp
238
210
  ```
239
211
 
240
- ## Architecture and failure behavior
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.
241
213
 
242
- See [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) for trust boundaries, request lifecycles, limits, reconnect behavior, and the rationale for the Worker/Durable Object/daemon split.
214
+ ## State and observability
215
+
216
+ Default state roots:
217
+
218
+ - macOS/Linux: `~/.local/state/machine-bridge-mcp`
219
+ - Linux with `XDG_STATE_HOME`: `$XDG_STATE_HOME/machine-bridge-mcp`
220
+ - Windows: `%APPDATA%\machine-bridge-mcp`
243
221
 
244
- Operationally:
222
+ 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.
245
223
 
246
- - A newer daemon connection replaces the older socket. The relay handshake does not upload the local workspace name, path hash, or process ID.
247
- - Pending calls are bound to the socket that received them, so a stale socket cannot complete or cancel calls on the replacement connection; active child processes are terminated when that connection is lost or replaced.
248
- - The daemon reconnects after transient Worker/network failures using bounded exponential backoff with jitter, and terminates active child processes when the active relay socket closes.
249
- - Tool calls and Wrangler subprocesses have bounded execution time and output; timed-out commands terminate their process tree where the platform permits.
250
- - Separate per-workspace startup and daemon locks prevent overlapping deploy/rotation operations and duplicate local daemons.
251
- - Uninstall stops and removes autostart first, refuses to proceed while an active startup or daemon process owns a lock, and preserves local state when Worker deletion fails so the operation can be retried.
252
- - Worker health checks verify the expected package/Worker version before a deployment hash is accepted.
224
+ Operational logs record bounded metadata such as component, tool name, shortened call ID, duration, outcome, and error class. They do not intentionally log file contents, patch bodies, command strings, stdin, OAuth passwords, access tokens, or daemon secrets. See [docs/OPERATIONS.md](docs/OPERATIONS.md).
253
225
 
254
- ## Development
226
+ ## Development and verification
255
227
 
256
- ```zsh
228
+ ```sh
257
229
  npm ci
258
230
  npm run check
259
231
  npm run worker:dry-run
260
232
  npm audit --omit=dev --audit-level=high
233
+ npm pack --dry-run
234
+ ```
235
+
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. A ready-to-enable GitHub Actions template is included at `docs/examples/github-actions-ci.yml` for Linux, macOS, and Windows with supported Node versions. Activating it requires a GitHub credential authorized to modify workflow files.
237
+
238
+ See [docs/TESTING.md](docs/TESTING.md), [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md), and [SECURITY.md](SECURITY.md).
239
+
240
+ ## Uninstall
241
+
242
+ ```sh
243
+ machine-mcp uninstall
244
+ npm uninstall -g machine-bridge-mcp
261
245
  ```
262
246
 
263
- `npm run check` generates Worker types, type-checks the Worker, checks all local JavaScript entry points, and runs regression tests for path confinement, symbolic-link escapes, atomic writes, UTF-8 handling, nested Git repositories, minimal environments, daemon locking, CLI parsing, state recovery/removal guards, log redaction, log trimming, Worker hardening guards, and a live local OAuth/MCP flow through Wrangler.
247
+ Use `--keep-worker` to retain deployed Workers while removing local state and autostart.
248
+
249
+ ## License
264
250
 
265
- The release checks are validated on Node.js 22 and 24. Node.js 22 or newer is required by the current Wrangler toolchain. See [CHANGELOG.md](CHANGELOG.md) for release notes.
251
+ MIT