13 Commits

Author SHA1 Message Date
Aaron Elijah Mars
99d31b15c8 Update opendia.dxt to version 1.0.5
🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-15 22:11:29 +02:00
Aaron Elijah Mars
a83df06513 Bump version to 1.0.5 and update installation instructions
- Update version to 1.0.5 in all package files and build script
- Add double-click .dxt installation as recommended option in README
- Keep npx option as alternative installation method

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-15 22:11:00 +02:00
Aaron Elijah Mars
05559b8b1d styling features 2025-07-15 20:15:02 +02:00
Aaron Elijah Mars
ca1a88776d bulk tabs (open + query + act) 2025-07-15 19:52:39 +02:00
Aaron Elijah Mars
14be38dd16 safety mode 2025-07-15 17:43:08 +02:00
Aaron Elijah Mars
aa78576ad7 autokill port + prompts 2025-07-15 17:33:03 +02:00
Aaron Elijah Mars
f57010971a Bump version to 1.0.4
Updated version in package.json and manifest.json for release 1.0.4

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-12 21:18:09 +02:00
Aaron Elijah Mars
e40805801a fix port assignment + license 2025-07-12 21:04:26 +02:00
Aaron Elijah Mars
c3c77c1e04 hosted mode w/ Ngrok + SSE 2025-07-12 20:30:15 +02:00
@aaronjmars
23eda72d91 Update README.md 2025-06-29 07:35:49 +02:00
@aaronjmars
b131e05513 Update README.md 2025-06-28 21:34:49 +02:00
Aaron Elijah Mars
019df3b3b0 v1 2025-06-28 21:28:52 +02:00
Aaron Elijah Mars
42e465045c v1 2025-06-28 21:27:42 +02:00
13 changed files with 3521 additions and 194 deletions

21
LICENSE Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2025 OpenDia Team
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

120
README.md
View File

