From 251b1939f72c7a53d0bf35718ce2b4c29afbb78b Mon Sep 17 00:00:00 2001 From: Jony Jas J Date: Sat, 14 Feb 2026 11:55:14 +0530 Subject: [PATCH 1/4] feat(client): add JSON-RPC log export functionality - Adds a download button to the logger toolbar allowing users to export current logs as a JSON file. Resolves #1140 --- .../client/src/components/logger-view.tsx | 38 ++++++++++++++++++- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/mcpjam-inspector/client/src/components/logger-view.tsx b/mcpjam-inspector/client/src/components/logger-view.tsx index 01c85fa4c..4c992f838 100644 --- a/mcpjam-inspector/client/src/components/logger-view.tsx +++ b/mcpjam-inspector/client/src/components/logger-view.tsx @@ -8,6 +8,7 @@ import { Trash2, PanelRightClose, Copy, + Download, } from "lucide-react"; import { JsonEditor } from "@/components/ui/json-editor"; import { Input } from "@/components/ui/input"; @@ -67,6 +68,8 @@ interface RenderableRpcItem { widgetId?: string; } +type LogEntrySnapshot = Omit; + interface LoggerViewProps { serverIds?: string[]; // Optional filter for specific server IDs onClose?: () => void; // Optional callback to close/hide the panel @@ -177,8 +180,8 @@ export function LoggerView({ setExpanded(new Set()); }; - const copyLogs = async () => { - const logs = filteredItems.map((item) => ({ + const extractLogs = (): Array => { + return filteredItems.map((item) => ({ timestamp: item.timestamp, source: item.source, serverId: item.serverId, @@ -186,6 +189,27 @@ export function LoggerView({ method: item.method, payload: item.payload, })); + }; + + const exportLogs = () => { + const logs = extractLogs(); + + const blob = new Blob([JSON.stringify(logs, null, 2)], { + type: "application/json", + }); + const url = URL.createObjectURL(blob); + const a = document.createElement("a"); + a.href = url; + a.download = `mcp-logs-${new Date().toISOString()}.json`; + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); + URL.revokeObjectURL(url); + toast.success("Logs exported"); + }; + + const copyLogs = async () => { + const logs = extractLogs(); try { await navigator.clipboard.writeText(JSON.stringify(logs, null, 2)); toast.success("Logs copied to clipboard"); @@ -248,6 +272,16 @@ export function LoggerView({

Logs

+
+
{isSearchVisible && ( From 37a906afd6668ca208919641d947ba793764f4bc Mon Sep 17 00:00:00 2001 From: Jony Jas J Date: Sat, 14 Feb 2026 12:58:39 +0530 Subject: [PATCH 3/4] feat(client): add JSON-RPC log export functionality - Added error handling - removed duplicate button caused due to merge conflict - added protol and widgets to extractLogs as optional --- .../client/src/components/logger-view.tsx | 66 ++++++------------- 1 file changed, 20 insertions(+), 46 deletions(-) diff --git a/mcpjam-inspector/client/src/components/logger-view.tsx b/mcpjam-inspector/client/src/components/logger-view.tsx index 02ffea4fd..f10f861d2 100644 --- a/mcpjam-inspector/client/src/components/logger-view.tsx +++ b/mcpjam-inspector/client/src/components/logger-view.tsx @@ -217,29 +217,35 @@ export function LoggerView({ direction: item.direction, method: item.method, payload: item.payload, + ...(item.protocol && { protocol: item.protocol }), + ...(item.widgetId && { widgetId: item.widgetId }), })); }; const exportLogs = () => { - const logs = extractLogs(); + try { + const logs = extractLogs(); - const blob = new Blob([JSON.stringify(logs, null, 2)], { - type: "application/json", - }); - const url = URL.createObjectURL(blob); - const a = document.createElement("a"); - a.href = url; - a.download = `mcp-logs-${new Date().toISOString()}.json`; - document.body.appendChild(a); - a.click(); - document.body.removeChild(a); - URL.revokeObjectURL(url); - toast.success("Logs exported"); + const blob = new Blob([JSON.stringify(logs, null, 2)], { + type: "application/json", + }); + const url = URL.createObjectURL(blob); + const a = document.createElement("a"); + a.href = url; + a.download = `mcp-logs-${new Date().toISOString()}.json`; + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); + URL.revokeObjectURL(url); + toast.success("Logs exported"); + } catch { + toast.error("Failed to export logs"); + } }; const copyLogs = async () => { - const logs = extractLogs(); try { + const logs = extractLogs(); await navigator.clipboard.writeText(JSON.stringify(logs, null, 2)); toast.success("Logs copied to clipboard"); } catch { @@ -487,38 +493,6 @@ export function LoggerView({ {/* Push action buttons to the right when search is hidden */} {!isSearchVisible &&
} - - - - {onClose && isCollapsable && ( - - )}
From 01fc037569257353f5bd8e9de9949922c79c8f76 Mon Sep 17 00:00:00 2001 From: Jony Jas J Date: Sat, 21 Feb 2026 17:39:17 +0530 Subject: [PATCH 4/4] feat(client): add JSON-RPC log export functionality --- .../client/src/components/logger-view.tsx | 96 +++++++++---------- 1 file changed, 44 insertions(+), 52 deletions(-) diff --git a/mcpjam-inspector/client/src/components/logger-view.tsx b/mcpjam-inspector/client/src/components/logger-view.tsx index f10f861d2..ecf8f9795 100644 --- a/mcpjam-inspector/client/src/components/logger-view.tsx +++ b/mcpjam-inspector/client/src/components/logger-view.tsx @@ -46,6 +46,7 @@ import { cn } from "@/lib/utils"; type RpcDirection = "in" | "out" | string; type TrafficSource = "mcp-server" | "mcp-apps"; +type LogEntrySnapshot = Omit; interface RpcEventMessage { serverId: string; @@ -66,8 +67,6 @@ interface RenderableRpcItem { widgetId?: string; } -type LogEntrySnapshot = Omit; - interface LoggerViewProps { serverIds?: string[]; // Optional filter for specific server IDs onClose?: () => void; // Optional callback to close/hide the panel @@ -303,55 +302,6 @@ export function LoggerView({ return (
-
-
-

Logs

-
- - - - {onClose && isCollapsable && ( - - )} -
-
-
-
{isSearchVisible && ( <> @@ -493,6 +443,48 @@ export function LoggerView({ {/* Push action buttons to the right when search is hidden */} {!isSearchVisible &&
} + + + + + {onClose && isCollapsable && ( + + )}
@@ -591,4 +583,4 @@ export function LoggerView({ ); } -export default LoggerView; +export default LoggerView; \ No newline at end of file