This guide explains how to configure and use Kapture with Model Context Protocol (MCP) clients like Claude Desktop, Cline, and custom implementations.
chrome://extensions/
extension
folderClaude Desktop (~/Library/Application Support/Claude/claude_desktop_config.json
):
{
"mcpServers": {
"kapture": {
"command": "npx",
"args": ["kapture-mcp-server", "bridge"]
}
}
}
Cline/VS Code (settings.json):
{
"cline.mcpServers": {
"kapture": {
"command": "npx",
"args": ["kapture-mcp-server", "bridge"]
}
}
}
Ask your AI assistant to:
The npx kapture-mcp-server
command includes intelligent server detection:
{
"mcpServers": {
"kapture": {
"command": "npx",
"args": ["kapture-mcp-server", "bridge"]
}
}
}
This approach:
If you've cloned the repository:
{
"mcpServers": {
"kapture": {
"command": "node",
"args": ["/path/to/kapture/server/dist/index.js", "bridge"]
}
}
}
For custom integrations or manual server control:
npx kapture-mcp-server
{
"mcpServers": {
"kapture": {
"transport": "websocket",
"url": "ws://localhost:61822/mcp"
}
}
}
~/Library/Application Support/Claude/claude_desktop_config.json
%APPDATA%\Claude\claude_desktop_config.json
~/.config/Claude/claude_desktop_config.json
Kapture provides 19 tools organized into functional categories:
Navigate to a URL with optional timeout.
{
tabId: "tab_1234567890",
url: "https://example.com",
timeout: 30000 // optional, ms
}
Browser history navigation.
{
tabId: "tab_1234567890"
}
Reload the current page (similar to pressing F5).
{
tabId: "tab_1234567890"
}
All interaction tools support both CSS selectors and XPath expressions.
Click elements. Returns the unique selector of clicked element.
{
tabId: "tab_1234567890",
selector: "button.submit", // CSS
// OR
xpath: "//button[contains(text(), 'Submit')]"
}
Hover over elements to trigger effects.
{
tabId: "tab_1234567890",
selector: ".dropdown-trigger"
}
Fill text inputs.
{
tabId: "tab_1234567890",
selector: "#email",
value: "user@example.com"
}
Select dropdown options (HTML <select>
only).
{
tabId: "tab_1234567890",
selector: "#country",
value: "us" // option value
}
Send keyboard events with modifier support.
{
tabId: "tab_1234567890",
key: "Control+a", // Select all
selector: "#editor", // optional
delay: 100 // optional ms
}
Supported keys:
"a"
, "Enter"
, "Tab"
"Control+c"
, "Shift+Tab"
"PageDown"
, "F5"
Manage element focus.
{
tabId: "tab_1234567890",
selector: "#search-input"
}
Capture screenshots with compression options.
{
tabId: "tab_1234567890",
selector: ".chart", // optional
scale: 0.5, // 0.1-1.0
format: "webp", // webp|jpeg|png
quality: 0.85 // 0.1-1.0
}
Get HTML content.
{
tabId: "tab_1234567890",
selector: "article" // optional
}
Query multiple elements with visibility filtering.
{
tabId: "tab_1234567890",
selector: "a.external-link",
visible: "true" // true|false|all
}
Retrieve browser console output.
{
tabId: "tab_1234567890",
level: "error", // optional
limit: 100, // optional
before: "2024-01-01T00:00:00Z"
}
Get all elements at specific coordinates.
{
tabId: "tab_1234567890",
x: 500,
y: 300
}
Get all connected tabs.
{} // no parameters needed
Get comprehensive tab information.
{
tabId: "tab_1234567890"
}
Open a new browser tab.
{
browser: "chrome" // optional
}
Opens the Kapture how-to page.
Close a browser tab.
{
tabId: "tab_1234567890"
}
Key behaviors to remember:
xpath
parameter instead of selector
for XPath expressionsResources provide read-only access to browser data:
Resource URI | Description | Query Parameters |
---|---|---|
kapture://tabs |
List of all connected tabs | None |
kapture://tab/{tabId} |
Detailed tab information | None |
kapture://tab/{tabId}/console |
Console logs with pagination | before , limit , level |
kapture://tab/{tabId}/screenshot |
Screenshot as MCP resource | selector , scale , format , quality |
kapture://tab/{tabId}/dom |
DOM HTML content | selector |
kapture://tab/{tabId}/elements |
Query elements | selector , visible |
kapture://tab/{tabId}/elementsFromPoint |
Elements at coordinates | x , y (required) |
// Get available tabs
const tabs = await callTool('list_tabs', {});
const tabId = tabs[0].tabId;
// Navigate to a website
await callTool('navigate', {
tabId,
url: 'https://example.com'
});
// Fill and submit a form
await callTool('fill', {
tabId,
selector: '#username',
value: 'myuser@example.com'
});
await callTool('fill', {
tabId,
selector: '#password',
value: 'secretpass123'
});
await callTool('click', {
tabId,
selector: 'button[type="submit"]'
});
// Wait for element to appear
async function waitForElement(tabId, selector, maxAttempts = 10) {
for (let i = 0; i < maxAttempts; i++) {
const result = await callTool('elements', {
tabId,
selector,
visible: 'true'
});
if (result.elements.length > 0) {
return result.elements[0];
}
await new Promise(resolve => setTimeout(resolve, 1000));
}
throw new Error(`Element ${selector} not found after ${maxAttempts} attempts`);
}
// Use it
const element = await waitForElement(tabId, '.dynamic-content');
await callTool('click', {
tabId,
selector: element.selector
});
// Handle custom dropdowns (not HTML select)
await callTool('click', {
tabId,
selector: '.custom-dropdown-trigger'
});
await new Promise(resolve => setTimeout(resolve, 500));
await callTool('click', {
tabId,
xpath: "//li[@role='option'][contains(text(), 'United States')]"
});
// Handle multi-step forms
async function fillMultiStepForm(tabId, formData) {
// Step 1: Personal Info
await callTool('fill', { tabId, selector: '#firstName', value: formData.firstName });
await callTool('fill', { tabId, selector: '#lastName', value: formData.lastName });
await callTool('click', { tabId, selector: 'button.next-step' });
// Wait for next step
await waitForElement(tabId, '#email');
// Step 2: Contact Info
await callTool('fill', { tabId, selector: '#email', value: formData.email });
await callTool('fill', { tabId, selector: '#phone', value: formData.phone });
await callTool('click', { tabId, selector: 'button.submit-form' });
}
// Capture different parts of a page
async function capturePageSections(tabId) {
const screenshots = {};
// Full page
screenshots.full = await callTool('screenshot', {
tabId,
scale: 0.3
});
// Specific sections
const sections = ['header', 'main', 'footer'];
for (const section of sections) {
screenshots[section] = await callTool('screenshot', {
tabId,
selector: section,
format: 'png',
scale: 0.5
});
}
return screenshots;
}
// Monitor for errors during automation
async function runWithErrorMonitoring(tabId, automation) {
// Clear existing logs
await callTool('console_logs', { tabId, limit: 1 });
// Run automation
await automation();
// Check for errors
const logs = await callTool('console_logs', {
tabId,
level: 'error',
limit: 100
});
if (logs.logs.length > 0) {
console.warn('Errors detected during automation:', logs.logs);
}
return logs.logs;
}
elements
tool to debuglist_tabs
to get current tabsAccess data directly via browser:
http://localhost:61822/
- Server statushttp://localhost:61822/tabs
- Tab listhttp://localhost:61822/tab/{tabId}/screenshot/view
- View screenshotconst elements = await callTool('elements', {
tabId,
selector: '.my-element',
visible: 'all'
});
elements.forEach(el => {
console.log(`${el.selector}: visible=${el.isVisible}`);
});
Enable real-time console monitoring in your client to see browser errors as they happen.
Kapture excels at supporting multiple AI clients simultaneously!
See the Multi-Assistant Guide for detailed setup.
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
import { spawn } from 'child_process';
// Spawn the server with bridge
const proc = spawn('npx', ['kapture-mcp-server', 'bridge']);
const transport = new StdioClientTransport({
command: proc
});
const client = new Client({
name: 'custom-client',
version: '1.0.0'
}, {
capabilities: {}
});
await client.connect(transport);
// Subscribe to notifications
client.on('notification', (notification) => {
if (notification.method === 'kapture/console_log') {
console.log('Browser console:', notification.params);
}
});
// Use tools
const result = await client.callTool('navigate', {
tabId: 'tab_1234567890',
url: 'https://example.com'
});
const tabs = await callTool('list_tabs', {});
if (tabs.length === 0) {
throw new Error('No tabs connected');
}
async function safeClick(tabId, selector, retries = 3) {
for (let i = 0; i < retries; i++) {
const result = await callTool('click', { tabId, selector });
if (result.clicked) return result;
await new Promise(resolve => setTimeout(resolve, 1000));
}
throw new Error(`Failed to click ${selector} after ${retries} attempts`);
}
Kapture provides a robust bridge between AI assistants and web browsers through:
Start with the basic configuration, connect a browser tab, and begin automating!