localagents
This MCP server lets you discover/configure local model endpoints and delegate coding or text tasks to agents running on local models.
List configured endpoints, live health, served models, and model-pool availability (
list_models).Get instructions to bring up an unavailable model (
request_model).Register or update models and inference endpoints in the config (
register_model,register_endpoint).Launch a headless Claude Code agent on a local model with a task brief, model/endpoint/cwd, optional git-worktree isolation, blocking wait, permission/tool/turn/timeout controls, and session resume (
run_agent).Monitor and manage delegated jobs: wait for completion, check status, list jobs, tail a transcript, and cancel (
wait_job,job_status,list_jobs,job_log,cancel_job).Run cheap one-shot local completions without tools or an agent loop (
local_complete).
Utilizes git worktrees and diff tracking to isolate agent jobs from the main working directory, ensuring that results are reviewable by Claude Code as a diff and managed within a standard version control workflow.
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., "@localagents Use the local agent to add a --json flag to the CLI and cover it in tests."
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.
localagents
Hand Claude Code's grunt work to a model running on your own hardware.
localagents is an MCP server that gives Claude Code a run_agent tool. Each call
starts a full headless Claude Code session — same tools, same CLAUDE.md, same
working tree — except its API traffic goes to a llama.cpp or vLLM server you run
instead of to Anthropic. Claude writes the brief and checks the result. The local
model does the work, and the Anthropic tokens go where Claude is actually needed.
A 27B Qwen on one GPU can handle "add a CLI for this module and tests to match" on its own, while Opus does the design instead of watching pytest. Two local agents can build the two halves of a package in parallel against an agreed interface.
It comes with a web monitor for the servers and the jobs running on them.
How it works
Claude Code (your session)
│ MCP: run_agent(task, model=...)
▼
localagents ── spawns ──▶ headless `claude` (Agent SDK)
│ │ ANTHROPIC_BASE_URL
│ ▼
└──── in-process shim ◀────┘ normalises requests, logs them,
│ translates backend errors
▼
llama-server / vllm (/v1/messages, on your machine or your LAN)Pointing ANTHROPIC_BASE_URL at a local server almost works by itself. localagents
adds three things on top. The config is a list of servers. The model each one is
serving, the real context window and how many slots are busy are read from the server
on every call. You start and stop models yourself. A shim between Claude Code and the
backend mediates the requests, reports the real context window and translates overflow
errors (what the shim does). Every result is recorded in one SQLite
database, so Claude can read a job after the work is completed.
Related MCP server: lmstudio-mcp
Quick start
You need Python 3.12+, uv, Claude Code (the Agent
SDK bundles its own claude binary, so nothing else to install), and a server that
speaks Anthropic's /v1/messages: llama.cpp's llama-server, Strata, or vLLM. The
model has to be able to drive Claude Code — solid native tool calling and a context
window of 128k or more per request. Qwen3.8-27B works well. Smaller windows work but
compact constantly; see Context windows.
Install it. Editable, so edits in the checkout take effect:
git clone https://github.com/ccebelenski/localagents.git && cd localagents uv tool install -e . # puts `localagents` on PATHTell it where your servers are. Copy the example and edit it (the file is gitignored). It lists servers and their kind; which model is loaded on each is discovered at call time. See Backends for starting each kind and Config for the file:
cp models.example.yaml models.yamlRegister the MCP server with Claude Code. User scope means every project gets it; the server inherits the cwd of the Claude Code session that launched it, so
run_agentdefaults to that project's tree:claude mcp add --scope user local -- localagents --config "$PWD/models.yaml"To keep it to one project instead, put this in that project's
.mcp.json:{"mcpServers": {"local": {"command": "localagents", "args": ["--config", "/path/to/models.yaml"]}}}MCP servers load at startup: restart Claude Code, or
/mcpand reconnect. The same applies after everygit pullof this repo — a running server keeps the code it started with until you reconnect.Shorten the auto-background delay.
run_agentblocks until the job ends, and Claude Code only moves a blocking MCP call to a background task afterCLAUDE_CODE_MCP_AUTO_BACKGROUND_MSmilliseconds — two minutes by default, per agent you launch. Ten seconds is about right;list_modelsand the other quick calls still return inline:{"env": {"CLAUDE_CODE_MCP_AUTO_BACKGROUND_MS": "10000"}}Install the
local-agentsubagent. Jobs then show up as agents, and it covers the cases where auto-backgrounding is off (see Using it):mkdir -p ~/.claude/agents && ln -s "$PWD/agents/local-agent.md" ~/.claude/agents/It names the server's tools as
mcp__local__*; if you registered the server under a name other thanlocal, copy the file instead and fix itstools:line.Optionally, the status line.
localagents statuslineprints the running jobs for your status line script; see Status line.Run a job. Start a model on one of your servers, then ask Claude:
Use the local agent to add a
--jsonflag to the CLI and cover it in the tests.Claude calls
list_models, picks a served model, and runsrun_agentwith the brief. If nothing suitable is up it asks you to start something. Which model that is, is your call; the config does not name one, and anything you leave running may get used.
localagents monitor opens the Monitor at http://127.0.0.1:8765/ when you
want to watch. The tools, the relay subagent, the status line and where a job's record
lives are in docs/using.md.
Backends
An endpoint is anything that serves Anthropic's /v1/messages and lists its models
at /v1/models. Beyond that, what localagents can see depends on the backend and
on how you start it. The backend: key in models.yaml picks the probe.
localagents reads | llama.cpp | Strata | vLLM |
served model ids |
|
|
|
context window per request |
|
|
|
slot or request occupancy ( |
|
|
|
server counters (per-job cache hit and throughput, the monitor's speed tiles) |
|
|
|
cache fields in each response's | always | always | needs |
GPU, VRAM, temperature, power | — |
| — |
Nothing here is required for a job to run; a figure the server doesn't expose is left
out of list_models and shows as a dash in the status line and the monitor. The two
flags in bold are the ones that get forgotten.
llama.cpp
llama-server -hf <repo>:<quant> -c 131072 --metricsThe flag defaults below are quoted from llama-server --help as of build b11913
(November 2026); check yours, the defaults have moved before.
--jinja— "whether to use jinja template engine for chat (default: enabled)". Tool calling needs it; leave it on.--slots/--no-slots— "expose slots monitoring endpoint (default: enabled)". With/slotson,list_modelsshows{total, busy, free}so Claude knows whether a second agent will run now or queue.--metrics— "enable prometheus compatible metrics endpoint (default: disabled)". With it on, each job records prompt tokens processed vs. cached, the cache hit ratio and prompt and generation tok/s, and the monitor's speed and cache tiles have data. The counters are server-wide, so overlapping jobs share the delta.-c N/--ctx-size Nand-np N/--parallel N— the window localagents reports is the per-slot windown_ctxfrom/props. Without unified KV (--kv-unified, "default: enabled if number of slots is auto") that is-cdivided by the slot count. Give each slot 128k or more.--reasoning onfor thinking models; the default,auto, detects it from the template.--api-key KEY— put the same key in the endpoint'sapi_key:; see Config.
Strata
A llama.cpp-compatible server; mark it backend: strata. Its /slots and /metrics
are always on and /metrics is JSON (cumulative totals, queue depth and the GPU
figures), so no flags are needed: list_models shows {total, busy, free} plus
requests_waiting, jobs get the same cache and throughput record as on llama.cpp, and
the monitor draws its hardware tiles. Marked llama.cpp it still works, but without
occupancy or per-job metrics, and list_models says so in a hint. Strata counts
max_tokens against the window instead of clamping it, so it refuses a request
earlier than llama-server would; the shim translates that refusal, or set
"fit_max_tokens": true in its strata-<model>.json to clamp.
vLLM
vllm serve <model> --served-model-name <alias> \
--enable-auto-tool-choice --tool-call-parser <parser> \
--enable-prompt-tokens-detailsFrom the vLLM CLI reference:
--enable-auto-tool-choice— "Enable auto tool choice for supported models. Use--tool-call-parserto specify which parser to use." DefaultFalse. Both are required for tool calling; the parser depends on the model.--enable-prompt-tokens-details— "If set to True, enable prompt_tokens_details in usage." DefaultFalse. Without it vLLM's Anthropic-shaped responses carry no cache fields: the request tables' reused column is blank and the prefill rate is an upper bound (the cell's title says so).--served-model-name— the idlist_modelsshows andrun_agent(model=...)matches;--max-model-lenis the window localagents reports.
The Anthropic /v1/messages endpoint and the Prometheus /metrics endpoint need no
flag. Sessions are started with CLAUDE_CODE_ATTRIBUTION_HEADER=0 on every backend,
because on vLLM the per-request attribution hash defeats prefix caching.
Other
backend: other probes /v1/models and, if it answers, /props for a window.
Without a window the session is told nothing and Claude Code assumes 200k, so only
use it for a server whose window really is that large.
Whatever the backend, the first turn of any job costs about 20k tokens of prompt on a cold slot (system prompt plus tool schemas), ~10 s on a 27B. Everything after that is a cache hit plus the delta.
Monitor
localagents monitor # http://127.0.0.1:8765/, opens in your browser
localagents monitor --port 9000 --config ~/.config/localagents/models.yamlOne process probes every endpoint in models.yaml into the shared database and serves
a page of them and the jobs running on them: a card per host, a table of recent jobs,
a timeline, and a page per endpoint and per job. Flags: --port, --host (default
127.0.0.1; the page has no authentication), --db, --config, --no-collect (serve
the database without probing) and --no-open. It stops on Ctrl-C. tools/monitor.sh start|status|log|stop keeps it running in the background from a checkout.
Its settings are an optional monitor: section in models.yaml:
monitor:
port: 8765
attention_hours: 24 # an endpoint seen up within this window and down now is an alert; older is dormant
retention_days: 7 # probe rows older than this are deleted (job rows never are)
refresh_s: 5 # at most one snapshot push per this many seconds (max 3600)
# db: /path/to/localagents.dbThe flags in detail, what the page shows, the smoke test and the JSON routes are in docs/monitor.md.
Config: models.yaml
Start from models.example.yaml. It's re-read on every call, so edits take effect
immediately, and the server never rewrites it — register_endpoint writes to a
sidecar models.local.yaml that is merged on top. Both the MCP server and the monitor
find it the same way: --config, else LOCALAGENTS_CONFIG, else ./models.yaml in the
current directory (so a project can carry its own), else
~/.config/localagents/models.yaml.
endpoints:
llamacpp:
base_url: http://127.0.0.1:8080
backend: llama.cpp
gpu-server:
base_url: http://gpu-server.lan:8000
backend: vllm
host: gpu-serverendpoints are places that serve /v1/messages, and that is all the file holds; which
model a server is serving is found by probing it. Order is priority: with no model
named, the first endpoint that is up and serving something wins. backend
(llama.cpp, vllm, strata, other) selects the probe; host groups endpoints
under one card in the monitor; env adds environment variables to sessions that run
against that endpoint. api_key is sent on every call to that endpoint (as both
x-api-key and Authorization: Bearer). It stays in the MCP server: the delegated
session is given the placeholder local and the shim swaps the real key in, so an
agent's env or Bash never sees it.
run_agent(model=...) takes a served id, a glob, or a fuzzy name (qwen3.8-27b finds
unsloth/Qwen3.8-27B-GGUF:UD-Q4_K_XL); endpoint= pins a server. Both are only needed
when more than one thing is up. An optional defaults: section holds model (a
standing preference in the same syntax), permission_mode (acceptEdits),
allowed_tools and disallowed_tools, setting_sources, max_turns (60),
timeout_s (1800), probe_timeout_s (2.5), job_retention_days (7), the debugging
switches log_events and dump_requests, and system_prompt_append, a suffix telling
the agent it's a delegate and how to report back. monitor: is the monitor's own
section, above.
Further reading
docs/using.md — the tools, the
local-agentrelay, the status line, job records and the database.docs/monitor.md — the monitor's flags, the page, the smoke test and the routes.
docs/shim.md — what the shim rewrites and why, and how a session is kept inside the real context window.
CONTRIBUTING.md — running from a checkout, the tests, and a seeded database for looking at the monitor without servers.
License
MIT. See LICENSE.
Copyright © 2026 Chris Cebelenski
Available Tools
11 toolscancel_jobB
Cancel a running job (kills the headless Claude session).
Inputs: job_id (required). Returns: object
job_logB
Tail of a job's human-readable transcript (assistant text, tool calls, results).
Inputs: job_id (required), tail_lines. Returns: object
job_statusB
Current status, last activity, files touched, and result (if finished) of a job.
Inputs: job_id (required). Returns: object
list_jobsA
List jobs from this server session (newest last).
Inputs: include_finished. Returns: result
list_modelsA
List configured endpoints (with live health + what they're serving now) and the model pool.
Pool entries that are currently reachable are marked `available: true` with the endpoint name
and the served id. Unavailable ones are the menu to ask the user for (by name, on `host`).
Inputs: no named parameters. Returns: object
local_completeA
One-shot completion on a local model, no tools, no agent loop. Cheap offload for summaries, drafts, classification, translation, boilerplate. Returns the text.
Inputs: prompt (required), model, system, endpoint, +2 more. Returns: object
register_endpointC
Add or update an inference endpoint (persisted to models.yaml) and probe it.
`base_url` is the server root that exposes `/v1/messages`, e.g. `http://127.0.0.1:8080`.
`backend` is one of llama.cpp | vllm | ollama | other (informational).
Inputs: name (required), base_url (required), host, notes, +1 more. Returns: object
register_modelA
Add or update a model in the pool (persisted to models.yaml).
Only `name` is required: it is fuzzy-matched against served ids (alphanumerics, case-folded,
substring), so `qwen3.8-27b` finds `unsloth/Qwen3.8-27B-GGUF:UD-Q4_K_XL`. `host` and `notes`
are what gets relayed when asking the user to bring it up. The rest are overrides:
`served_name` (exact id or glob) when fuzzy matching is ambiguous, `endpoint` to prefer one,
`context` as a fallback window when the backend doesn't report one, `bring_up` a start command
(goes stale quickly; usually leave empty).
Inputs: name (required), host, tags, notes, +4 more. Returns: object
request_modelA
What to relay to the user to bring up a model that is not currently running.
Returns the pool entry's `host`/`notes` (and a start command only if one is on file). If the
model is already up, says so instead.
Inputs: model (required). Returns: object
run_agentA
Delegate a task to an agent on a local model. Returns a job id immediately.
The agent is a headless Claude Code session (Read/Edit/Write/Glob/Grep/Bash, project
CLAUDE.md, same working tree) whose API calls go to the local endpoint. Write the task like a
brief for a capable but junior engineer: what to do, where, how to verify, and what to report.
Args:
task: The brief. Be explicit; local models follow less implicit context than Claude.
model: Pool name (see list_models) or a served model id/glob. Default from models.yaml.
endpoint: Force a specific endpoint; with no `model`, uses whatever it is serving.
cwd: Working directory (default: this server's cwd, i.e. the current project).
isolation: "none" (work in cwd, like a normal subagent) or "worktree" (fresh git worktree
on branch local-agent/<job>; kept only if the agent changed something, reported in
job.worktree with a diffstat). Use worktree for risky/large edits you want to review as a diff.
wait_s: If > 0, block up to this many seconds and return the result when done (else job id).
permission_mode: acceptEdits (default) | bypassPermissions | default | plan.
max_turns: Cap on agent turns (default from models.yaml).
allowed_tools: Override auto-approved tools.
system_prompt_append: Extra instructions appended to the Claude Code system prompt.
resume_job: Continue a previous job's session (same model) with `task` as the next message.
timeout_s: Wall-clock cap for the job.
Inputs: task (required), cwd, model, wait_s, +8 more. Returns: object
wait_jobA
Block up to timeout_s seconds for a job to finish; returns its status/result either way.
Inputs: job_id (required), timeout_s. Returns: object
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 11 tools
Most tools target distinct resources and actions: job lifecycle (run_agent, job_status, job_log, wait_job, cancel_job, list_jobs) and model/endpoint management (list_models, request_model, register_model, register_endpoint) are clearly separated. The main overlap risk is between wait_job and job_status, both returning status/result, but blocking vs non-blocking behavior distinguishes them.
The naming mostly follows a clear verb_noun pattern (cancel_job, list_models, register_model, run_agent, wait_job, list_jobs). Minor deviations exist with job_log, job_status, and local_complete, which use noun-first or adjective-verb constructions but are still readable and predictable.
11 tools is well-scoped for a local agent orchestration server. Each tool covers a distinct operational concern, and none feel redundant or superfluous.
The core domain is well covered: job creation, waiting, status, logs, cancellation, listing, plus model pool and endpoint registration and a one-shot completion fallback. Minor gaps include no explicit unregister/delete tool for models or endpoints, but these are not major blockers for typical workflows.
Maintenance
Related MCP Connectors
Add any agent you deploy on ibl.ai to Claude Code, Cursor or Claude Desktop and talk to it there.
Work on your own computers from Claude or ChatGPT: run commands, edit and search files.
Reduce your AI bills by up to 99% locally: focused code, warm prompt caches & zero secret leaks.
Connect ChatGPT, Claude, Cursor or VS Code to your Windows PC: files, terminal, browser, apps.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables Claude to delegate coding tasks to local Ollama models, reducing API token usage by up to 98.75% while leveraging local compute resources. Supports code generation, review, refactoring, and file analysis with Claude providing oversight and quality assurance.518 npm26AGPL 3.0
- AlicenseNot gradedqualityDmaintenanceEnables Claude Code to delegate mechanical tasks (summaries, boilerplate, reformatting) to local models running in LM Studio.1MIT
- AlicenseAqualityDmaintenanceEnables Claude Code to offload routine code generation and text processing tasks to a local Ollama LLM, saving Cloud API tokens and costs with automatic model selection and security features.11867 npm3Apache 2.0
- AlicenseNot gradedqualityBmaintenanceEnables Claude Code to hand off bulk, mechanical, read-heavy tasks to a local model, including agentic loops that can read, write, and run commands sandboxed at zero cloud token cost.MIT