Skip to content

feat: embed sprout CLI in dev-mcp, add NIP-OA auth tag support#525

Merged
tlongwell-block merged 1 commit into
mainfrom
feat/cli-shim-in-dev-mcp
May 11, 2026
Merged

feat: embed sprout CLI in dev-mcp, add NIP-OA auth tag support#525
tlongwell-block merged 1 commit into
mainfrom
feat/cli-shim-in-dev-mcp

Conversation

@tlongwell-block

Copy link
Copy Markdown
Collaborator

What

Expose sprout-cli as a library crate and embed it in sprout-dev-mcp using the same multi-call binary pattern as rg and tree. Add NIP-OA auth tag support to the CLI, bringing it to parity with sprout-mcp.

CLI as a dev-mcp shim

When an agent runs sprout list-channels through the shell tool, the dev-mcp binary recognizes argv[0] = "sprout" and handles it in-process — no external binary to install or discover.

  • sprout-cli gains a [lib] target exposing pub async fn run_from_args()
  • sprout-dev-mcp adds sprout as a symlink alongside rg and tree in the shim tempdir
  • Shell tool description updated to mention sprout is on PATH
  • Bootstrap instructions conditionally hint about the CLI when SPROUT_RELAY_URL and SPROUT_PRIVATE_KEY are set

The standalone sprout binary continues to work independently — main.rs is a thin wrapper calling the library.

NIP-OA auth tag support

The CLI now has full parity with sprout-mcp for owner attestation:

  • SproutClient gains sign_event() — injects the NIP-OA auth tag into every signed event before signing, with post-sign count enforcement (same pattern as RelayClient::sign_event() in sprout-mcp)
  • x-auth-tag HTTP header sent on all REST requests (/query, /events, /count, /media/upload) so closed relays accept delegated agents
  • --auth-tag / SPROUT_AUTH_TAG parsed and Schnorr-verified at startup
  • All 31 sign_with_keys call sites across 7 command modules replaced with client.sign_event()

The auth tag is optional and backwards compatible — when absent, behavior is unchanged. The env var is the same one the ACP harness already forwards.

Other fixes

  • commands/pack.rs: replaced 5 process::exit(1) calls with return Err(CliError::Usage(...)) — these would have killed the host MCP server process when the CLI is embedded

Why

The sprout MCP server exposes 49 tools with full JSON schemas to the LLM on every conversation turn. For a dev-mcp agent that primarily writes code and occasionally interacts with Sprout, that is a lot of permanent context overhead. Shipping the CLI as a shim means the agent sees one sprout mention in the shell tool description, runs sprout --help when it needs to, and discovers commands on demand.

The CLI uses stateless HTTP with NIP-98 auth — simpler and more resilient than the MCP's persistent WebSocket with NIP-42 reconnection logic. Per-request latency is noise against agent think time.

Testing

  • All 80 unit tests pass (41 sprout-cli + 39 sprout-dev-mcp)
  • Clippy clean (-D warnings)
  • Integration tested against a local relay: agent used sprout CLI 11 times through the dev-mcp shell tool (create-channel, send-message, get-messages, list-channels, join-channel, etc.)
  • Manual CLI testing against local relay: create-channel, send-message, get-messages, add-reaction, get-reactions, set-profile, get-users all verified

Expose sprout-cli as a library crate and embed it in sprout-dev-mcp
using the same multi-call binary pattern as rg and tree. When the
agent runs `sprout list-channels` through the shell tool, the dev-mcp
binary handles it in-process — no external binary needed.

Also adds NIP-OA auth tag support to the CLI, bringing it to parity
with sprout-mcp: SPROUT_AUTH_TAG is parsed, Schnorr-verified at
startup, injected into every signed event via SproutClient::sign_event(),
and sent as an x-auth-tag HTTP header on all REST requests.

sprout-cli remains independently usable as a standalone binary.
The --auth-tag / SPROUT_AUTH_TAG flag is optional and backwards
compatible — when absent, behavior is unchanged.
@tlongwell-block tlongwell-block force-pushed the feat/cli-shim-in-dev-mcp branch from 0c082b0 to a973a7e Compare May 11, 2026 10:27
@tlongwell-block tlongwell-block merged commit 91f16e3 into main May 11, 2026
15 checks passed
@tlongwell-block tlongwell-block deleted the feat/cli-shim-in-dev-mcp branch May 11, 2026 10:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant