Excessive approval prompts after recent changes for Playwright MCP

Open 💬 30 comments Opened Mar 4, 2026 by grray
💡 Likely answer: A maintainer (github-actions[bot], contributor) responded on this thread — see the highlighted reply below.

What version of Codex CLI is running?

codex-cli 0.107.0

What subscription do you have?

team subscription from my employer

Which model were you using?

gpt-5.3-codex

What platform is your computer?

Linux 6.8.0-101-generic x86_64 x86_64

What terminal emulator and version are you using (if applicable)?

_No response_

What issue are you seeing?

After recent changes, approval_policy = "never" does not stop approval prompts for Playwright MCP tool calls. If I ask Codex to test some UI using Playwright MCP, it asks for confirmation for many tools like browser_click or browser_type, dozens of them, which makes using Playwright very slow and tedious. It wasn’t like this before.

I need a way to trust a specific local MCP server (Playwright) without disabling safety globally for everything else.

What steps can reproduce the bug?

  1. Configure Codex with:
approval_policy = "never"
[mcp_servers.playwright]
command = "npx"
args = ["-y", "@playwright/mcp@latest"]
  1. Restart Codex.
  2. Start a task that uses Playwright MCP and performs mutating actions (for example:

navigate, click button, type into input).

  1. Observe that approval prompts are still requested for Playwright actions.

What is the expected behavior?

Either of these should work:

  1. approval_policy = "never" should also suppress Playwright MCP action approvals, or
  2. Codex should support per-MCP approval configuration, so trusted local servers can be

auto-approved.

Proposed config:

[mcp_servers.playwright]
default_tools_approval_mode = "approve" # auto | prompt | approve

Optional per-tool override:

[mcp_servers.playwright.tools.browser_click]
approval_mode = "approve"

Additional information

_No response_

View original on GitHub ↗

30 Comments

github-actions[bot] contributor · 4 months ago

Potential duplicates detected. Please review them and close your issue if it is a duplicate.

  • #11885
  • #12095
  • #13119
  • #13405

Powered by Codex Action

etraut-openai contributor · 4 months ago

You said "after recent changes". Can you be more specific? Are you talking about recent configuration changes on your system, a recent update to the Playwright MCP server, or a recent update to the Codex CLI? If it's the CLI, can you confirm that the behavior changed by downgrading and specifying where you first saw the problem occur? I'm trying to determine if something in Codex regressed.

grray · 4 months ago

@etraut-openai problem is absent in codex cli 0.104 (no approval prompts) and starts from 0.105. Same codex config, same Playwright mcp, same tools called. Codex told me that Playwright have some tools marked in metadata that they "mutate world", so perhaps codex started to take this into account, but don't provide convenient way to skip that, confirmations are per-session-per-tool at max, not even per-mcp. It looks so bad that I filed it as a bug.

etraut-openai contributor · 4 months ago

OK, thanks for the additional details. Very helpful.

duaneadam · 4 months ago

Yes, I faced similar issue. Previously Playwright MCP can just run without approval.

caidish · 4 months ago

Same issue. Reproducible.

WIth any MCP connected, the MCP tool cannot bypass permission anymore.

Sogl · 4 months ago

It’s very annoying to constantly press yes, yes for Playwright MCP and there is no allow setting for it...
v0.113.0

marcesengel · 4 months ago

To me it's especially stupid as I can't even see the args codex tries to pass, so I can't even make a proper decision on the approvals.

chardin1 · 4 months ago

I wasn't trying to use Playwright before, but I can confirm I'm seeing the same behavior. Asking for approval for every tool call (browser_click, browser_navigate, browser_type, etc) even when approval_policy = "never". Very annoying.

Relatedly, I wish there was a way to set "never" for specific tools/mcps too.

caidish · 4 months ago

The issue is more severe in codex exec: the process just halts silently.

razashariff · 4 months ago

Per-MCP trust configuration is the right direction. MCPS (MCP Secure) implements this at the protocol level with cryptographic trust levels (L0-L4):

  • L0 (self-signed): untrusted, requires per-tool approval
  • L1 (verified): Trust Authority verified the agent identity
  • L2 (scanned): agent code passed OWASP security scan
  • L3 (audited): third-party security audit completed
  • L4 (certified): full certification with revocation enforcement

