agent-browser-bridge 2.0.0 → 2.2.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/README.md +54 -22
- package/core/bridge.js +293 -0
- package/core/state.js +68 -0
- package/index.js +10 -951
- package/package.json +3 -1
- package/tools/browser-data-tools.js +141 -0
- package/tools/diagnostic-tools.js +170 -0
- package/tools/dom-tools.js +295 -0
- package/tools/emulation-tools.js +138 -0
- package/tools/extraction-tools.js +74 -0
- package/tools/media-tools.js +55 -0
- package/tools/navigation-tools.js +71 -0
- package/tools/network-tools.js +197 -0
- package/tools/registry.js +23 -0
- package/tools/tab-tools.js +186 -0
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
// Agent Bridge MCP - Viewport, Emulation, Screenshots & PDF Tools (ES Module)
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { jsonResult } from "../core/state.js";
|
|
4
|
+
import { callProfileExtension } from "../core/bridge.js";
|
|
5
|
+
|
|
6
|
+
export function registerEmulationTools(server) {
|
|
7
|
+
server.registerTool(
|
|
8
|
+
"browser_resize_page",
|
|
9
|
+
{
|
|
10
|
+
description: "Emulate viewport screen dimensions and device scale factor via CDP Emulation.",
|
|
11
|
+
inputSchema: {
|
|
12
|
+
profile: z.string().optional().describe("Target browser profile"),
|
|
13
|
+
tabId: z.number().describe("Target tabId"),
|
|
14
|
+
width: z.number().describe("Viewport width in pixels (e.g. 1280)"),
|
|
15
|
+
height: z.number().describe("Viewport height in pixels (e.g. 800)"),
|
|
16
|
+
deviceScaleFactor: z.number().optional().describe("Device scale factor / DPR (default 1)"),
|
|
17
|
+
mobile: z.boolean().optional().describe("Emulate mobile screen (default false)"),
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
async ({ profile, tabId, width, height, deviceScaleFactor, mobile }) => {
|
|
21
|
+
const res = await callProfileExtension(profile, "resize_page", { tabId, width, height, deviceScaleFactor, mobile });
|
|
22
|
+
return jsonResult(res);
|
|
23
|
+
}
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
server.registerTool(
|
|
27
|
+
"browser_emulate",
|
|
28
|
+
{
|
|
29
|
+
description: "Emulate device color scheme, network throttling, CPU throttling, geolocation, or user agent.",
|
|
30
|
+
inputSchema: {
|
|
31
|
+
profile: z.string().optional().describe("Target browser profile"),
|
|
32
|
+
tabId: z.number().describe("Target tabId"),
|
|
33
|
+
colorScheme: z.enum(["dark", "light", "no-preference"]).optional().describe("Emulate dark/light mode"),
|
|
34
|
+
userAgent: z.string().optional().describe("Custom User-Agent override"),
|
|
35
|
+
cpuThrottlingRate: z.number().optional().describe("CPU slowdown factor (1 = normal, 4 = 4x slowdown)"),
|
|
36
|
+
geolocation: z.object({
|
|
37
|
+
latitude: z.number(),
|
|
38
|
+
longitude: z.number(),
|
|
39
|
+
accuracy: z.number().optional(),
|
|
40
|
+
}).optional().describe("Mock geolocation coordinates"),
|
|
41
|
+
networkConditions: z.union([
|
|
42
|
+
z.enum(["offline", "slow3g", "fast3g", "4g"]),
|
|
43
|
+
z.object({
|
|
44
|
+
offline: z.boolean(),
|
|
45
|
+
latency: z.number(),
|
|
46
|
+
downloadThroughput: z.number(),
|
|
47
|
+
uploadThroughput: z.number(),
|
|
48
|
+
}),
|
|
49
|
+
]).optional().describe("Network throttling preset or custom conditions"),
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
async ({ profile, tabId, colorScheme, userAgent, cpuThrottlingRate, geolocation, networkConditions }) => {
|
|
53
|
+
const res = await callProfileExtension(profile, "emulate", {
|
|
54
|
+
tabId,
|
|
55
|
+
colorScheme,
|
|
56
|
+
userAgent,
|
|
57
|
+
cpuThrottlingRate,
|
|
58
|
+
geolocation,
|
|
59
|
+
networkConditions,
|
|
60
|
+
});
|
|
61
|
+
return jsonResult(res);
|
|
62
|
+
}
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
server.registerTool(
|
|
66
|
+
"browser_emulate_timezone",
|
|
67
|
+
{
|
|
68
|
+
description: "Override browser timezone and locale for geolocation testing or internationalization.",
|
|
69
|
+
inputSchema: {
|
|
70
|
+
profile: z.string().optional().describe("Target browser profile"),
|
|
71
|
+
tabId: z.number().describe("Target tabId"),
|
|
72
|
+
timezoneId: z.string().describe("IANA Timezone ID (e.g. 'America/New_York', 'Asia/Tokyo', 'Europe/London')"),
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
async ({ profile, tabId, timezoneId }) => {
|
|
76
|
+
const res = await callProfileExtension(profile, "emulate_timezone", { tabId, timezoneId });
|
|
77
|
+
return jsonResult(res);
|
|
78
|
+
}
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
server.registerTool(
|
|
82
|
+
"browser_screenshot",
|
|
83
|
+
{
|
|
84
|
+
description: "Capture high-resolution screenshot (PNG or compressed JPEG), full page, or clipped to an element ref/selector.",
|
|
85
|
+
inputSchema: {
|
|
86
|
+
profile: z.string().optional().describe("Target browser profile"),
|
|
87
|
+
tabId: z.number().describe("Target tabId"),
|
|
88
|
+
format: z.enum(["png", "jpeg"]).optional().describe("Image format (default 'png')"),
|
|
89
|
+
quality: z.number().optional().describe("Compression quality 0-100 (for jpeg)"),
|
|
90
|
+
fullPage: z.boolean().optional().describe("Capture entire scrollable page height (default false)"),
|
|
91
|
+
target: z.string().optional().describe("Clip screenshot to this element ref (e.g. 'ref_1') or selector"),
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
async ({ profile, tabId, format, quality, fullPage, target }) => {
|
|
95
|
+
const res = await callProfileExtension(profile, "screenshot", { tabId, format, quality, fullPage, target });
|
|
96
|
+
return {
|
|
97
|
+
content: [
|
|
98
|
+
{
|
|
99
|
+
type: "image",
|
|
100
|
+
data: res.dataBase64,
|
|
101
|
+
mimeType: res.mimeType,
|
|
102
|
+
},
|
|
103
|
+
],
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
server.registerTool(
|
|
109
|
+
"browser_print_to_pdf",
|
|
110
|
+
{
|
|
111
|
+
description: "Generate a PDF document of the webpage via Chrome DevTools Page.printToPDF.",
|
|
112
|
+
inputSchema: {
|
|
113
|
+
profile: z.string().optional().describe("Target browser profile"),
|
|
114
|
+
tabId: z.number().describe("Target tabId"),
|
|
115
|
+
landscape: z.boolean().optional().describe("Paper orientation landscape (default false)"),
|
|
116
|
+
displayHeaderFooter: z.boolean().optional().describe("Display header and footer"),
|
|
117
|
+
printBackground: z.boolean().optional().describe("Print background graphics (default true)"),
|
|
118
|
+
scale: z.number().optional().describe("Scale factor 0.1 - 2.0 (default 1)"),
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
async ({ profile, tabId, landscape, displayHeaderFooter, printBackground, scale }) => {
|
|
122
|
+
const res = await callProfileExtension(profile, "print_to_pdf", { tabId, landscape, displayHeaderFooter, printBackground, scale });
|
|
123
|
+
return {
|
|
124
|
+
content: [
|
|
125
|
+
{
|
|
126
|
+
type: "resource",
|
|
127
|
+
resource: {
|
|
128
|
+
uri: `data:application/pdf;base64,${res.dataBase64}`,
|
|
129
|
+
mimeType: res.mimeType,
|
|
130
|
+
text: "PDF document generated successfully. Base64 encoded PDF.",
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
],
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
// Agent Bridge MCP - Smart Content, Markdown & Table Extraction Tools (ES Module)
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { jsonResult } from "../core/state.js";
|
|
4
|
+
import { callProfileExtension } from "../core/bridge.js";
|
|
5
|
+
|
|
6
|
+
export function registerExtractionTools(server) {
|
|
7
|
+
server.registerTool(
|
|
8
|
+
"browser_get_markdown",
|
|
9
|
+
{
|
|
10
|
+
description: "Convert an entire webpage or a specific CSS container into clean, structured GitHub-flavored Markdown (stripping navbars, scripts, ads, and style bloat). Extremely token-efficient for LLM context windows.",
|
|
11
|
+
inputSchema: {
|
|
12
|
+
profile: z.string().optional().describe("Target browser profile"),
|
|
13
|
+
tabId: z.number().describe("Target tabId"),
|
|
14
|
+
selector: z.string().optional().describe("Optional container ref or CSS selector to extract markdown from (defaults to entire page body)"),
|
|
15
|
+
includeLinks: z.boolean().optional().describe("Whether to preserve hyperlinks in markdown format (default true)"),
|
|
16
|
+
includeImages: z.boolean().optional().describe("Whether to preserve image alt/src in markdown format (default false)"),
|
|
17
|
+
maxLength: z.number().optional().describe("Maximum character length to return (default 50000)"),
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
async ({ profile, tabId, selector, includeLinks, includeImages, maxLength }) => {
|
|
21
|
+
const res = await callProfileExtension(profile, "get_markdown", {
|
|
22
|
+
tabId,
|
|
23
|
+
selector,
|
|
24
|
+
includeLinks,
|
|
25
|
+
includeImages,
|
|
26
|
+
maxLength,
|
|
27
|
+
});
|
|
28
|
+
return jsonResult(res);
|
|
29
|
+
}
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
server.registerTool(
|
|
33
|
+
"browser_extract_table",
|
|
34
|
+
{
|
|
35
|
+
description: "Automatically detect and extract data from <table> elements or repeating grid layouts into clean structured JSON, CSV, or Markdown tables.",
|
|
36
|
+
inputSchema: {
|
|
37
|
+
profile: z.string().optional().describe("Target browser profile"),
|
|
38
|
+
tabId: z.number().describe("Target tabId"),
|
|
39
|
+
target: z.string().optional().describe("Optional table element ref or selector. If omitted, extracts all tables on the page."),
|
|
40
|
+
format: z.enum(["json", "csv", "markdown"]).optional().describe("Output data format (default 'json')"),
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
async ({ profile, tabId, target, format }) => {
|
|
44
|
+
const res = await callProfileExtension(profile, "extract_table", { tabId, target, format });
|
|
45
|
+
return jsonResult(res);
|
|
46
|
+
}
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
server.registerTool(
|
|
50
|
+
"browser_find_in_page",
|
|
51
|
+
{
|
|
52
|
+
description: "Search for text on the page (matching browser Ctrl+F), returning count of occurrences, surrounding text snippets, and optionally scrolling the matched occurrence into view.",
|
|
53
|
+
inputSchema: {
|
|
54
|
+
profile: z.string().optional().describe("Target browser profile"),
|
|
55
|
+
tabId: z.number().describe("Target tabId"),
|
|
56
|
+
query: z.string().describe("Search term or text to find"),
|
|
57
|
+
caseSensitive: z.boolean().optional().describe("Whether the search is case-sensitive (default false)"),
|
|
58
|
+
matchIndex: z.number().optional().describe("Zero-based index of the specific match to scroll to (default 0)"),
|
|
59
|
+
scrollToMatch: z.boolean().optional().describe("Whether to scroll to the matched element with visual highlight (default true)"),
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
async ({ profile, tabId, query, caseSensitive, matchIndex, scrollToMatch }) => {
|
|
63
|
+
const res = await callProfileExtension(profile, "find_in_page", {
|
|
64
|
+
tabId,
|
|
65
|
+
query,
|
|
66
|
+
caseSensitive,
|
|
67
|
+
matchIndex,
|
|
68
|
+
scrollToMatch,
|
|
69
|
+
});
|
|
70
|
+
return jsonResult(res);
|
|
71
|
+
}
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// Agent Bridge MCP - Media Player, Subtitles & Audio Tools (ES Module)
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { jsonResult } from "../core/state.js";
|
|
4
|
+
import { callProfileExtension } from "../core/bridge.js";
|
|
5
|
+
|
|
6
|
+
export function registerMediaTools(server) {
|
|
7
|
+
server.registerTool(
|
|
8
|
+
"browser_media_control",
|
|
9
|
+
{
|
|
10
|
+
description: "Control audio and video elements on the page: play, pause, toggle, mute, seek, change volume, or adjust playback speed.",
|
|
11
|
+
inputSchema: {
|
|
12
|
+
profile: z.string().optional().describe("Target browser profile"),
|
|
13
|
+
tabId: z.number().describe("Target tabId"),
|
|
14
|
+
action: z.enum(["play", "pause", "toggle", "mute", "unmute", "seek", "set_volume", "set_speed"]).describe("Media action to execute"),
|
|
15
|
+
value: z.union([z.number(), z.string()]).optional().describe("Parameter value (seconds for 'seek', 0.0-1.0 for 'set_volume', 0.25-4.0 for 'set_speed')"),
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
async ({ profile, tabId, action, value }) => {
|
|
19
|
+
const res = await callProfileExtension(profile, "media_control", { tabId, action, value });
|
|
20
|
+
return jsonResult(res);
|
|
21
|
+
}
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
server.registerTool(
|
|
25
|
+
"browser_mute_tab",
|
|
26
|
+
{
|
|
27
|
+
description: "Mute or unmute all audio output for an entire browser tab.",
|
|
28
|
+
inputSchema: {
|
|
29
|
+
profile: z.string().optional().describe("Target browser profile"),
|
|
30
|
+
tabId: z.number().describe("Target tabId"),
|
|
31
|
+
muted: z.boolean().describe("Whether the tab should be muted (true) or unmuted (false)"),
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
async ({ profile, tabId, muted }) => {
|
|
35
|
+
const res = await callProfileExtension(profile, "mute_tab", { tabId, muted });
|
|
36
|
+
return jsonResult(res);
|
|
37
|
+
}
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
server.registerTool(
|
|
41
|
+
"browser_get_subtitles",
|
|
42
|
+
{
|
|
43
|
+
description: "Extract current live captions, active subtitles, and text tracks from video players on the page (YouTube, Coursera, video players).",
|
|
44
|
+
inputSchema: {
|
|
45
|
+
profile: z.string().optional().describe("Target browser profile"),
|
|
46
|
+
tabId: z.number().describe("Target tabId"),
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
async ({ profile, tabId }) => {
|
|
50
|
+
const res = await callProfileExtension(profile, "get_subtitles", { tabId });
|
|
51
|
+
return jsonResult(res);
|
|
52
|
+
}
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
// Agent Bridge MCP - Navigation Tools (ES Module)
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { jsonResult } from "../core/state.js";
|
|
4
|
+
import { callProfileExtension } from "../core/bridge.js";
|
|
5
|
+
|
|
6
|
+
export function registerNavigationTools(server) {
|
|
7
|
+
server.registerTool(
|
|
8
|
+
"browser_navigate",
|
|
9
|
+
{
|
|
10
|
+
description: "Navigate an existing tab or open a new one to a specific URL with customizable ready wait conditions.",
|
|
11
|
+
inputSchema: {
|
|
12
|
+
profile: z.string().optional().describe("Target browser profile"),
|
|
13
|
+
tabId: z.number().optional().describe("Existing tabId to navigate. Omit to open and navigate a new tab."),
|
|
14
|
+
url: z.string().describe("Target URL to navigate to"),
|
|
15
|
+
waitFor: z.enum(["load", "domcontentloaded", "none"]).optional().describe("Wait condition (default 'load')"),
|
|
16
|
+
timeoutMs: z.number().optional().describe("Timeout in milliseconds (default 15000)"),
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
async ({ profile, tabId, url, waitFor, timeoutMs }) => {
|
|
20
|
+
const res = await callProfileExtension(profile, "navigate_or_open", { tabId, url, waitFor, timeoutMs });
|
|
21
|
+
return jsonResult(res);
|
|
22
|
+
}
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
server.registerTool(
|
|
26
|
+
"browser_go_back",
|
|
27
|
+
{
|
|
28
|
+
description: "Navigate back in browser history for a specific tab.",
|
|
29
|
+
inputSchema: {
|
|
30
|
+
profile: z.string().optional().describe("Target browser profile"),
|
|
31
|
+
tabId: z.number().describe("The ID of the tab to navigate back"),
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
async ({ profile, tabId }) => {
|
|
35
|
+
const res = await callProfileExtension(profile, "go_back", { tabId });
|
|
36
|
+
return jsonResult(res);
|
|
37
|
+
}
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
server.registerTool(
|
|
41
|
+
"browser_go_forward",
|
|
42
|
+
{
|
|
43
|
+
description: "Navigate forward in browser history for a specific tab.",
|
|
44
|
+
inputSchema: {
|
|
45
|
+
profile: z.string().optional().describe("Target browser profile"),
|
|
46
|
+
tabId: z.number().describe("The ID of the tab to navigate forward"),
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
async ({ profile, tabId }) => {
|
|
50
|
+
const res = await callProfileExtension(profile, "go_forward", { tabId });
|
|
51
|
+
return jsonResult(res);
|
|
52
|
+
}
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
server.registerTool(
|
|
56
|
+
"browser_reload",
|
|
57
|
+
{
|
|
58
|
+
description: "Reload a specific tab with optional cache bypass.",
|
|
59
|
+
inputSchema: {
|
|
60
|
+
profile: z.string().optional().describe("Target browser profile"),
|
|
61
|
+
tabId: z.number().describe("Target tabId"),
|
|
62
|
+
ignoreCache: z.boolean().optional().describe("Whether to hard reload bypassing cache (default false)"),
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
async ({ profile, tabId, ignoreCache }) => {
|
|
66
|
+
const res = await callProfileExtension(profile, "reload_tab", { tabId, ignoreCache });
|
|
67
|
+
return jsonResult(res);
|
|
68
|
+
}
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
// Agent Bridge MCP - Network, Cookies, Storage & Routing Tools (ES Module)
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { jsonResult } from "../core/state.js";
|
|
4
|
+
import { callProfileExtension } from "../core/bridge.js";
|
|
5
|
+
|
|
6
|
+
export function registerNetworkTools(server) {
|
|
7
|
+
server.registerTool(
|
|
8
|
+
"browser_list_network_requests",
|
|
9
|
+
{
|
|
10
|
+
description: "List captured network requests for a tab (status, method, url, resourceType, mimeType, timestamp).",
|
|
11
|
+
inputSchema: {
|
|
12
|
+
profile: z.string().optional().describe("Target browser profile"),
|
|
13
|
+
tabId: z.number().describe("Target tabId"),
|
|
14
|
+
limit: z.number().optional().describe("Max requests to return (default 50)"),
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
async ({ profile, tabId, limit }) => {
|
|
18
|
+
const res = await callProfileExtension(profile, "list_network_requests", { tabId, limit });
|
|
19
|
+
return jsonResult(res);
|
|
20
|
+
}
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
server.registerTool(
|
|
24
|
+
"browser_get_network_request",
|
|
25
|
+
{
|
|
26
|
+
description: "Get full details and request/response headers for a recorded requestId.",
|
|
27
|
+
inputSchema: {
|
|
28
|
+
profile: z.string().optional().describe("Target browser profile"),
|
|
29
|
+
tabId: z.number().describe("Target tabId"),
|
|
30
|
+
requestId: z.string().describe("The requestId returned by browser_list_network_requests"),
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
async ({ profile, tabId, requestId }) => {
|
|
34
|
+
const res = await callProfileExtension(profile, "get_network_request", { tabId, requestId });
|
|
35
|
+
return jsonResult(res);
|
|
36
|
+
}
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
server.registerTool(
|
|
40
|
+
"browser_get_network_body",
|
|
41
|
+
{
|
|
42
|
+
description: "Fetch the raw response body of a network request via CDP Network.getResponseBody.",
|
|
43
|
+
inputSchema: {
|
|
44
|
+
profile: z.string().optional().describe("Target browser profile"),
|
|
45
|
+
tabId: z.number().describe("Target tabId"),
|
|
46
|
+
requestId: z.string().describe("The requestId"),
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
async ({ profile, tabId, requestId }) => {
|
|
50
|
+
const res = await callProfileExtension(profile, "get_network_body", { tabId, requestId });
|
|
51
|
+
return jsonResult(res);
|
|
52
|
+
}
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
server.registerTool(
|
|
56
|
+
"browser_get_cookies",
|
|
57
|
+
{
|
|
58
|
+
description: "Retrieve cookies for the browser profile or filtered by URLs.",
|
|
59
|
+
inputSchema: {
|
|
60
|
+
profile: z.string().optional().describe("Target browser profile"),
|
|
61
|
+
urls: z.union([z.string(), z.array(z.string())]).optional().describe("URL(s) to filter cookies by"),
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
async ({ profile, urls }) => {
|
|
65
|
+
const res = await callProfileExtension(profile, "get_cookies", { urls });
|
|
66
|
+
return jsonResult(res);
|
|
67
|
+
}
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
server.registerTool(
|
|
71
|
+
"browser_set_cookie",
|
|
72
|
+
{
|
|
73
|
+
description: "Set a cookie in the active browser profile.",
|
|
74
|
+
inputSchema: {
|
|
75
|
+
profile: z.string().optional().describe("Target browser profile"),
|
|
76
|
+
url: z.string().describe("The request-URI with which the cookie will be associated"),
|
|
77
|
+
name: z.string().describe("Cookie name"),
|
|
78
|
+
value: z.string().describe("Cookie value"),
|
|
79
|
+
domain: z.string().optional().describe("Cookie domain"),
|
|
80
|
+
path: z.string().optional().describe("Cookie path"),
|
|
81
|
+
secure: z.boolean().optional().describe("HTTPS only"),
|
|
82
|
+
httpOnly: z.boolean().optional().describe("HttpOnly flag"),
|
|
83
|
+
sameSite: z.enum(["unspecified", "no_restriction", "lax", "strict"]).optional(),
|
|
84
|
+
expirationDate: z.number().optional().describe("Expiration timestamp in seconds"),
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
async ({ profile, url, name, value, domain, path, secure, httpOnly, sameSite, expirationDate }) => {
|
|
88
|
+
const res = await callProfileExtension(profile, "set_cookie", {
|
|
89
|
+
url,
|
|
90
|
+
name,
|
|
91
|
+
value,
|
|
92
|
+
domain,
|
|
93
|
+
path,
|
|
94
|
+
secure,
|
|
95
|
+
httpOnly,
|
|
96
|
+
sameSite,
|
|
97
|
+
expirationDate,
|
|
98
|
+
});
|
|
99
|
+
return jsonResult(res);
|
|
100
|
+
}
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
server.registerTool(
|
|
104
|
+
"browser_clear_cookies",
|
|
105
|
+
{
|
|
106
|
+
description: "Clear all cookies stored in the current browser profile.",
|
|
107
|
+
inputSchema: {
|
|
108
|
+
profile: z.string().optional().describe("Target browser profile"),
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
async ({ profile }) => {
|
|
112
|
+
const res = await callProfileExtension(profile, "clear_cookies");
|
|
113
|
+
return jsonResult(res);
|
|
114
|
+
}
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
server.registerTool(
|
|
118
|
+
"browser_storage",
|
|
119
|
+
{
|
|
120
|
+
description: "Read, write, or clear localStorage or sessionStorage in a tab.",
|
|
121
|
+
inputSchema: {
|
|
122
|
+
profile: z.string().optional().describe("Target browser profile"),
|
|
123
|
+
tabId: z.number().describe("Target tabId"),
|
|
124
|
+
type: z.enum(["local", "session"]).optional().describe("Storage type (default 'local')"),
|
|
125
|
+
action: z.enum(["get", "set", "remove", "clear"]).optional().describe("Storage action (default 'get')"),
|
|
126
|
+
key: z.string().optional().describe("Storage item key"),
|
|
127
|
+
value: z.any().optional().describe("Value to set"),
|
|
128
|
+
},
|
|
129
|
+
},
|
|
130
|
+
async ({ profile, tabId, type, action, key, value }) => {
|
|
131
|
+
const res = await callProfileExtension(profile, "storage", { tabId, type, action, key, value });
|
|
132
|
+
return jsonResult(res);
|
|
133
|
+
}
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
server.registerTool(
|
|
137
|
+
"browser_block_urls",
|
|
138
|
+
{
|
|
139
|
+
description: "Block network requests matching specific URL wildcard patterns (e.g. ['*google-analytics*', '*ads*', '*.png']) via CDP Network.setBlockedURLs.",
|
|
140
|
+
inputSchema: {
|
|
141
|
+
profile: z.string().optional().describe("Target browser profile"),
|
|
142
|
+
tabId: z.number().describe("Target tabId"),
|
|
143
|
+
patterns: z.union([z.string(), z.array(z.string())]).optional().describe("URL pattern(s) with wildcards to block"),
|
|
144
|
+
clear: z.boolean().optional().describe("If true, removes all URL blocking rules on this tab"),
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
async ({ profile, tabId, patterns, clear }) => {
|
|
148
|
+
const res = await callProfileExtension(profile, "block_urls", { tabId, patterns, clear });
|
|
149
|
+
return jsonResult(res);
|
|
150
|
+
}
|
|
151
|
+
);
|
|
152
|
+
|
|
153
|
+
server.registerTool(
|
|
154
|
+
"browser_set_extra_headers",
|
|
155
|
+
{
|
|
156
|
+
description: "Inject custom HTTP headers (e.g. Authorization, custom API keys, mock cookies) into all outgoing HTTP requests on a tab via CDP Network.setExtraHTTPHeaders.",
|
|
157
|
+
inputSchema: {
|
|
158
|
+
profile: z.string().optional().describe("Target browser profile"),
|
|
159
|
+
tabId: z.number().describe("Target tabId"),
|
|
160
|
+
headers: z.record(z.string()).optional().describe("Key-value dictionary of HTTP header names and values to inject"),
|
|
161
|
+
clear: z.boolean().optional().describe("If true, clears all custom headers on this tab"),
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
async ({ profile, tabId, headers, clear }) => {
|
|
165
|
+
const res = await callProfileExtension(profile, "set_extra_headers", { tabId, headers, clear });
|
|
166
|
+
return jsonResult(res);
|
|
167
|
+
}
|
|
168
|
+
);
|
|
169
|
+
|
|
170
|
+
server.registerTool(
|
|
171
|
+
"browser_mock_route",
|
|
172
|
+
{
|
|
173
|
+
description: "Intercept HTTP network requests matching a URL pattern and return custom mock status codes, headers, and response bodies via CDP Fetch interception.",
|
|
174
|
+
inputSchema: {
|
|
175
|
+
profile: z.string().optional().describe("Target browser profile"),
|
|
176
|
+
tabId: z.number().describe("Target tabId"),
|
|
177
|
+
urlPattern: z.string().optional().describe("URL pattern to intercept (e.g. '*api/v1/user*', 'https://api.example.com/*')"),
|
|
178
|
+
responseBody: z.any().optional().describe("Mock response body string or JSON object"),
|
|
179
|
+
status: z.number().optional().describe("HTTP response status code (default 200)"),
|
|
180
|
+
headers: z.record(z.string()).optional().describe("Custom HTTP response headers"),
|
|
181
|
+
clear: z.boolean().optional().describe("If true, disables Fetch interception and clears all mock routes for this tab"),
|
|
182
|
+
},
|
|
183
|
+
},
|
|
184
|
+
async ({ profile, tabId, urlPattern, responseBody, status, headers, clear }) => {
|
|
185
|
+
const res = await callProfileExtension(profile, "mock_route", {
|
|
186
|
+
tabId,
|
|
187
|
+
urlPattern,
|
|
188
|
+
responseBody,
|
|
189
|
+
status,
|
|
190
|
+
headers,
|
|
191
|
+
clear,
|
|
192
|
+
});
|
|
193
|
+
return jsonResult(res);
|
|
194
|
+
}
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// Agent Bridge MCP - Tool Registry Aggregator (ES Module)
|
|
2
|
+
import { registerTabTools } from "./tab-tools.js";
|
|
3
|
+
import { registerNavigationTools } from "./navigation-tools.js";
|
|
4
|
+
import { registerDomTools } from "./dom-tools.js";
|
|
5
|
+
import { registerExtractionTools } from "./extraction-tools.js";
|
|
6
|
+
import { registerNetworkTools } from "./network-tools.js";
|
|
7
|
+
import { registerBrowserDataTools } from "./browser-data-tools.js";
|
|
8
|
+
import { registerMediaTools } from "./media-tools.js";
|
|
9
|
+
import { registerEmulationTools } from "./emulation-tools.js";
|
|
10
|
+
import { registerDiagnosticTools } from "./diagnostic-tools.js";
|
|
11
|
+
|
|
12
|
+
export function registerAllTools(server) {
|
|
13
|
+
registerTabTools(server);
|
|
14
|
+
registerNavigationTools(server);
|
|
15
|
+
registerDomTools(server);
|
|
16
|
+
registerExtractionTools(server);
|
|
17
|
+
registerNetworkTools(server);
|
|
18
|
+
registerBrowserDataTools(server);
|
|
19
|
+
registerMediaTools(server);
|
|
20
|
+
registerEmulationTools(server);
|
|
21
|
+
registerDiagnosticTools(server);
|
|
22
|
+
}
|
|
23
|
+
|