/playwright-mcp-metabase
Drive Metabase's UI with the Playwright MCP browser tools (mcp__playwright__browser_*). Covers the snapshot/act/check pattern, Mantine component pitfalls (Menu race, Select/MultiSelect, the Escape-closes-modal trap, portal scoping), and Metabase-specific login flows. Use
$ npx -y skills add metabase/metabase --skill playwright-mcp-metabase --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/playwright-mcp-metabase
Context preview
The summary Claude sees to decide when to auto-load this skill.
Drive Metabase's UI with the Playwright MCP browser tools (mcp__playwright__browser_*). Covers the snapshot/act/check pattern, Mantine component pitfalls (Menu race, Select/MultiSelect, the Escape-closes-modal trap, portal scoping), and Metabase-specific login flows. Use
SKILL.md
playwright-mcp-metabase.SKILL.mdname: playwright-mcp-metabase
description: Drive Metabase's UI with the Playwright MCP browser tools (mcp__playwright__browser_*). Covers the snapshot/act/check pattern, Mantine component pitfalls (Menu race, Select/MultiSelect, the Escape-closes-modal trap, portal scoping), and Metabase-specific login flows. Use whenever a session needs to interact with the Metabase UI through Playwright MCP.
Browser Automation with Playwright MCP (Metabase)
A Playwright MCP server is configured in `.mcp.json`. Load the tool schemas first with `ToolSearch`: `select:mcp__playwright__browser_navigate,mcp__playwright__browser_snapshot,mcp__playwright__browser_click,mcp__playwright__browser_fill,mcp__playwright__browser_type,mcp__playwright__browser_press_key,mcp__playwright__browser_hover,mcp__playwright__browser_take_screenshot,mcp__playwright__browser_close`
If ToolSearch says "MCP servers still connecting," wait a few seconds and retry — the server takes a moment to start on first use.
Core pattern: Snapshot → Act → Check
1. **`browser_snapshot`** — see what's on screen, get element refs 2. **Act** — `browser_click`, `browser_fill`, `browser_type`, etc. using refs from the snapshot 3. **Check the inline response** — every action returns a snapshot in its response. Read it.
**When to take a separate `browser_snapshot` after acting:**
- The inline response snapshot looks wrong, empty, or unchanged — take a fresh one (async rendering may not have completed)
- You need refs for your NEXT action — the inline snapshot's refs are valid, use them directly
- You're unsure if the action worked — take one more snapshot to confirm
**When you do NOT need a separate snapshot after acting:**
- The inline response already shows the expected change (e.g., you clicked a link and the response shows the new page)
- You're about to take a screenshot anyway (`browser_take_screenshot` shows the current state)
- You're doing a chain of actions on the same form (e.g., filling multiple fields) — snapshot once at the end, not after each fill
**Element refs go stale after every action.** Use refs from the most recent snapshot or inline response — never from an earlier one.
How to interact with Metabase's UI components
Metabase uses Mantine UI components. Most interactions work with a plain `browser_click`. The hover-before-click pattern is only needed for specific component types.
**Regular buttons, links, form inputs, checkboxes, tabs:** Just `browser_click` them directly. No hover needed.
**Buttons that open dropdown menus (e.g., "+ New", "..." action menus, filter type pickers):** These use Mantine's `<Menu>` component which has a race condition with direct clicks. **Hover before clicking** these: 1. `browser_hover` on the button 2. `browser_click` on the button 3. Check the inline response — if the menu appeared, use its refs directly
How to tell if a button opens a dropdown menu: it usually has a chevron/arrow icon, a "..." label, or is labeled as creating something new (like "+ New"). If unsure, try a direct click first — if it doesn't work, retry with hover.
**Select and dropdown components (e.g., database picker, column picker):** Mantine Select/MultiSelect are NOT native `<select>` elements. `browser_select_option` will NOT work. Instead: 1. `browser_click` on the input/trigger 2. `browser_click` on the option you want (use refs from the inline response)
You can also type into the input to filter options before clicking.
**Modals and dialogs:** To dismiss: `browser_click` the close/action button, or `browser_press_key` with `Escape`.
**⚠️ Mantine `Escape`-inside-modal trap:** Pressing `Escape` while focus is inside a Mantine popover/Select/MultiSelect that is *itself* nested in a modal closes the **entire modal** and discards every form field you've already filled. To dismiss just an open dropdown, prefer `browser_click` outside the dropdown (or click another field). Only press `Escape` when you actually want the whole modal gone.
**Mantine portals + scoped snapshots:** Mantine renders dropdowns, popovers, and tooltips into a portal at `<body>` level — they are NOT children of the `[role=dialog]` element. If you scope `browser_snapshot` to the modal, dropdown options will be missing. Take a full-page snapshot when interacting with portaled content.
Login
1. `browser_navigate` to `http://localhost:$MB_JETTY_PORT/auth/login` 2. `browser_snapshot` → `browser_fill` email and password → `browser_click` sign-in button 3. **`browser_navigate` to `http://localhost:$MB_JETTY_PORT/`** — always navigate explicitly to the home page after login. Do NOT rely on the login redirect alone. The redirect can leave the browser session in a state where clicks don't register. 4. `browser_snapshot` to confirm you're logged in
Quick login via API (alternative)
Get a session token via API and set it as a cookie — faster than filling the login form:
./bin/mage -bot-api-call /api/session --method POST --body '{"username":"<email>","password":"<password>"}'Extract the `id` from the response, then use `browser_evaluate` with script:
document.cookie = 'metabase.SESSION=<token>;path=/'
Then `browser_navigate` to the target page. Use the credentials from `./bin/mage -bot-server-info`.
When clicks don't work
1. Take a fresh snapshot (async rendering). 2. Try hover + click (menu triggers). 3. Try keyboard (focus + Enter). 4. After 3 attempts, report and move on.
Rules
- Always use `http://localhost:$MB_JETTY_PORT`
- Close the browser when done
- Use inline response snapshots when sufficient — only take separate `browser_snapshot` when needed
- Browser is pre-configured: 1440x900 viewport, full snapshot mode, isolated session, 10s action timeout
Read more
name: playwright-mcp-metabase description: Drive Metabase's UI with the Playwright MCP browser tools (mcp__playwright__browser_*). Covers the snapshot/act/check pattern, Mantine component pitfalls (Menu race, Select/MultiSelect, the Escape-closes-modal trap, portal scoping), and Metabase-specific login flows. Use whenever a session needs to interact with the Metabase UI through Playwright MCP.
Browser Automation with Playwright MCP (Metabase)
A Playwright MCP server is configured in `.mcp.json`. Load the tool schemas first with `ToolSearch`: `select:mcp__playwright__browser_navigate,mcp__playwright__browser_snapshot,mcp__playwright__browser_click,mcp__playwright__browser_fill,mcp__playwright__browser_type,mcp__playwright__browser_press_key,mcp__playwright__browser_hover,mcp__playwright__browser_take_screenshot,mcp__playwright__browser_close`
If ToolSearch says "MCP servers still connecting," wait a few seconds and retry — the server takes a moment to start on first use.
Core pattern: Snapshot → Act → Check
1. **`browser_snapshot`** — see what's on screen, get element refs 2. **Act** — `browser_click`, `browser_fill`, `browser_type`, etc. using refs from the snapshot 3. **Check the inline response** — every action returns a snapshot in its response. Read it.
**When to take a separate `browser_snapshot` after acting:**
- The inline response snapshot looks wrong, empty, or unchanged — take a fresh one (async rendering may not have completed)
- You need refs for your NEXT action — the inline snapshot's refs are valid, use them directly
- You're unsure if the action worked — take one more snapshot to confirm
**When you do NOT need a separate snapshot after acting:**
- The inline response already shows the expected change (e.g., you clicked a link and the response shows the new page)
- You're about to take a screenshot anyway (`browser_take_screenshot` shows the current state)
- You're doing a chain of actions on the same form (e.g., filling multiple fields) — snapshot once at the end, not after each fill
**Element refs go stale after every action.** Use refs from the most recent snapshot or inline response — never from an earlier one.
How to interact with Metabase's UI components
Metabase uses Mantine UI components. Most interactions work with a plain `browser_click`. The hover-before-click pattern is only needed for specific component types.
**Regular buttons, links, form inputs, checkboxes, tabs:** Just `browser_click` them directly. No hover needed.
**Buttons that open dropdown menus (e.g., "+ New", "..." action menus, filter type pickers):** These use Mantine's `<Menu>` component which has a race condition with direct clicks. **Hover before clicking** these: 1. `browser_hover` on the button 2. `browser_click` on the button 3. Check the inline response — if the menu appeared, use its refs directly
How to tell if a button opens a dropdown menu: it usually has a chevron/arrow icon, a "..." label, or is labeled as creating something new (like "+ New"). If unsure, try a direct click first — if it doesn't work, retry with hover.
**Select and dropdown components (e.g., database picker, column picker):** Mantine Select/MultiSelect are NOT native `<select>` elements. `browser_select_option` will NOT work. Instead: 1. `browser_click` on the input/trigger 2. `browser_click` on the option you want (use refs from the inline response)
You can also type into the input to filter options before clicking.
**Modals and dialogs:** To dismiss: `browser_click` the close/action button, or `browser_press_key` with `Escape`.
**⚠️ Mantine `Escape`-inside-modal trap:** Pressing `Escape` while focus is inside a Mantine popover/Select/MultiSelect that is *itself* nested in a modal closes the **entire modal** and discards every form field you've already filled. To dismiss just an open dropdown, prefer `browser_click` outside the dropdown (or click another field). Only press `Escape` when you actually want the whole modal gone.
**Mantine portals + scoped snapshots:** Mantine renders dropdowns, popovers, and tooltips into a portal at `<body>` level — they are NOT children of the `[role=dialog]` element. If you scope `browser_snapshot` to the modal, dropdown options will be missing. Take a full-page snapshot when interacting with portaled content.
Login
1. `browser_navigate` to `http://localhost:$MB_JETTY_PORT/auth/login` 2. `browser_snapshot` → `browser_fill` email and password → `browser_click` sign-in button 3. **`browser_navigate` to `http://localhost:$MB_JETTY_PORT/`** — always navigate explicitly to the home page after login. Do NOT rely on the login redirect alone. The redirect can leave the browser session in a state where clicks don't register. 4. `browser_snapshot` to confirm you're logged in
Quick login via API (alternative)
Get a session token via API and set it as a cookie — faster than filling the login form:
./bin/mage -bot-api-call /api/session --method POST --body '{"username":"<email>","password":"<password>"}'Extract the `id` from the response, then use `browser_evaluate` with script:
document.cookie = 'metabase.SESSION=<token>;path=/'
Then `browser_navigate` to the target page. Use the credentials from `./bin/mage -bot-server-info`.
When clicks don't work
1. Take a fresh snapshot (async rendering). 2. Try hover + click (menu triggers). 3. Try keyboard (focus + Enter). 4. After 3 attempts, report and move on.
Rules
- Always use `http://localhost:$MB_JETTY_PORT`
- Close the browser when done
- Use inline response snapshots when sufficient — only take separate `browser_snapshot` when needed
- Browser is pre-configured: 1440x900 viewport, full snapshot mode, isolated session, 10s action timeout
Metabase is the easy, open-source way for everyone in your company to ask questions and learn from data.
Repo: metabase/metabase
Other skills on metabase.
- /add-malli-schemas
Efficiently add Malli schemas to API endpoints in the Metabase codebase with proper patterns, validation timing, and error handling
Open skill - /add-tracing
Add OpenTelemetry tracing spans to Clojure code following Metabase tracing conventions. Use when instrumenting backend code with trace coverage.
Open skill - /analytics-events
Add product analytics events to track user interactions in the Metabase frontend
Open skill - /clojure-eval
Evaluate Clojure code via nREPL using clj-nrepl-eval. Use this when you need to test code, check if edited files compile, verify function behavior, or interact with a running REPL session.
Open skill - /clojure-review
Review Clojure and ClojureScript code changes for compliance with Metabase coding standards, style violations, and code quality issues. Use when reviewing pull requests or diffs containing Clojure/ClojureScript code.
Open skill - /clojure-write
Guide Clojure and ClojureScript development using REPL-driven workflow, coding conventions, and best practices. Use when writing, developing, or refactoring Clojure/ClojureScript code.
Open skill

