File size: 25,723 Bytes
5f6bee4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
af2a027
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5f6bee4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2f623e7
 
5f6bee4
 
 
 
 
 
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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
"""
NASA Space Explorer Assistant - Complete MCP Server + Chat Interface
Gradio Agents & MCP Hackathon 2025

Features:
- 3 MCP servers (APOD, NeoWs, Mars Rover) with 15 total tools
- LlamaIndex chat agent with Mistral LLM
- Interactive testing interface
- Cross-MCP query capabilities
"""

import os
import asyncio
import gradio as gr
from dotenv import load_dotenv
import sys
import logging

# Add src to path
sys.path.append(os.path.join(os.path.dirname(__file__), 'src'))

from src.mcp_server import NASAMCPServer
from src.chat_agent import NASAChatAgent
from src.config import Config

# Load environment variables
load_dotenv()

# Global instances
mcp_server = None
chat_agent = None

# Setup logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

async def init_servers():
    """Initialize both MCP server and chat agent."""
    global mcp_server, chat_agent
    
    try:
        # Initialize MCP server
        print("πŸš€ Initializing MCP Server...")
        mcp_server = NASAMCPServer()
        await mcp_server.initialize()
        print("βœ… MCP Server initialized with 3 MCPs")
        
        # Initialize chat agent (if Mistral API key available)
        if Config.MISTRAL_API_KEY:
            print("πŸ€– Initializing Chat Agent...")
            # Pass the MCP server instance directly
            chat_agent = NASAChatAgent(mcp_server=mcp_server)
            success = await chat_agent.initialize()
            if success:
                print("βœ… Chat Agent initialized with LlamaIndex + Mistral")
            else:
                print("⚠️ Chat Agent failed to initialize")
                chat_agent = None
        else:
            print("⚠️ MISTRAL_API_KEY not set - chat features disabled")
            chat_agent = None
        
        return mcp_server, chat_agent
    
    except Exception as e:
        print(f"❌ Initialization error: {str(e)}")
        return None, None

