Skip to main content
Glama

Model-Shunt 🔀

CI Test Suite License: MIT Python 3.9+ Dependencies: 0 Website Live

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). No pip install, no virtual environment, and no npm required.

  • 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_MAX Limits: Unlike naive implementations that pass file contents as CLI arguments (capped at ~128 KB on Linux), Model-Shunt streams corpus data over stdin, 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_read payload 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 absolute N| 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-model in 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, or SHUNT_API_KEY). An api_key field 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

Model-Shunt provides a standard stdio MCP server exposing three tools:

  1. get_available_models(provider?): Discovers live models from the provider endpoint and returns recommended models for reading and code writing.

  2. bulk_read(question, file_paths, model?, provider?): Reads large or multiple files and outputs concise, structured bullets with exact line citations.

  3. 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 | bash

Manual 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 + Python

Any 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_write only operate on files inside the server's working directory (the agent workspace). Set SHUNT_ALLOWED_ROOTS (PATH-style list) to expand the sandbox.

Map-Reduce Tuning (optional)

Variable

Default

Purpose

SHUNT_MAX_DIRECT_TOKENS

200000

Payloads above this estimated size switch to map-reduce

SHUNT_CHUNK_CHARS

600000

Chunk size in characters (~150k tokens)

SHUNT_CHUNK_RETRIES

3

Retries per chunk on rate limits

SHUNT_CHUNK_RETRY_DELAY

60

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):

  1. 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 to bulk-read.

    • Targeted reads with offset and limit are allowed, preserving surgical context for code editing.

  2. Terminal Guard (check-bash-read):

    • Prevents agents from bypassing the read hook by executing commands like cat, less, or more on 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 gemini

Run Bulk Reading Analysis

./plugin/scripts/bulk-read \
  --question "How does the token refresh cycle work?" \
  --paths src/auth.py src/tokens.py \
  --auto-model

Generate 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.py

The 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 tools
bulk_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.

ParametersJSON Schema
NameRequiredDescriptionDefault
modelNoOptional model override (or 'auto' to select the best available reader model)
providerNoOptional provider override (gemini, groq, openai, deepseek, anthropic, ollama, openrouter)
questionYesThe specific question to answer about the files
file_pathsYesList of file paths to analyze

TDQS

A4.2/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
specYesDescription of what code to generate
modelNoOptional model override (or 'auto' to select the best available writer model)
providerNoOptional provider override (gemini, groq, openai, deepseek, anthropic, ollama, openrouter)
target_pathNoOptional path where generated code should be written directly on disk
reference_pathYesPath to reference file whose conventions, style, and structure should be replicated

TDQS

A3.9/5.0
Behavior3/5

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.

Conciseness5/5

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.

Completeness3/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
providerNoOptional provider to query (gemini, groq, openai, deepseek, anthropic, ollama, openrouter). Defaults to active provider.

TDQS

A3.9/5.0
Behavior3/5

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.

Conciseness5/5

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.

Completeness3/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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.

  1. 3 tool updatesv1.1.1
    • First observedbulk_read
    • First observedcode_write
    • First observedget_available_models

TDQS

A3.8/5.0

Scored across 3 tools

Disambiguation4/5

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.

Naming Consistency3/5

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.

Tool Count3/5

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.

Completeness3/5

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

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    D
    maintenance
    An 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.
    10
    1
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Serves structured code context via MCP, enabling AI agents to understand codebases with dependency graphs and significantly reduce token usage.
    13 npm
    MIT