Skip to content

fix(claude-code): disable built-in tools to prevent MCP tool deferral in call_with_tools#784

Merged
nicoloboschi merged 1 commit into
vectorize-io:mainfrom
mkremnev:fix/claude-code-deferred-tools
Mar 31, 2026
Merged

fix(claude-code): disable built-in tools to prevent MCP tool deferral in call_with_tools#784
nicoloboschi merged 1 commit into
vectorize-io:mainfrom
mkremnev:fix/claude-code-deferred-tools

Conversation

@mkremnev

Copy link
Copy Markdown
Contributor

Summary

Fixes flaky tool calling in call_with_tools() when using the claude-code LLM provider. Follow-up to #732 and PR #733.

Root Cause

When ClaudeAgentOptions doesn't specify tools, Claude Code CLI loads all built-in tools (~30+ tools: Read, Write, Bash, Grep, ToolSearch, Agent, etc.) alongside the MCP tools from hindsight_tools server.

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 ToolSearch tool to load its schema.

This creates a fatal interaction with max_turns=1:

  1. Claude sees MCP tools are deferred → calls ToolSearch to load schemas (1 turn spent)
  2. max_turns=1 exhausted → ResultMessage(subtype="error_max_turns")
  3. No actual MCP tool call happens → tool_calls=[] → reflect agent gets tools=[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:

# Same query, same session — sometimes works, sometimes doesn't:
17:17:38 tools=[search_mental_models, search_observations]  ← WORKS (eager)
17:32:05 tools=[none]                                       ← FAILS (deferred)
17:38:09 tools=[search_mental_models, search_observations, recall]  ← WORKS
17:38:30 tools=[none]                                       ← FAILS

When deferred, stream logs show Claude calling ToolSearch instead of MCP tools directly:

[claude-code-stream] ToolUseBlock: name=ToolSearch,
  input={'query': 'select:mcp__hindsight_tools__search_mental_models,...'}
[claude-code-stream] ResultMessage: subtype=error_max_turns, result=None

Fix

Two changes in call_with_tools():

  1. 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 needing ToolSearch.

  2. max_turns=2 — Allows the tool call + tool result round-trip. With max_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):

[claude-code-stream] ToolUseBlock: name=ToolSearch  ← wasted on schema lookup
[claude-code-stream] ResultMessage: error_max_turns

After fix:

[claude-code-stream] ToolUseBlock: name=mcp__hindsight_tools__search_mental_models  ← direct call!
[claude-code-stream] ToolUseBlock: name=mcp__hindsight_tools__search_observations
[claude-code-stream] ToolUseBlock: name=mcp__hindsight_tools__recall
[claude-code-stream] ToolUseBlock: name=mcp__hindsight_tools__done  ← success
[claude-code-stream] ResultMessage: subtype=success

Tested with budget: "low" (previously always failed) — now consistently returns real data from memory bank.

Environment

  • hindsight-api-slim v0.4.21
  • Claude Code CLI v2.1.x
  • claude-agent-sdk (Python)
  • macOS arm64

🤖 Generated with Claude Code

Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com

@nicoloboschi
nicoloboschi force-pushed the fix/claude-code-deferred-tools branch from bf8a962 to d43342b Compare March 31, 2026 07:32

@nicoloboschi nicoloboschi left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@nicoloboschi
nicoloboschi merged commit fa82efc into vectorize-io:main Mar 31, 2026
69 of 89 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants