local-model
Provides integration with Ollama, enabling coding tasks to be delegated to local models running on an Ollama server through a configurable coding-agent CLI.
This server does not currently have a deployable release on Glama. Follow the repository's setup instructions to install and configure it for your MCP client, including any required credentials and local dependencies.
local-model-mcp
MCP (Model Context Protocol) server that lets Claude Code (or any MCP client)
delegate coding tasks to a local model through a coding-agent CLI — pointed at
whatever OpenAI-compatible endpoint you run: a local vLLM instance, Ollama, or
any other self-hosted server. Ships configured for the
Qwen Code CLI by default (WORKER_CLI_BIN=qwen),
but the model behind MODEL_BASE_URL — and the CLI binary itself — are both
configurable.
Architecture
┌─────────────────────────┐
│ Claude Code / Claude │
│ (MCP Client) │
└────────────┬────────────┘
│ MCP Protocol
▼
┌─────────────────────────┐
│ local-model-mcp │
│ (this project) │
│ │
│ - execute_task │
│ - health_check │
│ - execute_task_with_ │
│ context │
└────────────┬────────────┘
│ subprocess + env vars
▼
┌─────────────────────────┐
│ Worker CLI │
│ (WORKER_CLI_BIN, │
│ default: qwen) │
│ │
│ http://YOUR_SERVER: │
│ 8002/v1 │
└─────────────────────────┘Related MCP server: Claude Code Manager WAN
Installation
Prerequisites
Python 3.9+
The worker CLI in
PATH(Qwen Code CLI by default)An OpenAI-compatible model server reachable at some
http://HOST:PORT/v1
Install
./install.shThis will:
Copy
.env.exampleto.env(edit it to point at your server)Create a Python virtual environment and install dependencies
Register the server as
local-modelin~/.claude/claude.jsonif presentIf
WORKER_CLI_BINis the default (qwen), patch~/.qwen/settings.jsonwith the write/exec permissions the CLI needs to run unattended
Configure
Edit .env:
MODEL_BASE_URL=http://your-server:8002/v1
MODEL_NAME=/models/your-model # optional — auto-detected from the server if unset
WORKER_CLI_BIN=qwen # optional — set to a different coding-agent CLI if not using Qwen CodeVerify:
.venv/bin/python check_env.pyRegister manually (if install.sh didn't find claude.json)
Add to .mcp.json or ~/.claude/claude.json:
{
"mcpServers": {
"local-model": {
"command": "local-model-mcp/.venv/bin/python",
"args": ["local-model-mcp/server.py"]
}
}
}.env in this directory supplies MODEL_BASE_URL/MODEL_NAME/WORKER_CLI_BIN if you don't set them in the client's own env block — either works, the client's env block wins.
Tools
health_check()
Check if the model server is online.
Returns:
{
"status": "online" | "offline",
"models": ["model1", "model2"],
"url": "http://YOUR_SERVER:8002/v1",
"error": "optional error message"
}Usage:
result = await client.call_tool("health_check", {})
if result["status"] == "online":
# Safe to proceed with execute_taskexecute_task(task, working_dir, files?)
Execute a task on the model.
Args:
task(str): Detailed task descriptionworking_dir(str): Absolute path to working directory (must exist)files(list[str], optional): File paths to mention in context
Returns:
{
"status": "success" | "error" | "timeout",
"return_code": 0,
"stdout": "task output",
"stderr": "error output if any",
"files_changed": ["src/file.py", "tests/test.py"],
"warning": "null or warning string if the model responded but made no file changes"
}Return fields:
files_changed— Git-based diff of files modified or created (snapshots dirty state before and after execution). Requires a git repo; returns empty list for non-git projects.warning— Non-null when the run succeeded butfiles_changedis empty on a previously clean repo. Usually the task description was too vague. Rephrase with explicit file paths and concrete instructions.
Example:
result = await client.call_tool("execute_task", {
"task": "Write unit tests for add() function in src/utils.py",
"working_dir": "/Users/you/workspace/myproject",
"files": ["src/utils.py"]
})execute_task_with_context(task, working_dir, context_files)
Execute task with file contents prepended to the prompt.
Args:
task(str): Task descriptionworking_dir(str): Absolute path to project rootcontext_files(list[str]): File paths to read and include as context
Returns:
Same as execute_task
Example:
result = await client.call_tool("execute_task_with_context", {
"task": "Add error handling to the request function",
"working_dir": "/Users/you/workspace/api",
"context_files": [
"/Users/you/workspace/api/src/client.py",
"/Users/you/workspace/api/src/errors.py"
]
})Read-only advisors: list_workers() / ask_worker(prompt, working_dir, worker?, role?, timeout?)
Ask a local Qwen or Gemini a question about a project without letting it change anything.
role is ask (default), explore, review or plan.
Workers are defined in workers.json (copy workers.example.json; the real file is
gitignored). It is re-read on every call, so changing a host or swapping a model is one
edit, no restart:
{"default": "qwen-a", "workers": {
"qwen-a": {"kind": "qwen", "base_url": "http://host-a:8002/v1", "model": ""},
"gemini": {"kind": "agy"}}}kind: qwen— any OpenAI-compatible vLLM endpoint via the Qwen Code CLI.model: ""asks the server which id it serves (survives a relaunch on a new checkpoint).kind: agy— Gemini through the Antigravity CLI (subscription login). The plaingeminiCLI needs an API key and is not used.list_workers()shows each worker's live status and served model.
Read-only is structural, not trusted to the CLI. agy --mode plan was observed to
write files anyway, and it makes every turn produce a plan + walkthrough artifact (a
one-line read: 47 s vs 14 s), so agy now runs without it. The worker runs in a throwaway copy of working_dir (git-tracked +
untracked-not-ignored files only, 200 MB cap; submodule contents are not copied). Relative
writes land in the copy and are listed in write_attempts_discarded. The original is
fingerprinted before/after: an absolute-path write is detected, not prevented and turns
the status into VIOLATION. Always check status before relying on the answer.
Usage from Claude Code
In your prompt when invoking tools:
AVAILABLE MCP:
- local-model (health_check, execute_task, execute_task_with_context)
WORKFLOW:
1. Call health_check() → verify the model server is online
2. IF online → call execute_task() with full task details
3. IF offline → implement yourself, notify userBest Practices
Always health check first:
status = health_check() if status["status"] != "online": # Fall back to manual implementationUse absolute paths:
working_dir: Must be absolute, must existcontext_files: Should be absolute for clarity
Include full context in task string:
The model has no memory of previous calls
Explicitly list file names, requirements, constraints
Parse output carefully:
files_changeduses git snapshots (before vs after)Read full
stdoutfor detailed results
For multi-file tasks:
Use
execute_task_with_contextto pass existing codeOr include file paths in task string with full instructions
Prompt Engineering
Sandwich Instruction Pattern
Every execute_task call automatically wraps the task with a PREFIX and SUFFIX to combat "description instead of code" failures. The model is instructed to write complete, runnable code — not explanations, partial snippets, or markdown-wrapped output.
The prompt structure is:
PREFIX + [project conventions] + task + SUFFIXPREFIX:
[INSTRUCTION: You are a code-writing worker.
Write complete, runnable code only.
No descriptions or explanations instead of code.
No markdown fences around output.
Write the full file content, not partial snippets.]SUFFIX:
[REMINDER: Output only complete, runnable code.
No descriptions. No markdown fences. Full file content.]This "sandwich" approach combats the "lost in the middle" problem on long prompts — the model sees code-writing instructions both before and after the task.
Automatic Project Conventions Injection
If the working directory contains qwen-memory/project-conventions.md, its contents are automatically injected between the PREFIX and the task. This directory name is kept as-is (not generalized along with the rest of this project) so existing per-project convention files keep working without a silent migration. This lets projects define conventions once and have them applied to every call without repeating them each time.
mkdir -p /path/to/project/qwen-memory
cat > /path/to/project/qwen-memory/project-conventions.md << 'EOF'
- Use Python type hints on all function signatures
- Write docstrings using Google style
- Run black and ruff before committing
- Tests live in tests/ and use pytest
EOFThe final prompt structure when conventions exist:
PREFIX
PROJECT CONVENTIONS:
(contents of qwen-memory/project-conventions.md)
task
SUFFIXTroubleshooting
" CLI not found"
which qwen # or whatever WORKER_CLI_BIN points to
# If not in PATH, add to ~/.zshrc or ~/.bashrc:
export PATH="/path/to/qwen/bin:$PATH""Cannot connect to http://YOUR_SERVER:8002/v1"
curl http://YOUR_SERVER:8002/v1/models
# If not running, start your model server first.Task timeout (>300s)
Reduce task scope
Break into smaller tasks
Increase
EXECUTION_TIMEOUTinserver.pyif needed
Files not detected in output
files_changeduses git snapshots (before vs after the run)If the repo was already dirty beforehand, pre-existing changes are not counted
Non-git projects return an empty list
Always read full
stdoutfor file paths
Development
.venv/bin/python -m pytest tests/ # run tests
.venv/bin/python server.py # start server manually
DEBUG=true .venv/bin/python server.py # enable MCP debug loggingEnvironment Variables
Set via .env (see .env.example) or exported directly:
MODEL_BASE_URL=http://custom-host:8002/v1
MODEL_NAME=/models/custom-model
WORKER_CLI_BIN=qwenTool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
Related MCP Connectors
Shared memory MCP server for Claude Code, Codex, Gemini CLI and Cursor. Cited, editable.
Connect ChatGPT and Claude to your Mac, Windows or Linux with secure MCP remote access.
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.
Related MCP Servers
- AlicenseAqualityBmaintenanceLocal MCP server that wraps the headless Claude Code CLI as MCP tools, providing stateless access to Claude's coding capabilities through prompt-based interactions. It enables users to execute Claude Code commands with various prompt formats and structured outputs directly from MCP clients.3MIT
- FlicenseNot gradedqualityCmaintenanceEnables ISLI agents and MCP clients to dispatch natural-language coding and terminal tasks to a locally-installed Claude Code CLI, supporting both one-shot execution and persistent sessions with workspace and security controls.-
- AlicenseNot gradedqualityBmaintenanceEnables claude.ai, including free users, to act as a coding agent on your own machine, allowing file edits, shell commands, and git operations within explicitly chosen project folders. It provides a secure local MCP server exposed as a custom connector with OAuth-based consent.GPL 3.0
- AlicenseNot gradedqualityBmaintenanceEnables MCP-capable chat clients like ChatGPT, Claude, and Cursor to read, search, edit, and run commands on a local machine, including git operations and browser automation. Runs as a local daemon with workspace path jails, safety modes, checkpoints, and human-in-the-loop approval for edits and shell commands.MIT