@@ -138,11 +138,9 @@ const App = () => {
138138 > ( [ ] ) ;
139139 const [ isAuthDebuggerVisible , setIsAuthDebuggerVisible ] = useState ( false ) ;
140140
141- // Auth debugger state
142141 const [ authState , setAuthState ] =
143142 useState < AuthDebuggerState > ( EMPTY_DEBUGGER_STATE ) ;
144143
145- // Helper function to update specific auth state properties
146144 const updateAuthState = ( updates : Partial < AuthDebuggerState > ) => {
147145 setAuthState ( ( prev ) => ( { ...prev , ...updates } ) ) ;
148146 } ;
@@ -170,6 +168,19 @@ const App = () => {
170168 const [ nextToolCursor , setNextToolCursor ] = useState < string | undefined > ( ) ;
171169 const progressTokenRef = useRef ( 0 ) ;
172170
171+ const [ activeTab , setActiveTab ] = useState < string > ( ( ) => {
172+ const hash = window . location . hash . slice ( 1 ) ;
173+ const initialTab = hash || "resources" ;
174+ return initialTab ;
175+ } ) ;
176+
177+ const currentTabRef = useRef < string > ( activeTab ) ;
178+ const lastToolCallOriginTabRef = useRef < string > ( activeTab ) ;
179+
180+ useEffect ( ( ) => {
181+ currentTabRef . current = activeTab ;
182+ } , [ activeTab ] ) ;
183+
173184 const { height : historyPaneHeight , handleDragStart } = useDraggablePane ( 300 ) ;
174185 const {
175186 width : sidebarWidth ,
@@ -213,6 +224,8 @@ const App = () => {
213224 ] ) ;
214225 } ,
215226 onElicitationRequest : ( request , resolve ) => {
227+ const currentTab = lastToolCallOriginTabRef . current ;
228+
216229 setPendingElicitationRequests ( ( prev ) => [
217230 ...prev ,
218231 {
@@ -222,16 +235,52 @@ const App = () => {
222235 message : request . params . message ,
223236 requestedSchema : request . params . requestedSchema ,
224237 } ,
238+ originatingTab : currentTab ,
225239 resolve,
226240 decline : ( error : Error ) => {
227241 console . error ( "Elicitation request rejected:" , error ) ;
228242 } ,
229243 } ,
230244 ] ) ;
245+
246+ setActiveTab ( "elicitations" ) ;
247+ window . location . hash = "elicitations" ;
231248 } ,
232249 getRoots : ( ) => rootsRef . current ,
233250 } ) ;
234251
252+ useEffect ( ( ) => {
253+ if ( serverCapabilities ) {
254+ const hash = window . location . hash . slice ( 1 ) ;
255+
256+ const validTabs = [
257+ ...( serverCapabilities ?. resources ? [ "resources" ] : [ ] ) ,
258+ ...( serverCapabilities ?. prompts ? [ "prompts" ] : [ ] ) ,
259+ ...( serverCapabilities ?. tools ? [ "tools" ] : [ ] ) ,
260+ "ping" ,
261+ "sampling" ,
262+ "elicitations" ,
263+ "roots" ,
264+ "auth" ,
265+ ] ;
266+
267+ const isValidTab = validTabs . includes ( hash ) ;
268+
269+ if ( ! isValidTab ) {
270+ const defaultTab = serverCapabilities ?. resources
271+ ? "resources"
272+ : serverCapabilities ?. prompts
273+ ? "prompts"
274+ : serverCapabilities ?. tools
275+ ? "tools"
276+ : "ping" ;
277+
278+ setActiveTab ( defaultTab ) ;
279+ window . location . hash = defaultTab ;
280+ }
281+ }
282+ } , [ serverCapabilities ] ) ;
283+
235284 useEffect ( ( ) => {
236285 localStorage . setItem ( "lastCommand" , command ) ;
237286 } , [ command ] ) ;
@@ -260,7 +309,6 @@ const App = () => {
260309 saveInspectorConfig ( CONFIG_LOCAL_STORAGE_KEY , config ) ;
261310 } , [ config ] ) ;
262311
263- // Auto-connect to previously saved serverURL after OAuth callback
264312 const onOAuthConnect = useCallback (
265313 ( serverUrl : string ) => {
266314 setSseUrl ( serverUrl ) ;
@@ -270,7 +318,6 @@ const App = () => {
270318 [ connectMcpServer ] ,
271319 ) ;
272320
273- // Update OAuth debug state during debug callback
274321 const onOAuthDebugConnect = useCallback (
275322 async ( {
276323 authorizationCode,
@@ -291,7 +338,6 @@ const App = () => {
291338 }
292339
293340 if ( restoredState && authorizationCode ) {
294- // Restore the previous auth state and continue the OAuth flow
295341 let currentState : AuthDebuggerState = {
296342 ...restoredState ,
297343 authorizationCode,
@@ -302,12 +348,10 @@ const App = () => {
302348 } ;
303349
304350 try {
305- // Create a new state machine instance to continue the flow
306351 const stateMachine = new OAuthStateMachine ( sseUrl , ( updates ) => {
307352 currentState = { ...currentState , ...updates } ;
308353 } ) ;
309354
310- // Continue stepping through the OAuth flow from where we left off
311355 while (
312356 currentState . oauthStep !== "complete" &&
313357 currentState . oauthStep !== "authorization_code"
@@ -316,7 +360,6 @@ const App = () => {
316360 }
317361
318362 if ( currentState . oauthStep === "complete" ) {
319- // After the flow completes or reaches a user-input step, update the app state
320363 updateAuthState ( {
321364 ...currentState ,
322365 statusMessage : {
@@ -339,7 +382,6 @@ const App = () => {
339382 } ) ;
340383 }
341384 } else if ( authorizationCode ) {
342- // Fallback to the original behavior if no state was restored
343385 updateAuthState ( {
344386 authorizationCode,
345387 oauthStep : "token_request" ,
@@ -349,7 +391,6 @@ const App = () => {
349391 [ sseUrl ] ,
350392 ) ;
351393
352- // Load OAuth tokens when sseUrl changes
353394 useEffect ( ( ) => {
354395 const loadOAuthTokens = async ( ) => {
355396 try {
@@ -408,6 +449,18 @@ const App = () => {
408449 }
409450 } , [ ] ) ;
410451
452+ useEffect ( ( ) => {
453+ const handleHashChange = ( ) => {
454+ const hash = window . location . hash . slice ( 1 ) ;
455+ if ( hash && hash !== activeTab ) {
456+ setActiveTab ( hash ) ;
457+ }
458+ } ;
459+
460+ window . addEventListener ( "hashchange" , handleHashChange ) ;
461+ return ( ) => window . removeEventListener ( "hashchange" , handleHashChange ) ;
462+ } , [ activeTab ] ) ;
463+
411464 const handleApproveSampling = ( id : number , result : CreateMessageResult ) => {
412465 setPendingSampleRequests ( ( prev ) => {
413466 const request = prev . find ( ( r ) => r . id === id ) ;
@@ -430,7 +483,34 @@ const App = () => {
430483 ) => {
431484 setPendingElicitationRequests ( ( prev ) => {
432485 const request = prev . find ( ( r ) => r . id === id ) ;
433- request ?. resolve ( response ) ;
486+ if ( request ) {
487+ request . resolve ( response ) ;
488+
489+ if ( request . originatingTab ) {
490+ const originatingTab = request . originatingTab ;
491+
492+ const validTabs = [
493+ ...( serverCapabilities ?. resources ? [ "resources" ] : [ ] ) ,
494+ ...( serverCapabilities ?. prompts ? [ "prompts" ] : [ ] ) ,
495+ ...( serverCapabilities ?. tools ? [ "tools" ] : [ ] ) ,
496+ "ping" ,
497+ "sampling" ,
498+ "elicitations" ,
499+ "roots" ,
500+ "auth" ,
501+ ] ;
502+
503+ if ( validTabs . includes ( originatingTab ) ) {
504+ setActiveTab ( originatingTab ) ;
505+ window . location . hash = originatingTab ;
506+
507+ setTimeout ( ( ) => {
508+ setActiveTab ( originatingTab ) ;
509+ window . location . hash = originatingTab ;
510+ } , 100 ) ;
511+ }
512+ }
513+ }
434514 return prev . filter ( ( r ) => r . id !== id ) ;
435515 } ) ;
436516 } ;
@@ -492,7 +572,23 @@ const App = () => {
492572 setNextResourceTemplateCursor ( response . nextCursor ) ;
493573 } ;
494574
575+ const getPrompt = async ( name : string , args : Record < string , string > = { } ) => {
576+ lastToolCallOriginTabRef . current = currentTabRef . current ;
577+
578+ const response = await sendMCPRequest (
579+ {
580+ method : "prompts/get" as const ,
581+ params : { name, arguments : args } ,
582+ } ,
583+ GetPromptResultSchema ,
584+ "prompts" ,
585+ ) ;
586+ setPromptContent ( JSON . stringify ( response , null , 2 ) ) ;
587+ } ;
588+
495589 const readResource = async ( uri : string ) => {
590+ lastToolCallOriginTabRef . current = currentTabRef . current ;
591+
496592 const response = await sendMCPRequest (
497593 {
498594 method : "resources/read" as const ,
@@ -549,18 +645,6 @@ const App = () => {
549645 setNextPromptCursor ( response . nextCursor ) ;
550646 } ;
551647
552- const getPrompt = async ( name : string , args : Record < string , string > = { } ) => {
553- const response = await sendMCPRequest (
554- {
555- method : "prompts/get" as const ,
556- params : { name, arguments : args } ,
557- } ,
558- GetPromptResultSchema ,
559- "prompts" ,
560- ) ;
561- setPromptContent ( JSON . stringify ( response , null , 2 ) ) ;
562- } ;
563-
564648 const listTools = async ( ) => {
565649 const response = await sendMCPRequest (
566650 {
@@ -572,11 +656,12 @@ const App = () => {
572656 ) ;
573657 setTools ( response . tools ) ;
574658 setNextToolCursor ( response . nextCursor ) ;
575- // Cache output schemas for validation
576659 cacheToolOutputSchemas ( response . tools ) ;
577660 } ;
578661
579662 const callTool = async ( name : string , params : Record < string , unknown > ) => {
663+ lastToolCallOriginTabRef . current = currentTabRef . current ;
664+
580665 try {
581666 const response = await sendMCPRequest (
582667 {
@@ -592,6 +677,7 @@ const App = () => {
592677 CompatibilityCallToolResultSchema ,
593678 "tools" ,
594679 ) ;
680+
595681 setToolResult ( response ) ;
596682 } catch ( e ) {
597683 const toolResult : CompatibilityCallToolResult = {
@@ -626,7 +712,6 @@ const App = () => {
626712 setStdErrNotifications ( [ ] ) ;
627713 } ;
628714
629- // Helper component for rendering the AuthDebugger
630715 const AuthDebuggerWrapper = ( ) => (
631716 < TabsContent value = "auth" >
632717 < AuthDebugger
@@ -638,7 +723,6 @@ const App = () => {
638723 </ TabsContent >
639724 ) ;
640725
641- // Helper function to render OAuth callback components
642726 if ( window . location . pathname === "/oauth/callback" ) {
643727 const OAuthCallback = React . lazy (
644728 ( ) => import ( "./components/OAuthCallback" ) ,
@@ -698,7 +782,6 @@ const App = () => {
698782 loggingSupported = { ! ! serverCapabilities ?. logging || false }
699783 clearStdErrNotifications = { clearStdErrNotifications }
700784 />
701- { /* Drag handle for resizing sidebar */ }
702785 < div
703786 onMouseDown = { handleSidebarDragStart }
704787 style = { {
@@ -719,21 +802,12 @@ const App = () => {
719802 < div className = "flex-1 overflow-auto" >
720803 { mcpClient ? (
721804 < Tabs
722- defaultValue = {
723- Object . keys ( serverCapabilities ?? { } ) . includes (
724- window . location . hash . slice ( 1 ) ,
725- )
726- ? window . location . hash . slice ( 1 )
727- : serverCapabilities ?. resources
728- ? "resources"
729- : serverCapabilities ?. prompts
730- ? "prompts"
731- : serverCapabilities ?. tools
732- ? "tools"
733- : "ping"
734- }
805+ value = { activeTab }
735806 className = "w-full p-4"
736- onValueChange = { ( value ) => ( window . location . hash = value ) }
807+ onValueChange = { ( value ) => {
808+ setActiveTab ( value ) ;
809+ window . location . hash = value ;
810+ } }
737811 >
738812 < TabsList className = "mb-4 py-0" >
739813 < TabsTrigger
@@ -895,7 +969,6 @@ const App = () => {
895969 clearTools = { ( ) => {
896970 setTools ( [ ] ) ;
897971 setNextToolCursor ( undefined ) ;
898- // Clear cached output schemas
899972 cacheToolOutputSchemas ( [ ] ) ;
900973 } }
901974 callTool = { async ( name , params ) => {
0 commit comments