dsh-tool-guardian
Fronts stdio MCP servers with three router tools (list_capabilities, describe_tool, call_tool) so schemas load on demand instead of riding every request; shapes every tool result through a deterministic output ladder that archives the original first (retrieve_spill reads it back); prices tool groups
Install
dsh plugin --profile web add dsh-tool-guardian
Sandbox test results
| Stage | Result |
|---|---|
| 1 install | ✓ |
| 2 list | ✓ |
| 3 mount | ✓ |
| 4 boot | — |
Four stages run in an isolated sandbox: install (network on) → list → mount → boot (last three with no network).
README
<h1 align="center">Tool Guardian</h1>
<p align="center"><b>Seven MCP servers for 1,084 tokens instead of 20,005 — and tool results that stop flooding the window.</b></p>
<p align="center">One MCP server in front of all your others. Tested with <b>Claude Code, OpenCode, Cline and Continue</b> (one scripted-model turn per client, see <a href="#works-with">Works with</a>); Claude Desktop, Cursor and other stdio MCP clients: expected, not yet tested.</p>
<p align="center">
<a href="https://github.com/LuminariSoftwares/tool-guardian/actions/workflows/test.yml"><img alt="tests" src="https://github.com/LuminariSoftwares/tool-guardian/actions/workflows/test.yml/badge.svg?branch=main"></a>
<a href="https://github.com/LuminariSoftwares/tool-guardian/actions/workflows/privacy.yml"><img alt="privacy" src="https://github.com/LuminariSoftwares/tool-guardian/actions/workflows/privacy.yml/badge.svg?branch=main"></a>
<img alt="License: MIT" src="https://img.shields.io/badge/license-MIT-yellow.svg">
<img alt="Python 3.9+" src="https://img.shields.io/badge/python-3.9%2B-blue.svg">
<img alt="Dependencies: none" src="https://img.shields.io/badge/python%20deps-none-2ea44f.svg">
<img alt="MCP server" src="https://img.shields.io/badge/MCP-server-6f42c1.svg">
<a href="https://hub.xerj.org/contributors/LuminariSoftwares"><img alt="XERJ Corpus Hub contributor" src="https://hub.xerj.org/contributors/LuminariSoftwares/badge.svg"></a>
<a href="https://glama.ai/mcp/servers/LuminariSoftwares/tool-guardian"><img alt="tool-guardian MCP server – quality and maintenance score on Glama" src="https://glama.ai/mcp/servers/LuminariSoftwares/tool-guardian/badges/score.svg"></a>
</p>
mcp-name: io.github.LuminariSoftwares/tool-guardian
The headline is this repo's bench, run against the recorded tools/list answers of seven public MCP servers (no network, no model; abridged where marked):
$ python bench/bench_tokens.py # Tool-Guardian Token Benchmark Token counting method: estimate:chars/3.5 | server | tools | tokens (full schemas) | ... | **Total** | **95** | **20005** | **Every request:** 20005 tokens of tool schemas without tool-guardian, 1084 with it (94.6% less).
<p align="center">
<a href="#quick-start-60-seconds">Quick start</a> ·
<a href="#works-with">Works with</a> ·
<a href="#deepseek-harness-results">DeepSeek Harness</a> ·
<a href="#install-both-deepseek-harness-about-5-minutes">Install both</a> ·
<a href="docs/first-5-minutes.md">First 5 minutes</a> ·
<a href="#why-this-exists">Why</a> ·
<a href="#two-ways-to-run-it">Two ways to run it</a> ·
<a href="#architecture">Architecture</a> ·
<a href="#install">Install</a> ·
<a href="#see-what-it-saves">Measure it</a> ·
<a href="#it-keeps-tool-results-small-too-030">Output ladder</a> ·
<a href="#native-deepseek-harness-dsh-bundle">DSH bundle</a> ·
<a href="#compatibility">Compatibility</a> ·
<a href="CHANGELOG.md">Changelog</a>
</p>
An MCP server that sits in front of your other MCP servers and exposes 6 router tools (8 with [skills](#skills)) instead of dozens of specific ones: four generic ones to list, search, describe and call the tools behind it, plus two for tool-group costs and archived results (see [Tools](#tools)) — discovering the rest on demand — so tool definitions stop eating your context window before the model reads a word.
The router never talks to the model backend, so it does not matter whether Ollama, LM Studio, vLLM or llama.cpp serves your model; what matters is that your client's model calls tools (run with Ollama; the others expected, not yet tested).
Companion to Context Guardian: Context Guardian compacts the conversation before the window fills; Tool Guardian keeps the tools from filling it in the first place. Two halves of the same problem.
· Without Tool Guardian · With it
7 MCP servers on a 32K model ([bench](#measured-savings)) · 20,005 tokens of schemas on every request (61 % of the window) · 1,084 tokens (3 %); a schema is fetched only when the model asks
A 3,000-line build log with one error ([bench](#measured-savings)) · 115,945 characters land in the conversation · 4,540 characters, the full original archived and one call away
A backend that fails to start · an empty tool list the model silently works around · status UNKNOWN plus the real error (e.g. could not start: …), never an empty list
Quick start (60 seconds)
Or tell your coding agent: Install tool-guardian (docs: https://raw.githubusercontent.com/LuminariSoftwares/tool-guardian/main/llms.txt) and route my MCP servers through it.
Nothing to install: uvx runs it from PyPI. The example server below
is the MCP filesystem server, which runs with npx, so that one line needs Node.js — the router
itself is Python 3.9+ and standard library only.
uvx tool-guardian --version uvx --from tool-guardian tool-guardian-setup add files -- npx -y @modelcontextprotocol/server-filesystem "$HOME" uvx tool-guardian --selftest claude mcp add --scope user tool-guardian -- uvx tool-guardian # or any client: see "Run" below
Prefer it installed? pip install tool-guardian, then drop the uvx prefixes (tool-guardian-setup add ...,
tool-guardian --selftest).
Success looks like added 'files' to ~/.tool-guardian/mcp.json, then from --selftest
1 backend(s) up, 14 tools reachable. and a router tools cost ~N tokens vs ~M line. Already have
servers in Claude Desktop, Cursor or Windsurf? tool-guardian-setup import copies them instead of add.
In the client, ask for something one of your servers does; the model should call list_capabilities
(or search_capabilities) and then call_tool.
What it looks like in practice
A real session against two servers (files a
…(truncated)
Rendered from the README published on npm. Formatted only, not edited.
Versions
Published on npm::17,最后更新 2026-11-05