def create_app():
    """Create and configure the complete Gradio application."""
    
    with gr.Blocks(
        title="NASA Space Explorer Assistant",
        theme=gr.themes.Soft(),
        css="""
        .chat-container { 
            max-height: 600px; 
            overflow-y: auto; 
        }
        .space-themed { 
            background: linear-gradient(135deg, #0c0c0c 0%, #1a1a2e 50%, #16213e 100%); 
        }
        .example-btn {
            margin: 2px;
        }
        """
    ) as app:
        
        gr.HTML("""
        <div style="text-align: center; padding: 20px; background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%); border-radius: 10px; margin-bottom: 20px;">
            <h1 style="color: white; margin: 0;">πŸš€ NASA Space Explorer Assistant</h1>
            <p style="color: #cccccc; margin: 10px 0 0 0;">MCP-powered space data access + AI Chat Assistant</p>
        </div>
        """)
        
        # Status indicator
        with gr.Row():
            with gr.Column(scale=1):
                gr.Markdown("### πŸ“‘ System Status")
                api_status = "🟒 NASA API" if Config.NASA_API_KEY != "DEMO_KEY" else "🟑 NASA Demo Key"
                chat_status = "🟒 Chat Ready" if Config.MISTRAL_API_KEY else "πŸ”΄ Chat Disabled"
                gr.Markdown(f"**{api_status}** | **{chat_status}**")
            
            with gr.Column(scale=2):
                gr.Markdown("### πŸ› οΈ Available Services")
                gr.Markdown("🌌 **APOD** (3 tools) | 🌍 **NeoWs** (6 tools) | πŸ”΄ **Mars Rover** (6 tools) | **Total: 15 MCP tools**")
        
        with gr.Tabs():
            # =================================
            # TAB 1: CHAT INTERFACE (NEW!)
            # =================================
            with gr.Tab("πŸ€– Chat with NASA Assistant") as chat_tab:
                if Config.MISTRAL_API_KEY:
                    gr.Markdown("""
                    ### 🌟 Your Personal NASA Space Expert
                    
                    I can access **live NASA data** to answer your questions about space! Try asking me about:
                    """)
                    
                    with gr.Row():
                        with gr.Column():
                            gr.Markdown("""
                            **🌌 Astronomy**
                            - Today's space picture
                            - Historical astronomy images
                            - Space phenomena explanations
                            """)
                        with gr.Column():
                            gr.Markdown("""
                            **🌍 Asteroids & NEOs**
                            - Dangerous space rocks
                            - Asteroid size comparisons
                            - Threat analysis
                            """)
                        with gr.Column():
                            gr.Markdown("""
                            **πŸ”΄ Mars Exploration**
                            - Rover photos and missions
                            - Mars surface discoveries
                            - Mission statistics
                            """)
                    
                    # Main chat interface
                    chatbot = gr.Chatbot(
                        value=[],
                        elem_classes=["chat-container"],
                        height=500,
                        show_label=False,
                        type="messages"  # Fix the warning
                    )
                    
                    with gr.Row():
                        msg = gr.Textbox(
                            placeholder="Ask me anything about space... πŸš€",
                            show_label=False,
                            scale=4,
                            container=False
                        )
                        send_btn = gr.Button("Send πŸš€", variant="primary", scale=1)
                        clear_btn = gr.Button("Clear πŸ—‘οΈ", variant="secondary", scale=1)
                    
                    # Quick example buttons
                    gr.Markdown("### 🎯 Quick Examples")
                    with gr.Row():
                        example_btn1 = gr.Button("🌌 What's today's astronomy picture?", elem_classes=["example-btn"])
                        example_btn2 = gr.Button("🌍 Any dangerous asteroids this week?", elem_classes=["example-btn"])
                    
                    with gr.Row():
                        example_btn3 = gr.Button("πŸ”΄ Show me latest Mars rover photos", elem_classes=["example-btn"])
                        example_btn4 = gr.Button("🌟 Give me today's space summary", elem_classes=["example-btn"])
                    
                    with gr.Row():
                        example_btn5 = gr.Button("πŸ“… What space events happened on January 1, 2024?", elem_classes=["example-btn"])
                        example_btn6 = gr.Button("πŸ“ Compare sizes of this week's largest asteroids", elem_classes=["example-btn"])
                    
                    # Chat functions
                    async def respond(message, history):
                        """Handle chat response."""
                        if not message.strip():
                            return history, ""
                        
                        if not chat_agent:
                            error_msg = "❌ Chat agent not available. Please check Mistral API key configuration."
                            # For messages format: list of dicts with 'role' and 'content'
                            return history + [
                                {"role": "user", "content": message},
                                {"role": "assistant", "content": error_msg}
                            ], ""
                        
                        # Add user message to history
                        history = history + [{"role": "user", "content": message}]
                        
                        # Get AI response
                        try:
                            print(f"πŸ€– Processing: {message}")
                            response = await chat_agent.chat(message)
                            # Add assistant response
                            history.append({"role": "assistant", "content": response})
                            print(f"βœ… Response generated ({len(response)} chars)")
                        except Exception as e:
                            error_response = f"❌ Sorry, I encountered an error: {str(e)}"
                            history.append({"role": "assistant", "content": error_response})
                            print(f"❌ Chat error: {str(e)}")
                        
                        return history, ""
                    
                    def clear_chat():
                        """Clear chat history."""
                        return [], ""
                    
                    def set_example_text(text):
                        """Set example text in input."""
                        return text
                    
                    # Event handlers
                    msg.submit(
                        respond,
                        inputs=[msg, chatbot],
                        outputs=[chatbot, msg]
                    )

                    send_btn.click(
                        respond,
                        inputs=[msg, chatbot],
                        outputs=[chatbot, msg]
                    )
                    
                    clear_btn.click(clear_chat, outputs=[chatbot, msg])
                    
                    # Example button handlers
                    example_btn1.click(
                        lambda: "What's today's astronomy picture?",
                        outputs=[msg]
                    )
                    example_btn2.click(
                        lambda: "Are there any potentially dangerous asteroids approaching Earth this week?",
                        outputs=[msg]
                    )
                    example_btn3.click(
                        lambda: "Show me the latest photos from Curiosity rover on Mars",
                        outputs=[msg]
                    )
                    example_btn4.click(
                        lambda: "Give me a comprehensive space summary for today",
                        outputs=[msg]
                    )
                    example_btn5.click(
                        lambda: "What space events happened on January 1st, 2024? Show me the astronomy picture, any asteroids, and Mars rover activity for that date.",
                        outputs=[msg]
                    )
                    example_btn6.click(
                        lambda: "What are the largest asteroids approaching Earth this week? Compare their sizes to familiar objects.",
                        outputs=[msg]
                    )
                
                else:
                    # Chat disabled - show setup instructions
                    gr.Markdown("""
                    ### πŸ” Chat Feature Disabled
                    
                    To enable the AI chat assistant, you need to add your Mistral API key:
                    
                    1. **Get API Key**: Visit [console.mistral.ai](https://console.mistral.ai/api-keys)
                    2. **Add to .env file**:
                       ```
                       MISTRAL_API_KEY=your_api_key_here
                       ```
                    3. **Restart the application**
                    
                    The chat assistant will then be able to:
                    - Answer questions about space in natural language
                    - Access all 15 NASA MCP tools automatically
                    - Provide cross-correlations and insights
                    - Generate comprehensive space summaries
                    """)
                    
                    gr.HTML("""
                    <div style="text-align: center; padding: 20px; background: #000000; border-radius: 10px; margin-top: 20px;">
                        <h3>🌟 Preview: What the chat can do</h3>
                        <p><strong>User:</strong> "What's today's astronomy picture?"</p>
                        <p><strong>Assistant:</strong> "Today's Astronomy Picture of the Day is..." <em>[Uses APOD MCP]</em></p>
                        <br>
                        <p><strong>User:</strong> "Are there dangerous asteroids this week?"</p>
                        <p><strong>Assistant:</strong> "Let me check current asteroid data..." <em>[Uses NeoWs MCP]</em></p>
                        <br>
                        <p><strong>User:</strong> "What space events happened on my birthday?"</p>
                        <p><strong>Assistant:</strong> "I'll check astronomy pictures, asteroids, and Mars activity for that date..." <em>[Uses all 3 MCPs]</em></p>
                    </div>
                    """)
            
            # =================================
            # TAB 2: MCP SERVER MANAGEMENT
            # =================================
            with gr.Tab("πŸ› οΈ MCP Server Dashboard") as mcp_tab:
                gr.Markdown("### πŸ”§ MCP Server Status & Management")
                
                with gr.Row():
                    with gr.Column():
                        gr.Markdown("#### πŸ“Š Server Status")
                        status_button = gr.Button("πŸ”„ Check Server Status", variant="secondary")
                        status_output = gr.JSON(label="Detailed Status")
                        
                        async def check_status():
                            if mcp_server:
                                return await mcp_server.get_server_status()
                            else:
                                return {"error": "MCP server not initialized"}
                        
                        status_button.click(
                            lambda: asyncio.run(check_status()),
                            outputs=[status_output]
                        )
                    
