Skip to content
Conduit

mcp server

toolrush-mcp

Kill the tool-call tax in any MCP agent harness: fast read/search, warm persistent shell, batched calls. Go port of OnlyTerp/toolrush.

dhava-gautama/toolrush-mcpcommunitylistedunreviewed

Set up

Runs on your computer. Pick your agent and operating system.

This project does not publish an install method we can turn into a config. Follow the README instead.

README

synced Oct 21, 2026

ToolRush-MCP

ci Release Go Report Card License: MIT

Kill the tool-call tax — in any agent harness. A fast local tool server for Kimi Code CLI, Codex CLI, Claude Code, and anything else that speaks the Model Context Protocol.

A universal port of ToolRush (a Hermes Agent plugin, Windows/MSYS-only) — same lanes, same fail-closed philosophy, shipped as one static Go binary instead of harness-specific monkeypatching.

What you get

ToolWhat it does
fast_readIn-process file read: line-number gutter, offset/limit paging, negative offset = tail, binary sniff, BOM strip, >64MB files stream the window. Line-level mtime cache — page turns are cache hits
batch_read1–16 reads through one tool call, input order, whole-batch validated before anything runs (serial by design — measured faster than pooling on page-cache-fast storage)
fast_searchDirect rg transport — real .gitignore, real regex grammar. Pure-Go walk fallback when rg is absent. context=N (0–5) adds N lines of gutter around each hit: L-line before, L+line after. Output stops at 8MB of rg output — capped:true means total_hits is a lower bound
batch_search1–16 searches through one call, fanned out across goroutines — each op spawns its own rg process, so the batch wall time approaches the slowest op, not the sum. Input order, whole-batch validated, per-op failures isolated
fast_treeBudgeted directory listing: deterministic dirs-first alphabetical order, depth (1–10) and entry (1–5000) budgets, basename pattern filter (invalid patterns error rather than matching nothing). Skips .git, node_modules, __pycache__, .venv, target, dist, build, *_cache. Entries carry is_symlink (lstat semantics, dangling links included). No .gitignore parsing — use pattern= to narrow
warm_execOne persistent bash: cd, export, and shell state survive across calls (harness terminals spawn fresh shells per call). Per-call framing, rc + cwd read back from the shell, process-group kill on timeout, never retries a submitted command
batch_exec1–16 shell commands through one call on the warm shell, sequentially, state flowing between them
doctorLane status, versions, kill-switch state, counters

Why it matters: every MCP tool call pays a fixed transport + dispatch cost. The structural wins are persistent shell state (impossible with per-call spawns) and batching (one round trip instead of sixteen) — plus the server itself is fast enough to never be the bottleneck.

Measured performance

From bench/bench_go.py (Linux, i7-8750H, medians; your numbers will vary):

MetricPython implGo implC ping ref
startup → first reply60.3 ms2.5 ms0.9 ms
ping round trip0.034 ms0.035 ms0.019 ms
cold batch_read, 16×1000-line files31.3 ms22.9 ms—
fast_read during a 2s warm_exec2002.4 ms0.37 ms—
6 searches: batch_search (1 call) vs 6× fast_search2899.9 ms2574.6 ms vs 2714.3 ms—

The last row is 6 full-tree rg scans over /usr/share/doc (424 MB, median of 10, this i7-8750H + HDD box). The Go server fans the ops out across goroutines but wins only ~1.05x here: the scans are disk-bound, and six concurrent rg processes saturate the same spindle (raw concurrent rg outside the server measures the same 1.05x). On page-cache-hot trees or CPU-bound regexes the parallelism shows up for real; on cold HDD scans, honestly, it mostly saves the five extra RPC round trips. The Python reference runs its ops sequentially (GIL + subprocess dispatch overhead) and, as expected, ties its own 6-call loop.

The fast_read-during-warm_exec row is the architectural one: per-request goroutines mean a long shell command never head-of-line blocks the other tools. Per-call latency is kernel/transport-bound and deliberately ties — there is nothing left to win there in any language.

