From 58e796a5a87f830fa23158c512abaf32206b313e Mon Sep 17 00:00:00 2001 From: Ashwin Bhat Date: Tue, 8 Oct 2024 13:06:08 -0700 Subject: [PATCH 1/2] add command history --- client/src/App.tsx | 204 +++++++++++++---------- client/src/components/CommandHistory.tsx | 94 +++++++++++ 2 files changed, 213 insertions(+), 85 deletions(-) create mode 100644 client/src/components/CommandHistory.tsx diff --git a/client/src/App.tsx b/client/src/App.tsx index 01d5552..313eb80 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -19,6 +19,7 @@ import ResourcesTab, { Resource } from "./components/ResourcesTab"; import NotificationsTab from "./components/NotificationsTab"; import PromptsTab, { Prompt } from "./components/PromptsTab"; import ToolsTab, { Tool as ToolType } from "./components/ToolsTab"; +import CommandHistory from "./components/CommandHistory"; const App = () => { const [socket, setSocket] = useState(null); @@ -39,6 +40,9 @@ const App = () => { "/Users/ashwin/code/example-servers/build/everything/index.js", ); const [mcpConnected, setMcpConnected] = useState(false); + const [commandHistory, setCommandHistory] = useState< + Array<{ command: string; response: string | null }> + >([]); useEffect(() => { const ws = new WebSocket("ws://localhost:3000"); @@ -55,25 +59,33 @@ const App = () => { if (message.type === "resources") { setResources(message.data.resources); setError(null); + updateCommandHistory(message); } else if (message.type === "resource") { setResourceContent(JSON.stringify(message.data, null, 2)); setError(null); + updateCommandHistory(message); } else if (message.type === "prompts") { setPrompts(message.data.prompts); setError(null); + updateCommandHistory(message); } else if (message.type === "prompt") { setPromptContent(JSON.stringify(message.data, null, 2)); setError(null); + updateCommandHistory(message); } else if (message.type === "tools") { setTools(message.data.tools); setError(null); + updateCommandHistory(message); } else if (message.type === "toolResult") { setToolResult(JSON.stringify(message.data, null, 2)); setError(null); + updateCommandHistory(message); } else if (message.type === "error") { setError(message.message); + updateCommandHistory(message); } else if (message.type === "connected") { setMcpConnected(true); + updateCommandHistory(message); } }; @@ -89,10 +101,29 @@ const App = () => { return () => ws.close(); }, []); + const updateCommandHistory = (response: unknown) => { + setCommandHistory((prev) => { + const lastCommand = prev[prev.length - 1]; + if (lastCommand && lastCommand.response === null) { + const updatedHistory = [...prev]; + updatedHistory[updatedHistory.length - 1] = { + ...lastCommand, + response: JSON.stringify(response), + }; + return updatedHistory; + } + return prev; + }); + }; + const sendWebSocketMessage = (message: object) => { if (socket) { console.log("Sending WebSocket message:", message); socket.send(JSON.stringify(message)); + setCommandHistory((prev) => [ + ...prev, + { command: JSON.stringify(message), response: null }, + ]); } }; @@ -136,97 +167,100 @@ const App = () => {

MCP Inspector

-
-
-

Connect MCP Server

-
- setCommand(e.target.value)} - /> - setArgs(e.target.value)} - /> - -
-
- {mcpConnected ? ( - - - - - Resources - - - - Prompts - - - - Requests - - - - Notifications - - - - Tools - - - - Console - - - -
- +
+
+

Connect MCP Server

+
+ setCommand(e.target.value)} /> - - setArgs(e.target.value)} /> - - - +
- - ) : ( -
-

- Connect to an MCP server to start inspecting -

- )} + {mcpConnected ? ( + + + + + Resources + + + + Prompts + + + + Requests + + + + Notifications + + + + Tools + + + + Console + + + +
+ + + + + + +
+
+ ) : ( +
+

+ Connect to an MCP server to start inspecting +

+
+ )} +
+
); }; diff --git a/client/src/components/CommandHistory.tsx b/client/src/components/CommandHistory.tsx new file mode 100644 index 0000000..853c17e --- /dev/null +++ b/client/src/components/CommandHistory.tsx @@ -0,0 +1,94 @@ +import { useState } from "react"; +import { Copy } from "lucide-react"; + +const CommandHistory = ({ + commandHistory, +}: { + commandHistory: Array<{ command: string; response: string | null }>; +}) => { + const [expandedCommands, setExpandedCommands] = useState<{ + [key: number]: boolean; + }>({}); + + const toggleCommandExpansion = (index: number) => { + setExpandedCommands((prev) => ({ ...prev, [index]: !prev[index] })); + }; + + const copyToClipboard = (text: string) => { + navigator.clipboard.writeText(text); + }; + + return ( +
+

Command History

+
    + {commandHistory + .slice() + .reverse() + .map((cmd, index) => ( +
  • +
    + toggleCommandExpansion(commandHistory.length - 1 - index) + } + > + + {commandHistory.length - index}.{" "} + {JSON.parse(cmd.command).type} + + + {expandedCommands[commandHistory.length - 1 - index] + ? "▼" + : "▶"} + +
    + {expandedCommands[commandHistory.length - 1 - index] && ( + <> +
    +
    + + Command: + + +
    +
    +                      {JSON.stringify(JSON.parse(cmd.command), null, 2)}
    +                    
    +
    + {cmd.response && ( +
    +
    + + Response: + + +
    +
    +                        {JSON.stringify(JSON.parse(cmd.response), null, 2)}
    +                      
    +
    + )} + + )} +
  • + ))} +
+
+ ); +}; + +export default CommandHistory; From 936a50b14bb6735b521793e486b5dc2ee73be42a Mon Sep 17 00:00:00 2001 From: Ashwin Bhat Date: Wed, 9 Oct 2024 08:54:37 -0700 Subject: [PATCH 2/2] remove Command verbiage, refactor slightly --- client/src/App.tsx | 32 ++++++-------- .../{CommandHistory.tsx => History.tsx} | 42 +++++++++---------- 2 files changed, 34 insertions(+), 40 deletions(-) rename client/src/components/{CommandHistory.tsx => History.tsx} (67%) diff --git a/client/src/App.tsx b/client/src/App.tsx index 313eb80..ad54ac0 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -19,7 +19,7 @@ import ResourcesTab, { Resource } from "./components/ResourcesTab"; import NotificationsTab from "./components/NotificationsTab"; import PromptsTab, { Prompt } from "./components/PromptsTab"; import ToolsTab, { Tool as ToolType } from "./components/ToolsTab"; -import CommandHistory from "./components/CommandHistory"; +import History from "./components/CommandHistory"; const App = () => { const [socket, setSocket] = useState(null); @@ -40,8 +40,8 @@ const App = () => { "/Users/ashwin/code/example-servers/build/everything/index.js", ); const [mcpConnected, setMcpConnected] = useState(false); - const [commandHistory, setCommandHistory] = useState< - Array<{ command: string; response: string | null }> + const [requestHistory, setRequestHistory] = useState< + Array<{ request: string; response: string | null }> >([]); useEffect(() => { @@ -59,34 +59,28 @@ const App = () => { if (message.type === "resources") { setResources(message.data.resources); setError(null); - updateCommandHistory(message); } else if (message.type === "resource") { setResourceContent(JSON.stringify(message.data, null, 2)); setError(null); - updateCommandHistory(message); } else if (message.type === "prompts") { setPrompts(message.data.prompts); setError(null); - updateCommandHistory(message); } else if (message.type === "prompt") { setPromptContent(JSON.stringify(message.data, null, 2)); setError(null); - updateCommandHistory(message); } else if (message.type === "tools") { setTools(message.data.tools); setError(null); - updateCommandHistory(message); } else if (message.type === "toolResult") { setToolResult(JSON.stringify(message.data, null, 2)); setError(null); - updateCommandHistory(message); } else if (message.type === "error") { setError(message.message); - updateCommandHistory(message); } else if (message.type === "connected") { setMcpConnected(true); - updateCommandHistory(message); } + + updateRequestHistory(message); }; ws.onerror = () => { @@ -101,13 +95,13 @@ const App = () => { return () => ws.close(); }, []); - const updateCommandHistory = (response: unknown) => { - setCommandHistory((prev) => { - const lastCommand = prev[prev.length - 1]; - if (lastCommand && lastCommand.response === null) { + const updateRequestHistory = (response: unknown) => { + setRequestHistory((prev) => { + const lastRequest = prev[prev.length - 1]; + if (lastRequest && lastRequest.response === null) { const updatedHistory = [...prev]; updatedHistory[updatedHistory.length - 1] = { - ...lastCommand, + ...lastRequest, response: JSON.stringify(response), }; return updatedHistory; @@ -120,9 +114,9 @@ const App = () => { if (socket) { console.log("Sending WebSocket message:", message); socket.send(JSON.stringify(message)); - setCommandHistory((prev) => [ + setRequestHistory((prev) => [ ...prev, - { command: JSON.stringify(message), response: null }, + { request: JSON.stringify(message), response: null }, ]); } }; @@ -260,7 +254,7 @@ const App = () => {
- + ); }; diff --git a/client/src/components/CommandHistory.tsx b/client/src/components/History.tsx similarity index 67% rename from client/src/components/CommandHistory.tsx rename to client/src/components/History.tsx index 853c17e..8ccf3ab 100644 --- a/client/src/components/CommandHistory.tsx +++ b/client/src/components/History.tsx @@ -1,17 +1,17 @@ import { useState } from "react"; import { Copy } from "lucide-react"; -const CommandHistory = ({ - commandHistory, +const History = ({ + requestHistory, }: { - commandHistory: Array<{ command: string; response: string | null }>; + requestHistory: Array<{ request: string; response: string | null }>; }) => { - const [expandedCommands, setExpandedCommands] = useState<{ + const [expandedRequests, setExpandedRequests] = useState<{ [key: number]: boolean; }>({}); - const toggleCommandExpansion = (index: number) => { - setExpandedCommands((prev) => ({ ...prev, [index]: !prev[index] })); + const toggleRequestExpansion = (index: number) => { + setExpandedRequests((prev) => ({ ...prev, [index]: !prev[index] })); }; const copyToClipboard = (text: string) => { @@ -20,12 +20,12 @@ const CommandHistory = ({ return (
-

Command History

+

History

    - {commandHistory + {requestHistory .slice() .reverse() - .map((cmd, index) => ( + .map((request, index) => (
  • - toggleCommandExpansion(commandHistory.length - 1 - index) + toggleRequestExpansion(requestHistory.length - 1 - index) } > - {commandHistory.length - index}.{" "} - {JSON.parse(cmd.command).type} + {requestHistory.length - index}.{" "} + {JSON.parse(request.request).type} - {expandedCommands[commandHistory.length - 1 - index] + {expandedRequests[requestHistory.length - 1 - index] ? "▼" : "▶"}
- {expandedCommands[commandHistory.length - 1 - index] && ( + {expandedRequests[requestHistory.length - 1 - index] && ( <>
- Command: + Request:
-                      {JSON.stringify(JSON.parse(cmd.command), null, 2)}
+                      {JSON.stringify(JSON.parse(request.request), null, 2)}
                     
- {cmd.response && ( + {request.response && (
Response:
-                        {JSON.stringify(JSON.parse(cmd.response), null, 2)}
+                        {JSON.stringify(JSON.parse(request.response), null, 2)}
                       
)} @@ -91,4 +91,4 @@ const CommandHistory = ({ ); }; -export default CommandHistory; +export default History;