#                    with gr.Column():
#                        gr.Markdown("#### πŸ”— Connection Information")
#                        gr.Markdown("""
#                        **For External MCP Clients:**
#                        
#                        - **Protocol**: MCP 2024-11-05
#                        - **Endpoint**: `http://localhost:8000/sse`
#                        - **Tools**: 15 available across 3 MCPs
#                        - **Capabilities**: tools, cross-mcp queries
#                        
#                        **Tool Prefixes:**
#                        - `apod_*` - Astronomy Picture tools (3)
#                        - `neows_*` - Asteroid tools (6)
#                        - `marsrover_*` - Mars Rover tools (6)
#                        """)
                
                # Tool testing interface
                gr.Markdown("### πŸ§ͺ Interactive Tool Testing")
                
                with gr.Row():
                    with gr.Column():
                        tool_dropdown = gr.Dropdown(
                            choices=[
                                "apod_get_apod_today",
                                "apod_get_apod_by_date",
                                "neows_get_asteroids_today",
                                "neows_get_potentially_hazardous",
                                "marsrover_get_latest_photos",
                                "marsrover_get_rover_status"
                            ],
                            label="Select Tool to Test",
                            value="apod_get_apod_today"
                        )
                        
                        args_input = gr.JSON(
                            label="Tool Arguments (JSON)",
                            value={}
                        )
                        
                        test_button = gr.Button("πŸ§ͺ Execute Tool", variant="primary")
                    
                    with gr.Column():
                        test_output = gr.JSON(label="Tool Response", height=400)
                
                async def test_tool(tool_name, arguments):
                    if mcp_server:
                        return await mcp_server.call_tool(tool_name, arguments)
                    else:
                        return {"error": "MCP server not initialized"}
                
                test_button.click(
                    lambda tool, args: asyncio.run(test_tool(tool, args)),
                    inputs=[tool_dropdown, args_input],
                    outputs=[test_output]
                )
                
                # Quick test buttons
                with gr.Row():
                    quick_test1 = gr.Button("🌌 Test APOD Today", size="sm")
                    quick_test2 = gr.Button("🌍 Test Asteroids", size="sm")
                    quick_test3 = gr.Button("πŸ”΄ Test Mars Status", size="sm")
                
                quick_test1.click(
                    lambda: ("apod_get_apod_today", {}),
                    outputs=[tool_dropdown, args_input]
                )
                quick_test2.click(
                    lambda: ("neows_get_asteroids_today", {}),
                    outputs=[tool_dropdown, args_input]
                )
                quick_test3.click(
                    lambda: ("marsrover_get_rover_status", {"rover": "curiosity"}),
                    outputs=[tool_dropdown, args_input]
                )
            
            # =================================
            # TAB 3: CROSS-MCP QUERIES
            # =================================
            with gr.Tab("🌟 Cross-MCP Queries") as cross_tab:
                gr.Markdown("### πŸš€ Advanced Cross-MCP Capabilities")
                gr.Markdown("These queries combine data from multiple NASA APIs for unique insights:")
                
                with gr.Row():
                    with gr.Column():
                        cross_query_type = gr.Dropdown(
                            choices=["space_summary", "correlate_date"],
                            label="Cross-MCP Query Type",
                            value="space_summary"
                        )
                        
                        cross_args = gr.JSON(
                            label="Query Arguments",
                            value={"date": "2024-01-01"}
                        )
                        
                        cross_button = gr.Button("πŸš€ Execute Cross-MCP Query", variant="primary")
                        
                        # Preset buttons
                        gr.Markdown("#### 🎯 Preset Queries")
                        preset_summary = gr.Button("πŸ“Š Today's Space Summary", variant="secondary")
                        preset_correlate = gr.Button("πŸ” Correlate Jan 1, 2024", variant="secondary")
                    
                    with gr.Column():
                        cross_output = gr.JSON(label="Cross-MCP Response", height=500)
                
                async def test_cross_query(query_type, arguments):
                    if mcp_server:
                        return await mcp_server.handle_cross_mcp_query(query_type, arguments)
                    else:
                        return {"error": "MCP server not initialized"}
                
                cross_button.click(
                    lambda query, args: asyncio.run(test_cross_query(query, args)),
                    inputs=[cross_query_type, cross_args],
                    outputs=[cross_output]
                )
                
                preset_summary.click(
                    lambda: ("space_summary", {"date": "2025-06-07"}),
                    outputs=[cross_query_type, cross_args]
                )
                preset_correlate.click(
                    lambda: ("correlate_date", {"date": "2024-01-01"}),
                    outputs=[cross_query_type, cross_args]
                )
            
            # =================================
            # TAB 4: DOCUMENTATION & EXAMPLES
            # =================================
            with gr.Tab("πŸ“š Documentation") as docs_tab:
                gr.Markdown("""
                ### πŸ“– NASA Space Explorer Documentation
                
                #### πŸ—οΈ Architecture
                ```
                User Interface (Gradio)
                    ↓
                Chat Agent (LlamaIndex + Mistral)
                    ↓
                MCP Server (NASA Space Explorer)
                    β”œβ”€β”€ APOD MCP ──→ NASA APOD API
                    β”œβ”€β”€ NeoWs MCP ──→ NASA Asteroids API
                    └── Mars Rover MCP ──→ NASA Mars Rover API
                ```
                
                #### πŸ› οΈ Available MCP Tools
                
                **APOD MCP (3 tools):**
                - `apod_get_apod_today` - Get today's astronomy picture
                - `apod_get_apod_by_date` - Get picture for specific date
                - `apod_get_apod_date_range` - Get pictures for date range
                
                **NeoWs MCP (6 tools):**
                - `neows_get_asteroids_today` - Today's approaching asteroids
                - `neows_get_asteroids_week` - This week's asteroids
                - `neows_get_asteroids_date_range` - Asteroids for date range
                - `neows_get_potentially_hazardous` - Only dangerous asteroids
                - `neows_get_largest_asteroids_week` - Largest asteroids this week
                - `neows_analyze_asteroid_danger` - Detailed threat analysis
                
                **Mars Rover MCP (6 tools):**
                - `marsrover_get_rover_status` - Rover mission status
                - `marsrover_get_latest_photos` - Most recent photos
                - `marsrover_get_photos_by_earth_date` - Photos by Earth date
                - `marsrover_get_photos_by_sol` - Photos by Martian day
                - `marsrover_get_photos_by_camera` - Photos by specific camera
                - `marsrover_compare_rovers` - Compare all rovers
                
                #### 🌟 Cross-MCP Features
                - **Space Summary**: Combine APOD + asteroids + Mars data for any date
                - **Date Correlation**: Find all space events for a specific date
                - **Intelligent Analysis**: AI-powered insights across multiple data sources
                
                #### πŸ’‘ Example Conversations
                
                **Simple Queries:**
                - "What's today's astronomy picture?"
                - "Are there dangerous asteroids this week?"
                - "Show me latest Curiosity photos"
                
                **Cross-MCP Queries:**
                - "What space events happened on my birthday?"
                - "Compare asteroid sizes to Mars rover scale"
                - "Give me a complete space summary for July 4th, 2023"
                
                **Advanced Analysis:**
                - "Analyze the threat level of asteroid 2023 BU"
                - "How has Curiosity's mission progressed over the years?"
                - "Correlate astronomy pictures with asteroid activity"
                
                #### βš™οΈ Technical Details
                
                **MCP Protocol:** 2024-11-05  
                **Chat LLM:** Mistral Large (via API)  
                **Framework:** LlamaIndex + Gradio  
                **NASA APIs:** APOD, NeoWs, Mars Rover Photos  
                **Rate Limiting:** 950 requests/hour (NASA limit buffer)  
                **Error Handling:** Comprehensive retry logic and validation  
                """)
        
        # Footer
        gr.HTML("""
        <div style="text-align: center; padding: 20px; margin-top: 30px; border-top: 1px solid #ddd;">
            <p style="color: #666;">
                πŸ† <strong>Built for Gradio Agents & MCP Hackathon 2025</strong> πŸš€<br>
                NASA Space Explorer Assistant - Making space data accessible to everyone
            </p>
        </div>
        """)
    
    return app

