Spaces:
Sleeping
Sleeping
import gradio as gr | |
import os | |
from mcp import StdioServerParameters | |
from smolagents import InferenceClientModel, CodeAgent, MCPClient | |
import pandas as pd | |
import requests | |
DEFAULT_MCP_URL = "https://alihmaou-mcp-tools.hf.space/gradio_api/mcp/sse" | |
HF_TOKEN = os.getenv("HUGGINGFACE_API_TOKEN") | |
def get_mcp_space_endpoints(): | |
"""Fetch MCP-compatible Spaces from the HF Hackathon org.""" | |
try: | |
resp = requests.get("https://huggingface.co/api/spaces?author=Agents-MCP-Hackathon") | |
resp.raise_for_status() | |
spaces = resp.json() | |
except Exception as e: | |
print(f"[Warning] Failed to fetch MCP spaces: {e}") | |
return [DEFAULT_MCP_URL] | |
endpoints = [DEFAULT_MCP_URL] | |
for space in spaces: | |
if "mcp-server" in space.get("tags", []): | |
full_id = space["id"] | |
slug = full_id.replace("/", "-").replace("_", "-").lower() | |
endpoint = f"https://{slug}.hf.space/gradio_api/mcp/sse" | |
if endpoint != DEFAULT_MCP_URL: | |
endpoints.append(endpoint) | |
return endpoints | |
def reload_tools_from_url(mcp_url_input): | |
global tools, agent, mcp_client, mcp_url | |
mcp_url=mcp_url_input | |
try: | |
mcp_client = MCPClient({"url": mcp_url,"transport": "sse"}) # Might be deprecated soon but didnt find out the clean way | |
tools = mcp_client.get_tools() | |
model = InferenceClientModel(token=os.getenv("HUGGINGFACE_API_TOKEN")) | |
agent = CodeAgent(tools=tools, model=model,) | |
except Exception as e: | |
print(f"[Warning] Failed to reach MCP server: {e}") | |
# Tableau structuré : nom, description, inputs attendus | |
rows = [] | |
for tool in tools: | |
input_fields = ", ".join(param for param in tool.inputs) | |
rows.append({ | |
"Tool name": tool.name, | |
"Description": tool.description, | |
"Params": input_fields | |
}) | |
df = pd.DataFrame(rows) | |
return gr.DataFrame(value=df) | |
with gr.Blocks() as demo: | |
gr.Markdown(""" | |
<div align="center"> | |
<h1>🚀 MCP Tools Explorer – Agents-MCP-Hackathon (June 2025)</h1> | |
<p> | |
🔍 Query any MCP-compatible endpoint, 🛠️ browse available tools in a clean table view, and 🤖 test real-time interactions using a `smolagent` powered by `HuggingFace`. <br/> | |
Perfect for 🧪 exploring fellow participants’ tools or 🧰 debugging your own MCP server during the event! </br> | |
🍒 As a cherry on the cake, the list of the tools developed for the hackathon will be updated here from time to time (see src/bonus.py) : <a href="https://huggingface.co/datasets/alihmaou/Agents_MCP_Hackathon_Tools_List/blob/main/hackathon_mcp_tools.parquet">Ready to use hackathon MCP tools list</a> | |
</p> | |
</div> | |
""",) | |
with gr.Row(): | |
with gr.Column(scale=1): | |
gr.Markdown(""" | |
<div align="center"> | |
<h2>🛠️ Set an MCP server and discover its tools</h2> | |
</div> | |
""") | |
source_selector = gr.Radio( | |
choices=["Hackathon candidates", "Custom MCP URL"], | |
label="🔀 Source", | |
value="Hackathon candidates" | |
) | |
hackathon_dropdown = gr.Dropdown( | |
label="Select a MCP server from the hackathon organisation", | |
choices=get_mcp_space_endpoints(), | |
value=DEFAULT_MCP_URL, | |
interactive=True, | |
visible=True | |
) | |
custom_url_input = gr.Textbox( | |
label="Enter custom MCP server URL", | |
value="https://abidlabs-mcp-tool-http.hf.space/gradio_api/mcp/sse", | |
visible=False | |
) | |
def toggle_url_input(source): | |
return ( | |
gr.update(visible=(source == "Hackathon candidates")), | |
gr.update(visible=(source == "Custom MCP URL")) | |
) | |
def reload_tools_router(source, dropdown_val, custom_val): | |
selected_url = dropdown_val if source == "Hackathon candidates" else custom_val | |
return reload_tools_from_url(selected_url) | |
source_selector.change(fn=toggle_url_input, inputs=source_selector, outputs=[hackathon_dropdown, custom_url_input]) | |
#print("[MCP] Endpoints loaded:", get_mcp_space_endpoints()) | |
tool_table = gr.DataFrame(headers=["Tool name", "Description", "Params"], interactive=False, label="🔧 MCP Tools availables", wrap=True) | |
reload_btn = gr.Button("🔄 Refresh and set MCP tools list") | |
reload_btn.click( | |
fn=reload_tools_router, | |
inputs=[source_selector, hackathon_dropdown, custom_url_input], | |
outputs=tool_table | |
) | |
hackathon_dropdown.change( | |
fn=reload_tools_router, | |
inputs=[source_selector, hackathon_dropdown, custom_url_input], | |
outputs=tool_table | |
) | |
custom_url_input.change( | |
fn=reload_tools_router, | |
inputs=[source_selector, hackathon_dropdown, custom_url_input], | |
outputs=tool_table | |
) | |
with gr.Column(scale=2): | |
gr.Markdown(""" | |
<div align="center"> | |
<h2>🔎 Test them with smolagents</h2> | |
</div> | |
""") | |
chatbot = gr.ChatInterface( | |
fn=lambda message, history: str(agent.run(message)), | |
type="messages", | |
) | |
demo.launch() | |
try: | |
if mcp_client: | |
mcp_client.disconnect() | |
except Exception as e: | |
print(f"[Warning] Failed to disconnect MCP client: {e}") |