anthropics / anthropics/claude-code

[BUG] Embedded claude-code (Claude Desktop / Cowork) declares elicitation capability but never renders server-initiated elicitations — calls hang until tool timeout

Offen
#88,901 2 Kommentare 2 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen
area:cowork area:mcp bug platform:macos
Vorherrschende Sprache
Python
Sterne
145k
Forks
23.1k
PR-Merge-Kennzahlen
PR-Kennzahlen ausstehend

Beschreibung

### Preflight Checklist

- [x] I have searched [existing issues](https://github.com/anthropics/claude-code/issues?q=is%3Aissue%20state%3Aopen%20label%3Abug) and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code

### What's Wrong?

## Summary

When claude-code runs as the embedded agent runtime inside the Claude Desktop app (Cowork cloud sessions), its MCP client declares the `elicitation` capability at `initialize`. However, when an MCP server sends `elicitation/create` on that session, the form is **accepted but never rendered anywhere** — no UI appears in the Desktop app, no prompt reaches the user. The elicitation is only resolved (with `cancel`) when the originating `tools/call` dies at the client's 60-second tool timeout and the connection tears down.

The result: any MCP server that legitimately uses elicitations (per the declared capability) hangs every affected tool call for a full 60s and then fails, with no signal to the server that the form was never displayed.

## Environment

- Claude Desktop app: `Claude 1.34493.1 (255293) 2026-08-21T02:05:20.000Z` on `MacOS 26.5.2`
- Session type: Cowork (cloud session; agent runtime is the Claude Agent SDK / claude-code lineage)
- MCP server: remote Streamable HTTP server (an MCP gateway proxying Stripe's MCP), connected as a claude.ai connector

## What the client declares

The Desktop app opens **two separate MCP sessions** to the same server, each with its own credentials and capability set (confirmed via server-side logging of `initialize`):

```
client=Anthropic/ClaudeAI elicit_form=false
client=claude-code elicit_form=true ← carries all tools/call traffic
```

The `claude-code` leg — the one that actually issues `tools/call` — truthfully identifies itself and declares elicitation support. The declaration appears to be static (inherited from the standalone CLI, where forms render in the terminal) rather than conditional on the embedding actually having a surface to render forms.

## Observed timeline (server-side logs, 2026-08-22 UTC)

```
22:06:09 Anthropic/ClaudeAI initialize session=01a02b82 elicit_form=false
22:06:26 tools/call arrives on session=01a02910 (claude-code leg, elicit_form=true)
22:06:31 elicitation relayed → accepted by client, no error returned
22:07:30 elicitation resolved {"dcsn":"cancel"} (~64s — at tool-call teardown)
```

## Actual behavior

The capability is declared, the elicitation request is accepted without error, no form is ever displayed, and the request is cancelled only after the originating tool call has already failed on timeout. From the server's perspective this is indistinguishable, byte-for-byte on the wire, from a client that is rendering the form while a slow human reads it — there is no error and no "displayed" acknowledgment in the protocol to key off.

## Impact

- Every MCP server that uses server-initiated elicitations against Claude Desktop / Cowork sessions experiences a guaranteed 60s hang followed by a failed tool call — the declared capability makes servers *choose* the broken path.
- Servers cannot detect or mitigate this from the handshake: the session is honestly identified, the capability truthfully reflects the software's ability (in its standalone context), and the wire behavior is identical to the working case until after the failure.
- Human-in-the-loop / approval-gateway servers are disproportionately affected, since elicitation is the protocol's intended mechanism for exactly that flow.

### What Should Happen?

One of:

- The elicitation form is rendered to the user in the Desktop app UI (which already renders its own interactive permission prompts, so a surface exists); **or**
- The embedded client does **not** declare the `elicitation` capability when running headless inside Desktop/Cowork, so servers can fall back to their non-elicitation flows (deep-link approvals, out-of-band confirmation, etc.).

### Error Messages/Logs

```shell

```

### Steps to Reproduce

1. Connect an MCP server that responds to a `tools/call` with a server-initiated `elicitation/create` (e.g. any server implementing human-approval flows per the declared capability) to Claude Desktop / a Cowork session.
2. From the Cowork session, invoke a tool that triggers the elicitation.
3. Observe: no form or prompt appears anywhere in the Desktop app UI.
4. After ~60 seconds, the tool call fails client-side with:
`MCP server "" tool "" timed out after 60s`
5. Server-side, the elicitation receives a `cancel` response only at teardown.

### Claude Model

None

### Is this a regression?

I don't know

### Last Working Version

_No response_

### Claude Code Version

Claude 1.34493.1 (255293)

### Platform

Anthropic API

### Operating System

macOS

### Terminal/Shell

iTerm2

### Additional Information

## Suggested fix

Either wire `elicitation/create` from the embedded claude-code runtime to the Desktop app's existing interactive-prompt UI, or gate the capability declaration on the embedding context (declare it only when a rendering surface is actually attached). The second option is a one-line-shaped fix that immediately unbreaks servers, and the first can follow.

## Notes

- The standalone claude-code CLI's elicitation support (since v2.1.76) works as documented; this issue is specifically about the embedded/Desktop composition.
- Happy to provide full server-side traces (initialize payloads, JWT-bound capability snapshots, per-request timing) on request.

Beitragsleitfaden

Für dieses Repository ist kein Beitragsleitfaden indexiert

Rechercherichtung

Start by tracing the embedded runtime's initialize capability declaration and its handling of elicitation/create during tools/call. Reproduce the Cowork flow with an eliciting MCP server; done means the form is rendered in Desktop/Cowork or the embedded session omits elicitation capability and no longer hangs for the 60-second timeout.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Bewertung

Tech-Stack
macos
Bereich
api, desktop
Issue-Typ
Bug
Schwierigkeit
4/5
Geschätzter Aufwand
3-5 Tage
Aktivitätsstatus
Aktiv
Klarheit
Größtenteils klar
Anfängerfreundlichkeit
38/100

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.