The minTrustLevel setting on the server side automatically gates which agents can call which tools — no per-invocation approval needed for agents that meet the trust threshold. Trust decisions are cryptographic, not configuration-based.

Published as an IETF Internet-Draft and available on npm as mcp-secure.

bertramn · 4 months ago

With Codex App Version 26.318.11754 (1100) on MacOS Playwright MCP is almost unusable. Every single new variation of a script fired off to the browser triggers an approval.

naodya · 3 months ago

This is painful SOS

jstiers · 3 months ago

Makes Playwright unusable with Codex. Please fix! (Codex Version 26.323.20928)

laffo16 · 3 months ago

I’m seeing the same problem on Codex CLI on Windows, and it is not limited to Playwright.

In my case, approval_policy = "never" is set globally, but I still get repeated MCP approval prompts during normal work.

I also checked my config and the current pattern seems to be tool-level, not MCP-level: it accumulates individual mcp_servers.<id>.tools.<tool>.approval_mode = "approve" entries over time. That gets noisy quickly and does not scale well once a trusted MCP exposes a lot of tools.

So I support this issue as a broader raw-MCP approval problem, not just a Playwright-specific one.

Ideally one of these should exist:

  1. approval_policy = "never" should suppress trusted raw MCP tool prompts as well.
  2. Raw MCP servers should support a per-MCP default such as:
[mcp_servers.my_server]
default_tools_approval_mode = "approve"

An MCP-level default would be much easier to manage than accumulating per-tool approval entries in config.

lkraider · 3 months ago

