Add stop_server + status MCP tools; TDQS-grade tool descriptions - #49
Merged
Merged
Conversation
Protocol: new optional `action` field on Request (exec|stop|ping,
default exec, omitted on the wire for exec). Control requests are sent
with an empty pipeline so a pre-1.1 daemon rejects them at validation —
before any prompt — and its version-stamped error reply lets new
clients detect the old peer. Control actions pass every gate an exec
does (peer uid, sanitization, freshness, replay).
Daemon: `stop` prints a notice on the TTY (no approval prompt), replies
ok, and shuts the accept loop down cleanly, removing the socket on the
way out; `ping` replies ok/pong without prompting. The shutdown flag is
now an Arc so handler threads can set it.
MCP: new `stop_server` and `status` tools ({host} optional). status
probes socket presence + readiness, then pings for the live daemon
version (refreshing the hosts.json cache); down hosts are a non-error
result. stop_server confirms shutdown and cleans up stale tunnel
sockets; both degrade gracefully against pre-1.1 daemons. All three
existing tool descriptions rewritten to document blocking behavior,
timeouts, return format, update semantics, and error cases (Glama TDQS
feedback).
Tests: protocol serde/validate coverage for actions, server-level
stop/ping/stale-stop integration tests, introspection tool list now
five tools. Docs: mcp.md, protocol.md, README. Version 1.0.0 -> 1.1.0.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The crates.io package installs four binaries (sudo-proxy, sudo-request, pkexec-cache, sudo-proxy-mcp) but the MCP registry's cargo convention runs the binary named after the crate — sudo-proxy, the CLI, not the MCP server. There is no server.json field to select a specific binary, so probe-based directory sites launch the wrong binary and their tools/list fails, listing zero tools. Add an mcpb package entry alongside cargo. An .mcpb bundle is a zip whose manifest.json pins sudo-proxy-mcp as the entry point, so clients and probes launch the MCP server directly. - packaging/mcpb/manifest.json: MCPB 0.3 binary-server manifest - packaging/mcpb/build-mcpb.sh: build the .mcpb from the musl binary - server.json: mcpb package entry (fileSha256 injected at publish time) - release.yml: build + minisign-sign + upload the .mcpb asset - publish.yml: wait for the asset, inject its sha256 into server.json before mcp-publisher publish (registry HEAD-validates the URL) Verified locally: the bundle builds, and an initialize + tools/list probe against the bundled binary returns the tool set. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Glama scores this server 3.9/5.0 on TDQS. The per-tool feedback:
update_hostbehavior 2/5 (update semantics undocumented),start_serverbehavior 3/5 (blocking/readiness unstated),executemissing timeout/return/error info — and server coherence 3/5: "no stop/status tool… no way to read hosts even though update_host implies a host registry". This PR addresses all of it: the three descriptions are rewritten andstop_server/statusbecome real tools.stop_serveralso serves the session-handoff workflow (shut the approval daemon down at wrap-up).Protocol: control actions
New optional
actionfield on the wire request:exec(default),stop,ping. Compatibility rests on two existing facts: everyResponseis version-stamped, and validation rejects an empty pipeline before any prompt."pipeline": []— an old daemon parses them (nodeny_unknown_fields), rejects at validate without prompting the human, and its error reply still reveals its version, which the new tools use for a friendly "predates this feature" message.actionentirely, staying byte-identical to the pre-1.1 wire format; old clients never send it and default toexec.Daemon
stop: prints a dim notice on the TTY ("sudo-proxy stopped by ") — no approval prompt, since a same-UID peer can already SIGTERM the daemon, so a gate would add friction without a security boundary — replies ok, then shuts the accept loop down cleanly and removes the socket. The terminal window (and SSH tunnel, remotely) closes with it.ping: replies ok/"pong" without prompting.Arc<AtomicBool>so handler threads can set it;mainnow cleans up the socket on clean return.MCP tools
stop_server { host? }— "not running" is a non-error result; on success polls briefly for the socket to disappear and removes a leftover tunnel socket; against a pre-1.1 daemon returns an error asking for a manual q/Ctrl+C.status { host? }— with no args, checks the local daemon plus every registry host; per host reports socket presence, readiness, live daemon version via ping, and registry metadata. Read-only except refreshing the hosts.json last-connected/version cache.Tests & docs
rundown without a prompt; ping answers without a prompt and the daemon keeps serving; a stale stop is rejected and the daemon survives.Verified live: full status → stop_server → status cycle against a 1.1.0 daemon (clean exit, socket removed), and against a real 0.12.0 daemon — status reports "running (sudo-proxy 0.12.0, predates ping)", stop_server returns the manual-stop message, old daemon unaffected, no prompt ever shown.
Note:
burst_connections_above_cap_get_busy_responseis flaky when run standalone in--releaseon unmodified main as well — pre-existing, unrelated.🤖 Generated with Claude Code