Skip to content

Commit b3886c4

Browse files
eyalzhCopilot
andauthored
Improve highlight tool and add relative time to tabs and history data (#7)
* Improve highlight tool and add relative time to tabs and history data * Update README.md Co-authored-by: Copilot <[email protected]> --------- Co-authored-by: Copilot <[email protected]>
1 parent 4b418c7 commit b3886c4

File tree

6 files changed

+50
-13
lines changed

6 files changed

+50
-13
lines changed

README.md

+11-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Browser Control MCP
22

3-
An MCP server paired with a browser extension that enables LLM clients, such as Claude Desktop, to control the user's local browser (e.g. Firefox).
3+
An MCP server paired with a browser extension that enables LLM clients, such as Claude Desktop, to control the user's local browser (Firefox).
44

55
## Features
66

@@ -17,11 +17,20 @@ to select browser tabs in the MCP client itself (e.g. Claude) and load their con
1717

1818
## Example use-cases:
1919

20+
21+
### Tab management
2022
- *"Close all non-work related tabs in my browser."*
2123
- *"Rearrange tabs in my browser in an order that makes sense."*
24+
- *"Close all tabs in my browser that haven't been accessed within the past 24 hours"*
25+
26+
### Browser history search
2227
- *"Help me find an article in my browser history about the Milford track in NZ."*
28+
- *"Open all the articles about AI that I visited during the last week, up to 10 articles, avoid duplications."*
29+
30+
### Browsing and research
2331
- *"Open hackernews in my browser, then open the top story, read it, also read the comments. Do the comments agree with the story?"*
24-
- *"In my browser, use Google Scholar to search for papers about L-theanine in the last 3 years. Open the 3 most cited works."*
32+
- *"In my browser, use Google Scholar to search for papers about L-theanine in the last 3 years. Open the 3 most cited papers. Read them and summarize them for me."*
33+
- *"Use google search in my browser to look for flower shops. Open the 10 most relevant results. Show me a table of each flower shop with location and opening hours."*
2534

2635
## Installation
2736

common/extension-messages.ts

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export interface BrowserTab {
1414
id?: number;
1515
url?: string;
1616
title?: string;
17+
lastAccessed?: number;
1718
}
1819

1920
export interface TabsExtensionMessage extends ExtensionMessageBase {

firefox-extension/background.ts

+3
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,9 @@ function initWsClient(port: number, secret: string) {
230230

231231
// If there are results, highlight them
232232
if (findResults.count > 0) {
233+
// But first, activate the tab. In firefox, this would also enable
234+
// auto-scrolling to the highlighted result.
235+
await browser.tabs.update(tabId, { active: true });
233236
browser.find.highlightResults({
234237
tabId,
235238
});

mcp-server/package-lock.json

+7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

mcp-server/package.json

+4-3
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,14 @@
1212
"license": "MIT",
1313
"description": "Browser Control MCP Server",
1414
"dependencies": {
15+
"@browser-control-mcp/common": "../common",
1516
"@modelcontextprotocol/sdk": "^1.7.0",
17+
"dayjs": "^1.11.13",
1618
"readline": "^1.3.0",
17-
"ws": "^8.18.1",
18-
"@browser-control-mcp/common": "../common"
19+
"ws": "^8.18.1"
1920
},
2021
"devDependencies": {
2122
"@types/ws": "^8.18.0",
2223
"typescript": "^5.8.2"
2324
}
24-
}
25+
}

mcp-server/server.ts

+24-8
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ import {
55
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
66
import { z } from "zod";
77
import { BrowserAPI } from "./browser-api";
8+
import dayjs from "dayjs";
9+
import relativeTime from "dayjs/plugin/relativeTime";
10+
11+
dayjs.extend(relativeTime);
812

913
const mcpServer = new McpServer({
1014
name: "BrowserControl",
@@ -52,10 +56,16 @@ mcpServer.tool(
5256
const openTabs = await browserApi.getTabList();
5357
if (openTabs) {
5458
return {
55-
content: openTabs.map((tab) => ({
56-
type: "text",
57-
text: `tab id=${tab.id}, tab url=${tab.url}, tab title=${tab.title}`,
58-
})),
59+
content: openTabs.map((tab) => {
60+
let lastAccessed = "unknown";
61+
if (tab.lastAccessed) {
62+
lastAccessed = dayjs(tab.lastAccessed).fromNow(); // LLM-friendly time ago
63+
}
64+
return {
65+
type: "text",
66+
text: `tab id=${tab.id}, tab url=${tab.url}, tab title=${tab.title}, last accessed=${lastAccessed}`,
67+
};
68+
}),
5969
};
6070
} else {
6171
return {
@@ -76,9 +86,13 @@ mcpServer.tool(
7686
if (browserHistory) {
7787
return {
7888
content: browserHistory.map((item) => {
89+
let lastVisited = "unknown";
90+
if (item.lastVisitTime) {
91+
lastVisited = dayjs(item.lastVisitTime).fromNow(); // LLM-friendly time ago
92+
}
7993
return {
8094
type: "text",
81-
text: `url=${item.url}, title="${item.title}", lastVisitTime=${item.lastVisitTime}`,
95+
text: `url=${item.url}, title="${item.title}", lastVisitTime=${lastVisited}`,
8296
};
8397
}),
8498
};
@@ -160,7 +174,6 @@ mcpServer.tool(
160174
}
161175
);
162176

163-
164177
mcpServer.resource(
165178
"open-tab-contents",
166179
new ResourceTemplate("browser://tab/{tabId}/content", {
@@ -178,8 +191,11 @@ mcpServer.resource(
178191
async (uri, { tabId }) => {
179192
const content = await browserApi.getTabContent(Number(tabId));
180193
const listOfLinks =
181-
content?.links.map((link: { text: string; url: string }) => `${link.text}: ${link.url}`).join("\n") ??
182-
"";
194+
content?.links
195+
.map(
196+
(link: { text: string; url: string }) => `${link.text}: ${link.url}`
197+
)
198+
.join("\n") ?? "";
183199
const fullText = content?.fullText ?? "";
184200
return {
185201
contents: [

0 commit comments

Comments
 (0)