Label MCP tool calls in tool group summaries

A tool the registry does not hold was counted as a command, so a turn's
MCP calls showed up as "2 commands" in its tool group summary and as
commands started in the status line.

Every MCP tool name has the mcp_ prefix, so those calls now have their
own activity kind. The summary reads "1 MCP call" or "2 MCP calls", and
the status line counts MCP calls made.
This commit is contained in:
Pranit committed 2026-10-27 11:12:46 -04:00
1 parent 70866b2712
commit 1ce845071e
5 files changed
+25 -7

No files matched your search

+1
View File
@@ -1338,6 +1338,7 @@ pub fn Runtime(comptime App: type) type {
.open => stream.open_count += 1,
.command => stream.command_count += 1,
.subagent => stream.subagent_count += 1,
.mcp => stream.mcp_count += 1,
.ask => {},
}
}
+3 -1
View File
@@ -99,6 +99,7 @@ fn streamStatusVerb(stream: StreamState) []const u8 {
.subagent => "delegating",
.open => "opening",
.ask => "asking",
.mcp => "calling",
};
}
@@ -231,7 +232,7 @@ fn buildThinkingLabelFull(buf: []u8, stream: StreamState) []const u8 {
return out.buffered();
}
fn activityParts(stream: StreamState) [7]ActivityPart {
fn activityParts(stream: StreamState) [8]ActivityPart {
return .{
.{ .count = stream.read_count, .singular = "file", .plural = "files", .verb = "read" },
.{ .count = stream.list_count, .singular = "directory", .plural = "directories", .verb = "listed" },
@@ -240,6 +241,7 @@ fn activityParts(stream: StreamState) [7]ActivityPart {
.{ .count = stream.command_count, .singular = "command", .plural = "commands", .verb = "started" },
.{ .count = stream.subagent_count, .singular = "subagent", .plural = "subagents", .verb = "created" },
.{ .count = stream.open_count, .singular = "file", .plural = "files", .verb = "opened" },
.{ .count = stream.mcp_count, .singular = "MCP call", .plural = "MCP calls", .verb = "made" },
};
}
+3
View File
@@ -290,6 +290,7 @@ pub const StreamState = struct {
open_count: usize = 0,
command_count: usize = 0,
subagent_count: usize = 0,
mcp_count: usize = 0,
token_progress: TurnTokenProgress = .{},
last_activity_kind: ?ToolActivityKind = null,
/// When the turn started; 0 hides the elapsed counter and activity blink.
@@ -2476,6 +2477,8 @@ pub const ToolActivityKind = enum {
command,
subagent,
ask,
/// A call to an MCP server's tool.
mcp,
};
pub const QuestionOption = struct {
+8 -2
View File
@@ -568,7 +568,13 @@ pub fn dispatchRunCommandCompatibility(
}
pub fn toolActivityKind(registry: Registry, tool_name: []const u8) core_types.ToolActivityKind {
return if (registry.lookup(tool_name)) |tool| tool.activity_kind else .command;
return if (registry.lookup(tool_name)) |tool| tool.activity_kind else unregisteredActivityKind(tool_name);
}
/// A name the registry does not hold is an MCP server's tool when it has the
/// `mcp_` prefix every MCP tool name gets, and is otherwise treated as a command.
fn unregisteredActivityKind(tool_name: []const u8) core_types.ToolActivityKind {
return if (std.mem.startsWith(u8, tool_name, "mcp_")) .mcp else .command;
}
pub fn staticPresentation(tool: Tool) CallPresentation {
@@ -609,7 +615,7 @@ pub fn toolActivityKindForCall(
call: core_types.ToolCall,
) core_types.ToolActivityKind {
const presentation = toolCallPresentation(alloc, registry, call) orelse
return .command;
return unregisteredActivityKind(call.name);
return presentation.activity_kind;
}
+10 -4
View File
@@ -149,8 +149,10 @@ const category_labels = [_][]const u8{
"command",
"subagent",
"browser",
"MCP call",
};
const command_category_index = 5;
const mcp_category_index = 8;
const Summary = struct {
total: usize = 0,
@@ -184,6 +186,7 @@ fn categoryIndex(kind: types.ToolActivityKind) ?usize {
.command => command_category_index,
.subagent => 6,
.ask => null,
.mcp => mcp_category_index,
};
}
@@ -531,10 +534,13 @@ fn formatGroupSummary(alloc: std.mem.Allocator, summary: Summary) ![]u8 {
const index = next_index orelse break;
emitted[index] = true;
const count = summary.categories[index];
const label = if (index == command_category_index and count != 1)
"commands"
else
category_labels[index];
const label = if (count == 1)
category_labels[index]
else switch (index) {
command_category_index => "commands",
mcp_category_index => "MCP calls",
else => category_labels[index],
};
try appendSegment(&out.writer, count, label);
}
try appendSegment(&out.writer, summary.completion_unreported, "unreported");