-
Notifications
You must be signed in to change notification settings - Fork 5
Add collapsible servers and compact tool display to reduce UI crowding #105
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Co-authored-by: garland3 <1162675+garland3@users.noreply.github.com>
|
You should make a new mcp server with 50+ tools. perhaps use some loop strategy to not need to hard code each one. Add to the mpc.json. Then take a screen shot to replicate the problem. |
|
@copilot You should make a new mcp server with 50+ tools. perhaps use some loop strategy to not need to hard code each one. Add to the mpc.json. Then take a screen shot to replicate the problem. |
Co-authored-by: garland3 <1162675+garland3@users.noreply.github.com>
Created a test MCP server with 64 tools and added it to mcp.json (commit 3ce3cbc). With 64-tool server expanded - Shows the problem without collapsing: With 64-tool server collapsed - Demonstrates the fix: Active Tools with 65 enabled - Shows compact view (+62 more): The collapsible servers and compact Active Tools indicator both work well with large tool counts. |
Co-authored-by: garland3 <1162675+garland3@users.noreply.github.com>
confirmed this is working. @sahiltyagi4
|
🔒 Security Scan ResultsSecurity Scan SummaryScan ResultsPython SAST (Bandit)Recommendations
|
…t 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
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR addresses UI crowding issues when working with many MCP tools by introducing collapsible server sections and compact active tools display. The changes allow users to manage 20+ tools more effectively by reducing visual clutter in both the Tools & Integrations panel and the chat input area.
Key Changes:
- Collapsible server sections with per-server expand/collapse state tracking
- Compact active tools indicator showing first 5 tools with "+N more" expansion
- Test MCP server (many_tools_demo) with 64 tools to validate UI scalability
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
frontend/src/components/ToolsPanel.jsx |
Adds collapsible server functionality with chevron icons, item counts, and conditional tool/prompt rendering based on collapse state |
frontend/src/components/EnabledToolsIndicator.jsx |
Implements compact display mode showing first 5 active tools with expandable "+N more" button |
backend/mcp/many_tools_demo/main.py |
Creates test server with 64 dynamically generated tools across 8 categories for UI stress testing |
config/defaults/mcp.json |
Registers many_tools_demo server with compliance level and descriptive metadata |
config/overrides/mcp.json |
Formatting cleanup (extra blank line removed) |
Comments suppressed due to low confidence (2)
frontend/src/components/ToolsPanel.jsx:22
- Unused variable setSinglePrompt.
setSinglePrompt,
frontend/src/components/ToolsPanel.jsx:99
- Unused variable selectedPromptInfo.
const selectedPromptInfo = (() => {
| 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}}" | ||
| """) |
Copilot
AI
Nov 22, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using exec() to dynamically create functions is a security risk and violates codebase security practices. The code-executor server explicitly forbids exec() for safety reasons (see backend/mcp/code-executor/main.py line 191).
Instead, define a factory function that creates closures or use partial functions. For example:
def create_tool_function(category: str, i: int, description_base: str):
def tool_func(input_data: str = "default") -> str:
f'''
{description_base} - Operation {i}
Args:
input_data: Input data to process
Returns:
str: Result of the operation
'''
tool_name = f"{category}_operation_{i}"
return f"Executed {tool_name} with input: {input_data}"
tool_func.__name__ = f"{category}_operation_{i}"
tool_func.__doc__ = f"{description_base} - Operation {i}\n\nArgs:\n input_data: Input data to process\n\nReturns:\n str: Result of the operation"
return tool_func
for category, count, description_base in TOOL_CATEGORIES:
for i in range(1, count + 1):
tool_func = create_tool_function(category, i, description_base)
mcp.tool()(tool_func)This approach is safer and more maintainable.
| 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}}" | |
| """) | |
| def create_tool_function(category: str, i: int, description_base: str): | |
| tool_name = f"{category}_operation_{i}" | |
| tool_description = f"{description_base} - Operation {i}" | |
| def tool_func(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}" | |
| tool_func.__name__ = tool_name | |
| tool_func.__doc__ = f"{tool_description}\n\nArgs:\n input_data: Input data to process\n\nReturns:\n str: Result of the operation" | |
| return tool_func | |
| for category, count, description_base in TOOL_CATEGORIES: | |
| for i in range(1, count + 1): | |
| tool_func = create_tool_function(category, i, description_base) | |
| mcp.tool()(tool_func) |
| if (allTools.length === 0) return null | ||
|
|
||
| // Threshold for showing compact view | ||
| const COMPACT_THRESHOLD = 5 |
Copilot
AI
Nov 22, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The COMPACT_THRESHOLD value is inconsistent with the PR description. The description states "Shows first 3 active tools by default when >3 are enabled" but the code uses COMPACT_THRESHOLD = 5.
Please update either the code to use 3 or the PR description to match the actual implementation of 5.
| const COMPACT_THRESHOLD = 5 | |
| const COMPACT_THRESHOLD = 3 |
| 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' |
Copilot
AI
Nov 22, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unused import useEffect.
| import { useState, useEffect } from 'react' | |
| import { useState } from 'react' |
🔒 Security Scan ResultsSecurity Scan SummaryScan ResultsPython SAST (Bandit)Recommendations
|



The Tools & Integrations panel and Active Tools indicator become difficult to use with 20+ tools, making navigation cumbersome and reducing available chat input space.
Changes
Collapsible Server Sections
Compact Active Tools Display
Test MCP Server (many_tools_demo)
config/overrides/mcp.jsonfor testing extreme casesImplementation
ToolsPanel.jsx:
EnabledToolsIndicator.jsx:
Screenshots
Before - 16 Tools:

After - 64-Tool Server Expanded:

After - 64-Tool Server Collapsed:

Active Tools - Compact View (65 tools, +62 more):

Original prompt
<issue_description>The crowding of the tools and integrations panel.
Also, if load many tools (20+) then the chat bar is crowded.
</issue_description>
Comments on the Issue (you are @copilot in this section)
Original prompt
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.