pinchtab-mcp-wrapper

mcp
SUMMARY

Token-efficient browser automation MCP server for AI agents. Web scraping, monitoring & testing with 12x cost savings vs traditional browsers.

README.md

Pinchtab MCP Wrapper

MCP
License

An MCP (Model Context Protocol) server that exposes the full Pinchtab browser API to AI coding agents. Built with token efficiency in mind — perfect for data extraction, web scraping, and automated testing workflows.

🙏 Credits: This wrapper is built on top of the excellent Pinchtab project by Luigi Agosti and the Pinchtab team. Pinchtab is a lightweight 12MB Go binary that provides browser automation via HTTP API with accessibility-first snapshots.


Why Use Pinchtab for AI Agents?

When AI agents need to browse the web, efficiency matters. Pinchtab delivers 5-13x cost savings compared to traditional browser automation.

Cost Comparison (Real Numbers)

Task Traditional Browser Pinchtab Savings
Extract article text ~10,000 tokens (full DOM) ~800 tokens 12.5x cheaper
Find interactive elements ~10,500 tokens ~3,600 tokens 3x cheaper
50-page monitoring task ~$0.30 ~$0.01 30x cheaper

Key Advantages for AI Workflows

1. Data Extraction & Web Scraping

  • Extract clean, structured text without HTML overhead
  • Accessibility tree provides semantic structure (roles, labels, states)
  • Filter to interactive elements only when needed

2. Website Change Monitoring

  • diff=true returns only changed elements since last snapshot
  • Track price changes, content updates, or availability
  • Monitor 50+ pages without context overflow

3. Async Multi-Tab Operations

  • Run 20+ tabs simultaneously (vs 3-5 with Playwright)
  • Tab locking prevents conflicts between agents
  • Each tab ~1MB RAM vs 50MB+ for full browser instances

4. Stable Automation

  • Stable element references (e0, e1) survive CSS changes
  • No brittle CSS selectors that break on redesigns
  • Works with sites that block traditional automation (stealth mode)

Quick Start

One-Line Installation

curl -fsSL https://raw.githubusercontent.com/BDuba/pinchtab-mcp-wrapper/main/install.sh | bash

Requirements: Docker, Node.js 18+, npm

Then restart your AI agent (OpenCode, Claude Code, etc.)

Test It

Open https://example.com and take a screenshot

Or use commands:

/browse https://example.com
/screenshot

Use Cases & Examples

1. Web Scraping at Scale

Problem: Extract product prices from 100 e-commerce pages

Traditional approach:

  • Load full DOM (~10,000 tokens per page)
  • Parse HTML manually
  • Cost: 1,000,000 tokens (~$3.00)

Pinchtab approach:

// Extract structured text only
pinchtab_read_page({url: "https://store.com/product"})
// Returns clean text with prices, descriptions
  • Cost: 80,000 tokens (~$0.24)
  • Savings: $2.76 (12.5x cheaper)

2. Change Detection & Monitoring

Problem: Monitor competitor prices or news updates

// First visit - establish baseline
snapshot1 = pinchtab_snapshot({url: "https://competitor.com/prices"})

// Later visits - get only changes
diff = pinchtab_snapshot({
  url: "https://competitor.com/prices", 
  diff: true
})
// Returns only modified elements (50-200 tokens vs 10,000)

Benefits:

  • Track 50 sites without context overflow
  • Instant detection of changes
  • 200x less data transfer

3. Multi-Source Research

Problem: Gather information from 10+ documentation sites simultaneously

// Open multiple tabs in parallel
tab1 = pinchtab_tab_open({url: "https://docs.api1.com"})
tab2 = pinchtab_tab_open({url: "https://docs.api2.com"})
tab3 = pinchtab_tab_open({url: "https://docs.api3.com"})

// Extract text from all tabs
text1 = pinchtab_read_page({tabId: tab1.tabId})
text2 = pinchtab_read_page({tabId: tab2.tabId})
text3 = pinchtab_read_page({tabId: tab3.tabId})

Benefits:

  • 20+ concurrent tabs
  • No memory issues (1MB per tab)
  • Async operations

4. Form Automation That Lasts

Problem: Automate login/checkout flows that break on website updates

Traditional selectors break:

// Brittle - breaks when CSS changes
await page.click('#login-btn')  // ❌

Pinchtab stable refs:

// Stable - survives redesigns
pinchtab_action({
  tabId: "...",
  kind: "click",
  ref: "e5"  // ✅ Persistent reference
})

5. Accessibility-First Testing

Built-in accessibility tree:

  • Element roles (button, link, heading)
  • Accessible names and labels
  • Focus states and visibility
  • Screen reader compatible
// Get only interactive elements
interactives = pinchtab_list_interactives()
// Returns: buttons, links, inputs with labels

Available Tools

Tool Purpose
pinchtab_tab_open Open URL in new tab
pinchtab_read_page Extract page text (token-efficient)
pinchtab_list_interactives Get clickable elements
pinchtab_snapshot Get accessibility tree
pinchtab_action Click, type, fill forms
pinchtab_screenshot Take JPEG screenshot
pinchtab_evaluate Run JavaScript
pinchtab_download Download files using browser session (preserves cookies, auth, stealth)
pinchtab_upload Upload files to file inputs (local paths, base64, or data URLs)
pinchtab_tab_lock Lock tab for exclusive access

CLI Integration

OpenCode

Add to ~/.config/opencode/opencode.json:

{
  "\$schema": "https://opencode.ai/config.json",
  "mcp": {
    "pinchtab": {
      "type": "local",
      "command": [
        "/usr/bin/node",
        "~/.pinchtab-mcp-wrapper/dist/index.js"
      ],
      "environment": {
        "PINCHTAB_MODE": "external",
        "PINCHTAB_URL": "http://127.0.0.1:9867",
        "PINCHTAB_TOKEN": "opencode-browser-token-secure",
        "MCP_TRANSPORT": "stdio",
        "LOG_LEVEL": "info"
      },
      "enabled": true
    }
  },
  "agent": {
    "browser": {
      "description": "Browser automation specialist",
      "prompt": "Use pinchtab MCP tools for all web browsing tasks. Prefer text extraction over screenshots for efficiency.",
      "tools": {
        "pinchtab*": true,
        "playwright*": false
      }
    }
  },
  "default_agent": "browser"
}

Prerequisites: Ensure Pinchtab Docker container is running:

docker ps | grep pinchtab  # Check if running
docker start pinchtab       # Start if stopped

Claude Code

Add to .mcp.json:

{
  "mcpServers": {
    "pinchtab": {
      "command": "bash",
      "args": ["~/.pinchtab-mcp-wrapper/run-mcp.sh"]
    }
  }
}

Claude Code Skill (Experimental): We also provide a skill file for Claude Code CLI users. See CLAUDE_CODE_SKILL.md for detailed installation and usage instructions in Spanish. You can save this file to ~/.claude/commands/pinchtab.md and use /pinchtab to access the full reference directly in your CLI.

Cursor

Add to Cursor's MCP settings (Settings → Features → MCP):

{
  "mcpServers": {
    "pinchtab": {
      "type": "stdio",
      "command": "bash",
      "args": ["~/.pinchtab-mcp-wrapper/run-mcp.sh"]
    }
  }
}

Zed

Add to ~/.config/zed/settings.json:

{
  "assistant": {
    "version": "2",
    "enabled": true
  },
  "context_servers": {
    "pinchtab": {
      "command": "bash",
      "args": ["~/.pinchtab-mcp-wrapper/run-mcp.sh"]
    }
  }
}


Automatic Configuration for Multiple AI Agents

The installer now automatically detects and configures pinchtab for multiple AI agents:

  • OpenCode (~/.config/opencode/opencode.json)
  • Claude Code (~/.mcp.json or ./.mcp.json)
  • Cursor (~/.config/Cursor/User/settings.json)
  • Zed (~/.config/zed/settings.json)

If a config file already exists, the installer will:

  1. Create a backup (.backup.YYYYMMDD_HHMMSS)
  2. Automatically merge pinchtab configuration using Node.js
  3. Preserve all existing settings

No manual editing required - just run the installer and restart your AI agent!

Installation Options

The install script now supports automatic mode detection and graceful fallback:

Automatic Mode (Default)

The installer automatically detects your environment and chooses the best mode:

curl -fsSL https://raw.githubusercontent.com/BDuba/pinchtab-mcp-wrapper/main/install.sh | bash

What happens:

  1. Checks for Docker (including macOS-specific paths: Homebrew, OrbStack, Docker Desktop)
  2. If Docker is available → builds Docker image and uses docker mode
  3. If Docker is unavailable → automatically downloads Pinchtab binary and uses external mode

Docker Mode

Recommended for most users. Requires Docker to be installed.

export PINCHTAB_MODE=docker
curl -fsSL https://raw.githubusercontent.com/BDuba/pinchtab-mcp-wrapper/main/install.sh | bash

External Mode (Binary)

For systems without Docker. The installer automatically downloads the Pinchtab binary for your architecture.

export PINCHTAB_MODE=external
curl -fsSL https://raw.githubusercontent.com/BDuba/pinchtab-mcp-wrapper/main/install.sh | bash

macOS Support

The installer automatically detects Docker in the following locations:

  • /opt/homebrew/bin/docker (Homebrew on Apple Silicon)
  • /usr/local/bin/docker (Homebrew on Intel)
  • /Applications/OrbStack.app/Contents/MacOS/../bin/docker (OrbStack)
  • /Applications/Docker.app/Contents/Resources/bin/docker (Docker Desktop)
  • ~/.docker/bin/docker (Docker Desktop alternative)

You can also manually specify the Docker path:

export DOCKER_PATH=/opt/homebrew/bin/docker
curl -fsSL https://raw.githubusercontent.com/BDuba/pinchtab-mcp-wrapper/main/install.sh | bash

Manual Installation

# Clone
git clone https://github.com/BDuba/pinchtab-mcp-wrapper.git
cd pinchtab-mcp-wrapper

# Build
npm install && npm run build

# Build Docker image
docker build -f pinchtab.Dockerfile -t pinchtab:local .

# Create wrapper
cat > run-mcp.sh << 'EOF'
#!/bin/bash
export PINCHTAB_MODE=docker
export PINCHTAB_TOKEN=opencode-browser-token-secure
export PINCHTAB_DOCKER_IMAGE=pinchtab:local
exec node "$(dirname "$0")/dist/index.js"
EOF
chmod +x run-mcp.sh

Configuration

Screenshot File Delivery (New)

When using delivery: "file", you can now use relative paths and auto-naming:

{
  "tool": "screenshot",
  "params": {
    "delivery": "file"
    // Auto-saved to: ~/Pictures/Screenshots/2026-02-21T12-34-56-tab-123.jpg
  }
}
{
  "tool": "screenshot",
  "params": {
    "delivery": "file",
    "path": "google/homepage.jpg"
    // Saved to: ~/Pictures/Screenshots/google/homepage.jpg
  }
}
{
  "tool": "screenshot",
  "params": {
    "delivery": "file",
    "path": "/absolute/path/to/screenshot.png"
    // Absolute paths still work as before
  }
}
Variable Description Default
SCREENSHOTS_DIR Base directory for screenshots OS-specific (~/Pictures/Screenshots)
SCREENSHOTS_AUTO_CREATE Auto-create directories true
SCREENSHOTS_PATTERN Filename pattern {timestamp}-{tabId}.jpg

Environment Variables

# Transport (v0.5.0+)
MCP_TRANSPORT=stdio               # stdio | streamable-http | sse
MCP_HTTP_PORT=3000                # HTTP server port
MCP_HTTP_HOST=0.0.0.0             # HTTP server host
MCP_AUTH_TYPE=none                # none | bearer | api-key
MCP_AUTH_TOKEN=secret-token       # Auth token for HTTP mode
MCP_ALLOWED_ORIGINS=*             # CORS origins

# Pinchtab connection
PINCHTAB_MODE=docker              # docker | external
PINCHTAB_TOKEN=secret-token       # Auth token
DEFAULT_SNAPSHOT_FORMAT=compact   # compact | text | json
DEFAULT_MAX_TOKENS=2500           # Token budget
SCREENSHOT_DEFAULT_DELIVERY=base64 # base64 | s3 | file

HTTP Mode (v0.5.0+)

Pinchtab MCP Wrapper now supports Streamable HTTP transport for remote/cloud deployments.

Use cases for HTTP mode:

  • Cloud deployments (AWS, GCP, Azure)
  • Remote AI agent access
  • Serverless architectures
  • Load balancing across multiple instances

Quick start with HTTP:

# Terminal 1: Start MCP server in HTTP mode
export MCP_TRANSPORT=streamable-http
export MCP_HTTP_PORT=3000
export MCP_AUTH_TYPE=bearer
export MCP_AUTH_TOKEN=your-secret-token
npm start

# Terminal 2: Test the HTTP endpoint
curl http://localhost:3000/health

HTTP Mode Configuration:

