-
Notifications
You must be signed in to change notification settings - Fork 0
Cookbook
Recipes. Paste, adjust the names, move on.
The whole point. A tool that returns 20 issues returns 20 full issues. You wanted three fields.
# measured on a real tracker: 24,568 characters down to 1,768
mduct call tracker list_issues limit=20 --json | jq -c '.issues|map({id,title,status})'--json strips the prose some servers wrap around their payload ("Found 20
issues:"), which is what makes the pipe work at all. It also skips the
oversized-list guard, since you are obviously already slimming the thing.
Don't know the shape? Look once, then project:
mduct call srv some_tool --json | jq 'if type=="array" then .[0] else . end | keys'mduct call tracker list_issues state=open --json \
| jq -r '.[].id' \
| while read -r id; do
mduct call tracker get_issue id="$id" --json | jq -c '{id, title, assignee}'
doneProject the second call as well, or you have moved the wall of text one line down and gained nothing.
# every open MR whose branch no longer exists
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 2>&1 || echo "stale: $b"
donemduct call srv create_thing --args @payload.json
jq -n '{title:"from a pipe"}' | mduct call srv create_thing --args -Guards live in the daemon, so this holds however the caller phrases the request:
Deny wins over allow. "deny": ["delete_*", "drop_*"] is the other direction
when a server is mostly fine.
export MDUCT_PROFILE=ci # ~/.config/mduct-ci/, own socket, own secrets, own daemon
mduct add tracker --url https://mcp.example.com/mcp
mduct call tracker list_issues --json | jq length
mduct daemon --stop # tidy upNothing is shared with your default instance. Not the config, not the tokens.
"playwright": {
"run": "bunx",
"args": ["playwright@1.61.1"],
"check": "bunx playwright@1.61.1 --version",
"setup": "bunx playwright@1.61.1 install chromium",
"note": "headless browser"
}mduct tool status # shows "↑ update 1.61.1 → 1.62.0" when one is out
mduct tool update playwright # bumps the pin
mduct run playwright test e2e/The env and the wrapping travel with the config, so the tool behaves the same on a laptop and on the build box.
mduct import # what's attached in ~/.claude* and .mcp.json
mduct import gitlab # copy one across; literal tokens land in the secret store
mduct doctor # anything still attached directly AND served here — you want zero
claude mcp remove gitlab # ...then drop the direct attachment, or you pay for bothmduct servers # config + connection state
mduct tools srv | head -30 # names and signatures, no schemas
mduct schema srv the_tool # the full schema, only when you need it
mduct call srv the_tool --raw # the MCP envelope, if a result looks wrongSequential calls reuse the same warm connection, so a loop is cheap:
for p in api web worker; do
mduct call gitlab list_pipelines project_id="grp/$p" --json | jq -c "{repo:\"$p\", last:.[0].status}"
doneThe daemon holds one connection per server. Parallel calls to the same server
are queued, so xargs -P buys you nothing there. Parallelise across servers, or
ask for more per call if the server supports it.
set -euo pipefail
if ! out=$(mduct call srv risky_tool id=42 --json 2>err.txt); then
echo "call failed: $(cat err.txt)" >&2 # errors go to stderr, exit code is nonzero
exit 1
fi
echo "$out" | jq -e '.ok' >/dev/nullError messages name the next action, e.g. unknown tool "x" — see: mduct tools srv.