anthropics / anthropics/claude-agent-sdk-python

SDK MCP tools unavailable when resuming with empty streaming input (regression in 0.2.140)

Aberta
#1,226 1 comentário 0 reações 0 responsáveis Ver no GitHub
bug
Linguagem predominante
Python
Estrelas
8.1k
Forks
1.3k
Métricas de merge de PRs
Métricas de PR pendentes

Descrição

Resuming a session with a pending deferred tool fails when the tool comes from an SDK MCP server and the resume passes an empty streaming input. Claude Code reports the tool as unavailable. It never re-invokes the tool. Passing a text prompt instead works.

0.2.139 works. 0.2.140 and later fail.

```python
import anyio, dataclasses, tempfile
from claude_agent_sdk import (ClaudeAgentOptions, HookMatcher, ResultMessage,
create_sdk_mcp_server, query, tool)

ALLOW = []

@tool("flux", "Read the flux", {})
async def flux(args): return {"content": [{"type": "text", "text": "41.7 gauss"}]}

async def gate(inp, tool_use_id, ctx):
dec = "allow" if ALLOW else "defer"
return {"hookSpecificOutput": {"hookEventName": "PreToolUse", "permissionDecision": dec}}

async def no_prompt():
return
yield

opts = ClaudeAgentOptions(
model="haiku", cwd=tempfile.mkdtemp(), setting_sources=[],
mcp_servers={"probe": create_sdk_mcp_server("probe", tools=[flux])},
allowed_tools=["mcp__probe__flux"],
hooks={"PreToolUse": [HookMatcher(matcher="mcp__probe__flux", hooks=[gate])]})

async def run(prompt, **kw):
async for m in query(prompt=prompt, options=dataclasses.replace(opts, **kw)):
if isinstance(m, ResultMessage): return m

async def main():
a = await run("Measure the flux.")
print("leg 1:", a.stop_reason)
ALLOW.append(True)
b = await run(no_prompt(), resume=a.session_id)
print("leg 2:", b.stop_reason, "| is_error:", b.is_error)

anyio.run(main)
```

Leg 1 defers the tool and ends with `tool_deferred`. Leg 2 resumes the session to re-invoke the deferred call. Output:

```
0.2.139 leg 2: end_turn is_error: False
0.2.140 leg 2: tool_deferred_unavailable is_error: True
```

On 0.2.140 the run also prints:

```
Task exception was never retrieved
future:
exception=CLIConnectionError('ProcessTransport is not ready for writing')>
File ".../claude_agent_sdk/_internal/query.py", line 580, in _handle_control_request
await self.transport.write(json.dumps(success_response) + "\n")
File ".../transport/subprocess_cli.py", line 1048, in write
raise CLIConnectionError("ProcessTransport is not ready for writing")
```

Claude Code logs `Deferred tool resume: tool '...' is no longer available (MCP server disconnected or tool removed)`. The failing run makes no API call. `duration_api_ms` is 0 and token usage is zero.

Other results:

- Replacing `no_prompt()` with a text prompt works on every version.
- Deferring a built-in tool such as `Read` the same way resumes correctly. Only SDK MCP tools fail.
- The Claude Code version does not matter. On 0.2.139 the resume works against CLI 2.1.232, 2.1.235 and 2.1.237. On 0.2.142 it fails against all three.

I have not confirmed the mechanism. The traceback shows the SDK failing to answer a control request from Claude Code after the input stream ends.

Environment: Claude Code 2.1.237, Python 3.13, Linux.

Guia de contribuição

Nenhum guia de contribuição indexado para este repositório

Avaliação

Esta issue ainda não foi avaliada.

Receba novas issues na sua caixa de entrada

Um resumo curto de issues do GitHub para quem está começando.