
mduct
Updated 1mo agoby TheFox666

One binary that turns any MCP server into a Unix tool — pipeable, scriptable, usable by hand — and keeps its tool schemas out of your model's context.

mduct call gitlab list_issues state=opened --json | jq '.[].title'
MCP servers don't come with a command line. This gives them one. It is a duct. Things go through it.
Why
An MCP server has no command line. It speaks JSON-RPC to an LLM client and that is the whole of it — you cannot pipe it, script it, loop over it, put it in a cron job, or try it by hand. Whatever it can do is reachable from exactly one place.
mduct makes them shell citizens:
# every open MR whose source branch is already gone
mduct call gitlab list_merge_requests project_id=grp/proj state=opened --json \
| jq -r '.[].source_branch' \
| while read -r b; do git ls-remote --exit-code --heads origin "$b" >/dev/null || echo "stale: $b"; done
# the same tool, across a set of projects, in a loop
for p in api web worker; do
mduct call gitlab list_pipelines project_id="grp/$p" --json | jq -c "{repo:\"$p\", last:.[0].status}"
done
None of that is possible against an MCP server otherwise, and none of it needs a model. Humans get to use these servers too.
The context bill is a side effect of the pipe
Because a shell sits in the middle, you filter before anything becomes context. A tool that returns 20 issues returns 20 full issues; you wanted three fields. On a real call that is 1,768 characters in context where the server sent 24,568 — the three fields you named, not the twenty objects it had.
That is the part worth having. The schemas are the smaller half of the same story: a client loads every connected server's tool definitions up front — one GitLab server is 189 tools and 191 kB of JSON Schema, call it 48k tokens before the model reads your question. mduct leaves them on disk and puts one line per server in the prompt instead:
MCP tools via `mduct` CLI (list+args: mduct tools <server>; call: mduct call <server> <tool> key=value):
notes — shared notes
search(query, limit?) get(id) put(id, body)
gitlab — GitLab: MRs, pipelines, issues, repos
189 tools — mduct tools gitlab
CLI tools via `mduct` CLI (what it can do: mduct tools <tool>; run: mduct run <tool> [args…]):
kubectl — read-only cluster access
A server small enough carries its signatures so an agent can see the call rather than remember to ask; a 189-tool one collapses to a count and a pointer. The signatures come from a cache the daemon fills as it is used, so the index never connects and works cold in a session hook. Measured on this setup — 7 servers, 290 tools:
| what the prompt carries | ||
|---|---|---|
| every schema, the way a client loads them | 295 kB | ~75k tokens |
| every tool mirrored into the tool namespace | 78 kB | ~20k tokens |
| the index | 2.4 kB | ~600 tokens |
Token counts are bytes ÷ 4. The ratios hold; the absolute numbers are estimates, and none of this is a claim about your bill — it is what sits in the prompt.
273 of those 295 kB are JSON Schema; names and descriptions are 22. The prose
that tells a model when to reach for a tool is 7% of the weight — and it is not
gone either, just one call away: mduct tools gitlab lists names and signatures,
mduct schema gitlab create_issue pulls one definition in full when the fields
matter.
Related servers

n8n
Updated todayby n8n-io
Fair-code workflow automation platform with native AI capabilities. Combine visual building with custom code, self-host or cloud, 400+ integrations.

mcp-server-fetch
OfficialUpdated 14d agoA Model Context Protocol server providing tools to fetch and convert web content for usage by LLMs

@modelcontextprotocol/server-everything
OfficialUpdated 14d agoMCP server that exercises all the features of the MCP protocol