feat(permissions): pretty-print MCP JSON

Amolith and Crush created

Add pretty-printed JSON parameters to MCP tool permission dialogs so
users can read more of the content.

Co-Authored-By: Crush <crush@charm.land>

Change summary

internal/llm/agent/mcp-tools.go                            |  2 
internal/tui/components/dialogs/permissions/permissions.go | 30 ++++++++
2 files changed, 31 insertions(+), 1 deletion(-)

Detailed changes

internal/llm/agent/mcp-tools.go 🔗

@@ -176,7 +176,7 @@ func (b *McpTool) Run(ctx context.Context, params tools.ToolCall) (tools.ToolRes
 	if sessionID == "" || messageID == "" {
 		return tools.ToolResponse{}, fmt.Errorf("session ID and message ID are required for creating a new file")
 	}
-	permissionDescription := fmt.Sprintf("execute %s with the following parameters: %s", b.Info().Name, params.Input)
+	permissionDescription := fmt.Sprintf("execute %s with the following parameters:", b.Info().Name)
 	p := b.permissions.Request(
 		permission.CreatePermissionRequest{
 			SessionID:   sessionID,

internal/tui/components/dialogs/permissions/permissions.go 🔗

@@ -1,6 +1,7 @@
 package permissions
 
 import (
+	"encoding/json"
 	"fmt"
 	"strings"
 
@@ -614,6 +615,35 @@ func (p *permissionDialogCmp) generateDefaultContent() string {
 
 	content := p.permission.Description
 
+	// Add pretty-printed JSON parameters for MCP tools
+	if p.permission.Params != nil {
+		var paramStr string
+
+		// Ensure params is a string
+		if str, ok := p.permission.Params.(string); ok {
+			paramStr = str
+		} else {
+			paramStr = fmt.Sprintf("%v", p.permission.Params)
+		}
+
+		// Try to parse as JSON for pretty printing
+		var parsed any
+		if err := json.Unmarshal([]byte(paramStr), &parsed); err == nil {
+			if b, err := json.MarshalIndent(parsed, "", "  "); err == nil {
+				if content != "" {
+					content += "\n\n"
+				}
+				content += string(b)
+			}
+		} else {
+			// Not JSON, show as-is
+			if content != "" {
+				content += "\n\n"
+			}
+			content += paramStr
+		}
+	}
+
 	content = strings.TrimSpace(content)
 	content = "\n" + content + "\n"
 	lines := strings.Split(content, "\n")