seanpoyner commited on
Commit
aab630b
Β·
1 Parent(s): 29c4a42

Add complete UI with all tabs, chat interface, and demo labels - direct users to GitHub for full functionality

Browse files
Files changed (2) hide show
  1. __pycache__/app.cpython-312.pyc +0 -0
  2. app.py +365 -104
__pycache__/app.cpython-312.pyc ADDED
Binary file (39 kB). View file
 
app.py CHANGED
@@ -16,6 +16,7 @@ import shutil
16
  # Configuration
17
  HF_SPACE_MODE = True
18
  HF_SPACE_ID = os.getenv("SPACE_ID", "seanpoyner/gradio-mcp-playground")
 
19
 
20
  class MCPPlaygroundApp:
21
  """Gradio MCP Playground - Functional demo for HF Spaces"""
@@ -24,6 +25,7 @@ class MCPPlaygroundApp:
24
  self.sessions = {}
25
  self.templates = self.load_templates()
26
  self.active_servers = {}
 
27
 
28
  def load_templates(self) -> List[Dict]:
29
  """Load available MCP server templates"""
@@ -177,6 +179,20 @@ while True:
177
  ),
178
  css=self.get_custom_css()
179
  ) as demo:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
180
  # Header
181
  gr.Markdown("""
182
  # πŸ› Gradio MCP Playground
@@ -189,135 +205,347 @@ while True:
189
  session_id = gr.State(value=lambda: str(uuid.uuid4()))
190
 
191
  with gr.Tabs() as tabs:
192
- # Dashboard Tab
193
- with gr.Tab("πŸ“Š Dashboard"):
194
- gr.Markdown("## Active MCP Servers")
195
 
196
  with gr.Row():
197
- server_status = gr.JSON(
198
- value={"message": "No active servers", "count": 0},
199
- label="Server Status"
 
 
200
  )
201
- refresh_btn = gr.Button("πŸ”„ Refresh", scale=0)
202
 
203
- gr.Markdown("## Quick Actions")
204
- with gr.Row():
205
- with gr.Column():
206
- quick_template = gr.Dropdown(
207
- choices=[t["name"] for t in self.templates],
208
- label="Select Template",
209
- value="Calculator"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
210
  )
211
- deploy_quick = gr.Button("πŸš€ Quick Deploy", variant="primary")
 
 
 
 
 
 
 
212
 
213
- deployment_result = gr.JSON(label="Deployment Result")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
214
 
215
- # Server Builder Tab
216
  with gr.Tab("πŸ”§ Server Builder"):
217
- gr.Markdown("## Create MCP Server from Template")
218
 
219
- with gr.Row():
220
- with gr.Column(scale=1):
221
- template_gallery = gr.Radio(
222
- choices=[t["name"] for t in self.templates],
223
- label="Available Templates",
224
- value="Calculator"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
225
  )
226
-
227
- template_info = gr.JSON(
228
- value=self.templates[0],
229
- label="Template Details"
230
  )
231
 
232
- with gr.Column(scale=2):
233
- server_name = gr.Textbox(
234
- label="Server Name",
235
- placeholder="my-calculator-server"
 
 
236
  )
237
 
238
- server_code = gr.Code(
239
- value=self.templates[0]["code"],
240
- language="python",
241
- label="Server Code",
242
- lines=20
243
- )
 
 
 
 
 
 
 
244
 
245
  with gr.Row():
246
- create_btn = gr.Button("✨ Create Server", variant="primary")
247
- test_btn = gr.Button("πŸ§ͺ Test Server")
 
 
 
248
 
249
- creation_output = gr.JSON(label="Server Status")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
250
 
251
- # Tools Tab
252
- with gr.Tab("πŸ› οΈ Tools"):
253
- gr.Markdown("## Test MCP Server Tools")
 
 
 
 
 
 
 
254
 
255
  with gr.Row():
256
  with gr.Column():
257
- active_server = gr.Dropdown(
258
- choices=["calculator", "text_processor", "echo"],
259
- label="Select Server",
260
- value="calculator"
 
 
 
 
 
 
 
 
 
 
261
  )
262
 
263
- tool_method = gr.Dropdown(
264
- choices=["add", "subtract", "multiply", "divide"],
265
- label="Select Method"
266
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
267
 
268
- tool_params = gr.JSON(
269
- value={"a": 10, "b": 5},
270
- label="Parameters"
271
- )
272
 
273
- execute_btn = gr.Button("▢️ Execute", variant="primary")
 
 
 
 
 
274
 
275
- with gr.Column():
276
- execution_result = gr.JSON(
277
- label="Execution Result",
278
- value={"status": "ready"}
 
 
 
279
  )
 
 
 
 
 
280
 
281
- execution_log = gr.Textbox(
282
- label="Execution Log",
283
- lines=10,
284
- max_lines=20
285
- )
286
-
287
- # Settings Tab
288
- with gr.Tab("βš™οΈ Settings"):
289
- gr.Markdown("## Playground Settings")
290
-
291
- with gr.Row():
292
- with gr.Column():
293
- gr.Markdown("### Display Settings")
294
- theme_select = gr.Radio(
295
- choices=["Light", "Dark", "System"],
296
- label="Theme",
297
- value="System"
298
- )
299
 
300
- gr.Markdown("### About")
301
- gr.Markdown(f"""
302
- - **Version**: 1.0.0
303
- - **Space ID**: {HF_SPACE_ID}
304
- - **Mode**: {'HF Space' if HF_SPACE_MODE else 'Local'}
305
- - **Created by**: Gradio MCP Team
 
 
 
 
306
  """)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
307
 
308
  # Event handlers
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
309
  refresh_btn.click(
310
  self.refresh_status,
311
  inputs=[session_id],
312
  outputs=[server_status]
313
  )
314
 
315
- deploy_quick.click(
316
- self.quick_deploy,
317
- inputs=[quick_template, session_id],
318
- outputs=[deployment_result, server_status]
319
- )
320
-
321
  template_gallery.change(
322
  self.update_template_view,
323
  inputs=[template_gallery],
@@ -336,25 +564,38 @@ while True:
336
  outputs=[creation_output]
337
  )
338
 
339
- active_server.change(
340
- self.update_tool_methods,
341
- inputs=[active_server],
342
- outputs=[tool_method, tool_params]
343
- )
344
-
345
- execute_btn.click(
346
- self.execute_tool,
347
- inputs=[active_server, tool_method, tool_params, session_id],
348
- outputs=[execution_result, execution_log]
349
- )
350
-
351
  return demo
352
 
353
  def get_custom_css(self) -> str:
354
  """Custom CSS for the interface"""
355
  return """
356
  .gradio-container {
357
- max-width: 1200px !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
358
  }
359
 
360
  /* Dark mode friendly styles */
@@ -387,6 +628,22 @@ while True:
387
  background: #ef4444;
388
  color: white;
389
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
390
  """
391
 
392
  def refresh_status(self, session_id: str) -> Dict:
@@ -568,6 +825,10 @@ while True:
568
  error_result = {"error": str(e), "type": type(e).__name__}
569
  log_lines.append(f"Error: {str(e)}")
570
  return error_result, "\n".join(log_lines)
 
 
 
 
571
 
572
  # Create and launch the app
573
  app = MCPPlaygroundApp()
 
16
  # Configuration
17
  HF_SPACE_MODE = True
18
  HF_SPACE_ID = os.getenv("SPACE_ID", "seanpoyner/gradio-mcp-playground")
19
+ GITHUB_REPO = "https://github.com/seanpoyner/gradio-mcp-playground"
20
 
21
  class MCPPlaygroundApp:
22
  """Gradio MCP Playground - Functional demo for HF Spaces"""
 
25
  self.sessions = {}
26
  self.templates = self.load_templates()
27
  self.active_servers = {}
28
+ self.demo_chat_history = []
29
 
30
  def load_templates(self) -> List[Dict]:
31
  """Load available MCP server templates"""
 
179
  ),
180
  css=self.get_custom_css()
181
  ) as demo:
182
+ # Banner directing to GitHub
183
+ gr.HTML(f"""
184
+ <div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); padding: 20px; border-radius: 10px; margin-bottom: 20px; text-align: center; color: white;">
185
+ <h2 style="margin: 0 0 10px 0; color: white;">🎯 Demo Version - Limited Functionality</h2>
186
+ <p style="margin: 0 0 15px 0; font-size: 16px;">
187
+ This is a demonstration of the Gradio MCP Playground with limited features.
188
+ For full functionality including AI assistants, agent building, and live MCP connections:
189
+ </p>
190
+ <a href="{GITHUB_REPO}" target="_blank" style="background: white; color: #667eea; padding: 12px 30px; border-radius: 25px; text-decoration: none; font-weight: bold; display: inline-block; transition: transform 0.2s;">
191
+ πŸš€ Get Full Version on GitHub
192
+ </a>
193
+ </div>
194
+ """)
195
+
196
  # Header
197
  gr.Markdown("""
198
  # πŸ› Gradio MCP Playground
 
205
  session_id = gr.State(value=lambda: str(uuid.uuid4()))
206
 
207
  with gr.Tabs() as tabs:
208
+ # Tab 1: AI Assistant (Demo)
209
+ with gr.Tab("πŸ› AI Assistant"):
210
+ gr.Markdown("## AI Assistant Hub [DEMO]")
211
 
212
  with gr.Row():
213
+ assistant_mode = gr.Radio(
214
+ choices=["General Assistant", "MCP Development", "Agent Builder"],
215
+ value="General Assistant",
216
+ label="Assistant Mode",
217
+ info="Choose your assistant type"
218
  )
 
219
 
220
+ # General Assistant Mode
221
+ with gr.Group(visible=True) as general_assistant_group:
222
+ gr.Markdown("### Adam - General Assistant [DEMO]")
223
+ gr.Markdown(
224
+ "In the full version, Adam has access to all connected MCP tools and can help with any task. "
225
+ "This demo shows a simulated conversation."
226
+ )
227
+
228
+ # Demo chat interface
229
+ demo_chatbot = gr.Chatbot(
230
+ label="Chat with Adam [DEMO]",
231
+ height=500,
232
+ type="messages",
233
+ value=[
234
+ {"role": "assistant", "content": "πŸ‘‹ Hello! I'm Adam, your general-purpose assistant. In the full version, I have access to MCP tools like screenshot capture, web search, file operations, and more!"},
235
+ {"role": "user", "content": "Can you take a screenshot of a website?"},
236
+ {"role": "assistant", "content": "In the full version, I would use the MCP screenshot tool to capture any website. This demo version doesn't have live MCP connections, but you can see how it would work in the full GitHub version!"}
237
+ ]
238
+ )
239
+
240
+ with gr.Row():
241
+ demo_input = gr.Textbox(
242
+ label="Message [DEMO]",
243
+ placeholder="This is a demo - messages won't be processed. Get the full version on GitHub!",
244
+ scale=4
245
  )
246
+ demo_send_btn = gr.Button("Send [DEMO]", variant="primary", scale=1)
247
+
248
+ # MCP Agent Mode
249
+ with gr.Group(visible=False) as mcp_agent_group:
250
+ gr.Markdown("### Liam - MCP Development Specialist [DEMO]")
251
+ gr.Markdown(
252
+ "In the full version, Liam helps with MCP server development, best practices, and troubleshooting."
253
+ )
254
 
255
+ mcp_demo_chatbot = gr.Chatbot(
256
+ label="Chat with Liam [DEMO]",
257
+ height=500,
258
+ type="messages",
259
+ value=[
260
+ {"role": "assistant", "content": "πŸ‘‹ I'm Liam, your MCP development specialist. In the full version, I can help you build, test, and deploy MCP servers!"}
261
+ ]
262
+ )
263
+
264
+ # Agent Builder Mode
265
+ with gr.Group(visible=False) as agent_builder_group:
266
+ gr.Markdown("### Arthur - Agent Builder [DEMO]")
267
+ gr.Markdown(
268
+ "In the full version, Arthur helps create custom Gradio agents using system prompts from top AI assistants."
269
+ )
270
+
271
+ agent_demo_chatbot = gr.Chatbot(
272
+ label="Agent Builder Assistant [DEMO]",
273
+ height=500,
274
+ type="messages",
275
+ value=[
276
+ {"role": "assistant", "content": "πŸ‘‹ I'm Arthur, your agent creation specialist. In the full version, I can help you create custom agents for data analysis, creative writing, code review, and more!"}
277
+ ]
278
+ )
279
 
280
+ # Tab 2: Server Builder
281
  with gr.Tab("πŸ”§ Server Builder"):
282
+ gr.Markdown("### Build MCP Servers")
283
 
284
+ with gr.Tabs():
285
+ # Quick Create
286
+ with gr.Tab("⚑ Quick Create"):
287
+ with gr.Row():
288
+ with gr.Column(scale=1):
289
+ template_gallery = gr.Radio(
290
+ choices=[t["name"] for t in self.templates],
291
+ label="Available Templates",
292
+ value="Calculator"
293
+ )
294
+
295
+ template_info = gr.JSON(
296
+ value=self.templates[0],
297
+ label="Template Details"
298
+ )
299
+
300
+ with gr.Column(scale=2):
301
+ server_name = gr.Textbox(
302
+ label="Server Name",
303
+ placeholder="my-calculator-server"
304
+ )
305
+
306
+ server_code = gr.Code(
307
+ value=self.templates[0]["code"],
308
+ language="python",
309
+ label="Server Code",
310
+ lines=20
311
+ )
312
+
313
+ with gr.Row():
314
+ create_btn = gr.Button("✨ Create Server", variant="primary")
315
+ test_btn = gr.Button("πŸ§ͺ Test Server")
316
+
317
+ creation_output = gr.JSON(label="Server Status")
318
+
319
+ # Pipeline Builder
320
+ with gr.Tab("πŸ”— Pipeline Builder"):
321
+ gr.Markdown("### Visual Pipeline Builder [DEMO]")
322
+ gr.Markdown(
323
+ "The full version includes a visual pipeline builder for creating complex workflows. "
324
+ "This feature requires the agent components from the GitHub repository."
325
  )
326
+ gr.Image(
327
+ value=None,
328
+ label="Pipeline Builder Preview [DEMO]"
 
329
  )
330
 
331
+ # Templates Gallery
332
+ with gr.Tab("πŸ“š Templates"):
333
+ gr.Markdown("## 🎨 Server Template Gallery")
334
+ gr.Markdown(
335
+ "Choose from our collection of pre-built MCP server templates. "
336
+ "Full versions include AI/ML templates, database connectors, and more!"
337
  )
338
 
339
+ with gr.Row():
340
+ for template in self.templates:
341
+ with gr.Column():
342
+ gr.Markdown(f"### {template['name']}")
343
+ gr.Markdown(f"_{template['description']}_")
344
+ gr.Button(f"Use {template['name']} Template", variant="secondary")
345
+
346
+ # Tab 3: Server Management
347
+ with gr.Tab("πŸ–₯️ Server Management"):
348
+ with gr.Tabs():
349
+ # Active Servers
350
+ with gr.Tab("🟒 Active Servers"):
351
+ gr.Markdown("### Currently Running Servers")
352
 
353
  with gr.Row():
354
+ server_status = gr.JSON(
355
+ value={"message": "Demo mode - showing simulated servers", "count": 2},
356
+ label="Server Status"
357
+ )
358
+ refresh_btn = gr.Button("πŸ”„ Refresh", scale=0)
359
 
360
+ # Simulated active servers
361
+ with gr.Row():
362
+ with gr.Column():
363
+ gr.Markdown("**Calculator Server** 🟒")
364
+ gr.Markdown("Port: 8080 | Status: Running")
365
+ with gr.Column():
366
+ gr.Markdown("**Text Processor** 🟒")
367
+ gr.Markdown("Port: 8081 | Status: Running")
368
+
369
+ # Browse Registry
370
+ with gr.Tab("πŸ“¦ Browse Registry"):
371
+ gr.Markdown("### MCP Server Registry [DEMO]")
372
+ gr.Markdown(
373
+ "The full version includes access to a registry of community MCP servers. "
374
+ "Install servers from npm, PyPI, or custom sources!"
375
+ )
376
 
377
+ # Tab 4: Agent Control Panel
378
+ with gr.Tab("πŸ€– Agent Control Panel"):
379
+ gr.Markdown("## Agent Control Panel [DEMO]")
380
+ gr.Markdown(
381
+ "In the full version, this panel allows you to:\n"
382
+ "- Create and manage custom agents\n"
383
+ "- Configure agent behaviors and tools\n"
384
+ "- Monitor agent performance\n"
385
+ "- Export and share agent configurations"
386
+ )
387
 
388
  with gr.Row():
389
  with gr.Column():
390
+ gr.Markdown("### Available Agents [DEMO]")
391
+ gr.Markdown("- πŸ€– Data Analysis Agent\n- ✍️ Creative Writing Agent\n- πŸ” Code Review Agent")
392
+ with gr.Column():
393
+ gr.Markdown("### Agent Status [DEMO]")
394
+ gr.JSON(value={"status": "demo", "agents": 3})
395
+
396
+ # Tab 5: MCP Connections
397
+ with gr.Tab("πŸ”Œ MCP Connections"):
398
+ with gr.Tabs():
399
+ # Quick Connect
400
+ with gr.Tab("⚑ Quick Connect"):
401
+ gr.Markdown("### Quick Connect to MCP Servers [DEMO]")
402
+ gr.Markdown(
403
+ "The full version allows instant connection to MCP servers via stdio, HTTP, or WebSocket."
404
  )
405
 
406
+ with gr.Row():
407
+ connection_type = gr.Radio(
408
+ choices=["stdio", "http", "websocket"],
409
+ label="Connection Type [DEMO]",
410
+ value="stdio"
411
+ )
412
+ connect_btn = gr.Button("Connect [DEMO]", variant="primary")
413
+
414
+ # Active Connections
415
+ with gr.Tab("πŸ”— Active Connections"):
416
+ gr.Markdown("### Currently Connected Servers [DEMO]")
417
+ gr.Markdown("No active connections in demo mode")
418
+
419
+ # Custom Connection
420
+ with gr.Tab("βž• Custom Connection"):
421
+ gr.Markdown("### Add Custom MCP Connection [DEMO]")
422
+ gr.Textbox(label="Server Command [DEMO]", placeholder="python my_server.py")
423
+ gr.Textbox(label="Arguments [DEMO]", placeholder="--port 8080")
424
+
425
+ # Tab 6: Help & Resources
426
+ with gr.Tab("πŸ“š Help & Resources"):
427
+ with gr.Tabs():
428
+ # User Guides
429
+ with gr.Tab("πŸ“– User Guides"):
430
+ gr.Markdown("""
431
+ ## User Guides
432
 
433
+ ### Getting Started
434
+ 1. **Install the full version** from [GitHub]({GITHUB_REPO})
435
+ 2. **Set up your environment** with required dependencies
436
+ 3. **Launch the playground** and start building!
437
 
438
+ ### Key Features
439
+ - πŸ€– **AI Assistants** - Three specialized assistants for different tasks
440
+ - πŸ”§ **Server Builder** - Create MCP servers from templates
441
+ - πŸ”Œ **Live Connections** - Connect to any MCP server
442
+ - πŸ“Š **Visual Pipeline Builder** - Create complex workflows
443
+ """.replace("{GITHUB_REPO}", GITHUB_REPO))
444
 
445
+ # Configuration
446
+ with gr.Tab("βš™οΈ Configuration"):
447
+ gr.Markdown("### Configuration Guide [DEMO]")
448
+ gr.Code(
449
+ value='{\n "servers": [\n {\n "name": "example-server",\n "command": "python",\n "args": ["server.py"]\n }\n ]\n}',
450
+ language="json",
451
+ label="Example Configuration"
452
  )
453
+
454
+ # Quick Start
455
+ with gr.Tab("πŸš€ Quick Start"):
456
+ gr.Markdown(f"""
457
+ ## Quick Start Guide
458
 
459
+ ### 1. Get the Full Version
460
+ ```bash
461
+ git clone {GITHUB_REPO}
462
+ cd gradio-mcp-playground
463
+ ```
 
 
 
 
 
 
 
 
 
 
 
 
 
464
 
465
+ ### 2. Install Dependencies
466
+ ```bash
467
+ pip install -e ".[all]"
468
+ ```
469
+
470
+ ### 3. Launch the Playground
471
+ ```bash
472
+ gmp --help # See all options
473
+ gmp ui # Launch the full UI
474
+ ```
475
  """)
476
+
477
+ # Tutorials
478
+ with gr.Tab("πŸ’‘ Tutorials"):
479
+ gr.Markdown("### Available Tutorials [DEMO]")
480
+ gr.Markdown(
481
+ "- Building Your First MCP Server\n"
482
+ "- Connecting Multiple Servers\n"
483
+ "- Creating Custom Agents\n"
484
+ "- Advanced Pipeline Workflows"
485
+ )
486
+
487
+ # API Reference
488
+ with gr.Tab("πŸ”§ API Reference"):
489
+ gr.Markdown("### MCP API Reference [DEMO]")
490
+ gr.Markdown("Full API documentation available in the GitHub repository.")
491
+
492
+ # Troubleshooting
493
+ with gr.Tab("πŸ› οΈ Troubleshooting"):
494
+ gr.Markdown("### Common Issues [DEMO]")
495
+ gr.Markdown(
496
+ "- **Connection Issues**: Check server logs and ports\n"
497
+ "- **Performance**: Optimize server code and connections\n"
498
+ "- **Compatibility**: Ensure MCP protocol version match"
499
+ )
500
 