Something like could also be another way (but isn't supported - this is a suggestion):

[mcp_servers.playwright.tools.*]
approval_mode = "approve"

For now, I am going with this (tool names extracted from playwright-mcp docs):

<details>
<summary><strong>🚨 CLICK TO EXPAND:</strong> Playwright MCP – full tool approval config (all tools)</summary>

# Keep command approvals interactive
approval_policy = "on-request"

[mcp_servers.playwright]
command = "npx"
args = ["@playwright/mcp@latest", "--browser", "chromium"]
enabled = true

# =========================
# Core / Navigation
# =========================
[mcp_servers.playwright.tools.browser_navigate]
approval_mode = "approve"

[mcp_servers.playwright.tools.browser_navigate_back]
approval_mode = "approve"

[mcp_servers.playwright.tools.browser_close]
approval_mode = "approve"

[mcp_servers.playwright.tools.browser_tabs]
approval_mode = "approve"

[mcp_servers.playwright.tools.browser_resize]
approval_mode = "approve"

# =========================
# Interaction
# =========================
[mcp_servers.playwright.tools.browser_click]
approval_mode = "approve"

[mcp_servers.playwright.tools.browser_drag]
approval_mode = "approve"

[mcp_servers.playwright.tools.browser_hover]
approval_mode = "approve"

[mcp_servers.playwright.tools.browser_type]
approval_mode = "approve"

[mcp_servers.playwright.tools.browser_press_key]
approval_mode = "approve"

[mcp_servers.playwright.tools.browser_select_option]
approval_mode = "approve"

[mcp_servers.playwright.tools.browser_file_upload]
approval_mode = "approve"

[mcp_servers.playwright.tools.browser_handle_dialog]
approval_mode = "approve"

[mcp_servers.playwright.tools.browser_fill_form]
approval_mode = "approve"

# =========================
# Page / Content / Eval
# =========================
[mcp_servers.playwright.tools.browser_evaluate]
approval_mode = "approve"

[mcp_servers.playwright.tools.browser_run_code]
approval_mode = "approve"

[mcp_servers.playwright.tools.browser_snapshot]
approval_mode = "approve"

[mcp_servers.playwright.tools.browser_console_messages]
approval_mode = "approve"

[mcp_servers.playwright.tools.browser_network_requests]
approval_mode = "approve"

[mcp_servers.playwright.tools.browser_wait_for]
approval_mode = "approve"

# =========================
# Screenshots / Media
# =========================
[mcp_servers.playwright.tools.browser_take_screenshot]
approval_mode = "approve"

# =========================
# Config (requires --caps=config)
# =========================
[mcp_servers.playwright.tools.browser_get_config]
approval_mode = "approve"

# =========================
# Network (requires --caps=network)
# =========================
[mcp_servers.playwright.tools.browser_network_state_set]
approval_mode = "approve"

[mcp_servers.playwright.tools.browser_route]
approval_mode = "approve"

[mcp_servers.playwright.tools.browser_route_list]
approval_mode = "approve"

[mcp_servers.playwright.tools.browser_unroute]
approval_mode = "approve"

# =========================
# Storage (requires --caps=storage)
# =========================
[mcp_servers.playwright.tools.browser_cookie_clear]
approval_mode = "approve"

[mcp_servers.playwright.tools.browser_cookie_delete]
approval_mode = "approve"

[mcp_servers.playwright.tools.browser_cookie_get]
approval_mode = "approve"

[mcp_servers.playwright.tools.browser_cookie_list]
approval_mode = "approve"

[mcp_servers.playwright.tools.browser_cookie_set]
approval_mode = "approve"

[mcp_servers.playwright.tools.browser_localstorage_clear]
approval_mode = "approve"

[mcp_servers.playwright.tools.browser_localstorage_delete]
approval_mode = "approve"

[mcp_servers.playwright.tools.browser_localstorage_get]
approval_mode = "approve"

[mcp_servers.playwright.tools.browser_localstorage_list]
approval_mode = "approve"

[mcp_servers.playwright.tools.browser_localstorage_set]
approval_mode = "approve"

[mcp_servers.playwright.tools.browser_sessionstorage_clear]
approval_mode = "approve"

[mcp_servers.playwright.tools.browser_sessionstorage_delete]
approval_mode = "approve"

[mcp_servers.playwright.tools.browser_sessionstorage_get]
approval_mode = "approve"

[mcp_servers.playwright.tools.browser_sessionstorage_list]
approval_mode = "approve"

[mcp_servers.playwright.tools.browser_sessionstorage_set]
approval_mode = "approve"

[mcp_servers.playwright.tools.browser_set_storage_state]
approval_mode = "approve"

[mcp_servers.playwright.tools.browser_storage_state]
approval_mode = "approve"

# =========================
# DevTools / Tracing (requires --caps=devtools)
# =========================
[mcp_servers.playwright.tools.browser_start_tracing]
approval_mode = "approve"

[mcp_servers.playwright.tools.browser_stop_tracing]
approval_mode = "approve"

[mcp_servers.playwright.tools.browser_start_video]
approval_mode = "approve"

[mcp_servers.playwright.tools.browser_stop_video]
approval_mode = "approve"

# =========================
# Vision / Mouse (requires --caps=vision)
# =========================
[mcp_servers.playwright.tools.browser_mouse_click_xy]
approval_mode = "approve"

[mcp_servers.playwright.tools.browser_mouse_down]
approval_mode = "approve"

[mcp_servers.playwright.tools.browser_mouse_drag_xy]
approval_mode = "approve"

[mcp_servers.playwright.tools.browser_mouse_move_xy]
approval_mode = "approve"

[mcp_servers.playwright.tools.browser_mouse_up]
approval_mode = "approve"

[mcp_servers.playwright.tools.browser_mouse_wheel]
approval_mode = "approve"

# =========================
# PDF (requires --caps=pdf)
# =========================
[mcp_servers.playwright.tools.browser_pdf_save]
approval_mode = "approve"

# =========================
# Testing (requires --caps=testing)
# =========================
[mcp_servers.playwright.tools.browser_generate_locator]
approval_mode = "approve"

[mcp_servers.playwright.tools.browser_verify_element_visible]
approval_mode = "approve"

[mcp_servers.playwright.tools.browser_verify_list_visible]
approval_mode = "approve"

[mcp_servers.playwright.tools.browser_verify_text_visible]
approval_mode = "approve"

[mcp_servers.playwright.tools.browser_verify_value]
approval_mode = "approve"

</detail>

N1k1tung · 3 months ago

This has been finally shipped to vscode extension - as is.
Who thought of this change as acceptable with such an implementation I wonder?
Atleast make the asterix (tools.*) work! And it's not just about Playwright, which I don't use, it's for every mcp! It's borderline insane, currently it either makes codex unusable or config unreadable.
Luckily there's an option to downgrade to previous extension version, but I'd like to utilise upstream updates too.

dogmatic69 · 3 months ago

I am using obsidian mcp tool and after updating to 0.117 I am being asked for every single tool use. This was not the case before. I can not see a way to allow all obsidian tools always, now having to allow each time resulting in things taking hours.

thomaswitt · 3 months ago

Same problem here, mainly with tool calls to chrome devtools, like chrome-devtools.take_snapshot({"verbose":false}). Approval on every single one despite my config.toml contains

[mcp_servers.chrome-devtools.take_screenshot]
approval_mode = "approve"
matys1 · 3 months ago

When will this finally be resolved?

For each MCP you literally have to whitelist every single tool individually right now e.g.:

[mcp_servers.chrome-devtools.tools.new_page]
approval_mode = "approve"
...

You should add a setting for MCPs like below like you have for apps:

[mcp_servers.chrome-devtools]
default_tools_approval_mode = "approve"
codengine · 3 months ago

I am struggling with the same issue. Moreover its really inconvenient that I have to approve tools twice - the tool itself and each call individually for certain tools (because of some security checks...)

jstiers · 3 months ago

This needs to be fixed. MCP is completely unusable like this.

grray · 3 months ago

So OpenAi implemented per-tool "auto-approve", so as a workaround you can use config from this comment (it's folded). And now we have option to allow specific tool inside Codex CLI (It used to be only "allow for session", now we can just allow specific tool, and it will be saved in config.toml). So this issue is kind of partially fixed.

dogmatic69 · 3 months ago

adding a config with 500 approval entries is not "fixed". This has already been stated as an option as well as not being acceptable.

Meowzz95 · 3 months ago

can't believe this is still open, so codex team's first priority is to squeeze every bit of usage limit out of your paying customer instead of fixing issues affecting daily use?

jstiers · 3 months ago
So OpenAi implemented per-tool "auto-approve", so as a workaround you can use config from this comment (it's folded). And now we have option to allow specific tool inside Codex CLI (It used to be only "allow for session", now we can just allow specific tool, and it will be saved in config.toml). So this issue is kind of partially fixed.

This does not work for me unfortunately. Using Playwright MCP and Codex App or CLI.

DejvyK · 3 months ago

the issue is still present in codex VScode chat option even if I add the approval_mode or default_tools_approval_mode = "approve" . I am thinking about running the codex via cli headlessly and doing the danger-full-access mode loop. which might work with the mcp. Have anyone tried that ?

chardin1 · 3 months ago

This seems to have gotten even worse. You can't approve for the session anymore and there's almost no info shown. Even though I've got the playwright mcp approvals in my config.toml I'm getting this every time.

<img width="784" height="225" alt="Image" src="https://github.com/user-attachments/assets/b4243849-41e2-420d-a04f-0640210dcf3f" />

emilheap · 3 months ago
When will this finally be resolved? For each MCP you literally have to whitelist every single tool individually right now e.g.: `` [mcp_servers.chrome-devtools.tools.new_page] approval_mode = "approve" ... ` You should add a setting for MCPs like below like you have for apps: ` [mcp_servers.chrome-devtools] default_tools_approval_mode = "approve" ``

Even with per-tool approve in config.toml, i'm still being asked everytime..

The reason it's not fixed is probably because it's not coming from the codex-cli/app, but more so from changes to their internal model's developer-instruction prompts

SylvainWinning · 1 month ago

I took another pass through this thread and the current repo/config behavior. The repeated theme seems to be that per-tool approval is useful as an escape hatch, but it is not a sufficient steady-state UX for large trusted MCP servers like Playwright, Chrome DevTools, Obsidian, etc.

A small MVP that seems aligned with the requests here would be a server-level default for raw MCP tools, for example:

[mcp_servers.playwright]
default_tools_approval_mode = "approve"

with existing per-tool entries continuing to override it:

[mcp_servers.playwright.tools.browser_click]
approval_mode = "prompt"

That keeps the safety model explicit: users still opt in per MCP server, and more sensitive tools can remain prompted. It also avoids configs with hundreds of generated mcp_servers.<id>.tools.<tool>.approval_mode entries, which several comments show is the current practical workaround.

One reason this shape seems consistent with the product is that app/connector config already has a similar concept: default_tools_approval_mode plus per-tool approval settings. The missing piece appears to be parity for user-configured MCP servers.

A useful acceptance test would be: configure a Playwright MCP with only the server-level default, run a flow using multiple mutating browser tools, and verify Codex does not prompt for each tool while still prompting for unrelated shell/file operations.

Per docs/contributing.md, I’m not opening an unsolicited PR, but this seems like a focused issue/RFC shape if maintainers agree with the config direction.