-
Notifications
You must be signed in to change notification settings - Fork 0
Troubleshooting
mduct status # is the daemon up, and which instance answered?
mduct daemon --stop # then run the next call — it restarts clean
mduct daemon # foreground: the startup errors go to your terminalRunning it in the foreground is the fastest way to catch a server that fails to launch. A stdio server that writes to stdout at startup, or dies immediately, shows up there and nowhere else.
You are probably talking to a different instance than you think.
mduct status
# config: /home/you/.config/mduct-ci/servers.jsonc ← MDUCT_PROFILE is setMDUCT_PROFILE, MDUCT_CONFIG and an exported MDUCT_SOCKET all outlive
anyone's memory of having set them.
The daemon inherits the environment of whichever process started it first. If that was the agent, the agent's environment is what the server sees.
Put what the server needs in the config (env), not in your shell profile:
Then mduct daemon --stop so the next call starts it fresh with the new config.
They should: the daemon watches the config file. When an entry changes, that server's connection is dropped so the next call reconnects with the new settings. Connections to unrelated servers are left alone on purpose.
So if an edit seems ignored, the file probably didn't parse:
mduct logs | tail -5
# config reload FAILED: server "srv": needs "command" (stdio) or "url" (http) — fix /home/you/.config/mduct/servers.jsoncA config that fails to load is not applied. The daemon keeps running on the last good one instead of dropping every connection over a stray comma. That is the right behaviour, and it is also why a broken edit can look exactly like no edit. Check the logs before you go hunting for a cache.
Resolution is process.env first, then the secret store. If neither has it, the
value is left as written, which usually surfaces as an auth error from the
server rather than an error from mduct.
mduct secret list # names only — is it actually stored?Remember that the daemon's environment is not your shell's (see above). The secret store exists so this stops mattering.
mduct auth <server> # re-consent; the token is stored 0600 and refreshed automaticallyA dead session fails with exactly that instruction. Tokens live next to the config, so a profile has its own.
Use --json. Without it you get the server's text content, which for many
servers is JSON wrapped in a sentence. With it you get the payload only.
If --json still gives you something odd, look at the envelope:
mduct call srv tool --rawmduct servers # the guard is shown per serverCheck the precedence: deny beats allow, a present allow list is
exhaustive, and "allow": [] blocks everything by design. "No restriction"
means leaving the key out.
One at a time per server by default. The protocol has request ids and does not care, but not every MCP server is reentrant, and the failure path closes the transport, which is only safe when nothing else is using it.
If a server handles concurrency, raise its limit:
"srv": { "command": "…", "maxConcurrent": 4 }Measured with a 300 ms tool and five calls at once: 1561 ms at the default,
360 ms at maxConcurrent: 5. A tool-level error (the server answering "no")
does not disturb the others; a transport that actually dies takes the in-flight
calls with it and is rebuilt once, after the last one drains.
mduct doctor # servers attached directly AND served hereAn MCP server attached directly to your agent still loads its full schemas. If mduct also serves it, you are paying twice for one thing. Remove the direct attachment.