github activeing123/mcptoon v0.8.23
v0.8.23 — presence channel, CLI edge-case polish, site redirect

latest releases: v0.8.34, v0.8.33, v0.8.32...
14 days ago

[0.8.23] - 2026-10-19

CLI papercuts and data-safety fixes reported on 2026-10-17, plus a presence channel so
a user who installed mcptoon and forgot can tell it is being used, by which agent, and
when. Each item was reproduced before fixing and pinned by a test. Held for the next
version per the one-release-per-topic rule.

Added

  • mcptoon search prints a copyable call line for every hit. It used to stop
    at params: message:string*, leaving the user to assemble the JSON arguments and
    to spot the * that marks a required one. Each result now ends with a
    ready-to-edit → mcptoon call <server> <tool> '{"required":"..."}' built from the
    tool's required arguments. Human output only; --json stays pure data.
  • mcptoon call explains how to fix malformed JSON instead of only quoting the
    parser.
    A bad argument object printed the raw JSONDecodeError and nothing else.
    It now follows with the correct invocation (required args filled in from the tool
    schema when available, else a generic skeleton) and the mcptoon inspect pointer.
  • mcptoon completion <shell> --install / --uninstall. completion only
    printed a script and told the user to paste it into the right rc file. --install
    writes it into that file inside # >>> mcptoon completion >>> markers, idempotently
    (a re-run updates in place and reports "already installed"); --uninstall removes
    exactly that block and leaves the user's own lines untouched. Printing the script
    (no flag) is unchanged, so eval "$(mcptoon completion bash)" still works.
  • mcptoon inspect <server> <tool> prints a copyable call line. It printed the
    schema and stopped; the reader still had to turn required/properties into an
    argument object. It now adds the ready-to-edit → mcptoon call … line to stderr,
    so inspect … > schema.json and every machine format stay pure data.
  • mcptoon select prints a call line for its top pick, next to the existing
    Inspect one: hint — same shape as search.
  • mcptoon search --json carries a call_hint field per hit, so an agent driving
    the CLI reaches the call as data, not just a human reading a terminal. An extra key;
    existing consumers are unaffected.
  • mcptoon completion … --install --dry previews the write. Prints the target rc
    file and the exact block that would be written, changes nothing.
  • mcptoon call warns about a missing required argument before it runs. When the
    tool's schema is cached, call echo add '{"a":1}' now says
    Warning: missing required argument(s) for add: b and points at inspect, instead
    of surfacing a downstream KeyError/server validation text. Cache-only, so a call
    never spawns a server just to pre-check.
  • mcptoon policy set names the scope in plain words — "every tool on 'server'
    (current and future)" for the * wildcard, "only 'server:tool'" otherwise.
  • mcptoon toggle prints the command that reverses it ("Re-enable it: …" /
    "Disable it again: …"), so the undo is stated rather than remembered.
  • mcptoon stats / mcptoon report say --head does not apply when it is given:
    both are aggregates (sums over all servers), so a cap cannot shrink them without
    making the totals lie. The note appears only when a cap was actually requested.
  • mcptoon config get <near-miss> suggests the closest key ("did you mean:
    footer?"), using the same matcher as the command/option typo hints.
  • mcptoon activity — a readable ledger of what mcptoon actually did. usage
    answers "how many, which servers" from a capped counter that cannot say which
    agent
    or when. Every routed call now also appends one line to activity.jsonl
    (time, host, server:tool, ok, tokens); mcptoon activity shows the last 20
    newest-first, --summary gives totals (today, last host, by host), --json is
    machine-readable, --clear wipes the ledger (the usage counters are separate
    and untouched). Append-only and capped at 2000 lines, so it never grows without
    bound.
  • Host identity — mcptoon records which agent is using it. serve reads the
    client's self-reported name from the MCP initialize handshake and stores it, so
    the ledger and status say "Cursor" or "Claude Desktop" instead of only counting
    calls. A client that sends no name leaves the host unknown (null), never guessed.
  • mcptoon status shows a "Last used" row — who last drove it, when, and how
    many calls today, with a pointer to mcptoon activity. On a machine nothing has
    routed through yet it says so plainly ("no routed calls yet"), which is itself the
    answer a fresh install needs. status --json carries the same fields
    (activity_entries, activity_today, last_host, last_used_ts,
    presence_enabled).
  • A one-line presence notice after a command that routed a call. When a command
    actually used mcptoon, one short line goes to stderr: ▸ mcptoon routed 3 calls for Cursor this command — see \mcptoon activity`. It fires only when something was really routed, so mcptoon statusstays silent, and it is stderr-only so--json`/piped output stays pure data.
  • A presence setting (on|brief|off, default on), separate from footer.
    footer is the token-savings broadcast; presence is the "you were just used"
    notice. Someone may want the usage notice without the big savings card, or the
    reverse — one switch for two questions forced all-or-nothing. brief keeps the
    notice but drops the host clause.
  • The gateway's own tools are now in the activity ledger. mcptoon_resolve_skills,
    mcptoon_manifest, mcptoon_inspect, mcptoon_call and friends are answered
    in-bridge and never passed through the router, so usage.track_call never saw
    them: a session that only ever distributed skills left activity empty — the
    single most important "was I used" event was invisible. They are now recorded
    under the reserved server name mcptoon, so activity and status show them
    alongside upstream calls.
  • A one-per-session "distributed N skills" banner. The first time
    mcptoon_resolve_skills actually surfaces skills in a session, the result carries
    one line — ▸ mcptoon distributed N skills for this task (see \mcptoon activity`)— so the "mcptoon is handing your capabilities to the agent" moment is stated, not left for the user to infer. Gated onpresence` and on a non-empty shortlist; it
    never repeats within a session.
  • mcptoon quickstart names the agents it registered mcptoon into. The install
    summary used to say only "your agents can now see mcptoon"; it now lists the hosts
    ("Cursor, Claude Desktop …") and points at mcptoon activity for watching it work.
  • mcptoon doctor teaches how to confirm it is working. On a fully healthy run
    with the gateway wired in, it now adds one line — let an agent use a tool, then run
    mcptoon activity — so a clean bill of health also answers "how would I notice it
    doing anything?".
  • The activity ledger now records which skills were distributed. A
    mcptoon_resolve_skills call used to record only that it ran; it now carries a
    detail line naming the skill slugs it handed out (distributed: xiewen-shipin, duanju-juben), and mcptoon activity prints it under the call. "Distributing your
    capabilities" is only legible if the ledger says which capabilities.
  • mcptoon usage shows a by-host breakdown, and mcptoon activity --host <name>
    filters to one agent.
    usage could say which servers were used but never which
    agent used them, and the ledger's host column was only filterable by hand-editing
    JSON. Both now answer "was it Cursor or Claude just now?" on a multi-agent machine.
  • status and doctor warn when the gateway is wired in but silent. A gateway
    registered in an agent that has recorded no call — ever, or for over a day — looks
    identical to one that is quietly working. Both surfaces now name that possibility
    in one soft warning line (never an error, never a changed exit code), so a broken
    wiring is not mistaken for a healthy idle install.
  • mcptoon activity --export json|csv dumps the whole ledger. The on-screen
    view is a 20-line tail; an audit or a pasted bug report wants every line in a form
    a spreadsheet or jq can take. --export csv writes a header plus one row per
    call (chronological), --export json a {count, ledger, entries} envelope. Both
    honour --host. The ledger is a local file — export prints it, uploads nothing.
  • The activity ledger records why a failed call failed. A red line used to say
    only that it was red; it now carries an err field (the error code, or
    Type: message for an exception) capped at 200 chars, and mcptoon activity
    prints it under the call. Full tracebacks are deliberately not stored — the ledger
    stays one line per call.
  • mcptoon status splits "calls recorded" into routed vs the gateway's own
    tools.
    The single number conflated calls proxied to upstream tools with calls
    to mcptoon's own native tools (skill distribution, manifest, inspect). It now
    reads "N routed to tools, M via mcptoon's own tools", and status --json carries
    calls_routed / calls_native — two different things a user deciding whether
    mcptoon is doing anything cares to tell apart.
  • Each activity line records how long the call took, and slow calls are flagged.
    The ledger gains an ms field (wall-clock, whole call as the caller experienced
    it); mcptoon activity prints it and marks anything over 3 s SLOW. A call that
    hung for eight seconds used to look identical to one that took ten milliseconds.
  • mcptoon activity --follow streams new calls live. A tail -f for the
    ledger: it starts at the current end and prints each new routed call as it
    arrives (honours --host), so you can watch an agent drive mcptoon in real time.
    Ctrl-C to stop.
  • mcptoon activity --summary reports the retention cap and the ledger's size.
    The ledger silently keeps only the newest 2000 calls; that roll-off was invisible.
    The summary now names the cap and the current file size, so a user treating it as
    an audit log knows what it actually keeps.
  • mcptoon status names the most recent failed call. A separate question from
    "is it being used": when a call has failed, status shows the agent, the tool,
    when, and the short reason ("Last failure: Cursor fetch:boom at … (CALL_ERROR: …)").
    status --json carries the same as last_fail.
  • mcptoon activity --since <today|1h|24h|7d|YYYY-MM-DD> and --failures.
    --since narrows the view (and --export) to a time window, applied before the
    --head cap so --failures --head 20 means "the last 20 failures"; --failures
    shows only calls that failed. Both compose with --host and --export.
  • mcptoon demo now records a line in the activity ledger. The demo drives a
    raw MCP client and bypassed the router, so it left the ledger empty — the one
    moment a brand-new user wants proof "it really is recording" was the one that
    recorded nothing. mcptoon demo && mcptoon activity now shows the demo's echo
    call (server name demo, clearly not a real upstream call).
  • activity --summary reports success rate and latency. It now shows
    "Success: N/M (P%)" and "Latency: avg X ms · K slow (>3000 ms)", read off the
    same window (using the ms field added last round) — "was it reliable?" is no
    longer unanswerable from the tail view.
  • mcptoon activity --top [N] ranks by host and by tool. "Which agent leans on
    me most, and which capability?" — a counting question the per-line tail cannot
    answer. Two bar tables, top N (default 10), honouring --since / --host /
    --failures; --json returns the counts.
  • mcptoon config set activity_keep N tunes the ledger cap. The 2000-line cap
    was a fixed constant; a heavy user can now raise or lower it (validated
    whole-number range 50–100000, bad values fail loudly). The trimmer reads it live.
  • mcptoon activity --clear --before <when> prunes only old entries. A plain
    --clear wiped everything; now you can drop calls older than 7d/24h/a date
    while keeping recent history. A torn line is kept, never silently eaten.
  • mcptoon activity colours failed/slow lines on a real terminal. Red for a
    failed call, red for a SLOW one — but only on a TTY; a pipe or NO_COLOR gets
    plain text, so a captured transcript stays clean. The signal was already in the
    text ("ERR"/"SLOW"); colour just makes it pop for a human watching --follow.
  • status and activity --summary report today's skill distributions. The
    number of mcptoon_resolve_skills calls that actually handed over skills today —
    "did it give me a capability today?", distinct from a generic routed call.
    status --json carries activity_today_skills; summary carries first_ts
    ("how far back does this history go?").
  • activity --tool <server:tool|tool> and --search <keyword> filter the view.
    --tool narrows to one tool (server:tool or a bare tool name); --search is a
    case-insensitive substring match over host/server/tool/detail/err — "when did
    that METHOD_NOT_FOUND happen?" no longer needs reading every line. Both compose
    with --since / --host / --failures / --export / --top.
  • activity --export csv now includes the ms column. It was in the json
    export but missing from csv, so a spreadsheet dropped every call's duration.
  • activity --summary reports p50/p90 latency, not just the mean. One 8s call
    among ninety 20ms calls barely moves the average yet is the one the user
    remembers; p50 says what a typical call costs, p90 what a bad one costs
    (nearest-rank, no interpolation — the honest reading for a small sample).
  • mcptoon mode — which delivery mode you are in, and which is cheapest. A
    fresh install can sit in direct (installed, but the agent still loads every
    upstream schema) and save nothing, while status and report happily showed
    the definition-side "99%". mode names the three states side by side — cli
    (shell, zero resident, cheapest), serve (MCP gateway, small fixed per-turn
    cost) and direct (most expensive) — flags the one you are in, and states the
    honest headline: the big saving is definition-side (not loading every schema);
    result compression is a rounding error (0.1–0.5%). Read-only, cache-only.
  • mcptoon statusline — one savings badge, safe to run every prompt. A
    single ≤80-column line (🎉 mcptoon · 9 tools (99% less) · ≈1.9B saved · 2,903 calls · cli) for a status bar or a turn header, so an agent that never runs a
    mcptoon command still shows it is there. Reads only cached figures, never
    spawns a server. --json for hosts that prefer structured output.
  • status and report now name the current delivery mode. status gained a
    Mode row and report a ⑥ Delivery mode section, so the "99%" can no longer
    be read without seeing whether this machine is in a mode that realises it.

Fixed

  • mcptoon import <path> accepts a bare file path. import only ever read
    --file/--from, so a positional path was silently dropped: import /nonexistent/x.json scanned every client and exited 0 as if the file had been
    read. One positional is now the file; a conflicting/extra positional errors.
  • mcptoon retrieve --list --json returns structured store stats. It printed
    human text regardless of format; scripts could not read count/bytes/ttl.
  • mcptoon select --top with a non-integer value fails loudly. --top abc
    used to fall back silently to the default 3, so a scripted --top $N with a bad
    value looked like it worked.
  • mcptoon policy clear on a missing policy errors instead of faking a
    "Cleared" report.
    It printed "Cleared: …" and exited 0 even when nothing was
    set, so mcptoon policy clear s t && echo done lied. A miss now exits 1.
  • mcptoon policy list --json returns the policy map as JSON. It printed human
    text regardless of format; scripts could not read it.
  • A bare mcptoon retrieve exits 1. It printed usage but exited 0, so
    mcptoon retrieve && echo ok reported success on a no-op. retrieve --help
    still exits 0.
  • A mistyped command that is close to a real one now errors instead of running
    the wrong command.
    mcptoon listt matched "list" inside the word and ran
    manifest; mcptoon healthh matched "health" and ran the health check — both
    exit 0, so a typo'd command in CI reported success. It now fails with a
    did-you-mean hint (exit 1). Genuine natural-language phrases still route.
  • --head / --max-chars with a non-integer value fail loudly. --head abc
    used to be swallowed (head_n stayed 0 = unlimited) and printed everything, so a
    scripted --head $N with a bad value looked like it worked.
  • search / select zero-match keep machine formats parseable. A query with no
    hits printed human text + tips for every format, so search q --json | jq (and
    select ... --json) crashed on non-JSON. Machine formats now emit an empty
    structure; humans still get the tips.
  • mcptoon select --head N caps the number of top picks shown. Only the json
    branch forwarded --head to the renderer; the human output printed every --top
    result regardless.
  • mcptoon doctor --json returns structured diagnostics. It printed human text,
    so CI could not parse the result. JSON carries checks / issues / ok /
    broken and keeps the exit-code contract (1 on any issue).
  • mcptoon config get/set/unset trim surrounding whitespace on the key.
    config get " footer " used to fail as an unknown key (get lowercased but never
    stripped; set never stripped).
  • mcptoon remove a b removes every named server. It used to delete only the
    first and silently ignore the rest; now all are removed, and any missing name
    makes the call exit 1.
  • mcptoon list honours --json / --head / --max-chars. list had no
    access to the global output flags, so --json printed human text and --head
    did nothing — a script could not get the server list as data.
  • mcptoon manifest --head N limits the number of servers shown. It was ignored
    in the human/compact/toon paths (slim already capped tools via the renderer).
  • mcptoon toggle --list --json returns JSON. It printed human text regardless.
  • mcptoon search --head N caps the result list in every output mode. Only the
    json/toon renderers honoured it; slim/compact/human printed all 20 hits, so
    search file --head 5 (documented "limit to 5 results") showed 20.
  • mcptoon call --envelope exits non-zero on a tool error. The envelope result
    carries isError: true; that path printed it and exited 0 while the non-envelope
    path already exited 1.
  • mcptoon toggle <server> <unknown-tool> is refused. It used to write a dead
    "disabled" entry and exit 0. The tool is checked against the cache when the server
    is cached (same offline-only rule as policy set).
  • mcptoon call refuses a JSON argument and --stdin together. --stdin
    silently won, so echo '{...A}' | mcptoon call s t '{...B}' --stdin used A and
    dropped B with no warning. Passing both is now an error; either alone works.
  • mcptoon policy set rejects a non-existent server or tool. policy set zzz zzz raw used to exit 0 and persist a dead rule that matched nothing. The server
    is checked against config, and the tool against the cache when one exists (an
    uncached server is accepted rather than forcing a slow fetch).
  • mcptoon health exits non-zero when a server is dead, in both output modes.
    The JSON path already exited 1; the human-readable path printed "1 dead" and
    exited 0, so mcptoon health && deploy treated an unreachable server as healthy.
  • mcptoon call exits non-zero when the tool itself reports an error. A tool
    that ran and returned isError: true (e.g. a missing required argument) printed
    its message and exited 0, so mcptoon call ... && next ran the next step on a
    failed tool. A tool-level failure is now exit 1; a payload that merely contains
    an error field (not the MCP error shape) is not misread as a failure.
  • mcptoon add --header refuses a header with no :. --header "Bearer abc"
    used to be dropped silently — the server was written with no Authorization header
    and a cheerful "Added", so auth failed later with no clue why. It now errors and
    exits 1 before writing.
  • mcptoon doctor exits non-zero when it finds issues. It printed "✗ … cannot
    start" and "N issue(s)" yet exited 0, so a CI health check read a broken machine
    as healthy. Warnings (!, e.g. an empty cache dir) are not issues and keep exit 0.
  • mcptoon inspect <server> (one argument) lists that server's tools. Its own
    usage block advertised this "list all tools" form, but the code required two
    arguments and exited 1, so the documented path was dead. Now a single argument
    renders the server's tool list; an unreachable server still errors to stderr.
  • mcptoon help <command> shows that command's own page. It used to ignore the
    argument and print the whole global page, so the two documented routes to a
    command's help (help <cmd> and <cmd> --help) disagreed. They now share one
    renderer and produce identical output; help with no argument stays the global page.
  • mcptoon --version --json prints structured JSON (version, python,
    platform) for CI/scripts; the plain --version line is unchanged.
  • Errors and usage hints go to stderr, not stdout. A bad argument, a missing
    server, an unknown policy/setting, or a usage block was printed to stdout, so
    mcptoon x >out 2>err mixed failures into out and left err empty — a script
    could not tell success text from a failure. These now go through cli._err
    (stderr) with a non-zero exit; legitimate empty results ("No servers
    configured", a zero-match search) stay on stdout because they are the answer, not
    an error. config with an unknown action now also exits 1 instead of falling
    through to 0.
  • mcptoon config --help shows config's own usage. config was missing from
    the per-command handler map even though _cmd_config has a Usage: docstring, so
    config --help re-dumped the whole global page and never showed its
    get/set/unset/reset syntax.
  • mcptoon add no longer clobbers an existing server silently. A re-run or a
    typo'd name used to replace a working server definition and print "Added". It now
    refuses with "already exists — use --force" (exit 1) unless --force is given.
  • Config writes are now atomic and keep a .bak. save_config called
    path.write_text(...) directly, so a crash mid-write, a full disk, or a reader
    landing during the write could leave a truncated/empty config.json — the user's
    whole server list, which is not regenerable. It also overwrote a good file with no
    snapshot (the other half of the 2026-10-02 "whole list replaced, no .bak"
    incident). The write now goes through a unique temp file + os.replace, and the
    last good file is copied to <config>.bak once before the first overwrite.
    set_setting uses the same atomic write.
  • mcptoon remove (and install --remove) now drop the server's schema cache.
    Removing a server from config left its per-server cache file on disk forever —
    add demo; manifest; remove demo still showed 1 file under cache/schema_cache/.
    cache.clear_server_cache() already existed and uninstall used it; the two
    remove doors simply never called it. Both now do.
  • mcptoon usage --json prints JSON, not human text. _cmd_usage only routed
    toon/mcptoon/compact to the renderer, so --json fell through to the human
    branch and printed Total calls: .... json is now routed too.
  • A typo'd command or flag suggests the nearest real one. mcptoon selec and
    mcptoon manifest --jsn failed with only "unknown ...". Both error paths now use
    cli._closest (difflib) to add a did you mean: select, serve? line, while
    keeping the exit codes (1 for a command, 2 for a flag).

Added

  • mcptoon config unset <key> and mcptoon config reset. config set had no
    inverse — once you set lang=en there was no supported way back to auto short of
    hand-editing ~/.mcptoon/settings.json. unset forgets one override (back to its
    default); reset forgets them all. Unknown keys fail loudly (exit 1), matching
    config set.
  • status --json reports skills_live and skills_stale. The human view already
    warned "index may be stale" when the built index lagged the live catalog, but a
    script reading --json saw only the index count and trusted it. The JSON now
    carries the live count and a skills_stale boolean.

Changed

  • Machine-readable --json payloads carry a schema version. The five
    script-facing views (footer-facts, status, stats, usage, bench) now run
    their payload through output.stamp_schema, adding schema_version (bumped only
    on a breaking shape change) and mcptoon_version. A consumer can now tell when a
    field moved instead of silently mis-reading a rename.
  • mcptoon <command> --help is short again. The first per-command-help fix
    printed the command's own usage followed by the whole global reference, so
    skills --help (10,814 chars) ended up longer than mcptoon --help (8,234). It
    now prints the command's own usage, a compact Options for '<cmd>': line, and a
    one-line pointer to mcptoon --help — strictly shorter than the global page.

Docs

  • The old GitHub Pages site now hard-redirects to the canonical site. The
    in-repo docs/ pages under the retired domain became redirect stubs pointing at
    mcptoon.github.io, so an old bookmark or search hit lands on the live site
    instead of a frozen copy. Two things this touched and had to be put back: the
    token-tax calculator pages (docs/tools/token-tax/*.html), which the redirect
    commit emptied while the tests still asserted their bodies, and the homepage
    GitHub vX.Y.Z badge that scripts/bump.py stamps on every release. Both are
    restored and pinned by the suite — the redirect keeps old URLs reachable, and the
    calculator pages keep working.

Don't miss a new mcptoon release

NewReleases is sending notifications on new releases.