Skip to content

Show what tools did in the REPL: parallel call count, Ctrl+O arguments, MCP errors and stderr - #151

Merged
fuseraft merged 7 commits into
mainfrom
fix/repl-tool-visibility
Oct 17, 2026
Merged

fuseraft merged 7 commits into
mainfrom
fix/repl-tool-visibility

Conversation

@fuseraft

Copy link
Copy Markdown
Owner

Found by driving the full-screen REPL against sql-mcp and four live databases (Postgres, MySQL, SQL Server, Oracle). The SQL work went fine. Checking what the agent actually did took the session file, and a few TUI states were misleading.

Changes

  • Every parallel tool call is counted. The stream loop read only the first FunctionCallContent and FunctionResultContent in each chunk. A model that calls tools in parallel sends them all in one chunk, so six calls showed as "1 tool". Only the first of several parallel writes reached the file-change list, the failure count and step verification.
  • Ctrl+O shows a call's arguments above its result, so the SQL an MCP tool ran and the parameters it bound can be read in the REPL.
  • MCP results read as MCP results. The viewer and the failure line show a result's text content, not the CallToolResult JSON around it. A result with isError counts as a failed call: it gets the red line and counts toward the consecutive-failure cutoff. A notice the loop guard appends after the JSON is kept, and doesn't stop the result from being recognized.
  • /mcp add asks for a stdio server's environment (KEY=VALUE). Env values now expand ${ENV_VAR}, as Url and Headers already do, so a secret need not be saved in the config. The wizard also says which transport and authentication were picked.
  • /mcp log <name> shows the last 200 lines a stdio server wrote to stderr, which is where servers log. They're kept even when the connect fails. Before, those lines were dropped, though errors like sql-mcp's "The server log lists why" point there.
  • Memory extraction leaves out retrieved data. At /exit it had saved a test table of every employee's salary, and each table's columns. The prompt now rules out tool-retrieved data, personal details of anyone but the user, secrets, and what can be cheaply looked up again.
  • TUI status line:
    • No "working" spinner or "Enter adds to the turn" while a question waits in the panel.
    • After /exit, it says the session is ending, and input is refused with a note. Before, input was echoed as "(sent when this ends)" and then dropped.

Tests

  • New: ParallelCalls_AreAllCountedAndReported (fails before the fix), McpToolResultTests, McpSessionManagerStderrTests (stderr kept, ${ENV_VAR} expanded in Env), ReplCommandsMcpTests, StatusViewTests, and viewer cases in TuiRendererTests.
  • Full suite: 3315 passed.
  • Live in the TUI: footer counts 5 tools for 4 parallel calls plus 1; Ctrl+O shows SQL and bound parameters; both of two consecutive MCP failures are marked failed; /mcp log shows sql-mcp's reason for refusing a login; no memories saved after the SQL session; typing during /exit gets the note.
  • McpSessionManagerStderrTests has a cmd.exe branch for Windows that CI (Linux) doesn't run.

The stream loop read only the first FunctionCallContent and the first
FunctionResultContent in each chunk. A model calling tools in parallel
sends them all in one chunk, so the footer said "1 tool" for six calls,
and only the first of several parallel writes reached the file-change
list, the failure count and step verification.
The viewer showed a call's result but not what it was asked to do, so
checking the SQL an MCP tool ran, or the parameters it bound, meant
digging through the session file. Each kept output now has the call's
arguments above its result.

An MCP tool's result is shown as its text content rather than the
CallToolResult JSON around it, and one with isError set counts as a
failed call: it gets the red line under the call and counts toward the
consecutive-failure cutoff, as the built-in tools' [ERROR] results do.
The wizard had no way to set Env, so a server that reads a password from
the environment (sql-mcp's PasswordEnvVar, for one) started without it
unless fuseraft itself happened to have the variable. It now asks for
KEY=VALUE pairs, and Env values expand ${ENV_VAR} tokens as Url and
Headers already do, so a secret need not be written into the saved
config.

The wizard also says which transport and authentication were picked;
the full-screen REPL showed only the question.
A stdio server's stderr is where it logs, and its errors often say to
look there: sql-mcp refuses a database with "The server log lists
why." The REPL dropped those lines, so the reason couldn't be read
without running the server by hand. The manager now keeps each stdio
server's last 200 stderr lines, kept even when the connect fails, and
/mcp log <name> prints them and keeps them for Ctrl+O.
…ries

Memory extraction saved what the session had read: a table of every
employee's salary from a test database, and the columns of each table.
The prompt now says not to save tool-retrieved data, personal
information about anyone but the user, or secrets, nor what a future
session can cheaply look up again.
While /mcp add or any other question had the panel, the status line
kept spinning "working 15s" with "Enter adds to the turn", though
nothing was running and Enter answered the question. The spinner and
the keys are now left out until the panel closes.
Saving memories at /exit takes a model call, and the status line kept
saying "Enter adds to the turn", so what was typed meanwhile was
echoed as "(sent when this ends)" and then dropped with the session.
The status line now says the session is ending, and input is refused
with a note instead of being queued.
@fuseraft
fuseraft merged commit fb2048b into main Oct 17, 2026
9 checks passed
@fuseraft
fuseraft deleted the fix/repl-tool-visibility branch October 17, 2026 22:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant