Skip to content

feat(claude_code): APIRequest.mcp_config + disable CLI built-ins (2.0.5)#207

Merged
CocoRoF merged 1 commit into
mainfrom
feat/claude-code-mcp-wrap-foundation-2.0.5
May 19, 2026
Merged

feat(claude_code): APIRequest.mcp_config + disable CLI built-ins (2.0.5)#207
CocoRoF merged 1 commit into
mainfrom
feat/claude-code-mcp-wrap-foundation-2.0.5

Conversation

@CocoRoF
Copy link
Copy Markdown
Owner

@CocoRoF CocoRoF commented May 19, 2026

Summary

Phase-I foundation for MCP-wrapped tools on claude_code_cli sessions. Surfaces the host's tool registry to the CLI's LLM without breaking the Stage 6 → Stage 10 → Stage 16 pipeline interface.

The problem

Stage 6 with provider claude_code_cli was the lone outlier in the otherwise provider-symmetric surface: every SDK client (anthropic / openai / google / vllm) accepts APIRequest.tools and passes schemas natively to the LLM. The CLI client dropped them — the LLM saw only the CLI's built-in palette (Bash / Read / Write / Glob / ToolSearch / …) and hallucinated against it whenever the host's intent referenced a Geny custom tool. Symptom on prod: "Tool execution complete: 32 calls, 29 errors".

What this PR ships (executor side)

  • APIRequest.mcp_config: Optional[Dict[str, Any]] — per-request MCP server configuration. CLI-based backends serialize to --mcp-config <json>; SDK-based backends ignore it.
  • claude_code_argv reads request.mcp_config (precedence over the per-client kwarg). When ANY MCP config is supplied, also emits:
    • --tools "" — disable CLI's built-in tool palette so the LLM cannot hallucinate against tools the host has no executor for. Skipped when caller explicitly passed allow_tools (mixed surface support).
    • --strict-mcp-config — ignore user-level / project-level MCP config sources so the per-session bridge is the sole surface.
  • Legacy callers without any MCP config keep today's behaviour exactly.

A companion Geny PR will ship the actual MCP bridge (stdio script) + HTTP endpoint that consume this wire.

Stage interface preservation

The Stage 6 → Stage 10 → Stage 16 interface is preserved. When the CLI uses MCP to call a host tool, the call is dispatched inside the CLI's agentic loop (via the bridge → host HTTP endpoint) and the final APIResponse carries only the assistant message — no tool_use blocks for Stage 10 to dispatch. Stage 10 sees no tool_use → naturally no-ops. Stage 16 sees no pending state → naturally finishes. Memory / persona / persistence stages run identically because the canonical APIResponse shape is the same.

Anthropic API path keeps the per-iteration tool-dispatch loop; the CLI path collapses it inside one CLI invocation. Both produce identical canonical outputs.

Test plan

  • 4 new argv tests (request_mcp_config_overrides_kwarg / host_mcp_disables_cli_builtins_and_strict / host_mcp_with_explicit_allow_tools_keeps_builtins / no_mcp_no_tools_flag)
  • Full tests/llm_client/ 193/193 pass
  • Manual smoke once Geny consumer PR lands

Release

2.0.5. Migration: none — purely additive. Legacy callers' argv is byte-identical.

… (2.0.5)

Phase-I foundation for MCP-wrapped tools on claude_code_cli
sessions. Stage 6 with provider claude_code_cli was the lone
outlier in the otherwise provider-symmetric surface: every SDK
client (anthropic / openai / google / vllm) accepts the canonical
APIRequest.tools and passes schemas natively to the LLM. The CLI
client dropped them — the LLM saw only the CLI's built-in palette
(Bash / Read / Write / Glob / ToolSearch / …) and hallucinated
against it whenever the host's intent referenced a Geny custom
tool. Symptom: "Tool execution complete: 32 calls, 29 errors" on
prod VTuber sessions.

This PR ships the executor-side wire so a companion Geny PR can
synthesize a per-session MCP config that bridges the host's tool
registry to the CLI.

### Added

- APIRequest.mcp_config: Optional[Dict[str, Any]] — per-request
  MCP server configuration.

### Changed

- claude_code_argv reads request.mcp_config with precedence over
  the per-client kwarg. When ANY MCP config is supplied, the argv
  builder also emits:
    * --tools ""           — disable CLI's built-in tool palette
                             so the LLM cannot hallucinate against
                             tools the host has no executor for.
                             Skipped when caller explicitly passed
                             allow_tools (mixed surface support).
    * --strict-mcp-config  — ignore user-level / project-level MCP
                             config sources so the per-session
                             bridge is the sole surface.
- Legacy callers without any MCP config keep today's behaviour
  exactly (no flags, CLI built-ins available).

### Stage interface preservation

The Stage 6 → Stage 10 → Stage 16 interface is preserved. When
the CLI uses MCP to call a host tool, the call is dispatched
inside the CLI's agentic loop (via the bridge → host HTTP
endpoint) and the final APIResponse carries only the assistant
message — no tool_use blocks for Stage 10 to dispatch. Stage 10
sees no tool_use → naturally no-ops. Stage 16 sees no pending
state → naturally finishes. Memory / persona / persistence stages
run identically because the canonical APIResponse shape is the
same. Anthropic API path keeps the per-iteration tool-dispatch
loop; the CLI path collapses it inside one CLI invocation. Both
produce identical canonical outputs.

### Tests

- test_argv_request_mcp_config_overrides_kwarg
- test_argv_host_mcp_disables_cli_builtins_and_strict
- test_argv_host_mcp_with_explicit_allow_tools_keeps_builtins
- test_argv_no_mcp_no_tools_flag (legacy back-compat)

Full tests/llm_client/ 193/193 pass.
@CocoRoF CocoRoF merged commit 915da87 into main May 19, 2026
5 of 6 checks passed
@CocoRoF CocoRoF deleted the feat/claude-code-mcp-wrap-foundation-2.0.5 branch May 19, 2026 10:55
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.

1 participant