fix(claude-code): disable built-in tools to prevent MCP tool deferral in call_with_tools#784
Merged
nicoloboschi merged 1 commit intoMar 31, 2026
Conversation
nicoloboschi
force-pushed
the
fix/claude-code-deferred-tools
branch
from
March 31, 2026 07:32
bf8a962 to
d43342b
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes flaky tool calling in
call_with_tools()when using theclaude-codeLLM provider. Follow-up to #732 and PR #733.Root Cause
When
ClaudeAgentOptionsdoesn't specifytools, Claude Code CLI loads all built-in tools (~30+ tools: Read, Write, Bash, Grep, ToolSearch, Agent, etc.) alongside the MCP tools fromhindsight_toolsserver.With this many tools loaded, the CLI defers MCP tools to save context space. Deferred tools are registered by name only — their schemas aren't loaded into the context. To use a deferred tool, Claude must first call the built-in
ToolSearchtool to load its schema.This creates a fatal interaction with
max_turns=1:ToolSearchto load schemas (1 turn spent)max_turns=1exhausted →ResultMessage(subtype="error_max_turns")tool_calls=[]→ reflect agent getstools=[none]The behavior is flaky because tool deferral depends on total context size. Sometimes MCP tools load eagerly (works), sometimes they're deferred (fails). Evidence from logs:
When deferred, stream logs show Claude calling
ToolSearchinstead of MCP tools directly:Fix
Two changes in
call_with_tools():tools=[]— Disables all built-in CLI tools. With only MCP tools registered, the CLI loads them eagerly (schemas in context). Claude calls them directly without needingToolSearch.max_turns=2— Allows the tool call + tool result round-trip. Withmax_turns=1, even when tools loaded eagerly, the single turn was consumed by the tool execution, leaving no room for additional processing.Testing
Before fix (with debug logging):
After fix:
Tested with
budget: "low"(previously always failed) — now consistently returns real data from memory bank.Environment
🤖 Generated with Claude Code
Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com