machine-bridge-mcp 0.12.2 → 0.14.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 +38 -0
- package/README.md +44 -13
- package/SECURITY.md +7 -3
- package/browser-extension/devtools-input.js +136 -0
- package/browser-extension/manifest.json +3 -2
- package/browser-extension/page-automation.js +309 -29
- package/browser-extension/service-worker.js +108 -5
- package/docs/AGENT_CONTEXT.md +16 -6
- package/docs/ARCHITECTURE.md +7 -5
- package/docs/AUDIT.md +13 -1
- package/docs/CLIENTS.md +1 -1
- package/docs/ENGINEERING.md +1 -0
- package/docs/LOCAL_AUTOMATION.md +14 -10
- package/docs/LOGGING.md +3 -1
- package/docs/OPERATIONS.md +17 -5
- package/docs/TESTING.md +8 -7
- package/package.json +10 -4
- package/src/local/agent-context.mjs +76 -19
- package/src/local/app-automation.mjs +15 -1
- package/src/local/browser-bridge.mjs +186 -88
- package/src/local/browser-command.mjs +126 -0
- package/src/local/capability-observer.mjs +56 -0
- package/src/local/cli.mjs +21 -3
- package/src/local/default-instructions.mjs +21 -91
- package/src/local/network-proxy.mjs +34 -0
- package/src/local/process-sessions.mjs +7 -0
- package/src/local/project-package.mjs +234 -0
- package/src/local/relay-connection.mjs +26 -0
- package/src/local/runtime.mjs +23 -20
- package/src/shared/tool-catalog.json +212 -6
- package/src/worker/index.ts +14 -8
package/src/local/runtime.mjs
CHANGED
|
@@ -7,7 +7,7 @@ import path, { basename, dirname, isAbsolute, join, relative, resolve, sep } fro
|
|
|
7
7
|
import { RelayConnection } from "./relay-connection.mjs";
|
|
8
8
|
import { applyUpdateHunks, parsePatchEnvelope } from "./patch.mjs";
|
|
9
9
|
import { executionEnv, workspaceShellCommand } from "./shell.mjs";
|
|
10
|
-
import { MAX_COMMAND_BYTES, ProcessSessionManager, terminateProcessTree, validateArgv } from "./process-sessions.mjs";
|
|
10
|
+
import { MAX_COMMAND_BYTES, ProcessSessionManager, terminateProcessTree, terminateProcessTreeWithEscalation, validateArgv } from "./process-sessions.mjs";
|
|
11
11
|
export { MAX_COMMAND_BYTES } from "./process-sessions.mjs";
|
|
12
12
|
import { allToolNames, assertCanonicalFullPolicy, isCanonicalFullPolicy, MCP_PROTOCOL_VERSION, MCP_SUPPORTED_PROTOCOL_VERSIONS, normalizePolicy, POLICY_PROFILES, SERVER_NAME, toolNamesForPolicy } from "./tools.mjs";
|
|
13
13
|
import { classifyOperationalError } from "./log.mjs";
|
|
@@ -17,6 +17,7 @@ import { expandHome } from "./state.mjs";
|
|
|
17
17
|
import { AgentContextManager } from "./agent-context.mjs";
|
|
18
18
|
import { AppAutomationManager } from "./app-automation.mjs";
|
|
19
19
|
import { BrowserBridgeManager } from "./browser-bridge.mjs";
|
|
20
|
+
import { CapabilityObserver } from "./capability-observer.mjs";
|
|
20
21
|
import { readBoundedRegularFileSync } from "./secure-file.mjs";
|
|
21
22
|
|
|
22
23
|
export const MAX_WRITE_BYTES = 5 * 1024 * 1024;
|
|
@@ -45,6 +46,8 @@ const RUNTIME_TOOL_HANDLERS = Object.freeze({
|
|
|
45
46
|
browser_status: (runtime, _args, context) => runtime.browserBridgeManager.status(context),
|
|
46
47
|
pair_browser_extension: (runtime, args, context) => runtime.browserBridgeManager.pair(args, context),
|
|
47
48
|
browser_list_tabs: (runtime, args, context) => runtime.browserBridgeManager.listTabs(args, context),
|
|
49
|
+
browser_manage_tabs: (runtime, args, context) => runtime.browserBridgeManager.manageTabs(args, context),
|
|
50
|
+
browser_wait: (runtime, args, context) => runtime.browserBridgeManager.wait(args, context),
|
|
48
51
|
browser_get_source: (runtime, args, context) => runtime.browserBridgeManager.getSource(args, context),
|
|
49
52
|
browser_inspect_page: (runtime, args, context) => runtime.browserBridgeManager.inspectPage(args, context),
|
|
50
53
|
browser_action: (runtime, args, context) => runtime.browserBridgeManager.act(args, context),
|
|
@@ -85,7 +88,7 @@ export function runtimeToolHandlerNames() {
|
|
|
85
88
|
}
|
|
86
89
|
|
|
87
90
|
export class LocalRuntime {
|
|
88
|
-
constructor({ workerUrl = "", secret = "", expectedRelayVersion = "", workspace, policy, logger = console, onSuperseded = null, onFatal = null, jobRoot = "", resources = {}, resourceStatePath = "", browserStateRoot = "", agentHome = process.env.HOME || process.env.USERPROFILE || "", codexHome = process.env.CODEX_HOME || "", recoverJobs = true }) {
|
|
91
|
+
constructor({ workerUrl = "", secret = "", expectedRelayVersion = "", workspace, policy, logger = console, onSuperseded = null, onFatal = null, jobRoot = "", resources = {}, resourceStatePath = "", browserStateRoot = "", agentHome = process.env.HOME || process.env.USERPROFILE || "", codexHome = process.env.CODEX_HOME || "", recoverJobs = true, applicationAutomation = {} }) {
|
|
89
92
|
const remoteWorkerUrl = workerUrl ? String(workerUrl) : "";
|
|
90
93
|
const remoteSecret = secret || "";
|
|
91
94
|
this.workspaceInput = resolve(workspace || process.cwd());
|
|
@@ -100,6 +103,7 @@ export class LocalRuntime {
|
|
|
100
103
|
this.callProcesses = new Map();
|
|
101
104
|
this.cancelledCalls = new Set();
|
|
102
105
|
this.mutationQueue = Promise.resolve();
|
|
106
|
+
this.capabilityObserver = new CapabilityObserver();
|
|
103
107
|
this.runtimeDir = createRuntimeDir();
|
|
104
108
|
if (typeof jobRoot !== "string" || !jobRoot.trim()) throw new Error("persistent managed-job root is required");
|
|
105
109
|
this.managedJobManager = new ManagedJobManager({
|
|
@@ -139,6 +143,7 @@ export class LocalRuntime {
|
|
|
139
143
|
const readResourceText = (name) => this.readLocalResourceText(name);
|
|
140
144
|
const readResourceBinary = (name) => this.readLocalResourceBinary(name);
|
|
141
145
|
this.appAutomationManager = new AppAutomationManager({
|
|
146
|
+
...applicationAutomation,
|
|
142
147
|
policy: this.policy,
|
|
143
148
|
displayPath: (value) => this.displayPath(value),
|
|
144
149
|
runProcess,
|
|
@@ -198,9 +203,11 @@ export class LocalRuntime {
|
|
|
198
203
|
per_tool_events: "debug-only",
|
|
199
204
|
default_logs_include_tool_failures: false,
|
|
200
205
|
tool_arguments_or_results_logged: false,
|
|
206
|
+
capability_routing: this.capabilityObserver.snapshot(),
|
|
201
207
|
},
|
|
202
208
|
runtime: {
|
|
203
209
|
environment: this.policy.minimalEnv ? "isolated-minimal" : "full-parent",
|
|
210
|
+
relay: this.relay?.status?.() || null,
|
|
204
211
|
runtime_dir: this.policy.exposeAbsolutePaths ? this.runtimeDir : "<private-runtime-dir>",
|
|
205
212
|
process_sessions: this.processSessionManager.status(),
|
|
206
213
|
managed_jobs: this.managedJobManager.status(),
|
|
@@ -323,14 +330,8 @@ export class LocalRuntime {
|
|
|
323
330
|
this.cancelledCalls.add(callId);
|
|
324
331
|
this.processSessionManager.notifyCancellation();
|
|
325
332
|
this.browserBridgeManager?.cancelCall(callId);
|
|
326
|
-
for (const child of this.callProcesses.get(callId) || []) terminateProcessTree(child, "SIGTERM");
|
|
327
333
|
const children = [...(this.callProcesses.get(callId) || [])];
|
|
328
|
-
|
|
329
|
-
const timer = setTimeout(() => {
|
|
330
|
-
for (const child of children) if (this.activeProcesses.has(child)) terminateProcessTree(child, "SIGKILL");
|
|
331
|
-
}, 2000);
|
|
332
|
-
timer.unref?.();
|
|
333
|
-
}
|
|
334
|
+
for (const child of children) terminateProcessTreeWithEscalation(child);
|
|
334
335
|
this.logger.debug?.("tool call cancellation requested", { call_id: shortCallId(callId), reason });
|
|
335
336
|
}
|
|
336
337
|
|
|
@@ -351,6 +352,7 @@ export class LocalRuntime {
|
|
|
351
352
|
gitRoot: git.code === 0 ? this.displayPath(git.stdout.trim()) : "",
|
|
352
353
|
policy: this.policy,
|
|
353
354
|
tools: ["server_info", ...this.tools()],
|
|
355
|
+
capabilityRouting: this.capabilityObserver.snapshot(),
|
|
354
356
|
topLevel: top.entries || [],
|
|
355
357
|
};
|
|
356
358
|
}
|
|
@@ -795,13 +797,14 @@ export class LocalRuntime {
|
|
|
795
797
|
status_tool: "browser_status",
|
|
796
798
|
} : null,
|
|
797
799
|
};
|
|
800
|
+
this.capabilityObserver.recordBootstrap(bootstrap);
|
|
798
801
|
return bootstrap;
|
|
799
802
|
}
|
|
800
803
|
|
|
801
804
|
async resolveTaskCapabilities(args = {}, context = {}) {
|
|
802
805
|
const result = await this.agentContextManager.resolveTaskCapabilities(args, context);
|
|
803
806
|
const task = String(args.task || "");
|
|
804
|
-
if (
|
|
807
|
+
if (this.policy.profile === "full") {
|
|
805
808
|
const applications = await this.appAutomationManager.listApplications({ query: "", max_results: 500 }, context).catch(() => ({ applications: [] }));
|
|
806
809
|
const lower = task.toLowerCase();
|
|
807
810
|
result.application_matches = applications.applications
|
|
@@ -813,7 +816,12 @@ export class LocalRuntime {
|
|
|
813
816
|
} else {
|
|
814
817
|
result.application_matches = [];
|
|
815
818
|
}
|
|
819
|
+
if (result.application_matches.length) {
|
|
820
|
+
result.recommended_tools = [...new Set([...result.recommended_tools, "list_local_applications", "open_local_application", "inspect_local_application", "operate_local_application"])];
|
|
821
|
+
}
|
|
816
822
|
result.browser_backend = this.policy.profile === "full" ? { tool: "browser_status", existing_profile: true, extension_bridge: true } : null;
|
|
823
|
+
result.routing_observability = "Call server_info or project_overview to verify that bootstrap and task capability resolution reached the local runtime.";
|
|
824
|
+
this.capabilityObserver.recordResolution(task, result);
|
|
817
825
|
return result;
|
|
818
826
|
}
|
|
819
827
|
|
|
@@ -873,12 +881,9 @@ export class LocalRuntime {
|
|
|
873
881
|
|
|
874
882
|
terminateActiveProcesses(signal = "SIGTERM", escalate = false) {
|
|
875
883
|
const children = [...this.activeProcesses];
|
|
876
|
-
for (const child of children)
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
for (const child of children) if (this.activeProcesses.has(child)) terminateProcessTree(child, "SIGKILL");
|
|
880
|
-
}, 2000);
|
|
881
|
-
timer.unref?.();
|
|
884
|
+
for (const child of children) {
|
|
885
|
+
if (escalate && signal !== "SIGKILL") terminateProcessTreeWithEscalation(child);
|
|
886
|
+
else terminateProcessTree(child, signal);
|
|
882
887
|
}
|
|
883
888
|
}
|
|
884
889
|
|
|
@@ -911,14 +916,12 @@ export class LocalRuntime {
|
|
|
911
916
|
let killTimer = null;
|
|
912
917
|
const timer = setTimeout(() => {
|
|
913
918
|
timedOut = true;
|
|
914
|
-
|
|
915
|
-
killTimer = setTimeout(() => terminateProcessTree(child, "SIGKILL"), 2000);
|
|
916
|
-
killTimer.unref?.();
|
|
919
|
+
killTimer = terminateProcessTreeWithEscalation(child);
|
|
917
920
|
}, timeoutMs);
|
|
918
921
|
timer.unref?.();
|
|
919
922
|
const cleanup = () => {
|
|
920
923
|
clearTimeout(timer);
|
|
921
|
-
if (killTimer) clearTimeout(killTimer);
|
|
924
|
+
if (killTimer && !timedOut) clearTimeout(killTimer);
|
|
922
925
|
this.activeProcesses.delete(child);
|
|
923
926
|
if (context.callId) {
|
|
924
927
|
const set = this.callProcesses.get(context.callId);
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
{
|
|
58
58
|
"name": "resolve_task_capabilities",
|
|
59
59
|
"title": "Resolve task capabilities",
|
|
60
|
-
"description": "Rescan built-in and automatic project context, local instruction files, skills,
|
|
60
|
+
"description": "Rescan built-in and automatic project context, local instruction files, skills, explicit and automatic package commands, installed applications, and browser capability metadata; rank the capabilities relevant to the current task and optionally load the best skill.",
|
|
61
61
|
"availability": "always",
|
|
62
62
|
"annotations": {
|
|
63
63
|
"readOnlyHint": true,
|
|
@@ -385,6 +385,55 @@
|
|
|
385
385
|
}
|
|
386
386
|
}
|
|
387
387
|
},
|
|
388
|
+
{
|
|
389
|
+
"name": "browser_manage_tabs",
|
|
390
|
+
"title": "Manage browser tabs",
|
|
391
|
+
"description": "Create, activate, or close tabs in the paired existing browser profile.",
|
|
392
|
+
"availability": "full",
|
|
393
|
+
"annotations": {
|
|
394
|
+
"readOnlyHint": false,
|
|
395
|
+
"destructiveHint": true,
|
|
396
|
+
"idempotentHint": false,
|
|
397
|
+
"openWorldHint": true
|
|
398
|
+
},
|
|
399
|
+
"inputSchema": {
|
|
400
|
+
"type": "object",
|
|
401
|
+
"additionalProperties": false,
|
|
402
|
+
"properties": {
|
|
403
|
+
"action": {
|
|
404
|
+
"type": "string",
|
|
405
|
+
"enum": [
|
|
406
|
+
"new",
|
|
407
|
+
"activate",
|
|
408
|
+
"close"
|
|
409
|
+
]
|
|
410
|
+
},
|
|
411
|
+
"tab_id": {
|
|
412
|
+
"type": "integer",
|
|
413
|
+
"minimum": 1,
|
|
414
|
+
"description": "Required for activate and close."
|
|
415
|
+
},
|
|
416
|
+
"url": {
|
|
417
|
+
"type": "string",
|
|
418
|
+
"maxLength": 32768,
|
|
419
|
+
"description": "Optional absolute http, https, or file URL for a new tab."
|
|
420
|
+
},
|
|
421
|
+
"active": {
|
|
422
|
+
"type": "boolean",
|
|
423
|
+
"default": true
|
|
424
|
+
},
|
|
425
|
+
"timeout_seconds": {
|
|
426
|
+
"type": "integer",
|
|
427
|
+
"minimum": 1,
|
|
428
|
+
"maximum": 120,
|
|
429
|
+
"default": 30
|
|
430
|
+
}
|
|
431
|
+
},
|
|
432
|
+
"required": [
|
|
433
|
+
"action"
|
|
434
|
+
]
|
|
435
|
+
}
|
|
436
|
+
},
|
|
388
437
|
{
|
|
389
438
|
"name": "browser_get_source",
|
|
390
439
|
"title": "Read browser page source",
|
|
@@ -473,10 +522,115 @@
|
|
|
473
522
|
}
|
|
474
523
|
}
|
|
475
524
|
},
|
|
525
|
+
{
|
|
526
|
+
"name": "browser_wait",
|
|
527
|
+
"title": "Wait for browser state",
|
|
528
|
+
"description": "Wait until all supplied URL, load, text, and element-state conditions are satisfied in an existing browser tab.",
|
|
529
|
+
"availability": "full",
|
|
530
|
+
"annotations": {
|
|
531
|
+
"readOnlyHint": true,
|
|
532
|
+
"destructiveHint": false,
|
|
533
|
+
"idempotentHint": true,
|
|
534
|
+
"openWorldHint": true
|
|
535
|
+
},
|
|
536
|
+
"inputSchema": {
|
|
537
|
+
"type": "object",
|
|
538
|
+
"additionalProperties": false,
|
|
539
|
+
"properties": {
|
|
540
|
+
"tab_id": {
|
|
541
|
+
"type": "integer",
|
|
542
|
+
"minimum": 1
|
|
543
|
+
},
|
|
544
|
+
"frame_id": {
|
|
545
|
+
"type": "integer",
|
|
546
|
+
"minimum": 0
|
|
547
|
+
},
|
|
548
|
+
"selector": {
|
|
549
|
+
"type": "object",
|
|
550
|
+
"properties": {
|
|
551
|
+
"ref": {
|
|
552
|
+
"type": "string",
|
|
553
|
+
"maxLength": 100,
|
|
554
|
+
"description": "Stable element reference returned by browser_inspect_page for the same document and frame."
|
|
555
|
+
},
|
|
556
|
+
"css": {
|
|
557
|
+
"type": "string",
|
|
558
|
+
"maxLength": 2000
|
|
559
|
+
},
|
|
560
|
+
"id": {
|
|
561
|
+
"type": "string",
|
|
562
|
+
"maxLength": 2000
|
|
563
|
+
},
|
|
564
|
+
"name": {
|
|
565
|
+
"type": "string",
|
|
566
|
+
"maxLength": 2000
|
|
567
|
+
},
|
|
568
|
+
"label": {
|
|
569
|
+
"type": "string",
|
|
570
|
+
"maxLength": 2000
|
|
571
|
+
},
|
|
572
|
+
"text": {
|
|
573
|
+
"type": "string",
|
|
574
|
+
"maxLength": 2000
|
|
575
|
+
},
|
|
576
|
+
"role": {
|
|
577
|
+
"type": "string",
|
|
578
|
+
"maxLength": 2000
|
|
579
|
+
},
|
|
580
|
+
"placeholder": {
|
|
581
|
+
"type": "string",
|
|
582
|
+
"maxLength": 2000
|
|
583
|
+
},
|
|
584
|
+
"index": {
|
|
585
|
+
"type": "integer",
|
|
586
|
+
"minimum": 0,
|
|
587
|
+
"maximum": 10000
|
|
588
|
+
}
|
|
589
|
+
},
|
|
590
|
+
"additionalProperties": false
|
|
591
|
+
},
|
|
592
|
+
"state": {
|
|
593
|
+
"type": "string",
|
|
594
|
+
"enum": [
|
|
595
|
+
"attached",
|
|
596
|
+
"detached",
|
|
597
|
+
"visible",
|
|
598
|
+
"hidden",
|
|
599
|
+
"enabled",
|
|
600
|
+
"editable",
|
|
601
|
+
"checked",
|
|
602
|
+
"unchecked"
|
|
603
|
+
],
|
|
604
|
+
"description": "Element state to wait for. Defaults to visible only when selector is supplied."
|
|
605
|
+
},
|
|
606
|
+
"text": {
|
|
607
|
+
"type": "string",
|
|
608
|
+
"maxLength": 4000
|
|
609
|
+
},
|
|
610
|
+
"url_contains": {
|
|
611
|
+
"type": "string",
|
|
612
|
+
"maxLength": 32768
|
|
613
|
+
},
|
|
614
|
+
"load_state": {
|
|
615
|
+
"type": "string",
|
|
616
|
+
"enum": [
|
|
617
|
+
"domcontentloaded",
|
|
618
|
+
"complete"
|
|
619
|
+
]
|
|
620
|
+
},
|
|
621
|
+
"timeout_seconds": {
|
|
622
|
+
"type": "integer",
|
|
623
|
+
"minimum": 1,
|
|
624
|
+
"maximum": 120,
|
|
625
|
+
"default": 30
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
},
|
|
476
630
|
{
|
|
477
631
|
"name": "browser_action",
|
|
478
632
|
"title": "Operate browser page",
|
|
479
|
-
"description": "Perform one structured navigation or
|
|
633
|
+
"description": "Perform one structured navigation or page action in the user's existing browser tab, with automatic actionability waits and optional fixed DevTools input, without accepting arbitrary JavaScript.",
|
|
480
634
|
"availability": "full",
|
|
481
635
|
"annotations": {
|
|
482
636
|
"readOnlyHint": false,
|
|
@@ -506,12 +660,21 @@
|
|
|
506
660
|
"submit",
|
|
507
661
|
"reload",
|
|
508
662
|
"back",
|
|
509
|
-
"forward"
|
|
663
|
+
"forward",
|
|
664
|
+
"double_click",
|
|
665
|
+
"hover",
|
|
666
|
+
"type_text",
|
|
667
|
+
"scroll_into_view"
|
|
510
668
|
]
|
|
511
669
|
},
|
|
512
670
|
"selector": {
|
|
513
671
|
"type": "object",
|
|
514
672
|
"properties": {
|
|
673
|
+
"ref": {
|
|
674
|
+
"type": "string",
|
|
675
|
+
"maxLength": 100,
|
|
676
|
+
"description": "Stable element reference returned by browser_inspect_page for the same document and frame."
|
|
677
|
+
},
|
|
515
678
|
"css": {
|
|
516
679
|
"type": "string",
|
|
517
680
|
"maxLength": 2000
|
|
@@ -582,6 +745,22 @@
|
|
|
582
745
|
"frame_id": {
|
|
583
746
|
"type": "integer",
|
|
584
747
|
"minimum": 0
|
|
748
|
+
},
|
|
749
|
+
"input_mode": {
|
|
750
|
+
"type": "string",
|
|
751
|
+
"enum": [
|
|
752
|
+
"auto",
|
|
753
|
+
"trusted",
|
|
754
|
+
"dom"
|
|
755
|
+
],
|
|
756
|
+
"default": "auto",
|
|
757
|
+
"description": "Use fixed DevTools Input commands when possible, require them, or use DOM events only."
|
|
758
|
+
},
|
|
759
|
+
"element_timeout_seconds": {
|
|
760
|
+
"type": "integer",
|
|
761
|
+
"minimum": 1,
|
|
762
|
+
"maximum": 60,
|
|
763
|
+
"default": 10
|
|
585
764
|
}
|
|
586
765
|
},
|
|
587
766
|
"required": [
|
|
@@ -618,6 +797,11 @@
|
|
|
618
797
|
"selector": {
|
|
619
798
|
"type": "object",
|
|
620
799
|
"properties": {
|
|
800
|
+
"ref": {
|
|
801
|
+
"type": "string",
|
|
802
|
+
"maxLength": 100,
|
|
803
|
+
"description": "Stable element reference returned by browser_inspect_page for the same document and frame."
|
|
804
|
+
},
|
|
621
805
|
"css": {
|
|
622
806
|
"type": "string",
|
|
623
807
|
"maxLength": 2000
|
|
@@ -691,6 +875,11 @@
|
|
|
691
875
|
"submit_selector": {
|
|
692
876
|
"type": "object",
|
|
693
877
|
"properties": {
|
|
878
|
+
"ref": {
|
|
879
|
+
"type": "string",
|
|
880
|
+
"maxLength": 100,
|
|
881
|
+
"description": "Stable element reference returned by browser_inspect_page for the same document and frame."
|
|
882
|
+
},
|
|
694
883
|
"css": {
|
|
695
884
|
"type": "string",
|
|
696
885
|
"maxLength": 2000
|
|
@@ -745,6 +934,12 @@
|
|
|
745
934
|
"frame_id": {
|
|
746
935
|
"type": "integer",
|
|
747
936
|
"minimum": 0
|
|
937
|
+
},
|
|
938
|
+
"element_timeout_seconds": {
|
|
939
|
+
"type": "integer",
|
|
940
|
+
"minimum": 1,
|
|
941
|
+
"maximum": 60,
|
|
942
|
+
"default": 10
|
|
748
943
|
}
|
|
749
944
|
},
|
|
750
945
|
"required": [
|
|
@@ -815,6 +1010,11 @@
|
|
|
815
1010
|
"selector": {
|
|
816
1011
|
"type": "object",
|
|
817
1012
|
"properties": {
|
|
1013
|
+
"ref": {
|
|
1014
|
+
"type": "string",
|
|
1015
|
+
"maxLength": 100,
|
|
1016
|
+
"description": "Stable element reference returned by browser_inspect_page for the same document and frame."
|
|
1017
|
+
},
|
|
818
1018
|
"css": {
|
|
819
1019
|
"type": "string",
|
|
820
1020
|
"maxLength": 2000
|
|
@@ -885,6 +1085,12 @@
|
|
|
885
1085
|
"frame_id": {
|
|
886
1086
|
"type": "integer",
|
|
887
1087
|
"minimum": 0
|
|
1088
|
+
},
|
|
1089
|
+
"element_timeout_seconds": {
|
|
1090
|
+
"type": "integer",
|
|
1091
|
+
"minimum": 1,
|
|
1092
|
+
"maximum": 60,
|
|
1093
|
+
"default": 10
|
|
888
1094
|
}
|
|
889
1095
|
},
|
|
890
1096
|
"required": [
|
|
@@ -897,7 +1103,7 @@
|
|
|
897
1103
|
{
|
|
898
1104
|
"name": "agent_context",
|
|
899
1105
|
"title": "Load agent context",
|
|
900
|
-
"description": "Discover built-in defaults, bounded automatic project facts, Codex-compatible global/root-to-target instruction precedence, progressively disclosed local skills, and
|
|
1106
|
+
"description": "Discover built-in defaults, bounded automatic project facts, Codex-compatible global/root-to-target instruction precedence, progressively disclosed local skills, explicit commands, and safe automatic package-script command aliases for a target path.",
|
|
901
1107
|
"availability": "always",
|
|
902
1108
|
"annotations": {
|
|
903
1109
|
"readOnlyHint": true,
|
|
@@ -1001,7 +1207,7 @@
|
|
|
1001
1207
|
{
|
|
1002
1208
|
"name": "list_local_commands",
|
|
1003
1209
|
"title": "List registered local commands",
|
|
1004
|
-
"description": "List commands
|
|
1210
|
+
"description": "List effective direct-argv commands from project manifests and safe automatic package-script aliases, including provenance and timeout limits.",
|
|
1005
1211
|
"availability": "always",
|
|
1006
1212
|
"annotations": {
|
|
1007
1213
|
"readOnlyHint": true,
|
|
@@ -1024,7 +1230,7 @@
|
|
|
1024
1230
|
{
|
|
1025
1231
|
"name": "run_local_command",
|
|
1026
1232
|
"title": "Run registered local command",
|
|
1027
|
-
"description": "
|
|
1233
|
+
"description": "Run an effective manifest or automatic package-script command through its fixed argv, cwd, timeout ceiling, and extra-argument policy.",
|
|
1028
1234
|
"availability": "direct-exec",
|
|
1029
1235
|
"annotations": {
|
|
1030
1236
|
"readOnlyHint": false,
|
package/src/worker/index.ts
CHANGED
|
@@ -3,7 +3,7 @@ import toolCatalog from "../shared/tool-catalog.json";
|
|
|
3
3
|
import serverMetadata from "../shared/server-metadata.json";
|
|
4
4
|
|
|
5
5
|
const SERVER_NAME = String(serverMetadata.name);
|
|
6
|
-
const SERVER_VERSION = "0.
|
|
6
|
+
const SERVER_VERSION = "0.14.0";
|
|
7
7
|
const MCP_PROTOCOL_VERSION = String(serverMetadata.protocolVersion);
|
|
8
8
|
const MCP_SUPPORTED_PROTOCOL_VERSIONS = serverMetadata.supportedProtocolVersions.map((value) => String(value));
|
|
9
9
|
const JSONRPC_VERSION = "2.0";
|
|
@@ -817,6 +817,7 @@ export class BridgeRoom extends DurableObject<BridgeEnv> {
|
|
|
817
817
|
client.last_used_at = now;
|
|
818
818
|
|
|
819
819
|
const code = randomToken("mcp_code");
|
|
820
|
+
const redirectLocation = authorizationRedirectLocation(redirectUri, code, state);
|
|
820
821
|
store.codes[code] = {
|
|
821
822
|
client_id: clientId,
|
|
822
823
|
redirect_uri: redirectUri,
|
|
@@ -829,9 +830,7 @@ export class BridgeRoom extends DurableObject<BridgeEnv> {
|
|
|
829
830
|
pruneRecordByExpiry(store.codes, MAX_OAUTH_CODES);
|
|
830
831
|
await this.ctx.storage.put("oauth", store);
|
|
831
832
|
|
|
832
|
-
|
|
833
|
-
if (state) params.set("state", state);
|
|
834
|
-
return oauthRedirect(`${redirectUri}${redirectUri.includes("?") ? "&" : "?"}${params.toString()}`);
|
|
833
|
+
return oauthRedirect(redirectLocation);
|
|
835
834
|
});
|
|
836
835
|
}
|
|
837
836
|
|
|
@@ -996,11 +995,11 @@ function methodNotAllowed(allow: string): Response {
|
|
|
996
995
|
});
|
|
997
996
|
}
|
|
998
997
|
|
|
999
|
-
function oauthRedirect(location:
|
|
998
|
+
function oauthRedirect(location: URL): Response {
|
|
1000
999
|
return new Response(null, {
|
|
1001
|
-
status:
|
|
1000
|
+
status: 303,
|
|
1002
1001
|
headers: {
|
|
1003
|
-
location,
|
|
1002
|
+
location: location.href,
|
|
1004
1003
|
"cache-control": "no-store",
|
|
1005
1004
|
"referrer-policy": "no-referrer",
|
|
1006
1005
|
"x-content-type-options": "nosniff",
|
|
@@ -1008,6 +1007,13 @@ function oauthRedirect(location: string): Response {
|
|
|
1008
1007
|
});
|
|
1009
1008
|
}
|
|
1010
1009
|
|
|
1010
|
+
function authorizationRedirectLocation(redirectUri: string, code: string, state: string): URL {
|
|
1011
|
+
const location = new URL(redirectUri);
|
|
1012
|
+
location.searchParams.append("code", code);
|
|
1013
|
+
if (state) location.searchParams.append("state", state);
|
|
1014
|
+
return location;
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1011
1017
|
function isFreshDaemonCandidate(connectedAt: string): boolean {
|
|
1012
1018
|
const timestamp = Date.parse(connectedAt);
|
|
1013
1019
|
if (!Number.isFinite(timestamp)) return false;
|
|
@@ -1187,7 +1193,7 @@ function daemonToolTimeoutMs(name: string, args: Record<string, unknown>): numbe
|
|
|
1187
1193
|
const configurable = new Set([
|
|
1188
1194
|
"exec_command", "run_process", "run_local_command", "open_local_application",
|
|
1189
1195
|
"inspect_local_application", "operate_local_application", "browser_list_tabs",
|
|
1190
|
-
"browser_get_source", "browser_inspect_page", "browser_action", "browser_fill_form",
|
|
1196
|
+
"browser_manage_tabs", "browser_wait", "browser_get_source", "browser_inspect_page", "browser_action", "browser_fill_form",
|
|
1191
1197
|
"browser_screenshot", "browser_upload_files",
|
|
1192
1198
|
]);
|
|
1193
1199
|
if (!configurable.has(name)) return 60_000;
|