""" Simple HuggingFace MCP Spaces Finder Module A minimal module to discover MCP servers on HuggingFace Spaces. Just a dropdown that displays the selected value in a textbox. Usage: from mcp_spaces_finder import create_simple_mcp_selector # One-liner in your Gradio app dropdown, textbox = create_simple_mcp_selector() """ import gradio as gr from huggingface_hub import list_spaces import time from typing import List, Tuple from concurrent.futures import ThreadPoolExecutor, as_completed class SimpleMCPFinder: """Simple MCP spaces finder with caching.""" def __init__(self, cache_duration: int = 300): self.cache = None self.cache_time = None self.cache_duration = cache_duration def get_mcp_spaces(self) -> List[str]: """Get list of running MCP space IDs.""" # Check cache if (self.cache is not None and self.cache_time is not None and time.time() - self.cache_time < self.cache_duration): return self.cache print("Fetching MCP spaces...") # Get MCP spaces sorted by likes spaces = list(list_spaces( filter="mcp-server", sort="likes", direction=-1, limit=1000, full=True )) # Extract just the space IDs space_ids = [space.id for space in spaces] # Cache results self.cache = space_ids self.cache_time = time.time() print(f"Found {len(space_ids)} MCP spaces") return space_ids # Global instance _finder = SimpleMCPFinder() def create_simple_mcp_selector( dropdown_label: str = "🤖 Select MCP Server", textbox_label: str = "Selected MCP Server", placeholder: str = "No server selected" ) -> Tuple[gr.Dropdown, gr.Textbox]: """ Create a simple MCP selector with dropdown and textbox. Args: dropdown_label (str): Label for the dropdown textbox_label (str): Label for the textbox placeholder (str): Placeholder text when nothing selected Returns: Tuple[gr.Dropdown, gr.Textbox]: The dropdown and textbox components """ # Get MCP spaces spaces = _finder.get_mcp_spaces() # Create dropdown with space choices dropdown = gr.Dropdown( choices=spaces, label=f"{dropdown_label} ({len(spaces)} available)", value=None ) # Create textbox to display selection textbox = gr.Textbox( label=textbox_label, value=placeholder, interactive=False ) # Connect dropdown to textbox def update_textbox(selected_value): return selected_value if selected_value else placeholder dropdown.change( fn=update_textbox, inputs=[dropdown], outputs=[textbox] ) return dropdown, textbox def refresh_mcp_spaces(): """Clear cache to force refresh.""" _finder.cache = None _finder.cache_time = None