Problem
When an MCP server is configured with "requires approval" permission, the approval prompt shows only the tool name (Dropbox/upload) with zero argument context. The user has no idea what the tool is about to do — which path, which file, what payload.
Current approval prompt (Slack):
Tool: `Dropbox/upload`
Request: `Dropbox/upload`
This gives the approver no actionable information. The request line should surface the arguments (paths, targets, values) so the user can make an informed decision.
Root Cause
`DefaultApprovalMatcher.FormatForDisplay()` (`src/Netclaw.Security/IToolApprovalMatcher.cs:772-773`) receives the arguments dictionary but ignores it entirely:
public string FormatForDisplay(ToolName toolName, IDictionary<string, object?>? arguments)
=> toolName.Value;
Contrast with `ShellApprovalMatcher.FormatForDisplay()` at line 572, which does extract and format the command from arguments:
public string FormatForDisplay(ToolName toolName, IDictionary<string, object?>? arguments)
{
var command = GetCommand(arguments); // extracts "command" arg
if (string.IsNullOrWhiteSpace(command))
return "(empty command)";
// ... formats multi-line commands ...
return command;
}
Shell approval prompts show the full command text. MCP tool prompts show only the tool name.
Data Flow
The `displayText` flows through the entire pipeline at a single point:
- `ToolAccessPolicy.CheckApprovalGate()` (line 315): `displayText = matcher.FormatForDisplay(toolName, arguments)`
- → `ToolApprovalContext` → `ToolApprovalRequiredException` → `SessionToolExecutionPipeline` (line 467)
- → `ToolInteractionRequest.DisplayText`
- → Each channel renderer (Slack / Discord / Mattermost / CLI) renders `request.DisplayText` as-is
No renderer changes are needed — all channels already render whatever `DisplayText` contains.
Affected Channels
All channels are affected equally:
| Channel |
Label |
What it renders |
| Slack |
`Request:` |
tool name only |
| Discord |
`Action:` |
tool name only |
| Mattermost |
`Action:` |
tool name only |
Proposed Fix
Update `DefaultApprovalMatcher.FormatForDisplay()` to format the arguments into a readable summary:
public string FormatForDisplay(ToolName toolName, IDictionary<string, object?>? arguments)
{
if (arguments is null || arguments.Count == 0)
return toolName.Value;
// Build: tool_name(arg1=value, arg2=value, ...)
// Truncate long values, summarize binary content
var parts = arguments
.Select(kv => $"{kv.Key}={FormatArgumentValue(kv.Value)}")
.Where(s => !string.IsNullOrEmpty(s));
return $"{toolName.Value}({string.Join(", ", parts)})}";
}
With this fix, the approval prompt would show:
Tool: `Dropbox/upload`
Request: `Dropbox/upload(path=/docs/README.md, contents=(2.4 KB))`
Considerations
- Value formatting: MCP arguments arrive as `JsonElement` values — need to handle strings, numbers, objects, arrays
- Truncation: Long string values should be summarized (`(2.4 KB)`, `(15 lines)`) rather than dumped verbatim. The outer budget is handled by `ApprovalDisplayTextFormatter.Truncate()` (2500 chars for Slack, 1700 for Discord)
- Binary detection: Skip or summarize base64/hex blobs
- Key ordering: Sort alphabetically or surface important keys (paths, targets, URLs) first
Files to Change
- `src/Netclaw.Security/IToolApprovalMatcher.cs` — `DefaultApprovalMatcher.FormatForDisplay()`
- Add matching tests in `src/Netclaw.Security.Tests/`
Problem
When an MCP server is configured with "requires approval" permission, the approval prompt shows only the tool name (
Dropbox/upload) with zero argument context. The user has no idea what the tool is about to do — which path, which file, what payload.Current approval prompt (Slack):
This gives the approver no actionable information. The request line should surface the arguments (paths, targets, values) so the user can make an informed decision.
Root Cause
`DefaultApprovalMatcher.FormatForDisplay()` (`src/Netclaw.Security/IToolApprovalMatcher.cs:772-773`) receives the arguments dictionary but ignores it entirely:
Contrast with `ShellApprovalMatcher.FormatForDisplay()` at line 572, which does extract and format the command from arguments:
Shell approval prompts show the full command text. MCP tool prompts show only the tool name.
Data Flow
The `displayText` flows through the entire pipeline at a single point:
No renderer changes are needed — all channels already render whatever `DisplayText` contains.
Affected Channels
All channels are affected equally:
Proposed Fix
Update `DefaultApprovalMatcher.FormatForDisplay()` to format the arguments into a readable summary:
With this fix, the approval prompt would show:
Considerations
Files to Change