Skip to content

Commit 9ae43f6

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 66b7fe2 commit 9ae43f6

File tree

6 files changed

+422
-4
lines changed

6 files changed

+422
-4
lines changed

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ Read our [docs](https://browsertools.agentdesk.ai/) for the full installation, q
1010

1111
There are three core components all used to capture and analyze browser data:
1212

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

@@ -37,13 +37,15 @@ All consumers of the BrowserTools MCP Server interface with the same NodeJS API
3737
- Tracks selected DOM elements
3838
- Sends all logs and current element to the BrowserTools Connector
3939
- Connects to Websocket server to capture/send screenshots
40+
- Retrieves cookies, localStorage, and sessionStorage data
4041
- Allows user to configure token/truncation limits + screenshot folder path
4142

4243
#### Node Server
4344

4445
- Acts as middleware between the Chrome extension and MCP server
4546
- Receives logs and currently selected element from Chrome extension
4647
- Processes requests from MCP server to capture logs, screenshot or current element
48+
- Retrieves browser storage data (cookies, localStorage, sessionStorage)
4749
- Sends Websocket command to the Chrome extension for capturing a screenshot
4850
- Intelligently truncates strings and # of duplicate objects in logs to avoid token limits
4951
- Removes cookies and sensitive headers to avoid sending to LLMs in MCP clients
@@ -68,6 +70,7 @@ Once installed and configured, the system allows any compatible MCP client to:
6870
- Capture network traffic
6971
- Take screenshots
7072
- Analyze selected elements
73+
- Access browser storage (cookies, localStorage, sessionStorage)
7174
- Wipe logs stored in our MCP server
7275

7376
## 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
@@ -339,6 +339,48 @@ server.tool("wipeLogs", "Wipe all browser logs from memory", async () => {
339339
});
340340
});
341341

