Skip to content

v2 web/desktop: MCP permission prompt shows only *, not the tool name #51519

Open

Description

@DamienSchreurs

Description

When an MCP tool asks for permission, the prompt in the web and desktop UI shows only *. The tool name never appears, so there is no way to tell what the agent is asking about. The TUI is fine: it labels the prompt with the action.

The shared dock (packages/app/src/session/requests/session-permission-dock.tsx) renders request.resources as the detail line. The MCP tool wrapper (packages/core/src/tool/mcp.ts) passes resources: ["*"]. The dock does read request.action, but only to look up settings.permissions.tool.<action>.description, and MCP actions have no entry, so there is no hint line either.

The v2 PR #51062 only forwards metadata and leaves resources as ["*"], so v2 still shows *.

Plugins

No response

OpenCode version

2.0.18

Steps to reproduce

  1. Configure an MCP server with a tool set to ask, e.g. { "action": "_", "resource": "", "effect": "ask" }.
  2. In the web or desktop UI, have the agent call that MCP tool.
  3. The permission prompt shows only *.

Screenshot and/or share link

Image

Operating System

macOS 15.7.9

Terminal

No response

Activity

  1. github-actions commented on Sep 26, 2026

    @github-actions
    Contributor

    This issue might be a duplicate of an existing issue. Please check:

  2. DamienSchreurs commented on Sep 26, 2026

    @DamienSchreurs
    Author

    Same bug as #19549. That one was closed by the stale bot and never fixed; none of the attempts (#19618, #24605, #32564) were merged. This is the v2 version, reproduced on 2.0.18 in the web/desktop dock. Either way is fine with me: track it here or reopen #19549.

  3. opencodejr commented on Oct 28, 2026

    @opencodejr

    Thanks for the detailed report. I can confirm this on 2.0.18, and it still happens on the latest dev (86ce19d).

    What I did:

    • Set up a small local MCP server demo with one tool, greet, and the rule { "action": "demo_*", "resource": "*", "effect": "ask" }.
    • Had a simulated model call demo_greet.

    What I saw:

    • The pending permission request is action: "demo_greet", resources: ["*"]. On dev, metadata.input is now set too (from fix(mcp): pass tool input as permission metadata #51062).
    • The TUI labels the prompt "Call tool demo_greet".
    • I rendered the web/desktop SessionPermissionDock with that same request. It shows no hint line and only *, and the tool name appears nowhere. I couldn't run the full web or desktop app here, so this check covered the dock component on its own.

    The script below reproduces the server side and prints the request. I've passed this on to the maintainers. Related: #51062 (forwards the tool input as permission metadata, but the dock doesn't show it yet).

    Reproduction script (drive.ts)
    // Repro for #51519: MCP tool permission request carries resources ["*"],
    // which is all the web/desktop permission dock renders.
    import { Effect, Stream } from "effect"
    import { Llm, OpenCodeDriver } from "opencode-drive"
    const server = "// Minimal stdio MCP server exposing one tool: \"greet\"\nimport readline from \"node:readline\"\nconst rl = readline.createInterface({ input: process.stdin })\nconst send = (m) => process.stdout.write(JSON.stringify(m) + \"\\n\")\nrl.on(\"line\", (line) => {\n  let msg; try { msg = JSON.parse(line) } catch { return }\n  if (msg.id === undefined) return\n  if (msg.method === \"initialize\")\n    return send({ jsonrpc: \"2.0\", id: msg.id, result: { protocolVersion: msg.params?.protocolVersion ?? \"2025-06-18\", capabilities: { tools: {} }, serverInfo: { name: \"demo\", version: \"1.0.0\" } } })\n  if (msg.method === \"tools/list\")\n    return send({ jsonrpc: \"2.0\", id: msg.id, result: { tools: [{ name: \"greet\", description: \"Greet someone\", inputSchema: { type: \"object\", properties: { name: { type: \"string\" } } } }] } })\n  if (msg.method === \"tools/call\")\n    return send({ jsonrpc: \"2.0\", id: msg.id, result: { content: [{ type: \"text\", text: \"Hello \" + (msg.params?.arguments?.name ?? \"?\") }] } })\n  send({ jsonrpc: \"2.0\", id: msg.id, result: {} })\n})\n"
    
    export default OpenCodeDriver.use(
      {
        ...(process.env.OC_DEV ? { opencode: { dev: process.env.OC_DEV } } : {}),
        tui: { recording: true },
        project: { git: true, files: { "mcp-server.mjs": server } },
        config: {
          mcp: { servers: { demo: { type: "local", command: ["bun", "mcp-server.mjs"], codemode: false } } },
          permissions: [{ action: "demo_*", resource: "*", effect: "ask" }],
        },
      },
      ({ ui, llm, opencode }) =>
        Effect.gen(function* () {
          yield* Effect.sleep(process.env.OC_DEV ? 15000 : 3000)
          let called = false
          yield* llm.serve((request) => {
            const body = JSON.stringify(request)
            // Title-generation requests just get a title.
            if (body.includes("You name conversations")) return Stream.make(Llm.text("MCP greet"))
            const first = !called
            called = true
            return first
              ? Stream.make(Llm.toolCall({ index: 0, id: "call_1", name: "demo_greet", input: { name: "Damien" } }))
              : Stream.make(Llm.text("done"))
          })
          yield* ui.submit("Greet Damien using the demo MCP tool")
          let requests = yield* opencode.permission.request.list().pipe(Effect.orDie)
          for (let i = 0; i < 30 && requests.data.length === 0; i++) {
            yield* Effect.sleep(1000)
            requests = yield* opencode.permission.request.list().pipe(Effect.orDie)
          }
          yield* Effect.sleep(1000)
          yield* Effect.log("PENDING PERMISSION REQUESTS: " + JSON.stringify(requests, null, 2))
          yield* ui.screenshot("tui-permission")
        }),
    )

    Run it with opencode-drive: opencode-drive run ./drive.ts. It drives opencode from your PATH; set OC_DEV to the path of an OpenCode checkout to run that from source instead.

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

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions