Model-Shunt
Summary: This MCP server lets AI agents delegate token-heavy file analysis and boilerplate code generation to cheap/fast worker models via three tools.
get_available_models(provider?)– Discover live models from the configured provider and get recommendations for the best reader (high-context/low-cost) and writer (code-focused) models.bulk_read(question, file_paths, model?, provider?)– Read large/multiple files and get concise, structured, line-cited answers to a targeted question, saving up to ~90% of frontier-agent tokens.code_write(spec, reference_path, target_path?, model?, provider?)– Generate tests, mocks, stubs, or configs that match a reference file’s style and conventions, and optionally write the result directly to disk without consuming agent output tokens.Provider flexibility – Works with Gemini, Groq, OpenAI, DeepSeek, Anthropic, Ollama, and OpenRouter, with optional per-call model/provider overrides or
autoselection.Agent integration – Exposes these capabilities as standard MCP tools, so any MCP-compatible agent can dynamically offload tasks to cheaper worker models.
Allows Google Gemini models to be used as fast, economical worker models for bulk file analysis and boilerplate code generation.
Allows local Ollama models to serve as private, offline worker models for reading and code-writing tasks.
Allows OpenAI models to be used as worker models for delegated reading and code generation workloads.
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., "@Model-ShuntUse a worker model to summarize src/processor.py"
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.
Model-Shunt 🔀
A decoupled, zero-dependency, universal implementation of the Shunt model-routing pattern (originally conceived by Spotify Engineering).
Model-Shunt allows AI coding agents (Antigravity, Cursor, Windsurf, Claude Code, Aider, OpenHands, etc.) to delegate token-heavy I/O (bulk file reading/code analysis) and repetitive boilerplate generation (tests, mocks, stubs, configs) to fast, economical, or local worker models (Gemini 2.5 Flash, Groq/Llama, Ollama, DeepSeek, GPT-4o-mini). This cuts primary agent token consumption by up to 90% while keeping the main context window clean.
⚡ Key Highlights
Zero External Dependencies: Built with pure Python 3 standard library (
urllib,json,re,argparse). Nopip install, no virtual environment, and nonpmrequired.Agent-Agnostic: Works transparently across any AI coding agent via standard MCP (Model Context Protocol), standalone CLI scripts, or PreToolUse lifecycle hooks.
Dynamic Model Discovery & Auto-Routing: Queries the worker endpoint in real time to discover available models and automatically routes to the best model for the task:
Reader Mode (Bulk I/O): Prioritizes massive context windows and ultra-low cost (e.g.,
gemini-2.5-flash,llama-3.3-70b-versatile,gpt-4o-mini).Writer Mode (Code Generation): Prioritizes specialized coding models (e.g.,
qwen2.5-coder:latest,gemini-2.5-flash,deepseek-chat).
Bypasses Linux
ARG_MAXLimits: Unlike naive implementations that pass file contents as CLI arguments (capped at ~128 KB on Linux), Model-Shunt streams corpus data overstdin, allowing analysis of hundreds of thousands of lines without buffer overflows.Deterministic Line Numbering (
N|): Automatically prefixes every line in file blocks with its 1-based index, forcing worker models to cite verifiable, exact line numbers instead of hallucinating locations.Binary File Protection: Inspects byte headers to reject binary files (PDFs, images, compiled objects) before sending them to the LLM.
Network Resilience: Automatic exponential backoff retries for rate limits (HTTP 429) and transient server errors (HTTP 503/502), with configurable timeouts and token limits.
Map-Reduce for Oversized Corpora: When a
bulk_readpayload exceeds the direct limit (SHUNT_MAX_DIRECT_TOKENS, default ~200k tokens), Model-Shunt automatically splits the corpus into chunks, maps the question over each chunk (preserving absoluteN|line numbers), and reduces the extracts into one cited answer. Giant single-line files (minified JSON/JS) are sliced by characters with explicit position markers. Rate-limit pacing waits out provider quota windows instead of failing.
Related MCP server: token-pilot
📁 Repository Structure
model-shunt/
├── src/model_shunt/
│ ├── worker.py # Universal LLM worker engine with model discovery (zero-deps)
│ └── server.py # Stdio MCP server exposing routing tools
├── bin/model-shunt.js # npm/npx launcher shim (requires local Python 3)
├── plugin/
│ ├── .claude-plugin/ # Plugin manifest for hook-compatible agents
│ ├── hooks/ # PreToolUse interceptor hooks (check-file-size, check-bash-read)
│ ├── scripts/ # Executable streaming CLIs (bulk-read, code-write)
│ └── skills/ # Agent skill manifests (/bulk-reader, /code-writer)
├── pyproject.toml # PyPI packaging (uvx / pip install)
├── package.json # npm packaging (npx)
├── config.example.json # Configuration template
├── test_shunt.py # Automated test suite
└── .gitignore # Credential and cache protection⚙️ Configuration
Configure your worker model via environment variables or a config.json file (placed in ~/.config/model-shunt/config.json or in the project root):
Using config.json
{
"provider": "gemini",
"model": "auto",
"timeout": 90,
"max_tokens": 8192
}Tip: Setting
"model": "auto"(or passing--auto-modelin the CLI) will automatically inspect the provider's active models and pick the optimal one for reading vs writing.
Security: Do not put your API key in
config.json— use environment variables instead (e.g.GEMINI_API_KEY,GROQ_API_KEY, orSHUNT_API_KEY). Anapi_keyfield exists as a last-resort fallback, but keeping secrets out of files is strongly recommended.
Using Environment Variables
# Google Gemini (Recommended: 1M token context, high speed, ultra-low cost)
export SHUNT_PROVIDER="gemini"
export GEMINI_API_KEY="your-api-key"
# Groq (Ultra-low latency inference)
export SHUNT_PROVIDER="groq"
export GROQ_API_KEY="your-api-key"
# Ollama (100% private, local, and free)
export SHUNT_PROVIDER="ollama"
export SHUNT_BASE_URL="http://localhost:11434/v1"
# OpenAI / DeepSeek / OpenRouter / Anthropic
export SHUNT_PROVIDER="deepseek"
export DEEPSEEK_API_KEY="your-api-key"🛠️ Usage Modes
Mode 1: Universal MCP Server (Recommended)
Model-Shunt provides a standard stdio MCP server exposing three tools:
get_available_models(provider?): Discovers live models from the provider endpoint and returns recommended models for reading and code writing.bulk_read(question, file_paths, model?, provider?): Reads large or multiple files and outputs concise, structured bullets with exact line citations.code_write(spec, reference_path, target_path?, model?, provider?): Replicates patterns, styling, and conventions from a reference file and writes generated code directly to disk without consuming frontier agent output tokens.
Installation
MCP Registry name: mcp-name: io.github.yasmanycastillo/model-shunt
Universal one-liner (detects uv / pip / pipx / npm, installs the model-shunt command, and registers it with Claude Code if present):
curl -fsSL https://yasmanycastillo.github.io/model-shunt/install.sh | bashManual alternatives:
claude mcp add model-shunt -- uvx model-shunt # if you have uv
claude mcp add model-shunt -- npx -y model-shunt # if you have Node + PythonAny MCP client (Cursor, Windsurf, Antigravity, Claude Desktop, etc.) — add to its MCP settings. No clone, no absolute paths:
{
"mcpServers": {
"model-shunt": {
"command": "uvx",
"args": ["model-shunt"],
"env": {
"SHUNT_PROVIDER": "gemini",
"SHUNT_MODEL": "auto",
"GEMINI_API_KEY": "your-api-key"
}
}
}
}Fallback (offline / no uv / no npx): run straight from a clone with Python 3.9+ — replace
"command"/"args"with"command": "python3", "args": ["/absolute/path/to/model-shunt/src/model_shunt/server.py"].
Security: by default
bulk_read/code_writeonly operate on files inside the server's working directory (the agent workspace). SetSHUNT_ALLOWED_ROOTS(PATH-style list) to expand the sandbox.
Map-Reduce Tuning (optional)
Variable | Default | Purpose |
|
| Payloads above this estimated size switch to map-reduce |
|
| Chunk size in characters (~150k tokens) |
|
| Retries per chunk on rate limits |
|
| Seconds to wait out a provider quota window (free-tier TPM) |
Mode 2: PreToolUse Interceptor Hooks
For agents supporting pre-execution hooks (e.g., Claude Code, custom agent loops):
File Read Interceptor (
check-file-size):If the agent attempts a whole-file read on a file exceeding the threshold (default: 350 lines, configurable via
SHUNT_MIN_LINES), the hook blocks the call and instructs the agent to delegate tobulk-read.Targeted reads with
offsetandlimitare allowed, preserving surgical context for code editing.
Terminal Guard (
check-bash-read):Prevents agents from bypassing the read hook by executing commands like
cat,less, ormoreon large files directly in the terminal context.
Mode 3: Standalone CLI & Scripts
You can also use Model-Shunt directly from the command line or from agent bash sessions:
Discover Available Models & Recommendations
python3 src/model_shunt/worker.py --list-models --provider geminiRun Bulk Reading Analysis
./plugin/scripts/bulk-read \
--question "How does the token refresh cycle work?" \
--paths src/auth.py src/tokens.py \
--auto-modelGenerate Boilerplate Directly to Disk
./plugin/scripts/code-write \
--spec "Create unit tests for the BillingService covering charge and refund" \
--reference tests/test_user.py \
--target tests/test_billing.py \
--auto-model🧪 Verification
Run the built-in test suite to verify your environment:
python3 test_shunt.pyThe test suite validates:
Configuration resolution, fallback cascades, and model selection.
Binary file detection and rejection.
Hook decisions (surgical reads allowed, large file reads blocked, bash flag parsing).
MCP stdio protocol compliance and tool execution.
CLI discovery flags.
📄 License
MIT. Inspired by Spotify Engineering's Shunt architecture.
Available Tools
3 toolsbulk_readA
Reads multiple or large files and answers a targeted question using a cheap, fast worker model (e.g. Gemini Flash, Groq, Ollama). Saves ~90% tokens by returning only structured bullet points.
| Name | Required | Description | Default |
|---|---|---|---|
| model | No | Optional model override (or 'auto' to select the best available reader model) | |
| provider | No | Optional provider override (gemini, groq, openai, deepseek, anthropic, ollama, openrouter) | |
| question | Yes | The specific question to answer about the files | |
| file_paths | Yes | List of file paths to analyze |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden and does well: it discloses use of a cheap/fast worker model, ~90% token savings, and structured bullet-point output. It could mention accuracy/fidelity tradeoffs or failure behavior, but the core behavior is 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?
Two concise sentences with key info front-loaded: what it reads, what it answers, and the major benefit. No filler or redundancy.
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?
No output schema exists, but the description specifies output format (structured bullet points) and the token-saving tradeoff. It omits edge-case details like acceptable file types, size limits, or failure modes, but is adequate for a straightforward read-and-summarize tool.
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 100%, so the baseline is 3. The description adds light context for 'question' (targeted) and 'file_paths' (multiple or large), but does not provide new parameter-level syntax or constraints beyond 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 states a specific verb ('Reads'), target resource ('multiple or large files'), and purpose ('answers a targeted question'). It clearly differentiates from siblings like code_write and get_available_models by describing a read/analyze operation.
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?
It gives clear context for when to use: multiple or large files with a targeted question, implying a cost/speed benefit over full reads. It does not explicitly state when not to use or name alternatives, but siblings are not close alternatives, so the implied guidance is sufficient.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
code_writeA
Generates boilerplate code (tests, mocks, stubs, configs) matching the patterns of a reference file. Can write directly to disk without consuming frontier output tokens.
| Name | Required | Description | Default |
|---|---|---|---|
| spec | Yes | Description of what code to generate | |
| model | No | Optional model override (or 'auto' to select the best available writer model) | |
| provider | No | Optional provider override (gemini, groq, openai, deepseek, anthropic, ollama, openrouter) | |
| target_path | No | Optional path where generated code should be written directly on disk | |
| reference_path | Yes | Path to reference file whose conventions, style, and structure should be replicated |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full disclosure burden. It usefully reveals that the tool can write directly to disk and bypasses frontier token consumption, but it does not disclose potential overwrites, permission requirements, or what happens when target_path is omitted. Some behavioral context is present, but important side-effect risks remain unmentioned.
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, no filler, with the core purpose first and the key differentiator second. Every clause adds value: what is generated, how, and a side benefit that matters for tool selection.
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?
For a tool with 5 parameters and no output schema, the description is reasonably complete, but it leaves notable gaps: the default behavior when target_path is absent, whether existing files are overwritten, and how generated code is returned when not writing to disk. These are material to correct invocation and not covered elsewhere.
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 the baseline is 3. The description does not add much beyond the schema, though it reinforces that reference_path drives style replication and target_path enables disk writes. Since the schema already documents all five parameters, no significant compensation 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 states a specific verb ('Generates') and resource ('boilerplate code') plus the defining mechanism ('matching the patterns of a reference file'). It is clearly distinct from sibling tools bulk_read and get_available_models, leaving no ambiguity about the tool's function.
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 clearly implies the intended context: generating boilerplate while referencing an existing file, and offers a concrete benefit ('without consuming frontier output tokens'). It does not explicitly name alternatives or exclusions, but the use case is transparent enough that an agent can decide when to invoke it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_available_modelsA
Discovers active models from the worker provider and recommends the best model for reading (high context / low cost) and writing (code intelligence). Enables calling agents to delegate dynamically to the best model.
| Name | Required | Description | Default |
|---|---|---|---|
| provider | No | Optional provider to query (gemini, groq, openai, deepseek, anthropic, ollama, openrouter). Defaults to active provider. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description must disclose behavioral traits. It states that the tool 'discovers' and 'recommends', implying a read-only operation, but does not explicitly confirm it is non-destructive or describe side effects. It also does not clarify the output format (e.g., a single recommendation vs. a list) or how the 'best' model is determined beyond the reading/writing criteria. This is a moderate gap.
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 two concise sentences, front-loaded with the primary action ('Discovers active models') and then the secondary purpose. There is no wasted verbiage, and the key information is presented efficiently.
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?
While the tool is simple (one optional parameter, no output schema), the description does not explain what the tool returns or how the agent should use the recommendation. It gives context about the intended use (reading and writing) but omits details about the response structure, which could leave an agent uncertain about the next steps. Given the lack of output schema, the description should carry more of this burden.
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 100%, so the 'provider' parameter is already fully described in the schema, including the list of valid providers and the default behavior. The description does not add additional parameter-level meaning beyond what the schema provides, so the baseline score of 3 is appropriate.
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: discovering active models and recommending the best one for reading and writing tasks. It distinguishes itself from sibling tools (bulk_read, code_write) by focusing on model selection rather than performing the read/write operations themselves. The verb 'Discovers' and resource 'active models' are specific and unambiguous.
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 when to use this tool—when an agent needs to delegate to the best model—but it does not explicitly state when NOT to use it or mention alternatives. It provides clear context about its role in model selection but lacks explicit exclusions. Given the sibling tools are actions, the distinction is implicit rather than spelled out.
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.
3 tool updates
v1.1.1- First observed
bulk_read - First observed
code_write - First observed
get_available_models
TDQS
Scored across 3 tools
The three tools have distinct purposes: bulk_read handles file reading and summarization, code_write handles code generation, and get_available_models handles model discovery. There is minor potential confusion between bulk_read and code_write since both involve file operations, but their core functions are clearly separated.
Tool names use a mix of conventions: bulk_read and code_write follow a noun_verb pattern, while get_available_models follows a verb_adjective_noun pattern. The naming is readable and descriptive, but the inconsistent verb placement (bulk_read vs get_available_models) creates minor inconsistency.
Three tools is on the low end but appropriate for a focused utility server that handles delegated reading, writing, and model selection. The count feels slightly thin for a server that could benefit from additional tools like a direct file write or model configuration tool, but it is not unreasonable.
The server covers the core workflow of reading files, generating code, and selecting models, but there are notable gaps. There is no tool for direct file writing (code_write writes to disk but only for boilerplate), no tool for updating existing code, and no way to configure or manage the worker provider beyond model discovery.
Maintenance
Related MCP Connectors
Persistent memory and cross-session learning for AI coding assistants (hosted remote MCP).
A paid remote MCP for OpenAI Codex agent coordination MCP, built to return verdicts, receipts, usage
OCR, transcription, file extraction, and image generation for AI agents via MCP.
- DazbenchOAuthapp.dazbench
Task management your AI agents can actually run. One line becomes a context-ready task over MCP.
Related MCP Servers
- AlicenseAqualityDmaintenanceAn MCP server that offloads bulk coding tasks to local LLMs, allowing Claude Code to delegate repetitive work like boilerplate generation and code polishing while preserving its context for complex reasoning.101MIT
- AlicenseAqualityCmaintenanceMCP server that reduces token consumption in AI coding assistants by up to 90% via structural reads, PreToolUse hooks, and tp-\* subagents.25189 npm5MIT
- FlicenseNot gradedqualityCmaintenanceEnables AI agents to access a codebase context, select relevant files, and route queries to the appropriate AI model based on complexity, all through an MCP interface.-
- AlicenseNot gradedqualityDmaintenanceServes structured code context via MCP, enabling AI agents to understand codebases with dependency graphs and significantly reduce token usage.13 npmMIT