mcp-rnw-browser
Enables browser automation for React Native Web applications using coordinate-based clicks to trigger RNW's gesture responder, with multi-tab management, screenshots, and persistent sessions.
README
MCP Browser Server for React Native Web
A Model Context Protocol (MCP) browser automation server specifically designed to work with React Native Web applications. Features multi-tab support, screenshot capabilities, and persistent browser sessions.
The Problem
React Native Web uses a gesture responder system that listens for mousedown/mouseup events instead of standard click events. This breaks standard browser automation tools like Playwright's locator.click() method.
The Solution
This MCP server uses coordinate-based clicks with Playwright's low-level page.mouse API, which properly triggers the mouse events that React Native Web components listen for.
Features
- Coordinate-based clicking - Uses
page.mouse.down()/page.mouse.up()instead of synthetic clicks - Multiple element finding strategies - CSS selector, text content, testID, or exact coordinates
- Custom page snapshots - Shows interactive elements with positions (not reliant on accessibility tree)
- Screenshot support - Returns base64-encoded PNG images that AI agents can view
- Multi-tab management - Create, switch between, and close browser tabs
- Persistent sessions - Browser stays open between tool calls for continuous interaction
- Full browser control - Navigate, type, scroll, press keys, evaluate JavaScript
Installation
From npm
npm install @nizarius/mcp-rnw-browser
npx playwright install chromium
From source
git clone https://github.com/nizarius/mcp-rnw-browser.git
cd mcp-rnw-browser
npm install
npm run build
npx playwright install chromium
Configuration for Cursor
Add to your Cursor MCP settings (~/.cursor/mcp.json or Cursor Settings > MCP):
Using npm package (recommended)
{
"mcpServers": {
"rnw-browser": {
"command": "npx",
"args": ["@nizarius/mcp-rnw-browser"]
}
}
}
Using local installation
{
"mcpServers": {
"rnw-browser": {
"command": "node",
"args": ["/path/to/mcp-rnw-browser/dist/index.js"]
}
}
}
Available Tools
Navigation
rnw_navigate
Navigate to a URL. Creates a browser session if none exists.
{ "url": "http://localhost:8081" }
Returns: Page snapshot with all interactive elements.
Screenshots & Snapshots
rnw_snapshot
Get a text snapshot of interactive elements on the page with their positions. Returns element tags, text content, testIDs, roles, positions, and center coordinates for clicking.
// No parameters required
{}
Returns: Text list of all interactive elements with their positions.
rnw_screenshot
Take a screenshot and return as a base64-encoded PNG image.
// Viewport screenshot (default)
{}
// Full page screenshot (captures entire scrollable area)
{ "fullPage": true }
// Element screenshot (captures specific element)
{ "selector": "#my-component" }
Returns: Base64-encoded PNG image that AI agents can view directly.
Interactions
rnw_click
Click on an element using React Native Web compatible mouse events (mousedown/mouseup).
// By CSS selector
{ "selector": "button.submit", "findBy": "css" }
// By text content (partial match)
{ "selector": "Sign In", "findBy": "text" }
// By testID (data-testid attribute)
{ "selector": "login-button", "findBy": "testid" }
// By exact coordinates (useful when element detection fails)
{ "x": 500, "y": 300, "findBy": "coordinates" }
Returns: Click coordinates and updated page snapshot.
rnw_type
Type text into a focused element or find an element first and type into it.
// Type into currently focused element
{ "text": "Hello World" }
// Find element first, then type (clicks to focus)
{ "text": "Hello World", "selector": "input", "findBy": "css" }
// Type and press Enter (e.g., for search/submit)
{ "text": "Hello World", "selector": "input", "findBy": "css", "pressEnter": true }
Returns: Confirmation of typed text.
rnw_scroll
Scroll the page or a specific scrollable element.
// Scroll page down by 300 pixels
{ "direction": "down", "amount": 300 }
// Scroll page up
{ "direction": "up", "amount": 500 }
// Scroll within a specific container
{ "direction": "down", "amount": 200, "selector": ".scroll-container" }
Parameters: direction (up/down/left/right), amount (pixels, default: 300), selector (optional).
Returns: Updated page snapshot.
rnw_wait
Wait for a specified time or until an element appears on the page.
// Wait for 1 second (1000ms)
{ "time": 1000 }
// Wait for element to appear (with 5s timeout)
{ "selector": "button.loaded", "findBy": "css" }
// Wait for text to appear
{ "selector": "Loading complete", "findBy": "text" }
Returns: Confirmation when wait completes or error if timeout.
rnw_press_key
Press a keyboard key. Useful for navigation, form submission, or triggering shortcuts.
// Press Enter
{ "key": "Enter" }
// Press Escape
{ "key": "Escape" }
// Press arrow keys
{ "key": "ArrowDown" }
// Press Tab to move focus
{ "key": "Tab" }
Common keys: Enter, Escape, Tab, ArrowUp, ArrowDown, ArrowLeft, ArrowRight, Backspace, Delete, Space.
Returns: Confirmation of key pressed.
rnw_evaluate
Execute JavaScript in the browser context. Useful for debugging, reading state, or performing custom interactions.
// Get page title
{ "script": "document.title" }
// Get current URL
{ "script": "window.location.href" }
// Read localStorage value
{ "script": "localStorage.getItem('authToken')" }
// Get element count
{ "script": "document.querySelectorAll('button').length" }
// Trigger custom action
{ "script": "window.scrollTo(0, document.body.scrollHeight)" }
Returns: JSON-stringified result of the script execution.
Tab Management
rnw_tabs_list
List all open browser tabs with their index, title, and URL.
// No parameters required
{}
Returns: List of all tabs showing index, active status, title, and URL.
rnw_tabs_new
Create a new browser tab and optionally navigate to a URL. The new tab becomes the active tab.
// Create empty new tab (about:blank)
{}
// Create new tab and navigate to URL
{ "url": "http://localhost:8081/settings" }
Returns: New tab index and page snapshot.
rnw_tabs_select
Switch to a specific tab by index (0-based). Use rnw_tabs_list to see available tabs.
// Switch to second tab
{ "index": 1 }
// Switch to first tab
{ "index": 0 }
Returns: Snapshot of the selected tab's page.
rnw_tabs_close
Close a browser tab. If the closed tab was active, switches to the nearest remaining tab.
// Close current active tab
{}
// Close specific tab by index
{ "index": 2 }
Returns: Confirmation and snapshot of the new active tab.
Session Management
rnw_session_status
Get current browser session status. Useful for checking if a session is active before performing actions.
// No parameters required
{}
Returns:
isRunning: Whether browser is activetabCount: Number of open tabscurrentTabIndex: Index of active tabcurrentUrl: URL of active tabviewport: Browser window dimensions (width x height)
rnw_close
Close the browser and end the session. All tabs are closed and resources are released.
// No parameters required
{}
Returns: Confirmation that browser session has ended.
How It Works
Standard Playwright Click (Doesn't work with RNW)
// This dispatches a synthetic 'click' event that RNW ignores
await element.click();
This MCP Server's Click (Works with RNW)
// This triggers real mousedown/mouseup events that RNW responds to
await page.mouse.move(x, y);
await page.mouse.down();
await page.mouse.up();
Example Usage with AI Agent
Agent: Let me navigate to your React Native Web app, take a screenshot, and click the login button.
> rnw_navigate { "url": "http://localhost:8081" }
Page loaded. I can see the following interactive elements:
[0] button testid="login-button"
text: "Sign In"
center: (640, 400)
> rnw_screenshot {}
[Returns PNG image of the page]
> rnw_click { "selector": "login-button", "findBy": "testid" }
Clicked at (640, 400). The login form is now visible.
> rnw_tabs_new { "url": "http://localhost:8081/settings" }
Created new tab [1] and navigated to settings page.
> rnw_tabs_list {}
Open Tabs (2):
[0] Home - http://localhost:8081/
[1] (active) Settings - http://localhost:8081/settings
Continuous Session Workflow
The browser session persists across tool calls, enabling:
- Multi-step interactions - Navigate, screenshot, interact, screenshot again
- Visual verification - Take screenshots to verify UI state after actions
- Multi-page workflows - Open multiple tabs for complex testing scenarios
- Debugging - Use
rnw_evaluateto inspect page state
Agent: I'll test the multi-step form submission.
> rnw_navigate { "url": "http://localhost:8081/form" }
> rnw_screenshot {} // Verify initial state
> rnw_type { "text": "John Doe", "selector": "[data-testid='name-input']", "findBy": "css" }
> rnw_screenshot {} // Verify text entered
> rnw_click { "selector": "Submit", "findBy": "text" }
> rnw_screenshot {} // Verify submission result
> rnw_close {} // End session when done
Troubleshooting
Elements not found
- Make sure your React Native Web components have
testIDprops set - Use
rnw_snapshotto see available elements - Try using text content with
findBy: "text"
Clicks not registering
- Ensure the element is visible and not covered by another element
- Try increasing the delay with
rnw_waitbefore clicking - Use coordinates directly if element finding fails
Screenshots not working
- Ensure the browser session is active (
rnw_session_status) - For element screenshots, verify the selector matches a visible element
Version History
v2.0.0
- Added screenshot support with base64 image return
- Added multi-tab management (list, new, select, close)
- Added session status tool
- Improved tool response format
- Persistent browser sessions
v1.0.0
- Initial release with RNW-compatible clicking
- Basic navigation, snapshot, and interaction tools
License
MIT
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。