File size: 6,230 Bytes
cb42665
 
 
 
 
 
 
a60731c
cb42665
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
df93caa
0e2044b
3cd2521
 
0e2044b
3cd2521
 
 
 
 
 
 
 
 
0e2044b
 
 
 
 
 
 
 
3bcf4c6
0e2044b
de15032
0e2044b
 
 
de15032
0e2044b
 
 
 
 
df93caa
0e2044b
 
 
 
 
 
 
 
de15032
0e2044b
 
 
 
de15032
0e2044b
 
 
cb42665
0e2044b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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("""
                <h1 style="text-align:center; font-size: 2em; margin-bottom: 0.5em;">
                    🚀 MCP Explorer – Agents-MCP-Hackathon (June 2025)
                </h1>
                <p style="text-align:center; 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>
            """
           )
    with gr.Row():
        with gr.Column():
            gr.Markdown("""
                <div align="center">
                    <h2>🛠️ Set an MCP server and discover its tools</h2>
                </div>
                """)
            source_selector = gr.Radio(
                choices=["Hackathon submissions", "Custom MCP URL"],
                label="🔀 Source",
                value="Hackathon submissions"
            )
            
            hackathon_dropdown = gr.Dropdown(
                label="Select a MCP server from the Agent-MCP hackathon submissions",
                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 submissions")),
                    gr.update(visible=(source == "Custom MCP URL"))
                )
                
            def reload_tools_router(source, dropdown_val, custom_val):
                selected_url = dropdown_val if source == "Hackathon submissions" 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
            ) 
        with gr.Column():
            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}")