Skip to content

Commit 2ef71b2

Browse files
committed
feat: Enable access to browser storage (cookies, localStorage, sessionStorage)
- Add the ability to retrieve and analyze cookies, localStorage, and sessionStorage. - Implement new MCP tools and API endpoints for accessing browser storage data. - Enhance the Chrome extension to capture browser storage.
1 parent 8e215b6 commit 2ef71b2

File tree

6 files changed

+377
-1
lines changed

6 files changed

+377
-1
lines changed

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ If you have any questions or issues, feel free to open an issue ticket! And if y
2727

2828
There are three core components all used to capture and analyze browser data:
2929

30-
1. **Chrome Extension**: A browser extension that captures screenshots, console logs, network activity and DOM elements.
30+
1. **Chrome Extension**: A browser extension that captures screenshots, console logs, network activity, DOM elements, and browser storage (cookies, localStorage, sessionStorage).
3131
2. **Node Server**: An intermediary server that facilitates communication between the Chrome extension and any instance of an MCP server.
3232
3. **MCP Server**: A Model Context Protocol server that provides standardized tools for AI clients to interact with the browser.
3333

@@ -54,13 +54,15 @@ All consumers of the BrowserTools MCP Server interface with the same NodeJS API
5454
- Tracks selected DOM elements
5555
- Sends all logs and current element to the BrowserTools Connector
5656
- Connects to Websocket server to capture/send screenshots
57+
- Retrieves cookies, localStorage, and sessionStorage data
5758
- Allows user to configure token/truncation limits + screenshot folder path
5859

5960
#### Node Server
6061

6162
- Acts as middleware between the Chrome extension and MCP server
6263
- Receives logs and currently selected element from Chrome extension
6364
- Processes requests from MCP server to capture logs, screenshot or current element
65+
- Retrieves browser storage data (cookies, localStorage, sessionStorage)
6466
- Sends Websocket command to the Chrome extension for capturing a screenshot
6567
- Intelligently truncates strings and # of duplicate objects in logs to avoid token limits
6668
- Removes cookies and sensitive headers to avoid sending to LLMs in MCP clients
@@ -85,6 +87,7 @@ Once installed and configured, the system allows any compatible MCP client to:
8587
- Capture network traffic
8688
- Take screenshots
8789
- Analyze selected elements
90+
- Access browser storage (cookies, localStorage, sessionStorage)
8891
- Wipe logs stored in our MCP server
8992

9093
## Compatibility

browser-tools-mcp/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ A Model Context Protocol (MCP) server that provides AI-powered browser tools int
99
- Network request analysis
1010
- Screenshot capture capabilities
1111
- Element selection and inspection
12+
- Browser storage access (cookies, localStorage, sessionStorage)
1213
- Real-time browser state monitoring
1314

1415
## Installation
@@ -44,6 +45,7 @@ npx @agentdeskai/browser-tools-mcp
4445
- Screenshot capture
4546
- Element selection
4647
- Browser state analysis
48+
- Browser storage access
4749

4850
## MCP Functions
4951

@@ -55,6 +57,9 @@ The server provides the following MCP functions:
5557
- `mcp_getNetworkSuccess` - Get successful network requests
5658
- `mcp_getNetworkLogs` - Get all network logs
5759
- `mcp_getSelectedElement` - Get the currently selected DOM element
60+
- `mcp_getCookies` - Get cookies from the current page
61+
- `mcp_getLocalStorage` - Get localStorage data
62+
- `mcp_getSessionStorage` - Get sessionStorage data
5863

5964
## Integration
6065

browser-tools-mcp/mcp-server.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,48 @@ server.tool("wipeLogs", "Wipe all browser logs from memory", async () => {
190190
};
191191
});
192192

193+
// Add new tool for getting cookies
194+
server.tool("getCookies", "Get all cookies from the browser", async () => {
195+
const response = await fetch(`http://127.0.0.1:${PORT}/cookies`);
196+
const json = await response.json();
197+
return {
198+
content: [
199+
{
200+
type: "text",
201+
text: JSON.stringify(json, null, 2),
202+
},
203+
],
204+
};
205+
});
206+
207+
// Add new tool for getting localStorage
208+
server.tool("getLocalStorage", "Get all localStorage items", async () => {
209+
const response = await fetch(`http://127.0.0.1:${PORT}/local-storage`);
210+
const json = await response.json();
211+
return {
212+
content: [
213+
{
214+
type: "text",
215+
text: JSON.stringify(json, null, 2),
216+
},
217+
],
218+
};
219+
});
220+
221+
// Add new tool for getting sessionStorage
222+
server.tool("getSessionStorage", "Get all sessionStorage items", async () => {
223+
const response = await fetch(`http://127.0.0.1:${PORT}/session-storage`);
224+
const json = await response.json();
225+
return {
226+
content: [
227+
{
228+
type: "text",
229+
text: JSON.stringify(json, null, 2),
230+
},
231+
],
232+
};
233+
});
234+
193235
// Start receiving messages on stdio
194236
(async () => {
195237
try {

browser-tools-server/README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ A powerful browser tools server for capturing and managing browser events, logs,
88
- Network request monitoring
99
- Screenshot capture
1010
- Element selection tracking
11+
- Browser storage access (cookies, localStorage, sessionStorage)
1112
- WebSocket real-time communication
1213
- Configurable log limits and settings
1314

@@ -44,6 +45,9 @@ npx @agentdeskai/browser-tools-server
4445
- `/all-xhr` - Get all network requests
4546
- `/screenshot` - Capture screenshots
4647
- `/selected-element` - Get currently selected DOM element
48+
- `/cookies` - Get cookies from the current page
49+
- `/local-storage` - Get localStorage data
50+
- `/session-storage` - Get sessionStorage data
4751

4852
## API Documentation
4953

@@ -55,6 +59,9 @@ npx @agentdeskai/browser-tools-server
5559
- `GET /network-success` - Returns recent successful network requests
5660
- `GET /all-xhr` - Returns all recent network requests
5761
- `GET /selected-element` - Returns the currently selected DOM element
62+
- `GET /cookies` - Returns cookies from the current page
63+
- `GET /local-storage` - Returns localStorage data
64+
- `GET /session-storage` - Returns sessionStorage data
5865

5966
### POST Endpoints
6067

browser-tools-server/browser-connector.ts

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,24 @@ export class BrowserConnector {
415415
);
416416
screenshotCallbacks.clear(); // Clear all callbacks
417417
}
418+
}
419+
// Handle cookies data
420+
else if (data.type === "cookies-data") {
421+
console.log("Received cookies data from extension");
422+
// Store the cookies data temporarily
423+
this.lastCookiesData = data.cookies;
424+
}
425+
// Handle localStorage data
426+
else if (data.type === "local-storage-data") {
427+
console.log("Received localStorage data from extension");
428+
// Store the localStorage data temporarily
429+
this.lastLocalStorageData = data.storage;
430+
}
431+
// Handle sessionStorage data
432+
else if (data.type === "session-storage-data") {
433+
console.log("Received sessionStorage data from extension");
434+
// Store the sessionStorage data temporarily
435+
this.lastSessionStorageData = data.storage;
418436
} else {
419437
console.log("Unhandled message type:", data.type);
420438
}
@@ -484,6 +502,191 @@ export class BrowserConnector {
484502
}
485503
}
486504
);
505+
506+
// Add endpoint for cookies
507+
this.app.get(
508+
"/cookies",
509+
(req: express.Request, res: express.Response): void => {
510+
console.log("Browser Connector: Received request to /cookies endpoint");
511+
512+
if (!this.activeConnection) {
513+
console.log("Browser Connector: No active WebSocket connection to Chrome extension");
514+
res.status(503).json({ error: "Chrome extension not connected" });
515+
return;
516+
}
517+
518+
// Request cookies data from extension
519+
this.getCookies()
520+
.then((cookiesData) => {
521+
console.log("Browser Connector: Received cookies data from extension");
522+
res.json(cookiesData);
523+
})
524+
.catch((error) => {
525+
const errorMessage = error instanceof Error ? error.message : String(error);
526+
console.error("Browser Connector: Error getting cookies:", errorMessage);
527+
res.status(500).json({ error: errorMessage });
528+
});
529+
}
530+
);
531+
532+
// Add endpoint for localStorage
533+
this.app.get(
534+
"/local-storage",
535+
(req: express.Request, res: express.Response): void => {
536+
console.log("Browser Connector: Received request to /local-storage endpoint");
537+
538+
if (!this.activeConnection) {
539+
console.log("Browser Connector: No active WebSocket connection to Chrome extension");
540+
res.status(503).json({ error: "Chrome extension not connected" });
541+
return;
542+
}
543+
544+
// Request localStorage data from extension
545+
this.getLocalStorage()
546+
.then((storageData) => {
547+
console.log("Browser Connector: Received localStorage data from extension");
548+
res.json(storageData);
549+
})
550+
.catch((error) => {
551+
const errorMessage = error instanceof Error ? error.message : String(error);
552+
console.error("Browser Connector: Error getting localStorage:", errorMessage);
553+
res.status(500).json({ error: errorMessage });
554+
});
555+
}
556+
);
557+
558+
// Add endpoint for sessionStorage
559+
this.app.get(
560+
"/session-storage",
561+
(req: express.Request, res: express.Response): void => {
562+
console.log("Browser Connector: Received request to /session-storage endpoint");
563+
564+
if (!this.activeConnection) {
565+
console.log("Browser Connector: No active WebSocket connection to Chrome extension");
566+
res.status(503).json({ error: "Chrome extension not connected" });
567+
return;
568+
}
569+
570+
// Request sessionStorage data from extension
571+
this.getSessionStorage()
572+
.then((storageData) => {
573+
console.log("Browser Connector: Received sessionStorage data from extension");
574+
res.json(storageData);
575+
})
576+
.catch((error) => {
577+
const errorMessage = error instanceof Error ? error.message : String(error);
578+
console.error("Browser Connector: Error getting sessionStorage:", errorMessage);
579+
res.status(500).json({ error: errorMessage });
580+
});
581+
}
582+
);
583+
}
584+
585+
// Add properties to store the latest data
586+
private lastCookiesData: any = null;
587+
private lastLocalStorageData: any = null;
588+
private lastSessionStorageData: any = null;
589+
590+
// Add method to get cookies
591+
private getCookies(): Promise<any> {
592+
if (!this.activeConnection) {
593+
throw new Error("Chrome extension not connected");
594+
}
595+
596+
// Reset the stored data
597+
this.lastCookiesData = null;
598+
599+
// Create a promise that will resolve when we get the cookies data
600+
const cookiesPromise = new Promise<any>((resolve, reject) => {
601+
// Set timeout to reject if we don't get a response
602+
const timeout = setTimeout(() => {
603+
reject(new Error("Timeout waiting for cookies data from Chrome extension"));
604+
}, 5000);
605+
606+
// Set up an interval to check for data
607+
const checkInterval = setInterval(() => {
608+
if (this.lastCookiesData) {
609+
clearTimeout(timeout);
610+
clearInterval(checkInterval);
611+
resolve(this.lastCookiesData);
612+
}
613+
}, 100);
614+
});
615+
616+
// Send request to extension
617+
console.log("Browser Connector: Requesting cookies data from extension");
618+
this.activeConnection.send(JSON.stringify({ type: "get-cookies" }));
619+
620+
// Wait for data
621+
return cookiesPromise;
622+
}
623+
624+
// Add method to get localStorage
625+
private getLocalStorage(): Promise<any> {
626+
if (!this.activeConnection) {
627+
throw new Error("Chrome extension not connected");
628+
}
629+
630+
// Reset the stored data
631+
this.lastLocalStorageData = null;
632+
633+
// Create a promise that will resolve when we get the localStorage data
634+
const storagePromise = new Promise<any>((resolve, reject) => {
635+
// Set timeout to reject if we don't get a response
636+
const timeout = setTimeout(() => {
637+
reject(new Error("Timeout waiting for localStorage data from Chrome extension"));
638+
}, 5000);
639+
640+
// Set up an interval to check for data
641+
const checkInterval = setInterval(() => {
642+
if (this.lastLocalStorageData) {
643+
clearTimeout(timeout);
644+
clearInterval(checkInterval);
645+
resolve(this.lastLocalStorageData);
646+
}
647+
}, 100);
648+
});
649+
650+
// Send request to extension
651+
console.log("Browser Connector: Requesting localStorage data from extension");
652+
this.activeConnection.send(JSON.stringify({ type: "get-local-storage" }));
653+
654+
// Wait for data
655+
return storagePromise;
656+
}
657+
658+
// Add method to get sessionStorage
659+
private getSessionStorage(): Promise<any> {
660+
if (!this.activeConnection) {
661+
throw new Error("Chrome extension not connected");
662+
}
663+
664+
// Reset the stored data
665+
this.lastSessionStorageData = null;
666+
667+
// Create a promise that will resolve when we get the sessionStorage data
668+
const storagePromise = new Promise<any>((resolve, reject) => {
669+
// Set timeout to reject if we don't get a response
670+
const timeout = setTimeout(() => {
671+
reject(new Error("Timeout waiting for sessionStorage data from Chrome extension"));
672+
}, 5000);
673+
674+
// Set up an interval to check for data
675+
const checkInterval = setInterval(() => {
676+
if (this.lastSessionStorageData) {
677+
clearTimeout(timeout);
678+
clearInterval(checkInterval);
679+
resolve(this.lastSessionStorageData);
680+
}
681+
}, 100);
682+
});
683+
684+
// Send request to extension
685+
console.log("Browser Connector: Requesting sessionStorage data from extension");
686+
this.activeConnection.send(JSON.stringify({ type: "get-session-storage" }));
687+
688+
// Wait for data
689+
return storagePromise;
487690
}
488691

489692
private async handleScreenshot(req: express.Request, res: express.Response) {

0 commit comments

Comments
 (0)