package main

import (
	"context"
	"encoding/json"
	"fmt"
	"log"
	"os"
	"strconv"
	"time"

	"git.teamworkapps.com/shortcut/cremote/client"
	"github.com/mark3labs/mcp-go/mcp"
	"github.com/mark3labs/mcp-go/server"
)

const Version = "2.0.0"

// CremoteServer wraps the cremote client for MCP
type CremoteServer struct {
	client      *client.Client
	currentTab  string
	tabHistory  []string
	iframeMode  bool
	screenshots []string
}

// NewCremoteServer creates a new cremote MCP server
func NewCremoteServer(host string, port int) *CremoteServer {
	return &CremoteServer{
		client:      client.NewClient(host, port),
		tabHistory:  make([]string, 0),
		screenshots: make([]string, 0),
	}
}

// Helper functions for parameter extraction
func getStringParam(params map[string]any, key, defaultValue string) string {
	if val, ok := params[key].(string); ok {
		return val
	}
	return defaultValue
}

func getBoolParam(params map[string]any, key string, defaultValue bool) bool {
	if val, ok := params[key].(bool); ok {
		return val
	}
	return defaultValue
}

func getIntParam(params map[string]any, key string, defaultValue int) int {
	if val, ok := params[key].(float64); ok {
		return int(val)
	}
	if val, ok := params[key].(int); ok {
		return val
	}
	return defaultValue
}

