mcp-inspector-cli

    One-shot command-line MCP client for the 2026-07-28 protocol era.

    mcp
    model-context-protocol
    cli
    inspector
    Download zip
    Version
    0.8.0
    License
    MIT
    Last updated
    26 days ago
    Downloads
    42

    #marianoguerra/mcp-inspector-cli

    A one-shot command-line client for MCP 2026-07-28 servers, modelled on mcp-inspector --cli from the reference implementation.

    moon install marianoguerra/mcp-inspector-cli mcp-inspector-cli --help

    mcp-inspector-cli http://127.0.0.1:3100/mcp --transport http --method tools/list mcp-inspector-cli ./my-server --transport stdio --method tools/call \ --tool-name echo --tool-arg message=hi mcp-inspector-cli --config ./mcp.json --server my-server --method tools/list

    --tool-arg values are JSON-coerced, so count=1 is a number and name=hi a string. Output is pretty-printed JSON, or a single-line {"result": …} envelope with --format json.

    Exit codes: 0 ok · 1 usage/error · 2 no app · 3 auth required · 4 unreachable · 5 tool error. Every non-zero exit also writes one JSON line to stderr: {"error":{"code":…,"message":…,"status":…,"url":…}}.

    Modern era only. There is no legacy initialize handshake, so a 2025-era server — which today means every server in the official MCP monorepo — is rejected rather than fallen back to. See the repository README for the measured details.

    CliExit

    pub(all) suberror CliExit {
    CliExit(code~ : Int, envelope~ : ErrorEnvelope)
    } derive(
    Debug
    )

    Raised to request a specific exit code without going through classification.

    UsageError

    pub(all) suberror UsageError {
    UsageError(String)
    } derive(
    Debug
    )

    Raised for anything that makes the command line unusable. Maps to exit 1.
    impl Show for UsageError

    Args

    pub struct Args {
    target : Array[String]
    multi : Map[String, Array[String]]
    single : Map[String, String]
    flags : Map[String, Bool]
    }

    Everything the CLI was asked to do.

    Args::flag

    fn Args::flag(self : Args, name : String) -> Bool

    Args::list

    fn Args::list(self : Args, name : String) -> Array[String]

    Args::opt

    fn Args::opt(self : Args, name : String) -> String?

    ErrorEnvelope

    pub(all) struct ErrorEnvelope {
    code : String
    message : String
    cause : String?
    status : Int?
    url : String?
    } derive(
    Debug
    )

    A failure classified for a programmatic caller.

    ErrorEnvelope::to_json

    fn ErrorEnvelope::to_json(self : ErrorEnvelope) -> Json

    Target

    type Target

    Where to connect, resolved from the target and flags.

    classify

    fn classify(e : Error, url? : String) -> (Int, ErrorEnvelope)

    Map an error onto an exit code and envelope.

    Classification is structural where it can be: a TransportError::Network is unreachable because of what it is, not because its text matched a regex.

    collect_kv

    fn collect_kv(pairs : Array[String]) -> Map[String, Json] raise UsageError

    Collect repeated key=value options into a JSON object.

    collect_meta

    fn collect_meta(pairs : Array[String]) -> Map[String, Json] raise UsageError

    Metadata values are carried as strings: a non-string coerced value is re-encoded rather than stringified structurally, so {"a":1} stays JSON and not "[object ...]".

    emit_error

    async fn emit_error(envelope : ErrorEnvelope) -> Unit

    Write the one-line error envelope to stderr.

    emit_result

    async fn emit_result(result : Json, format : String, app_info? : Json) -> Unit

    Write the result to stdout in the requested format.

    text is pretty-printed JSON, json is a single-line {"result": ...} envelope so the whole output pipes into jq.

    exit_auth_required

    let exit_auth_required : Int

    The server requires authentication.

    exit_no_app

    let exit_no_app : Int

    --app-info found no MCP App on the tool.

    exit_ok

    let exit_ok : Int

    exit_tool_error

    let exit_tool_error : Int

    A tool returned isError:true, or the named tool does not exist.

    exit_unreachable

    let exit_unreachable : Int

    The server is unreachable.

    exit_usage

    let exit_usage : Int

    Usage or unexpected error -- the catch-all.

    parse_args

    fn parse_args(argv : Array[String]) -> Args raise UsageError

    Parse argv (without the program name).

    The target/option split follows the reference: with an explicit --, everything BEFORE it is the target and everything after is options; otherwise the target is the leading run of tokens that do not start with -. That ordering is what lets inspector-cli node server.js --method tools/list work without quoting.

    parse_header

    fn parse_header(pair : String) -> (String, String) raise UsageError

    Parse a Name: Value header pair. Split on the FIRST colon so a URL in the value survives.

    parse_kv

    fn parse_kv(pair : String) -> (String, Json) raise UsageError

    Parse a key=value pair, JSON-coercing the value.

    This is what makes --tool-arg count=1 a number and --tool-arg name=hello a string: the value is offered to the JSON parser first and falls back to a string.