mirror of
https://github.com/aaronjmars/opendia.git
synced 2025-12-29 16:16:00 +00:00
works on X
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -32,7 +32,9 @@ async function handleMCPRequest(request) {
|
|||||||
switch (method) {
|
switch (method) {
|
||||||
case "initialize":
|
case "initialize":
|
||||||
// RESPOND IMMEDIATELY - don't wait for extension
|
// RESPOND IMMEDIATELY - don't wait for extension
|
||||||
console.error(`MCP client initializing: ${params?.clientInfo?.name || "unknown"}`);
|
console.error(
|
||||||
|
`MCP client initializing: ${params?.clientInfo?.name || "unknown"}`
|
||||||
|
);
|
||||||
result = {
|
result = {
|
||||||
protocolVersion: "2024-11-05",
|
protocolVersion: "2024-11-05",
|
||||||
capabilities: {
|
capabilities: {
|
||||||
@@ -40,19 +42,31 @@ async function handleMCPRequest(request) {
|
|||||||
},
|
},
|
||||||
serverInfo: {
|
serverInfo: {
|
||||||
name: "browser-mcp-server",
|
name: "browser-mcp-server",
|
||||||
version: "1.0.0",
|
version: "2.0.0",
|
||||||
},
|
},
|
||||||
instructions: "Browser automation tools via Chrome Extension bridge. Extension may take a moment to connect."
|
instructions:
|
||||||
|
"🎯 Enhanced browser automation with anti-detection bypass for Twitter/X, LinkedIn, Facebook. Extension may take a moment to connect.",
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "tools/list":
|
case "tools/list":
|
||||||
// Debug logging
|
// Debug logging
|
||||||
console.error(`Tools/list called. Extension connected: ${chromeExtensionSocket && chromeExtensionSocket.readyState === WebSocket.OPEN}, Available tools: ${availableTools.length}`);
|
console.error(
|
||||||
|
`Tools/list called. Extension connected: ${
|
||||||
|
chromeExtensionSocket &&
|
||||||
|
chromeExtensionSocket.readyState === WebSocket.OPEN
|
||||||
|
}, Available tools: ${availableTools.length}`
|
||||||
|
);
|
||||||
|
|
||||||
// Return tools from extension if available, otherwise fallback tools
|
// Return tools from extension if available, otherwise fallback tools
|
||||||
if (chromeExtensionSocket && chromeExtensionSocket.readyState === WebSocket.OPEN && availableTools.length > 0) {
|
if (
|
||||||
console.error(`Returning ${availableTools.length} tools from extension`);
|
chromeExtensionSocket &&
|
||||||
|
chromeExtensionSocket.readyState === WebSocket.OPEN &&
|
||||||
|
availableTools.length > 0
|
||||||
|
) {
|
||||||
|
console.error(
|
||||||
|
`Returning ${availableTools.length} tools from extension`
|
||||||
|
);
|
||||||
result = {
|
result = {
|
||||||
tools: availableTools.map((tool) => ({
|
tools: availableTools.map((tool) => ({
|
||||||
name: tool.name,
|
name: tool.name,
|
||||||
@@ -64,22 +78,25 @@ async function handleMCPRequest(request) {
|
|||||||
// Return basic fallback tools
|
// Return basic fallback tools
|
||||||
console.error("Extension not connected, returning fallback tools");
|
console.error("Extension not connected, returning fallback tools");
|
||||||
result = {
|
result = {
|
||||||
tools: getFallbackTools()
|
tools: getFallbackTools(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "tools/call":
|
case "tools/call":
|
||||||
if (!chromeExtensionSocket || chromeExtensionSocket.readyState !== WebSocket.OPEN) {
|
if (
|
||||||
|
!chromeExtensionSocket ||
|
||||||
|
chromeExtensionSocket.readyState !== WebSocket.OPEN
|
||||||
|
) {
|
||||||
// Extension not connected - return helpful error
|
// Extension not connected - return helpful error
|
||||||
result = {
|
result = {
|
||||||
content: [
|
content: [
|
||||||
{
|
{
|
||||||
type: "text",
|
type: "text",
|
||||||
text: "❌ Chrome Extension not connected. Please install and activate the browser extension, then try again.\n\nSetup instructions:\n1. Go to chrome://extensions/\n2. Enable Developer mode\n3. Click 'Load unpacked' and select the extension folder\n4. Ensure the extension is active",
|
text: "❌ Chrome Extension not connected. Please install and activate the browser extension, then try again.\n\nSetup instructions:\n1. Go to chrome://extensions/\n2. Enable Developer mode\n3. Click 'Load unpacked' and select the extension folder\n4. Ensure the extension is active\n\n🎯 Features: Anti-detection bypass for Twitter/X, LinkedIn, Facebook + universal automation",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
isError: true
|
isError: true,
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
// Extension connected - try the tool call
|
// Extension connected - try the tool call
|
||||||
@@ -99,7 +116,7 @@ async function handleMCPRequest(request) {
|
|||||||
text: formattedResult,
|
text: formattedResult,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
isError: false
|
isError: false,
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
result = {
|
result = {
|
||||||
@@ -109,7 +126,7 @@ async function handleMCPRequest(request) {
|
|||||||
text: `❌ Tool execution failed: ${error.message}`,
|
text: `❌ Tool execution failed: ${error.message}`,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
isError: true
|
isError: true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -142,54 +159,41 @@ async function handleMCPRequest(request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove static tools - they were causing duplicates
|
// Enhanced tool result formatting with anti-detection support
|
||||||
// All tools now come from the extension only
|
|
||||||
|
|
||||||
// Format tool results for better MCP response
|
|
||||||
function formatToolResult(toolName, result) {
|
function formatToolResult(toolName, result) {
|
||||||
const metadata = {
|
const metadata = {
|
||||||
tool: toolName,
|
tool: toolName,
|
||||||
execution_time: result.execution_time || 0,
|
execution_time: result.execution_time || 0,
|
||||||
timestamp: new Date().toISOString()
|
timestamp: new Date().toISOString(),
|
||||||
};
|
};
|
||||||
|
|
||||||
switch (toolName) {
|
switch (toolName) {
|
||||||
case 'page_analyze':
|
case "page_analyze":
|
||||||
if (result.elements && result.elements.length > 0) {
|
return formatPageAnalyzeResult(result, metadata);
|
||||||
const summary = `Found ${result.elements.length} relevant elements using ${result.method}:\n\n` +
|
|
||||||
result.elements.map(el =>
|
|
||||||
`• ${el.name} (${el.type}) - Confidence: ${Math.round(el.confidence * 100)}%\n Selector: ${el.selector}\n Element ID: ${el.id}`
|
|
||||||
).join('\n\n');
|
|
||||||
return `${summary}\n\n${JSON.stringify(metadata, null, 2)}`;
|
|
||||||
} else {
|
|
||||||
return `No relevant elements found for intent: "${result.intent_hint || 'unknown'}"\n\n${JSON.stringify(metadata, null, 2)}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 'page_extract_content':
|
case "page_extract_content":
|
||||||
const contentSummary = `Extracted ${result.content_type} content using ${result.method}:\n\n`;
|
return formatContentExtractionResult(result, metadata);
|
||||||
if (result.content) {
|
|
||||||
const preview = typeof result.content === 'string'
|
|
||||||
? result.content.substring(0, 500) + (result.content.length > 500 ? '...' : '')
|
|
||||||
: JSON.stringify(result.content, null, 2).substring(0, 500);
|
|
||||||
return `${contentSummary}${preview}\n\n${JSON.stringify(metadata, null, 2)}`;
|
|
||||||
} else {
|
|
||||||
return `${contentSummary}No content found\n\n${JSON.stringify(metadata, null, 2)}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 'element_click':
|
case "element_click":
|
||||||
return `✅ Successfully clicked element: ${result.element_name || result.element_id}\n` +
|
return formatElementClickResult(result, metadata);
|
||||||
`Click type: ${result.click_type || 'left'}\n\n${JSON.stringify(metadata, null, 2)}`;
|
|
||||||
|
|
||||||
case 'element_fill':
|
case "element_fill":
|
||||||
return `✅ Successfully filled element: ${result.element_name || result.element_id}\n` +
|
return formatElementFillResult(result, metadata);
|
||||||
`Value: "${result.value}"\n\n${JSON.stringify(metadata, null, 2)}`;
|
|
||||||
|
|
||||||
case 'page_navigate':
|
case "page_navigate":
|
||||||
return `✅ Successfully navigated to: ${result.url || 'unknown URL'}\n\n${JSON.stringify(metadata, null, 2)}`;
|
return `✅ Successfully navigated to: ${
|
||||||
|
result.url || "unknown URL"
|
||||||
|
}\n\n${JSON.stringify(metadata, null, 2)}`;
|
||||||
|
|
||||||
case 'page_wait_for':
|
case "page_wait_for":
|
||||||
return `✅ Condition met: ${result.condition_type || 'unknown'}\n` +
|
return (
|
||||||
`Wait time: ${result.wait_time || 0}ms\n\n${JSON.stringify(metadata, null, 2)}`;
|
`✅ Condition met: ${result.condition_type || "unknown"}\n` +
|
||||||
|
`Wait time: ${result.wait_time || 0}ms\n\n${JSON.stringify(
|
||||||
|
metadata,
|
||||||
|
null,
|
||||||
|
2
|
||||||
|
)}`
|
||||||
|
);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// Legacy tools or unknown tools
|
// Legacy tools or unknown tools
|
||||||
@@ -197,98 +201,331 @@ function formatToolResult(toolName, result) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fallback tools when extension is not connected
|
function formatPageAnalyzeResult(result, metadata) {
|
||||||
|
if (result.elements && result.elements.length > 0) {
|
||||||
|
const platformInfo = result.summary?.anti_detection_platform
|
||||||
|
? `\n🎯 Anti-detection platform detected: ${result.summary.anti_detection_platform}`
|
||||||
|
: "";
|
||||||
|
|
||||||
|
const summary =
|
||||||
|
`Found ${result.elements.length} relevant elements using ${result.method}:${platformInfo}\n\n` +
|
||||||
|
result.elements
|
||||||
|
.map((el) => {
|
||||||
|
const readyStatus = el.ready ? "✅ Ready" : "⚠️ Not ready";
|
||||||
|
const stateInfo = el.state === "disabled" ? " (disabled)" : "";
|
||||||
|
return `• ${el.name} (${el.type}) - Confidence: ${el.conf}% ${readyStatus}${stateInfo}\n Element ID: ${el.id}`;
|
||||||
|
})
|
||||||
|
.join("\n\n");
|
||||||
|
return `${summary}\n\n${JSON.stringify(metadata, null, 2)}`;
|
||||||
|
} else {
|
||||||
|
const intentHint = result.intent_hint || "unknown";
|
||||||
|
const platformInfo = result.summary?.anti_detection_platform
|
||||||
|
? `\nPlatform: ${result.summary.anti_detection_platform}`
|
||||||
|
: "";
|
||||||
|
return `No relevant elements found for intent: "${intentHint}"${platformInfo}\n\n${JSON.stringify(
|
||||||
|
metadata,
|
||||||
|
null,
|
||||||
|
2
|
||||||
|
)}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatContentExtractionResult(result, metadata) {
|
||||||
|
const contentSummary = `Extracted ${result.content_type} content using ${result.method}:\n\n`;
|
||||||
|
if (result.content) {
|
||||||
|
const preview =
|
||||||
|
typeof result.content === "string"
|
||||||
|
? result.content.substring(0, 500) +
|
||||||
|
(result.content.length > 500 ? "..." : "")
|
||||||
|
: JSON.stringify(result.content, null, 2).substring(0, 500);
|
||||||
|
return `${contentSummary}${preview}\n\n${JSON.stringify(
|
||||||
|
metadata,
|
||||||
|
null,
|
||||||
|
2
|
||||||
|
)}`;
|
||||||
|
} else if (result.summary) {
|
||||||
|
// Enhanced summarized content response
|
||||||
|
const summaryText = formatContentSummary(
|
||||||
|
result.summary,
|
||||||
|
result.content_type
|
||||||
|
);
|
||||||
|
return `${contentSummary}${summaryText}\n\n${JSON.stringify(
|
||||||
|
metadata,
|
||||||
|
null,
|
||||||
|
2
|
||||||
|
)}`;
|
||||||
|
} else {
|
||||||
|
return `${contentSummary}No content found\n\n${JSON.stringify(
|
||||||
|
metadata,
|
||||||
|
null,
|
||||||
|
2
|
||||||
|
)}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatContentSummary(summary, contentType) {
|
||||||
|
switch (contentType) {
|
||||||
|
case "article":
|
||||||
|
return (
|
||||||
|
`📰 Article: "${summary.title}"\n` +
|
||||||
|
`📝 Word count: ${summary.word_count}\n` +
|
||||||
|
`⏱️ Reading time: ${summary.reading_time} minutes\n` +
|
||||||
|
`🖼️ Has media: ${summary.has_images || summary.has_videos}\n` +
|
||||||
|
`Preview: ${summary.preview}`
|
||||||
|
);
|
||||||
|
|
||||||
|
case "search_results":
|
||||||
|
return (
|
||||||
|
`🔍 Search Results Summary:\n` +
|
||||||
|
`📊 Total results: ${summary.total_results}\n` +
|
||||||
|
`🏆 Quality score: ${summary.quality_score}/100\n` +
|
||||||
|
`📈 Average relevance: ${Math.round(summary.avg_score * 100)}%\n` +
|
||||||
|
`🌐 Top domains: ${summary.top_domains
|
||||||
|
?.map((d) => d.domain)
|
||||||
|
.join(", ")}\n` +
|
||||||
|
`📝 Result types: ${summary.result_types?.join(", ")}`
|
||||||
|
);
|
||||||
|
|
||||||
|
case "posts":
|
||||||
|
return (
|
||||||
|
`📱 Social Posts Summary:\n` +
|
||||||
|
`📊 Post count: ${summary.post_count}\n` +
|
||||||
|
`📝 Average length: ${summary.avg_length} characters\n` +
|
||||||
|
`❤️ Total engagement: ${summary.engagement_total}\n` +
|
||||||
|
`🖼️ Posts with media: ${summary.has_media_count}\n` +
|
||||||
|
`👥 Unique authors: ${summary.authors}\n` +
|
||||||
|
`📋 Post types: ${summary.post_types?.join(", ")}`
|
||||||
|
);
|
||||||
|
|
||||||
|
default:
|
||||||
|
return JSON.stringify(summary, null, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatElementClickResult(result, metadata) {
|
||||||
|
return (
|
||||||
|
`✅ Successfully clicked element: ${
|
||||||
|
result.element_name || result.element_id
|
||||||
|
}\n` +
|
||||||
|
`Click type: ${result.click_type || "left"}\n\n${JSON.stringify(
|
||||||
|
metadata,
|
||||||
|
null,
|
||||||
|
2
|
||||||
|
)}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatElementFillResult(result, metadata) {
|
||||||
|
// Enhanced formatting for anti-detection bypass methods
|
||||||
|
const methodEmojis = {
|
||||||
|
twitter_direct_bypass: "🐦 Twitter Direct Bypass",
|
||||||
|
linkedin_direct_bypass: "💼 LinkedIn Direct Bypass",
|
||||||
|
facebook_direct_bypass: "📘 Facebook Direct Bypass",
|
||||||
|
generic_direct_bypass: "🎯 Generic Direct Bypass",
|
||||||
|
standard_fill: "🔧 Standard Fill",
|
||||||
|
anti_detection_bypass: "🛡️ Anti-Detection Bypass",
|
||||||
|
};
|
||||||
|
|
||||||
|
const methodDisplay = methodEmojis[result.method] || result.method;
|
||||||
|
const successIcon = result.success ? "✅" : "❌";
|
||||||
|
|
||||||
|
let fillResult = `${successIcon} Element fill ${
|
||||||
|
result.success ? "completed" : "failed"
|
||||||
|
} using ${methodDisplay}\n`;
|
||||||
|
fillResult += `📝 Target: ${result.element_name || result.element_id}\n`;
|
||||||
|
fillResult += `💬 Input: "${result.value}"\n`;
|
||||||
|
|
||||||
|
if (result.actual_value) {
|
||||||
|
fillResult += `📄 Result: "${result.actual_value}"\n`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add bypass-specific information
|
||||||
|
if (
|
||||||
|
result.method?.includes("bypass") &&
|
||||||
|
result.execCommand_result !== undefined
|
||||||
|
) {
|
||||||
|
fillResult += `🔧 execCommand success: ${result.execCommand_result}\n`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!result.success && result.method?.includes("bypass")) {
|
||||||
|
fillResult += `\n⚠️ Direct bypass failed - page may have enhanced detection. Try refreshing the page.\n`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return `${fillResult}\n${JSON.stringify(metadata, null, 2)}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enhanced fallback tools when extension is not connected
|
||||||
function getFallbackTools() {
|
function getFallbackTools() {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
name: "page_analyze",
|
name: "page_analyze",
|
||||||
description: "Analyze current page structure (Extension required)",
|
description:
|
||||||
|
"🎯 Analyze page structure with anti-detection bypass (Extension required)",
|
||||||
inputSchema: {
|
inputSchema: {
|
||||||
type: "object",
|
type: "object",
|
||||||
properties: {
|
properties: {
|
||||||
intent_hint: { type: "string", description: "What user wants to do" }
|
intent_hint: {
|
||||||
|
type: "string",
|
||||||
|
description:
|
||||||
|
"What user wants to do: post_tweet, search, login, etc.",
|
||||||
|
},
|
||||||
|
phase: {
|
||||||
|
type: "string",
|
||||||
|
enum: ["discover", "detailed"],
|
||||||
|
default: "discover",
|
||||||
|
description:
|
||||||
|
"Analysis phase: 'discover' for quick scan, 'detailed' for full analysis",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
required: ["intent_hint"]
|
required: ["intent_hint"],
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "page_extract_content",
|
name: "page_extract_content",
|
||||||
description: "Extract structured content (Extension required)",
|
description:
|
||||||
|
"📄 Extract structured content with smart summarization (Extension required)",
|
||||||
inputSchema: {
|
inputSchema: {
|
||||||
type: "object",
|
type: "object",
|
||||||
properties: {
|
properties: {
|
||||||
content_type: { type: "string", enum: ["article", "search_results", "posts"] }
|
content_type: {
|
||||||
|
type: "string",
|
||||||
|
enum: ["article", "search_results", "posts"],
|
||||||
|
description: "Type of content to extract",
|
||||||
|
},
|
||||||
|
summarize: {
|
||||||
|
type: "boolean",
|
||||||
|
default: true,
|
||||||
|
description:
|
||||||
|
"Return summary instead of full content (saves tokens)",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
required: ["content_type"]
|
required: ["content_type"],
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "element_click",
|
name: "element_click",
|
||||||
description: "Click page elements (Extension required)",
|
description:
|
||||||
|
"🖱️ Click page elements with smart targeting (Extension required)",
|
||||||
inputSchema: {
|
inputSchema: {
|
||||||
type: "object",
|
type: "object",
|
||||||
properties: {
|
properties: {
|
||||||
element_id: { type: "string", description: "Element ID from page_analyze" }
|
element_id: {
|
||||||
|
type: "string",
|
||||||
|
description: "Element ID from page_analyze",
|
||||||
|
},
|
||||||
|
click_type: {
|
||||||
|
type: "string",
|
||||||
|
enum: ["left", "right", "double"],
|
||||||
|
default: "left",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
required: ["element_id"]
|
required: ["element_id"],
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "element_fill",
|
name: "element_fill",
|
||||||
description: "Fill input fields (Extension required)",
|
description:
|
||||||
|
"✍️ Fill input fields with anti-detection bypass for Twitter/X, LinkedIn, Facebook (Extension required)",
|
||||||
inputSchema: {
|
inputSchema: {
|
||||||
type: "object",
|
type: "object",
|
||||||
properties: {
|
properties: {
|
||||||
element_id: { type: "string", description: "Element ID" },
|
element_id: {
|
||||||
value: { type: "string", description: "Text to input" }
|
type: "string",
|
||||||
|
description: "Element ID from page_analyze",
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
type: "string",
|
||||||
|
description: "Text to input",
|
||||||
|
},
|
||||||
|
clear_first: {
|
||||||
|
type: "boolean",
|
||||||
|
default: true,
|
||||||
|
description: "Clear existing content before filling",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
required: ["element_id", "value"]
|
required: ["element_id", "value"],
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "page_navigate",
|
name: "page_navigate",
|
||||||
description: "Navigate to URLs (Extension required)",
|
description:
|
||||||
|
"🧭 Navigate to URLs with wait conditions (Extension required)",
|
||||||
inputSchema: {
|
inputSchema: {
|
||||||
type: "object",
|
type: "object",
|
||||||
properties: {
|
properties: {
|
||||||
url: { type: "string", description: "URL to navigate to" }
|
url: { type: "string", description: "URL to navigate to" },
|
||||||
|
wait_for: {
|
||||||
|
type: "string",
|
||||||
|
description: "CSS selector to wait for after navigation",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
required: ["url"]
|
required: ["url"],
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "page_wait_for",
|
name: "page_wait_for",
|
||||||
description: "Wait for elements (Extension required)",
|
description: "⏳ Wait for elements or conditions (Extension required)",
|
||||||
inputSchema: {
|
inputSchema: {
|
||||||
type: "object",
|
type: "object",
|
||||||
properties: {
|
properties: {
|
||||||
condition_type: { type: "string", enum: ["element_visible", "text_present"] }
|
condition_type: {
|
||||||
|
type: "string",
|
||||||
|
enum: ["element_visible", "text_present"],
|
||||||
|
description: "Type of condition to wait for",
|
||||||
|
},
|
||||||
|
selector: {
|
||||||
|
type: "string",
|
||||||
|
description: "CSS selector (for element_visible condition)",
|
||||||
|
},
|
||||||
|
text: {
|
||||||
|
type: "string",
|
||||||
|
description: "Text to wait for (for text_present condition)",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
required: ["condition_type"]
|
required: ["condition_type"],
|
||||||
}
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "get_analytics",
|
||||||
|
description: "📊 Get performance analytics and token usage metrics",
|
||||||
|
inputSchema: {
|
||||||
|
type: "object",
|
||||||
|
properties: {},
|
||||||
|
additionalProperties: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "clear_analytics",
|
||||||
|
description: "🗑️ Clear analytics data and reset performance tracking",
|
||||||
|
inputSchema: {
|
||||||
|
type: "object",
|
||||||
|
properties: {},
|
||||||
|
additionalProperties: false,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "browser_navigate",
|
name: "browser_navigate",
|
||||||
description: "Navigate to URLs - legacy (Extension required)",
|
description: "🌐 Navigate to URLs - legacy (Extension required)",
|
||||||
inputSchema: {
|
inputSchema: {
|
||||||
type: "object",
|
type: "object",
|
||||||
properties: {
|
properties: {
|
||||||
url: { type: "string", description: "URL to navigate to" }
|
url: { type: "string", description: "URL to navigate to" },
|
||||||
},
|
},
|
||||||
required: ["url"]
|
required: ["url"],
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "browser_execute_script",
|
name: "browser_execute_script",
|
||||||
description: "Execute JavaScript (Extension required - limited by CSP)",
|
description:
|
||||||
|
"⚡ Execute JavaScript (Extension required - limited by CSP)",
|
||||||
inputSchema: {
|
inputSchema: {
|
||||||
type: "object",
|
type: "object",
|
||||||
properties: {
|
properties: {
|
||||||
code: { type: "string", description: "JavaScript code" }
|
code: { type: "string", description: "JavaScript code" },
|
||||||
},
|
},
|
||||||
required: ["code"]
|
required: ["code"],
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -357,8 +594,14 @@ wss.on("connection", (ws) => {
|
|||||||
|
|
||||||
if (message.type === "register") {
|
if (message.type === "register") {
|
||||||
availableTools = message.tools;
|
availableTools = message.tools;
|
||||||
console.error(`✅ Registered ${availableTools.length} browser tools from extension`);
|
console.error(
|
||||||
console.error(`Tools: ${availableTools.map(t => t.name).join(', ')}`);
|
`✅ Registered ${availableTools.length} browser tools from extension`
|
||||||
|
);
|
||||||
|
console.error(
|
||||||
|
`🎯 Enhanced tools with anti-detection bypass: ${availableTools
|
||||||
|
.map((t) => t.name)
|
||||||
|
.join(", ")}`
|
||||||
|
);
|
||||||
} else if (message.type === "ping") {
|
} else if (message.type === "ping") {
|
||||||
// Respond to ping with pong
|
// Respond to ping with pong
|
||||||
ws.send(JSON.stringify({ type: "pong", timestamp: Date.now() }));
|
ws.send(JSON.stringify({ type: "pong", timestamp: Date.now() }));
|
||||||
@@ -420,14 +663,25 @@ app.get("/health", (req, res) => {
|
|||||||
status: "ok",
|
status: "ok",
|
||||||
chromeExtensionConnected: chromeExtensionSocket !== null,
|
chromeExtensionConnected: chromeExtensionSocket !== null,
|
||||||
availableTools: availableTools.length,
|
availableTools: availableTools.length,
|
||||||
|
features: [
|
||||||
|
"Anti-detection bypass for Twitter/X, LinkedIn, Facebook",
|
||||||
|
"Two-phase intelligent page analysis",
|
||||||
|
"Smart content extraction with summarization",
|
||||||
|
"Element state detection and interaction readiness",
|
||||||
|
"Performance analytics and token optimization",
|
||||||
|
],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
app.listen(3001, () => {
|
app.listen(3001, () => {
|
||||||
|
console.error("🎯 Enhanced Browser MCP Server with Anti-Detection Features");
|
||||||
console.error(
|
console.error(
|
||||||
"Health check endpoint available at http://localhost:3001/health"
|
"Health check endpoint available at http://localhost:3001/health"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
console.error("Browser MCP Server started");
|
console.error("🚀 Enhanced Browser MCP Server started");
|
||||||
console.error("Waiting for Chrome Extension connection on ws://localhost:3000");
|
console.error(
|
||||||
|
"🔌 Waiting for Chrome Extension connection on ws://localhost:3000"
|
||||||
|
);
|
||||||
|
console.error("🎯 Features: Anti-detection bypass + intelligent automation");
|
||||||
|
|||||||
Reference in New Issue
Block a user