Skip to content

Claude Code

Put Claude Code behind a LazyBridge agent in either of two modes:

  • CLI modeclaude_code: hand the CLI a task, it runs its own loop, you get a result string.
  • MCP modeclaude_code_mcp: run claude mcp serve and let your agent orchestrate Claude Code's own tools (View, Edit, LS, Bash, …).

See Code Support Agent for install, the CLI-vs-MCP overview, the startup check, and timeout guidance.

CLI mode — claude_code

from lazytools.connectors.code_support import claude_code

claude_code(
    task: str,
    *,
    mode: str = "read",          # "read" | "write" | "plan"
    cwd: str | None = None,
    session_id: str | None = None,
    timeout: float = 300.0,
) -> str

Wraps claude -p "<task>" --output-format json and returns the parsed result. The JSON envelope also carries session_id, total_cost_usd, and a subtype (success | error); an error subtype is surfaced as the returned string rather than raised.

Parameter Type Default Meaning
task str The instruction for Claude Code.
mode str "read" readRead,Bash,Grep,Glob (analysis only, safe default). write → adds Write,Edit with --permission-mode acceptEdits. plan--permission-mode plan, no edits.
cwd str \| None None Working directory for the subprocess.
session_id str \| None None If set, resumes an existing session via --resume.
timeout float 300.0 Max seconds for the subprocess.
from lazybridge import Agent, LLMEngine
from lazytools.connectors.code_support import claude_code

agent = Agent(
    engine=LLMEngine("claude-opus-4-8", tool_timeout=None),
    tools=[claude_code],
)
print(agent("Analyse the auth module and flag any security issues").text())

Auth. Left to the CLI. claude_code passes no custom environment, so the Claude Code CLI uses its own on-disk login (~/.claude/.credentials.json), and the inherited environment still carries CLAUDE_CODE_OAUTH_TOKEN (the token string from claude setup-token) or ANTHROPIC_API_KEY if you set them. The tool deliberately does not synthesize CLAUDE_CODE_OAUTH_TOKEN from the JSON credential store — that env var is a token string, not the store, and overriding it would break a valid disk login.

MCP mode — claude_code_mcp

from lazytools.connectors.code_support import claude_code_mcp

claude_code_mcp(
    *,
    name: str = "claude_code",
    allow: Iterable[str] | None = None,
    deny: Iterable[str] | None = None,
    args: list[str] | None = None,
    env: dict[str, str] | None = None,
    namespace: bool = True,
    prefix: str | None = None,
    cache_tools_ttl: float | None = 60.0,
) -> MCPServer

claude mcp serve exposes Claude Code's own built-in tools to your agent: Read/View, Edit, Write, LS, Glob, Grep, Bash, and others (NotebookEdit, WebFetch, WebSearch, TodoWrite, …). Your agent calls them like any other tool; there is no Claude model in the loop — these are the raw file/shell primitives. The factory is a thin wrapper over MCP.stdio, so namespacing, lazy connect, deny-by-default filtering, and the discovery cache all apply.

Parameter Type Default Meaning
name str "claude_code" Server name and default namespace prefix (<name>.).
allow Iterable[str] \| None None fnmatch globs (against the namespaced name) to permit. allow= or deny= is required.
deny Iterable[str] \| None None fnmatch globs to block — the natural way to drop Bash/Write while keeping the rest.
args list[str] \| None None Extra CLI args appended after mcp serve.
env dict[str, str] \| None None Extra subprocess env (auth otherwise inherited).
namespace bool True Prefix every tool with <name>.. False keeps raw names.
prefix str \| None None Custom prefix instead of <name>..
cache_tools_ttl float \| None 60.0 Seconds the discovered tool list is cached; None = never expire.
from lazybridge import Agent, LLMEngine
from lazytools.connectors.code_support import claude_code_mcp

# Read-only slice: analysis tools only, no Edit/Write/Bash.
reader = claude_code_mcp(allow=["claude_code.Read", "claude_code.LS",
                                "claude_code.Glob", "claude_code.Grep"])

agent = Agent(engine=LLMEngine("claude-opus-4-8"), tools=[reader])
agent("Find every TODO in src/ and summarise them by file")

The agent now sees tools named claude_code.Read, claude_code.Glob, … and invokes them directly. A read-then-edit setup just widens the allow-list:

editor = claude_code_mcp(allow=["claude_code.Read", "claude_code.Edit",
                                "claude_code.Glob", "claude_code.Grep"])
# Or: keep everything except the dangerous shell, via deny=
safe = claude_code_mcp(deny=["claude_code.Bash"])

Your client owns confirmation

Claude's docs are explicit: when Claude Code runs as an MCP server it only exposes its toolsyour MCP client is responsible for confirming individual tool calls. There is no built-in acceptEdits/plan gate here (unlike the claude_code CLI tool). Treat Edit, Write, and especially Bash as live, unconfirmed capabilities and gate them with an allow=/deny= list (and, if needed, LazyBridge guards / human-in-the-loop).

Discovering the live tool surface

Tool names belong to the installed Claude Code version, so the factory never hardcodes them. To see what's advertised, allow everything once and inspect the agent's tool map, then tighten:

srv = claude_code_mcp(allow=["*"])
agent = Agent(engine=LLMEngine("claude-opus-4-8"), tools=[srv])
print(sorted(agent._tool_map))   # ['claude_code.Bash', 'claude_code.Edit', ...]

Troubleshooting

Symptom Cause Fix
[claude_code] CLI 'claude' not found in PATH Claude Code not installed / not on PATH Install it; verify with check_clis_available()
[claude_code] error (exit 1): … auth … No valid Claude credentials Sign in to Claude Code, or set ANTHROPIC_API_KEY
[claude_code] timeout after 300s Task longer than timeout Raise timeout=; set engine tool_timeout=None
Orphaned claude process after a run Engine tool_timeout fired before the subprocess Use tool_timeout=None, or tool_timeout > timeout
ValueError: requires an explicit allow= / deny= claude_code_mcp called without a filter Pass allow=["*"] (after auditing) or an explicit glob list
ImportError: requires the official MCP SDK MCP mode used without the extra pip install 'lazytoolkit[mcp]'

See also

  • Codex — the other code-support agent.
  • Collaboration — Claude Code + Codex working together.
  • Code Support Agent — install, modes, timeouts, startup check.
  • MCP — the connector MCP mode is built on.