Skip to content

bake create/update --description is stored but never used #63

Description

@jburnham

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_implbuild_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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions