@pokutuna/mcp-chrome-tabs 0.5.0 → 0.6.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 CHANGED
@@ -4,6 +4,8 @@
4
4
 
5
5
  Model Context Protocol (MCP) server that provides direct access to your browser's open tabs content. No additional fetching or authentication required - simply access what you're already viewing.
6
6
 
7
+ <img src="./demo/demo.webp" width="600px" />
8
+
7
9
  ## Key Features
8
10
 
9
11
  - **Direct browser tab access** - No web scraping needed, reads content from already open tabs
@@ -55,17 +57,18 @@ The server accepts optional command line arguments for configuration:
55
57
  - `--check-interval` - Interval in milliseconds to check for tab changes and notify clients (default: 3000, set to 0 to disable)
56
58
  - `--max-content-chars` - Truncates tab content to a maximum number of characters (default: 20000)
57
59
 
58
- #### Experimental Safari Support
60
+ ## Other Browser Support (Experimental)
61
+
62
+ ### Safari
59
63
 
60
- Limited Safari support is available. Note that Safari lacks unique tab IDs, making it sensitive to tab order changes during execution:
64
+ Note that Safari lacks unique tab IDs, making it sensitive to tab order changes during execution:
61
65
 
62
66
  ```bash
63
67
  npx @pokutuna/mcp-chrome-tabs --application-name=Safari --experimental-browser=safari
64
68
  ```
65
69
 
66
- #### Experimental Arc Browser Support
67
70
 
68
- Arc Browser support is available. Arc is Chrome-based and supports JavaScript execution from Apple Events:
71
+ ### Arc
69
72
 
70
73
  ```bash
71
74
  npx @pokutuna/mcp-chrome-tabs --application-name=Arc --experimental-browser=arc
@@ -101,6 +104,7 @@ Get readable content from a tab in the user's browser.
101
104
  Open a URL in a new tab to present content or enable user interaction with webpages.
102
105
 
103
106
  - `url` (required): URL to open in the browser
107
+ - Returns: Tab ID in format `ID:windowId:tabId` for immediate access to the new tab
104
108
 
105
109
  </details>
106
110
 
@@ -111,12 +111,20 @@ async function getPageContent(applicationName, tab) {
111
111
  }
112
112
  async function openURL(applicationName, url) {
113
113
  const escapedUrl = escapeAppleScript(url);
114
+ const sep = separator();
114
115
  const appleScript = `
115
116
  tell application "${applicationName}"
116
- open location "${escapedUrl}"
117
+ tell front window
118
+ set newTab to (make new tab with properties {URL:"${escapedUrl}"})
119
+ set windowId to id
120
+ set tabId to id of (active tab) -- cannot retrieve id of newTab
121
+ return windowId & "${sep}" & tabId
122
+ end tell
117
123
  end tell
118
124
  `;
119
- await executeAppleScript(appleScript);
125
+ const result = await executeAppleScript(appleScript);
126
+ const [windowId, tabId] = result.trim().split(sep);
127
+ return { windowId, tabId };
120
128
  }
121
129
  export const arcBrowser = {
122
130
  getTabList: getArcTabList,
@@ -15,6 +15,6 @@ export type TabContent = {
15
15
  export type BrowserInterface = {
16
16
  getTabList(applicationName: string): Promise<Tab[]>;
17
17
  getPageContent(applicationName: string, tab?: TabRef | null): Promise<TabContent>;
18
- openURL(applicationName: string, url: string): Promise<void>;
18
+ openURL(applicationName: string, url: string): Promise<TabRef>;
19
19
  };
20
20
  export declare function getInterface(browser: Browser): BrowserInterface;
@@ -90,17 +90,23 @@ async function getPageContent(applicationName, tab) {
90
90
  return {
91
91
  title,
92
92
  url,
93
- content, // Return raw HTML content
93
+ content,
94
94
  };
95
95
  }
96
96
  async function openURL(applicationName, url) {
97
97
  const escapedUrl = escapeAppleScript(url);
98
+ const sep = separator();
98
99
  const appleScript = `
99
100
  tell application "${applicationName}"
100
- open location "${escapedUrl}"
101
+ set newTab to (make new tab at end of tabs of front window with properties {URL:"${escapedUrl}"})
102
+ set windowId to id of front window
103
+ set tabId to id of newTab
104
+ return windowId & "${sep}" & tabId
101
105
  end tell
102
106
  `;
103
- await executeAppleScript(appleScript);
107
+ const result = await executeAppleScript(appleScript);
108
+ const [windowId, tabId] = result.trim().split(sep);
109
+ return { windowId, tabId };
104
110
  }
105
111
  export const chromeBrowser = {
106
112
  getTabList: getChromeTabList,
@@ -90,17 +90,25 @@ async function getPageContent(applicationName, tab) {
90
90
  return {
91
91
  title,
92
92
  url,
93
- content, // Return raw HTML content
93
+ content,
94
94
  };
95
95
  }
96
96
  async function openURL(applicationName, url) {
97
97
  const escapedUrl = escapeAppleScript(url);
98
+ const sep = separator();
98
99
  const appleScript = `
99
100
  tell application "${applicationName}"
100
- open location "${escapedUrl}"
101
+ tell front window
102
+ set newTab to (make new tab with properties {URL:"${escapedUrl}"})
103
+ set windowId to id
104
+ set tabIndex to index of newTab
105
+ return (windowId as string) & "${sep}" & (tabIndex as string)
106
+ end tell
101
107
  end tell
102
108
  `;
103
- await executeAppleScript(appleScript);
109
+ const result = await executeAppleScript(appleScript);
110
+ const [windowId, tabId] = result.trim().split(sep);
111
+ return { windowId, tabId };
104
112
  }
105
113
  export const safariBrowser = {
106
114
  getTabList: getSafariTabList,
package/dist/mcp.js CHANGED
@@ -122,12 +122,13 @@ export async function createMcpServer(options) {
122
122
  }, async (args) => {
123
123
  const { url } = args;
124
124
  const browser = getInterface(options.browser);
125
- await browser.openURL(options.applicationName, url);
125
+ const tabRef = await browser.openURL(options.applicationName, url);
126
+ const tabId = `ID:${tabRef.windowId}:${tabRef.tabId}`;
126
127
  return {
127
128
  content: [
128
129
  {
129
130
  type: "text",
130
- text: `Successfully opened the URL`,
131
+ text: `Successfully opened URL in new tab. Tab: \`${tabId}\``,
131
132
  },
132
133
  ],
133
134
  };
package/package.json CHANGED
@@ -1,12 +1,19 @@
1
1
  {
2
2
  "name": "@pokutuna/mcp-chrome-tabs",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/pokutuna/mcp-chrome-tabs"
7
7
  },
8
8
  "license": "MIT",
9
9
  "type": "module",
10
+ "keywords": [
11
+ "mcp",
12
+ "model-context-protocol",
13
+ "chrome",
14
+ "ai",
15
+ "macos"
16
+ ],
10
17
  "bin": {
11
18
  "mcp-chrome-tabs": "./dist/cli.js"
12
19
  },
@@ -28,18 +35,18 @@
28
35
  "test:e2e": "playwright test"
29
36
  },
30
37
  "dependencies": {
31
- "@modelcontextprotocol/sdk": "^1.16.0",
32
- "defuddle": "^0.6.4",
38
+ "@modelcontextprotocol/sdk": "^1.17.3",
39
+ "defuddle": "^0.6.6",
33
40
  "jsdom": "^24.0.0",
34
41
  "zod": "^3.25.76"
35
42
  },
36
43
  "devDependencies": {
37
- "@playwright/test": "^1.54.1",
44
+ "@playwright/test": "^1.55.0",
38
45
  "@types/node": "^20.11.17",
39
46
  "playwright": "^1.54.1",
40
47
  "prettier": "^3.6.2",
41
- "tsx": "^4.7.1",
42
- "typescript": "~5.8.3",
48
+ "tsx": "^4.20.4",
49
+ "typescript": "~5.9.2",
43
50
  "vitest": "^3.2.4"
44
51
  }
45
52
  }