async def main():
    """Main application entry point."""
    print("🌌 NASA Space Explorer Assistant")
    print("=" * 50)
    
    # Configuration validation
    print("πŸ“‹ Validating configuration...")
    config_valid = Config.validate()
    
    if Config.NASA_API_KEY == "DEMO_KEY":
        print("ℹ️  Using NASA DEMO_KEY (30 requests/hour limit)")
    else:
        print("βœ… NASA API key configured")
    
    if Config.MISTRAL_API_KEY:
        print("βœ… Mistral API key configured - chat enabled")
    else:
        print("⚠️  Mistral API key missing - chat disabled")
    
    # Initialize all servers
    print("\nπŸš€ Initializing services...")
    await init_servers()
    
    # Create and launch application
    print("\n🌐 Creating Gradio interface...")
    app = create_app()
    
    print("πŸŽ‰ Launch complete!")
    print("=" * 50)
    print("πŸ“‘ MCP Server: http://localhost:8000")
    print("πŸ€– Chat Interface: Available if Mistral API key configured")
    print("πŸ› οΈ  Dashboard: Interactive MCP testing available")
    print("🌟 Cross-MCP: Advanced query capabilities")
    print("=" * 50)
    
    # Launch the application
    app.launch(
        server_name="0.0.0.0",
        server_port=7860,
        #share=True,  # Enable sharing for Hugging Face Spaces
        show_error=True,
        quiet=False
    )

if __name__ == "__main__":
    asyncio.run(main())