anthropics / anthropics/claude-agent-sdk-python

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

Abierto
#1,226 1 comentario 0 reacciones 0 asignados Ver en GitHub
bug
Lenguaje dominante
Python
Estrellas
8.1k
Forks
1.3k
Métricas de merge de PR
Métricas de PR pendientes

Descripción

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.

Guía de contribución

No hay ninguna guía de contribución indexada para este repositorio

Evaluación

Este issue todavía no se ha evaluado.

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.