pdfcraft-cli --help lists `mcp` only when the build has it (#574)

Follow-up to #540: a build without the `mcp` feature (`--no-default-features`) still listed
`pdfcraft-cli mcp` in its usage, and `pdfcraft-cli mcp` then said "unknown command".

USAGE is now put together with `concat!`, and its `mcp` lines come from a macro that is empty
without the feature. In such a build `pdfcraft-cli mcp` says the MCP server was left out instead
of calling it an unknown command.

- tests/help.rs: usage_lists_mcp_only_when_built_with_it (runs in both feature sets) and
  mcp_without_the_feature_says_it_was_left_out (without the feature)

Co-authored-by: lloyd <lloyd@stackworx.io>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
This commit is contained in:
LloydNicholson 2026-10-09 20:44:11 +02:00 committed by GitHub
parent dbd0748177
commit fce60eacb4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 47 additions and 4 deletions

View File

@ -26,8 +26,26 @@ use std::time::{Duration, Instant};
use pdfcraft_engine::export::ImageFormat;
use pdfcraft_render::{PageRenderer, RenderConfig, RenderRequest, RequestKind, inspect};
/// The `mcp` lines of [`USAGE`]: only a build with the `mcp` feature has the command.
#[cfg(feature = "mcp")]
macro_rules! mcp_usage {
() => {
"\
pdfcraft-cli mcp [--root DIR] [--compact] MCP server on stdin/stdout (opt-in)
--compact lists a core set of tools plus tool_search and tool_call
"
};
}
#[cfg(not(feature = "mcp"))]
macro_rules! mcp_usage {
() => {
""
};
}
/// The full usage, printed by `--help` (also after a command, e.g. `render --help`).
const USAGE: &str = "\
const USAGE: &str = concat!(
"\
pdfcraft-cli info <file.pdf> [--password PW] document summary as JSON
pdfcraft-cli render <file.pdf> --page N [--dpi 96] --out x.png (.png, .jpg, .tif or .pam)
pdfcraft-cli text <file.pdf> [--page N] extracted text (pages separated by form feeds)
@ -40,11 +58,13 @@ pdfcraft-cli check <files or dirs…> [--timeout 20] [--dpi 36] [--json out.jso
pdfcraft-cli tools automation tools and their JSON Schemas
pdfcraft-cli run <tool> [key=value …] [--root DIR] [--out image.png]
pdfcraft-cli run --script steps.json [--root DIR] [{\"tool\": \"doc_open\", \"args\": {…}}, …]
pdfcraft-cli mcp [--root DIR] [--compact] MCP server on stdin/stdout (opt-in)
--compact lists a core set of tools plus tool_search and tool_call
",
mcp_usage!(),
"\
pdfcraft-cli ui --control FILE <method> [key=value …] [--out shot.png]
drive a running app started with --control FILE
help and feedback: https://discord.gg/artcraft";
help and feedback: https://discord.gg/artcraft"
);
fn main() -> ExitCode {
let args: Vec<String> = std::env::args().skip(1).collect();
@ -70,6 +90,8 @@ fn main() -> ExitCode {
Some("ui") => ui(&args[1..]),
#[cfg(feature = "mcp")]
Some("mcp") => mcp(&args[1..]),
#[cfg(not(feature = "mcp"))]
Some("mcp") => Err("mcp: this build leaves out the MCP server (built without the `mcp` feature)".into()),
Some("--version") => version(),
Some(other) => Err(format!("unknown command '{other}'; see pdfcraft-cli --help").into()),
};

View File

@ -34,6 +34,27 @@ fn no_command_fails_with_usage_on_stderr() {
assert!(text(&out.stderr).contains("pdfcraft-cli render <file.pdf> --page N"));
}
/// `mcp` is listed only when the build has it (`--no-default-features` leaves it out).
#[test]
fn usage_lists_mcp_only_when_built_with_it() {
let out = run(&["--help"]);
let stdout = text(&out.stdout);
assert_eq!(stdout.contains("pdfcraft-cli mcp"), cfg!(feature = "mcp"), "{stdout}");
assert_eq!(stdout.contains("--compact"), cfg!(feature = "mcp"), "{stdout}");
// The lines around it are still there.
assert!(stdout.contains("pdfcraft-cli run --script steps.json"), "{stdout}");
assert!(stdout.contains("pdfcraft-cli ui --control FILE"), "{stdout}");
}
#[cfg(not(feature = "mcp"))]
#[test]
fn mcp_without_the_feature_says_it_was_left_out() {
let out = run(&["mcp"]);
assert!(!out.status.success());
let stderr = text(&out.stderr);
assert!(stderr.contains("without the `mcp` feature"), "{stderr}");
}
#[test]
fn unknown_command_names_it_and_points_to_help() {
let out = run(&["frobnicate"]);