From 8c46e57b4991d81227d004868d1bc39b73d1c134 Mon Sep 17 00:00:00 2001 From: Jerome Date: Thu, 12 Jun 2025 14:05:01 +0100 Subject: [PATCH] Implement comprehensive QoL improvements for MCP client MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Features Added - **Unique server name validation**: Prevent duplicate MCP server names to avoid tool routing conflicts - **Quick-add server examples**: Added example server buttons for "Everything" and "Test Server" configurations - **Conversation model selector**: Added dropdown to change AI models directly in chat interface - **Fixed nav bar height**: Conversation widget now properly accounts for navigation bar height ## User Experience Improvements - Server name uniqueness prevents tool naming conflicts and confusion - Quick-add buttons make it easier to get started with common MCP servers - Model selector allows switching between AI models without leaving conversation - Proper height calculation eliminates layout issues with conversation interface ## Technical Details - Server name validation happens before calling addMcpServer API - Model selector integrates with existing inference context - Height calculation uses CSS calc(100vh - 4rem) for nav bar compensation - All changes maintain backward compatibility 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- src/components/ChatInterface.tsx | 34 ++++++++++++++---- src/components/ConversationApp.tsx | 2 +- src/components/MCPTest.tsx | 56 +++++++++++++++++++++++++++--- 3 files changed, 80 insertions(+), 12 deletions(-) diff --git a/src/components/ChatInterface.tsx b/src/components/ChatInterface.tsx index 74b7af5..2117db1 100644 --- a/src/components/ChatInterface.tsx +++ b/src/components/ChatInterface.tsx @@ -16,7 +16,12 @@ export function ChatInterface() { getAgentLoopState, } = useConversation(); - const { provider: currentProvider } = useInference(); + const { + models, + selectedModel, + selectModel, + isAuthenticated + } = useInference(); const [isLoading, setIsLoading] = useState(false); const messagesEndRef = useRef(null); @@ -29,7 +34,7 @@ export function ChatInterface() { }, [activeConversation?.messages]); const handleSendMessage = async (content: string) => { - if (!activeConversationId || !currentProvider?.isAuthenticated) { + if (!activeConversationId || !isAuthenticated) { return; } @@ -65,7 +70,7 @@ export function ChatInterface() { } // Show auth prompt if not authenticated - if (!currentProvider?.isAuthenticated) { + if (!isAuthenticated) { return (
@@ -80,13 +85,28 @@ export function ChatInterface() { {/* Chat Header */}
-
+

{activeConversation.title}

-

- Model: {currentProvider.selectedModel?.name || 'None selected'} -

+
+ + Model: + + +
{isGenerating && ( diff --git a/src/components/ConversationApp.tsx b/src/components/ConversationApp.tsx index 0463e89..7e93758 100644 --- a/src/components/ConversationApp.tsx +++ b/src/components/ConversationApp.tsx @@ -11,7 +11,7 @@ export function ConversationApp() { return ( -
+
{/* Left Sidebar - Conversations */}
diff --git a/src/components/MCPTest.tsx b/src/components/MCPTest.tsx index aa905a8..a04d943 100644 --- a/src/components/MCPTest.tsx +++ b/src/components/MCPTest.tsx @@ -32,8 +32,17 @@ export function MCPTest() { return; } + const trimmedName = newServerName.trim(); + + // Check for duplicate server names + const existingServer = connections.find(conn => conn.name === trimmedName); + if (existingServer) { + alert(`A server with the name "${trimmedName}" already exists. Please choose a different name.`); + return; + } + const config: MCPServerConfig = { - name: newServerName.trim(), + name: trimmedName, url: newServerUrl.trim(), transport: 'auto', authType: 'none', @@ -48,7 +57,7 @@ export function MCPTest() { console.error('Failed to add server:', error); alert(`Failed to add server: ${error instanceof Error ? error.message : 'Unknown error'}`); } - }, [newServerName, newServerUrl, addMcpServer]); + }, [newServerName, newServerUrl, addMcpServer, connections]); const handleAddServerWithOAuth = useCallback(async () => { if (!newServerName.trim() || !newServerUrl.trim()) { @@ -56,8 +65,17 @@ export function MCPTest() { return; } + const trimmedName = newServerName.trim(); + + // Check for duplicate server names + const existingServer = connections.find(conn => conn.name === trimmedName); + if (existingServer) { + alert(`A server with the name "${trimmedName}" already exists. Please choose a different name.`); + return; + } + const config: MCPServerConfig = { - name: newServerName.trim(), + name: trimmedName, url: newServerUrl.trim(), transport: 'auto', authType: 'oauth', @@ -72,7 +90,7 @@ export function MCPTest() { console.error('Failed to add server with OAuth:', error); alert(`Failed to add server with OAuth: ${error instanceof Error ? error.message : 'Unknown error'}`); } - }, [newServerName, newServerUrl, addMcpServer]); + }, [newServerName, newServerUrl, addMcpServer, connections]); const handleRemoveServer = useCallback((connectionId: string) => { if (confirm('Are you sure you want to remove this server?')) { @@ -151,6 +169,36 @@ export function MCPTest() { Add MCP Server + {/* Quick Add Examples */} +
+

+ Quick Add Examples +

+
+ + +
+

+ Click to auto-fill common server configurations +

+
+