safari-mcp
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| SAFARI_MCP_GUARD | No | Enable or disable the safety guard (Layer 2). Overrides `guard_enabled` in the config file. | true |
| SAFARI_MCP_DENY_EXTRA | No | Comma-separated additional deny-list patterns to merge with the default deny list. | |
| SAFARI_MCP_GUARD_MODEL | No | The Ollama model used by the guard. Any Ollama model can be specified. | qwen3.5:4b |
| SAFARI_MCP_OLLAMA_HOST | No | The base URL of the Ollama server. | http://127.0.0.1:11434 |
| SAFARI_MCP_LOAD_TIMEOUT | No | Timeout in seconds when waiting for a page to load. | 20.0 |
| SAFARI_MCP_GUARD_TIMEOUT | No | Timeout in seconds for guard model calls. | 20.0 |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": false
} |
| prompts | {
"listChanged": false
} |
| resources | {
"subscribe": false,
"listChanged": false
} |
| experimental | {} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| list_tabsA | List every open Safari tab, with the handle you use to address it. Call this first. Every other tool takes a Returns one line per tab as |
| read_pageA | Read the visible text of a tab, or of one element inside it. This is the workhorse — prefer it over screenshots. It returns rendered
text ( Args: tab: Tab index within window 1, or a substring of its URL or title. selector: Optional CSS selector. Omit it to read the whole page. max_chars: Truncate beyond this many characters. Default 8000. |
| find_elementsA | Inspect the elements a CSS selector matches, before acting on them. Use this to check that a selector hits what you think it does, and to read
the index you will pass to Args: tab: Tab index within window 1, or a substring of its URL or title. selector: The CSS selector to inspect. limit: Most elements to describe. Default 20. |
| open_tabA | Open a URL in a new Safari tab and wait for it to finish loading. Prefer this over Args: url: The URL to open. Parentheses and spaces are encoded for you. |
| navigateA | Point an existing tab at a URL and wait for the load to complete. Returns the URL actually landed on, so you can see redirects. Parentheses, spaces and other characters Safari's URL setter silently refuses are percent-encoded for you. Args: tab: Tab index within window 1, or a substring of its URL or title. url: Where to send it. |
| clickA | Click an element. Check it with Passes through the denylist and then the local safety gate, either of which may refuse — the refusal explains itself and is worth relaying verbatim rather than retrying. Args: tab: Tab index within window 1, or a substring of its URL or title. selector: CSS selector for the element. index: Which match to click when the selector hits several. Default 0. |
| fillA | Type a value into an input, textarea, or contenteditable element. Sets the value through the element's native setter and then dispatches
Args: tab: Tab index within window 1, or a substring of its URL or title. selector: CSS selector for the field. value: The text to enter. index: Which match to fill when the selector hits several. Default 0. |
| run_jsA | Run arbitrary JavaScript in a tab. The escape hatch; prefer the others. Your code runs as a function body, so Args:
tab: Tab index within window 1, or a substring of its URL or title.
code: JavaScript to execute. Use |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
TDQS
Scored across 8 tools
Each tool targets a distinct action: listing tabs, reading content, inspecting elements, opening/navigating tabs, clicking, filling, and executing JS. Even overlapping actions like open_tab vs. navigate are clearly separated by whether they open a new tab or reuse an existing one. There is no ambiguity in selecting the right tool for a task.
Most names follow a verb_noun pattern (list_tabs, read_page, find_elements, open_tab, run_js), but navigate, click, and fill are bare verbs without an object. The names are still predictable and all lowercase snake_case, but the pattern is not perfectly uniform.
Eight tools is a well-scoped set for browser automation. Each tool has a clear purpose and no redundant utilities; the count feels appropriate for the domain without being sparse or bloated.
The surface covers the core browser automation lifecycle: inspect (list_tabs, read_page, find_elements), act (click, fill), navigate (open_tab, navigate), and an escape hatch (run_js). Missing operations like back/forward, close tab, or direct URL getter are minor and can be worked around with run_js or navigate.