Install

Go (recommended):

go install github.com/dhava-gautama/toolrush-mcp@latest
# binary lands in $(go env GOPATH)/bin/toolrush-mcp

From source:

git clone https://github.com/dhava-gautama/toolrush-mcp.git
cd toolrush-mcp
CGO_ENABLED=0 go build -trimpath -ldflags="-s -w" -o toolrush-go .

Requirements: bash; rg on PATH is optional (the search lane falls back to a built-in walker without it). POSIX only (Linux/macOS).

Register with your harness

Use the binary path from the install step above ($HOME/go/bin/toolrush-mcp for go install, ./toolrush-go for source builds).

Kimi Code CLI — ~/.kimi-code/mcp.json (new sessions pick it up; /mcp to verify):

{
  "mcpServers": {
    "toolrush": {
      "command": "/home/YOU/go/bin/toolrush-mcp",
      "args": [],
      "toolTimeoutMs": 120000
    }
  }
}

Codex CLI:

codex mcp add toolrush -- /home/YOU/go/bin/toolrush-mcp

Claude Code:

claude mcp add toolrush -s user -- /home/YOU/go/bin/toolrush-mcp

Any other MCP harness: stdio server, command = the binary, no args. Newline-delimited JSON-RPC: initialize / tools/list / tools/call / ping.

Kill-switches (fail-closed)

Set any of these to 0 in the server's environment to disable a lane — a disabled lane errors clearly so the agent falls back to its native tools (TOOLRUSH_PERSIST=0 runs spawn-per-call instead, as a negative control):

TOOLRUSH_FASTLANE=0  TOOLRUSH_SEARCH=0  TOOLRUSH_PERSIST=0  TOOLRUSH_PARALLEL=0

Safety model

Read/search lanes are read-only. There is deliberately no write tool — writes belong behind your harness's own permission UI. warm_exec carries the same privileges as the harness's terminal tool; gate it with your harness's MCP approval rules. No network access, no persistence, stdout carries protocol frames only (diagnostics on stderr).

Verify / develop

python3 python/smoke.py                                   # 53 checks vs Python impl
TOOLRUSH_SERVER=./toolrush-go python3 python/smoke.py     # same 53 vs Go binary
python3 bench/bench_go.py                                 # Python vs Go vs C shootout
gcc -O2 -o bench/ping_ref bench/ping_ref.c                # C floor reference
python3 bench/bench_lang.py                               # transport floor

Layout

PathWhat
main.gothe Go server (the shipped implementation)
python/Python reference implementation (toolrush_mcp.py), the smoke suite, lane bench
bench/cross-language benchmarks + pure-C transport-floor reference

Changelog

See CHANGELOG.md.

Known limitations

Honest footguns, so you learn them here instead of in a lost hour:

  • warm_exec: a command with an unclosed quote hangs until the call timeout, then the shell is destroyed and respawned (state lost). Quote carefully.
  • warm_exec: background jobs that outlive their command (e.g. sleep 99 &) keep writing into whichever call is in flight — output attribution is best-effort. Processes that call setsid escape the timeout kill (same as any terminal).
  • Concurrent warm_exec calls from a pipelining client have no execution-order guarantee — use batch_exec for ordered sequences.
  • A background child holding the shell's output pipe delays death detection until the timeout.
  • Output caps: fast_search/batch_search stop at 8MB of rg output (see capped); warm_exec caps at 8MB (truncated).
  • fast_tree doesn't parse .gitignore (the skip list covers the common cases).
  • POSIX only; Windows untested.

Origin and license

Port of ToolRush by OnlyTerp — the Hermes-side design, kill-switch discipline, and "measured evidence or it didn't happen" methodology are theirs; the MCP universalization and Go implementation are here. Dropped in the port: Hermes byte-parity quirks and the update-survival machinery (no upstream harness to survive here). MIT — see LICENSE.

↑↓ navigate openesc close