func main() {
	// Get cremote daemon connection settings
	cremoteHost := os.Getenv("CREMOTE_HOST")
	if cremoteHost == "" {
		cremoteHost = "localhost"
	}

	cremotePortStr := os.Getenv("CREMOTE_PORT")
	cremotePort := 8989
	if cremotePortStr != "" {
		if p, err := strconv.Atoi(cremotePortStr); err == nil {
			cremotePort = p
		}
	}

	log.Printf("Starting cremote MCP server, connecting to cremote daemon at %s:%d", cremoteHost, cremotePort)

	// Create the cremote server
	cremoteServer := NewCremoteServer(cremoteHost, cremotePort)

	// Create MCP server
	mcpServer := server.NewMCPServer("cremote-mcp", "2.0.0")

	// Register version tool
	mcpServer.AddTool(mcp.Tool{
		Name:        "version_cremotemcp",
		Description: "Get version information for MCP server and daemon",
		InputSchema: mcp.ToolInputSchema{
			Type:       "object",
			Properties: map[string]any{},
			Required:   []string{},
		},
	}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
		// Get daemon version
		daemonVersion, err := cremoteServer.client.GetVersion()
		if err != nil {
			daemonVersion = fmt.Sprintf("Unable to connect: %v", err)
		}

		return &mcp.CallToolResult{
			Content: []mcp.Content{
				mcp.NewTextContent(fmt.Sprintf("MCP Server version: %s\nDaemon version: %s", Version, daemonVersion)),
			},
			IsError: false,
		}, nil
	})

	// Register web_navigate tool
	mcpServer.AddTool(mcp.Tool{
		Name:        "web_navigate_cremotemcp",
		Description: "Navigate to a URL and optionally take a screenshot",
		InputSchema: mcp.ToolInputSchema{
			Type: "object",
			Properties: map[string]any{
				"url": map[string]any{
					"type":        "string",
					"description": "URL to navigate to",
				},
				"tab": map[string]any{
					"type":        "string",
					"description": "Tab ID (optional, uses current tab)",
				},
				"timeout": map[string]any{
					"type":        "integer",
					"description": "Timeout in seconds",
					"default":     5,
				},
				"screenshot": map[string]any{
					"type":        "boolean",
					"description": "Take screenshot after navigation",
				},
			},
			Required: []string{"url"},
		},
	}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
		// Convert arguments to map
		params, ok := request.Params.Arguments.(map[string]any)
		if !ok {
			return nil, fmt.Errorf("invalid arguments format")
		}

		url := getStringParam(params, "url", "")
		if url == "" {
			return nil, fmt.Errorf("url parameter is required")
		}

		tab := getStringParam(params, "tab", cremoteServer.currentTab)
		timeout := getIntParam(params, "timeout", 5)
		takeScreenshot := getBoolParam(params, "screenshot", false)

		// If no tab specified and no current tab, create a new one
		if tab == "" {
			newTab, err := cremoteServer.client.OpenTab(timeout)
			if err != nil {
				return nil, fmt.Errorf("failed to create new tab: %w", err)
			}
			tab = newTab
			cremoteServer.currentTab = tab
			cremoteServer.tabHistory = append(cremoteServer.tabHistory, tab)
		}

		// Load the URL
		err := cremoteServer.client.LoadURL(tab, url, timeout)
		if err != nil {
			return nil, fmt.Errorf("failed to load URL: %w", err)
		}

		message := fmt.Sprintf("Successfully navigated to %s in tab %s", url, tab)

		// Take screenshot if requested
		if takeScreenshot {
			screenshotPath := fmt.Sprintf("/tmp/navigate-%d.png", time.Now().Unix())
			err = cremoteServer.client.TakeScreenshot(tab, screenshotPath, false, timeout)
			if err == nil {
				cremoteServer.screenshots = append(cremoteServer.screenshots, screenshotPath)
				message += fmt.Sprintf(" (screenshot saved to %s)", screenshotPath)
			}
		}

		return &mcp.CallToolResult{
			Content: []mcp.Content{
				mcp.NewTextContent(message),
			},
			IsError: false,
		}, nil
	})

	// Register web_interact tool
	mcpServer.AddTool(mcp.Tool{
		Name:        "web_interact_cremotemcp",
		Description: "Interact with web elements (click, fill, submit)",
		InputSchema: mcp.ToolInputSchema{
			Type: "object",
			Properties: map[string]any{
				"action": map[string]any{
					"type":        "string",
					"description": "Action to perform",
					"enum":        []any{"click", "fill", "submit", "upload", "select"},
				},
				"selector": map[string]any{
					"type":        "string",
					"description": "CSS selector for the element",
				},
				"value": map[string]any{
					"type":        "string",
					"description": "Value to fill (for fill/upload actions)",
				},
				"tab": map[string]any{
					"type":        "string",
					"description": "Tab ID (optional)",
				},
				"timeout": map[string]any{
					"type":        "integer",
					"description": "Timeout in seconds",
					"default":     5,
				},
			},
			Required: []string{"action", "selector"},
		},
	}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
		// Convert arguments to map
		params, ok := request.Params.Arguments.(map[string]any)
		if !ok {
			return nil, fmt.Errorf("invalid arguments format")
		}

		action := getStringParam(params, "action", "")
		selector := getStringParam(params, "selector", "")
		value := getStringParam(params, "value", "")
		tab := getStringParam(params, "tab", cremoteServer.currentTab)
		timeout := getIntParam(params, "timeout", 5)

		if action == "" {
			return nil, fmt.Errorf("action parameter is required")
		}
		if selector == "" {
			return nil, fmt.Errorf("selector parameter is required")
		}
		if tab == "" {
			return nil, fmt.Errorf("no tab available - navigate to a page first")
		}

		var err error
		var message string

		switch action {
		case "click":
			err = cremoteServer.client.ClickElement(tab, selector, timeout)
			message = fmt.Sprintf("Clicked element %s", selector)

		case "fill":
			if value == "" {
				return nil, fmt.Errorf("value parameter is required for fill action")
			}
			err = cremoteServer.client.FillFormField(tab, selector, value, timeout)
			message = fmt.Sprintf("Filled element %s with value", selector)

		case "submit":
			err = cremoteServer.client.SubmitForm(tab, selector, timeout)
			message = fmt.Sprintf("Submitted form %s", selector)

		case "upload":
			if value == "" {
				return nil, fmt.Errorf("value parameter (file path) is required for upload action")
			}
			err = cremoteServer.client.UploadFile(tab, selector, value, timeout)
			message = fmt.Sprintf("Uploaded file %s to element %s", value, selector)

		case "select":
			if value == "" {
				return nil, fmt.Errorf("value parameter is required for select action")
			}
			err = cremoteServer.client.SelectElement(tab, selector, value, timeout)
			message = fmt.Sprintf("Selected option %s in element %s", value, selector)

		default:
			return nil, fmt.Errorf("unknown action: %s", action)
		}

		if err != nil {
			return nil, fmt.Errorf("failed to %s element: %w", action, err)
		}

		return &mcp.CallToolResult{
			Content: []mcp.Content{
				mcp.NewTextContent(message),
			},
			IsError: false,
		}, nil
	})

	// Register web_extract tool
	mcpServer.AddTool(mcp.Tool{
		Name:        "web_extract_cremotemcp",
		Description: "Extract data from the page (source, element HTML, or execute JavaScript)",
		InputSchema: mcp.ToolInputSchema{
			Type: "object",
			Properties: map[string]any{
				"type": map[string]any{
					"type":        "string",
					"description": "Type of extraction",
					"enum":        []any{"source", "element", "javascript"},
				},
				"selector": map[string]any{
					"type":        "string",
					"description": "CSS selector (for element type)",
				},
				"code": map[string]any{
					"type":        "string",
					"description": "JavaScript code (for javascript type)",
				},
				"tab": map[string]any{
					"type":        "string",
					"description": "Tab ID (optional)",
				},
				"timeout": map[string]any{
					"type":        "integer",
					"description": "Timeout in seconds",
					"default":     5,
				},
			},
			Required: []string{"type"},
		},
	}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
		// Convert arguments to map
		params, ok := request.Params.Arguments.(map[string]any)
		if !ok {
			return nil, fmt.Errorf("invalid arguments format")
		}

		extractType := getStringParam(params, "type", "")
		selector := getStringParam(params, "selector", "")
		code := getStringParam(params, "code", "")
		tab := getStringParam(params, "tab", cremoteServer.currentTab)
		timeout := getIntParam(params, "timeout", 5)

		if extractType == "" {
			return nil, fmt.Errorf("type parameter is required")
		}
		if tab == "" {
			return nil, fmt.Errorf("no tab available - navigate to a page first")
		}

		var data string
		var err error

		switch extractType {
		case "source":
			data, err = cremoteServer.client.GetPageSource(tab, timeout)

		case "element":
			if selector == "" {
				return nil, fmt.Errorf("selector parameter is required for element extraction")
			}
			data, err = cremoteServer.client.GetElementHTML(tab, selector, timeout)

		case "javascript":
			if code == "" {
				return nil, fmt.Errorf("code parameter is required for javascript extraction")
			}
			data, err = cremoteServer.client.EvalJS(tab, code, timeout)

		default:
			return nil, fmt.Errorf("unknown extraction type: %s", extractType)
		}

		if err != nil {
			return nil, fmt.Errorf("failed to extract %s: %w", extractType, err)
		}

		return &mcp.CallToolResult{
			Content: []mcp.Content{
				mcp.NewTextContent(fmt.Sprintf("Extracted %s data: %s", extractType, data)),
			},
			IsError: false,
		}, nil
	})

	// Register web_screenshot tool
	mcpServer.AddTool(mcp.Tool{
		Name:        "web_screenshot_cremotemcp",
		Description: "Take a screenshot of the current page with optional zoom level and viewport size for accessibility testing",
		InputSchema: mcp.ToolInputSchema{
			Type: "object",
			Properties: map[string]any{
				"output": map[string]any{
					"type":        "string",
					"description": "Output file path",
				},
				"full_page": map[string]any{
					"type":        "boolean",
					"description": "Capture full page",
					"default":     false,
				},
				"zoom_level": map[string]any{
					"type":        "number",
					"description": "Zoom level (e.g., 1.0, 2.0, 4.0) for accessibility testing",
				},
				"width": map[string]any{
					"type":        "integer",
					"description": "Viewport width in pixels for responsive testing",
				},
				"height": map[string]any{
					"type":        "integer",
					"description": "Viewport height in pixels for responsive testing",
				},
				"tab": map[string]any{
					"type":        "string",
					"description": "Tab ID (optional)",
				},
				"timeout": map[string]any{
					"type":        "integer",
					"description": "Timeout in seconds",
					"default":     5,
				},
			},
			Required: []string{"output"},
		},
	}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
		// Convert arguments to map
		params, ok := request.Params.Arguments.(map[string]any)
		if !ok {
			return nil, fmt.Errorf("invalid arguments format")
		}

		output := getStringParam(params, "output", "")
		fullPage := getBoolParam(params, "full_page", false)
		tab := getStringParam(params, "tab", cremoteServer.currentTab)
		timeout := getIntParam(params, "timeout", 5)

		// Get optional zoom and viewport parameters
		var zoomLevel float64
		if zoomParam, ok := params["zoom_level"].(float64); ok {
			zoomLevel = zoomParam
		}
		var width, height int
		if widthParam, ok := params["width"].(float64); ok {
			width = int(widthParam)
		}
		if heightParam, ok := params["height"].(float64); ok {
			height = int(heightParam)
		}

		if output == "" {
			return nil, fmt.Errorf("output parameter is required")
		}
		if tab == "" {
			return nil, fmt.Errorf("no tab available - navigate to a page first")
		}

		// Build command parameters
		cmdParams := map[string]string{
			"output":    output,
			"full-page": strconv.FormatBool(fullPage),
			"tab":       tab,
			"timeout":   strconv.Itoa(timeout),
		}
		if zoomLevel > 0 {
			cmdParams["zoom_level"] = strconv.FormatFloat(zoomLevel, 'f', 1, 64)
		}
		if width > 0 {
			cmdParams["width"] = strconv.Itoa(width)
		}
		if height > 0 {
			cmdParams["height"] = strconv.Itoa(height)
		}

		// Send command to daemon
		resp, err := cremoteServer.client.SendCommand("screenshot", cmdParams)
		if err != nil {
			return nil, fmt.Errorf("failed to take screenshot: %w", err)
		}

		if !resp.Success {
			return &mcp.CallToolResult{
				Content: []mcp.Content{
					mcp.NewTextContent(fmt.Sprintf("Screenshot failed: %s", resp.Error)),
				},
				IsError: true,
			}, nil
		}

		cremoteServer.screenshots = append(cremoteServer.screenshots, output)

		return &mcp.CallToolResult{
			Content: []mcp.Content{
				mcp.NewTextContent(fmt.Sprintf("Screenshot saved to %s", output)),
			},
			IsError: false,
		}, nil
	})

	// Register web_manage_tabs tool
	mcpServer.AddTool(mcp.Tool{
		Name:        "web_manage_tabs_cremotemcp",
		Description: "Manage browser tabs (open, close, list, switch)",
		InputSchema: mcp.ToolInputSchema{
			Type: "object",
			Properties: map[string]any{
				"action": map[string]any{
					"type":        "string",
					"description": "Action to perform",
					"enum":        []any{"open", "close", "list", "switch"},
				},
				"tab": map[string]any{
					"type":        "string",
					"description": "Tab ID (for close/switch actions)",
				},
				"timeout": map[string]any{
					"type":        "integer",
					"description": "Timeout in seconds",
					"default":     5,
				},
			},
			Required: []string{"action"},
		},
	}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
		// Convert arguments to map
		params, ok := request.Params.Arguments.(map[string]any)
		if !ok {
			return nil, fmt.Errorf("invalid arguments format")
		}

		action := getStringParam(params, "action", "")
		tab := getStringParam(params, "tab", "")
		timeout := getIntParam(params, "timeout", 5)

		if action == "" {
			return nil, fmt.Errorf("action parameter is required")
		}

		var err error
		var message string

		switch action {
		case "open":
			newTab, err := cremoteServer.client.OpenTab(timeout)
			if err != nil {
				return nil, fmt.Errorf("failed to open new tab: %w", err)
			}
			cremoteServer.currentTab = newTab
			cremoteServer.tabHistory = append(cremoteServer.tabHistory, newTab)
			message = fmt.Sprintf("Opened new tab: %s", newTab)

		case "close":
			if tab == "" {
				return nil, fmt.Errorf("tab parameter is required for close action")
			}
			err = cremoteServer.client.CloseTab(tab, timeout)
			if err != nil {
				return nil, fmt.Errorf("failed to close tab: %w", err)
			}
			// Remove from history and update current tab
			for i, id := range cremoteServer.tabHistory {
				if id == tab {
					cremoteServer.tabHistory = append(cremoteServer.tabHistory[:i], cremoteServer.tabHistory[i+1:]...)
					break
				}
			}
			if cremoteServer.currentTab == tab {
				if len(cremoteServer.tabHistory) > 0 {
					cremoteServer.currentTab = cremoteServer.tabHistory[len(cremoteServer.tabHistory)-1]
				} else {
					cremoteServer.currentTab = ""
				}
			}
			message = fmt.Sprintf("Closed tab: %s", tab)

		case "list":
			tabs, err := cremoteServer.client.ListTabs()
			if err != nil {
				return nil, fmt.Errorf("failed to list tabs: %w", err)
			}
			message = fmt.Sprintf("Found %d tabs: %v", len(tabs), tabs)

		case "switch":
			if tab == "" {
				return nil, fmt.Errorf("tab parameter is required for switch action")
			}
			cremoteServer.currentTab = tab
			// Add to history if not already there
			found := false
			for _, t := range cremoteServer.tabHistory {
				if t == tab {
					found = true
					break
				}
			}
			if !found {
				cremoteServer.tabHistory = append(cremoteServer.tabHistory, tab)
			}
			message = fmt.Sprintf("Switched to tab: %s", tab)

		default:
			return nil, fmt.Errorf("unknown tab action: %s", action)
		}

		return &mcp.CallToolResult{
			Content: []mcp.Content{
				mcp.NewTextContent(message),
			},
			IsError: false,
		}, nil
	})

	// Register web_iframe tool
	mcpServer.AddTool(mcp.Tool{
		Name:        "web_iframe_cremotemcp",
		Description: "Switch iframe context for subsequent operations",
		InputSchema: mcp.ToolInputSchema{
			Type: "object",
			Properties: map[string]any{
				"action": map[string]any{
					"type":        "string",
					"description": "Action to perform",
					"enum":        []any{"enter", "exit"},
				},
				"selector": map[string]any{
					"type":        "string",
					"description": "Iframe CSS selector (for enter action)",
				},
				"tab": map[string]any{
					"type":        "string",
					"description": "Tab ID (optional)",
				},
				"timeout": map[string]any{
					"type":        "integer",
					"description": "Timeout in seconds",
					"default":     5,
				},
			},
			Required: []string{"action"},
		},
	}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
		// Convert arguments to map
		params, ok := request.Params.Arguments.(map[string]any)
		if !ok {
			return nil, fmt.Errorf("invalid arguments format")
		}

		action := getStringParam(params, "action", "")
		selector := getStringParam(params, "selector", "")
		tab := getStringParam(params, "tab", cremoteServer.currentTab)
		timeout := getIntParam(params, "timeout", 5)

		if action == "" {
			return nil, fmt.Errorf("action parameter is required")
		}
		if tab == "" {
			return nil, fmt.Errorf("no tab available - navigate to a page first")
		}

		var err error
		var message string

		switch action {
		case "enter":
			if selector == "" {
				return nil, fmt.Errorf("selector parameter is required for enter action")
			}
			err = cremoteServer.client.SwitchToIframe(tab, selector, timeout)
			cremoteServer.iframeMode = true
			message = fmt.Sprintf("Entered iframe: %s", selector)

		case "exit":
			err = cremoteServer.client.SwitchToMain(tab, timeout)
			cremoteServer.iframeMode = false
			message = "Exited iframe context"

		default:
			return nil, fmt.Errorf("unknown iframe action: %s", action)
		}

		if err != nil {
			return nil, fmt.Errorf("failed to %s iframe: %w", action, err)
		}

		return &mcp.CallToolResult{
			Content: []mcp.Content{
				mcp.NewTextContent(message),
			},
			IsError: false,
		}, nil
	})

	// Register file_upload tool
	mcpServer.AddTool(mcp.Tool{
		Name:        "file_upload_cremotemcp",
		Description: "Upload a file from the client to the container for use in form uploads",
		InputSchema: mcp.ToolInputSchema{
			Type: "object",
			Properties: map[string]any{
				"local_path": map[string]any{
					"type":        "string",
					"description": "Path to the file on the client machine",
				},
				"container_path": map[string]any{
					"type":        "string",
					"description": "Optional path where to store the file in the container (defaults to /tmp/filename)",
				},
			},
			Required: []string{"local_path"},
		},
	}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
		// Convert arguments to map
		params, ok := request.Params.Arguments.(map[string]any)
		if !ok {
			return nil, fmt.Errorf("invalid arguments format")
		}

		localPath := getStringParam(params, "local_path", "")
		containerPath := getStringParam(params, "container_path", "")

		if localPath == "" {
			return nil, fmt.Errorf("local_path parameter is required")
		}

		// Upload the file to the container
		targetPath, err := cremoteServer.client.UploadFileToContainer(localPath, containerPath)
		if err != nil {
			return nil, fmt.Errorf("failed to upload file: %w", err)
		}

		return &mcp.CallToolResult{
			Content: []mcp.Content{
				mcp.NewTextContent(fmt.Sprintf("File uploaded successfully to container at: %s", targetPath)),
			},
			IsError: false,
		}, nil
	})

	// Register file_download tool
	mcpServer.AddTool(mcp.Tool{
		Name:        "file_download_cremotemcp",
		Description: "Download a file from the container to the client (e.g., downloaded files from browser)",
		InputSchema: mcp.ToolInputSchema{
			Type: "object",
			Properties: map[string]any{
				"container_path": map[string]any{
					"type":        "string",
					"description": "Path to the file in the container",
				},
				"local_path": map[string]any{
					"type":        "string",
					"description": "Path where to save the file on the client machine",
				},
			},
			Required: []string{"container_path", "local_path"},
		},
	}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
		// Convert arguments to map
		params, ok := request.Params.Arguments.(map[string]any)
		if !ok {
			return nil, fmt.Errorf("invalid arguments format")
		}

		containerPath := getStringParam(params, "container_path", "")
		localPath := getStringParam(params, "local_path", "")

		if containerPath == "" {
			return nil, fmt.Errorf("container_path parameter is required")
		}
		if localPath == "" {
			return nil, fmt.Errorf("local_path parameter is required")
		}

		// Download the file from the container
		err := cremoteServer.client.DownloadFileFromContainer(containerPath, localPath)
		if err != nil {
			return nil, fmt.Errorf("failed to download file: %w", err)
		}

		return &mcp.CallToolResult{
			Content: []mcp.Content{
				mcp.NewTextContent(fmt.Sprintf("File downloaded successfully from container to: %s", localPath)),
			},
			IsError: false,
		}, nil
	})

	// Register console_logs tool
	mcpServer.AddTool(mcp.Tool{
		Name:        "console_logs_cremotemcp",
		Description: "Get console logs from the browser tab",
		InputSchema: mcp.ToolInputSchema{
			Type: "object",
			Properties: map[string]any{
				"tab": map[string]any{
					"type":        "string",
					"description": "Tab ID (optional, uses current tab)",
				},
				"clear": map[string]any{
					"type":        "boolean",
					"description": "Clear logs after retrieval (default: false)",
					"default":     false,
				},
			},
			Required: []string{},
		},
	}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
		// Convert arguments to map
		params, ok := request.Params.Arguments.(map[string]any)
		if !ok {
			return nil, fmt.Errorf("invalid arguments format")
		}

		tab := getStringParam(params, "tab", cremoteServer.currentTab)
		clear := getBoolParam(params, "clear", false)

		// Get console logs
		logs, err := cremoteServer.client.GetConsoleLogs(tab, clear)
		if err != nil {
			return nil, fmt.Errorf("failed to get console logs: %w", err)
		}

		// Format logs for display
		var logText string
		if len(logs) == 0 {
			logText = "No console logs found."
		} else {
			logText = fmt.Sprintf("Found %d console log entries:\n\n", len(logs))
			for i, log := range logs {
				level := log["level"].(string)
				message := log["message"].(string)
				timestamp := log["timestamp"].(string)
				logText += fmt.Sprintf("[%d] %s [%s]: %s\n", i+1, timestamp, level, message)
			}
		}

		return &mcp.CallToolResult{
			Content: []mcp.Content{
				mcp.NewTextContent(logText),
			},
			IsError: false,
		}, nil
	})

	// Register console_command tool
	mcpServer.AddTool(mcp.Tool{
		Name:        "console_command_cremotemcp",
		Description: "Execute a command in the browser console with optional library injection (axe-core, jQuery, Lodash, etc.)",
		InputSchema: mcp.ToolInputSchema{
			Type: "object",
			Properties: map[string]any{
				"command": map[string]any{
					"type":        "string",
					"description": "JavaScript command to execute in console",
				},
				"tab": map[string]any{
					"type":        "string",
					"description": "Tab ID (optional, uses current tab)",
				},
				"inject_library": map[string]any{
					"type":        "string",
					"description": "Library to inject before executing command (optional). Can be a known library name (axe, jquery, lodash, moment, underscore) or a full URL",
				},
				"timeout": map[string]any{
					"type":        "integer",
					"description": "Timeout in seconds (default: 5)",
					"default":     5,
				},
			},
			Required: []string{"command"},
		},
	}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
		// Convert arguments to map
		params, ok := request.Params.Arguments.(map[string]any)
		if !ok {
			return nil, fmt.Errorf("invalid arguments format")
		}

		command := getStringParam(params, "command", "")
		tab := getStringParam(params, "tab", cremoteServer.currentTab)
		injectLibrary := getStringParam(params, "inject_library", "")
		timeout := getIntParam(params, "timeout", 5)

		if command == "" {
			return nil, fmt.Errorf("command parameter is required")
		}

		// Build command parameters
		cmdParams := map[string]string{
			"command": command,
			"timeout": strconv.Itoa(timeout),
		}
		if tab != "" {
			cmdParams["tab"] = tab
		}
		if injectLibrary != "" {
			cmdParams["inject_library"] = injectLibrary
		}

		// Send command to daemon
		resp, err := cremoteServer.client.SendCommand("console-command", cmdParams)
		if err != nil {
			return nil, fmt.Errorf("failed to execute console command: %w", err)
		}

		if !resp.Success {
			return &mcp.CallToolResult{
				Content: []mcp.Content{
					mcp.NewTextContent(fmt.Sprintf("Console command failed: %s", resp.Error)),
				},
				IsError: true,
			}, nil
		}

		// Format result
		resultStr := fmt.Sprintf("Console command executed successfully.\nCommand: %s", command)
		if injectLibrary != "" {
			resultStr += fmt.Sprintf("\nInjected library: %s", injectLibrary)
		}
		if resp.Data != nil {
			resultStr += fmt.Sprintf("\nResult: %v", resp.Data)
		}

		return &mcp.CallToolResult{
			Content: []mcp.Content{
				mcp.NewTextContent(resultStr),
			},
			IsError: false,
		}, nil
	})

	// Register web_element_check tool
	mcpServer.AddTool(mcp.Tool{
		Name:        "web_element_check_cremotemcp",
		Description: "Check existence, visibility, enabled state, count elements",
		InputSchema: mcp.ToolInputSchema{
			Type: "object",
			Properties: map[string]any{
				"selector": map[string]any{
					"type":        "string",
					"description": "CSS selector for the element(s)",
				},
				"check_type": map[string]any{
					"type":        "string",
					"description": "Type of check to perform",
					"enum":        []any{"exists", "visible", "enabled", "focused", "selected", "all"},
					"default":     "exists",
				},
				"tab": map[string]any{
					"type":        "string",
					"description": "Tab ID (optional, uses current tab)",
				},
				"timeout": map[string]any{
					"type":        "integer",
					"description": "Timeout in seconds",
					"default":     5,
				},
			},
			Required: []string{"selector"},
		},
	}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
		// Convert arguments to map
		params, ok := request.Params.Arguments.(map[string]any)
		if !ok {
			return nil, fmt.Errorf("invalid arguments format")
		}

		selector := getStringParam(params, "selector", "")
		checkType := getStringParam(params, "check_type", "exists")
		tab := getStringParam(params, "tab", cremoteServer.currentTab)
		timeout := getIntParam(params, "timeout", 5)

		if selector == "" {
			return nil, fmt.Errorf("selector parameter is required")
		}
		if tab == "" {
			return nil, fmt.Errorf("no tab available - navigate to a page first")
		}

		result, err := cremoteServer.client.CheckElement(tab, selector, checkType, timeout)
		if err != nil {
			return nil, fmt.Errorf("failed to check element: %w", err)
		}

		// Format result as JSON string for display
		resultJSON, _ := json.Marshal(result)

		return &mcp.CallToolResult{
			Content: []mcp.Content{
				mcp.NewTextContent(fmt.Sprintf("Element check result: %s", string(resultJSON))),
			},
			IsError: false,
		}, nil
	})

	// Register web_element_attributes tool
	mcpServer.AddTool(mcp.Tool{
		Name:        "web_element_attributes_cremotemcp",
		Description: "Get attributes, properties, computed styles of an element",
		InputSchema: mcp.ToolInputSchema{
			Type: "object",
			Properties: map[string]any{
				"selector": map[string]any{
					"type":        "string",
					"description": "CSS selector for the element",
				},
				"attributes": map[string]any{
					"type":        "string",
					"description": "Comma-separated list of attributes or 'all' for common attributes. Use 'style_' prefix for computed styles, 'prop_' for JavaScript properties",
					"default":     "all",
				},
				"tab": map[string]any{
					"type":        "string",
					"description": "Tab ID (optional, uses current tab)",
				},
				"timeout": map[string]any{
					"type":        "integer",
					"description": "Timeout in seconds",
					"default":     5,
				},
			},
			Required: []string{"selector"},
		},
	}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
		// Convert arguments to map
		params, ok := request.Params.Arguments.(map[string]any)
		if !ok {
			return nil, fmt.Errorf("invalid arguments format")
		}

		selector := getStringParam(params, "selector", "")
		attributes := getStringParam(params, "attributes", "all")
		tab := getStringParam(params, "tab", cremoteServer.currentTab)
		timeout := getIntParam(params, "timeout", 5)

		if selector == "" {
			return nil, fmt.Errorf("selector parameter is required")
		}
		if tab == "" {
			return nil, fmt.Errorf("no tab available - navigate to a page first")
		}

		result, err := cremoteServer.client.GetElementAttributes(tab, selector, attributes, timeout)
		if err != nil {
			return nil, fmt.Errorf("failed to get element attributes: %w", err)
		}

		// Format result as JSON string for display
		resultJSON, _ := json.Marshal(result)

		return &mcp.CallToolResult{
			Content: []mcp.Content{
				mcp.NewTextContent(fmt.Sprintf("Element attributes: %s", string(resultJSON))),
			},
			IsError: false,
		}, nil
	})

	// Register web_extract_multiple tool
	mcpServer.AddTool(mcp.Tool{
		Name:        "web_extract_multiple_cremotemcp",
		Description: "Extract from multiple selectors in one call",
		InputSchema: mcp.ToolInputSchema{
			Type: "object",
			Properties: map[string]any{
				"selectors": map[string]any{
					"type":        "object",
					"description": "Object with keys as labels and values as CSS selectors",
				},
				"tab": map[string]any{
					"type":        "string",
					"description": "Tab ID (optional, uses current tab)",
				},
				"timeout": map[string]any{
					"type":        "integer",
					"description": "Timeout in seconds",
					"default":     5,
				},
			},
			Required: []string{"selectors"},
		},
	}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
		// Convert arguments to map
		params, ok := request.Params.Arguments.(map[string]any)
		if !ok {
			return nil, fmt.Errorf("invalid arguments format")
		}

		selectorsParam := params["selectors"]
		tab := getStringParam(params, "tab", cremoteServer.currentTab)
		timeout := getIntParam(params, "timeout", 5)

		if selectorsParam == nil {
			return nil, fmt.Errorf("selectors parameter is required")
		}
		if tab == "" {
			return nil, fmt.Errorf("no tab available - navigate to a page first")
		}

		// Convert selectors to map[string]string
		selectorsMap := make(map[string]string)
		if selectorsObj, ok := selectorsParam.(map[string]any); ok {
			for key, value := range selectorsObj {
				if selector, ok := value.(string); ok {
					selectorsMap[key] = selector
				}
			}
		} else {
			return nil, fmt.Errorf("selectors must be an object with string values")
		}

		result, err := cremoteServer.client.ExtractMultiple(tab, selectorsMap, timeout)
		if err != nil {
			return nil, fmt.Errorf("failed to extract multiple: %w", err)
		}

		// Format result as JSON string for display
		resultJSON, _ := json.Marshal(result)

		return &mcp.CallToolResult{
			Content: []mcp.Content{
				mcp.NewTextContent(fmt.Sprintf("Multiple extraction result: %s", string(resultJSON))),
			},
			IsError: false,
		}, nil
	})

	// Register web_extract_links tool
	mcpServer.AddTool(mcp.Tool{
		Name:        "web_extract_links_cremotemcp",
		Description: "Extract all links with filtering options",
		InputSchema: mcp.ToolInputSchema{
			Type: "object",
			Properties: map[string]any{
				"container_selector": map[string]any{
					"type":        "string",
					"description": "Optional CSS selector to limit search to a container",
				},
				"href_pattern": map[string]any{
					"type":        "string",
					"description": "Optional regex pattern to filter links by href",
				},
				"text_pattern": map[string]any{
					"type":        "string",
					"description": "Optional regex pattern to filter links by text content",
				},
				"tab": map[string]any{
					"type":        "string",
					"description": "Tab ID (optional, uses current tab)",
				},
				"timeout": map[string]any{
					"type":        "integer",
					"description": "Timeout in seconds",
					"default":     5,
				},
			},
			Required: []string{},
		},
	}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
		// Convert arguments to map
		params, ok := request.Params.Arguments.(map[string]any)
		if !ok {
			return nil, fmt.Errorf("invalid arguments format")
		}

		containerSelector := getStringParam(params, "container_selector", "")
		hrefPattern := getStringParam(params, "href_pattern", "")
		textPattern := getStringParam(params, "text_pattern", "")
		tab := getStringParam(params, "tab", cremoteServer.currentTab)
		timeout := getIntParam(params, "timeout", 5)

		if tab == "" {
			return nil, fmt.Errorf("no tab available - navigate to a page first")
		}

		result, err := cremoteServer.client.ExtractLinks(tab, containerSelector, hrefPattern, textPattern, timeout)
		if err != nil {
			return nil, fmt.Errorf("failed to extract links: %w", err)
		}

		// Format result as JSON string for display
		resultJSON, _ := json.Marshal(result)

		return &mcp.CallToolResult{
			Content: []mcp.Content{
				mcp.NewTextContent(fmt.Sprintf("Links extraction result: %s", string(resultJSON))),
			},
			IsError: false,
		}, nil
	})

	// Register web_extract_table tool
	mcpServer.AddTool(mcp.Tool{
		Name:        "web_extract_table_cremotemcp",
		Description: "Extract table data as structured JSON",
		InputSchema: mcp.ToolInputSchema{
			Type: "object",
			Properties: map[string]any{
				"selector": map[string]any{
					"type":        "string",
					"description": "CSS selector for the table element",
				},
				"include_headers": map[string]any{
					"type":        "boolean",
					"description": "Whether to extract and use headers for structured data",
					"default":     true,
				},
				"tab": map[string]any{
					"type":        "string",
					"description": "Tab ID (optional, uses current tab)",
				},
				"timeout": map[string]any{
					"type":        "integer",
					"description": "Timeout in seconds",
					"default":     5,
				},
			},
			Required: []string{"selector"},
		},
	}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
		// Convert arguments to map
		params, ok := request.Params.Arguments.(map[string]any)
		if !ok {
			return nil, fmt.Errorf("invalid arguments format")
		}

		selector := getStringParam(params, "selector", "")
		includeHeaders := getBoolParam(params, "include_headers", true)
		tab := getStringParam(params, "tab", cremoteServer.currentTab)
		timeout := getIntParam(params, "timeout", 5)

		if selector == "" {
			return nil, fmt.Errorf("selector parameter is required")
		}
		if tab == "" {
			return nil, fmt.Errorf("no tab available - navigate to a page first")
		}

		result, err := cremoteServer.client.ExtractTable(tab, selector, includeHeaders, timeout)
		if err != nil {
			return nil, fmt.Errorf("failed to extract table: %w", err)
		}

		// Format result as JSON string for display
		resultJSON, _ := json.Marshal(result)

		return &mcp.CallToolResult{
			Content: []mcp.Content{
				mcp.NewTextContent(fmt.Sprintf("Table extraction result: %s", string(resultJSON))),
			},
			IsError: false,
		}, nil
	})

	// Register web_extract_text tool
	mcpServer.AddTool(mcp.Tool{
		Name:        "web_extract_text_cremotemcp",
		Description: "Extract text with pattern matching",
		InputSchema: mcp.ToolInputSchema{
			Type: "object",
			Properties: map[string]any{
				"selector": map[string]any{
					"type":        "string",
					"description": "CSS selector for elements to extract text from",
				},
				"pattern": map[string]any{
					"type":        "string",
					"description": "Optional regex pattern to match within text",
				},
				"extract_type": map[string]any{
					"type":        "string",
					"description": "Type of text extraction",
					"enum":        []any{"text", "innerText", "textContent"},
					"default":     "textContent",
				},
				"tab": map[string]any{
					"type":        "string",
					"description": "Tab ID (optional, uses current tab)",
				},
				"timeout": map[string]any{
					"type":        "integer",
					"description": "Timeout in seconds",
					"default":     5,
				},
			},
			Required: []string{"selector"},
		},
	}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
		// Convert arguments to map
		params, ok := request.Params.Arguments.(map[string]any)
		if !ok {
			return nil, fmt.Errorf("invalid arguments format")
		}

		selector := getStringParam(params, "selector", "")
		pattern := getStringParam(params, "pattern", "")
		extractType := getStringParam(params, "extract_type", "textContent")
		tab := getStringParam(params, "tab", cremoteServer.currentTab)
		timeout := getIntParam(params, "timeout", 5)

		if selector == "" {
			return nil, fmt.Errorf("selector parameter is required")
		}
		if tab == "" {
			return nil, fmt.Errorf("no tab available - navigate to a page first")
		}

		result, err := cremoteServer.client.ExtractText(tab, selector, pattern, extractType, timeout)
		if err != nil {
			return nil, fmt.Errorf("failed to extract text: %w", err)
		}

		// Format result as JSON string for display
		resultJSON, _ := json.Marshal(result)

		return &mcp.CallToolResult{
			Content: []mcp.Content{
				mcp.NewTextContent(fmt.Sprintf("Text extraction result: %s", string(resultJSON))),
			},
			IsError: false,
		}, nil
	})

	// Register web_form_analyze tool
	mcpServer.AddTool(mcp.Tool{
		Name:        "web_form_analyze_cremotemcp",
		Description: "Analyze forms completely",
		InputSchema: mcp.ToolInputSchema{
			Type: "object",
			Properties: map[string]any{
				"selector": map[string]any{
					"type":        "string",
					"description": "CSS selector for the form element",
				},
				"tab": map[string]any{
					"type":        "string",
					"description": "Tab ID (optional, uses current tab)",
				},
				"timeout": map[string]any{
					"type":        "integer",
					"description": "Timeout in seconds",
					"default":     5,
				},
			},
			Required: []string{"selector"},
		},
	}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
		// Convert arguments to map
		params, ok := request.Params.Arguments.(map[string]any)
		if !ok {
			return nil, fmt.Errorf("invalid arguments format")
		}

		selector := getStringParam(params, "selector", "")
		if selector == "" {
			return nil, fmt.Errorf("selector parameter is required")
		}

		tab := getStringParam(params, "tab", cremoteServer.currentTab)
		timeout := getIntParam(params, "timeout", 5)

		result, err := cremoteServer.client.AnalyzeForm(tab, selector, timeout)
		if err != nil {
			return nil, fmt.Errorf("failed to analyze form: %w", err)
		}

		resultJSON, err := json.MarshalIndent(result, "", "  ")
		if err != nil {
			return nil, fmt.Errorf("failed to marshal result: %w", err)
		}

		return &mcp.CallToolResult{
			Content: []mcp.Content{
				mcp.NewTextContent(fmt.Sprintf("Form analysis result: %s", string(resultJSON))),
			},
			IsError: false,
		}, nil
	})

	// Register web_interact_multiple tool
	mcpServer.AddTool(mcp.Tool{
		Name:        "web_interact_multiple_cremotemcp",
		Description: "Batch interactions",
		InputSchema: mcp.ToolInputSchema{
			Type: "object",
			Properties: map[string]any{
				"interactions": map[string]any{
					"type":        "array",
					"description": "Array of interactions to perform",
					"items": map[string]any{
						"type": "object",
						"properties": map[string]any{
							"selector": map[string]any{
								"type":        "string",
								"description": "CSS selector for the element",
							},
							"action": map[string]any{
								"type":        "string",
								"description": "Action to perform",
								"enum":        []any{"click", "fill", "select", "check", "uncheck"},
							},
							"value": map[string]any{
								"type":        "string",
								"description": "Value for the action (required for fill, select)",
							},
						},
						"required": []string{"selector", "action"},
					},
				},
				"tab": map[string]any{
					"type":        "string",
					"description": "Tab ID (optional, uses current tab)",
				},
				"timeout": map[string]any{
					"type":        "integer",
					"description": "Timeout in seconds",
					"default":     5,
				},
			},
			Required: []string{"interactions"},
		},
	}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
		// Convert arguments to map
		params, ok := request.Params.Arguments.(map[string]any)
		if !ok {
			return nil, fmt.Errorf("invalid arguments format")
		}

		interactionsData, ok := params["interactions"].([]any)
		if !ok {
			return nil, fmt.Errorf("interactions parameter is required and must be an array")
		}

		// Parse interactions
		var interactions []client.InteractionItem
		for _, interactionData := range interactionsData {
			interactionMap, ok := interactionData.(map[string]any)
			if !ok {
				return nil, fmt.Errorf("each interaction must be an object")
			}

			interaction := client.InteractionItem{}

			if selector, ok := interactionMap["selector"].(string); ok {
				interaction.Selector = selector
			} else {
				return nil, fmt.Errorf("each interaction must have a selector")
			}

			if action, ok := interactionMap["action"].(string); ok {
				interaction.Action = action
			} else {
				return nil, fmt.Errorf("each interaction must have an action")
			}

			if value, ok := interactionMap["value"].(string); ok {
				interaction.Value = value
			}

			interactions = append(interactions, interaction)
		}

		tab := getStringParam(params, "tab", cremoteServer.currentTab)
		timeout := getIntParam(params, "timeout", 5)

		result, err := cremoteServer.client.InteractMultiple(tab, interactions, timeout)
		if err != nil {
			return nil, fmt.Errorf("failed to perform multiple interactions: %w", err)
		}

		resultJSON, err := json.MarshalIndent(result, "", "  ")
		if err != nil {
			return nil, fmt.Errorf("failed to marshal result: %w", err)
		}

		return &mcp.CallToolResult{
			Content: []mcp.Content{
				mcp.NewTextContent(fmt.Sprintf("Multiple interactions result: %s", string(resultJSON))),
			},
			IsError: false,
		}, nil
	})

	// Register web_form_fill_bulk tool
	mcpServer.AddTool(mcp.Tool{
		Name:        "web_form_fill_bulk_cremotemcp",
		Description: "Fill entire forms with key-value pairs",
		InputSchema: mcp.ToolInputSchema{
			Type: "object",
			Properties: map[string]any{
				"fields": map[string]any{
					"type":        "object",
					"description": "Map of field names/selectors to values",
				},
				"form_selector": map[string]any{
					"type":        "string",
					"description": "CSS selector for the form element (optional)",
				},
				"tab": map[string]any{
					"type":        "string",
					"description": "Tab ID (optional, uses current tab)",
				},
				"timeout": map[string]any{
					"type":        "integer",
					"description": "Timeout in seconds",
					"default":     5,
				},
			},
			Required: []string{"fields"},
		},
	}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
		// Convert arguments to map
		params, ok := request.Params.Arguments.(map[string]any)
		if !ok {
			return nil, fmt.Errorf("invalid arguments format")
		}

		fieldsData, ok := params["fields"].(map[string]any)
		if !ok {
			return nil, fmt.Errorf("fields parameter is required and must be an object")
		}

		// Convert fields to map[string]string
		fields := make(map[string]string)
		for key, value := range fieldsData {
			if strValue, ok := value.(string); ok {
				fields[key] = strValue
			} else {
				return nil, fmt.Errorf("all field values must be strings")
			}
		}

		formSelector := getStringParam(params, "form_selector", "")
		tab := getStringParam(params, "tab", cremoteServer.currentTab)
		timeout := getIntParam(params, "timeout", 5)

		result, err := cremoteServer.client.FillFormBulk(tab, formSelector, fields, timeout)
		if err != nil {
			return nil, fmt.Errorf("failed to fill form bulk: %w", err)
		}

		resultJSON, err := json.MarshalIndent(result, "", "  ")
		if err != nil {
			return nil, fmt.Errorf("failed to marshal result: %w", err)
		}

		return &mcp.CallToolResult{
			Content: []mcp.Content{
				mcp.NewTextContent(fmt.Sprintf("Form bulk fill result: %s", string(resultJSON))),
			},
			IsError: false,
		}, nil
	})

	// Register web_page_info tool
	mcpServer.AddTool(mcp.Tool{
		Name:        "web_page_info_cremotemcp",
		Description: "Get comprehensive page metadata and state information",
		InputSchema: mcp.ToolInputSchema{
			Type: "object",
			Properties: map[string]any{
				"tab": map[string]any{
					"type":        "string",
					"description": "Tab ID (optional, uses current tab if not specified)",
				},
				"timeout": map[string]any{
					"type":        "integer",
					"description": "Timeout in seconds (default: 5)",
					"default":     5,
				},
			},
		},
	}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
		// Convert arguments to map
		params, ok := request.Params.Arguments.(map[string]any)
		if !ok {
			return nil, fmt.Errorf("invalid arguments format")
		}

		tabID := getStringParam(params, "tab", "")
		timeout := getIntParam(params, "timeout", 5)

		result, err := cremoteServer.client.GetPageInfo(tabID, timeout)
		if err != nil {
			return &mcp.CallToolResult{
				Content: []mcp.Content{
					mcp.NewTextContent(fmt.Sprintf("Error getting page info: %v", err)),
				},
				IsError: true,
			}, nil
		}

		resultJSON, err := json.MarshalIndent(result, "", "  ")
		if err != nil {
			return nil, fmt.Errorf("failed to marshal result: %w", err)
		}

		return &mcp.CallToolResult{
			Content: []mcp.Content{
				mcp.NewTextContent(fmt.Sprintf("Page info: %s", string(resultJSON))),
			},
			IsError: false,
		}, nil
	})

	// Register web_viewport_info tool
	mcpServer.AddTool(mcp.Tool{
		Name:        "web_viewport_info_cremotemcp",
		Description: "Get viewport and scroll information",
		InputSchema: mcp.ToolInputSchema{
			Type: "object",
			Properties: map[string]any{
				"tab": map[string]any{
					"type":        "string",
					"description": "Tab ID (optional, uses current tab if not specified)",
				},
				"timeout": map[string]any{
					"type":        "integer",
					"description": "Timeout in seconds (default: 5)",
					"default":     5,
				},
			},
		},
	}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
		// Convert arguments to map
		params, ok := request.Params.Arguments.(map[string]any)
		if !ok {
			return nil, fmt.Errorf("invalid arguments format")
		}

		tabID := getStringParam(params, "tab", "")
		timeout := getIntParam(params, "timeout", 5)

		result, err := cremoteServer.client.GetViewportInfo(tabID, timeout)
		if err != nil {
			return &mcp.CallToolResult{
				Content: []mcp.Content{
					mcp.NewTextContent(fmt.Sprintf("Error getting viewport info: %v", err)),
				},
				IsError: true,
			}, nil
		}

		resultJSON, err := json.MarshalIndent(result, "", "  ")
		if err != nil {
			return nil, fmt.Errorf("failed to marshal result: %w", err)
		}

		return &mcp.CallToolResult{
			Content: []mcp.Content{
				mcp.NewTextContent(fmt.Sprintf("Viewport info: %s", string(resultJSON))),
			},
			IsError: false,
		}, nil
	})

	// Register web_performance_metrics tool
	mcpServer.AddTool(mcp.Tool{
		Name:        "web_performance_metrics_cremotemcp",
		Description: "Get page performance metrics",
		InputSchema: mcp.ToolInputSchema{
			Type: "object",
			Properties: map[string]any{
				"tab": map[string]any{
					"type":        "string",
					"description": "Tab ID (optional, uses current tab if not specified)",
				},
				"timeout": map[string]any{
					"type":        "integer",
					"description": "Timeout in seconds (default: 5)",
					"default":     5,
				},
			},
		},
	}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
		// Convert arguments to map
		params, ok := request.Params.Arguments.(map[string]any)
		if !ok {
			return nil, fmt.Errorf("invalid arguments format")
		}

		tabID := getStringParam(params, "tab", "")
		timeout := getIntParam(params, "timeout", 5)

		result, err := cremoteServer.client.GetPerformance(tabID, timeout)
		if err != nil {
			return &mcp.CallToolResult{
				Content: []mcp.Content{
					mcp.NewTextContent(fmt.Sprintf("Error getting performance metrics: %v", err)),
				},
				IsError: true,
			}, nil
		}

		resultJSON, err := json.MarshalIndent(result, "", "  ")
		if err != nil {
			return nil, fmt.Errorf("failed to marshal result: %w", err)
		}

		return &mcp.CallToolResult{
			Content: []mcp.Content{
				mcp.NewTextContent(fmt.Sprintf("Performance metrics: %s", string(resultJSON))),
			},
			IsError: false,
		}, nil
	})

	// Register web_content_check tool
	mcpServer.AddTool(mcp.Tool{
		Name:        "web_content_check_cremotemcp",
		Description: "Check for specific content types and loading states",
		InputSchema: mcp.ToolInputSchema{
			Type: "object",
			Properties: map[string]any{
				"type": map[string]any{
					"type":        "string",
					"description": "Content type to check",
					"enum":        []any{"images", "scripts", "styles", "forms", "links", "iframes", "errors"},
				},
				"tab": map[string]any{
					"type":        "string",
					"description": "Tab ID (optional, uses current tab if not specified)",
				},
				"timeout": map[string]any{
					"type":        "integer",
					"description": "Timeout in seconds (default: 5)",
					"default":     5,
				},
			},
			Required: []string{"type"},
		},
	}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
		// Convert arguments to map
		params, ok := request.Params.Arguments.(map[string]any)
		if !ok {
			return nil, fmt.Errorf("invalid arguments format")
		}

		contentType := getStringParam(params, "type", "")
		if contentType == "" {
			return nil, fmt.Errorf("type parameter is required")
		}

		tabID := getStringParam(params, "tab", "")
		timeout := getIntParam(params, "timeout", 5)

		result, err := cremoteServer.client.CheckContent(tabID, contentType, timeout)
		if err != nil {
			return &mcp.CallToolResult{
				Content: []mcp.Content{
					mcp.NewTextContent(fmt.Sprintf("Error checking content: %v", err)),
				},
				IsError: true,
			}, nil
		}

		resultJSON, err := json.MarshalIndent(result, "", "  ")
		if err != nil {
			return nil, fmt.Errorf("failed to marshal result: %w", err)
		}

		return &mcp.CallToolResult{
			Content: []mcp.Content{
				mcp.NewTextContent(fmt.Sprintf("Content check result: %s", string(resultJSON))),
			},
			IsError: false,
		}, nil
	})

	// Phase 5: Enhanced Screenshot and File Management Tools

	// web_screenshot_element_cremotemcp - Screenshot specific elements
	mcpServer.AddTool(mcp.Tool{
		Name:        "web_screenshot_element_cremotemcp",
		Description: "Take a screenshot of a specific element on the page",
		InputSchema: mcp.ToolInputSchema{
			Type: "object",
			Properties: map[string]any{
				"selector": map[string]any{
					"type":        "string",
					"description": "CSS selector for the element to screenshot",
				},
				"output": map[string]any{
					"type":        "string",
					"description": "Path where to save the screenshot",
				},
				"tab": map[string]any{
					"type":        "string",
					"description": "Tab ID (optional, uses current tab if not specified)",
				},
				"timeout": map[string]any{
					"type":        "integer",
					"description": "Timeout in seconds (default: 5)",
				},
			},
			Required: []string{"selector", "output"},
		},
	}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
		// Convert arguments to map
		params, ok := request.Params.Arguments.(map[string]any)
		if !ok {
			return nil, fmt.Errorf("invalid arguments format")
		}

		selector := getStringParam(params, "selector", "")
		output := getStringParam(params, "output", "")
		tab := getStringParam(params, "tab", cremoteServer.currentTab)
		timeout := getIntParam(params, "timeout", 5)

		if selector == "" {
			return nil, fmt.Errorf("selector parameter is required")
		}
		if output == "" {
			return nil, fmt.Errorf("output parameter is required")
		}
		if tab == "" {
			return nil, fmt.Errorf("no tab available - navigate to a page first")
		}

		err := cremoteServer.client.ScreenshotElement(tab, selector, output, timeout)
		if err != nil {
			return &mcp.CallToolResult{
				Content: []mcp.Content{
					mcp.NewTextContent(fmt.Sprintf("Error taking element screenshot: %v", err)),
				},
				IsError: true,
			}, nil
		}

		cremoteServer.screenshots = append(cremoteServer.screenshots, output)

		return &mcp.CallToolResult{
			Content: []mcp.Content{
				mcp.NewTextContent(fmt.Sprintf("Element screenshot saved to: %s", output)),
			},
			IsError: false,
		}, nil
	})

	// web_screenshot_enhanced_cremotemcp - Enhanced screenshots with metadata
	mcpServer.AddTool(mcp.Tool{
		Name:        "web_screenshot_enhanced_cremotemcp",
		Description: "Take an enhanced screenshot with metadata (timestamp, viewport size, URL)",
		InputSchema: mcp.ToolInputSchema{
			Type: "object",
			Properties: map[string]any{
				"output": map[string]any{
					"type":        "string",
					"description": "Path where to save the screenshot",
				},
				"full_page": map[string]any{
					"type":        "boolean",
					"description": "Capture full page (default: false)",
				},
				"tab": map[string]any{
					"type":        "string",
					"description": "Tab ID (optional, uses current tab if not specified)",
				},
				"timeout": map[string]any{
					"type":        "integer",
					"description": "Timeout in seconds (default: 5)",
				},
			},
			Required: []string{"output"},
		},
	}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
		// Convert arguments to map
		params, ok := request.Params.Arguments.(map[string]any)
		if !ok {
			return nil, fmt.Errorf("invalid arguments format")
		}

		output := getStringParam(params, "output", "")
		fullPage := getBoolParam(params, "full_page", false)
		tab := getStringParam(params, "tab", cremoteServer.currentTab)
		timeout := getIntParam(params, "timeout", 5)

		if output == "" {
			return nil, fmt.Errorf("output parameter is required")
		}
		if tab == "" {
			return nil, fmt.Errorf("no tab available - navigate to a page first")
		}

		metadata, err := cremoteServer.client.ScreenshotEnhanced(tab, output, fullPage, timeout)
		if err != nil {
			return &mcp.CallToolResult{
				Content: []mcp.Content{
					mcp.NewTextContent(fmt.Sprintf("Error taking enhanced screenshot: %v", err)),
				},
				IsError: true,
			}, nil
		}

		cremoteServer.screenshots = append(cremoteServer.screenshots, output)

		metadataJSON, err := json.MarshalIndent(metadata, "", "  ")
		if err != nil {
			return nil, fmt.Errorf("failed to marshal metadata: %w", err)
		}

		return &mcp.CallToolResult{
			Content: []mcp.Content{
				mcp.NewTextContent(fmt.Sprintf("Enhanced screenshot saved with metadata:\n%s", string(metadataJSON))),
			},
			IsError: false,
		}, nil
	})

	// file_operations_bulk_cremotemcp - Bulk file operations
	mcpServer.AddTool(mcp.Tool{
		Name:        "file_operations_bulk_cremotemcp",
		Description: "Perform bulk file operations (upload/download multiple files)",
		InputSchema: mcp.ToolInputSchema{
			Type: "object",
			Properties: map[string]any{
				"operation": map[string]any{
					"type":        "string",
					"description": "Operation type",
					"enum":        []any{"upload", "download"},
				},
				"files": map[string]any{
					"type":        "array",
					"description": "Array of file operations",
					"items": map[string]any{
						"type": "object",
						"properties": map[string]any{
							"local_path": map[string]any{
								"type":        "string",
								"description": "Path on client machine",
							},
							"container_path": map[string]any{
								"type":        "string",
								"description": "Path in container",
							},
							"operation": map[string]any{
								"type":        "string",
								"description": "Override operation type for this file",
								"enum":        []any{"upload", "download"},
							},
						},
						"required": []any{"local_path", "container_path"},
					},
				},
				"timeout": map[string]any{
					"type":        "integer",
					"description": "Timeout in seconds (default: 30)",
				},
			},
			Required: []string{"operation", "files"},
		},
	}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
		// Convert arguments to map
		params, ok := request.Params.Arguments.(map[string]any)
		if !ok {
			return nil, fmt.Errorf("invalid arguments format")
		}

		operation := getStringParam(params, "operation", "")
		filesParam := params["files"]
		timeout := getIntParam(params, "timeout", 30)

		if operation == "" {
			return nil, fmt.Errorf("operation parameter is required")
		}
		if filesParam == nil {
			return nil, fmt.Errorf("files parameter is required")
		}

		// Convert files parameter to FileOperation slice
		filesArray, ok := filesParam.([]any)
		if !ok {
			return nil, fmt.Errorf("files must be an array")
		}

		var operations []client.FileOperation
		for _, fileItem := range filesArray {
			fileMap, ok := fileItem.(map[string]any)
			if !ok {
				return nil, fmt.Errorf("each file must be an object")
			}

			localPath := getStringParam(fileMap, "local_path", "")
			containerPath := getStringParam(fileMap, "container_path", "")
			fileOperation := getStringParam(fileMap, "operation", operation)

			if localPath == "" || containerPath == "" {
				return nil, fmt.Errorf("local_path and container_path are required for each file")
			}

			operations = append(operations, client.FileOperation{
				LocalPath:     localPath,
				ContainerPath: containerPath,
				Operation:     fileOperation,
			})
		}

		result, err := cremoteServer.client.BulkFiles(operation, operations, timeout)
		if err != nil {
			return &mcp.CallToolResult{
				Content: []mcp.Content{
					mcp.NewTextContent(fmt.Sprintf("Error performing bulk file operations: %v", err)),
				},
				IsError: true,
			}, nil
		}

		resultJSON, err := json.MarshalIndent(result, "", "  ")
		if err != nil {
			return nil, fmt.Errorf("failed to marshal result: %w", err)
		}

		return &mcp.CallToolResult{
			Content: []mcp.Content{
				mcp.NewTextContent(fmt.Sprintf("Bulk file operations completed:\n%s", string(resultJSON))),
			},
			IsError: false,
		}, nil
	})

	// file_management_cremotemcp - File management operations
	mcpServer.AddTool(mcp.Tool{
		Name:        "file_management_cremotemcp",
		Description: "Manage files (cleanup, list, get info)",
		InputSchema: mcp.ToolInputSchema{
			Type: "object",
			Properties: map[string]any{
				"operation": map[string]any{
					"type":        "string",
					"description": "Management operation",
					"enum":        []any{"cleanup", "list", "info"},
				},
				"pattern": map[string]any{
					"type":        "string",
					"description": "File pattern for cleanup/list, or file path for info",
				},
				"max_age": map[string]any{
					"type":        "string",
					"description": "Max age in hours for cleanup (default: 24)",
				},
			},
			Required: []string{"operation"},
		},
	}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
		// Convert arguments to map
		params, ok := request.Params.Arguments.(map[string]any)
		if !ok {
			return nil, fmt.Errorf("invalid arguments format")
		}

		operation := getStringParam(params, "operation", "")
		pattern := getStringParam(params, "pattern", "")
		maxAge := getStringParam(params, "max_age", "")

		if operation == "" {
			return nil, fmt.Errorf("operation parameter is required")
		}

		result, err := cremoteServer.client.ManageFiles(operation, pattern, maxAge)
		if err != nil {
			return &mcp.CallToolResult{
				Content: []mcp.Content{
					mcp.NewTextContent(fmt.Sprintf("Error managing files: %v", err)),
				},
				IsError: true,
			}, nil
		}

		resultJSON, err := json.MarshalIndent(result, "", "  ")
		if err != nil {
			return nil, fmt.Errorf("failed to marshal result: %w", err)
		}

		return &mcp.CallToolResult{
			Content: []mcp.Content{
				mcp.NewTextContent(fmt.Sprintf("File management result:\n%s", string(resultJSON))),
			},
			IsError: false,
		}, nil
	})

	// Accessibility tree tools
	mcpServer.AddTool(mcp.Tool{
		Name:        "get_accessibility_tree_cremotemcp",
		Description: "Get the full accessibility tree for a page with optional contrast data annotation",
		InputSchema: mcp.ToolInputSchema{
			Type: "object",
			Properties: map[string]any{
				"tab": map[string]any{
					"type":        "string",
					"description": "Tab ID (optional, uses current tab)",
				},
				"depth": map[string]any{
					"type":        "integer",
					"description": "Maximum depth to retrieve (optional, omit for full tree)",
					"minimum":     0,
				},
				"include_contrast": map[string]any{
					"type":        "boolean",
					"description": "Include contrast check availability annotation for text nodes (default: false)",
					"default":     false,
				},
				"timeout": map[string]any{
					"type":        "integer",
					"description": "Timeout in seconds",
					"default":     5,
				},
			},
			Required: []string{},
		},
	}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
		params, ok := request.Params.Arguments.(map[string]any)
		if !ok {
			return nil, fmt.Errorf("invalid arguments format")
		}

		tab := getStringParam(params, "tab", cremoteServer.currentTab)
		includeContrast := getBoolParam(params, "include_contrast", false)
		timeout := getIntParam(params, "timeout", 5)

		// Parse depth parameter
		var depth *int
		if depthParam := getIntParam(params, "depth", -1); depthParam >= 0 {
			depth = &depthParam
		}

		// Build command parameters
		cmdParams := map[string]string{
			"timeout": strconv.Itoa(timeout),
		}
		if tab != "" {
			cmdParams["tab"] = tab
		}
		if depth != nil {
			cmdParams["depth"] = strconv.Itoa(*depth)
		}
		if includeContrast {
			cmdParams["include_contrast"] = "true"
		}

		// Send command to daemon
		resp, err := cremoteServer.client.SendCommand("get-accessibility-tree", cmdParams)
		if err != nil {
			return nil, fmt.Errorf("failed to get accessibility tree: %w", err)
		}

		if !resp.Success {
			return &mcp.CallToolResult{
				Content: []mcp.Content{
					mcp.NewTextContent(fmt.Sprintf("Failed to get accessibility tree: %s", resp.Error)),
				},
				IsError: true,
			}, nil
		}

		resultJSON, err := json.MarshalIndent(resp.Data, "", "  ")
		if err != nil {
			return nil, fmt.Errorf("failed to marshal result: %w", err)
		}

		return &mcp.CallToolResult{
			Content: []mcp.Content{
				mcp.NewTextContent(string(resultJSON)),
			},
			IsError: false,
		}, nil
	})

	mcpServer.AddTool(mcp.Tool{
		Name:        "get_partial_accessibility_tree_cremotemcp",
		Description: "Get accessibility tree for a specific element and its relatives",
		InputSchema: mcp.ToolInputSchema{
			Type: "object",
			Properties: map[string]any{
				"selector": map[string]any{
					"type":        "string",
					"description": "CSS selector for the target element",
				},
				"tab": map[string]any{
					"type":        "string",
					"description": "Tab ID (optional, uses current tab)",
				},
				"fetch_relatives": map[string]any{
					"type":        "boolean",
					"description": "Whether to fetch ancestors, siblings, and children",
					"default":     true,
				},
				"timeout": map[string]any{
					"type":        "integer",
					"description": "Timeout in seconds",
					"default":     5,
				},
			},
			Required: []string{"selector"},
		},
	}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
		params, ok := request.Params.Arguments.(map[string]any)
		if !ok {
			return nil, fmt.Errorf("invalid arguments format")
		}

		selector := getStringParam(params, "selector", "")
		if selector == "" {
			return nil, fmt.Errorf("selector parameter is required")
		}

		tab := getStringParam(params, "tab", cremoteServer.currentTab)
		timeout := getIntParam(params, "timeout", 5)
		fetchRelatives := getBoolParam(params, "fetch_relatives", true)

		result, err := cremoteServer.client.GetPartialAccessibilityTree(tab, selector, fetchRelatives, timeout)
		if err != nil {
			return nil, fmt.Errorf("failed to get partial accessibility tree: %w", err)
		}

		resultJSON, err := json.MarshalIndent(result, "", "  ")
		if err != nil {
			return nil, fmt.Errorf("failed to marshal result: %w", err)
		}

		return &mcp.CallToolResult{
			Content: []mcp.Content{
				mcp.NewTextContent(string(resultJSON)),
			},
			IsError: false,
		}, nil
	})

	mcpServer.AddTool(mcp.Tool{
		Name:        "query_accessibility_tree_cremotemcp",
		Description: "Query accessibility tree for nodes matching specific criteria",
		InputSchema: mcp.ToolInputSchema{
			Type: "object",
			Properties: map[string]any{
				"tab": map[string]any{
					"type":        "string",
					"description": "Tab ID (optional, uses current tab)",
				},
				"selector": map[string]any{
					"type":        "string",
					"description": "CSS selector to limit search scope (optional)",
				},
				"accessible_name": map[string]any{
					"type":        "string",
					"description": "Accessible name to match (optional)",
				},
				"role": map[string]any{
					"type":        "string",
					"description": "ARIA role to match (optional)",
				},
				"timeout": map[string]any{
					"type":        "integer",
					"description": "Timeout in seconds",
					"default":     5,
				},
			},
			Required: []string{},
		},
	}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
		params, ok := request.Params.Arguments.(map[string]any)
		if !ok {
			return nil, fmt.Errorf("invalid arguments format")
		}

		tab := getStringParam(params, "tab", cremoteServer.currentTab)
		timeout := getIntParam(params, "timeout", 5)
		selector := getStringParam(params, "selector", "")
		accessibleName := getStringParam(params, "accessible_name", "")
		role := getStringParam(params, "role", "")

		// At least one search criteria must be provided
		if selector == "" && accessibleName == "" && role == "" {
			return nil, fmt.Errorf("at least one search criteria (selector, accessible_name, or role) must be provided")
		}

		result, err := cremoteServer.client.QueryAccessibilityTree(tab, selector, accessibleName, role, timeout)
		if err != nil {
			return nil, fmt.Errorf("failed to query accessibility tree: %w", err)
		}

		resultJSON, err := json.MarshalIndent(result, "", "  ")
		if err != nil {
			return nil, fmt.Errorf("failed to marshal result: %w", err)
		}

		return &mcp.CallToolResult{
			Content: []mcp.Content{
				mcp.NewTextContent(string(resultJSON)),
			},
			IsError: false,
		}, nil
	})

	// Cache management tools
	mcpServer.AddTool(mcp.Tool{
		Name:        "web_disable_cache_cremotemcp",
		Description: "Disable browser cache for a tab",
		InputSchema: mcp.ToolInputSchema{
			Type: "object",
			Properties: map[string]any{
				"tab": map[string]any{
					"type":        "string",
					"description": "Tab ID (optional, uses current tab)",
				},
				"timeout": map[string]any{
					"type":        "integer",
					"description": "Timeout in seconds (default: 5)",
					"default":     5,
				},
			},
		},
	}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
		// Convert arguments to map
		params, ok := request.Params.Arguments.(map[string]any)
		if !ok {
			return nil, fmt.Errorf("invalid arguments format")
		}

		tab := getStringParam(params, "tab", "")
		timeout := getIntParam(params, "timeout", 5)

		err := cremoteServer.client.DisableCache(tab, timeout)
		if err != nil {
			return &mcp.CallToolResult{
				Content: []mcp.Content{
					mcp.NewTextContent(fmt.Sprintf("Error disabling cache: %v", err)),
				},
				IsError: true,
			}, nil
		}

		return &mcp.CallToolResult{
			Content: []mcp.Content{
				mcp.NewTextContent("Cache disabled successfully"),
			},
			IsError: false,
		}, nil
	})

	mcpServer.AddTool(mcp.Tool{
		Name:        "web_enable_cache_cremotemcp",
		Description: "Enable browser cache for a tab",
		InputSchema: mcp.ToolInputSchema{
			Type: "object",
			Properties: map[string]any{
				"tab": map[string]any{
					"type":        "string",
					"description": "Tab ID (optional, uses current tab)",
				},
				"timeout": map[string]any{
					"type":        "integer",
					"description": "Timeout in seconds (default: 5)",
					"default":     5,
				},
			},
		},
	}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
		// Convert arguments to map
		params, ok := request.Params.Arguments.(map[string]any)
		if !ok {
			return nil, fmt.Errorf("invalid arguments format")
		}

		tab := getStringParam(params, "tab", "")
		timeout := getIntParam(params, "timeout", 5)

		err := cremoteServer.client.EnableCache(tab, timeout)
		if err != nil {
			return &mcp.CallToolResult{
				Content: []mcp.Content{
					mcp.NewTextContent(fmt.Sprintf("Error enabling cache: %v", err)),
				},
				IsError: true,
			}, nil
		}

		return &mcp.CallToolResult{
			Content: []mcp.Content{
				mcp.NewTextContent("Cache enabled successfully"),
			},
			IsError: false,
		}, nil
	})

	mcpServer.AddTool(mcp.Tool{
		Name:        "web_clear_cache_cremotemcp",
		Description: "Clear browser cache for a tab",
		InputSchema: mcp.ToolInputSchema{
			Type: "object",
			Properties: map[string]any{
				"tab": map[string]any{
					"type":        "string",
					"description": "Tab ID (optional, uses current tab)",
				},
				"timeout": map[string]any{
					"type":        "integer",
					"description": "Timeout in seconds (default: 5)",
					"default":     5,
				},
			},
		},
	}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
		// Convert arguments to map
		params, ok := request.Params.Arguments.(map[string]any)
		if !ok {
			return nil, fmt.Errorf("invalid arguments format")
		}

		tab := getStringParam(params, "tab", "")
		timeout := getIntParam(params, "timeout", 5)

		err := cremoteServer.client.ClearCache(tab, timeout)
		if err != nil {
			return &mcp.CallToolResult{
				Content: []mcp.Content{
					mcp.NewTextContent(fmt.Sprintf("Error clearing cache: %v", err)),
				},
				IsError: true,
			}, nil
		}

		return &mcp.CallToolResult{
			Content: []mcp.Content{
				mcp.NewTextContent("Cache cleared successfully"),
			},
			IsError: false,
		}, nil
	})

	// Site data management tools
	mcpServer.AddTool(mcp.Tool{
		Name:        "web_clear_all_site_data_cremotemcp",
		Description: "Clear all site data including cookies, storage, cache, etc. for a tab",
		InputSchema: mcp.ToolInputSchema{
			Type: "object",
			Properties: map[string]any{
				"tab": map[string]any{
					"type":        "string",
					"description": "Tab ID (optional, uses current tab)",
				},
				"timeout": map[string]any{
					"type":        "integer",
					"description": "Timeout in seconds (default: 5)",
					"default":     5,
				},
			},
		},
	}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
		// Convert arguments to map
		params, ok := request.Params.Arguments.(map[string]any)
		if !ok {
			return nil, fmt.Errorf("invalid arguments format")
		}

		tab := getStringParam(params, "tab", "")
		timeout := getIntParam(params, "timeout", 5)

		err := cremoteServer.client.ClearAllSiteData(tab, timeout)
		if err != nil {
			return &mcp.CallToolResult{
				Content: []mcp.Content{
					mcp.NewTextContent(fmt.Sprintf("Error clearing all site data: %v", err)),
				},
				IsError: true,
			}, nil
		}

		return &mcp.CallToolResult{
			Content: []mcp.Content{
				mcp.NewTextContent("All site data cleared successfully"),
			},
			IsError: false,
		}, nil
	})

	mcpServer.AddTool(mcp.Tool{
		Name:        "web_clear_cookies_cremotemcp",
		Description: "Clear cookies for a tab",
		InputSchema: mcp.ToolInputSchema{
			Type: "object",
			Properties: map[string]any{
				"tab": map[string]any{
					"type":        "string",
					"description": "Tab ID (optional, uses current tab)",
				},
				"timeout": map[string]any{
					"type":        "integer",
					"description": "Timeout in seconds (default: 5)",
					"default":     5,
				},
			},
		},
	}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
		// Convert arguments to map
		params, ok := request.Params.Arguments.(map[string]any)
		if !ok {
			return nil, fmt.Errorf("invalid arguments format")
		}

		tab := getStringParam(params, "tab", "")
		timeout := getIntParam(params, "timeout", 5)

		err := cremoteServer.client.ClearCookies(tab, timeout)
		if err != nil {
			return &mcp.CallToolResult{
				Content: []mcp.Content{
					mcp.NewTextContent(fmt.Sprintf("Error clearing cookies: %v", err)),
				},
				IsError: true,
			}, nil
		}

		return &mcp.CallToolResult{
			Content: []mcp.Content{
				mcp.NewTextContent("Cookies cleared successfully"),
			},
			IsError: false,
		}, nil
	})

	mcpServer.AddTool(mcp.Tool{
		Name:        "web_clear_storage_cremotemcp",
		Description: "Clear web storage (localStorage, sessionStorage, IndexedDB, etc.) for a tab",
		InputSchema: mcp.ToolInputSchema{
			Type: "object",
			Properties: map[string]any{
				"tab": map[string]any{
					"type":        "string",
					"description": "Tab ID (optional, uses current tab)",
				},
				"timeout": map[string]any{
					"type":        "integer",
					"description": "Timeout in seconds (default: 5)",
					"default":     5,
				},
			},
		},
	}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
		// Convert arguments to map
		params, ok := request.Params.Arguments.(map[string]any)
		if !ok {
			return nil, fmt.Errorf("invalid arguments format")
		}

		tab := getStringParam(params, "tab", "")
		timeout := getIntParam(params, "timeout", 5)

		err := cremoteServer.client.ClearStorage(tab, timeout)
		if err != nil {
			return &mcp.CallToolResult{
				Content: []mcp.Content{
					mcp.NewTextContent(fmt.Sprintf("Error clearing storage: %v", err)),
				},
				IsError: true,
			}, nil
		}

		return &mcp.CallToolResult{
			Content: []mcp.Content{
				mcp.NewTextContent("Storage cleared successfully"),
			},
			IsError: false,
		}, nil
	})

	// Drag and drop tools
	mcpServer.AddTool(mcp.Tool{
		Name:        "web_drag_and_drop_cremotemcp",
		Description: "Perform drag and drop operation from source element to target element",
		InputSchema: mcp.ToolInputSchema{
			Type: "object",
			Properties: map[string]any{
				"source": map[string]any{
					"type":        "string",
					"description": "CSS selector for the source element to drag",
				},
				"target": map[string]any{
					"type":        "string",
					"description": "CSS selector for the target element to drop on",
				},
				"tab": map[string]any{
					"type":        "string",
					"description": "Tab ID (optional, uses current tab)",
				},
				"timeout": map[string]any{
					"type":        "integer",
					"description": "Timeout in seconds (default: 5)",
					"default":     5,
				},
			},
			Required: []string{"source", "target"},
		},
	}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
		// Convert arguments to map
		params, ok := request.Params.Arguments.(map[string]any)
		if !ok {
			return nil, fmt.Errorf("invalid arguments format")
		}

		source := getStringParam(params, "source", "")
		target := getStringParam(params, "target", "")
		tab := getStringParam(params, "tab", "")
		timeout := getIntParam(params, "timeout", 5)

		if source == "" {
			return &mcp.CallToolResult{
				Content: []mcp.Content{
					mcp.NewTextContent("Error: source parameter is required"),
				},
				IsError: true,
			}, nil
		}

		if target == "" {
			return &mcp.CallToolResult{
				Content: []mcp.Content{
					mcp.NewTextContent("Error: target parameter is required"),
				},
				IsError: true,
			}, nil
		}

		err := cremoteServer.client.DragAndDrop(tab, source, target, timeout)
		if err != nil {
			return &mcp.CallToolResult{
				Content: []mcp.Content{
					mcp.NewTextContent(fmt.Sprintf("Error performing drag and drop: %v", err)),
				},
				IsError: true,
			}, nil
		}

		return &mcp.CallToolResult{
			Content: []mcp.Content{
				mcp.NewTextContent(fmt.Sprintf("Drag and drop completed successfully from %s to %s", source, target)),
			},
			IsError: false,
		}, nil
	})

	mcpServer.AddTool(mcp.Tool{
		Name:        "web_drag_and_drop_coordinates_cremotemcp",
		Description: "Perform drag and drop operation from source element to specific coordinates",
		InputSchema: mcp.ToolInputSchema{
			Type: "object",
			Properties: map[string]any{
				"source": map[string]any{
					"type":        "string",
					"description": "CSS selector for the source element to drag",
				},
				"x": map[string]any{
					"type":        "integer",
					"description": "Target X coordinate",
				},
				"y": map[string]any{
					"type":        "integer",
					"description": "Target Y coordinate",
				},
				"tab": map[string]any{
					"type":        "string",
					"description": "Tab ID (optional, uses current tab)",
				},
				"timeout": map[string]any{
					"type":        "integer",
					"description": "Timeout in seconds (default: 5)",
					"default":     5,
				},
			},
			Required: []string{"source", "x", "y"},
		},
	}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
		// Convert arguments to map
		params, ok := request.Params.Arguments.(map[string]any)
		if !ok {
			return nil, fmt.Errorf("invalid arguments format")
		}

		source := getStringParam(params, "source", "")
		x := getIntParam(params, "x", 0)
		y := getIntParam(params, "y", 0)
		tab := getStringParam(params, "tab", "")
		timeout := getIntParam(params, "timeout", 5)

		if source == "" {
			return &mcp.CallToolResult{
				Content: []mcp.Content{
					mcp.NewTextContent("Error: source parameter is required"),
				},
				IsError: true,
			}, nil
		}

		err := cremoteServer.client.DragAndDropToCoordinates(tab, source, x, y, timeout)
		if err != nil {
			return &mcp.CallToolResult{
				Content: []mcp.Content{
					mcp.NewTextContent(fmt.Sprintf("Error performing drag and drop to coordinates: %v", err)),
				},
				IsError: true,
			}, nil
		}

		return &mcp.CallToolResult{
			Content: []mcp.Content{
				mcp.NewTextContent(fmt.Sprintf("Drag and drop to coordinates (%d, %d) completed successfully from %s", x, y, source)),
			},
			IsError: false,
		}, nil
	})

	mcpServer.AddTool(mcp.Tool{
		Name:        "web_drag_and_drop_offset_cremotemcp",
		Description: "Perform drag and drop operation from source element by relative offset",
		InputSchema: mcp.ToolInputSchema{
			Type: "object",
			Properties: map[string]any{
				"source": map[string]any{
					"type":        "string",
					"description": "CSS selector for the source element to drag",
				},
				"offset_x": map[string]any{
					"type":        "integer",
					"description": "Horizontal offset in pixels",
				},
				"offset_y": map[string]any{
					"type":        "integer",
					"description": "Vertical offset in pixels",
				},
				"tab": map[string]any{
					"type":        "string",
					"description": "Tab ID (optional, uses current tab)",
				},
				"timeout": map[string]any{
					"type":        "integer",
					"description": "Timeout in seconds (default: 5)",
					"default":     5,
				},
			},
			Required: []string{"source", "offset_x", "offset_y"},
		},
	}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
		// Convert arguments to map
		params, ok := request.Params.Arguments.(map[string]any)
		if !ok {
			return nil, fmt.Errorf("invalid arguments format")
		}

		source := getStringParam(params, "source", "")
		offsetX := getIntParam(params, "offset_x", 0)
		offsetY := getIntParam(params, "offset_y", 0)
		tab := getStringParam(params, "tab", "")
		timeout := getIntParam(params, "timeout", 5)

		if source == "" {
			return &mcp.CallToolResult{
				Content: []mcp.Content{
					mcp.NewTextContent("Error: source parameter is required"),
				},
				IsError: true,
			}, nil
		}

		err := cremoteServer.client.DragAndDropByOffset(tab, source, offsetX, offsetY, timeout)
		if err != nil {
			return &mcp.CallToolResult{
				Content: []mcp.Content{
					mcp.NewTextContent(fmt.Sprintf("Error performing drag and drop by offset: %v", err)),
				},
				IsError: true,
			}, nil
		}

		return &mcp.CallToolResult{
			Content: []mcp.Content{
				mcp.NewTextContent(fmt.Sprintf("Drag and drop by offset (%d, %d) completed successfully from %s", offsetX, offsetY, source)),
			},
			IsError: false,
		}, nil
	})

	// Register web_right_click tool
	mcpServer.AddTool(mcp.Tool{
		Name:        "web_right_click_cremotemcp",
		Description: "Right-click on an element",
		InputSchema: mcp.ToolInputSchema{
			Type: "object",
			Properties: map[string]any{
				"selector": map[string]any{
					"type":        "string",
					"description": "CSS selector for the element to right-click",
				},
				"tab": map[string]any{
					"type":        "string",
					"description": "Tab ID (optional, uses current tab)",
				},
				"timeout": map[string]any{
					"type":        "integer",
					"description": "Timeout in seconds (default: 5)",
					"default":     5,
				},
			},
			Required: []string{"selector"},
		},
	}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
		params, ok := request.Params.Arguments.(map[string]any)
		if !ok {
			return nil, fmt.Errorf("invalid arguments format")
		}

		selector, ok := params["selector"].(string)
		if !ok || selector == "" {
			return nil, fmt.Errorf("selector is required")
		}

		tab := ""
		if tabParam, exists := params["tab"]; exists {
			if tabStr, ok := tabParam.(string); ok {
				tab = tabStr
			}
		}

		timeout := 5
		if timeoutParam, exists := params["timeout"]; exists {
			if timeoutFloat, ok := timeoutParam.(float64); ok {
				timeout = int(timeoutFloat)
			}
		}

		err := cremoteServer.client.RightClick(tab, selector, timeout)
		if err != nil {
			return &mcp.CallToolResult{
				Content: []mcp.Content{
					mcp.NewTextContent(fmt.Sprintf("Failed to right-click: %v", err)),
				},
				IsError: true,
			}, nil
		}

		return &mcp.CallToolResult{
			Content: []mcp.Content{
				mcp.NewTextContent("Right-click completed successfully"),
			},
			IsError: false,
		}, nil
	})

	// Register web_double_click tool
	mcpServer.AddTool(mcp.Tool{
		Name:        "web_double_click_cremotemcp",
		Description: "Double-click on an element",
		InputSchema: mcp.ToolInputSchema{
			Type: "object",
			Properties: map[string]any{
				"selector": map[string]any{
					"type":        "string",
					"description": "CSS selector for the element to double-click",
				},
				"tab": map[string]any{
					"type":        "string",
					"description": "Tab ID (optional, uses current tab)",
				},
				"timeout": map[string]any{
					"type":        "integer",
					"description": "Timeout in seconds (default: 5)",
					"default":     5,
				},
			},
			Required: []string{"selector"},
		},
	}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
		params, ok := request.Params.Arguments.(map[string]any)
		if !ok {
			return nil, fmt.Errorf("invalid arguments format")
		}

		selector, ok := params["selector"].(string)
		if !ok || selector == "" {
			return nil, fmt.Errorf("selector is required")
		}

		tab := ""
		if tabParam, exists := params["tab"]; exists {
			if tabStr, ok := tabParam.(string); ok {
				tab = tabStr
			}
		}

		timeout := 5
		if timeoutParam, exists := params["timeout"]; exists {
			if timeoutFloat, ok := timeoutParam.(float64); ok {
				timeout = int(timeoutFloat)
			}
		}

		err := cremoteServer.client.DoubleClick(tab, selector, timeout)
		if err != nil {
			return &mcp.CallToolResult{
				Content: []mcp.Content{
					mcp.NewTextContent(fmt.Sprintf("Failed to double-click: %v", err)),
				},
				IsError: true,
			}, nil
		}

		return &mcp.CallToolResult{
			Content: []mcp.Content{
				mcp.NewTextContent("Double-click completed successfully"),
			},
			IsError: false,
		}, nil
	})

	// Register web_hover tool
	mcpServer.AddTool(mcp.Tool{
		Name:        "web_hover_cremotemcp",
		Description: "Hover over an element",
		InputSchema: mcp.ToolInputSchema{
			Type: "object",
			Properties: map[string]any{
				"selector": map[string]any{
					"type":        "string",
					"description": "CSS selector for the element to hover over",
				},
				"tab": map[string]any{
					"type":        "string",
					"description": "Tab ID (optional, uses current tab)",
				},
				"timeout": map[string]any{
					"type":        "integer",
					"description": "Timeout in seconds (default: 5)",
					"default":     5,
				},
			},
			Required: []string{"selector"},
		},
	}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
		params, ok := request.Params.Arguments.(map[string]any)
		if !ok {
			return nil, fmt.Errorf("invalid arguments format")
		}

		selector, ok := params["selector"].(string)
		if !ok || selector == "" {
			return nil, fmt.Errorf("selector is required")
		}

		tab := ""
		if tabParam, exists := params["tab"]; exists {
			if tabStr, ok := tabParam.(string); ok {
				tab = tabStr
			}
		}

		timeout := 5
		if timeoutParam, exists := params["timeout"]; exists {
			if timeoutFloat, ok := timeoutParam.(float64); ok {
				timeout = int(timeoutFloat)
			}
		}

		err := cremoteServer.client.Hover(tab, selector, timeout)
		if err != nil {
			return &mcp.CallToolResult{
				Content: []mcp.Content{
					mcp.NewTextContent(fmt.Sprintf("Failed to hover: %v", err)),
				},
				IsError: true,
			}, nil
		}

		return &mcp.CallToolResult{
			Content: []mcp.Content{
				mcp.NewTextContent("Hover completed successfully"),
			},
			IsError: false,
		}, nil
	})

	// Register web_middle_click tool
	mcpServer.AddTool(mcp.Tool{
		Name:        "web_middle_click_cremotemcp",
		Description: "Middle-click on an element (typically opens links in new tabs)",
		InputSchema: mcp.ToolInputSchema{
			Type: "object",
			Properties: map[string]any{
				"selector": map[string]any{
					"type":        "string",
					"description": "CSS selector for the element to middle-click",
				},
				"tab": map[string]any{
					"type":        "string",
					"description": "Tab ID (optional, uses current tab)",
				},
				"timeout": map[string]any{
					"type":        "integer",
					"description": "Timeout in seconds (default: 5)",
					"default":     5,
				},
			},
			Required: []string{"selector"},
		},
	}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
		params, ok := request.Params.Arguments.(map[string]any)
		if !ok {
			return nil, fmt.Errorf("invalid arguments format")
		}

		selector, ok := params["selector"].(string)
		if !ok || selector == "" {
			return nil, fmt.Errorf("selector is required")
		}

		tab := ""
		if tabParam, exists := params["tab"]; exists {
			if tabStr, ok := tabParam.(string); ok {
				tab = tabStr
			}
		}

		timeout := 5
		if timeoutParam, exists := params["timeout"]; exists {
			if timeoutFloat, ok := timeoutParam.(float64); ok {
				timeout = int(timeoutFloat)
			}
		}

		err := cremoteServer.client.MiddleClick(tab, selector, timeout)
		if err != nil {
			return &mcp.CallToolResult{
				Content: []mcp.Content{
					mcp.NewTextContent(fmt.Sprintf("Failed to middle-click: %v", err)),
				},
				IsError: true,
			}, nil
		}

		return &mcp.CallToolResult{
			Content: []mcp.Content{
				mcp.NewTextContent("Middle-click completed successfully"),
			},
			IsError: false,
		}, nil
	})

	// Register web_mouse_move tool
	mcpServer.AddTool(mcp.Tool{
		Name:        "web_mouse_move_cremotemcp",
		Description: "Move mouse to specific coordinates without clicking",
		InputSchema: mcp.ToolInputSchema{
			Type: "object",
			Properties: map[string]any{
				"x": map[string]any{
					"type":        "integer",
					"description": "X coordinate to move mouse to",
				},
				"y": map[string]any{
					"type":        "integer",
					"description": "Y coordinate to move mouse to",
				},
				"tab": map[string]any{
					"type":        "string",
					"description": "Tab ID (optional, uses current tab)",
				},
				"timeout": map[string]any{
					"type":        "integer",
					"description": "Timeout in seconds (default: 5)",
					"default":     5,
				},
			},
			Required: []string{"x", "y"},
		},
	}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
		params, ok := request.Params.Arguments.(map[string]any)
		if !ok {
			return nil, fmt.Errorf("invalid arguments format")
		}

		xFloat, ok := params["x"].(float64)
		if !ok {
			return nil, fmt.Errorf("x coordinate is required")
		}
		x := int(xFloat)

		yFloat, ok := params["y"].(float64)
		if !ok {
			return nil, fmt.Errorf("y coordinate is required")
		}
		y := int(yFloat)

		tab := ""
		if tabParam, exists := params["tab"]; exists {
			if tabStr, ok := tabParam.(string); ok {
				tab = tabStr
			}
		}

		timeout := 5
		if timeoutParam, exists := params["timeout"]; exists {
			if timeoutFloat, ok := timeoutParam.(float64); ok {
				timeout = int(timeoutFloat)
			}
		}

		err := cremoteServer.client.MouseMove(tab, x, y, timeout)
		if err != nil {
			return &mcp.CallToolResult{
				Content: []mcp.Content{
					mcp.NewTextContent(fmt.Sprintf("Failed to move mouse: %v", err)),
				},
				IsError: true,
			}, nil
		}

		return &mcp.CallToolResult{
			Content: []mcp.Content{
				mcp.NewTextContent(fmt.Sprintf("Mouse moved to coordinates (%d, %d) successfully", x, y)),
			},
			IsError: false,
		}, nil
	})

	// Register web_scroll_wheel tool
	mcpServer.AddTool(mcp.Tool{
		Name:        "web_scroll_wheel_cremotemcp",
		Description: "Scroll with mouse wheel at specific coordinates",
		InputSchema: mcp.ToolInputSchema{
			Type: "object",
			Properties: map[string]any{
				"x": map[string]any{
					"type":        "integer",
					"description": "X coordinate for scroll wheel",
				},
				"y": map[string]any{
					"type":        "integer",
					"description": "Y coordinate for scroll wheel",
				},
				"delta_x": map[string]any{
					"type":        "integer",
					"description": "Horizontal scroll delta (negative = left, positive = right)",
					"default":     0,
				},
				"delta_y": map[string]any{
					"type":        "integer",
					"description": "Vertical scroll delta (negative = up, positive = down)",
				},
				"tab": map[string]any{
					"type":        "string",
					"description": "Tab ID (optional, uses current tab)",
				},
				"timeout": map[string]any{
					"type":        "integer",
					"description": "Timeout in seconds (default: 5)",
					"default":     5,
				},
			},
			Required: []string{"x", "y", "delta_y"},
		},
	}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
		params, ok := request.Params.Arguments.(map[string]any)
		if !ok {
			return nil, fmt.Errorf("invalid arguments format")
		}

		xFloat, ok := params["x"].(float64)
		if !ok {
			return nil, fmt.Errorf("x coordinate is required")
		}
		x := int(xFloat)

		yFloat, ok := params["y"].(float64)
		if !ok {
			return nil, fmt.Errorf("y coordinate is required")
		}
		y := int(yFloat)

		deltaXFloat := float64(0)
		if deltaXParam, exists := params["delta_x"]; exists {
			if deltaXVal, ok := deltaXParam.(float64); ok {
				deltaXFloat = deltaXVal
			}
		}
		deltaX := int(deltaXFloat)

		deltaYFloat, ok := params["delta_y"].(float64)
		if !ok {
			return nil, fmt.Errorf("delta_y is required")
		}
		deltaY := int(deltaYFloat)

		tab := ""
		if tabParam, exists := params["tab"]; exists {
			if tabStr, ok := tabParam.(string); ok {
				tab = tabStr
			}
		}

		timeout := 5
		if timeoutParam, exists := params["timeout"]; exists {
			if timeoutFloat, ok := timeoutParam.(float64); ok {
				timeout = int(timeoutFloat)
			}
		}

		err := cremoteServer.client.ScrollWheel(tab, x, y, deltaX, deltaY, timeout)
		if err != nil {
			return &mcp.CallToolResult{
				Content: []mcp.Content{
					mcp.NewTextContent(fmt.Sprintf("Failed to scroll with mouse wheel: %v", err)),
				},
				IsError: true,
			}, nil
		}

		return &mcp.CallToolResult{
			Content: []mcp.Content{
				mcp.NewTextContent(fmt.Sprintf("Mouse wheel scroll at (%d, %d) with delta (%d, %d) completed successfully", x, y, deltaX, deltaY)),
			},
			IsError: false,
		}, nil
	})

	// Register web_key_combination tool
	mcpServer.AddTool(mcp.Tool{
		Name:        "web_key_combination_cremotemcp",
		Description: "Send key combinations like Ctrl+C, Alt+Tab, Shift+Enter, etc.",
		InputSchema: mcp.ToolInputSchema{
			Type: "object",
			Properties: map[string]any{
				"keys": map[string]any{
					"type":        "string",
					"description": "Key combination to send (e.g., 'Ctrl+C', 'Alt+Tab', 'Shift+Enter', 'Ctrl+Shift+T')",
				},
				"tab": map[string]any{
					"type":        "string",
					"description": "Tab ID (optional, uses current tab)",
				},
				"timeout": map[string]any{
					"type":        "integer",
					"description": "Timeout in seconds (default: 5)",
					"default":     5,
				},
			},
			Required: []string{"keys"},
		},
	}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
		params, ok := request.Params.Arguments.(map[string]any)
		if !ok {
			return nil, fmt.Errorf("invalid arguments format")
		}

		keys, ok := params["keys"].(string)
		if !ok || keys == "" {
			return nil, fmt.Errorf("keys parameter is required")
		}

		tab := ""
		if tabParam, exists := params["tab"]; exists {
			if tabStr, ok := tabParam.(string); ok {
				tab = tabStr
			}
		}

		timeout := 5
		if timeoutParam, exists := params["timeout"]; exists {
			if timeoutFloat, ok := timeoutParam.(float64); ok {
				timeout = int(timeoutFloat)
			}
		}

		err := cremoteServer.client.KeyCombination(tab, keys, timeout)
		if err != nil {
			return &mcp.CallToolResult{
				Content: []mcp.Content{
					mcp.NewTextContent(fmt.Sprintf("Failed to send key combination: %v", err)),
				},
				IsError: true,
			}, nil
		}

		return &mcp.CallToolResult{
			Content: []mcp.Content{
				mcp.NewTextContent(fmt.Sprintf("Key combination '%s' sent successfully", keys)),
			},
			IsError: false,
		}, nil
	})

	// Register web_special_key tool
	mcpServer.AddTool(mcp.Tool{
		Name:        "web_special_key_cremotemcp",
		Description: "Send special keys like Enter, Escape, Tab, F1-F12, Arrow keys, etc.",
		InputSchema: mcp.ToolInputSchema{
			Type: "object",
			Properties: map[string]any{
				"key": map[string]any{
					"type":        "string",
					"description": "Special key to send (e.g., 'Enter', 'Escape', 'Tab', 'F1', 'ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'Home', 'End', 'PageUp', 'PageDown', 'Delete', 'Backspace')",
				},
				"tab": map[string]any{
					"type":        "string",
					"description": "Tab ID (optional, uses current tab)",
				},
				"timeout": map[string]any{
					"type":        "integer",
					"description": "Timeout in seconds (default: 5)",
					"default":     5,
				},
			},
			Required: []string{"key"},
		},
	}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
		params, ok := request.Params.Arguments.(map[string]any)
		if !ok {
			return nil, fmt.Errorf("invalid arguments format")
		}

		key, ok := params["key"].(string)
		if !ok || key == "" {
			return nil, fmt.Errorf("key parameter is required")
		}

		tab := ""
		if tabParam, exists := params["tab"]; exists {
			if tabStr, ok := tabParam.(string); ok {
				tab = tabStr
			}
		}

		timeout := 5
		if timeoutParam, exists := params["timeout"]; exists {
			if timeoutFloat, ok := timeoutParam.(float64); ok {
				timeout = int(timeoutFloat)
			}
		}

		err := cremoteServer.client.SpecialKey(tab, key, timeout)
		if err != nil {
			return &mcp.CallToolResult{
				Content: []mcp.Content{
					mcp.NewTextContent(fmt.Sprintf("Failed to send special key: %v", err)),
				},
				IsError: true,
			}, nil
		}

		return &mcp.CallToolResult{
			Content: []mcp.Content{
				mcp.NewTextContent(fmt.Sprintf("Special key '%s' sent successfully", key)),
			},
			IsError: false,
		}, nil
	})

	// Register web_modifier_click tool
	mcpServer.AddTool(mcp.Tool{
		Name:        "web_modifier_click_cremotemcp",
		Description: "Click on an element with modifier keys (Ctrl+click, Shift+click, Alt+click, etc.)",
		InputSchema: mcp.ToolInputSchema{
			Type: "object",
			Properties: map[string]any{
				"selector": map[string]any{
					"type":        "string",
					"description": "CSS selector for the element to click",
				},
				"modifiers": map[string]any{
					"type":        "string",
					"description": "Modifier keys to hold while clicking (e.g., 'Ctrl', 'Shift', 'Alt', 'Ctrl+Shift', 'Ctrl+Alt')",
				},
				"tab": map[string]any{
					"type":        "string",
					"description": "Tab ID (optional, uses current tab)",
				},
				"timeout": map[string]any{
					"type":        "integer",
					"description": "Timeout in seconds (default: 5)",
					"default":     5,
				},
			},
			Required: []string{"selector", "modifiers"},
		},
	}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
		params, ok := request.Params.Arguments.(map[string]any)
		if !ok {
			return nil, fmt.Errorf("invalid arguments format")
		}

		selector, ok := params["selector"].(string)
		if !ok || selector == "" {
			return nil, fmt.Errorf("selector is required")
		}

		modifiers, ok := params["modifiers"].(string)
		if !ok || modifiers == "" {
			return nil, fmt.Errorf("modifiers parameter is required")
		}

		tab := ""
		if tabParam, exists := params["tab"]; exists {
			if tabStr, ok := tabParam.(string); ok {
				tab = tabStr
			}
		}

		timeout := 5
		if timeoutParam, exists := params["timeout"]; exists {
			if timeoutFloat, ok := timeoutParam.(float64); ok {
				timeout = int(timeoutFloat)
			}
		}

		err := cremoteServer.client.ModifierClick(tab, selector, modifiers, timeout)
		if err != nil {
			return &mcp.CallToolResult{
				Content: []mcp.Content{
					mcp.NewTextContent(fmt.Sprintf("Failed to perform modifier click: %v", err)),
				},
				IsError: true,
			}, nil
		}

		return &mcp.CallToolResult{
			Content: []mcp.Content{
				mcp.NewTextContent(fmt.Sprintf("Modifier click with '%s' on %s completed successfully", modifiers, selector)),
			},
			IsError: false,
		}, nil
	})

	// Register web_inject_axe tool
	mcpServer.AddTool(mcp.Tool{
		Name:        "web_inject_axe_cremotemcp",
		Description: "Inject axe-core accessibility testing library into the page for comprehensive WCAG 2.1 AA/AAA testing",
		InputSchema: mcp.ToolInputSchema{
			Type: "object",
			Properties: map[string]any{
				"tab": map[string]any{
					"type":        "string",
					"description": "Tab ID (optional, uses current tab)",
				},
				"version": map[string]any{
					"type":        "string",
					"description": "Axe-core version (optional, defaults to 4.8.0)",
					"default":     "4.8.0",
				},
				"timeout": map[string]any{
					"type":        "integer",
					"description": "Timeout in seconds (default: 10)",
					"default":     10,
				},
			},
			Required: []string{},
		},
	}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
		params, ok := request.Params.Arguments.(map[string]any)
		if !ok {
			return nil, fmt.Errorf("invalid arguments format")
		}

		tab := getStringParam(params, "tab", cremoteServer.currentTab)
		version := getStringParam(params, "version", "4.8.0")
		timeout := getIntParam(params, "timeout", 10)

		err := cremoteServer.client.InjectAxeCore(tab, version, timeout)
		if err != nil {
			return &mcp.CallToolResult{
				Content: []mcp.Content{
					mcp.NewTextContent(fmt.Sprintf("Failed to inject axe-core: %v", err)),
				},
				IsError: true,
			}, nil
		}

		return &mcp.CallToolResult{
			Content: []mcp.Content{
				mcp.NewTextContent(fmt.Sprintf("Successfully injected axe-core v%s", version)),
			},
			IsError: false,
		}, nil
	})

	// Register web_run_axe tool
	mcpServer.AddTool(mcp.Tool{
		Name:        "web_run_axe_cremotemcp",
		Description: "Run axe-core accessibility tests and return violations, passes, incomplete checks, and inapplicable rules",
		InputSchema: mcp.ToolInputSchema{
			Type: "object",
			Properties: map[string]any{
				"tab": map[string]any{
					"type":        "string",
					"description": "Tab ID (optional, uses current tab)",
				},
				"run_only": map[string]any{
					"type":        "array",
					"description": "Array of tags to run (e.g., ['wcag2a', 'wcag2aa', 'wcag21aa'])",
					"items": map[string]any{
						"type": "string",
					},
				},
				"rules": map[string]any{
					"type":        "object",
					"description": "Specific rules configuration (optional)",
				},
				"timeout": map[string]any{
					"type":        "integer",
					"description": "Timeout in seconds (default: 30)",
					"default":     30,
				},
			},
			Required: []string{},
		},
	}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
		params, ok := request.Params.Arguments.(map[string]any)
		if !ok {
			return nil, fmt.Errorf("invalid arguments format")
		}

		tab := getStringParam(params, "tab", cremoteServer.currentTab)
		timeout := getIntParam(params, "timeout", 30)

		// Build options
		options := make(map[string]interface{})
		if runOnly, ok := params["run_only"].([]interface{}); ok && len(runOnly) > 0 {
			tags := make([]string, 0, len(runOnly))
			for _, tag := range runOnly {
				if tagStr, ok := tag.(string); ok {
					tags = append(tags, tagStr)
				}
			}
			if len(tags) > 0 {
				options["runOnly"] = map[string]interface{}{
					"type":   "tag",
					"values": tags,
				}
			}
		}

		if rules, ok := params["rules"].(map[string]interface{}); ok && len(rules) > 0 {
			options["rules"] = rules
		}

		result, err := cremoteServer.client.RunAxeCore(tab, options, timeout)
		if err != nil {
			return &mcp.CallToolResult{
				Content: []mcp.Content{
					mcp.NewTextContent(fmt.Sprintf("Failed to run axe-core: %v", err)),
				},
				IsError: true,
			}, nil
		}

		// Format results as JSON
		resultJSON, err := json.MarshalIndent(result, "", "  ")
		if err != nil {
			return nil, fmt.Errorf("failed to marshal results: %w", err)
		}

		// Create summary
		summary := fmt.Sprintf("Axe-core Accessibility Test Results:\n\n"+
			"URL: %s\n"+
			"Timestamp: %s\n"+
			"Test Engine: %s v%s\n\n"+
			"Summary:\n"+
			"  Violations: %d\n"+
			"  Passes: %d\n"+
			"  Incomplete: %d (require manual review)\n"+
			"  Inapplicable: %d\n\n"+
			"Full Results:\n%s",
			result.URL,
			result.Timestamp,
			result.TestEngine.Name,
			result.TestEngine.Version,
			len(result.Violations),
			len(result.Passes),
			len(result.Incomplete),
			len(result.Inapplicable),
			string(resultJSON))

		return &mcp.CallToolResult{
			Content: []mcp.Content{
				mcp.NewTextContent(summary),
			},
			IsError: false,
		}, nil
	})

	// Register web_contrast_check tool
	mcpServer.AddTool(mcp.Tool{
		Name:        "web_contrast_check_cremotemcp",
		Description: "Check color contrast ratios for text elements and verify WCAG AA/AAA compliance",
		InputSchema: mcp.ToolInputSchema{
			Type: "object",
			Properties: map[string]any{
				"tab": map[string]any{
					"type":        "string",
					"description": "Tab ID (optional, uses current tab)",
				},
				"selector": map[string]any{
					"type":        "string",
					"description": "CSS selector for specific elements (optional, defaults to all text elements)",
				},
				"timeout": map[string]any{
					"type":        "integer",
					"description": "Timeout in seconds (default: 10)",
					"default":     10,
				},
			},
			Required: []string{},
		},
	}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
		params, ok := request.Params.Arguments.(map[string]any)
		if !ok {
			return nil, fmt.Errorf("invalid arguments format")
		}

		tab := getStringParam(params, "tab", cremoteServer.currentTab)
		selector := getStringParam(params, "selector", "")
		timeout := getIntParam(params, "timeout", 10)

		result, err := cremoteServer.client.CheckContrast(tab, selector, timeout)
		if err != nil {
			return &mcp.CallToolResult{
				Content: []mcp.Content{
					mcp.NewTextContent(fmt.Sprintf("Failed to check contrast: %v", err)),
				},
				IsError: true,
			}, nil
		}

		// Format results as JSON
		resultJSON, err := json.MarshalIndent(result, "", "  ")
		if err != nil {
			return nil, fmt.Errorf("failed to marshal results: %w", err)
		}

		// Create summary with violations
		summary := fmt.Sprintf("Color Contrast Check Results:\n\n"+
			"Summary:\n"+
			"  Total Elements Checked: %d\n"+
			"  WCAG AA Compliance:\n"+
			"    Passed: %d\n"+
			"    Failed: %d\n"+
			"  WCAG AAA Compliance:\n"+
			"    Passed: %d\n"+
			"    Failed: %d\n"+
			"  Unable to Check: %d\n\n",
			result.TotalElements,
			result.PassedAA,
			result.FailedAA,
			result.PassedAAA,
			result.FailedAAA,
			result.UnableToCheck)

		// Add violations if any
		if result.FailedAA > 0 {
			summary += "WCAG AA Violations:\n"
			for _, elem := range result.Elements {
				if !elem.PassesAA && elem.Error == "" {
					summary += fmt.Sprintf("  - %s: %.2f:1 (required: %.1f:1)\n"+
						"    Text: %s\n"+
						"    Colors: %s on %s\n",
						elem.Selector,
						elem.ContrastRatio,
						elem.RequiredAA,
						elem.Text,
						elem.ForegroundColor,
						elem.BackgroundColor)
				}
			}
			summary += "\n"
		}

		summary += fmt.Sprintf("Full Results:\n%s", string(resultJSON))

		return &mcp.CallToolResult{
			Content: []mcp.Content{
				mcp.NewTextContent(summary),
			},
			IsError: false,
		}, nil
	})

	// Register web_keyboard_test tool
	mcpServer.AddTool(mcp.Tool{
		Name:        "web_keyboard_test_cremotemcp",
		Description: "Test keyboard navigation and accessibility including tab order, focus indicators, and keyboard traps",
		InputSchema: mcp.ToolInputSchema{
			Type: "object",
			Properties: map[string]any{
				"tab": map[string]any{
					"type":        "string",
					"description": "Tab ID (optional, uses current tab)",
				},
				"timeout": map[string]any{
					"type":        "integer",
					"description": "Timeout in seconds (default: 15)",
					"default":     15,
				},
			},
			Required: []string{},
		},
	}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
		params, ok := request.Params.Arguments.(map[string]any)
		if !ok {
			return nil, fmt.Errorf("invalid arguments format")
		}

		tab := getStringParam(params, "tab", cremoteServer.currentTab)
		timeout := getIntParam(params, "timeout", 15)

		result, err := cremoteServer.client.TestKeyboardNavigation(tab, timeout)
		if err != nil {
			return &mcp.CallToolResult{
				Content: []mcp.Content{
					mcp.NewTextContent(fmt.Sprintf("Failed to test keyboard navigation: %v", err)),
				},
				IsError: true,
			}, nil
		}

		// Format results as JSON
		resultJSON, err := json.MarshalIndent(result, "", "  ")
		if err != nil {
			return nil, fmt.Errorf("failed to marshal results: %w", err)
		}

		// Create summary with issues
		summary := fmt.Sprintf("Keyboard Navigation Test Results:\n\n"+
			"Summary:\n"+
			"  Total Interactive Elements: %d\n"+
			"  Keyboard Focusable: %d\n"+
			"  Not Focusable: %d\n"+
			"  Missing Focus Indicator: %d\n"+
			"  Keyboard Traps Detected: %d\n"+
			"  Total Issues: %d\n\n",
			result.TotalInteractive,
			result.Focusable,
			result.NotFocusable,
			result.NoFocusIndicator,
			result.KeyboardTraps,
			len(result.Issues))

		// Add high severity issues
		highSeverityIssues := 0
		for _, issue := range result.Issues {
			if issue.Severity == "high" {
				highSeverityIssues++
			}
		}

		if highSeverityIssues > 0 {
			summary += fmt.Sprintf("High Severity Issues (%d):\n", highSeverityIssues)
			count := 0
			for _, issue := range result.Issues {
				if issue.Severity == "high" && count < 10 {
					summary += fmt.Sprintf("  - %s: %s\n    Element: %s\n",
						issue.Type,
						issue.Description,
						issue.Element)
					count++
				}
			}
			if highSeverityIssues > 10 {
				summary += fmt.Sprintf("  ... and %d more issues\n", highSeverityIssues-10)
			}
			summary += "\n"
		}

		// Add tab order summary
		if len(result.TabOrder) > 0 {
			summary += fmt.Sprintf("Tab Order (first 5 elements):\n")
			for i, elem := range result.TabOrder {
				if i >= 5 {
					summary += fmt.Sprintf("  ... and %d more elements\n", len(result.TabOrder)-5)
					break
				}
				focusIndicator := "✓"
				if !elem.HasFocusStyle {
					focusIndicator = "✗"
				}
				summary += fmt.Sprintf("  %d. %s [%s] %s - Focus: %s\n",
					elem.Index+1,
					elem.Selector,
					elem.TagName,
					elem.Text,
					focusIndicator)
			}
			summary += "\n"
		}

		summary += fmt.Sprintf("Full Results:\n%s", string(resultJSON))

		return &mcp.CallToolResult{
			Content: []mcp.Content{
				mcp.NewTextContent(summary),
			},
			IsError: false,
		}, nil
	})

	// Register web_zoom_test tool
	mcpServer.AddTool(mcp.Tool{
		Name:        "web_zoom_test_cremotemcp",
		Description: "Test page at different zoom levels (100%, 200%, 400%) and verify WCAG 1.4.4 and 1.4.10 compliance",
		InputSchema: mcp.ToolInputSchema{
			Type: "object",
			Properties: map[string]any{
				"tab": map[string]any{
					"type":        "string",
					"description": "Tab ID (optional, uses current tab)",
				},
				"zoom_levels": map[string]any{
					"type":        "array",
					"description": "Array of zoom levels to test (optional, defaults to [1.0, 2.0, 4.0])",
					"items": map[string]any{
						"type": "number",
					},
				},
				"timeout": map[string]any{
					"type":        "integer",
					"description": "Timeout in seconds per zoom level (default: 10)",
					"default":     10,
				},
			},
			Required: []string{},
		},
	}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
		params, ok := request.Params.Arguments.(map[string]any)
		if !ok {
			return nil, fmt.Errorf("invalid arguments format")
		}

		tab := getStringParam(params, "tab", cremoteServer.currentTab)
		timeout := getIntParam(params, "timeout", 10)

		// Parse zoom levels if provided
		var zoomLevels []float64
		if zoomLevelsParam, ok := params["zoom_levels"].([]interface{}); ok {
			for _, level := range zoomLevelsParam {
				if levelFloat, ok := level.(float64); ok {
					zoomLevels = append(zoomLevels, levelFloat)
				}
			}
		}

		result, err := cremoteServer.client.TestZoom(tab, zoomLevels, timeout)
		if err != nil {
			return &mcp.CallToolResult{
				Content: []mcp.Content{
					mcp.NewTextContent(fmt.Sprintf("Failed to test zoom: %v", err)),
				},
				IsError: true,
			}, nil
		}

		// Format results as JSON
		resultJSON, err := json.MarshalIndent(result, "", "  ")
		if err != nil {
			return nil, fmt.Errorf("failed to marshal results: %w", err)
		}

		// Create summary
		summary := fmt.Sprintf("Zoom Level Test Results:\n\n"+
			"Tested %d zoom levels\n"+
			"Total Issues: %d\n\n",
			len(result.ZoomLevels),
			len(result.Issues))

		// Add zoom level details
		for _, zoomTest := range result.ZoomLevels {
			status := "✓ PASS"
			if zoomTest.HasHorizontalScroll || zoomTest.OverflowingElements > 0 || !zoomTest.TextReadable {
				status = "✗ FAIL"
			}

			summary += fmt.Sprintf("Zoom %.0f%% %s:\n"+
				"  Viewport: %dx%d\n"+
				"  Content: %dx%d\n"+
				"  Horizontal Scroll: %v\n"+
				"  Overflowing Elements: %d\n"+
				"  Text Readable: %v\n\n",
				zoomTest.ZoomLevel*100,
				status,
				zoomTest.ViewportWidth,
				zoomTest.ViewportHeight,
				zoomTest.ContentWidth,
				zoomTest.ContentHeight,
				zoomTest.HasHorizontalScroll,
				zoomTest.OverflowingElements,
				zoomTest.TextReadable)
		}

		// Add issues
		if len(result.Issues) > 0 {
			summary += "Issues Found:\n"
			for _, issue := range result.Issues {
				summary += fmt.Sprintf("  [%.0f%%] %s (%s): %s\n",
					issue.ZoomLevel*100,
					issue.Type,
					issue.Severity,
					issue.Description)
			}
			summary += "\n"
		}

		summary += fmt.Sprintf("Full Results:\n%s", string(resultJSON))

		return &mcp.CallToolResult{
			Content: []mcp.Content{
				mcp.NewTextContent(summary),
			},
			IsError: false,
		}, nil
	})

	// Register web_reflow_test tool
	mcpServer.AddTool(mcp.Tool{
		Name:        "web_reflow_test_cremotemcp",
		Description: "Test responsive design at WCAG breakpoints (320px, 1280px) and verify WCAG 1.4.10 reflow compliance",
		InputSchema: mcp.ToolInputSchema{
			Type: "object",
			Properties: map[string]any{
				"tab": map[string]any{
					"type":        "string",
					"description": "Tab ID (optional, uses current tab)",
				},
				"widths": map[string]any{
					"type":        "array",
					"description": "Array of viewport widths to test in pixels (optional, defaults to [320, 1280])",
					"items": map[string]any{
						"type": "integer",
					},
				},
				"timeout": map[string]any{
					"type":        "integer",
					"description": "Timeout in seconds per width (default: 10)",
					"default":     10,
				},
			},
			Required: []string{},
		},
	}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
		params, ok := request.Params.Arguments.(map[string]any)
		if !ok {
			return nil, fmt.Errorf("invalid arguments format")
		}

		tab := getStringParam(params, "tab", cremoteServer.currentTab)
		timeout := getIntParam(params, "timeout", 10)

		// Parse widths if provided
		var widths []int
		if widthsParam, ok := params["widths"].([]interface{}); ok {
			for _, width := range widthsParam {
				if widthFloat, ok := width.(float64); ok {
					widths = append(widths, int(widthFloat))
				}
			}
		}

		result, err := cremoteServer.client.TestReflow(tab, widths, timeout)
		if err != nil {
			return &mcp.CallToolResult{
				Content: []mcp.Content{
					mcp.NewTextContent(fmt.Sprintf("Failed to test reflow: %v", err)),
				},
				IsError: true,
			}, nil
		}

		// Format results as JSON
		resultJSON, err := json.MarshalIndent(result, "", "  ")
		if err != nil {
			return nil, fmt.Errorf("failed to marshal results: %w", err)
		}

		// Create summary
		summary := fmt.Sprintf("Reflow/Responsive Design Test Results:\n\n"+
			"Tested %d breakpoints\n"+
			"Total Issues: %d\n\n",
			len(result.Breakpoints),
			len(result.Issues))

		// Add breakpoint details
		for _, breakpoint := range result.Breakpoints {
			status := "✓ PASS"
			if breakpoint.HasHorizontalScroll || !breakpoint.ResponsiveLayout || breakpoint.OverflowingElements > 0 {
				status = "✗ FAIL"
			}

			summary += fmt.Sprintf("%dpx Width %s:\n"+
				"  Viewport: %dx%d\n"+
				"  Content: %dx%d\n"+
				"  Horizontal Scroll: %v\n"+
				"  Responsive Layout: %v\n"+
				"  Overflowing Elements: %d\n\n",
				breakpoint.Width,
				status,
				breakpoint.Width,
				breakpoint.Height,
				breakpoint.ContentWidth,
				breakpoint.ContentHeight,
				breakpoint.HasHorizontalScroll,
				breakpoint.ResponsiveLayout,
				breakpoint.OverflowingElements)
		}

		// Add issues
		if len(result.Issues) > 0 {
			summary += "Issues Found:\n"
			for _, issue := range result.Issues {
				summary += fmt.Sprintf("  [%dpx] %s (%s): %s\n",
					issue.Width,
					issue.Type,
					issue.Severity,
					issue.Description)
			}
			summary += "\n"
		}

		summary += fmt.Sprintf("Full Results:\n%s", string(resultJSON))

		return &mcp.CallToolResult{
			Content: []mcp.Content{
				mcp.NewTextContent(summary),
			},
			IsError: false,
		}, nil
	})

	// Start the server
	log.Printf("Cremote MCP server ready")
	if err := server.ServeStdio(mcpServer); err != nil {
		log.Fatalf("Server error: %v", err)
	}
}
