Skip to content

permissions: asks from MCP tools inside Code Mode never surface in the TUI, execute hangs until user interrupt #51223

Description

@rissanssi

Summary

Permission asks raised by MCP tools invoked from inside Code Mode (execute) never render in the TUI. The execute call blocks indefinitely on the invisible ask, and the next user message (or Esc) aborts it with {"type":"aborted","message":"Tool execution interrupted"}. This silently deadlocks agent↔user workflows. Direct (non-Code-Mode) tool calls show their permission dialogs normally.

Environment

  • opencode version: 2.0.16
  • OS: Linux 7.2.6-1-omarchy-rc3 (x64, Arch-based Omarchy)
  • Terminal: ghostty (TERM=xterm-ghostty, COLORTERM=truecolor)
  • Shell: /bin/bash
  • Install/channel: latest (v2.0.16, background service via opencode serve --service)
  • Active plugins: superpowers (git+https://github.com/obra/superpowers.git)
  • MCP: two local stdio servers (a custom FastMCP Python server, desktop-commander)

Reproduction

  1. Configure an MCP tool to require an ask, e.g. in opencode.json:
    { "permissions": [ { "action": "hyprland_*", "resource": "*", "effect": "ask" } ] }
  2. In a session, call that tool from Code Mode:
    await tools.hyprland.clipboard_copy({ text: "hello" })
  3. No permission dialog appears anywhere in the TUI.
  4. The execute call hangs indefinitely (observed 5–44 minutes).
  5. Type any new message (or press Esc) → the tool result becomes:
    {"error":{"type":"aborted","message":"Tool execution interrupted"}}

Expected Behavior

The permission ask renders in the TUI like asks for direct tool calls, so the user can approve/deny and the Code Mode call proceeds.

Actual Behavior

  • No ask is ever displayed; the model believes the tool call is running while the user sees nothing. Both sides wait on each other.
  • A pending ask eventually exceeds the MCP request timeout in some cases: on v1.18.32→v2 era data we also captured MCP error -32001: Request timed out (~60 s) for an unanswered ask.
  • Additional quirks observed in the same timeline (may be the same root cause):
    • Editing opencode.json permissions mid-session fires config.updated (seen in the log), but the running session still hangs the newly-allowed tool — permission rules are only effective for sessions started after the change.
    • An "Allow always" answer is stored project-scoped (row in the permission table with the project id). A long-running session that belongs to the legacy global project never receives that grant, so its Code Mode calls keep asking (and hanging) forever.

Additional Context

Evidence that the hang is the invisible ask (not the MCP server):

  • A config-allowed tool called via Code Mode returns in 31 ms (tools.hyprland.list_windows()), so Code Mode → MCP plumbing and permission allow-rules work.
  • A hung call completed at 18:28:53 — the exact timestamp an hyprland_clipboard_copy allow row was written to the permission table — i.e. it had been blocked on the ask for 278 s and was released by the grant.
  • Reproduced twice in one session after a config change was confirmed applied (config.updated in the server log 4 s before the second hang).
  • The server log shows message=asking entries for direct tool-call asks (which users answer normally), but no asking entries for the Code Mode hangs.

Full investigation report with timeline available on request.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions