Public leaderboard

Public assessment

achiya-automation/safari-mcp (safari-mcp)

safari-mcp · v2.15.11 · scanned

What changed in the harness

Selection accuracy 90→90, token cost up 5%, unconfirmed writes 0%→0%.

Category breakdown

Where the score comes from.

Earned points across the four signals Gradable measures. Safety and Legibility are scored out of 30; Economics and Discoverability are scored out of 20.

01Safety

0.0 / 30

0.0 out of 30
02Legibility

16.2 / 30

16.2 out of 30
03Economics

11.4 / 20

11.4 out of 20
04Discoverability

11.8 / 20

11.8 out of 20

Highest-impact fix

Estimated gain +30 points

Add explicit identity and permission preflight tools

Expose machine-readable principal/tenant confirmation and a non-mutating permission check so agents can verify both before destructive actions.

Description evidence

Defects and rewrites.

78 defects found across the exposed tool descriptions. Suggested rewrites make purpose, inputs, boundaries, and returns easier for an agent to understand.

Tool Defect types Suggested rewrite
safari_navigate
name_restates_behavior no_return_description
Loads the given URL in the current Safari tab and blocks until the page finishes loading. Returns the final page title and URL once loaded.
safari_go_back
no_return_description
Navigates the current tab to the previous page in browser history, equivalent to clicking the back button. Returns the resulting page's title and URL.
safari_go_forward
no_return_description
Navigates the current tab to the next page in browser history, equivalent to clicking the forward button. Returns the resulting page's title and URL.
safari_reload
no_return_description
Reloads the current page in Safari; set hard:true to bypass the cache and force a full reload from the server. Returns the reloaded page's title and URL.
safari_get_source
no_return_description
Retrieves the raw HTML source of the current page, truncated to maxLength characters (default 200000). Returns the HTML as a string.
safari_click
no_return_description
Clicks an element identified by ref, CSS selector, visible text, or x/y coordinates, dispatching a full PointerEvent+MouseEvent sequence (with a React Fiber fallback) so it works on React/Airtable/virtual DOM apps; never moves the real mouse. Returns confirmation of what was clicked or an error if no matching element was found.
safari_double_click
no_return_description
Double-clicks an element identified by CSS selector or x/y coordinates, e.g. to select a word in text. Returns confirmation of the action or an error if no matching element was found.
safari_right_click
no_return_description
Right-clicks an element identified by CSS selector or x/y coordinates to open its context menu. Returns confirmation of the action or an error if no matching element was found.
safari_native_hover
no_return_description
Moves the real macOS cursor (via CGEvent) onto an element identified by ref, selector, text, or x/y to trigger native :hover/mouseenter handlers — for obfuscated UIs like Discord's server sidebar or portal-rendered tooltips where JS-dispatched hover isn't enough. Dwells for dwellMs before optionally restoring the cursor to its original position. Returns confirmation that the hover was performed; use safari_wait_for or safari_evaluate afterward to read any resulting tooltip.
safari_native_type
no_return_description
Focuses the element given by selector or ref (if provided) and pastes value into it via a real OS-level clipboard paste (CGEvent Cmd+V), so frameworks like ProseMirror/Slate/Draft.js process it as a native paste event and update their internal state — unlike safari_fill's direct DOM manipulation. Saves and restores the user's existing clipboard content. Returns confirmation that the paste was performed.
safari_fill
no_return_description
Sets/replaces the value of an input, textarea, select, or contenteditable element identified by ref or selector, handling React controlled inputs, ProseMirror, Draft.js, and Google Closure editors automatically. Returns confirmation of the new value or an error if no matching element was found.
safari_clear_field
no_return_description
Clears the value of the input element matched by selector. Returns confirmation that the field was cleared or an error if no matching element was found.
safari_select_option
no_return_description
Selects an option in a native <select> element (matched by selector or ref) by setting its value and dispatching a change event. Returns the resulting selected value or an error if no matching option was found.
safari_fill_form
no_return_description
Fills multiple input/textarea fields in one call from an array of {selector, value} pairs. Returns confirmation of which fields were filled or errors for any selectors that didn't match.
safari_press_key
no_return_description
Dispatches a keyboard event for the given key (e.g. enter, tab, escape, arrows) to the currently focused element, optionally with modifier keys (cmd, shift, alt, ctrl). Returns confirmation that the key was pressed.
safari_type_text
no_return_description
Types text character-by-character with realistic key events into the element given by ref or selector (or the currently focused element), useful for search boxes, chat inputs, and fields that react to each keystroke. Returns confirmation that the text was typed.
safari_replace_editor
no_return_description
Replaces all content in a code editor (Monaco, CodeMirror, Ace, ProseMirror) with the given text, detecting the editor type and using its native API. Returns confirmation that the content was replaced.
safari_screenshot
no_return_description
Captures a visual screenshot of the current viewport, or the full page if fullPage is true. Returns the image as base64-encoded JPEG data.
safari_scroll
no_return_description
Scrolls the page up or down by amount pixels (default 500) in the given direction (default down). Returns the resulting scroll position.
safari_scroll_to
no_return_description
Scrolls the page to the absolute x,y position (defaults 0,0). Returns the resulting scroll position.
safari_list_tabs
name_restates_behavior no_return_description
Enumerates every open Safari tab, useful for choosing a target for safari_switch_tab. Returns an array of tabs with their index, title, and URL.
safari_reload_extension
no_return_description
Forces the Safari MCP Bridge extension to reload its own code from disk, for use after editing extension/background.js or extension/content.js — the extension disconnects briefly and auto-reconnects within ~2 seconds. Requires extension v2.9.1+ to support this command. Returns confirmation once the reload has been triggered.
safari_new_tab
no_return_description
Opens a new Safari tab, optionally navigating it to url (blank tab if omitted). Returns the new tab's index.
safari_close_tab
no_return_description
Closes the current tab. Returns confirmation that the tab was closed.
safari_switch_tab
no_return_description
Switches the active tab that subsequent commands (click, fill, evaluate, screenshot, scroll, etc.) target, using the 1-based index from safari_list_tabs. Returns confirmation of the newly active tab's title and URL.
safari_wait_for
no_return_description
Polls the page until the element matching selector or the given text appears, up to timeout ms (default 10000). Returns confirmation once found or a timeout error.
safari_wait_for_new_tab
no_return_description
Waits (up to timeout ms, default 10000) for a new Safari tab to open, e.g. after clicking an OAuth login link that opens a popup, optionally restricted to tabs whose URL contains urlContains, and automatically switches to it. Returns the new tab's index, title, and URL.
safari_evaluate
no_return_description
Executes arbitrary JavaScript in the current page context, automatically falling back to AppleScript when CSP blocks execution (e.g. Google Search Console, LinkedIn). Returns the script's result value, serialized as JSON.
safari_eval_file
no_return_description
Executes JavaScript read from the file at path using the same engine as safari_evaluate (extension-first, AppleScript fallback), useful for large scripts or uploading binary data as base64 without pasting it inline. Returns the script's result value, serialized as JSON.
safari_get_element
no_return_description
Looks up the element matching selector and inspects it. Returns its tag name, text content, bounding rect, attributes, and visibility state.
safari_hover
no_return_description
Moves the mouse pointer (via JS events, not a real OS cursor) over the element given by ref, selector, or x/y to trigger hover-based UI like tooltips or dropdown menus. Returns confirmation that the hover was performed.
safari_handle_dialog
no_return_description
Registers a handler that will accept or dismiss the next browser alert/confirm/prompt dialog, optionally supplying text for prompt dialogs. Returns confirmation that the handler was registered.
safari_resize
name_restates_behavior no_return_description
Sets the Safari window to the given width and height in pixels, useful for testing responsive layouts. Returns the window's resulting dimensions.
safari_drag
no_return_description
Drags an element from a source (sourceSelector or sourceX/sourceY) to a target (targetSelector or targetX/targetY) by simulating a mouse-down, move, and mouse-up sequence. Returns confirmation that the drag was performed.
safari_paste_image
no_return_description
Pastes the image at filePath into the currently focused element via a JS DataTransfer event (no clipboard, no focus stealing) — works on Medium, dev.to, HackerNoon, TOI, etc. Returns confirmation that the image was pasted.
safari_emulate
no_return_description
Emulates a mobile device by resizing the Safari window and setting the user agent, either from a known device preset (device, e.g. iphone-14, ipad, pixel-7, galaxy-s24) or custom width/height/userAgent/scale values. Returns the resulting viewport dimensions and user agent.
safari_reset_emulation
no_return_description
Resets device emulation back to normal desktop viewport and user agent. Returns confirmation that emulation was reset.
safari_get_cookies
no_return_description
Reads the cookies visible to the current page. Returns an array of cookies with their name, value, domain, path, and flags.
safari_local_storage
no_return_description
Reads localStorage for the current page, either a single key or all entries if key is omitted. Returns the stored value(s) as JSON.
safari_run_script
no_return_description
Executes a sequence of Safari actions (matching other safari_* tool names without the prefix, e.g. 'navigate', 'click', 'fill', 'evaluate', 'readPage') in one call, running each step's args in order. Returns an array of each step's result.
safari_start_console
no_return_description
Begins capturing console messages (log, warn, error, info) emitted by the current page; call once per page before using safari_get_console. Returns confirmation that capture has started.
safari_get_console
name_restates_behavior no_return_description
Retrieves the console messages captured since safari_start_console was called. Returns an array of messages with their level, text, and timestamp.
safari_clear_console
no_return_description
Clears all console messages captured so far by safari_start_console. Returns confirmation that the buffer was cleared.
safari_save_pdf
name_restates_behavior no_return_description
Renders the current page to a PDF using screencapture-based rendering (no Safari print UI involved) and writes it to path. Returns confirmation of the saved file path.
safari_accessibility_snapshot
no_return_description
Walks the accessibility tree of the page (or the subtree under selector) up to maxDepth levels deep, for a11y auditing. Returns each node's role, ARIA label, focusable/form state, and hierarchy.
safari_set_cookie
no_return_description
Sets a cookie (name, value, and optional domain/path/expires/secure/sameSite) on the current page. Returns confirmation that the cookie was set.
safari_delete_cookies
no_return_description
Deletes the cookie matching name, or every cookie if all is true. Returns confirmation of which cookies were deleted.
safari_session_storage
no_return_description
Reads sessionStorage for the current page, either a single key or all entries if key is omitted. Returns the stored value(s) as JSON.
safari_set_session_storage
name_restates_behavior no_return_description
Writes value to sessionStorage under key on the current page, useful for restoring session state without going through the UI. Returns confirmation that the value was set.
safari_set_local_storage
name_restates_behavior no_return_description
Writes value to localStorage under key on the current page, useful for restoring session state without going through the UI. Returns confirmation that the value was set.
safari_delete_local_storage
name_restates_behavior no_return_description
Deletes the localStorage entry for key, or clears all localStorage if key is omitted. Returns confirmation of what was cleared.
safari_delete_session_storage
name_restates_behavior no_return_description
Deletes the sessionStorage entry for key, or clears all sessionStorage if key is omitted. Returns confirmation of what was cleared.
safari_export_storage
no_return_description
Captures the page's full storage state — cookies, localStorage, and sessionStorage — for saving and later restoring a login session. Returns the state serialized as a JSON string.
safari_import_storage
name_restates_behavior no_return_description
Restores cookies, localStorage, and sessionStorage on the current page from a JSON string previously produced by safari_export_storage. Returns confirmation that the state was applied.
safari_clipboard_read
no_return_description
Reads the current text content of the system clipboard. Returns the clipboard text as a string.
safari_clipboard_write
no_return_description
Writes text to the system clipboard, replacing its current content. Returns confirmation that the clipboard was set.
safari_clear_mocks
no_return_description
Removes all network route mocks registered via safari_mock_route, restoring real network behavior. Returns confirmation that mocks were cleared.
safari_wait
no_return_description
Pauses execution for a fixed ms milliseconds; prefer safari_wait_for when waiting on a specific element or text instead of a blind delay. Returns confirmation once the wait completes.
safari_start_network_capture
no_return_description
Begins intercepting fetch and XHR requests made by the page, capturing headers, status, and timing for requests made after this call; call once per page before using safari_network_details. Returns confirmation that capture has started.
safari_network_details
no_return_description
Retrieves detailed network requests captured since safari_start_network_capture was called, optionally limited to limit results or filtered by URL substring. Returns an array of requests with method, URL, status, headers, and timing.
safari_clear_network
no_return_description
Clears all network requests captured so far by safari_start_network_capture. Returns confirmation that the buffer was cleared.
safari_performance_metrics
no_return_description
Collects the page's navigation timing, Web Vitals (FCP, LCP, CLS), resource breakdown, and memory usage. Returns these metrics as a structured object.
safari_throttle_network
no_return_description
Simulates network conditions for the page using a preset profile (slow-3g, fast-3g, 4g, offline) or custom latency/downloadKbps values; call with no args to reset to normal speed. Returns confirmation of the throttling profile applied.
safari_console_filter
no_return_description
Retrieves captured console messages filtered to a single level (log, warn, error, info); requires safari_start_console to have been called first. Returns an array of matching messages.
safari_extract_tables
no_return_description
Parses HTML tables matching selector (default 'table'), up to limit tables. Returns each table as structured JSON with headers and rows.
safari_extract_meta
no_return_description
Scans the page's <head> for SEO and social metadata. Returns title, meta description, canonical URL, Open Graph tags, Twitter card tags, JSON-LD blocks, alternate-language links, and RSS feed links.
safari_extract_images
no_return_description
Scans the page for <img> elements, up to limit images. Returns each image's src, alt text, dimensions, loading strategy, and current viewport visibility.
safari_extract_links
no_return_description
Scans the page for <a> elements, up to limit links, optionally filtered by URL or text substring. Returns each link's href, text, rel, target, and whether it's external/nofollow.
safari_get_computed_style
name_restates_behavior no_return_description
Reads the browser's computed CSS for the element matching selector, optionally limited to specific properties. Returns a map of property names to their computed values.
safari_list_indexed_dbs
no_return_description
Enumerates the IndexedDB databases available on the current page. Returns an array of database names and versions.
safari_get_indexed_db
params_unexplained no_return_description
Reads records from storeName, an object store within the IndexedDB database dbName, up to limit records (default 20). Returns the store's records as an array of JSON objects.
safari_css_coverage
no_return_description
Runs the CSS coverage profiler across all stylesheets on the page to find unused rules. Returns each stylesheet's URL with used/unused byte counts and coverage percentage.
safari_safe_area_insets
no_return_description
Reads the live CSS safe-area-inset values (top/right/bottom/left) as the page renders them, for notch/Dynamic Island layout debugging. Returns the inset values, whether viewport-fit=cover is set, and whether any stylesheet uses env(safe-area-inset-*).
safari_webkit_compat
no_return_description
Tests every CSS property used on the page against this Safari's live engine via CSS.supports(). Returns a list of unsupported properties, properties needing a -webkit- prefix, and known Safari rendering quirks (e.g. position:sticky inside overflow ancestors).
safari_detect_forms
no_return_description
Scans the page for <form> elements and their fields. Returns each form's fields (name, type, selector) and submit button, for use in automated form filling.
safari_scroll_to_element
no_return_description
Scrolls to the element matching selector, or repeatedly scrolls down (up to timeout ms) until text appears — useful for virtual DOM/lazy-loaded content like Airtable. Returns confirmation once the target is in view, aligned per block (default center).
safari_fill_and_submit
no_return_description
Fills the given fields (array of {selector, value}) and submits the form, auto-detecting the submit button unless submitSelector is given. Returns confirmation of submission or the resulting page state.
safari_analyze_page
no_return_description
Runs a full page audit in one call — title, URL, meta tags, Open Graph tags, headings, link stats, image stats, forms, and a text preview — for SEO/audit workflows. Returns this analysis as a structured object.