342+
// Add new tool for getting cookies
343+
server.tool("getCookies", "Get all cookies from the browser", async () => {
344+
const response = await fetch(`http://127.0.0.1:${PORT}/cookies`);
345+
const json = await response.json();
346+
return {
347+
content: [
348+
{
349+
type: "text",
350+
text: JSON.stringify(json, null, 2),
351+
},
352+
],
353+
};
354+
});
355+
356+
// Add new tool for getting localStorage
357+
server.tool("getLocalStorage", "Get all localStorage items", async () => {
358+
const response = await fetch(`http://127.0.0.1:${PORT}/local-storage`);
359+
const json = await response.json();
360+
return {
361+
content: [
362+
{
363+
type: "text",
364+
text: JSON.stringify(json, null, 2),
365+
},
366+
],
367+
};
368+
});
369+
370+
// Add new tool for getting sessionStorage
371+
server.tool("getSessionStorage", "Get all sessionStorage items", async () => {
372+
const response = await fetch(`http://127.0.0.1:${PORT}/session-storage`);
373+
const json = await response.json();
374+
return {
375+
content: [
376+
{
377+
type: "text",
378+
text: JSON.stringify(json, null, 2),
379+
},
380+
],
381+
};
382+
});
383+
342384
// Start receiving messages on stdio
343385
(async () => {
344386
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
@@ -596,6 +596,24 @@ export class BrowserConnector {
596596
);
597597
screenshotCallbacks.clear(); // Clear all callbacks
598598
}
599+
}
600+
// Handle cookies data
601+
else if (data.type === "cookies-data") {
602+
console.log("Received cookies data from extension");
603+
// Store the cookies data temporarily
604+
this.lastCookiesData = data.cookies;
605+
}
606+
// Handle localStorage data
607+
else if (data.type === "local-storage-data") {
608+
console.log("Received localStorage data from extension");
609+
// Store the localStorage data temporarily
610+
this.lastLocalStorageData = data.storage;
611+
}
612+
// Handle sessionStorage data
613+
else if (data.type === "session-storage-data") {
614+
console.log("Received sessionStorage data from extension");
615+
// Store the sessionStorage data temporarily
616+
this.lastSessionStorageData = data.storage;
599617
} else {
600618
console.log("Unhandled message type:", data.type);
601619
}
@@ -665,6 +683,191 @@ export class BrowserConnector {
665683
}
666684
}
667685
);
686+
687+
// Add endpoint for cookies
688+
this.app.get(
689+
"/cookies",
690+
(req: express.Request, res: express.Response): void => {
691+
console.log("Browser Connector: Received request to /cookies endpoint");
692+
693+
if (!this.activeConnection) {
694+
console.log("Browser Connector: No active WebSocket connection to Chrome extension");
695+
res.status(503).json({ error: "Chrome extension not connected" });
696+
return;
697+
}
698+
699+
// Request cookies data from extension
700+
this.getCookies()
701+
.then((cookiesData) => {
702+
console.log("Browser Connector: Received cookies data from extension");
703+
res.json(cookiesData);
704+
})
705+
.catch((error) => {
706+
const errorMessage = error instanceof Error ? error.message : String(error);
707+
console.error("Browser Connector: Error getting cookies:", errorMessage);
708+
res.status(500).json({ error: errorMessage });
709+
});
710+
}
711+
);
712+
713+
// Add endpoint for localStorage
714+
this.app.get(
715+
"/local-storage",
716+
(req: express.Request, res: express.Response): void => {
717+
console.log("Browser Connector: Received request to /local-storage endpoint");
718+
719+
if (!this.activeConnection) {
720+
console.log("Browser Connector: No active WebSocket connection to Chrome extension");
721+
res.status(503).json({ error: "Chrome extension not connected" });
722+
return;
723+
}
724+
725+
// Request localStorage data from extension
726+
this.getLocalStorage()
727+
.then((storageData) => {
728+
console.log("Browser Connector: Received localStorage data from extension");
729+
res.json(storageData);
730+
})
731+
.catch((error) => {
732+
const errorMessage = error instanceof Error ? error.message : String(error);
733+
console.error("Browser Connector: Error getting localStorage:", errorMessage);
734+
res.status(500).json({ error: errorMessage });
735+
});
736+
}
737+
);
738+
739+
// Add endpoint for sessionStorage
740+
this.app.get(
741+
"/session-storage",
742+
(req: express.Request, res: express.Response): void => {
743+
console.log("Browser Connector: Received request to /session-storage endpoint");
744+
745+
if (!this.activeConnection) {
746+
console.log("Browser Connector: No active WebSocket connection to Chrome extension");
747+
res.status(503).json({ error: "Chrome extension not connected" });
748+
return;
749+
}
750+
751+
// Request sessionStorage data from extension
752+
this.getSessionStorage()
753+
.then((storageData) => {
754+
console.log("Browser Connector: Received sessionStorage data from extension");
755+
res.json(storageData);
756+
})
757+
.catch((error) => {
758+
const errorMessage = error instanceof Error ? error.message : String(error);
759+
console.error("Browser Connector: Error getting sessionStorage:", errorMessage);
760+
res.status(500).json({ error: errorMessage });
761+
});
762+
}
763+
);
764+
}
765+
766+
// Add properties to store the latest data
767+
private lastCookiesData: any = null;
768+
private lastLocalStorageData: any = null;
769+
private lastSessionStorageData: any = null;
770+
771+
// Add method to get cookies
772+
private getCookies(): Promise<any> {
773+
if (!this.activeConnection) {
774+
throw new Error("Chrome extension not connected");
775+
}
776+
777+
// Reset the stored data
778+
this.lastCookiesData = null;
779+
780+
// Create a promise that will resolve when we get the cookies data
781+
const cookiesPromise = new Promise<any>((resolve, reject) => {
782+
// Set timeout to reject if we don't get a response
783+
const timeout = setTimeout(() => {
784+
reject(new Error("Timeout waiting for cookies data from Chrome extension"));
785+
}, 5000);
786+
787+
// Set up an interval to check for data
788+
const checkInterval = setInterval(() => {
789+
if (this.lastCookiesData) {
790+
clearTimeout(timeout);
791+
clearInterval(checkInterval);
792+
resolve(this.lastCookiesData);
793+
}
794+
}, 100);
795+
});
796+
797+
// Send request to extension
798+
console.log("Browser Connector: Requesting cookies data from extension");
799+
this.activeConnection.send(JSON.stringify({ type: "get-cookies" }));
800+
801+
// Wait for data
802+
return cookiesPromise;
803+
}
804+
805+
// Add method to get localStorage
806+
private getLocalStorage(): Promise<any> {
807+
if (!this.activeConnection) {
808+
throw new Error("Chrome extension not connected");
809+
}
810+
811+
// Reset the stored data
812+
this.lastLocalStorageData = null;
813+
814+
// Create a promise that will resolve when we get the localStorage data
815+
const storagePromise = new Promise<any>((resolve, reject) => {
816+
// Set timeout to reject if we don't get a response
817+
const timeout = setTimeout(() => {
818+
reject(new Error("Timeout waiting for localStorage data from Chrome extension"));
819+
}, 5000);
820+
821+
// Set up an interval to check for data
822+
const checkInterval = setInterval(() => {
823+
if (this.lastLocalStorageData) {
824+
clearTimeout(timeout);
825+
clearInterval(checkInterval);
826+
resolve(this.lastLocalStorageData);
827+
}
828+
}, 100);
829+
});
830+
831+
// Send request to extension
832+
console.log("Browser Connector: Requesting localStorage data from extension");
833+
this.activeConnection.send(JSON.stringify({ type: "get-local-storage" }));
834+
835+
// Wait for data
836+
return storagePromise;
837+
}
838+
839+
// Add method to get sessionStorage
840+
private getSessionStorage(): Promise<any> {
841+
if (!this.activeConnection) {
842+
throw new Error("Chrome extension not connected");
843+
}
844+
845+
// Reset the stored data
846+
this.lastSessionStorageData = null;
847+
848+
// Create a promise that will resolve when we get the sessionStorage data
849+
const storagePromise = new Promise<any>((resolve, reject) => {
850+
// Set timeout to reject if we don't get a response
851+
const timeout = setTimeout(() => {
852+
reject(new Error("Timeout waiting for sessionStorage data from Chrome extension"));
853+
}, 5000);
854+
855+
// Set up an interval to check for data
856+
const checkInterval = setInterval(() => {
857+
if (this.lastSessionStorageData) {
858+
clearTimeout(timeout);
859+
clearInterval(checkInterval);
860+
resolve(this.lastSessionStorageData);
861+
}
862+
}, 100);
863+
});
864+
865+
// Send request to extension
866+
console.log("Browser Connector: Requesting sessionStorage data from extension");
867+
this.activeConnection.send(JSON.stringify({ type: "get-session-storage" }));
868+
869+
// Wait for data
870+
return storagePromise;
668871
}
669872

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

0 commit comments

Comments
 (0)