seanpoyner commited on
Commit
518eab8
ยท
1 Parent(s): 245fd86

Deploy Gradio MCP Playground to HF Space

Browse files
Files changed (3) hide show
  1. README.md +193 -7
  2. app.py +999 -0
  3. requirements.txt +9 -0
README.md CHANGED
@@ -1,13 +1,199 @@
1
  ---
2
- title: Gradio Mcp Playground
3
- emoji: ๐Ÿ“Š
4
  colorFrom: blue
5
- colorTo: purple
6
  sdk: gradio
7
- sdk_version: 5.32.1
8
  app_file: app.py
9
- pinned: false
10
- license: mit
 
 
 
 
 
 
11
  ---
12
 
13
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ title: Gradio MCP Playground
3
+ emoji: ๐Ÿ›
4
  colorFrom: blue
5
+ colorTo: green
6
  sdk: gradio
7
+ sdk_version: 4.31.0
8
  app_file: app.py
9
+ pinned: true
10
+ license: apache-2.0
11
+ tags:
12
+ - mcp
13
+ - agents
14
+ - gradio
15
+ - hackathon
16
+ short_description: Build AI agents visually - No code required!
17
  ---
18
 
19
+ # ๐Ÿ› Gradio MCP Playground
20
+
21
+ <div align="center">
22
+
23
+ [![Hugging Face Spaces](https://img.shields.io/badge/%F0%9F%A4%97%20Hugging%20Face-Spaces-blue)](https://huggingface.co/spaces/seanpoyner/gradio-mcp-playground)
24
+ [![GitHub](https://img.shields.io/badge/GitHub-Repository-black)](https://github.com/seanpoyner/gradio-mcp-playground)
25
+ [![License](https://img.shields.io/badge/License-Apache%202.0-green.svg)](LICENSE)
26
+ [![Hackathon](https://img.shields.io/badge/HF%20MCP%20Hackathon-2025-orange)](https://huggingface.co/hackathon)
27
+
28
+ **Transform any Python function into an AI agent in seconds!**
29
+
30
+ [Try Demo](https://huggingface.co/spaces/seanpoyner/gradio-mcp-playground) | [Documentation](https://github.com/seanpoyner/gradio-mcp-playground/wiki) | [Report Bug](https://github.com/seanpoyner/gradio-mcp-playground/issues)
31
+
32
+ </div>
33
+
34
+ ## ๐Ÿ† Hugging Face MCP Hackathon Submission
35
+
36
+ This project democratizes AI agent development by providing a visual, no-code platform for creating, testing, and deploying MCP (Model Context Protocol) agents. Built with Gradio, it makes agent creation accessible to everyone - from beginners to experts.
37
+
38
+ ## โœจ What Makes This Special?
39
+
40
+ - **๐Ÿš€ Zero to Agent in 30 Seconds** - Choose a template, customize, and deploy
41
+ - **๐ŸŽจ Visual Builder** - No coding required with our drag-and-drop interface
42
+ - **๐Ÿค– AI-Powered Assistance** - Three specialized AI modes to guide you
43
+ - **๐Ÿ”Œ Live MCP Integration** - Connect and test real MCP servers instantly
44
+ - **๐Ÿ“ฆ One-Click Deploy** - Deploy to production with a single button
45
+
46
+ ## ๐ŸŽฅ Demo Video
47
+
48
+ [Watch our 2-minute demo](https://youtu.be/demo-link) to see the playground in action!
49
+
50
+ ## ๐ŸŒŸ Key Features
51
+
52
+ ### ๐Ÿ› AI Assistant Hub
53
+ Three specialized AI assistants help you at every step:
54
+
55
+ - **Adam (General)** - Your friendly AI companion with MCP superpowers
56
+ - **Liam (MCP Agent)** - Expert in MCP development and troubleshooting
57
+ - **Arthur (Agent Builder)** - Architect for complex agent systems
58
+
59
+ ### ๐Ÿ—๏ธ Visual Server Builder
60
+ Create MCP servers without writing code:
61
+
62
+ - **Template Gallery** - Pre-built templates for common use cases
63
+ - **Live Code Generation** - See your Python code as you build
64
+ - **Instant Testing** - Test your tools without deployment
65
+ - **Custom Templates** - Start from scratch or modify existing ones
66
+
67
+ ### ๐Ÿ”Œ MCP Connections
68
+ Connect to any MCP server with ease:
69
+
70
+ - **Quick Connect** - One-click connection to popular servers
71
+ - **Tool Discovery** - Automatically discover available tools
72
+ - **Live Testing** - Execute tools and see results in real-time
73
+ - **Activity Monitoring** - Track all tool executions
74
+
75
+ ### ๐Ÿ“ฆ Server Management
76
+ Professional-grade server management:
77
+
78
+ - **Dashboard View** - Monitor all your servers at a glance
79
+ - **One-Click Deploy** - Deploy to Hugging Face Spaces instantly
80
+ - **Version Control** - Track changes and rollback if needed
81
+ - **Share & Collaborate** - Share your agents with the community
82
+
83
+ ## ๐Ÿš€ Quick Start
84
+
85
+ ### Try the Demo (No Installation)
86
+
87
+ Visit our [Hugging Face Space](https://huggingface.co/spaces/seanpoyner/gradio-mcp-playground) to try the platform instantly!
88
+
89
+ ### Local Installation (Full Features)
90
+
91
+ ```bash
92
+ # Clone repository
93
+ git clone https://github.com/seanpoyner/gradio-mcp-playground
94
+ cd gradio-mcp-playground
95
+
96
+ # Install dependencies
97
+ pip install -e ".[all]"
98
+
99
+ # Run the unified dashboard
100
+ gmp dashboard
101
+
102
+ # Or run with custom port
103
+ gmp dashboard --port 8081
104
+ ```
105
+
106
+ ## ๐Ÿ’ก Use Cases
107
+
108
+ ### For Developers
109
+ - **Rapid Prototyping** - Test ideas without boilerplate code
110
+ - **API Integration** - Wrap any API as an MCP server
111
+ - **Tool Development** - Create reusable tools for AI assistants
112
+
113
+ ### For Businesses
114
+ - **Custom Assistants** - Build domain-specific AI agents
115
+ - **Workflow Automation** - Create multi-step processes
116
+ - **Team Collaboration** - Share tools across your organization
117
+
118
+ ### For Educators
119
+ - **Teaching AI Concepts** - Visual way to explain agent architectures
120
+ - **Student Projects** - Let students build without infrastructure worries
121
+ - **Interactive Demos** - Show real AI capabilities in action
122
+
123
+ ### For Researchers
124
+ - **Protocol Testing** - Experiment with MCP implementations
125
+ - **Tool Benchmarking** - Compare different approaches
126
+ - **Rapid Experimentation** - Test hypotheses quickly
127
+
128
+ ## ๐Ÿ“ธ Screenshots
129
+
130
+ <div align="center">
131
+ <img src="https://github.com/seanpoyner/gradio-mcp-playground/assets/demo/assistant.png" width="45%" alt="AI Assistant">
132
+ <img src="https://github.com/seanpoyner/gradio-mcp-playground/assets/demo/builder.png" width="45%" alt="Server Builder">
133
+ </div>
134
+
135
+ ## ๐Ÿ› ๏ธ Technical Implementation
136
+
137
+ ### Architecture
138
+ - **Frontend**: Gradio 4.31.0 with custom themes
139
+ - **Backend**: Python with async support
140
+ - **Protocol**: Model Context Protocol (MCP)
141
+ - **Deployment**: Hugging Face Spaces compatible
142
+
143
+ ### Key Technologies
144
+ - **Gradio** - Interactive web UI framework
145
+ - **MCP** - Standardized protocol for AI tools
146
+ - **AsyncIO** - High-performance async operations
147
+ - **Pydantic** - Data validation and serialization
148
+
149
+ ## ๐ŸŽฏ Why This Matters
150
+
151
+ The Model Context Protocol (MCP) is powerful but can be complex to implement. Our playground removes these barriers:
152
+
153
+ 1. **Accessibility** - No need to understand protocol details
154
+ 2. **Speed** - Build in minutes instead of hours
155
+ 3. **Learning** - See how MCP works through examples
156
+ 4. **Community** - Share and discover agents easily
157
+
158
+ ## ๐Ÿค Contributing
159
+
160
+ We welcome contributions! See our [Contributing Guide](CONTRIBUTING.md) for details.
161
+
162
+ ### Development Setup
163
+
164
+ ```bash
165
+ # Install in development mode
166
+ pip install -e ".[dev]"
167
+
168
+ # Run tests
169
+ pytest
170
+
171
+ # Format code
172
+ black .
173
+ ruff check .
174
+ ```
175
+
176
+ ## ๐Ÿ“„ License
177
+
178
+ This project is licensed under the Apache License 2.0 - see the [LICENSE](LICENSE) file.
179
+
180
+ ## ๐Ÿ™ Acknowledgments
181
+
182
+ - **Hugging Face** - For hosting and the MCP Hackathon
183
+ - **Gradio Team** - For the amazing framework
184
+ - **Anthropic** - For the Model Context Protocol
185
+ - **Community** - For feedback and contributions
186
+
187
+ ## ๐Ÿ“ž Contact & Support
188
+
189
+ - **GitHub Issues**: [Report bugs or request features](https://github.com/seanpoyner/gradio-mcp-playground/issues)
190
+ - **Discussions**: [Join the conversation](https://huggingface.co/spaces/seanpoyner/gradio-mcp-playground/discussions)
191
+ - **Twitter**: [@seanpoyner](https://twitter.com/seanpoyner)
192
+
193
+ ---
194
+
195
+ <div align="center">
196
+ <b>Made with โค๏ธ for the Hugging Face MCP Hackathon 2025</b>
197
+ <br>
198
+ <i>Empowering everyone to build AI agents</i>
199
+ </div>
app.py ADDED
@@ -0,0 +1,999 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # app.py - Gradio MCP Playground Demo for HF Spaces
2
+ import gradio as gr
3
+ import json
4
+ import os
5
+ from datetime import datetime
6
+ from typing import Dict, List, Optional, Tuple
7
+ import uuid
8
+ import asyncio
9
+ import time
10
+
11
+ # Demo mode flag
12
+ DEMO_MODE = True
13
+ HF_SPACE_ID = os.getenv("SPACE_ID", "demo")
14
+
15
+ class GradioMCPPlayground:
16
+ """Streamlined demo showcasing core MCP agent capabilities"""
17
+
18
+ def __init__(self):
19
+ self.demo_mode = DEMO_MODE
20
+ self.sessions = {} # Session-based storage
21
+ self.setup_demo_data()
22
+
23
+ def setup_demo_data(self):
24
+ """Initialize impressive demo content"""
25
+ self.demo_agents = [
26
+ {
27
+ "id": "weather-assistant",
28
+ "name": "Weather Assistant",
29
+ "description": "Real-time weather information using MCP tools",
30
+ "template": "weather",
31
+ "status": "active",
32
+ "tools": ["get_weather", "get_forecast"],
33
+ "created": "2025-01-08"
34
+ },
35
+ {
36
+ "id": "code-helper",
37
+ "name": "Code Helper",
38
+ "description": "AI pair programmer with file system access",
39
+ "template": "filesystem",
40
+ "status": "active",
41
+ "tools": ["read_file", "write_file", "list_directory"],
42
+ "created": "2025-01-09"
43
+ },
44
+ {
45
+ "id": "research-agent",
46
+ "name": "Research Agent",
47
+ "description": "Web search and summarization",
48
+ "template": "search",
49
+ "status": "beta",
50
+ "tools": ["web_search", "summarize"],
51
+ "created": "2025-01-10"
52
+ }
53
+ ]
54
+
55
+ self.mcp_servers = {
56
+ "filesystem": {
57
+ "name": "File System MCP",
58
+ "status": "connected",
59
+ "endpoint": "mcp://localhost:3000",
60
+ "tools": ["read_file", "write_file", "list_directory", "create_directory", "delete_file"]
61
+ },
62
+ "brave-search": {
63
+ "name": "Brave Search MCP",
64
+ "status": "available",
65
+ "endpoint": "mcp://localhost:3001",
66
+ "tools": ["web_search", "image_search"]
67
+ },
68
+ "weather": {
69
+ "name": "Weather API MCP",
70
+ "status": "connected",
71
+ "endpoint": "mcp://localhost:3002",
72
+ "tools": ["get_weather", "get_forecast"]
73
+ }
74
+ }
75
+
76
+ self.chat_history = []
77
+
78
+ def get_session_data(self, session_id: str) -> Dict:
79
+ """Get or create session data"""
80
+ if session_id not in self.sessions:
81
+ self.sessions[session_id] = {
82
+ "agents": list(self.demo_agents),
83
+ "chat_history": [],
84
+ "created_agents": []
85
+ }
86
+ return self.sessions[session_id]
87
+
88
+ def create_interface(self) -> gr.Blocks:
89
+ """Create the main Gradio interface"""
90
+ with gr.Blocks(
91
+ title="๐Ÿ› Gradio MCP Playground",
92
+ theme=gr.themes.Soft(
93
+ primary_hue="blue",
94
+ secondary_hue="green",
95
+ ),
96
+ css="""
97
+ .gradio-container {max-width: 1200px !important}
98
+ .success-message {
99
+ background-color: #d4edda !important;
100
+ border: 1px solid #c3e6cb;
101
+ color: #155724;
102
+ padding: 12px;
103
+ border-radius: 4px;
104
+ margin: 10px 0;
105
+ }
106
+ .info-box {
107
+ background-color: #d1ecf1;
108
+ border: 1px solid #bee5eb;
109
+ color: #0c5460;
110
+ padding: 12px;
111
+ border-radius: 4px;
112
+ margin: 10px 0;
113
+ }
114
+ .tool-response {
115
+ background-color: #f8f9fa;
116
+ border-left: 4px solid #007bff;
117
+ padding: 10px;
118
+ margin: 10px 0;
119
+ font-family: monospace;
120
+ }
121
+ .template-card {
122
+ background: #374151;
123
+ border: 2px solid #4b5563;
124
+ border-radius: 8px;
125
+ padding: 15px;
126
+ margin: 10px 0;
127
+ cursor: pointer;
128
+ transition: all 0.3s ease;
129
+ }
130
+ .template-card:hover {
131
+ border-color: #60a5fa;
132
+ transform: translateY(-2px);
133
+ }
134
+ .template-name {
135
+ color: #f3f4f6;
136
+ font-weight: bold;
137
+ margin-bottom: 5px;
138
+ }
139
+ .template-description {
140
+ color: #d1d5db;
141
+ font-size: 0.9em;
142
+ }
143
+ .template-tools {
144
+ color: #9ca3af;
145
+ font-size: 0.8em;
146
+ margin-top: 8px;
147
+ }
148
+ """
149
+ ) as demo:
150
+ # State management
151
+ session_id = gr.State(value=str(uuid.uuid4()))
152
+
153
+ # Header
154
+ with gr.Row():
155
+ gr.Markdown("""
156
+ # ๐Ÿ› Gradio MCP Playground
157
+ ### Build AI Agents in Seconds - No Code Required!
158
+
159
+ <div class="info-box">
160
+ <b>๐Ÿ† Hugging Face MCP Hackathon Submission</b><br>
161
+ Transform any Python function into an AI agent with visual tools and instant testing.
162
+ <a href="https://github.com/seanpoyner/gradio-mcp-playground" target="_blank">GitHub</a> |
163
+ <a href="https://huggingface.co/spaces/seanpoyner/gradio-mcp-playground" target="_blank">Documentation</a>
164
+ </div>
165
+ """)
166
+
167
+ # Main tabs
168
+ with gr.Tabs() as main_tabs:
169
+ # Tab 1: AI Assistant Hub (Main Feature)
170
+ with gr.Tab("๐Ÿ› AI Assistant", id="assistant"):
171
+ self.create_assistant_tab(session_id)
172
+
173
+ # Tab 2: Visual Agent Builder
174
+ with gr.Tab("๐Ÿ—๏ธ Server Builder", id="builder"):
175
+ self.create_builder_tab(session_id)
176
+
177
+ # Tab 3: MCP Connections
178
+ with gr.Tab("๐Ÿ”Œ MCP Connections", id="tools"):
179
+ self.create_tools_tab(session_id)
180
+
181
+ # Tab 4: My Agents
182
+ with gr.Tab("๐Ÿ“ฆ Server Management", id="agents"):
183
+ self.create_agents_tab(session_id)
184
+
185
+ # Tab 5: Help
186
+ with gr.Tab("๐Ÿ“š Help & Resources", id="help"):
187
+ self.create_help_tab()
188
+
189
+ # Footer
190
+ gr.Markdown("""
191
+ ---
192
+ <center>
193
+ Made with โค๏ธ using Gradio |
194
+ <a href="https://huggingface.co/spaces/seanpoyner/gradio-mcp-playground/discussions" target="_blank">Feedback</a> |
195
+ <a href="https://github.com/seanpoyner/gradio-mcp-playground" target="_blank">GitHub</a>
196
+ </center>
197
+ """)
198
+
199
+ return demo
200
+
201
+ def create_assistant_tab(self, session_id):
202
+ """Multi-mode AI assistant interface"""
203
+ with gr.Row():
204
+ with gr.Column(scale=1):
205
+ assistant_mode = gr.Radio(
206
+ choices=[
207
+ "Adam (General)",
208
+ "Liam (MCP Agent)",
209
+ "Arthur (Agent Builder)"
210
+ ],
211
+ value="Adam (General)",
212
+ label="Choose AI Assistant",
213
+ info="Each assistant specializes in different tasks"
214
+ )
215
+
216
+ gr.Markdown("""
217
+ ### ๐Ÿ› ๏ธ Available MCP Tools
218
+
219
+ **Connected:**
220
+ - ๐Ÿ“ **FileSystem**: Read/write files
221
+ - ๐ŸŒค๏ธ **Weather**: Real-time weather
222
+ - ๐Ÿ” **Search**: Web search
223
+
224
+ **Available:**
225
+ - ๐Ÿ–ผ๏ธ Images
226
+ - ๐Ÿ“Š Data Analysis
227
+ - ๐Ÿ—„๏ธ Database
228
+ """)
229
+
230
+ clear_btn = gr.Button("Clear Chat", variant="secondary")
231
+
232
+ with gr.Column(scale=2):
233
+ chatbot = gr.Chatbot(
234
+ value=[
235
+ (None, "๐Ÿ‘‹ Hi! I'm Adam, your AI assistant with MCP superpowers. I can help you build agents, test MCP tools, or answer questions. Try asking me to check the weather or create a calculator agent!")
236
+ ],
237
+ height=400,
238
+ avatar_images=(None, "https://api.dicebear.com/7.x/bottts/svg?seed=adam")
239
+ )
240
+
241
+ with gr.Row():
242
+ msg_input = gr.Textbox(
243
+ label="Message",
244
+ placeholder="Try: 'What's the weather in Paris?' or 'Help me build a calculator agent'",
245
+ scale=4,
246
+ lines=1
247
+ )
248
+ send_btn = gr.Button("Send", variant="primary", scale=1)
249
+
250
+ # Tool execution display
251
+ with gr.Accordion("๐Ÿ”ง Tool Execution Log", open=False) as tool_log:
252
+ tool_display = gr.Markdown("*No tools executed yet*")
253
+
254
+ # Example prompts
255
+ gr.Examples(
256
+ examples=[
257
+ "What's the weather in San Francisco?",
258
+ "Help me create a calculator agent",
259
+ "Show me available MCP tools",
260
+ "How do I connect a new MCP server?",
261
+ "Build an agent that can search the web"
262
+ ],
263
+ inputs=msg_input,
264
+ label="Quick Start Examples"
265
+ )
266
+
267
+ # Chat functionality
268
+ def respond(message: str, history: List, mode: str) -> Tuple[List, str, str]:
269
+ """Process chat messages and simulate MCP tool execution"""
270
+ if not message.strip():
271
+ return history, "", tool_display.value
272
+
273
+ # Simulate different assistant personalities
274
+ assistant_name = mode.split(" ")[0]
275
+
276
+ # Simulate MCP tool execution for certain queries
277
+ tool_executed = None
278
+
279
+ if "weather" in message.lower():
280
+ # Simulate weather tool execution
281
+ location = "San Francisco" # Extract from message in real impl
282
+ if "paris" in message.lower():
283
+ location = "Paris"
284
+ tool_executed = f"""
285
+ ### ๐Ÿ”ง Tool Execution
286
+
287
+ **Tool:** `weather.get_current`
288
+ **Parameters:** `{{"location": "{location}"}}`
289
+ **Response:**
290
+ ```json
291
+ {{
292
+ "temperature": 72,
293
+ "condition": "Sunny",
294
+ "humidity": 65,
295
+ "wind_speed": 12
296
+ }}
297
+ ```
298
+ **Status:** โœ… Success
299
+ """
300
+ response = f"I've checked the weather using the MCP weather tool. In {location}, it's currently 72ยฐF and sunny with 65% humidity and winds at 12 mph. Perfect weather for a walk! โ˜€๏ธ"
301
+
302
+ elif "create" in message.lower() and ("agent" in message.lower() or "calculator" in message.lower()):
303
+ response = """I'll help you create a calculator agent! Here's what I'll do:
304
+
305
+ 1. **Choose a template**: I'll use the calculator template that includes basic math operations
306
+ 2. **Configure the agent**: Set up addition, subtraction, multiplication, and division tools
307
+ 3. **Generate MCP server code**: Create a Python-based MCP server
308
+ 4. **Test the tools**: Verify each operation works correctly
309
+
310
+ Would you like me to walk you through the visual builder, or should I generate the code directly for you?"""
311
+
312
+ elif "mcp tools" in message.lower() or "available tools" in message.lower():
313
+ response = """Here are the currently available MCP tools:
314
+
315
+ ๐Ÿ“ **FileSystem MCP** (Connected)
316
+ - `read_file`: Read file contents
317
+ - `write_file`: Write to files
318
+ - `list_directory`: List folder contents
319
+
320
+ ๐ŸŒค๏ธ **Weather MCP** (Connected)
321
+ - `get_current`: Current weather
322
+ - `get_forecast`: 5-day forecast
323
+
324
+ ๐Ÿ” **Search MCP** (Available)
325
+ - `web_search`: Search the web
326
+ - `image_search`: Find images
327
+
328
+ Would you like to test any of these tools or learn how to create your own?"""
329
+
330
+ else:
331
+ # General responses based on assistant mode
332
+ if assistant_name == "Adam":
333
+ response = f"Great question! As a general assistant with MCP capabilities, I can help you with {message}. Would you like me to use any specific tools or create an agent for this task?"
334
+ elif assistant_name == "Liam":
335
+ response = f"As an MCP development specialist, I'll help you with {message}. I can show you how to implement this as an MCP tool or integrate it into an existing server. Which approach would you prefer?"
336
+ else: # Arthur
337
+ response = f"Let's architect a solution for {message}. I can help you design the agent structure, choose the right MCP tools, and create a scalable implementation. What's your main goal with this agent?"
338
+
339
+ # Add to history
340
+ history.append((message, response))
341
+
342
+ # Update tool display
343
+ tool_display_text = tool_executed if tool_executed else "*No tools executed*"
344
+
345
+ return history, "", tool_display_text
346
+
347
+ # Wire up events
348
+ msg_input.submit(respond, [msg_input, chatbot, assistant_mode], [chatbot, msg_input, tool_display])
349
+ send_btn.click(respond, [msg_input, chatbot, assistant_mode], [chatbot, msg_input, tool_display])
350
+ clear_btn.click(lambda: ([(None, "Chat cleared! How can I help you?")], ""), outputs=[chatbot, msg_input])
351
+
352
+ def create_builder_tab(self, session_id):
353
+ """Visual agent builder interface"""
354
+ with gr.Row():
355
+ with gr.Column():
356
+ gr.Markdown("### ๐Ÿ—๏ธ Create Your Server")
357
+
358
+ agent_name = gr.Textbox(
359
+ label="Server Name",
360
+ placeholder="my-awesome-server",
361
+ info="Lowercase letters, numbers, and hyphens only"
362
+ )
363
+
364
+ agent_desc = gr.Textbox(
365
+ label="Description",
366
+ placeholder="What does your server do?",
367
+ lines=2
368
+ )
369
+
370
+ template = gr.Dropdown(
371
+ choices=[
372
+ ("๐Ÿงฎ Calculator - Math operations", "calculator"),
373
+ ("๐ŸŒค๏ธ Weather - Weather information", "weather"),
374
+ ("๐Ÿ” Search - Web search", "search"),
375
+ ("๐Ÿ“ FileSystem - File operations", "filesystem"),
376
+ ("โšก Custom - Start from scratch", "custom")
377
+ ],
378
+ label="Template",
379
+ value="calculator",
380
+ info="Choose a starting template"
381
+ )
382
+
383
+ with gr.Row():
384
+ create_btn = gr.Button("Create Server", variant="primary")
385
+ test_btn = gr.Button("Test Server", variant="secondary")
386
+
387
+ creation_status = gr.HTML()
388
+
389
+ # Templates gallery
390
+ gr.Markdown("### ๐Ÿ“š Template Gallery")
391
+ templates_html = gr.HTML(self.render_templates_gallery())
392
+
393
+ with gr.Column():
394
+ gr.Markdown("### ๐Ÿ“ Generated Code")
395
+
396
+ code_editor = gr.Code(
397
+ label="MCP Server Implementation",
398
+ language="python",
399
+ value=self.get_template_code("calculator"),
400
+ lines=20
401
+ )
402
+
403
+ with gr.Accordion("๐Ÿงช Test Console", open=False):
404
+ test_input = gr.Textbox(
405
+ label="Test Input",
406
+ placeholder='{"operation": "add", "a": 5, "b": 3}'
407
+ )
408
+ test_output = gr.JSON(label="Test Output")
409
+
410
+ # Template change handler
411
+ def update_template(template_choice):
412
+ return self.get_template_code(template_choice)
413
+
414
+ template.change(update_template, template, code_editor)
415
+
416
+ # Create agent handler
417
+ def create_agent(name, desc, template_choice, session_data):
418
+ if not name:
419
+ return '<div class="error">Please enter a server name</div>'
420
+
421
+ # Add to session agents
422
+ new_agent = {
423
+ "id": str(uuid.uuid4()),
424
+ "name": name,
425
+ "description": desc,
426
+ "template": template_choice,
427
+ "status": "created",
428
+ "created": datetime.now().strftime("%Y-%m-%d %H:%M")
429
+ }
430
+
431
+ # In demo mode, just show success
432
+ return f'''
433
+ <div class="success-message">
434
+ โœ… <b>Server "{name}" created successfully!</b><br>
435
+ Template: {template_choice}<br>
436
+ Status: Ready to deploy<br>
437
+ <small>Note: In production, this would be saved to your account.</small>
438
+ </div>
439
+ '''
440
+
441
+ create_btn.click(
442
+ create_agent,
443
+ [agent_name, agent_desc, template, session_id],
444
+ creation_status
445
+ )
446
+
447
+ # Test handler
448
+ def test_agent(test_input_str):
449
+ try:
450
+ # Simulate test execution
451
+ import json
452
+ input_data = json.loads(test_input_str)
453
+
454
+ # Mock response based on template
455
+ if "operation" in input_data:
456
+ result = {"result": 8, "operation": "add", "status": "success"}
457
+ else:
458
+ result = {"status": "success", "message": "Test completed"}
459
+
460
+ return result
461
+ except Exception as e:
462
+ return {"error": str(e), "status": "failed"}
463
+
464
+ test_btn.click(test_agent, test_input, test_output)
465
+
466
+ def create_tools_tab(self, session_id):
467
+ """MCP tools and connections interface"""
468
+ with gr.Row():
469
+ with gr.Column():
470
+ gr.Markdown("### ๐Ÿ”Œ Quick Connect")
471
+
472
+ # Quick connect buttons
473
+ with gr.Row():
474
+ fs_btn = gr.Button("๐Ÿ“ Filesystem", variant="secondary")
475
+ weather_btn = gr.Button("๐ŸŒค๏ธ Weather", variant="secondary")
476
+ search_btn = gr.Button("๐Ÿ” Search", variant="secondary")
477
+
478
+ gr.Markdown("### ๐Ÿ”Œ Connected MCP Servers")
479
+
480
+ # Server status cards
481
+ server_html = self.render_server_cards()
482
+ server_display = gr.HTML(server_html)
483
+
484
+ # Add new server
485
+ with gr.Accordion("โž• Add MCP Server", open=False):
486
+ server_url = gr.Textbox(
487
+ label="Server URL",
488
+ placeholder="mcp://localhost:3000"
489
+ )
490
+ server_name = gr.Textbox(
491
+ label="Server Name",
492
+ placeholder="My Custom Server"
493
+ )
494
+ connect_btn = gr.Button("Connect", variant="primary")
495
+
496
+ refresh_btn = gr.Button("๐Ÿ”„ Refresh Status", variant="secondary")
497
+
498
+ with gr.Column():
499
+ gr.Markdown("### ๐Ÿงช Test MCP Tools")
500
+
501
+ # Tool selector
502
+ tool_category = gr.Dropdown(
503
+ choices=list(self.mcp_servers.keys()),
504
+ label="Select Server",
505
+ value="filesystem"
506
+ )
507
+
508
+ tool_name = gr.Dropdown(
509
+ choices=self.mcp_servers["filesystem"]["tools"],
510
+ label="Select Tool"
511
+ )
512
+
513
+ # Tool parameters
514
+ tool_params = gr.JSON(
515
+ value={"path": "/tmp/test.txt"},
516
+ label="Tool Parameters",
517
+ lines=5
518
+ )
519
+
520
+ execute_btn = gr.Button("โ–ถ๏ธ Execute Tool", variant="primary")
521
+
522
+ # Results
523
+ execution_result = gr.JSON(
524
+ label="Execution Result",
525
+ value={"status": "ready"}
526
+ )
527
+
528
+ # Activity log
529
+ gr.Markdown("### ๐Ÿ“Š Activity Log")
530
+ activity_log = gr.Textbox(
531
+ value=self.get_activity_log(),
532
+ label="Recent Activity",
533
+ lines=8,
534
+ max_lines=10,
535
+ interactive=False
536
+ )
537
+
538
+ # Update tool list when server changes
539
+ def update_tools(server):
540
+ return gr.update(choices=self.mcp_servers.get(server, {}).get("tools", []))
541
+
542
+ tool_category.change(update_tools, tool_category, tool_name)
543
+
544
+ # Execute tool
545
+ def execute_tool(server, tool, params):
546
+ # Simulate tool execution
547
+ result = {
548
+ "server": server,
549
+ "tool": tool,
550
+ "params": params,
551
+ "response": {
552
+ "status": "success",
553
+ "data": f"Executed {tool} successfully",
554
+ "timestamp": datetime.now().isoformat()
555
+ }
556
+ }
557
+
558
+ # Update activity log
559
+ new_log = f"[{datetime.now().strftime('%H:%M:%S')}] Executed {server}.{tool}\n"
560
+
561
+ return result, activity_log.value + new_log
562
+
563
+ execute_btn.click(
564
+ execute_tool,
565
+ [tool_category, tool_name, tool_params],
566
+ [execution_result, activity_log]
567
+ )
568
+
569
+ def create_agents_tab(self, session_id):
570
+ """Display user's agents"""
571
+ with gr.Row():
572
+ with gr.Column():
573
+ gr.Markdown("### ๐Ÿ“ฆ Your Servers")
574
+
575
+ # Search and filter
576
+ with gr.Row():
577
+ search_box = gr.Textbox(
578
+ label="Search",
579
+ placeholder="Search servers...",
580
+ scale=3
581
+ )
582
+ filter_status = gr.Dropdown(
583
+ choices=["All", "Active", "Inactive", "Beta"],
584
+ value="All",
585
+ label="Status",
586
+ scale=1
587
+ )
588
+
589
+ # Agent gallery
590
+ agent_gallery = gr.HTML(self.render_agent_gallery())
591
+
592
+ # Refresh button
593
+ refresh_agents_btn = gr.Button("๐Ÿ”„ Refresh", variant="secondary")
594
+
595
+ with gr.Column():
596
+ gr.Markdown("### ๐Ÿ“Š Server Details")
597
+
598
+ selected_agent = gr.JSON(
599
+ label="Selected Server",
600
+ value=self.demo_agents[0] if self.demo_agents else {}
601
+ )
602
+
603
+ with gr.Row():
604
+ deploy_btn = gr.Button("๐Ÿš€ Deploy", variant="primary")
605
+ edit_btn = gr.Button("โœ๏ธ Edit", variant="secondary")
606
+ delete_btn = gr.Button("๐Ÿ—‘๏ธ Delete", variant="stop")
607
+
608
+ deployment_status = gr.HTML()
609
+
610
+ # Deploy handler
611
+ def deploy_agent(agent_data):
612
+ return f'''
613
+ <div class="success-message">
614
+ ๐Ÿš€ <b>Deployment Initiated!</b><br>
615
+ Server: {agent_data.get('name', 'Unknown')}<br>
616
+ Target: Hugging Face Spaces<br>
617
+ Status: In Progress...<br>
618
+ <small>Note: In production, this would deploy to your HF Space.</small>
619
+ </div>
620
+ '''
621
+
622
+ deploy_btn.click(deploy_agent, selected_agent, deployment_status)
623
+
624
+ def create_help_tab(self):
625
+ """Help and resources tab"""
626
+ gr.Markdown("""
627
+ ## ๐Ÿ“š Help & Resources
628
+
629
+ ### ๐Ÿš€ Quick Start Guide
630
+
631
+ 1. **Choose an AI Assistant** - Start with Adam for general help, Liam for MCP development, or Arthur for architecture
632
+ 2. **Build Your First Agent** - Use the Server Builder tab to create an agent from templates
633
+ 3. **Connect MCP Servers** - Use the MCP Connections tab to connect to available servers
634
+ 4. **Test and Deploy** - Test your agents and deploy them to production
635
+
636
+ ### ๐Ÿ”ง Available Templates
637
+
638
+ - **Calculator** - Basic math operations (add, subtract, multiply, divide)
639
+ - **Weather** - Get weather information for any location
640
+ - **Search** - Web search capabilities
641
+ - **FileSystem** - Read and write files (with safety checks)
642
+ - **Custom** - Start from scratch with your own implementation
643
+
644
+ ### ๐Ÿ“– Documentation
645
+
646
+ - [Getting Started Guide](https://github.com/seanpoyner/gradio-mcp-playground/wiki/Getting-Started)
647
+ - [MCP Protocol Specification](https://github.com/anthropics/mcp)
648
+ - [Gradio Documentation](https://gradio.app/docs)
649
+
650
+ ### ๐Ÿ’ก Tips
651
+
652
+ - Use the chat to ask for help building specific agents
653
+ - Templates are fully customizable - modify the generated code as needed
654
+ - Test your tools before deploying to ensure they work correctly
655
+ - Join our Discord for community support and sharing
656
+
657
+ ### ๐Ÿ› Known Limitations (Demo Mode)
658
+
659
+ - MCP servers are simulated in this demo
660
+ - File operations are limited to safe paths
661
+ - API integrations require your own keys
662
+ - Deployments are simulated (not real)
663
+
664
+ ### ๐Ÿ“ž Support
665
+
666
+ - [GitHub Issues](https://github.com/seanpoyner/gradio-mcp-playground/issues)
667
+ - [Discussions](https://huggingface.co/spaces/seanpoyner/gradio-mcp-playground/discussions)
668
+ - [Discord Community](#)
669
+ """)
670
+
671
+ def get_template_code(self, template: str) -> str:
672
+ """Return template code for different agent types"""
673
+ templates = {
674
+ "calculator": '''"""
675
+ Calculator MCP Server
676
+ A simple calculator that performs basic math operations
677
+ """
678
+ import json
679
+ from typing import Dict, Any
680
+ from mcp.server import Server, Tool
681
+
682
+ class CalculatorServer(Server):
683
+ def __init__(self):
684
+ super().__init__("calculator")
685
+ self.register_tools()
686
+
687
+ def register_tools(self):
688
+ self.add_tool(Tool(
689
+ name="calculate",
690
+ description="Perform a calculation",
691
+ input_schema={
692
+ "type": "object",
693
+ "properties": {
694
+ "operation": {
695
+ "type": "string",
696
+ "enum": ["add", "subtract", "multiply", "divide"]
697
+ },
698
+ "a": {"type": "number"},
699
+ "b": {"type": "number"}
700
+ },
701
+ "required": ["operation", "a", "b"]
702
+ },
703
+ handler=self.calculate
704
+ ))
705
+
706
+ async def calculate(self, operation: str, a: float, b: float) -> Dict[str, Any]:
707
+ """Execute calculation based on operation"""
708
+ operations = {
709
+ "add": lambda x, y: x + y,
710
+ "subtract": lambda x, y: x - y,
711
+ "multiply": lambda x, y: x * y,
712
+ "divide": lambda x, y: x / y if y != 0 else None
713
+ }
714
+
715
+ if operation in operations:
716
+ result = operations[operation](a, b)
717
+ if result is not None:
718
+ return {"result": result, "status": "success"}
719
+ else:
720
+ return {"error": "Division by zero", "status": "error"}
721
+
722
+ return {"error": "Unknown operation", "status": "error"}
723
+
724
+ if __name__ == "__main__":
725
+ server = CalculatorServer()
726
+ server.run()
727
+ ''',
728
+ "weather": '''"""
729
+ Weather MCP Server
730
+ Provides weather information for any location
731
+ """
732
+ import aiohttp
733
+ from mcp.server import Server, Tool
734
+
735
+ class WeatherServer(Server):
736
+ def __init__(self):
737
+ super().__init__("weather")
738
+ self.api_key = "YOUR_API_KEY" # Set via environment variable
739
+ self.register_tools()
740
+
741
+ def register_tools(self):
742
+ self.add_tool(Tool(
743
+ name="get_current_weather",
744
+ description="Get current weather for a location",
745
+ input_schema={
746
+ "type": "object",
747
+ "properties": {
748
+ "location": {"type": "string"}
749
+ },
750
+ "required": ["location"]
751
+ },
752
+ handler=self.get_weather
753
+ ))
754
+
755
+ async def get_weather(self, location: str) -> dict:
756
+ """Fetch current weather data"""
757
+ # Demo response
758
+ return {
759
+ "location": location,
760
+ "temperature": 72,
761
+ "condition": "Sunny",
762
+ "humidity": 65,
763
+ "wind_speed": 12,
764
+ "unit": "fahrenheit"
765
+ }
766
+
767
+ if __name__ == "__main__":
768
+ server = WeatherServer()
769
+ server.run()
770
+ ''',
771
+ "filesystem": '''"""
772
+ FileSystem MCP Server
773
+ Safe file operations within allowed directories
774
+ """
775
+ import os
776
+ import json
777
+ from pathlib import Path
778
+ from mcp.server import Server, Tool
779
+
780
+ class FileSystemServer(Server):
781
+ def __init__(self):
782
+ super().__init__("filesystem")
783
+ self.allowed_paths = ["/tmp", "/workspace"]
784
+ self.register_tools()
785
+
786
+ def register_tools(self):
787
+ tools = [
788
+ Tool(
789
+ name="read_file",
790
+ description="Read file contents",
791
+ input_schema={
792
+ "type": "object",
793
+ "properties": {
794
+ "path": {"type": "string"}
795
+ },
796
+ "required": ["path"]
797
+ },
798
+ handler=self.read_file
799
+ ),
800
+ Tool(
801
+ name="write_file",
802
+ description="Write content to file",
803
+ input_schema={
804
+ "type": "object",
805
+ "properties": {
806
+ "path": {"type": "string"},
807
+ "content": {"type": "string"}
808
+ },
809
+ "required": ["path", "content"]
810
+ },
811
+ handler=self.write_file
812
+ )
813
+ ]
814
+
815
+ for tool in tools:
816
+ self.add_tool(tool)
817
+
818
+ async def read_file(self, path: str) -> dict:
819
+ """Read file with safety checks"""
820
+ try:
821
+ file_path = Path(path).resolve()
822
+
823
+ # Safety check
824
+ if not any(str(file_path).startswith(allowed)
825
+ for allowed in self.allowed_paths):
826
+ return {"error": "Path not allowed", "status": "error"}
827
+
828
+ if file_path.exists() and file_path.is_file():
829
+ content = file_path.read_text()
830
+ return {"content": content, "status": "success"}
831
+
832
+ return {"error": "File not found", "status": "error"}
833
+
834
+ except Exception as e:
835
+ return {"error": str(e), "status": "error"}
836
+
837
+ if __name__ == "__main__":
838
+ server = FileSystemServer()
839
+ server.run()
840
+ ''',
841
+ "custom": '''"""
842
+ Custom MCP Server Template
843
+ Build your own MCP server with custom tools
844
+ """
845
+ from mcp.server import Server, Tool
846
+
847
+ class CustomServer(Server):
848
+ def __init__(self):
849
+ super().__init__("custom-server")
850
+ self.register_tools()
851
+
852
+ def register_tools(self):
853
+ # Add your custom tools here
854
+ self.add_tool(Tool(
855
+ name="example_tool",
856
+ description="An example tool",
857
+ input_schema={
858
+ "type": "object",
859
+ "properties": {
860
+ "input": {"type": "string"}
861
+ },
862
+ "required": ["input"]
863
+ },
864
+ handler=self.example_handler
865
+ ))
866
+
867
+ async def example_handler(self, input: str) -> dict:
868
+ """Your tool implementation"""
869
+ return {
870
+ "result": f"Processed: {input}",
871
+ "status": "success"
872
+ }
873
+
874
+ if __name__ == "__main__":
875
+ server = CustomServer()
876
+ server.run()
877
+ '''
878
+ }
879
+ return templates.get(template, templates["custom"])
880
+
881
+ def render_templates_gallery(self) -> str:
882
+ """Render template gallery as HTML"""
883
+ templates = [
884
+ {"name": "Calculator", "desc": "Math operations", "tools": 4, "icon": "๐Ÿงฎ"},
885
+ {"name": "Weather", "desc": "Weather data", "tools": 2, "icon": "๐ŸŒค๏ธ"},
886
+ {"name": "Search", "desc": "Web search", "tools": 2, "icon": "๐Ÿ”"},
887
+ {"name": "FileSystem", "desc": "File operations", "tools": 5, "icon": "๐Ÿ“"},
888
+ ]
889
+
890
+ html = '<div style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px;">'
891
+ for tmpl in templates:
892
+ html += f'''
893
+ <div class="template-card">
894
+ <div class="template-name">{tmpl["icon"]} {tmpl["name"]}</div>
895
+ <div class="template-description">{tmpl["desc"]}</div>
896
+ <div class="template-tools">{tmpl["tools"]} tools included</div>
897
+ </div>
898
+ '''
899
+ html += '</div>'
900
+ return html
901
+
902
+ def render_server_cards(self) -> str:
903
+ """Render MCP server status cards"""
904
+ html = '<div style="display: grid; gap: 15px;">'
905
+
906
+ for server_id, server_info in self.mcp_servers.items():
907
+ status_color = "#28a745" if server_info["status"] == "connected" else "#ffc107"
908
+ status_icon = "๐ŸŸข" if server_info["status"] == "connected" else "๐ŸŸก"
909
+
910
+ html += f'''
911
+ <div style="border: 1px solid #dee2e6; border-radius: 8px; padding: 15px; background: #f8f9fa;">
912
+ <div style="display: flex; justify-content: space-between; align-items: center;">
913
+ <h4 style="margin: 0;">{server_info["name"]}</h4>
914
+ <span style="color: {status_color};">{status_icon} {server_info["status"].title()}</span>
915
+ </div>
916
+ <p style="color: #6c757d; font-size: 14px; margin: 5px 0;">
917
+ {server_info["endpoint"]}
918
+ </p>
919
+ <div style="margin-top: 10px;">
920
+ <span style="background: #e9ecef; padding: 2px 8px; border-radius: 3px; font-size: 12px;">
921
+ {len(server_info["tools"])} tools
922
+ </span>
923
+ </div>
924
+ </div>
925
+ '''
926
+
927
+ html += '</div>'
928
+ return html
929
+
930
+ def render_agent_gallery(self) -> str:
931
+ """Render agent gallery cards"""
932
+ html = '<div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 20px;">'
933
+
934
+ for agent in self.demo_agents:
935
+ status_color = {
936
+ "active": "#28a745",
937
+ "inactive": "#dc3545",
938
+ "beta": "#ffc107"
939
+ }.get(agent["status"], "#6c757d")
940
+
941
+ html += f'''
942
+ <div style="border: 1px solid #dee2e6; border-radius: 8px; padding: 20px; cursor: pointer; transition: transform 0.2s; hover: transform: scale(1.02);">
943
+ <h4 style="margin: 0 0 10px 0;">{agent["name"]}</h4>
944
+ <p style="color: #6c757d; font-size: 14px; margin-bottom: 15px;">
945
+ {agent["description"]}
946
+ </p>
947
+ <div style="display: flex; justify-content: space-between; align-items: center;">
948
+ <span style="color: {status_color}; font-size: 12px;">
949
+ โ— {agent["status"].upper()}
950
+ </span>
951
+ <span style="font-size: 12px; color: #6c757d;">
952
+ {len(agent["tools"])} tools
953
+ </span>
954
+ </div>
955
+ <div style="margin-top: 10px;">
956
+ <small style="color: #6c757d;">Created: {agent["created"]}</small>
957
+ </div>
958
+ <button style="width: 100%; margin-top: 15px; padding: 8px; background: #007bff; color: white; border: none; border-radius: 4px; cursor: pointer;">
959
+ View Details
960
+ </button>
961
+ </div>
962
+ '''
963
+
964
+ html += '</div>'
965
+ return html
966
+
967
+ def get_activity_log(self) -> str:
968
+ """Generate activity log entries"""
969
+ return """[10:00:00] System initialized
970
+ [10:00:01] Connected to filesystem MCP server
971
+ [10:00:02] Connected to weather MCP server
972
+ [10:00:03] Tool discovery completed: 10 tools available
973
+ [10:00:05] Agent registry loaded: 3 agents
974
+ [10:00:10] Ready for connections
975
+ [10:01:23] Executed: filesystem.read_file
976
+ [10:02:45] Executed: weather.get_current
977
+ """
978
+
979
+ # Initialize and launch
980
+ if __name__ == "__main__":
981
+ print("๐Ÿš€ Starting Gradio MCP Playground...")
982
+
983
+ # Create app instance
984
+ app = GradioMCPPlayground()
985
+
986
+ # Create interface
987
+ demo = app.create_interface()
988
+
989
+ # Configure for HF Spaces
990
+ demo.queue(max_size=20)
991
+
992
+ # Launch
993
+ demo.launch(
994
+ server_name="0.0.0.0",
995
+ server_port=7860,
996
+ share=False,
997
+ show_error=True,
998
+ favicon_path="๐Ÿ›"
999
+ )
requirements.txt ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ # requirements.txt for HF Space
2
+ gradio==4.31.0
3
+ huggingface-hub>=0.23.0
4
+ pydantic>=2.0.0
5
+ typing-extensions>=4.5.0
6
+ aiohttp>=3.9.0
7
+ python-multipart>=0.0.6
8
+ uvicorn>=0.27.0
9
+ fastapi>=0.109.0