From 1705fd1145c640a48a70147caeba63562a871251 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 21 Nov 2025 23:23:14 +0000 Subject: [PATCH 1/5] Initial plan From dcbd4dad5c643556a701c7417b8acd1be48248af Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 21 Nov 2025 23:53:45 +0000 Subject: [PATCH 2/5] Add collapsible servers and compact active tools display Co-authored-by: garland3 <1162675+garland3@users.noreply.github.com> --- .../src/components/EnabledToolsIndicator.jsx | 34 +++++++++++-- frontend/src/components/ToolsPanel.jsx | 49 ++++++++++++++++--- 2 files changed, 74 insertions(+), 9 deletions(-) diff --git a/frontend/src/components/EnabledToolsIndicator.jsx b/frontend/src/components/EnabledToolsIndicator.jsx index 30b7c9c..a37caa7 100644 --- a/frontend/src/components/EnabledToolsIndicator.jsx +++ b/frontend/src/components/EnabledToolsIndicator.jsx @@ -1,8 +1,10 @@ import { useChat } from '../contexts/ChatContext' -import { X } from 'lucide-react' +import { X, ChevronDown, ChevronUp } from 'lucide-react' +import { useState } from 'react' const EnabledToolsIndicator = () => { const { selectedTools, toggleTool } = useChat() + const [isExpanded, setIsExpanded] = useState(false) const allTools = Array.from(selectedTools).map(key => { const parts = key.split('_') @@ -12,11 +14,18 @@ const EnabledToolsIndicator = () => { // Only show tools (prompts are now in the PromptSelector) if (allTools.length === 0) return null + // Threshold for showing compact view + const COMPACT_THRESHOLD = 3 + const shouldShowCompact = allTools.length > COMPACT_THRESHOLD + const displayTools = shouldShowCompact && !isExpanded + ? allTools.slice(0, COMPACT_THRESHOLD) + : allTools + return (
Active Tools: -
- {allTools.map((item, idx) => ( +
+ {displayTools.map((item, idx) => (
{
))} + {shouldShowCompact && ( + + )}
) diff --git a/frontend/src/components/ToolsPanel.jsx b/frontend/src/components/ToolsPanel.jsx index 2f1194f..c24ca67 100644 --- a/frontend/src/components/ToolsPanel.jsx +++ b/frontend/src/components/ToolsPanel.jsx @@ -1,4 +1,4 @@ -import { X, Trash2, Search, Plus, Wrench, Shield, Info } from 'lucide-react' +import { X, Trash2, Search, Plus, Wrench, Shield, Info, ChevronDown, ChevronRight } from 'lucide-react' import { useNavigate } from 'react-router-dom' import { useState, useEffect } from 'react' import { useChat } from '../contexts/ChatContext' @@ -10,6 +10,7 @@ const DEFAULT_PARAM_TYPE = 'any' const ToolsPanel = ({ isOpen, onClose }) => { const [searchTerm, setSearchTerm] = useState('') const [expandedTools, setExpandedTools] = useState(new Set()) + const [collapsedServers, setCollapsedServers] = useState(new Set()) const navigate = useNavigate() const { selectedTools, @@ -279,6 +280,16 @@ const ToolsPanel = ({ isOpen, onClose }) => { setExpandedTools(newExpanded) } + const toggleServerCollapse = (serverName) => { + const newCollapsed = new Set(collapsedServers) + if (newCollapsed.has(serverName)) { + newCollapsed.delete(serverName) + } else { + newCollapsed.add(serverName) + } + setCollapsedServers(newCollapsed) + } + /** * Renders the input schema parameters for a tool. * @param {Object} schema - The JSON schema object containing properties and required fields @@ -422,10 +433,28 @@ const ToolsPanel = ({ isOpen, onClose }) => { ) : (
{filteredServers.map(server => { + const isCollapsed = collapsedServers.has(server.server) + const toolCount = server.tools.length + const promptCount = server.prompts.length + const totalItems = toolCount + promptCount + return (
{/* Main Server Row */}
+ {/* Collapse/Expand Button */} + + {/* Server Icon */}
@@ -437,6 +466,9 @@ const ToolsPanel = ({ isOpen, onClose }) => {

{server.server}

+ + ({totalItems} {totalItems === 1 ? 'item' : 'items'}) + {server.is_exclusive && ( Exclusive @@ -451,11 +483,14 @@ const ToolsPanel = ({ isOpen, onClose }) => {

{server.description}

- {/* Tools Display */} - {server.tools.length > 0 && ( -
-
- {server.tools.map(tool => { + {/* Tools and Prompts - only show when not collapsed */} + {!isCollapsed && ( + <> + {/* Tools Display */} + {server.tools.length > 0 && ( +
+
+ {server.tools.map(tool => { const toolKey = `${server.server}_${tool}` const isSelected = selectedTools.has(toolKey) const isToolExpanded = expandedTools.has(toolKey) @@ -531,6 +566,8 @@ const ToolsPanel = ({ isOpen, onClose }) => {
)} + + )}
{/* Action Buttons */} From 3ce3cbc1c2b2f5981f4b68f1bae01b02dfef0635 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 22 Nov 2025 00:11:08 +0000 Subject: [PATCH 3/5] Add test MCP server with 64 tools to demonstrate UI improvements Co-authored-by: garland3 <1162675+garland3@users.noreply.github.com> --- backend/mcp/many_tools_demo/main.py | 50 +++++++++++++++++++++++++++++ config/overrides/mcp.json | 15 +++++++++ 2 files changed, 65 insertions(+) create mode 100644 backend/mcp/many_tools_demo/main.py diff --git a/backend/mcp/many_tools_demo/main.py b/backend/mcp/many_tools_demo/main.py new file mode 100644 index 0000000..c33d585 --- /dev/null +++ b/backend/mcp/many_tools_demo/main.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python3 +""" +MCP Server with 50+ tools for testing UI with many tools. +Demonstrates that the collapsible UI can handle servers with large numbers of tools. +""" + +from fastmcp import FastMCP + +# Create the MCP server +mcp = FastMCP("ManyToolsDemo") + +# Generate 50+ tools dynamically to test UI scalability +# Categories: data, analytics, file, network, system, database, security, etc. + +TOOL_CATEGORIES = [ + ("data", 10, "Process and transform data"), + ("analytics", 10, "Analyze data and generate insights"), + ("file", 8, "File operations and management"), + ("network", 8, "Network operations and monitoring"), + ("system", 8, "System administration tasks"), + ("database", 8, "Database operations"), + ("security", 6, "Security and encryption tasks"), + ("report", 6, "Report generation and formatting"), +] + +# Dynamically create tools for each category +for category, count, description_base in TOOL_CATEGORIES: + for i in range(1, count + 1): + tool_name = f"{category}_operation_{i}" + tool_description = f"{description_base} - Operation {i}" + + # Use exec to create properly named functions + exec(f""" +@mcp.tool() +def {tool_name}(input_data: str = "default") -> str: + ''' + {tool_description} + + Args: + input_data: Input data to process + + Returns: + str: Result of the operation + ''' + return f"Executed {tool_name} with input: {{input_data}}" +""") + +if __name__ == "__main__": + mcp.run() + diff --git a/config/overrides/mcp.json b/config/overrides/mcp.json index be86aad..2734486 100644 --- a/config/overrides/mcp.json +++ b/config/overrides/mcp.json @@ -128,5 +128,20 @@ ], "description": "Mock HTTP MCP server for testing authentication", "auth_token": "${MCP_EXTERNAL_API_TOKEN}" + }, + "many_tools_demo": { + "command": [ + "python", + "mcp/many_tools_demo/main.py" + ], + "cwd": "backend", + "groups": [ + "users" + ], + "description": "Demo server with 64 tools to test UI scalability with large numbers of tools. Includes operations for data, analytics, files, network, system, database, security, and reporting.", + "author": "Chat UI Team", + "short_description": "Large tool set demo (64 tools)", + "help_email": "support@chatui.example.com", + "compliance_level": "Public" } } From f731b6ae26d217aec8846f1a346e817b61af4e6e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 22 Nov 2025 00:13:20 +0000 Subject: [PATCH 4/5] Update docstring to accurately reflect 64 tools Co-authored-by: garland3 <1162675+garland3@users.noreply.github.com> --- backend/mcp/many_tools_demo/main.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/backend/mcp/many_tools_demo/main.py b/backend/mcp/many_tools_demo/main.py index c33d585..3dc3cf4 100644 --- a/backend/mcp/many_tools_demo/main.py +++ b/backend/mcp/many_tools_demo/main.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 """ -MCP Server with 50+ tools for testing UI with many tools. +MCP Server with 64 tools for testing UI with many tools. Demonstrates that the collapsible UI can handle servers with large numbers of tools. """ @@ -9,8 +9,8 @@ # Create the MCP server mcp = FastMCP("ManyToolsDemo") -# Generate 50+ tools dynamically to test UI scalability -# Categories: data, analytics, file, network, system, database, security, etc. +# Generate 64 tools dynamically to test UI scalability +# Categories: data, analytics, file, network, system, database, security, report TOOL_CATEGORIES = [ ("data", 10, "Process and transform data"), From ece85ad5e50037dc2093c6e9e09706c05e9eddaf Mon Sep 17 00:00:00 2001 From: Anthony Date: Sat, 22 Nov 2025 04:10:18 +0000 Subject: [PATCH 5/5] feat(config,ui): move many_tools_demo to defaults and increase compact threshold - Added many_tools_demo (64 tools demo) to config/defaults/mcp.json to make it available by default for testing UI scalability with large tool sets - Removed it from config/overrides/mcp.json - Increased COMPACT_THRESHOLD from 3 to 5 in EnabledToolsIndicator.jsx to better accommodate displaying many tools in compact view when collapsed --- config/defaults/mcp.json | 15 +++++++++++++++ config/overrides/mcp.json | 16 +--------------- .../src/components/EnabledToolsIndicator.jsx | 2 +- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/config/defaults/mcp.json b/config/defaults/mcp.json index 235ea37..f23e534 100644 --- a/config/defaults/mcp.json +++ b/config/defaults/mcp.json @@ -119,5 +119,20 @@ ], "description": "Mock HTTP MCP server for testing authentication", "auth_token": "${MCP_EXTERNAL_API_TOKEN}" + }, + "many_tools_demo": { + "command": [ + "python", + "mcp/many_tools_demo/main.py" + ], + "cwd": "backend", + "groups": [ + "users" + ], + "description": "Demo server with 64 tools to test UI scalability with large numbers of tools. Includes operations for data, analytics, files, network, system, database, security, and reporting.", + "author": "Chat UI Team", + "short_description": "Large tool set demo (64 tools)", + "help_email": "support@chatui.example.com", + "compliance_level": "Public" } } diff --git a/config/overrides/mcp.json b/config/overrides/mcp.json index 2734486..845daca 100644 --- a/config/overrides/mcp.json +++ b/config/overrides/mcp.json @@ -128,20 +128,6 @@ ], "description": "Mock HTTP MCP server for testing authentication", "auth_token": "${MCP_EXTERNAL_API_TOKEN}" - }, - "many_tools_demo": { - "command": [ - "python", - "mcp/many_tools_demo/main.py" - ], - "cwd": "backend", - "groups": [ - "users" - ], - "description": "Demo server with 64 tools to test UI scalability with large numbers of tools. Includes operations for data, analytics, files, network, system, database, security, and reporting.", - "author": "Chat UI Team", - "short_description": "Large tool set demo (64 tools)", - "help_email": "support@chatui.example.com", - "compliance_level": "Public" } + } diff --git a/frontend/src/components/EnabledToolsIndicator.jsx b/frontend/src/components/EnabledToolsIndicator.jsx index a37caa7..62aeb92 100644 --- a/frontend/src/components/EnabledToolsIndicator.jsx +++ b/frontend/src/components/EnabledToolsIndicator.jsx @@ -15,7 +15,7 @@ const EnabledToolsIndicator = () => { if (allTools.length === 0) return null // Threshold for showing compact view - const COMPACT_THRESHOLD = 3 + const COMPACT_THRESHOLD = 5 const shouldShowCompact = allTools.length > COMPACT_THRESHOLD const displayTools = shouldShowCompact && !isExpanded ? allTools.slice(0, COMPACT_THRESHOLD)