machine-bridge-mcp 1.0.5 → 1.0.6
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 +7 -0
- package/README.md +1 -1
- package/browser-extension/manifest.json +2 -2
- package/docs/ARCHITECTURE.md +1 -1
- package/docs/CLIENTS.md +1 -1
- package/docs/GETTING_STARTED.md +1 -1
- package/docs/TESTING.md +1 -1
- package/package.json +1 -1
- package/src/worker/http.ts +0 -5
- package/src/worker/index.ts +3 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.0.6 - 2026-07-14
|
|
4
|
+
|
|
5
|
+
### OAuth navigation origin handling
|
|
6
|
+
|
|
7
|
+
- Stop treating the browser `Origin` header as an authentication boundary for actual Worker requests. OAuth authorization navigations and form submissions from opaque or client-specific browser containers now reach normal protocol validation instead of failing early with `origin_not_allowed`.
|
|
8
|
+
- Keep CORS response sharing strict: only the Worker origin, the built-in ChatGPT/Grok origins, and exact `MBM_ALLOWED_ORIGINS` additions pass preflight and receive `Access-Control-Allow-Origin`. Unrelated and `null` origins receive no CORS permission, while PKCE, exact redirect/resource binding, account authentication, bearer tokens, and admin/daemon secrets remain authoritative.
|
|
9
|
+
|
|
3
10
|
## 1.0.5 - 2026-07-14
|
|
4
11
|
|
|
5
12
|
### Built-in ChatGPT and Grok origins
|
package/README.md
CHANGED
|
@@ -138,7 +138,7 @@ MCP Server URL: https://<worker>.<account>.workers.dev/mcp
|
|
|
138
138
|
|
|
139
139
|
During OAuth authorization, enter the name and password of a Machine Bridge account. The first start creates `owner` and prints its generated password once. Additional accounts are managed with `machine-mcp account`. The authorization flow uses PKCE S256, exact redirect/resource binding, expiring hashed access tokens, per-account version checks, and a deployment-wide token version for emergency bulk revocation.
|
|
140
140
|
|
|
141
|
-
The Worker
|
|
141
|
+
The Worker grants browser CORS response access to the exact first-party origins used by ChatGPT (`https://chatgpt.com` and the legacy `https://chat.openai.com`) and Grok (`https://grok.com` and its X-hosted surface at `https://x.com`). Users do not need to run Wrangler or edit Cloudflare variables. `MBM_ALLOWED_ORIGINS` remains an operator-only, comma-separated extension point for other exact origins; it is additive and does not replace the built-in set. Wildcards and `null` do not receive CORS permission. Actual OAuth navigations and form submissions are not rejected solely because a browser container supplies an opaque or client-specific `Origin`; authorization still depends on exact redirect/resource binding, PKCE, account authentication, and bearer-token validation.
|
|
142
142
|
|
|
143
143
|
### Multiple clients and accounts
|
|
144
144
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"manifest_version": 3,
|
|
3
3
|
"name": "Machine Bridge Browser",
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.6",
|
|
5
5
|
"description": "Connects the current Chromium browser profile to the local Machine Bridge runtime for user-authorized automation.",
|
|
6
6
|
"permissions": [
|
|
7
7
|
"tabs",
|
|
@@ -30,5 +30,5 @@
|
|
|
30
30
|
"action": {
|
|
31
31
|
"default_title": "Machine Bridge Browser"
|
|
32
32
|
},
|
|
33
|
-
"version_name": "1.0.
|
|
33
|
+
"version_name": "1.0.6"
|
|
34
34
|
}
|
package/docs/ARCHITECTURE.md
CHANGED
|
@@ -235,7 +235,7 @@ Removal first acquires a state-root maintenance lock that blocks new profile/sta
|
|
|
235
235
|
|
|
236
236
|
OAuth metadata is pruned on access. Expired codes/tokens, old throttling records, and inactive clients without active credentials are removed. Source identities are deployment-keyed HMAC values, not stored source addresses or reversible unsalted hashes.
|
|
237
237
|
|
|
238
|
-
Browser-origin
|
|
238
|
+
Browser-origin handling separates CORS response sharing from protocol authentication. Preflight succeeds only for the Worker's own origin, a fixed first-party set for ChatGPT (`https://chatgpt.com`, `https://chat.openai.com`) and Grok (`https://grok.com`, `https://x.com`), or optional exact comma-separated additions from `MBM_ALLOWED_ORIGINS`; wildcard and `null` origins are not granted CORS access. Actual requests are routed without using `Origin` as an authentication boundary, and `Access-Control-Allow-Origin` is added only when that exact predicate passes. This permits OAuth top-level navigation and form submission from opaque or client-specific containers while exact redirect/resource binding, PKCE, account credentials, bearer tokens, and private admin/daemon secrets enforce authority.
|
|
239
239
|
|
|
240
240
|
## Observability
|
|
241
241
|
|
package/docs/CLIENTS.md
CHANGED
|
@@ -122,7 +122,7 @@ Run:
|
|
|
122
122
|
machine-mcp --workspace /path/to/project
|
|
123
123
|
```
|
|
124
124
|
|
|
125
|
-
Enter the printed `/mcp` URL in the remote MCP connector. During OAuth authorization, verify the displayed client name and redirect URI before entering a Machine Bridge account name and password. The Worker has exact built-in CORS support for `https://chatgpt.com`, legacy `https://chat.openai.com`, `https://grok.com`, and the X-hosted Grok surface at `https://x.com`; no direct Wrangler command or Cloudflare variable edit is required.
|
|
125
|
+
Enter the printed `/mcp` URL in the remote MCP connector. During OAuth authorization, verify the displayed client name and redirect URI before entering a Machine Bridge account name and password. The Worker has exact built-in CORS response support for `https://chatgpt.com`, legacy `https://chat.openai.com`, `https://grok.com`, and the X-hosted Grok surface at `https://x.com`; no direct Wrangler command or Cloudflare variable edit is required. OAuth navigations and form submissions from opaque or client-specific browser containers are routed normally but receive no cross-origin response-sharing permission unless their exact origin is allowed.
|
|
126
126
|
|
|
127
127
|
Several OAuth clients and named accounts can coexist. Accounts have independent passwords, roles, active state, versions, and targeted revocation. Their effective tool sets are intersected with the connected daemon policy. All accounts still share one daemon and OS user, so hard tenant isolation requires separate deployments; see [MULTI_ACCOUNT.md](MULTI_ACCOUNT.md).
|
|
128
128
|
|
package/docs/GETTING_STARTED.md
CHANGED
|
@@ -204,7 +204,7 @@ Current ChatGPT developer-mode flow, as documented in OpenAI's [Connect from Cha
|
|
|
204
204
|
7. Enter the Machine Bridge account name and password only after those values are recognized.
|
|
205
205
|
8. Create a new chat and enable the app for that conversation.
|
|
206
206
|
|
|
207
|
-
ChatGPT navigation labels can change. The invariant is that the client must connect to the public `/mcp` endpoint and complete the OAuth authorization page served by the Worker. The same public `/mcp` URL can be entered in Grok where remote MCP configuration is available. Machine Bridge
|
|
207
|
+
ChatGPT navigation labels can change. The invariant is that the client must connect to the public `/mcp` endpoint and complete the OAuth authorization page served by the Worker. The same public `/mcp` URL can be entered in Grok where remote MCP configuration is available. Machine Bridge grants CORS response access to the exact `https://grok.com` and `https://x.com` browser origins as well as ChatGPT's current and legacy origins without requiring a Wrangler command. OAuth navigation and form POST requests are not failed solely because an embedded authorization container reports an opaque or different origin.
|
|
208
208
|
|
|
209
209
|
## 8. Verify the first connection
|
|
210
210
|
|
package/docs/TESTING.md
CHANGED
|
@@ -53,7 +53,7 @@ The suite includes:
|
|
|
53
53
|
- deterministic property tests over hostile browser-protocol byte strings, canonical/custom policy combinations, argv bounds/NULs, and a real direct process proving shell metacharacters remain literal argv;
|
|
54
54
|
- CLI parsing, policy profiles, and client configuration boundaries;
|
|
55
55
|
- live stdio MCP initialization with session instructions, capability resolution, discovery, calls, rich content, sessions, cancellation, managed-job acceptance, and a detached job/finally phase that survives stdio shutdown;
|
|
56
|
-
- live local Worker OAuth registration, consent, URL-constructed `303` callbacks including the ChatGPT redirect URI and encoded state, PKCE, token replay rejection, throttling, exact built-in ChatGPT/Grok browser origins, additive custom origins, unrelated
|
|
56
|
+
- live local Worker OAuth registration, consent, URL-constructed `303` callbacks including the ChatGPT redirect URI and encoded state, PKCE, token replay rejection, throttling, exact built-in ChatGPT/Grok browser origins, additive custom origins, unrelated-origin preflight rejection, no CORS response sharing for unrelated or opaque origins, opaque-origin authorization-form routing, protocol negotiation, HMAC-bound MCP session issuance, two-session same-id concurrency, sessionless same-id independence, session-scoped cancellation isolation, same-session duplicate rejection, daemon-backed session bootstrap, dynamic tool advertisement, rich content, daemon replacement, cancellation, malformed daemon JSON/non-object rejection, duplicate hello rejection, and unknown-message closure.
|
|
57
57
|
- local runtime proof that one blocked tool handler does not serialize an independent handler, plus relay fault injection proving an undeliverable terminal result interrupts the ambiguous socket and enters reconnect backoff.
|
|
58
58
|
|
|
59
59
|
## Opt-in live desktop and browser validation
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "machine-bridge-mcp",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.6",
|
|
4
4
|
"description": "Cross-client MCP bridge for local agent context, structured browser and application automation, files, Git, processes, resources, and durable jobs over stdio or OAuth relay.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
package/src/worker/http.ts
CHANGED
|
@@ -190,11 +190,6 @@ export function applyCors(response: Response, request: Request, base: string, co
|
|
|
190
190
|
return new Response(response.body, { status: response.status, statusText: response.statusText, headers });
|
|
191
191
|
}
|
|
192
192
|
|
|
193
|
-
export function validateOrigin(request: Request, base: string, configured = ""): boolean {
|
|
194
|
-
const origin = request.headers.get("Origin");
|
|
195
|
-
return !origin || isConfiguredOrSameOrigin(origin, base, configured);
|
|
196
|
-
}
|
|
197
|
-
|
|
198
193
|
export function searchParamsEntries(params: URLSearchParams): Array<[string, string]> {
|
|
199
194
|
const entries: Array<[string, string]> = [];
|
|
200
195
|
params.forEach((value, key) => entries.push([key, value]));
|
package/src/worker/index.ts
CHANGED
|
@@ -18,11 +18,11 @@ import {
|
|
|
18
18
|
import {
|
|
19
19
|
HttpError, applyCors, authorizationRedirectLocation, baseUrl, bearerToken, corsPreflight, escapeHtml,
|
|
20
20
|
html, json, methodNotAllowed, normalizeDisplayText, normalizeRedirectUri, oauthRedirect, sanitizeMetadataText,
|
|
21
|
-
parseJsonRequest, parseRequestBody, searchParamsEntries, searchParamsObject,
|
|
21
|
+
parseJsonRequest, parseRequestBody, searchParamsEntries, searchParamsObject, workerErrorClass,
|
|
22
22
|
} from "./http";
|
|
23
23
|
|
|
24
24
|
const SERVER_NAME = String(serverMetadata.name);
|
|
25
|
-
const SERVER_VERSION = "1.0.
|
|
25
|
+
const SERVER_VERSION = "1.0.6";
|
|
26
26
|
const MCP_PROTOCOL_VERSION = String(serverMetadata.protocolVersion);
|
|
27
27
|
const MCP_SUPPORTED_PROTOCOL_VERSIONS = serverMetadata.supportedProtocolVersions.map((value) => String(value));
|
|
28
28
|
const JSONRPC_VERSION = "2.0";
|
|
@@ -92,8 +92,7 @@ export class BridgeRoom extends DurableObject<BridgeEnv> {
|
|
|
92
92
|
const base = baseUrl(request);
|
|
93
93
|
const extraOrigins = this.env.MBM_ALLOWED_ORIGINS ?? "";
|
|
94
94
|
let response: Response;
|
|
95
|
-
if (
|
|
96
|
-
else if (request.method === "OPTIONS" && request.headers.has("Origin")) response = corsPreflight(request, base, extraOrigins);
|
|
95
|
+
if (request.method === "OPTIONS" && request.headers.has("Origin")) response = corsPreflight(request, base, extraOrigins);
|
|
97
96
|
else response = applyCors(await this.handleRequest(request, base), request, base, extraOrigins);
|
|
98
97
|
this.observability.requestFinished(response.status);
|
|
99
98
|
return response;
|