-
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
Changes from all commits
1705fd1
dcbd4da
3ce3cbc
f731b6a
ece85ad
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| #!/usr/bin/env python3 | ||
| """ | ||
| MCP Server with 64 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 64 tools dynamically to test UI scalability | ||
| # Categories: data, analytics, file, network, system, database, security, report | ||
|
|
||
| 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() | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -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 = 5 | ||||||
|
||||||
| const COMPACT_THRESHOLD = 5 | |
| const COMPACT_THRESHOLD = 3 |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -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 { useState, useEffect } from 'react' | |
| import { useState } from 'react' |
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 forbidsexec()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:
This approach is safer and more maintainable.