[BUG] form-mode MCP elicitation auto-declines in interactive TUI — server-initiated form is treated as "print mode"

Open 💬 5 comments Opened May 25, 2026 by Evgenas

Preflight Checklist

  • [x] I have searched existing issues — closest matches are #48164 (URL-mode, different mode) and #51785 (docs about print/SDK mode). This is a distinct bug: form-mode elicitation auto-declines even in interactive TUI, after the v2.1.117 print/SDK fix.
  • [x] This is a single bug report
  • [x] I am using the latest version of Claude Code (2.1.144)

What's Wrong?

Claude Code 2.1.144, running interactively (TUI, human at the keyboard), receives a perfectly valid elicitation/create request with mode: "form" from a connected MCP server during a tool call — and auto-declines without ever rendering a dialog. Claude Code's own MCP debug log labels the situation "Elicitation request received in print mode", even though there is no -p/--print/headless flag in play.

The docs at https://code.claude.com/docs/en/mcp#respond-to-mcp-elicitation-requests state:

Claude Code displays an interactive dialog and passes your response back to the server. No configuration is required on your side: elicitation dialogs appear automatically when a server requests them.

In practice no dialog appears, the tool call returns the server-side "elicitation declined" error, and there is no way for the user to grant feedback through native MCP — only the server's chat-fallback path works.

Setup

  • Claude Code: 2.1.144 (Claude Code)
  • Platform: macOS Darwin 24.6.0
  • Invocation: interactive TUI session (claude started normally, no --print, no Agent SDK)
  • MCP server: Orcho MCP v1.27.1 — but the bug reproduces with any MCP server that sends elicitation/create with mode: "form" during a tool call. A minimal stdio probe using the official mcp Python SDK is attached below as a smoke comparison.
  • Server-side capability advertisement (from server's initialize request payload): elicitation.form capability is registered via the FastMCP Python SDK; the server only attempts ctx.elicit(...) when the client's initialize capabilities include elicitation.form. So the server entered the elicitation branch — meaning Claude Code advertised the capability to the server.

Reproduction

  1. Connect Claude Code to an MCP server that exposes a tool which, when called without an optional argument, requests it via elicitation/create with mode: "form" (the Orcho orcho_phase_handoff_decide retry_feedback flow is a real-world example).
  2. Run that tool from the TUI without supplying the optional argument, so the server-side elicitation path triggers.
  3. Observe: tool call fails immediately, no dialog appears.
  4. Inspect ~/Library/Caches/claude-cli-nodejs/<project>/mcp-logs-<server>/*.jsonl for the most recent session.

Smoke comparison — same server, same args, generic Python MCP client with elicitation handler:

# /tmp/probe.py — generic MCP client that handles the same elicitation/create
async def elicit_handler(ctx, params):
    return mcp_types.ElicitResult(
        action="accept",
        content={"feedback": "test feedback"},
    )

async with ClientSession(read, write, elicitation_callback=elicit_handler) as session:
    await session.initialize()
    decide = await session.call_tool("orcho_phase_handoff_decide", arguments={...})
    # Returns successfully with feedback persisted.

That run succeeds end-to-end. The exact same server binary, called from Claude Code TUI, fails with auto-decline.

Observed Log Evidence

From Claude Code's MCP debug log (2026-05-25T22-01-19-486Z.jsonl), exact line on receipt of the server request:

{
  "debug": "Elicitation request received in print mode: {\"method\":\"elicitation/create\",\"params\":{\"mode\":\"form\",\"message\":\"Explain what the reviewer should reconsider…\",\"requestedSchema\":{\"type\":\"object\",\"properties\":{\"feedback\":{\"type\":\"string\",\"title\":\"Feedback\",\"description\":\"…\",\"minLength\":1}},\"required\":[\"feedback\"]}}}",
  "timestamp": "2026-05-25T22:01:57.807Z",
  "sessionId": "f328d477-2d6b-48a8-8c71-5b6df9af68da",
  "cwd": "/Users/smartgamma/www/orcho"
}

Immediately followed by the tool-error frame (server-side error, after Claude Code returned action != "accept"):

{
  "error": "Error executing tool orcho_phase_handoff_decide: retry_feedback requires feedback. Native MCP elicitation was decline by the client; ask the user for feedback in chat and retry with args.feedback.",
  "timestamp": "2026-05-25T22:01:57.837Z"
}

The 30 ms gap between the two lines confirms no interactive prompt was shown — the round-trip happened entirely inside the MCP client.

Expected Behavior

Per the docs, an interactive TUI session should render a form dialog for the user (the JSON Schema is well-formed with a single string feedback field, minLength: 1), collect input, and return it as {action: "accept", content: {feedback: "<user text>"}}.

Actual Behavior

  • No dialog shown.
  • Claude Code internally labels the request as "print mode" — even though TUI is active and the user is present.
  • Client auto-responds with a non-accept action (looks like decline from the server-side error wording).
  • The tool call fails; server's documented chat-fallback path becomes the only option.

Hypothesis

Mid-tool-call elicitation arriving inside an assistant turn is being routed through the same code path as --print mode, where there is no UI surface to render a dialog. The v2.1.117 fix mentioned in #51785 addressed auto-cancelling during print/SDK connection setup, but the auto-declining-mid-turn case in TUI still seems to fall through to the headless branch.

Impact

High for MCP server authors who want to use the documented mid-tool elicitation feature. Currently every form-mode elicitation issued during a tool call has to be paired with a manual chat-fallback path, doubling implementation work and breaking the "no configuration required on your side" promise in the docs.

Workaround

Server-side: ship a chat-fallback (server returns a clear error with retry instructions, client/agent asks the user via normal chat tools like AskUserQuestion, then retries the same tool call with the argument supplied). Functional but adds boilerplate to every server.

Related Issues

  • #48164 — URL-mode elicitation unsupported (different mode, similar shape)
  • #51785 — Docs missing print/SDK guidance (different scope: that issue is about documenting print/SDK behavior; this one is that TUI itself behaves as if it were print mode)
  • #56243 — Cowork-specific elicitation cancelled (closed/duplicate, different surface)

View original on GitHub ↗

This issue has 5 comments on GitHub. Read the full discussion on GitHub ↗