Variable Description Default
MCP_TRANSPORT Transport type stdio
MCP_HTTP_PORT HTTP server port 3000
MCP_HTTP_HOST HTTP server host 0.0.0.0
MCP_HTTP_PATH MCP endpoint path /mcp
MCP_AUTH_TYPE Auth type: none, bearer, api-key none
MCP_AUTH_TOKEN Auth token (required for bearer/api-key) -
MCP_ALLOWED_ORIGINS CORS allowed origins (comma-separated) *
MCP_ENABLE_SESSIONS Enable stateful sessions true
MCP_SESSION_TIMEOUT Session timeout in seconds 3600

Security best practices for HTTP mode:

  1. Always use authentication in production (MCP_AUTH_TYPE=bearer)
  2. Restrict CORS origins (MCP_ALLOWED_ORIGINS=https://yourdomain.com)
  3. Use HTTPS with a reverse proxy (nginx, traefik)
  4. Keep auth tokens secure and rotate regularly
    Streamable HTTP Endpoint Details:

When running in HTTP mode, the MCP server exposes:

Endpoint Method Description
http://host:port/mcp POST/GET Main MCP Streamable HTTP endpoint
http://host:port/health GET Health check endpoint
http://host:port/health GET
http://host:port/status GET Status endpoint (alias for health)

LobeChat Integration

For LobeChat v2 (and other HTTP-based MCP clients):

  1. Start MCP in HTTP mode (listening on all interfaces for Docker network access):
./run-mcp-http-all.sh
# or
export MCP_TRANSPORT=streamable-http
export MCP_HTTP_HOST=0.0.0.0
export MCP_HTTP_PORT=3001
export MCP_AUTH_TYPE=none
npm start
  1. Configure in LobeChat:

    • Go to SettingsPluginsMCP
    • Add new MCP server:
      • Name: pinchtab
      • Type: HTTP (or Streamable HTTP)
      • URL: http://172.21.0.1:3001/mcp (adjust IP based on your Docker network)
      • Auth Type: None
    • Click "Test Connection"
  2. Finding the correct IP address:

    • Check your Docker network: docker network inspect bridge
    • Find the gateway IP for your container network
    • Common values:
      • 172.17.0.1 - default Docker bridge
      • 172.21.0.1 - custom networks
      • host.docker.internal - Docker Desktop (Mac/Windows)

Note: The run-mcp-http-all.sh script listens on 0.0.0.0 to allow connections from any Docker container.
Example MCP Client Configuration:

// MCP Client Streamable HTTP configuration
{
  "mcpServers": {
    "pinchtab": {
      "transport": "streamable-http",
      "url": "http://localhost:3000/mcp",
      "headers": {
        "Authorization": "Bearer your-secret-token"
      }
    }
  }
}

HTTP Headers:

Header Required Description
Authorization If auth enabled Bearer <token> or raw token for api-key
Content-Type Yes application/json
Mcp-Session-Id Optional Session ID for stateful mode

Authentication Examples:

# Bearer token auth
curl -H "Authorization: Bearer your-secret-token" \
     http://localhost:3000/mcp

# API key auth (header)
curl -H "Authorization: your-api-key" \
     http://localhost:3000/mcp

# API key auth (query param)
curl "http://localhost:3000/mcp?api_key=your-api-key"

Connecting from AI Agents:

Most MCP clients support Streamable HTTP natively. Configure your AI agent with:

{
  "mcp": {
    "pinchtab": {
      "type": "http",
      "url": "http://your-server:3000/mcp",
      "headers": {
        "Authorization": "Bearer your-secret-token"
      }
    }
  }
}

Running Multiple AI Agents with One Pinchtab Instance

Scenario: You have multiple AI agents (OpenCode, LobeChat, Claude Code, Cursor, etc.) and want to use a single Pinchtab Docker container for all of them.

Problem: Each AI agent may require a different MCP transport (stdio for CLI agents, HTTP for server-based agents).

Solution: Use one Pinchtab container with multiple MCP servers:

┌─────────────────────────────────────────────────────────────┐
│                 Pinchtab Docker Container                   │
│                 (http://127.0.0.1:9867)                      │
└─────────────────────────┬───────────────────────────────────┘
                          │
┌─────────────────────────▼───────────────────────────────────┐
│              MCP Wrapper HTTP Server                        │
│              (http://0.0.0.0:3001/mcp)                      │
│   • LobeChat ───────┐  • Other HTTP clients ───┐            │
│   • Remote agents ──┘  • Cloud services ───────┘            │
└─────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────┐
│              MCP Wrapper stdio Servers                      │
│   • OpenCode ───────┐  • Claude Code ───────┐               │
│   • Cursor ─────────┘  • Zed ───────────────┘               │
└─────────────────────────────────────────────────────────────┘

Setup Steps:

  1. Start Pinchtab Docker container:
docker run -d \
  --name pinchtab \
  -p 127.0.0.1:9867:9867 \
  -e PINCHTAB_TOKEN=opencode-browser-token-secure \
  pinchtab:local
  1. Start HTTP MCP server for server-based agents (LobeChat, etc.):
export PINCHTAB_MODE=external
export PINCHTAB_URL=http://127.0.0.1:9867
export PINCHTAB_TOKEN=opencode-browser-token-secure
export MCP_TRANSPORT=streamable-http
export MCP_HTTP_PORT=3001
export MCP_HTTP_HOST=0.0.0.0
export MCP_AUTH_TYPE=none
export MCP_ENABLE_SESSIONS=true
node dist/index.js
  1. Configure CLI agents (OpenCode, Claude Code, Cursor, Zed) to use stdio:

  2. Configure server-based agents (LobeChat) to use HTTP:

    • URL: http://172.21.0.1:3001/mcp
    • Type: Streamable HTTP
    • Auth: None

Benefits:

  • Single Pinchtab instance for all AI agents
  • No port conflicts (stdio for CLI, HTTP for servers)
  • Resource efficient (one browser instance)
  • Consistent browser state across all agents

Making HTTP MCP server persistent:

sudo tee /etc/systemd/system/pinchtab-mcp.service << 'EOF'
[Unit]
Description=Pinchtab MCP HTTP Server
After=network.target docker.service

[Service]
Type=simple
User=root
WorkingDirectory=/root/.pinchtab-mcp-wrapper
ExecStart=/bin/bash -c 'export PINCHTAB_MODE=external && export PINCHTAB_URL=http://127.0.0.1:9867 && export PINCHTAB_TOKEN=opencode-browser-token-secure && export MCP_TRANSPORT=streamable-http && export MCP_HTTP_PORT=3001 && export MCP_HTTP_HOST=0.0.0.0 && export MCP_AUTH_TYPE=none && export MCP_ENABLE_SESSIONS=true && node dist/index.js'
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable pinchtab-mcp
sudo systemctl start pinchtab-mcp

Pinchtab Options (via Docker)

Pinchtab Options (via Docker)

PINCHTAB_MODE=docker              # docker | external
PINCHTAB_TOKEN=secret-token       # Auth token
DEFAULT_SNAPSHOT_FORMAT=compact   # compact | text | json
DEFAULT_MAX_TOKENS=2500           # Token budget
SCREENSHOT_DEFAULT_DELIVERY=base64 # base64 | s3 | file

Pinchtab Options (via Docker)

BRIDGE_STEALTH=full          # Bypass bot detection
BRIDGE_BLOCK_IMAGES=true     # Faster loading
BRIDGE_NO_ANIMATIONS=true    # Consistent snapshots
BRIDGE_TIMEOUT=30            # Action timeout (seconds)

Troubleshooting

Issue Solution
"Connection closed" Check docker ps, verify container running
"MCP error -32000" Restart AI agent completely
Health check timeout docker logs pinchtab for errors
401 errors Verify PINCHTAB_TOKEN matches

Token Efficiency Guide

Best practices for minimizing costs:

  1. Use /text for reading - 800 tokens vs 10,000 for DOM
  2. Filter interactives - 3,600 tokens vs 10,500 for full page
  3. Use diff=true - Only changed elements (50-200 tokens)
  4. Block images/media - Faster loading, less noise
  5. Lock tabs - Prevent conflicts, avoid re-work

Development

npm install
npm run build
npm test

Release History

See CHANGELOG.md for detailed version history and changes.

Latest release: v0.6.1 (2026-03-19)

  • E2E HTTP tests stability - Fixed intermittent timeouts in HTTP mode E2E tests
  • All v0.6.0 features included

Previous release (v0.6.0):

  • Pinchtab v0.7.8 support - Updated to stable Pinchtab version
  • Fixed MCP Streamable HTTP transport - Improved connection stability and error handling

Previous releases:

  • v0.5.1 - Pinchtab v0.6.3 support, file upload tool
  • v0.5.0 - Streamable HTTP transport, multi-transport architecture
  • v0.4.0 - CI/CD pipeline, ESLint, comprehensive test suite
  • v0.2.0 - Download tool, Pinchtab 0.6.1, multi-agent configuration

Credits & License

This MCP wrapper is built on Pinchtab by Luigi Agosti and contributors.

MIT License

Yorumlar (0)

Sonuc bulunamadi