claude-code-delegate-local
It is an MCP server for delegating Claude Code subagents to alternative OpenAI/Anthropic-compatible backends while keeping the main Claude Code orchestrator session intact.
Run named
.md-defined agents on a configured backend with full tool calling (read_file,write_file,run_bash).Dispatch up to 4 independent agent tasks in parallel in one call, with optional KV-cache reuse when reusing agent names.
Route an agent to any arbitrary OpenAI/Anthropic-compatible provider by passing endpoint URL, API key, and model.
List available local agents from
~/.claude/agentswith their frontmatter metadata.Check the configured backend’s health and available models before delegating.
Control per-dispatch model, workdir, max turns, max tokens, and mode tag; auto-select turn limits for local vs cloud backends.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@claude-code-delegate-localrun the security-engineer agent on local model to review the project"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
claude-code-delegate-local
🇬🇧 English · 🇪🇸 Español
MCP server that delegates Claude Code subagents to alternative backends — local models (LM Studio, llama.cpp, Ollama, vLLM, LiteLLM), DeepSeek, MiniMax M3, GLM Coding Plan (Z.ai), AWS Bedrock, or any OpenAI/Anthropic-compatible endpoint — without losing your Claude Code orchestrator session.
Built for users who want to keep their main Claude Code session on Anthropic (Max plan or API) for orchestration, while offloading specific subagents to cheaper, faster, or HIPAA-safe local backends.
Table of contents
Related MCP server: openai-agents-mcp
What it solves
You're working with Claude Code on a project and you want to:
Send a specific subagent (e.g.,
security-engineer) to a local model to save tokens from your Max plan, or because you're handling sensitive data that can't leave your machine.Route another subagent to DeepSeek because it's 10× cheaper and faster for large tasks.
Keep your main Claude Code session exactly as it is — no swapping commands, no separate CLI, no losing the Max plan.
That's what delegate-local does. It's an MCP server you install once that exposes tools the orchestrator can invoke to route specific subagents to whatever backend you've configured.
Features
✅ Your Anthropic Max plan stays intact. No need to launch a separate CLI like
ccr codeor swap commands.✅ 3-tier agent lookup. Same command works in any project — finds
.claude/agents/<name>.mdin the project first, then.claude/skills/<name>/SKILL.md, then global~/.claude/agents/<name>.md.✅ Dual-format backend. Auto-routes to
/v1/messages(Anthropic format) or/v1/chat/completions(OpenAI format) based on model prefix. Works with DeepSeek'sreasoning_contentthinking mode out of the box.✅ Full tool calling. Delegated agents get
read_file,write_file, andrun_bashwith the same loop semantics as Claude Code's native subagents.
Quick install
Requires uv and Claude Code.
git clone https://github.com/fegone/claude-code-delegate-local.git
cd claude-code-delegate-local
uv sync
# Register as Claude Code MCP (user scope = global across projects)
claude mcp add delegate-local \
--scope user \
--env DELEGATE_LOCAL_URL=http://localhost:4000/v1/messages \
--env DELEGATE_LOCAL_KEY=your-backend-api-key \
--env DELEGATE_LOCAL_MODEL=local-qwen-3-6-35b \
-- uv run --directory $(pwd) python server.pyRestart Claude Code. The MCP exposes 4 tools (see below).
Configuration
All env vars are optional; defaults assume a LiteLLM proxy on localhost:4000.
Env var | Default | Description |
|
| Anthropic-format endpoint. For OpenAI-format models, the server auto-converts the URL to |
|
| Bearer token / API key. Sent as both |
|
| Default model alias if the caller doesn't specify one. |
| (= | Opt-in: coding agents ( |
|
| Where to look for global agent definitions. |
See docs/CONFIGURATION.md for full details and example setups with LiteLLM, llama.cpp, Ollama, DeepSeek direct, and AWS Bedrock.
Concurrency pools and failover
Each model gets a pool of six concurrent dispatches, shared across every open Claude Code
session — not per session, and not per provider. The pools are real files under
~/.cache/claude-delegate-local/slots/<bucket>/, each requiring an exclusive flock; the
kernel releases the lock if a process dies, so a crashed session leaves no phantom slots.
The bucket is chosen by longest matching prefix, so specific entries win over family ones:
Bucket | Slots | Covers |
| 6 |
|
| 6 |
|
| 6 | plain, |
| 6 |
|
| 2 | everything else local |
Variants of one model share a pool on purpose: they sit behind the same flat plan.
Override any of them with DELEGATE_CONCURRENCY_<BUCKET> (e.g.
DELEGATE_CONCURRENCY_GLM_CODING_PLAN=4).
Failover
When a pool is full, the dispatch walks a chain of equivalent models rather than failing:
glm-coding-plan-think → qwen-3-8-max → deepseek-v4-flash
deepseek-v4-flash → glm-coding-plan-think → qwen-3-8-maxFlash goes straight to Pro because Flash already bills per token — hopping to Pro does not turn a flat plan into an invoice. For the same reason DeepSeek sits last in the other chains: GLM and Qwen bill $0 against their plans, so a busy afternoon should not quietly become a bill.
Fallbacks wait only DELEGATE_FAILOVER_GRACE (default 10s) for their own slot — the point is
to find room now, not to queue four times over. A result that failed over carries
failed_over_from and model_used.
⚠️ The chain preserves the NAME of a thinking tier, not measured equivalence. GLM's
-maxdoes not reason more than-think; Qwen 3.8'sreasoning_effortdoes not scale; DeepSeek'smedium/high/maxare indistinguishable. The mapping is the best available, not a claim that the models reason alike.
Local models and Codex never fail over
local-, ornith, codex and gpt- are pinned to themselves, in both directions.
Local models run on hardware that may see regulated data; a silent hop to a cloud provider would move that data off-premise and nobody would notice, because the failure mode of an automatic fallback is that it does not announce itself. Codex bills against a ChatGPT subscription, where failing over means nothing and failing over to it burns plan quota.
The guard filters the chain itself, not just the origin, so editing FAILOVER_CHAINS later
cannot route a local model outward.
Tools exposed
Tool | Purpose |
| Run a |
| NEW v0.5.0 — Dispatch up to 4 agent tasks in parallel via |
| Run an agent on any arbitrary endpoint (DeepSeek, OpenRouter, etc.) |
| NEW — Delegate to the OpenAI Codex CLI as an autonomous agent, authenticated by the user's ChatGPT subscription (Plus/Pro) — OpenAI's official path, no API key, no proxy. Codex does its own file edits + shell in its sandbox; the tool shells out to |
| Launch one or many Codex runs without waiting; returns job ids at once. Each task: |
| Per job: |
| Dequeue a queued job or kill the process group of a running one; always ends |
| List agents found in |
| Health check + list of models available on the configured backend |
Operating Codex jobs
Rule: one worktree per job. Create git worktree add ../wt-<card> -b <card> for every card and
pass that path as workdir. Two jobs in one checkout are serialized on purpose (they would overwrite
each other and fight over index.lock); worktrees of the same repo are separate checkouts but share
the per-project cap. Integrate branches one at a time.
Ramp plan. Defaults are 8 global / 6 per project. Raise by env, one step at a time, only after a
clean block of work at the current step (few throttle retries, no auth_failed, memory fine):
DELEGATE_CODEX_MAX_CONCURRENT=12 (with MAX_PER_PROJECT=8), then 16, then 20 (MAX_PER_PROJECT=10).
Every server must run the same caps and the same DELEGATE_CODEX_STATE_DIR.
Statuses. queued (see queue_reason: global_cap, adaptive_cap, workspace_busy,
waiting_for_slot, throttle_cooldown, auth_failed) · running · done (CLI exit 0) · failed
(failure_kind: quota, throttle after 3 retries, infra, other) · timeout · cancelled ·
auth_failed (login invalid: run codex login; admission resumes by itself once auth.json
changes) · lost / killed_on_restart (owner server died). Extra fields: queued_s, retry_count,
retry_in_s, last_activity_age_s, exit_code, session_id, owner {pid, sid, alive}; the
poll response also carries account (ok / cooldown / auth_failed and the effective caps).
429 handling. codex-cli 0.159.2 does not retry direct HTTP 429s (retry_429: false), so the server
does: a throttle sets an account-wide cooldown shared by all servers (shared.json in the state dir),
honors a Retry-After-style hint if the output has one, else backs off 5/10/20/40/60 s with jitter,
and retries the job up to 3 times (the prompt is replayed from the start; session_id is recorded for
manual inspection). Three throttles in 5 minutes halve the effective caps for 10 minutes. Quota
exhaustion and auth failures are never retried.
done is not "verified". Codex exiting 0 says nothing about whether the change is correct. Run
the project's own tests in the job's worktree (or a separate runner) yourself and merge only what
passes; sandbox-restricted or skipped tests count as unverified.
Gemini por Antigravity CLI (delegate_to_gemini, submit_gemini, poll_gemini, cancel_gemini)
Mismas ideas que Codex, con el plan Google AI Pro en vez de una API key. Cada tarea ejecuta
agy -p ... --output-format json --dangerously-skip-permissions con el stdin cerrado (sin -p,
agy abre una TUI y se cuelga).
Instalar:
brew install --cask antigravity-cli, y correragyuna vez para iniciar sesion. Otra ruta:DELEGATE_AGY_BIN. Sin el binario el servidor arranca igual y las herramientas devuelven "agy binary no encontrado".effort=low(por defecto),mediumohigh, que eligengemini-3.8-flash-<effort>. Cualquier otro valor se rechaza; los modelosclaude-*ygpt-ossque listaagy modelsno se exponen.delegate_to_gemini(task, workdir, effort, timeout_s)bloquea y devuelvestatus,response,conversation_id,usage,duration_syexit_code.submit_gemini(tasks)lanza varias sin esperar,poll_gemini(ids)consulta ycancel_gemini(id)saca de la cola o mata el grupo de procesos.Topes:
DELEGATE_GEMINI_MAX_CONCURRENT(4) yDELEGATE_GEMINI_MAX_QUEUE(32), un job por workdir. El estado vive en memoria del servidor: no hay estado compartido entre sesiones como en Codex.Puerta: como
danger-full-accessde Codex, las herramientas se niegan a correr salvo conDELEGATE_GEMINI_ALLOW_DANGER=1, porqueagy -pno puede pedir permisos y corre con--dangerously-skip-permissions.Aislamiento (siempre):
agycorre dentro desandbox-execcon un perfil generado por corrida, mas su propio--sandbox. La lectura esta denegada en todo el sistema de archivos y solo se devuelve: el workdir,~/.gemini,~/Library/Keychains(solo lectura; la sesion de Google deagyvive en el llavero) y rutas de sistema:/usr,/bin,/sbin,/System,/Library/Developer,/opt/homebrew,/private/etc,/private/var/db/timezone,/private/var/foldersy/dev(cada una medida con elagyreal,python3,gitycurl)./Volumes(copias de Time Machine, discos externos),/Users,/Applications,/private/tmpy/private/var/rootno se pueden leer, ni siquiera listar. Solo se permitestat()(no contenido) en el resto del sistema y en~/Library, porquesecurityno encuentra el llavero sin eso. Escritura solo en el workdir, los temporales y las rutas de estado deagy(~/.gemini/antigravity-cli/{annotations,brain,cache,conversations,implicit,log,crashes,presence}y unos pocos archivos);~/.gemini/config(mcp_config.json),settings.json,builtinybinquedan de solo lectura. Sinexecde/usr/bin/open,osascriptni de nada en/Applications: si la sesion no se lee dentro de la jaula el job termina con "agy session not readable in the jail" y nunca abre un login. Sisandbox-execno funciona, no corre nada. Mas permisos solo se agregan midiendo con elagyreal (EXTRA_READ_PATHS).Limites conocidos:
agyobtiene su token ejecutando/usr/bin/security, asi que ese exec NO se puede negar (medido); los elementos del llavero creados consecurity add-generic-passwordsin-Tsiguen siendo legibles desde la jaula (confian en ese binario). La red de salida queda abierta (agy debe hablar con Google), asi que un archivo del workdir con instrucciones hostiles puede intentar exfiltrar lo que el workdir contiene.~/.geminiguarda las conversaciones completas.Nunca PHI ni datos de pacientes, ni en la tarea ni en ningun archivo bajo
workdir:agylee esos archivos y los sube a Google. El plan de consumidor no tiene BAA.
Operating dsh jobs (submit_dsh / poll_dsh / cancel_dsh)
Same model as the Codex jobs, for DeepSeek Harness runs inside the sandboxed, Herdr-visible launcher
(dsh-herdr.sh --cwd --model --task-file --out-dir, override with DELEGATE_DSH_LAUNCHER). Each job
reads <out-dir>/result.json (status, rc, diff_stat, summary, tokens, wall_s); the change
itself stays in the run dir (out_dir in the poll) to be reviewed and applied by hand.
submit_dsh(tasks): each task is{task, model (required), workdir='.', timeout_s=2400}. Atomic: one invalid task and nothing starts.poll_dsh(ids)returnsqueued | running | done | failed | cancelled | timeout | lost | unknown,final_responsetrimmed to ~300 words,owner.lost= the owning server died with the job queued or running.Own state and caps, separate from Codex:
DELEGATE_DSH_STATE_DIR(default~/.dsh-jobs),DELEGATE_DSH_MAX_CONCURRENT=2,DELEGATE_DSH_MAX_PER_PROJECT=2(local models share one Mac Studio),DELEGATE_DSH_MAX_QUEUE=16,DELEGATE_DSH_STAGGER_S=5. One job per checkout; use one worktree per job.Model allowlist:
DELEGATE_DSH_MODELS_FILE(default~/.config/neola-lab/dsh-models.json, example inexamples/dsh-models.json, same shape as the launcher'smodels.json). Unknown or disabled models are refused; with no file, everything is refused.Any
mimo*/xiaomi*alias is refused for automated dispatch (Xiaomi Token Plan terms forbid automation).Privacy: cloud models take code only, never PHI or real personal data.
Note on delegate_batch and sub-agents
Claude Code sub-agents launched via the native Agent/Task tool do not inherit the parent session's MCP servers. This means delegate_batch (and any other MCP tool) is only callable from the main orchestrator session. Sub-agents that need parallel local-backend dispatch should use httpx.AsyncClient + asyncio.gather directly against the LiteLLM endpoint instead. This is a Claude Code architecture constraint, not a delegate-local limitation.
3-tier agent lookup
When you call delegate_to_local_agent("webdev", ...) with a workdir, the server looks for the agent definition in this order:
<workdir>/.claude/agents/webdev.md— project agent (highest priority)<workdir>/.claude/skills/webdev/SKILL.md— project skill (alternative location)~/.claude/agents/webdev.md— global agent (fallback)
This means the same delegate call works in any project, using whichever scope owns the agent. The response includes agent_source so the orchestrator knows which one was loaded.
Dual-format backend routing
Models with these prefixes are routed to OpenAI-format /v1/chat/completions:
deepseek-*openai-*gpt-*qwen-*(external Qwen APIs — note thatlocal-qwen-*aliases route via Anthropic/v1/messages)
All other models go to Anthropic-format /v1/messages. Inside the server everything is normalized to Anthropic-style content blocks (text / tool_use / thinking) so the agent loop stays uniform.
GLM Coding Plan (Z.ai): the
glm-coding-planalias has noopenai/gpt/deepseek/qwenprefix, so it routes via Anthropic/v1/messages— which is what Z.ai's Anthropic-compatible endpoint (https://api.z.ai/api/anthropic) expects. Flat-rate subscription with automatic server-side prompt caching. In LiteLLM use the plain model codeanthropic/glm-5.2— the[1m](1M-context) suffix errors against this endpoint there; it only works when Claude Code points directly at Z.ai (seeexamples/claude-glm.sh). Setup: docs/CONFIGURATION.md.
Thinking-mode support
For models that emit reasoning_content (DeepSeek V4, OpenAI o1-style), the server preserves it as a {"type": "thinking", "thinking": "..."} content block between turns. This is required by LiteLLM and most providers — if you drop reasoning_content from the assistant message in multi-turn, the next request fails with 400 Bad Request.
max_tokens defaults to 65536 (parameter of the tool — caller can override). High default is intentional so thinking-mode models have budget for both reasoning and content output, and so large monolithic outputs (e.g., complete HTML files with embedded JS) don't get truncated. Lower it explicitly only if your backend has a stricter cap.
Example: LiteLLM proxy
A minimal litellm/config.yaml to use with this MCP:
model_list:
- model_name: local-qwen-3-6-35b
litellm_params:
model: openai/Qwen3-6-35B
api_base: http://localhost:8000/v1 # your llama.cpp / vLLM server
api_key: sk-no-key-required
- model_name: deepseek-v4-flash
litellm_params:
model: deepseek/deepseek-chat
api_key: os.environ/DEEPSEEK_API_KEY
- model_name: bedrock-sonnet-4-6
litellm_params:
model: bedrock/anthropic.claude-sonnet-4-6-20260101-v1:0
aws_region_name: us-east-1Then run litellm --config config.yaml --port 4000 and point this MCP at it.
Tested with
Backend | Model | Single-turn | Multi-turn |
LiteLLM + llama.cpp |
| ✅ | ✅ |
LiteLLM + DeepSeek API |
| ✅ | ✅ |
LiteLLM + Z.ai |
| ✅ | ✅ |
LiteLLM + AWS Bedrock |
| ✅ | ✅ |
Picking a DeepSeek tier:
deepseek-v4-flashis the default for coding and agentic work; it already reasons at high effort by default (which is why it has no-thinkvariant).deepseek-v4-prowas removed from the supported set on 2026-10-15.⚠️ Both tiers can spend their whole token budget reasoning and return nothing. The server auto-raises the default budget for them; see max_tokens troubleshooting.
Validation tasks: SQL injection review (security-engineer agent), HTML calculator (creative agent, 500-800 LOC monolithic), Pac-Man game (884 LOC monolithic single-shot).
Best practices
⚠️ If you dispatch multi-file sprints to local backends, read this first. Naive single-dispatch of 6+ files at once causes ReadTimeout at high turn counts as context saturates the slot. Splitting the work and reusing the same agent name across parallel workers can cut wall-clock time by ~60% and tokens by ~78%.
🎯 docs/BEST-PRACTICES.md — empirical thresholds for when to split work, KV-cache prefix reuse for parallel dispatches, scope-bounded prompts, estimated savings table
Further reading
📐 docs/ARCHITECTURE.md — how it works internally, diagrams, design decisions
⚙️ docs/CONFIGURATION.md — full env var reference, LiteLLM setup from scratch, how to add new providers
💡 docs/EXAMPLES.md — 7 end-to-end use cases with copy-pasteable code
🔧 docs/TROUBLESHOOTING.md — common errors, lessons learned, and a dedicated section for AI agents helping with setup
📋 examples/litellm.example.yaml — ready-to-use LiteLLM config with 9 providers (local + cloud)
🤝 CONTRIBUTING.md — how to contribute
📝 CHANGELOG.md — version history
Caveats
run_bashruns shell commands insideworkdirwithout sandboxing. Trust the agents you delegate. If you delegate to an unvetted public agent, the tool can read/write anywhere the calling user has access. There is no Docker isolation by default.Caps (v0.6.0):
read_filesupportsoffset/limit(line ranges) and returns up to ~50KB per call with line numbers and a[lines N-M of TOTAL]header — paginate large files instead of re-reading.run_bashtruncates stdout to 12KB and stderr to 4KB, timeout 120s.max_turnshard cap is 40. Long-running orchestrations should be designed as multiple delegate calls rather than one huge loop.
License
MIT. See LICENSE.
Conmutador de gateway (T09)
DELEGATE_GATEWAY decide por dónde sale el tráfico del delegate. Un solo env var para
cambiar y otro para volver: hoy el default es litellm y nada cambia.
Env var | Default | Descripción |
|
|
|
| — | Solo con |
| vacío | Base opcional para |
|
| Con |
API OpenAI de Bifrost | — | Normaliza la base de cada carril y convierte mensajes y herramientas a OpenAI, con o sin streaming; conserva las virtual keys y las cabeceras de enrutado. |
Validación de API | — | Cualquier otro valor causa error de arranque solo con |
Carriles Bifrost | — | El carril local usa |
Validación Bifrost | — | Con |
| — | Virtual key del carril local con bifrost: alias |
| — | Virtual key del carril de código con bifrost: todo lo demás (deepseek, glm, qwen, mimo…). |
Además (T09):
response_modelreal: los dos lectores SSE capturan elmodeldelmessage_start/ primer chunk y, con bifrost, las cabecerasx-bifrost-routing-info-*. Si el que contestó no es el alias pedido, el resultado del tool lleva la nota visiblefallback_note=answered_by: deepseek-flash (requested glm-5-3-flash)(hallazgo 4).DELEGATE_RESEND_REASONING(hallazgo 15):auto(default) = reenviar elreasoning_contentdel assistant previo solo adeepseek-*(que lo exige);1= a todos;0= a nadie. A los providers que lo rechazan nunca se le manda.
Avisos al terminar
Every successful submit_codex, submit_gemini and submit_dsh returns watch and watch_hint. Start the exact watch command with the Monitor tool (or Bash run_in_background) immediately. This is the only completion notification path; never rely on remembering to poll. The MCP server does not wake Claude Code on its own.
delegate-wait cx-aaa gm-bbb dsh-ccc
delegate-wait --all --timeout 1800 --json cx-aaa gm-bbbThe default emits and flushes one line per terminal job; --all waits for every job before printing. --json emits one JSON object per line. Exit codes: 0 all done, 1 any unsuccessful terminal job (including lost/restarted), 2 an id never appeared within 30 seconds, 3 watcher timeout. The first applicable timeout/grace deadline wins. Dead owners become LOST immediately. Poll interval defaults to 5 seconds (DELEGATE_WAIT_INTERVAL). All three providers use per-server snapshots under ~/.codex-jobs, ~/.gemini-jobs, ~/.dsh-jobs; use matching DELEGATE_CODEX_STATE_DIR, DELEGATE_GEMINI_STATE_DIR, DELEGATE_DSH_STATE_DIR overrides in the server and watcher if needed.
Poll results expose persist_error, warnings, and, for shortened responses, truncated: true with final_response_length (full character count). Persistence errors also go to server stderr; an unwritable state directory cannot deliver fresh snapshots to a watcher, so inspect MCP stderr/poll errors if updates stop. very_short_run means under 45 seconds; Codex empty_response still preserves the existing exit-zero done status. Gemini refuses unsafe git config with failure_kind: jail_git_config and hint run: git branch --unset-upstream; the jail stays enabled. Dead Gemini jobs are recorded as killed_on_restart on first use after restart; this means interrupted and unresumable, not proof that every child process was killed. Review the workdir before resubmitting.
Completion output replaces control/format/bidi characters and line separators with spaces, collapses whitespace, and caps text fields at 256 characters (preview 110); JSON string values, including nested values, are sanitized and capped at 4,000 characters. Persistence and runner exceptions expose only a bounded exception class, errno and canonical OS description, never exception paths or arguments.
All providers reject workdirs overlapping any provider's default or overridden job-state directory, including ancestors, descendants and symlink targets, with failure_kind: workdir_forbidden. Gemini's sandbox explicitly denies writes to these directories even beneath writable temporary roots.
Offline verification: .venv/bin/python -m pytest tests -q -p no:cacheprovider and .venv/bin/python scripts/check-completion-mutations.py (41 guard-removal mutations). tests/conftest.py isolates HOME, provider state, locks, sessions and caches at import time, before collection imports providers; private agy homes under Library/Caches/delegate-agy therefore stay in the temporary HOME. Per-test resets remain enabled. A collection-only subprocess starts with the real HOME and checks for new provider/cache entries attributed to pytest or its descendants, ignoring concurrent foreign writers. PIDs are retained at each subprocess spawn and sampled from ps -axo pid,ppid at spawn and session end; unavailable process-tree inspection warns and limits tracking to direct children. PID-less entries require a new path, a modification time after session start, and an open file owned by a test PID (lsof); closed PID-less writes cannot be attributed. No production sweep bypass is needed.
Install the watcher globally from this checkout:
uv sync --locked
uv tool install --force .
uv tool update-shell
# Open a new terminal so delegate-wait is on PATH.
delegate-wait --helpRestart Claude Code: each session loads its MCP server once. Keep the existing MCP command pointing to this checkout.
Test storage safety net
DELEGATE_TEST_ISOLATION (presence, even empty) enables a safety net against
accidental test writes to the real HOME. DELEGATE_TEST_ISOLATION_ROOT must be an
absolute path; storage resolvers validate containment and use canonical absolute
paths, including for relative overrides. Final lock components reject symlinks,
atomic snapshot writes replace rather than follow destination symlinks, and
production temporary files/directories use explicitly validated destinations.
Children inherit the guard through provider environment allowlists.
This is not a security boundary against a hostile process. Whoever controls
the startup environment or filesystem can disable it by removing
DELEGATE_TEST_ISOLATION or setting DELEGATE_TEST_ISOLATION_ROOT=/; this is
accepted by design. Closing the TOCTOU race where a concurrent attacker replaces
an intermediate directory is out of scope, as is preventing environment-based
disabling. The tests use disposable storage; they do not probe writes to real HOME.
Available Tools
5 toolsdelegate_batchA
Despacha hasta N agentes EN PARALELO en una sola llamada, usando asyncio.gather. Útil cuando el orquestador quiere ejecutar N sub-tareas independientes simultáneamente en backends que soportan paralelismo nativo (e.g., llama.cpp con --parallel 4).
USE WHEN you have multiple independent sub-tasks and your backend has parallel slots available (delegate cap = 4 = heavy-coding throughput sweet-spot; oMLX allows 8). With same agent_name reused across tasks, you also benefit from KV cache prefix reuse on the shared system prompt (~30-50% prompt-processing savings).
LIMITATION: Sub-agents launched via Claude Code's Agent/Task tool do NOT inherit parent's MCP servers, so this tool cannot be called from within a sub-agent. It only works from the main orchestrator session. Sub-agents that need parallelism should use httpx.AsyncClient + asyncio.gather directly against your LiteLLM endpoint.
| Name | Required | Description | Default |
|---|---|---|---|
| tasks | Yes | List of task dicts. Each dict has the same keys as delegate_to_local_agent's parameters: {agent_name, task, workdir?, max_turns?, model?, max_tokens?}. agent_name and task are required; rest use defaults. Hard cap MAX_BATCH_SIZE (4) tasks per call. For more, split into multiple calls or use sequential delegate_to_local_agent calls. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Discloses parallelism, batch size cap, KV cache benefits, and the sub-agent limitation. However, lacks details on error handling or behavior on partial failures.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded main purpose, but some sections (limitation, alternatives) are lengthy. Still efficient overall.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers purpose, usage, parameters, and limitations well. With output schema present, return format is not needed. Minor gaps like error behavior do not detract significantly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Only parameter 'tasks' is described beyond schema: explains it is a list of dicts with keys matching delegate_to_local_agent and a hard cap, adding value over the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it dispatches up to N agents in parallel using asyncio.gather, contrasting with the sibling delegate_to_local_agent which handles single agents.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly tells when to use (multiple independent sub-tasks with parallel slots) and when not to use (cannot be called from sub-agent), with clear alternative suggestions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delegate_to_local_agentA
Despacha un agente (cargado desde un .md con frontmatter) a un backend OpenAI/Anthropic- compatible con tool calling completo (read_file / write_file / run_bash). Devuelve resultado consolidado.
USAR cuando el usuario quiera ejecutar un agente específico en un backend alternativo (local, cloud, etc.) en vez del default del orquestador. El orquestador sigue intacto.
Para despachar VARIOS agentes en paralelo en una sola llamada, ver delegate_batch.
| Name | Required | Description | Default |
|---|---|---|---|
| task | Yes | Tarea concreta para el agente. Sé específico, el agente leerá ese prompt. | |
| model | No | Model alias as configured in your LiteLLM proxy (or direct provider). Default 'local-qwen-3-6-35b'. Override via DELEGATE_LOCAL_MODEL env var. | local-qwen-3-6-35b |
| workdir | No | Directorio de trabajo del agente (default: '.' del MCP). Recomendado pasar ruta absoluta al proyecto donde trabajará. | . |
| max_turns | No | Tope de iteraciones de tool-calling (hard cap 40). Default 0 = AUTO: 15 para backends locales (local-*, MoE-A3B con techo de ctx ~262K), 25 para backends cloud (MiniMax M3 512K, DeepSeek API, Sonnet/Opus). Pasar un valor explícito lo fuerza. Para tareas cortas conocidas: 5-10. Para review/análisis multi-archivo pesado en cloud: 25-30. | |
| agent_name | Yes | Nombre del agente sin .md. Ej: 'seo-content', 'security-engineer', 'database-optimizer'. Debe existir en ~/.claude/agents/ | |
| max_tokens | No | Tope de tokens por turno del modelo. Default = 65536, EXCEPTO si `model` termina en "-max" (p.ej. glm-coding-plan-max, deepseek-v4-pro-max) -> default sube a 150000 automático. Motivo: en deep-reasoning tiers el modelo puede gastar TODO el budget pensando y no dejar nada para la respuesta (verificado: deepseek-v4-pro-max con 32K devolvió 0 tool_calls, respuesta vacía). Pasar un valor explícito siempre gana sobre el auto-bump. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations were provided, so the description carries full burden. It discloses that the agent is loaded from a .md file with frontmatter, that tool calling includes read_file/write_file/run_bash, that the backend must be OpenAI/Anthropic-compatible, and that the orchestrator remains intact. This sufficiently informs the agent of behavioral traits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise and front-loaded with the core action. Each sentence serves a purpose: stating the action, clarifying when to use, and pointing to an alternative. No unnecessary words or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (6 parameters, output schema exists), the description covers the agent source, backend compatibility, alternative tool, and basic behavior. The presence of an output schema means return values do not need explanation. The description is complete for the agent to select and invoke correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so baseline is 3. The main description does not add additional meaning beyond what is already in the input schema parameter descriptions, which are already detailed. Therefore, no extra value is provided by the description for parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: 'Despacha un agente (cargado desde un .md con frontmatter) a un backend OpenAI/Anthropic-compatible con tool calling completo (read_file / write_file / run_bash).' It distinguishes from the sibling tool delegate_batch by specifying 'Para despachar VARIOS agentes en paralelo en una sola llamada, ver delegate_batch.'
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states when to use the tool: 'USAR cuando el usuario quiera ejecutar un agente específico en un backend alternativo (local, cloud, etc.) en vez del default del orquestador.' It also provides an exclusion by pointing to delegate_batch for multiple agents in parallel.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delegate_to_providerB
Versión genérica: despacha un agente a CUALQUIER endpoint OpenAI/Anthropic-compatible. Usar para rutear explícitamente a providers no configurados como default (DeepSeek, MiniMax, Alibaba, OpenRouter, etc.).
| Name | Required | Description | Default |
|---|---|---|---|
| task | Yes | ||
| model | Yes | Identificador del modelo (depende del provider) | |
| api_key | Yes | API key del provider | |
| workdir | No | . | |
| mode_tag | No | Tag a prepender en system prompt (default MODE:LOCAL — puede ser MODE:DEEPSEEK etc.) | MODE:LOCAL |
| max_turns | No | ||
| agent_name | Yes | ||
| max_tokens | No | ||
| provider_url | Yes | URL completa al endpoint /v1/messages (o equivalente) |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are present, so the description must disclose behavioral traits. It only states 'generic version' and the act of dispatching, but does not explain error handling, authentication requirements (beyond api_key), response format, or whether the call is synchronous/streaming.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is very short and front-loaded: one sentence defining function, one for usage. No fluff or repetition. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (9 parameters, 5 required) and generic nature, the description is too sparse. It lacks details on constructing provider_url, task format, and what the output schema contains aside from its mere existence. An agent would struggle to invoke correctly without additional manual or external knowledge.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is low (44%), and the description adds no parameter-level information. It does not explain the format of provider_url, task, agent_name, or other critical fields beyond what the schema already provides, failing to compensate for gaps.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states that the tool dispatches an agent to any OpenAI/Anthropic-compatible endpoint, and contrasts with default providers by naming alternatives (DeepSeek, MiniMax, etc.). It is specific and hints at differentiation from siblings like delegate_to_local_agent.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly instructs to use this for non-default providers, providing concrete examples. It gives clear usage context but does not explain when not to use (e.g., when default provider is sufficient) or alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_local_agentsA
Lista los agentes disponibles en ~/.claude/agents/ que pueden delegarse con delegate_to_local_agent(). Devuelve nombre, descripción (del frontmatter) y modelo declarado de cada uno.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided, so description carries full burden. It clearly states it is a listing operation with no side effects, and specifies return values. Sufficiently transparent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Single sentence conveying all necessary information without redundancy. Highly concise and front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no parameters and a clear output schema (described), the description fully covers what the tool does and returns. Complete for its simplicity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
No parameters exist, so the description adds no value beyond schema. Baseline score of 4 is appropriate as schema coverage is 100% and no extra parameter info is needed.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool lists available agents from a specific directory, mentions the sibling function for delegation, and specifies the returned fields (name, description, model). It is specific and distinguishes from siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies use when needing to know available local agents for delegation, but does not explicitly state when not to use or compare to alternatives. Sibling context helps, but explicit guidance is missing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
local_backend_statusA
Health check del backend configurado (LiteLLM proxy por default). Devuelve estado, modelos disponibles y latencia básica. Útil antes de delegar para validar que el backend está alcanzable.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It discloses that the tool is a read-only health check returning status, models, and latency, which is sufficient behavioral context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with purpose and specific outputs. No wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no parameters and a clear output schema, the description adequately covers the tool's purpose and return values. Completes the context for its role as a pre-delegation check.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Zero parameters, so no additional info needed. Schema coverage is 100% vacuously. Baseline for 0 params is 4.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it performs a health check on the backend, returning status, models, and latency. It distinguishes from sibling tools like delegation and listing agents.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly mentions it is useful before delegating to validate backend reachability. No explicit when-not-to or alternatives, but the context is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
5 tool updates
v0.6.0- First observed
delegate_batch - First observed
delegate_to_local_agent - First observed
delegate_to_provider - First observed
list_local_agents - First observed
local_backend_status
TDQS
Scored across 5 tools
Tools have distinct purposes, but delegate_to_local_agent and delegate_to_provider are both delegation variants that could be confused; descriptions clarify the difference but conceptual overlap remains.
All tool names follow a consistent snake_case pattern with clear verb_noun structure (delegate_batch, delegate_to_local_agent, list_local_agents, local_backend_status).
5 tools is a reasonable number for a focused delegation server, though it covers the core workflows without feeling overly slim.
Covers delegation, listing, and health check, but misses obvious lifecycle operations like adding/removing agents or providers, and lacks a way to stop or monitor ongoing delegations.
Related MCP Connectors
Shared memory MCP server for Claude Code, Codex, Gemini CLI and Cursor. Cited, editable.
Talk to your public-facing AI from any MCP client — Claude, ChatGPT, Cursor, Cline, Windsurf.
Real-time chat hub for AI agents — Claude Code, Cursor, Cline, Codex over MCP or REST.
One MCP endpoint for Claude, GPT & Gemini: 100+ tools + no-code connectors + agent workers.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceMCP server that lets Claude Code delegate mechanical tasks to a local LLM for summarization, classification, extraction, and drafting.10 npm15MIT
- AlicenseAqualityDmaintenanceMCP server that bridges OpenAI's Agents SDK with Claude Code, enabling web search, file search, and computer use capabilities directly in your development environment.29 npm1MIT
- AlicenseNot gradedqualityDmaintenanceMCP server that enables Claude Code to communicate with other Claude Code agents over HTTP, allowing users to ask questions about remote codebases or delegate coding tasks.MIT
- AlicenseAqualityFmaintenanceMCP server for running external coding agents as background tasks inside Claude Code. Supports multiple backends including Codex, Grok, GLM, DeepSeek, and more.7MIT