ysharma HF Staff commited on
Commit
5899d68
·
verified ·
1 Parent(s): 5738139

Create mcp_spaces_finder.py

Browse files
Files changed (1) hide show
  1. mcp_spaces_finder.py +187 -0
mcp_spaces_finder.py ADDED
@@ -0,0 +1,187 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Simple HuggingFace MCP Spaces Finder Module - Corrected Version
3
+ A minimal module to discover MCP servers on HuggingFace Spaces.
4
+ Fixed to fetch ALL available MCP servers using proper pagination.
5
+ Usage:
6
+ from mcp_spaces_finder import create_simple_mcp_selector
7
+
8
+ # One-liner in your Gradio app
9
+ dropdown, textbox = create_simple_mcp_selector()
10
+ """
11
+ import gradio as gr
12
+ from huggingface_hub import list_spaces
13
+ import time
14
+ from typing import List, Tuple
15
+
16
+ class SimpleMCPFinder:
17
+ """Simple MCP spaces finder with caching and proper pagination."""
18
+
19
+ def __init__(self, cache_duration: int = 300):
20
+ self.cache = None
21
+ self.cache_time = None
22
+ self.cache_duration = cache_duration
23
+
24
+ def get_mcp_spaces(self) -> List[str]:
25
+ """Get list of ALL running MCP space IDs using proper pagination."""
26
+
27
+ # Check cache
28
+ if (self.cache is not None and
29
+ self.cache_time is not None and
30
+ time.time() - self.cache_time < self.cache_duration):
31
+ return self.cache
32
+
33
+ print("Fetching ALL MCP spaces...")
34
+
35
+ # Get ALL MCP spaces by setting a much higher limit
36
+ # The HF API supports pagination, so we set limit high enough to get all
37
+ spaces = list(list_spaces(
38
+ filter="mcp-server",
39
+ sort="likes",
40
+ direction=-1,
41
+ limit=5000, # Increased from 1000 to capture all ~2500 spaces
42
+ full=True
43
+ ))
44
+
45
+ # Extract just the space IDs
46
+ space_ids = [space.id for space in spaces]
47
+
48
+ # Cache results
49
+ self.cache = space_ids
50
+ self.cache_time = time.time()
51
+
52
+ print(f"Found {len(space_ids)} MCP spaces")
53
+ return space_ids
54
+
55
+ def get_mcp_spaces_paginated(self) -> List[str]:
56
+ """Alternative method: Get ALL MCP spaces using explicit pagination if needed."""
57
+
58
+ # Check cache
59
+ if (self.cache is not None and
60
+ self.cache_time is not None and
61
+ time.time() - self.cache_time < self.cache_duration):
62
+ return self.cache
63
+
64
+ print("Fetching ALL MCP spaces with pagination...")
65
+
66
+ all_space_ids = []
67
+ limit_per_page = 1000
68
+
69
+ # Keep fetching until we get all spaces
70
+ # Note: HuggingFace API handles pagination internally with the iterator
71
+ try:
72
+ spaces = list(list_spaces(
73
+ filter="mcp-server",
74
+ sort="likes",
75
+ direction=-1,
76
+ limit=None, # No limit to get all
77
+ full=True
78
+ ))
79
+ all_space_ids = [space.id for space in spaces]
80
+
81
+ except Exception as e:
82
+ print(f"Error with unlimited fetch, trying with high limit: {e}")
83
+ # Fallback to high limit
84
+ spaces = list(list_spaces(
85
+ filter="mcp-server",
86
+ sort="likes",
87
+ direction=-1,
88
+ limit=5000, # High limit as fallback
89
+ full=True
90
+ ))
91
+ all_space_ids = [space.id for space in spaces]
92
+
93
+ # Cache results
94
+ self.cache = all_space_ids
95
+ self.cache_time = time.time()
96
+
97
+ print(f"Found {len(all_space_ids)} MCP spaces total")
98
+ return all_space_ids
99
+
100
+ # Global instance
101
+ _finder = SimpleMCPFinder()
102
+
103
+ def create_simple_mcp_selector(
104
+ dropdown_label: str = "🤖 Select MCP Server",
105
+ textbox_label: str = "Selected MCP Server",
106
+ placeholder: str = "No server selected"
107
+ ) -> Tuple[gr.Dropdown, gr.Textbox]:
108
+ """
109
+ Create a simple MCP selector with dropdown and textbox.
110
+
111
+ Args:
112
+ dropdown_label (str): Label for the dropdown
113
+ textbox_label (str): Label for the textbox
114
+ placeholder (str): Placeholder text when nothing selected
115
+
116
+ Returns:
117
+ Tuple[gr.Dropdown, gr.Textbox]: The dropdown and textbox components
118
+ """
119
+
120
+ # Get MCP spaces
121
+ spaces = _finder.get_mcp_spaces()
122
+
123
+ # Create dropdown with space choices
124
+ dropdown = gr.Dropdown(
125
+ choices=spaces,
126
+ label=f"{dropdown_label} ({len(spaces)} available)",
127
+ value=None,
128
+ allow_custom_value=True, # Allow users to type custom space IDs
129
+ info="Choose from discovered MCP spaces or type a custom space ID"
130
+ )
131
+
132
+ # Create textbox to display selection
133
+ textbox = gr.Textbox(
134
+ label=textbox_label,
135
+ value=placeholder,
136
+ interactive=False
137
+ )
138
+
139
+ # Connect dropdown to textbox
140
+ def update_textbox(selected_value):
141
+ return selected_value if selected_value else placeholder
142
+
143
+ dropdown.change(
144
+ fn=update_textbox,
145
+ inputs=[dropdown],
146
+ outputs=[textbox]
147
+ )
148
+
149
+ return dropdown, textbox
150
+
151
+ def refresh_mcp_spaces():
152
+ """Clear cache to force refresh."""
153
+ _finder.cache = None
154
+ _finder.cache_time = None
155
+
156
+ def test_space_exists(space_id: str) -> bool:
157
+ """Test if a specific space exists in our discovered list."""
158
+ spaces = _finder.get_mcp_spaces()
159
+ return space_id in spaces
160
+
161
+ def debug_search_for_spaces(space_ids: List[str]):
162
+ """Debug function to check if specific spaces are found."""
163
+ spaces = _finder.get_mcp_spaces()
164
+ print(f"Total MCP spaces found: {len(spaces)}")
165
+
166
+ for space_id in space_ids:
167
+ if space_id in spaces:
168
+ print(f"✅ Found: {space_id}")
169
+ else:
170
+ print(f"❌ Missing: {space_id}")
171
+
172
+ # Show first 10 spaces for reference
173
+ print(f"\nFirst 10 spaces found:")
174
+ for i, space in enumerate(spaces[:10]):
175
+ print(f" {i+1}. {space}")
176
+
177
+ if __name__ == "__main__":
178
+ # Test the specific spaces you mentioned
179
+ test_spaces = [
180
+ "ysharma/Kokoro-TTS-mcp-test",
181
+ "ysharma/ltx-video-distilled",
182
+ "ysharma/dalle-3-xl-lora-v2"
183
+ ]
184
+
185
+ print("Testing MCP space discovery...")
186
+ debug_search_for_spaces(test_spaces)
187
+