A cargo-generate starter
template for wrapping an HTTP API as three Rust crates: a library, a CLI, and an
MCP server. It targets the common case of an API authenticated with a single
long-lived API key sent as an X-Api-Key header against a configurable base URL.
| Crate | Description |
|---|---|
myapp-core |
Async API client library |
myapp-cli |
Terminal CLI (myapp) |
myapp-mcp |
MCP server (myapp-mcp) for LLM clients |
The CLI and the MCP server both depend on the core library, so the request, auth, config, and error handling live in one place:
myapp-core (ApiClient, Config, models, errors)
/ \
myapp-cli myapp-mcp
(clap CLI) (rmcp: stdio + streamable HTTP)
cargo generate --git https://github.com/seferino-fernandez/rust-mcp-cli-starter --name acme-tools --allow-commandsThis renames everything (myapp → acme-tools, MYAPP_ → ACME_TOOLS_).
--allow-commands is required because the generation hook runs sed/cargo fmt
to rename the project; without it, cargo-generate prompts for confirmation
(interactive) or fails (with --silent).
Build the project:
cargo buildRun the project's tests:
cargo testRun a command from the CLI module:
MYAPP_BASE_URL=http://localhost:8080 MYAPP_API_KEY=xxxx cargo run -p myapp-cli -- statusConfiguration is layered, highest precedence first:
CLI flag, then MYAPP_* env, then MYAPP_*_FILE env, then config.toml, then
built-in defaults. See config.toml.example for every setting.
Both binaries take -v/--verbose and -q/--quiet flags. By default only
errors are reported; repeat -v to step up:
-qsilent- (default) errors only
-vwarn,-vvinfo,-vvvdebug,-vvvvtrace
Place the flag before the subcommand: myapp -v status. Setting RUST_LOG
overrides these flags entirely (e.g. RUST_LOG=myapp_core=trace,reqwest=debug).
The myapp CLI supports static completions for bash, elvish, fish, nushell,
powershell, and zsh, plus dynamic completions for every shell except nushell.
Static - generate a script once and install it where your shell looks for it:
myapp completions zsh > ~/.zsh/completions/_myappmyapp completions bash | sudo tee /usr/share/bash-completion/completions/myappmyapp completions fish > ~/.config/fish/completions/myapp.fishmyapp completions nushell > ~/.config/nushell/completions/myapp.nuDynamic - let the binary drive completions at runtime via the COMPLETE
environment variable. Add one line to your shell startup file:
echo 'source <(COMPLETE=zsh myapp)' >> ~/.zshrcecho 'source <(COMPLETE=bash myapp)' >> ~/.bashrcecho 'COMPLETE=fish myapp | source' >> ~/.config/fish/completions/myapp.fishThe myapp CLI generates ROFF man pages for itself and every subcommand into a
directory (created if missing):
myapp man ~/.local/share/man/man1myapp-mcp implements MCP 2026-07-28 (rmcp 3.x) and exposes the same API to
LLM clients over two transports:
stdio: for local clients such as Claude Desktop.http(streamable HTTP): for networked clients, with a choice of auth mode:token: static bearer token (constant-time compared).oauth: OAuth 2.1 authorization-code flow with PKCE.none: no auth (loopback only).
Older clients still negotiate down: the server accepts every protocol version rmcp knows, so a 2025-11-25 client keeps its session and resumability while a 2026-07-28 client is served statelessly.
Tool input schemas are closed (additionalProperties: false) and tool results
are capped to a configurable byte budget. See the
myapp-mcp README for details.