Selection evidence

Confusable tool pairs.

23 pairs where similar names or overlapping descriptions may send an agent toward the wrong tool.

Tool A Tool B Confidence Why they collide
safari_wait_for safari_wait high A task like 'wait for the page to finish loading' could map to either the fixed-ms wait or the smarter element/text wait; both take a generic 'wait' framing even though wait_for is explicitly preferred.
safari_navigate safari_navigate_and_read high 'Go to this URL and tell me what's on the page' plausibly triggers either a navigate call followed by a separate read, or the combined navigate_and_read tool, since both satisfy the same phrasing.
safari_snapshot safari_accessibility_snapshot high Both descriptions reference 'accessibility tree' and page state; a task like 'get the accessibility tree of the page' could pick either, even though snapshot is meant for interaction refs and accessibility_snapshot for a11y auditing.
safari_click safari_click_and_read medium 'Click the button and show me the result' is ambiguous between a plain click (then separately reading) and the combined click_and_read tool.
safari_click safari_click_and_wait medium 'Click submit and wait for the page to update' could resolve to click alone (expecting a follow-up wait) or the combined click_and_wait tool.
safari_click safari_native_click medium A task like 'click the button, it's not registering' doesn't specify WAF/bot-detection context, so the agent may not clearly choose between regular click and OS-level native_click.
safari_click_and_read safari_click_and_wait medium Both are combined click+followup tools differing only in whether they return page content or just wait; a vague 'click and see what happens' task is ambiguous between them.
safari_double_click safari_native_click medium safari_native_click has a doubleClick parameter, so a task like 'double-click this element to select text' could plausibly route to either tool.
safari_fill safari_fill_and_submit medium 'Fill in the login form and log in' is ambiguous between filling then a separate submit action versus the combined fill_and_submit tool.
safari_fill safari_fill_form medium 'Fill out the signup form' doesn't specify single vs multiple fields, so the agent could choose repeated safari_fill calls or the batch fill_form tool.
safari_native_hover safari_hover medium A task like 'hover over the menu item to show the tooltip' doesn't indicate whether native OS-level hover is needed, making the choice between hover and native_hover ambiguous.
safari_network safari_network_details medium 'Show me the network requests' is ambiguous between the no-setup quick overview (safari_network) and the detailed capture-based safari_network_details, especially since both surface request info.
safari_scroll safari_scroll_to_element medium 'Scroll down to the footer/button' could be interpreted as a generic pixel scroll or as scrolling precisely to that element by text/selector.
safari_scroll_to safari_scroll_to_element medium 'Scroll to the login button' vs 'scroll to the top' both use 'scroll to' phrasing but map to different tools (element-targeted vs coordinate-targeted).
safari_scroll safari_scroll_to medium 'Scroll to the top of the page' could be attempted with relative scroll(direction:up, large amount) or the absolute scroll_to(x:0,y:0), since both achieve similar effects via different mechanisms.
safari_wait_for safari_click_and_wait medium 'Click the link and wait until the new content appears' could be done via separate click+wait_for calls or the combined click_and_wait tool, causing overlap in tool choice.
safari_get_console safari_console_filter medium 'Show me the console errors' is ambiguous between getting all console messages (then filtering mentally) and directly calling console_filter with level='error'.
safari_local_storage safari_session_storage medium A generic task like 'check the storage data for this page' doesn't specify local vs session storage, and both tools have nearly identical get-semantics.
safari_clear_mocks safari_clear_network medium 'Clear the network mocking/state' is ambiguous between removing route mocks (clear_mocks) and clearing captured network request logs (clear_network).
safari_eval_file safari_upload_file medium The eval_file description explicitly mentions using it 'to upload binary via a generated .js containing base64', overlapping with upload_file's purpose for a task like 'upload this file to the input'.
safari_set_session_storage safari_set_local_storage medium 'Store this value in the browser' doesn't indicate storage type, so the agent could plausibly pick either set_session_storage or set_local_storage.
safari_delete_local_storage safari_delete_session_storage low 'Clear the site's storage' is somewhat ambiguous between clearing local vs session storage, though the distinct 'local'/'session' terms usually disambiguate when the user is specific.
safari_new_tab safari_wait_for_new_tab low A task like 'handle the tab that opens after clicking login' could be misrouted to opening a new tab versus waiting for one that opens automatically, though their action verbs (open vs wait) differ enough to usually disambiguate.

Compare the field

One score is useful.
The evidence makes it actionable.

Back to the leaderboard