@@ -1,9 +1,10 @@
# OpenDia <img src="opendia-extension/icon-128.png" alt="OpenDia" width="32" height="32">
> **The open alternative to Dia**
> Connect your browser to AI models. No browser switching needed—works seamlessly with any Chromium browser including Chrome & Arc.
**The open alternative to Dia**
Connect your browser to AI models. No browser switching needed—works seamlessly with any Chromium browser including Chrome & Arc.
[![npm version](https://badge.fury.io/js/opendia.svg)](https://badge.fury.io/js/opendia)
[![npm version](https://img.shields.io/npm/v/opendia)](https://www.npmjs.com/package/opendia)
[![GitHub release](https://img.shields.io/github/release/aaronjmars/opendia.svg)](https://github.com/aaronjmars/opendia/releases/latest)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
## 📺 See it in Action
@@ -15,7 +16,7 @@
OpenDia lets AI models control your browser automatically. **The key advantage? It leverages everything you already have**—your logged-in accounts, saved passwords, cookies, wallets, and browsing history. No need to start from scratch or switch contexts.
**🔑 Use Your Existing Digital Life:**
-**Logged-in accounts**: Post to Twitter / X, LinkedIn, Facebook with your existing sessions
-**Logged-in accounts**: Post to Twitter/X, LinkedIn, Facebook with your existing sessions
-**Browser data**: Access your bookmarks, history, and saved passwords
-**Extensions & wallets**: Use MetaMask, password managers, or any installed extensions
-**Cookies & sessions**: Stay authenticated across all your favorite sites
@@ -32,12 +33,11 @@ OpenDia lets AI models control your browser automatically. **The key advantage?
Works with **any Chromium-based browser**:
-**Google Chrome**
-**Arc Browser**
-**Arc**
-**Microsoft Edge**
-**Brave Browser**
-**Brave**
-**Opera**
-**Vivaldi**
-**Any Chromium variant**
-**Any Chromium based browser**
Perfect for **Cursor users** who want to automate their local testing and development workflows!
@@ -69,21 +69,30 @@ Perfect for **Cursor users** who want to automate their local testing and develo
- **"Monitor this webpage and notify me when the content changes"**
- **"Automatically bookmark interesting articles I'm reading"**
### 🎨 Visual Customization & Fun
- **"Apply a cyberpunk theme to this documentation site to make it more engaging"**
- **"Make this page dark mode with green text for late-night reading"**
- **"Add rainbow party effects to celebrate finishing this project"**
- **"Transform this boring form with a retro 80s theme while I fill it out"**
- **"Use high contrast styling so I can read this better"**
## ⚡ Quick Start
### 1. Start the Server
```bash
npx opendia
```
### 2. Install the Browser Extension
### 1. Install the Browser Extension
1. Download from [releases](https://github.com/aaronjmars/opendia/releases)
2. Go to `chrome://extensions/` (or your browser's extension page)
3. Enable "Developer mode"
4. Click "Load unpacked" and select the extension folder
### 3. Connect to Your AI
**For Claude Desktop**, add to your configuration:
### 2. Connect to Your AI
**Option 1: Double-click Installation (Recommended)**
1. Download the `opendia.dxt` file from [releases](https://github.com/aaronjmars/opendia/releases)
2. Double-click the `.dxt` file to install automatically
3. The MCP will be added to your Claude Desktop configuration
**Option 2: Manual Configuration**
Add to your Claude Desktop configuration:
```json
{
"mcpServers": {
@@ -97,9 +106,67 @@ npx opendia
**For Cursor or other AI tools**, use the same configuration or follow their specific setup instructions.
## Usage Modes
### Local Mode (Default)
```bash
npx opendia
```
- Chrome extension: ws://localhost:5555 (auto-discovery enabled)
- Claude Desktop: stdio (existing config)
- Local SSE: http://localhost:5556/sse
### Port Configuration
```bash
# Use custom ports
npx opendia --port=6000 # Uses 6000 (WebSocket) + 6001 (HTTP)
npx opendia --ws-port=5555 --http-port=5556 # Specify individually
# Handle port conflicts
# Note: Existing OpenDia processes are automatically terminated on startup
```
### Auto-Tunnel Mode
```bash
npx opendia --tunnel
```
- Automatically creates ngrok tunnel
- Copy URL for ChatGPT/online AI services
- Local functionality preserved
**Note**: For auto-tunneling to work, you need ngrok installed:
**macOS:**
```bash
brew install ngrok
```
**Windows:**
```bash
# Using Chocolatey
choco install ngrok
# Or download from https://ngrok.com/download
```
**Linux:**
```bash
# Ubuntu/Debian
curl -s https://ngrok-agent.s3.amazonaws.com/ngrok.asc | sudo tee /etc/apt/trusted.gpg.d/ngrok.asc >/dev/null
echo "deb https://ngrok-agent.s3.amazonaws.com buster main" | sudo tee /etc/apt/sources.list.d/ngrok.list
sudo apt update && sudo apt install ngrok
# Or download from https://ngrok.com/download
```
Then get your free authtoken from https://dashboard.ngrok.com/get-started/your-authtoken and run:
```bash
ngrok config add-authtoken YOUR_TOKEN_HERE
```
## 🛠️ Capabilities
OpenDia gives AI models **17 powerful browser tools**:
OpenDia gives AI models **18 powerful browser tools**:
### 🎯 Smart Page Understanding
- **Analyze any webpage** - AI automatically finds buttons, forms, and interactive elements
@@ -127,6 +194,13 @@ OpenDia gives AI models **17 powerful browser tools**:
- **Natural interactions** - Mimics human behavior to avoid triggering security measures
- **Reliable automation** - Works consistently even on sites that block typical automation tools
### 🎨 Page Styling & Customization
- **Transform any website** - Apply fun themes, custom colors, and visual effects
- **Preset themes** - Dark hacker, retro 80s, rainbow party, minimalist zen, and more
- **AI mood styling** - Describe a mood and get matching visual design
- **Interactive effects** - Matrix rain, floating particles, neon glow, and cursor trails
- **Accessibility themes** - High contrast and readable designs for better visibility
## 💬 Example Prompts to Try
Once everything is set up, try asking your AI:
@@ -149,6 +223,15 @@ Once everything is set up, try asking your AI:
**Personal Assistant:**
> *"Find that GitHub repo I was looking at yesterday about React components and bookmark it for later"*
**Page Styling & Fun:**
> *"Apply a dark hacker theme to this page to make it look more interesting"*
> *"Make this boring documentation page feel like a cozy coffee shop"*
> *"Add some matrix rain effects to this page for 30 seconds for a cool screenshot"*
> *"Transform this page with a high contrast theme for better readability"*
## 🏗️ How It Works
```mermaid
@@ -188,8 +271,9 @@ cd opendia-mcp
npm install
npm start
# Load extension in your browser
# Load extension in your browser
# Go to chrome://extensions/ → Developer mode → Load unpacked: ./opendia-extension
# Extension will auto-connect to server on localhost:5555
```
### Ways to Contribute

380
build-dxt.sh Executable file
View File

@@ -0,0 +1,380 @@
#!/bin/bash
# OpenDia DXT Build Script - Fixed Version
# Run this from the OpenDia project root directory
set -e # Exit on any error
echo "🚀 Building OpenDia DXT package..."
# Check if we're in the right directory
if [ ! -f "opendia-mcp/package.json" ]; then
echo "❌ Error: Please run this script from the OpenDia project root directory"
echo " Expected to find: opendia-mcp/package.json"
echo " Current directory: $(pwd)"
exit 1
fi
if [ ! -d "opendia-extension" ]; then
echo "❌ Error: opendia-extension directory not found"
exit 1
fi
# Clean and create dist directory
echo "🧹 Cleaning previous build..."
rm -rf dist
mkdir -p dist/opendia-dxt
echo "📦 Setting up package..."
# Copy server files
cp opendia-mcp/server.js dist/opendia-dxt/
# Create optimized package.json for DXT
cat > dist/opendia-dxt/package.json << 'EOF'
{
"name": "opendia",
"version": "1.0.5",
"description": "🎯 OpenDia - The open alternative to Dia. Connect your browser to AI models with anti-detection bypass for Twitter/X, LinkedIn, Facebook",
"main": "server.js",
"scripts": {
"start": "node server.js"
},
"keywords": [
"mcp",
"browser",
"automation",
"ai",
"claude",
"chrome",
"extension",
"twitter",
"linkedin",
"facebook",
"anti-detection",
"dxt"
],
"author": "Aaron Elijah Mars <aaronjmars@proton.me>",
"license": "MIT",
"dependencies": {
"cors": "^2.8.5",
"express": "^4.21.2",
"ws": "^8.18.0"
},
"engines": {
"node": ">=16.0.0"
}
}
EOF
# Install dependencies
echo "⬇️ Installing dependencies..."
cd dist/opendia-dxt
npm install --production --silent
cd ../..
# Copy browser extension
echo "🌐 Copying browser extension..."
cp -r opendia-extension dist/opendia-dxt/extension
# Copy logo/icon files for DXT - try multiple sources
echo "🎨 Copying logo files..."
LOGO_COPIED=false
# Try different icon files from the extension
for icon_file in "icon-128.png" "icon-48.png" "icon-32.png" "icon-16.png" "icon.png"; do
if [ -f "opendia-extension/$icon_file" ]; then
cp "opendia-extension/$icon_file" dist/opendia-dxt/icon.png
echo "✅ Logo copied from extension/$icon_file"
LOGO_COPIED=true
break
fi
done
# If no extension icon found, check root directory
if [ "$LOGO_COPIED" = false ]; then
for icon_file in "icon.png" "logo.png" "opendia.png"; do
if [ -f "$icon_file" ]; then
cp "$icon_file" dist/opendia-dxt/icon.png
echo "✅ Logo copied from $icon_file"
LOGO_COPIED=true
break
fi
done
fi
# Create a simple placeholder if no icon found
if [ "$LOGO_COPIED" = false ]; then
echo "⚠️ No logo file found, you may need to add icon.png manually to dist/opendia-dxt/"
fi
# Create DXT manifest - CORRECT FORMAT BASED ON WORKING EXAMPLES
echo "📋 Creating DXT manifest..."
cat > dist/opendia-dxt/manifest.json << 'EOF'
{
"dxt_version": "0.1",
"name": "opendia",
"display_name": "OpenDia - Browser Automation",
"version": "1.0.5",
"description": "🎯 OpenDia - The open alternative to Dia. Connect your browser to AI models with anti-detection bypass for Twitter/X, LinkedIn, Facebook + universal automation",
"author": {
"name": "Aaron Elijah Mars",
"email": "aaronjmars@proton.me",
"url": "https://github.com/aaronjmars/opendia"
},
"homepage": "https://github.com/aaronjmars/opendia",
"license": "MIT",
"keywords": ["browser", "automation", "mcp", "ai", "claude", "chrome", "extension", "twitter", "linkedin", "facebook", "anti-detection"],
"icon": "icon.png",
"icons": {
"128": "icon.png"
},
"server": {
"type": "node",
"entry_point": "server.js",
"mcp_config": {
"command": "node",
"args": ["${__dirname}/server.js"],
"env": {
"NODE_ENV": "production",
"WS_PORT": "${user_config.ws_port}",
"HTTP_PORT": "${user_config.http_port}",
"ENABLE_TUNNEL": "${user_config.enable_tunnel}",
"SAFETY_MODE": "${user_config.safety_mode}"
}
}
},
"user_config": {
"ws_port": {
"type": "number",
"title": "WebSocket Port",
"description": "Port for Chrome extension connection",
"default": 5555,
"minimum": 1024,
"maximum": 65535
},
"http_port": {
"type": "number",
"title": "HTTP Port",
"description": "Port for HTTP/SSE server",
"default": 5556,
"minimum": 1024,
"maximum": 65535
},
"enable_tunnel": {
"type": "boolean",
"title": "Auto-Tunnel",
"description": "Automatically create ngrok tunnel for online AI access (requires ngrok)",
"default": false
},
"safety_mode": {
"type": "boolean",
"title": "Safety Mode",
"description": "Block write/edit tools (element_click, element_fill) by default",
"default": false
}
},
"tools": [
{
"name": "page_analyze",
"description": "🔍 Analyze any tab without switching! Two-phase intelligent page analysis"
},
{
"name": "page_extract_content",
"description": "📄 Extract content from any tab without switching!"
},
{
"name": "element_click",
"description": "🖱️ Click elements with anti-detection bypass for social platforms"
},
{
"name": "element_fill",
"description": "✏️ Fill forms with anti-detection bypass for Twitter/X, LinkedIn, Facebook"
},
{
"name": "page_navigate",
"description": "🧭 Navigate to URLs with wait conditions"
},
{
"name": "page_wait_for",
"description": "⏳ Wait for elements or conditions"
},
{
"name": "tab_create",
"description": "📱 Create single or multiple tabs with batch support"
},
{
"name": "tab_close",
"description": "❌ Close specific tab(s) by ID"
},
{
"name": "tab_list",
"description": "📋 Get list of all open tabs with IDs"
},
{
"name": "tab_switch",
"description": "🔄 Switch to specific tab by ID"
},
{
"name": "element_get_state",
"description": "🔍 Get detailed element state information"
},
{
"name": "get_bookmarks",
"description": "📚 Get all bookmarks or search for specific ones"
},
{
"name": "add_bookmark",
"description": " Add new bookmark"
},
{
"name": "get_history",
"description": "🕒 Search browser history with comprehensive filters"
},
{
"name": "get_selected_text",
"description": "📝 Get selected text from any tab"
},
{
"name": "page_scroll",
"description": "📜 Scroll any tab without switching"
},
{
"name": "get_page_links",
"description": "🔗 Get all hyperlinks with smart filtering"
},
{
"name": "page_style",
"description": "🎨 Transform page appearance with themes and effects"
}
],
"capabilities": {
"browser_automation": true,
"anti_detection": true,
"background_tabs": true,
"multi_tab_workflows": true,
"content_extraction": true,
"form_filling": true,
"social_media_posting": true,
"page_styling": true,
"bookmark_management": true,
"history_search": true,
"tab_management": true
},
"requirements": {
"chrome_extension": {
"name": "OpenDia Browser Extension",
"description": "Required Chrome extension for browser automation by Aaron Elijah Mars",
"version": "1.0.5",
"auto_install": false
}
}
}
EOF
# Validate JSON syntax
echo "🔍 Validating manifest.json..."
if ! python3 -m json.tool dist/opendia-dxt/manifest.json > /dev/null 2>&1; then
echo "❌ Error: Invalid JSON in manifest.json"
exit 1
fi
echo "✅ Manifest JSON is valid"
# Copy documentation
echo "📝 Adding documentation..."
cp README.md dist/opendia-dxt/ 2>/dev/null || echo "⚠️ README.md not found, skipping"
cp LICENSE dist/opendia-dxt/ 2>/dev/null || echo "⚠️ LICENSE not found, skipping"
# Create extension installation guide
cat > dist/opendia-dxt/EXTENSION_INSTALL.md << 'EOF'
# OpenDia Chrome Extension Installation
## Quick Setup
1. **Enable Developer Mode**
- Go to `chrome://extensions/`
- Toggle "Developer mode" in the top right
2. **Install Extension**
- Click "Load unpacked"
- Select the `extension/` folder from this DXT package
- Extension should appear in your extensions list
3. **Verify Connection**
- Click the OpenDia extension icon
- Should show "Connected to MCP server"
- Green status indicator means ready to use
## Supported Browsers
- Google Chrome, Arc Browser, Microsoft Edge, Brave Browser, Opera
- Any Chromium-based browser
## Features
🎯 Anti-detection bypass for Twitter/X, LinkedIn, Facebook
📱 Smart automation and page analysis
🔧 Form filling with enhanced compatibility
📊 Multi-tab workflows and background operations
🎨 Page styling and visual customization
For more help, visit: https://github.com/aaronjmars/opendia
EOF
# Verify structure before zipping
echo "🔍 Verifying DXT structure..."
echo "📋 Files in DXT directory:"
ls -la dist/opendia-dxt/
# Check if icon exists and show its details
if [ -f "dist/opendia-dxt/icon.png" ]; then
echo "✅ Icon file found:"
file dist/opendia-dxt/icon.png
ls -lh dist/opendia-dxt/icon.png
else
echo "❌ Icon file missing!"
fi
# Verify manifest.json exists and is at root level
if [ ! -f "dist/opendia-dxt/manifest.json" ]; then
echo "❌ Error: manifest.json not found!"
exit 1
fi
echo "✅ Structure verified"
# Create the DXT archive - CRITICAL: ZIP from inside the directory
echo "🗜️ Creating DXT archive..."
cd dist/opendia-dxt
zip -r ../opendia.dxt . -q
cd ../..
# Verify the DXT file structure
echo "🔍 Verifying DXT file contents..."
if ! unzip -l dist/opendia.dxt | grep -q "manifest.json"; then
echo "❌ Error: manifest.json not found in DXT file!"
echo "DXT contents:"
unzip -l dist/opendia.dxt
exit 1
fi
# Get file size
DXT_SIZE=$(du -h dist/opendia.dxt | cut -f1)
echo ""
echo "✅ DXT package created successfully!"
echo "📦 File: dist/opendia.dxt"
echo "💾 Size: $DXT_SIZE"
echo ""
echo "📋 DXT Contents:"
unzip -l dist/opendia.dxt | head -10
echo ""
echo "🚀 Installation:"
echo "1. Double-click the .dxt file"
echo "2. Or: Claude Desktop Settings → Extensions → Install Extension"
echo "3. Install Chrome extension from extension/ folder"
echo ""
echo "🎯 Features ready: Anti-detection bypass + universal automation"

File diff suppressed because it is too large Load Diff

View File

@@ -283,6 +283,13 @@ class BrowserAutomation {
case "page_scroll":
result = await this.scrollPage(data);
break;
case "page_style":
result = await this.handlePageStyle(data);
break;
case "ping":
// Health check for background tab content script readiness
result = { status: "ready", timestamp: Date.now(), url: window.location.href };
break;
default:
throw new Error(`Unknown action: ${action}`);
}
@@ -2503,7 +2510,375 @@ class BrowserAutomation {
};
}
}
// 🎨 Page Styling System
async handlePageStyle(data) {
const { mode, theme, background, text_color, font, font_size, mood, intensity, effect, duration, remember } = data;
// Remove existing custom styles
const existingStyle = document.getElementById('opendia-custom-style');
if (existingStyle) existingStyle.remove();
let css = '';
let description = '';
try {
switch (mode) {
case 'preset':
const themeData = THEME_PRESETS[theme];
if (!themeData) throw new Error(`Unknown theme: ${theme}`);
css = themeData.css;
description = `Applied ${themeData.name} theme`;
break;
case 'custom':
css = this.buildCustomCSS({ background, text_color, font, font_size });
description = 'Applied custom styling';
break;
case 'ai_mood':
css = this.generateMoodCSS(mood, intensity);
description = `Applied AI-generated style for mood: "${mood}"`;
break;
case 'effect':
css = this.applyEffect(effect, duration);
description = `Applied ${effect} effect for ${duration}s`;
break;
case 'reset':
// CSS already removed above
description = 'Reset page to original styling';
break;
default:
throw new Error(`Unknown styling mode: ${mode}`);
}
if (css) {
const styleElement = document.createElement('style');
styleElement.id = 'opendia-custom-style';
styleElement.textContent = css;
document.head.appendChild(styleElement);
}
// Remember preference if requested
if (remember && mode !== 'reset') {
const domain = window.location.hostname;
chrome.storage.local.set({ [`style_${domain}`]: { mode, theme, css } });
}
return {
success: true,
description,
applied_css: css.length,
mode,
theme: theme || 'custom',
remember_enabled: remember,
effect_duration: duration,
mood,
intensity
};
} catch (error) {
return {
success: false,
error: error.message,
mode,
theme,
applied_css: 0
};
}
}
buildCustomCSS({ background, text_color, font, font_size }) {
let css = '';
if (background || text_color || font || font_size) {
css += '* { ';
if (background) css += `background: ${background} !important; `;
if (text_color) css += `color: ${text_color} !important; `;
if (font) css += `font-family: ${font} !important; `;
if (font_size) css += `font-size: ${font_size} !important; `;
css += '}';
}
return css;
}
generateMoodCSS(mood, intensity) {
const moodMap = {
'cozy coffee shop': {
background: '#2c1810',
text: '#f4e4bc',
accent: '#d4af37',
font: 'Georgia, serif'
},
'energetic': {
background: 'linear-gradient(45deg, #ff6b35, #f7931e)',
text: '#ffffff',
effects: 'animation: energyPulse 1s infinite;'
},
'calm ocean': {
background: 'linear-gradient(to bottom, #87ceeb, #4682b4)',
text: '#ffffff',
effects: 'animation: gentleWave 4s ease-in-out infinite;'
},
'dark professional': {
background: '#1a1a1a',
text: '#e0e0e0',
accent: '#0066cc'
},
'warm sunset': {
background: 'linear-gradient(to bottom, #ff7e5f, #feb47b)',
text: '#ffffff'
}
};
const style = moodMap[mood.toLowerCase()] || moodMap['cozy coffee shop'];
return this.buildMoodCSS(style, intensity);
}
buildMoodCSS(style, intensity) {
const opacity = intensity === 'subtle' ? '0.3' : intensity === 'medium' ? '0.6' : '0.9';
let css = `
body {
background: ${style.background} !important;
color: ${style.text} !important;
${style.font ? `font-family: ${style.font} !important;` : ''}
}
* {
color: ${style.text} !important;
}
a {
color: ${style.accent || style.text} !important;
}
`;
if (style.effects) {
css += style.effects;
}
// Add animation keyframes if needed
if (style.effects && style.effects.includes('energyPulse')) {
css += `
@keyframes energyPulse {
0%, 100% { filter: hue-rotate(0deg); }
50% { filter: hue-rotate(180deg); }
}
`;
}
if (style.effects && style.effects.includes('gentleWave')) {
css += `
@keyframes gentleWave {
0%, 100% { background-position: 0% 50%; }
50% { background-position: 100% 50%; }
}
`;
}
return css;
}
applyEffect(effect, duration) {
const effects = {
matrix_rain: `
body::after {
content: '';
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><text y="10" font-size="8" fill="%2300ff00">0</text><text y="20" font-size="8" fill="%2300ff00">1</text><text y="30" font-size="8" fill="%2300ff00">0</text><text y="40" font-size="8" fill="%2300ff00">1</text></svg>');
animation: matrixFall 2s linear infinite;
pointer-events: none;
z-index: 9999;
opacity: 0.7;
}
@keyframes matrixFall {
from { transform: translateY(-100px); }
to { transform: translateY(100vh); }
}
`,
floating_particles: `
body::before {
content: '✨ 🌟 ⭐ 💫';
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
animation: floatParticles 6s ease-in-out infinite;
pointer-events: none;
z-index: 9999;
font-size: 20px;
}
@keyframes floatParticles {
0%, 100% { transform: translateY(100vh) rotate(0deg); }
50% { transform: translateY(-100px) rotate(180deg); }
}
`,
cursor_trail: `
body {
cursor: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20"><circle cx="10" cy="10" r="8" fill="rgba(255,0,255,0.5)"/></svg>'), auto !important;
}
`,
neon_glow: `
* {
text-shadow: 0 0 10px #00ffff, 0 0 20px #00ffff, 0 0 30px #00ffff !important;
}
a, button {
box-shadow: 0 0 15px #ff00ff !important;
}
`,
typing_effect: `
* {
animation: typewriter 2s steps(40, end) infinite !important;
}
@keyframes typewriter {
from { width: 0; }
to { width: 100%; }
}
`
};
const css = effects[effect] || '';
// Auto-remove effect after duration
if (duration && duration > 0) {
setTimeout(() => {
const effectStyle = document.getElementById('opendia-custom-style');
if (effectStyle) effectStyle.remove();
}, duration * 1000);
}
return css;
}
}
// Theme Presets Database
const THEME_PRESETS = {
"dark_hacker": {
name: "🖤 Dark Hacker",
css: `
* {
background: #0a0a0a !important;
color: #00ff00 !important;
font-family: 'Courier New', monospace !important;
}
a { color: #00ffff !important; }
body::before {
content: ''; position: fixed; top: 0; left: 0; width: 100%; height: 100%;
background: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><text y="50" font-size="10" fill="%23003300">01010101</text></svg>');
opacity: 0.1; pointer-events: none; z-index: -1;
}
`
},
"retro_80s": {
name: "📼 Retro 80s",
css: `
* {
background: linear-gradient(45deg, #ff0080, #8000ff) !important;
color: #ffffff !important;
font-family: 'Arial Black', sans-serif !important;
text-shadow: 2px 2px 4px #000000 !important;
}
body { animation: retroPulse 2s infinite; }
@keyframes retroPulse { 0%, 100% { filter: hue-rotate(0deg); } 50% { filter: hue-rotate(180deg); } }
`
},
"rainbow_party": {
name: "🌈 Rainbow Party",
css: `
body {
background: linear-gradient(45deg, red, orange, yellow, green, blue, indigo, violet) !important;
background-size: 400% 400% !important;
animation: rainbowShift 3s ease infinite !important;
}
@keyframes rainbowShift {
0%, 100% { background-position: 0% 50%; }
50% { background-position: 100% 50%; }
}
* { color: white !important; text-shadow: 1px 1px 2px black !important; }
`
},
"minimalist_zen": {
name: "🧘 Minimalist Zen",
css: `
* {
background: #f8f8f8 !important;
color: #333333 !important;
font-family: 'Georgia', serif !important;
line-height: 1.6 !important;
}
body { max-width: 800px; margin: 0 auto; padding: 20px; }
`
},
"high_contrast": {
name: "🔍 High Contrast",
css: `
* {
background: #000000 !important;
color: #ffffff !important;
font-family: Arial, sans-serif !important;
font-weight: bold !important;
}
a { color: #ffff00 !important; }
`
},
"cyberpunk": {
name: "🤖 Cyberpunk",
css: `
* {
background: #0d1117 !important;
color: #ff006e !important;
font-family: 'Courier New', monospace !important;
}
a { color: #00ffff !important; }
body {
background-image:
linear-gradient(90deg, transparent 79px, #abced4 79px, #abced4 81px, transparent 81px),
linear-gradient(#eee .1em, transparent .1em);
background-size: 81px 1.2em;
}
`
},
"pastel_dream": {
name: "🌸 Pastel Dream",
css: `
* {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
color: #2c3e50 !important;
font-family: 'Comic Sans MS', cursive !important;
}
body { filter: sepia(20%) saturate(80%); }
`
},
"newspaper": {
name: "📰 Newspaper",
css: `
* {
background: #ffffff !important;
color: #000000 !important;
font-family: 'Times New Roman', serif !important;
line-height: 1.4 !important;
}
body {
column-count: 2;
column-gap: 2em;
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}
`
}
};
// Initialize the automation system
const browserAutomation = new BrowserAutomation();

View File

@@ -1,7 +1,7 @@
{
"manifest_version": 3,
"name": "OpenDia",
"version": "1.0.0",
"version": "1.0.5",
"description": "Browser automation through Model Context Protocol",
"icons": {
"16": "icon-16.png",

View File

@@ -236,6 +236,80 @@
button:active {
transform: translateY(0);
}
.safety-mode {
background: rgba(255, 255, 255, 0.6);
padding: 16px;
border-radius: 10px;
margin-bottom: 16px;
border: 1px solid rgba(255, 255, 255, 0.8);
backdrop-filter: blur(20px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
}
.safety-row {
display: flex;
justify-content: space-between;
align-items: center;
}
.safety-label {
color: #374151;
font-weight: 600;
font-size: 0.875rem;
}
.safety-toggle {
position: relative;
display: inline-block;
width: 50px;
height: 24px;
}
.safety-toggle input {
opacity: 0;
width: 0;
height: 0;
}
.safety-slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #e5e7eb;
transition: 0.3s;
border-radius: 24px;
border: 1px solid rgba(0, 129, 247, 0.2);
}
.safety-slider:before {
position: absolute;
content: "";
height: 18px;
width: 18px;
left: 2px;
bottom: 2px;
background-color: white;
transition: 0.3s;
border-radius: 50%;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
}
input:checked + .safety-slider {
background: linear-gradient(135deg, #0081F7, #1d4ed8);
border-color: rgba(0, 129, 247, 0.4);
}
input:checked + .safety-slider:before {
transform: translateX(26px);
}
.safety-slider:hover {
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}
</style>
</head>
<body>
@@ -255,9 +329,9 @@
<span id="statusText" class="tooltip">
Checking connection...
<span class="tooltip-content">
Make sure your MCP server is connected.
If it's the case, click on Reconnect.
If it still don't work, kill your 3000 port & try again.
Start server with: npx opendia
Auto-discovery will find the correct ports.
Existing processes are automatically terminated on startup
</span>
</span>
</div>
@@ -265,7 +339,7 @@
<div class="info">
<div class="info-row">
<span class="info-label">Server</span>
<span class="info-value" id="serverUrl">ws://localhost:3000</span>
<span class="info-value" id="serverUrl">Auto-Discovery</span>
</div>
<div class="info-row">
<span class="info-label">Available Tools</span>
@@ -277,6 +351,21 @@
</div>
</div>
<div class="safety-mode">
<div class="safety-row">
<span class="safety-label tooltip">
Safety Mode
<span class="tooltip-content">
When enabled, blocks write/edit tools: element_click, element_fill
</span>
</span>
<label class="safety-toggle">
<input type="checkbox" id="safetyMode">
<span class="safety-slider"></span>
</label>
</div>
</div>
<div class="button-group">
<button id="reconnectBtn">Reconnect</button>
</div>

View File

@@ -3,6 +3,7 @@ let statusIndicator = document.getElementById("statusIndicator");
let statusText = document.getElementById("statusText");
let toolCount = document.getElementById("toolCount");
let currentPage = document.getElementById("currentPage");
let serverUrl = document.getElementById("serverUrl");
// Get dynamic tool count from background script
function updateToolCount() {
@@ -59,16 +60,31 @@ function checkStatus() {
checkStatus();
setInterval(checkStatus, 2000);
// Update server URL display
function updateServerUrl() {
if (chrome.runtime?.id) {
chrome.runtime.sendMessage({ action: "getPorts" }, (response) => {
if (!chrome.runtime.lastError && response?.websocketUrl) {
serverUrl.textContent = response.websocketUrl;
}
});
}
}
// Update server URL periodically
updateServerUrl();
setInterval(updateServerUrl, 5000);
// Update UI based on connection status
function updateStatus(connected) {
if (connected) {
statusIndicator.className = "status-indicator connected";
statusText.innerHTML = `Connected to MCP server
<span class="tooltip-content">Make sure your MCP server is connected. If it's the case, click on Reconnect. If it still don't work, kill your 3000 port & try again.</span>`;
<span class="tooltip-content">Connected successfully! Server auto-discovery is working. Default ports: WebSocket=5555, HTTP=5556</span>`;
} else {
statusIndicator.className = "status-indicator disconnected";
statusText.innerHTML = `Disconnected from MCP server
<span class="tooltip-content">Make sure your MCP server is connected. If it's the case, click on Reconnect. If it still don't work, kill your 3000 port & try again.</span>`;
<span class="tooltip-content">Start server with: npx opendia. Auto-discovery will find the correct ports. Existing processes are automatically terminated on startup</span>`;
}
}
@@ -84,6 +100,29 @@ document.getElementById("reconnectBtn").addEventListener("click", () => {
});
// Safety Mode Management
const safetyModeToggle = document.getElementById("safetyMode");
// Load safety mode state from storage
chrome.storage.local.get(['safetyMode'], (result) => {
const safetyEnabled = result.safetyMode || false; // Default to false (safety off)
safetyModeToggle.checked = safetyEnabled;
});
// Handle safety mode toggle changes
safetyModeToggle.addEventListener('change', () => {
const safetyEnabled = safetyModeToggle.checked;
// Save to storage
chrome.storage.local.set({ safetyMode: safetyEnabled });
// Notify background script
chrome.runtime.sendMessage({
action: "setSafetyMode",
enabled: safetyEnabled
});
});
// Listen for updates from background script
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (message.type === "statusUpdate") {

208
opendia-mcp/README.md Normal file
View File

@@ -0,0 +1,208 @@
# OpenDia <img src="opendia-extension/icon-128.png" alt="OpenDia" width="32" height="32">
> **The open alternative to Dia**
> Connect your browser to AI models. No browser switching needed—works seamlessly with any Chromium browser including Chrome & Arc.
[![npm version](https://badge.fury.io/js/opendia.svg)](https://badge.fury.io/js/opendia)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
## 📺 See it in Action
![OpenDia Demo](./preview.gif)
## 🚀 What is OpenDia?
OpenDia lets AI models control your browser automatically. **The key advantage? It leverages everything you already have**—your logged-in accounts, saved passwords, cookies, wallets, and browsing history. No need to start from scratch or switch contexts.
**🔑 Use Your Existing Digital Life:**
-**Logged-in accounts**: Post to Twitter / X, LinkedIn, Facebook with your existing sessions
-**Browser data**: Access your bookmarks, history, and saved passwords
-**Extensions & wallets**: Use MetaMask, password managers, or any installed extensions
-**Cookies & sessions**: Stay authenticated across all your favorite sites
-**Local testing**: Perfect for development with Cursor - test with real user sessions
**✨ Key Benefits:**
- 🔄 **Universal AI Support**: Works with Claude, ChatGPT, Cursor and even local models
- 🎯 **Anti-Detection**: Specialized bypasses for Twitter/X, LinkedIn, Facebook
- 📱 **Smart Automation**: AI understands your pages and finds the right elements
- 🛡️ **Privacy-First**: Everything runs locally, your data stays with you
-**Zero Setup**: Get started with one command
## 🌐 Browser Support
Works with **any Chromium-based browser**:
-**Google Chrome**
-**Arc Browser**
-**Microsoft Edge**
-**Brave Browser**
-**Opera**
-**Vivaldi**
-**Any Chromium variant**
Perfect for **Cursor users** who want to automate their local testing and development workflows!
## 🎬 What You Can Do
**Real workflows you can try today:**
### 📰 Content & Social Media
- **"Summarize all the articles I read today and post a Twitter thread about the key insights"**
- **"Find interesting articles related to AI from my bookmarks and create a reading list"**
- **"Read this article and post a thoughtful comment on the LinkedIn version"**
- **"Check my recent Twitter bookmarks and summarize the main themes"**
### 📧 Productivity & Research
- **"Browse my latest emails and tell me what needs urgent attention"**
- **"Find all the GitHub repos I visited this week and create a summary report"**
- **"Extract the main points from this research paper and save them to my notes"**
- **"Search my browsing history for that article about AI safety I read last month"**
### 🤖 Development & Testing (Perfect for Cursor!)
- **"Test my web app's signup flow and take screenshots at each step"**
- **"Fill out this form with test data and check if validation works"**
- **"Navigate through my app and check if all the buttons work properly"**
- **"Use my connected wallet to test this DeFi interface"**
### 🔄 Advanced Automation
- **"Open tabs for all my daily news sources and summarize the top stories"**
- **"Draft replies to my unread messages based on the context"**
- **"Monitor this webpage and notify me when the content changes"**
- **"Automatically bookmark interesting articles I'm reading"**
## ⚡ Quick Start
### 1. Start the Server
```bash
npx opendia
```
### 2. Install the Browser Extension
1. Download from [releases](https://github.com/aaronjmars/opendia/releases)
2. Go to `chrome://extensions/` (or your browser's extension page)
3. Enable "Developer mode"
4. Click "Load unpacked" and select the extension folder
### 3. Connect to Your AI
**For Claude Desktop**, add to your configuration:
```json
{
"mcpServers": {
"opendia": {
"command": "npx",
"args": ["opendia"]
}
}
}
```
**For Cursor or other AI tools**, use the same configuration or follow their specific setup instructions.
## 🛠️ Capabilities
OpenDia gives AI models **17 powerful browser tools**:
### 🎯 Smart Page Understanding
- **Analyze any webpage** - AI automatically finds buttons, forms, and interactive elements
- **Extract content intelligently** - Get clean text from articles, social posts, or search results
- **Understand context** - AI knows what type of page it's looking at and how to interact with it
### 🖱️ Natural Interactions
- **Click anything** - Buttons, links, menus - AI finds and clicks the right elements
- **Fill forms smartly** - Works even on complex sites like Twitter, LinkedIn, Facebook
- **Navigate seamlessly** - Go to pages, scroll, wait for content to load
- **Handle modern web apps** - Bypasses detection on social platforms
### 📑 Tab & Window Management
- **Multi-tab workflows** - Open, close, switch between tabs automatically
- **Organize your workspace** - Let AI manage your browser tabs efficiently
- **Coordinate complex tasks** - Work across multiple sites simultaneously
### 📊 Access Your Browser Data
- **Bookmarks & History** - Find that article you read last week
- **Current page content** - Get selected text, links, or full page content
- **Real-time information** - Work with whatever's currently on your screen
### 🛡️ Anti-Detection Features
- **Social media posting** - Bypass automation detection on Twitter/X, LinkedIn, Facebook
- **Natural interactions** - Mimics human behavior to avoid triggering security measures
- **Reliable automation** - Works consistently even on sites that block typical automation tools
## 💬 Example Prompts to Try
Once everything is set up, try asking your AI:
**Content Creation:**
> *"Read the article on this page and create a Twitter thread summarizing the main points"*
**Research & Analysis:**
> *"Look through my browser history from this week and find articles about machine learning. Summarize the key trends."*
**Social Media Management:**
> *"Check my Twitter bookmarks and organize them into categories. Create a summary of each category."*
**Productivity:**
> *"Open tabs for my usual morning reading sites and give me a briefing of today's top stories"*
**Development Testing:**
> *"Fill out this contact form with test data and check if the submission works properly"*
**Personal Assistant:**
> *"Find that GitHub repo I was looking at yesterday about React components and bookmark it for later"*
## 🏗️ How It Works
```mermaid
graph LR
A[AI Model] --> B[OpenDia Server]
B --> C[Browser Extension]
C --> D[Your Browser]
D --> E[Any Website]
```
1. **You ask** your AI to do something browser-related
2. **AI calls** OpenDia tools to understand and interact with pages
3. **OpenDia controls** your browser through the extension
4. **You get results** - AI can see what happened and respond intelligently
## 🔒 Security & Privacy
**Your data stays private**:
-**Everything runs locally** - No cloud processing of your browsing data
-**You control access** - Extension only works when you want it to
-**Open source** - Full transparency of what the code does
-**No tracking** - We don't collect or store any of your information
**Important**: This tool requires broad browser permissions to function. Only use with AI models you trust, and in environments where you're comfortable with browser automation.
## 🤝 Contributing
Love to have your help making OpenDia better!
### Quick Development Setup
```bash
git clone https://github.com/aaronjmars/opendia.git
cd opendia
# Start the server
cd opendia-mcp
npm install
npm start
# Load extension in your browser
# Go to chrome://extensions/ → Developer mode → Load unpacked: ./opendia-extension
```
### Ways to Contribute
- 🐛 **Report bugs** via [GitHub Issues](https://github.com/aaronjmars/opendia/issues)
- 💡 **Share it on social medias**
- 🔧 **Add new browser capabilities**
- 📖 **Improve documentation**
- 🧪 **Test with different AI models**
## 📝 License
MIT License - see [LICENSE](LICENSE) for details.
---
**Ready to supercharge your browser with AI? Get started with `npx opendia`! 🚀**

View File

@@ -1,15 +1,23 @@
{
"name": "opendia-server",
"version": "1.0.0",
"name": "opendia",
"version": "1.0.5",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "opendia-server",
"version": "1.0.0",
"name": "opendia",
"version": "1.0.5",
"license": "MIT",
"dependencies": {
"express": "^4.x.x",
"ws": "^8.x.x"
"cors": "^2.8.5",
"express": "^4.21.2",
"ws": "^8.18.0"
},
"bin": {
"opendia": "server.js"
},
"engines": {
"node": ">=16.0.0"
}
},
"node_modules/accepts": {
@@ -78,7 +86,7 @@
}
},
"node_modules/call-bound": {
"version": "1.0.4",
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
"integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
"license": "MIT",
@@ -129,6 +137,19 @@
"integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==",
"license": "MIT"
},
"node_modules/cors": {
"version": "2.8.5",
"resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
"integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
"license": "MIT",
"dependencies": {
"object-assign": "^4",
"vary": "^1"
},
"engines": {
"node": ">= 0.10"
}
},
"node_modules/debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
@@ -522,6 +543,15 @@
"node": ">= 0.6"
}
},
"node_modules/object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/object-inspect": {
"version": "1.13.4",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",

View File

@@ -1,13 +1,51 @@
{
"name": "opendia-server",
"version": "1.0.0",
"description": "MCP Server for OpenDia Browser Bridge",
"name": "opendia",
"version": "1.0.5",
"description": "🎯 OpenDia - The open alternative to Dia. Connect your browser to AI models with anti-detection bypass for Twitter/X, LinkedIn, Facebook",
"main": "server.js",
"bin": {
"opendia": "./server.js"
},
"scripts": {
"start": "node server.js"
"start": "node server.js",
"tunnel": "node server.js --tunnel",
"sse-only": "node server.js --sse-only",
"tunnel-sse": "node server.js --tunnel --sse-only",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
"mcp",
"browser",
"automation",
"ai",
"claude",
"chrome",
"extension",
"twitter",
"linkedin",
"facebook",
"anti-detection"
],
"author": "OpenDia Team",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/aaronjmars/opendia.git"
},
"homepage": "https://github.com/aaronjmars/opendia",
"bugs": {
"url": "https://github.com/aaronjmars/opendia/issues"
},
"dependencies": {
"ws": "^8.x.x",
"express": "^4.x.x"
}
}
"cors": "^2.8.5",
"express": "^4.21.2",
"ws": "^8.18.0"
},
"engines": {
"node": ">=16.0.0"
},
"files": [
"server.js",
"README.md"
]
}

1491
opendia-mcp/server.js Normal file → Executable file

File diff suppressed because it is too large Load Diff

BIN
opendia.dxt Normal file

Binary file not shown.