Skip to main content
Glama

Peekaboo MCP

by steipete
ScrollCommand.swiftβ€’5.78 kB
import ArgumentParser import CoreGraphics import Foundation import PeekabooCore import PeekabooFoundation /// Scrolls the mouse wheel in a specified direction. /// Supports scrolling on specific elements or at the current mouse position. @available(macOS 14.0, *) struct ScrollCommand: AsyncParsableCommand, ErrorHandlingCommand, OutputFormattable { static let configuration = CommandConfiguration( commandName: "scroll", abstract: "Scroll the mouse wheel in any direction", discussion: """ The 'scroll' command simulates mouse wheel scrolling events. It can scroll up, down, left, or right by a specified amount. EXAMPLES: peekaboo scroll --direction down --amount 5 peekaboo scroll --direction up --amount 10 --on element_42 peekaboo scroll --direction right --amount 3 --smooth DIRECTION: up - Scroll content up (wheel down) down - Scroll content down (wheel up) left - Scroll content left right - Scroll content right AMOUNT: The number of scroll "lines" or "ticks" to perform. Each tick is equivalent to one notch on a physical mouse wheel. """ ) @Option(help: "Scroll direction: up, down, left, or right") var direction: String @Option(help: "Number of scroll ticks") var amount: Int = 3 @Option(help: "Element ID to scroll on (from 'see' command)") var on: String? @Option(help: "Session ID (uses latest if not specified)") var session: String? @Option(help: "Delay between scroll ticks in milliseconds") var delay: Int = 2 @Flag(help: "Use smooth scrolling with smaller increments") var smooth = false @Flag(help: "Output in JSON format") var jsonOutput = false @Option(name: .long, help: "Target application to focus before scrolling") var app: String? @OptionGroup var focusOptions: FocusOptions mutating func run() async throws { let startTime = Date() Logger.shared.setJsonOutputMode(self.jsonOutput) do { // Parse direction guard let scrollDirection = ScrollDirection(rawValue: direction.lowercased()) else { throw ArgumentParser.ValidationError("Invalid direction. Use: up, down, left, or right") } // Determine session ID if element target is specified let sessionId: String? = if self.on != nil { if let providedSession = session { providedSession } else { await PeekabooServices.shared.sessions.getMostRecentSession() } } else { nil } // Ensure window is focused before scrolling try await self.ensureFocused( sessionId: sessionId, applicationName: self.app, options: self.focusOptions ) // Perform scroll using the service try await PeekabooServices.shared.automation.scroll( direction: scrollDirection, amount: self.amount, target: self.on, smooth: self.smooth, delay: self.delay, sessionId: sessionId ) // Calculate total ticks for output let totalTicks = self.smooth ? self.amount * 3 : self.amount // Determine scroll location for output let scrollLocation: CGPoint = if let elementId = on { // Try to get element location from session if let activeSessionId = sessionId, let detectionResult = try? await PeekabooServices.shared.sessions .getDetectionResult(sessionId: activeSessionId), let element = detectionResult.elements.findById(elementId) { CGPoint( x: element.bounds.midX, y: element.bounds.midY ) } else { // Fallback to zero if element not found (scroll still happened though) .zero } } else { // Get current mouse position CGEvent(source: nil)?.location ?? .zero } // Output results if self.jsonOutput { let output = ScrollResult( success: true, direction: direction, amount: amount, location: ["x": scrollLocation.x, "y": scrollLocation.y], totalTicks: totalTicks, executionTime: Date().timeIntervalSince(startTime) ) outputSuccessCodable(data: output) } else { print("βœ… Scroll completed") print("🎯 Direction: \(self.direction)") print("πŸ“Š Amount: \(self.amount) ticks") if self.on != nil { print("πŸ“ Location: (\(Int(scrollLocation.x)), \(Int(scrollLocation.y)))") } print("⏱️ Completed in \(String(format: "%.2f", Date().timeIntervalSince(startTime)))s") } } catch { self.handleError(error) throw ExitCode.failure } } // Error handling is provided by ErrorHandlingCommand protocol } // MARK: - JSON Output Structure struct ScrollResult: Codable { let success: Bool let direction: String let amount: Int let location: [String: Double] let totalTicks: Int let executionTime: TimeInterval }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/steipete/Peekaboo'

If you have feedback or need assistance with the MCP directory API, please join our Discord server