Version: mcp2cli 3.3.1 — corresponds to commit dd2a5a6 (current main HEAD; the installed 3.3.1 wheel's mcp2cli/__init__.py is byte-identical to src/mcp2cli/__init__.py at that commit, so the behavior below is also present on main).
Summary
bake create --description "..." and bake update --description "..." write a description field into the baked tool's config, but nothing ever reads it back. The top-level parser for a baked tool always shows the generic prog="mcp2cli" banner and the hardcoded tagline "Turn any MCP server or OpenAPI spec into a CLI", regardless of what --description was set to.
Repro
$ mcp2cli bake create petstore --description "petstore cli" --spec https://petstore3.swagger.io/api/v3/openapi.json
Baked tool 'petstore' created.
$ mcp2cli @petstore -h
usage: mcp2cli [-h] [--spec SPEC] [--mcp MCP] [--mcp-stdio MCP_STDIO] [--graphql GRAPHQL] [--auth-header AUTH_HEADER] [--base-url BASE_URL] [--cache-key CACHE_KEY] [--cache-ttl CACHE_TTL] [--refresh]
[--list] [--search PATTERN] [--verbose] [--sort {usage,recent,alpha,default}] [--top N] [--compact] [--pretty] [--raw] [--json] [--toon] [--head N] [--fields FIELDS]
[--transport {auto,sse,streamable}] [--env ENV] [--oauth] [--oauth-client-id OAUTH_CLIENT_ID] [--oauth-client-secret OAUTH_CLIENT_SECRET] [--oauth-client-name OAUTH_CLIENT_NAME]
[--oauth-scope OAUTH_SCOPE] [--oauth-redirect-uri URI] [--oauth-flow {auto,authorization_code,client_credentials}] [--list-resources] [--list-resource-templates] [--read-resource URI]
[--list-prompts] [--get-prompt NAME] [--prompt-arg KEY=VALUE] [--session-start NAME] [--session-stop NAME] [--session-list] [--session NAME] [--version]
{update-pet,add-pet,find-pets-by-status,find-pets-by-tags,get-pet-by-id,update-pet-with-form,delete-pet,upload-file,get-inventory,place-order,get-order-by-id,delete-order,create-user,create-users-with-list-input,login-user,logout-user,get-user-by-name,update-user,delete-user} ...
Turn any MCP server or OpenAPI spec into a CLI
Expected the banner to read something like:
usage: petstore [-h]
{...} ...
petstore cli
Root cause
build_argparse() hardcodes both prog and description (src/mcp2cli/init.py#L2199-L2206):
def build_argparse(
commands: list[CommandDef], pre_parser: argparse.ArgumentParser
) -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(
prog="mcp2cli",
description="Turn any MCP server or OpenAPI spec into a CLI",
parents=[pre_parser],
)
_run_baked() never passes the baked config's name or description through to build_argparse() (src/mcp2cli/init.py#L2179-L2191):
def _run_baked(name: str, argv: list[str]) -> None:
"""Load a baked config and run it."""
cfg = _load_baked(name)
if cfg is None:
print(f"Error: no baked tool named '{name}'", file=sys.stderr)
sys.exit(1)
synthetic_argv = _baked_to_argv(cfg) + list(argv)
bake_config = BakeConfig(
include=cfg.get("include", []),
exclude=cfg.get("exclude", []),
methods=cfg.get("methods", []),
)
_main_impl(synthetic_argv, bake_config=bake_config)
Searching the codebase, cfg["description"] is written at create/update time (#L2055, #L2142) and echoed by bake show, but there is no other read site — _baked_to_argv() (#L1891-L1928) never reconstructs it, so it's effectively dead config once saved.
This also affects bake install: the generated wrapper script always execs mcp2cli @<name> "$@", so even a user-installed petstore binary shows usage: mcp2cli instead of usage: petstore.
Suggested fix
- Thread
name and cfg.get("description") through _run_baked → _main_impl → build_argparse, and use them for prog= / description= on the top-level parser when running a baked tool.
- Optionally have
bake list display the description column too, since it's already collected.
Happy to send a PR if useful — wanted to flag the behavior first in case there's a reason description is currently write-only.
Version: mcp2cli 3.3.1 — corresponds to commit
dd2a5a6(currentmainHEAD; the installed 3.3.1 wheel'smcp2cli/__init__.pyis byte-identical tosrc/mcp2cli/__init__.pyat that commit, so the behavior below is also present onmain).Summary
bake create --description "..."andbake update --description "..."write adescriptionfield into the baked tool's config, but nothing ever reads it back. The top-level parser for a baked tool always shows the genericprog="mcp2cli"banner and the hardcoded tagline"Turn any MCP server or OpenAPI spec into a CLI", regardless of what--descriptionwas set to.Repro
Expected the banner to read something like:
Root cause
build_argparse()hardcodes bothproganddescription(src/mcp2cli/init.py#L2199-L2206):_run_baked()never passes the baked config'snameordescriptionthrough tobuild_argparse()(src/mcp2cli/init.py#L2179-L2191):Searching the codebase,
cfg["description"]is written at create/update time (#L2055, #L2142) and echoed bybake show, but there is no other read site —_baked_to_argv()(#L1891-L1928) never reconstructs it, so it's effectively dead config once saved.This also affects
bake install: the generated wrapper script always execsmcp2cli @<name> "$@", so even a user-installedpetstorebinary showsusage: mcp2cliinstead ofusage: petstore.Suggested fix
nameandcfg.get("description")through_run_baked→_main_impl→build_argparse, and use them forprog=/description=on the top-level parser when running a baked tool.bake listdisplay the description column too, since it's already collected.Happy to send a PR if useful — wanted to flag the behavior first in case there's a reason
descriptionis currently write-only.