← Back to Documentation

Using Kapture with MCP Clients

This guide explains how to configure and use Kapture with Model Context Protocol (MCP) clients like Claude Desktop, Cline, and custom implementations.

Table of Contents

Quick Start

1. Install the Chrome Extension

  1. Download from releases or clone the repo
  2. Open chrome://extensions/
  3. Enable "Developer mode"
  4. Click "Load unpacked" and select the extension folder

2. Configure Your MCP Client

Claude 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"]
    }
  }
}

3. Connect Browser Tab

  1. Open any website in Chrome
  2. Open DevTools (F12)
  3. Click the "Kapture" panel
  4. You'll see "Connected" status

4. Start Using

Ask your AI assistant to:

Understanding the Architecture

How Kapture Works

graph LR MCP[MCP Client
Claude/Cline] -->|stdio| B[bridge] B -->|WebSocket| KS[Kapture Server] KS --> CE[Chrome Extension] CE --> BT[Browser Tabs]

Key Components

  1. MCP Server: Runs on port 61822, handles all MCP protocol communication
  2. Bridge Mode: Translates between stdio (used by MCP clients) and WebSocket
  3. Chrome Extension: Injects into DevTools, executes browser commands
  4. WebSocket: Real-time bidirectional communication

Smart Server Management

The npx kapture-mcp-server command includes intelligent server detection:

Installation & Configuration

System Requirements

Configuration Options

Recommended: Bridge Command

{
  "mcpServers": {
    "kapture": {
      "command": "npx",
      "args": ["kapture-mcp-server", "bridge"]
    }
  }
}

This approach:

Alternative: Local Installation

If you've cloned the repository:

{
  "mcpServers": {
    "kapture": {
      "command": "node",
      "args": ["/path/to/kapture/server/dist/index.js", "bridge"]
    }
  }
}

Advanced: Direct WebSocket

For custom integrations or manual server control:

  1. Start server manually: npx kapture-mcp-server
  2. Configure client:
    {
      "mcpServers": {
        "kapture": {
          "transport": "websocket",
          "url": "ws://localhost:61822/mcp"
        }
      }
    }

Configuration File Locations

Claude Desktop:

VS Code (Cline):

Available Tools

Kapture provides 19 tools organized into functional categories:

Navigation Tools

navigate

Navigate to a URL with optional timeout.

{
  tabId: "tab_1234567890",
  url: "https://example.com",
  timeout: 30000  // optional, ms
}

back / forward

Browser history navigation.

{
  tabId: "tab_1234567890"
}

reload

Reload the current page (similar to pressing F5).

{
  tabId: "tab_1234567890"
}

Interaction Tools

All interaction tools support both CSS selectors and XPath expressions.

click

Click elements. Returns the unique selector of clicked element.

{
  tabId: "tab_1234567890",
  selector: "button.submit",  // CSS
  // OR
  xpath: "//button[contains(text(), 'Submit')]"
}

hover

Hover over elements to trigger effects.

{
  tabId: "tab_1234567890",
  selector: ".dropdown-trigger"
}

fill

Fill text inputs.

{
  tabId: "tab_1234567890",
  selector: "#email",
  value: "user@example.com"
}

select

Select dropdown options (HTML <select> only).

{
  tabId: "tab_1234567890",
  selector: "#country",
  value: "us"  // option value
}

keypress

Send keyboard events with modifier support.

{
  tabId: "tab_1234567890",
  key: "Control+a",  // Select all
  selector: "#editor",  // optional
  delay: 100  // optional ms
}

Supported keys:

  • Single: "a", "Enter", "Tab"
  • Modifiers: "Control+c", "Shift+Tab"
  • Special: "PageDown", "F5"

focus / blur

Manage element focus.

{
  tabId: "tab_1234567890",
  selector: "#search-input"
}

Information Tools

screenshot

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
}

dom

Get HTML content.

{
  tabId: "tab_1234567890",
  selector: "article"  // optional
}

elements

Query multiple elements with visibility filtering.

{
  tabId: "tab_1234567890",
  selector: "a.external-link",
  visible: "true"  // true|false|all
}

console_logs

Retrieve browser console output.

{
  tabId: "tab_1234567890",
  level: "error",  // optional
  limit: 100,  // optional
  before: "2024-01-01T00:00:00Z"
}

elementsFromPoint

Get all elements at specific coordinates.

{
  tabId: "tab_1234567890",
  x: 500,
  y: 300
}

Tab Management Tools

list_tabs

Get all connected tabs.

{}  // no parameters needed

tab_detail

Get comprehensive tab information.

{
  tabId: "tab_1234567890"
}

new_tab

Open a new browser tab.

{
  browser: "chrome"  // optional
}

Opens the Kapture how-to page.

close

Close a browser tab.

{
  tabId: "tab_1234567890"
}

Important Tool Behaviors

Key behaviors to remember:

  1. First Element Only: Tools that accept selectors only operate on the first matching element
  2. Unique Selectors: Tools return the unique selector of the element they operated on
  3. XPath Support: Use xpath parameter instead of selector for XPath expressions
  4. Error Handling: Element-not-found returns success with error details, not an exception

MCP Resources

Resources 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)

Examples & Patterns

Basic Navigation and Interaction

// 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"]'
});

Working with Dynamic Content

// 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
});

Advanced Form Handling

// 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' });
}

Screenshot Automation

// 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;
}

Console Monitoring

// 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;
}

Troubleshooting

Common Issues

"No tabs connected"

  • Open Chrome DevTools (F12)
  • Navigate to Kapture panel
  • Check connection status
  • Reload the page if needed

"Element not found"

  • Verify selector is correct
  • Check if element is visible
  • Use elements tool to debug
  • Try XPath if CSS selector fails

Commands timing out

  • Increase timeout parameter
  • Check for JavaScript errors in console
  • Verify tab is still responsive

"Tab not found"

  • Tab may have disconnected
  • Use list_tabs to get current tabs
  • Reopen DevTools if needed

Performance Tips

  1. Keep Kapture Panel Active: Click/hover operations perform better when Kapture panel is selected
  2. Use Efficient Selectors: ID selectors are fastest, followed by class, then complex selectors
  3. Batch Operations: Group related commands together
  4. Add Strategic Delays: Some interactions need time to complete

Debugging Strategies

1. Use HTTP Endpoints

Access data directly via browser:

2. Check Element Visibility

const elements = await callTool('elements', {
  tabId,
  selector: '.my-element',
  visible: 'all'
});

elements.forEach(el => {
  console.log(`${el.selector}: visible=${el.isVisible}`);
});

3. Monitor Console Output

Enable real-time console monitoring in your client to see browser errors as they happen.

Advanced Topics

Multiple AI Assistants

Kapture excels at supporting multiple AI clients simultaneously!

  1. Each client uses the same bridge configuration
  2. Server automatically manages shared access
  3. Commands are queued per tab to prevent conflicts
  4. All clients receive real-time notifications

See the Multi-Assistant Guide for detailed setup.

Custom MCP Client Integration

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'
});

Security Considerations

  1. Localhost Only: Server only accepts connections from localhost
  2. Tab Isolation: Each tab has a unique ID, preventing cross-tab access
  3. No File System Access: Extension runs in browser sandbox
  4. Command Validation: All inputs are validated before execution

Best Practices

1. Always Check Tab Status

const tabs = await callTool('list_tabs', {});
if (tabs.length === 0) {
  throw new Error('No tabs connected');
}

2. Handle Dynamic Content Gracefully

3. Optimize Selectors

4. Error Recovery

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`);
}

Summary

Kapture provides a robust bridge between AI assistants and web browsers through:

Start with the basic configuration, connect a browser tab, and begin automating!