501
  # Event handlers
502
+
503
+ # Assistant mode switching
504
+ def switch_assistant_mode(mode):
505
+ return (
506
+ gr.update(visible=mode == "General Assistant"),
507
+ gr.update(visible=mode == "MCP Development"),
508
+ gr.update(visible=mode == "Agent Builder")
509
+ )
510
+
511
+ assistant_mode.change(
512
+ switch_assistant_mode,
513
+ inputs=[assistant_mode],
514
+ outputs=[general_assistant_group, mcp_agent_group, agent_builder_group]
515
+ )
516
+
517
+ # Demo chat handlers
518
+ def demo_chat_response(message, history):
519
+ """Simulate chat responses for demo"""
520
+ history = history or []
521
+ history.append({"role": "user", "content": message})
522
+
523
+ # Simple demo responses
524
+ if "screenshot" in message.lower():
525
+ response = "In the full version, I would capture a screenshot using the MCP screenshot tool. This demo doesn't have live MCP connections, but you can get the full functionality on GitHub!"
526
+ elif "file" in message.lower():
527
+ response = "In the full version, I can read, write, and manipulate files using MCP file tools. Check out the GitHub repository for the complete experience!"
528
+ elif "search" in message.lower():
529
+ response = "In the full version, I can search the web using MCP search tools. This demo shows what's possible - get the full version for actual functionality!"
530
+ else:
531
+ response = f"This is a demo response. In the full version, I would process your request: '{message}' using connected MCP tools. Visit our GitHub repository for the complete Gradio MCP Playground!"
532
+
533
+ history.append({"role": "assistant", "content": response})
534
+ return "", history
535
+
536
+ demo_send_btn.click(
537
+ demo_chat_response,
538
+ inputs=[demo_input, demo_chatbot],
539
+ outputs=[demo_input, demo_chatbot]
540
+ )
541
+
542
+ # Server management handlers
543
  refresh_btn.click(
544
  self.refresh_status,
545
  inputs=[session_id],
546
  outputs=[server_status]
547
  )
548
 
 
 
 
 
 
 
549
  template_gallery.change(
550
  self.update_template_view,
551
  inputs=[template_gallery],
 
564
  outputs=[creation_output]
565
  )
566
 
 
 
 
 
 
 
 
 
 
 
 
 
567
  return demo
568
 
569
  def get_custom_css(self) -> str:
570
  """Custom CSS for the interface"""
571
  return """
572
  .gradio-container {
573
+ max-width: 1400px !important;
574
+ }
575
+
576
+ /* Banner styling */
577
+ .banner a:hover {
578
+ transform: scale(1.05);
579
+ }
580
+
581
+ /* Demo labels */
582
+ button:has-text("[DEMO]"),
583
+ .label:has-text("[DEMO]") {
584
+ position: relative;
585
+ }
586
+
587
+ button:has-text("[DEMO]")::after,
588
+ .label:has-text("[DEMO]")::after {
589
+ content: "DEMO";
590
+ position: absolute;
591
+ top: -8px;
592
+ right: -8px;
593
+ background: #ff6b6b;
594
+ color: white;
595
+ padding: 2px 6px;
596
+ border-radius: 4px;
597
+ font-size: 10px;
598
+ font-weight: bold;
599
  }
600
 
601
  /* Dark mode friendly styles */
 
628
  background: #ef4444;
629
  color: white;
630
  }
631
+
632
+ /* Tab styling */
633
+ .tabs {
634
+ margin-top: 20px;
635
+ }
636
+
637
+ /* Demo mode indicators */
638
+ .demo-indicator {
639
+ background: #ff6b6b;
640
+ color: white;
641
+ padding: 4px 8px;
642
+ border-radius: 4px;
643
+ font-size: 12px;
644
+ display: inline-block;
645
+ margin-left: 8px;
646
+ }
647
  """
648
 
649
  def refresh_status(self, session_id: str) -> Dict:
 
825
  error_result = {"error": str(e), "type": type(e).__name__}
826
  log_lines.append(f"Error: {str(e)}")
827
  return error_result, "\n".join(log_lines)
828
+
829
+ def demo_notification(self, action: str) -> str:
830
+ """Return a demo notification message"""
831
+ return f"[DEMO MODE] {action} - This feature requires the full version. Visit {GITHUB_REPO} for complete functionality!"
832
 
833
  # Create and launch the app
834
  app = MCPPlaygroundApp()