Spaces:
Sleeping
Sleeping
File size: 5,711 Bytes
cb42665 a60731c cb42665 df93caa 3cd2521 df93caa cb42665 df93caa cb42665 df93caa cb42665 df93caa cb42665 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
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://agents-mcp-hackathon-mcp-drawittome.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.HTML("""
<div style="text-align:center; max-width: 100%; margin-bottom: 20px;">
<h1 style="font-size: 2em; margin-bottom: 0.5em;">
🚀 MCP Explorer – Agents-MCP-Hackathon (June 2025)
</h1>
<p style="font-size: 1em; line-height: 1.5em; margin: 0 auto; max-width: 600px;">
🔍 Query any MCP-compatible endpoint, 🛠️ browse available tools in a clean table view, and 🤖 test real-time interactions using a <code>smolagent</code> powered by <code>HuggingFace</code>.<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 <code>src/bonus.py</code>):<br/>
<a href="https://huggingface.co/datasets/alihmaou/Agents_MCP_Hackathon_Tools_List" target="_blank" style="color: #4A90E2; text-decoration: underline;">
Ready to use hackathon MCP tools list
</a>
</p>
</div>
"""
)
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://agents-mcp-hackathon-mcp-server-demo.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.submit(
fn=reload_tools_router,
inputs=[source_selector, hackathon_dropdown, custom_url_input],
outputs=tool_table
)
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}") |