Skip to main content
Glama
app.pyβ€’19.9 kB
import streamlit as st import requests import time # Set page config for wide layout and custom favicon st.set_page_config( page_title="Agentic AI Demo", page_icon="πŸš€", layout="wide", initial_sidebar_state="collapsed" ) # Custom CSS for modern, compact design st.markdown(""" <style> /* Import Google Fonts */ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap'); /* Hide Streamlit branding and padding */ #MainMenu {visibility: hidden;} footer {visibility: hidden;} header {visibility: hidden;} .block-container {padding-top: 1rem !important; padding-bottom: 1rem !important;} /* Main container styling */ .stApp { background: #1e3c72; font-family: 'Inter', sans-serif; min-height: 100vh; } /* Floating particles */ .stApp::before { content: ''; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-image: radial-gradient(2px 2px at 20px 30px, rgba(255,255,255,0.3), transparent), radial-gradient(2px 2px at 40px 70px, rgba(255,255,255,0.2), transparent), radial-gradient(1px 1px at 90px 40px, rgba(255,255,255,0.3), transparent), radial-gradient(1px 1px at 130px 80px, rgba(255,255,255,0.2), transparent), radial-gradient(2px 2px at 160px 30px, rgba(255,255,255,0.1), transparent); background-repeat: repeat; background-size: 200px 100px; z-index: -1; animation: floatParticles 20s linear infinite; } @keyframes floatParticles { from { transform: translateY(100vh); } to { transform: translateY(-100px); } } /* Header with stats */ .header-stats { background: rgba(0, 0, 0, 0.2); backdrop-filter: blur(10px); padding: 0.5rem 1rem; margin-bottom: 1rem; border-radius: 0; display: flex; justify-content: space-between; align-items: center; color: white; font-size: 0.9rem; } /* Main content grid */ .main-grid { display: grid; grid-template-columns: 1fr 2fr 1fr; gap: 1rem; max-width: 1400px; margin: 0 auto; padding: 1rem; } /* Left sidebar */ .left-sidebar { display: flex; flex-direction: column; gap: 1rem; } /* Right sidebar */ .right-sidebar { display: flex; flex-direction: column; gap: 1rem; } /* Main content area */ .main-content { background: rgba(255, 255, 255, 0.1); backdrop-filter: blur(20px); border-radius: 20px; padding: 1.5rem; box-shadow: 0 8px 32px rgba(31, 38, 135, 0.37); border: 1px solid rgba(255, 255, 255, 0.18); animation: slideUp 0.8s ease-out; } @keyframes slideUp { from { opacity: 0; transform: translateY(30px); } to { opacity: 1; transform: translateY(0); } } /* Sidebar cards */ .sidebar-card { background: rgba(255, 255, 255, 0.1); backdrop-filter: blur(15px); border-radius: 15px; padding: 1rem; border: 1px solid rgba(255, 255, 255, 0.2); color: white; transition: all 0.3s ease; animation: fadeIn 0.6s ease-out; } .sidebar-card:hover { transform: translateY(-2px); background: rgba(255, 255, 255, 0.15); box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2); } .sidebar-card h4 { margin: 0 0 0.5rem 0; color: #ffd93d; font-size: 1.1rem; font-weight: 600; } .sidebar-card p { margin: 0; font-size: 0.9rem; opacity: 0.9; line-height: 1.4; } /* Stats cards */ .stat-number { font-size: 1.5rem; font-weight: 700; color: #6bcf7f; } /* Title styling */ .main-title { text-align: center; color: white; font-size: 2.5rem; font-weight: 700; margin-bottom: 0.5rem; text-shadow: 0 4px 8px rgba(0, 0, 0, 0.3); animation: glow 2s ease-in-out infinite alternate; } @keyframes glow { from { text-shadow: 0 0 20px rgba(255, 255, 255, 0.5); } to { text-shadow: 0 0 30px rgba(255, 255, 255, 0.8); } } .subtitle { text-align: center; color: rgba(255, 255, 255, 0.9); font-size: 1rem; margin-bottom: 1.5rem; font-weight: 400; } /* Feature cards in main content */ .feature-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; margin-bottom: 1.5rem; } .feature-card { background: rgba(255, 255, 255, 0.1); backdrop-filter: blur(10px); border-radius: 12px; padding: 1rem; border: 1px solid rgba(255, 255, 255, 0.2); transition: all 0.3s ease; text-align: center; } .feature-card:hover { transform: scale(1.02); background: rgba(255, 255, 255, 0.15); } .feature-icon { font-size: 2rem; margin-bottom: 0.5rem; } .feature-title { color: white; font-size: 1rem; font-weight: 600; margin-bottom: 0.3rem; } .feature-description { color: rgba(255, 255, 255, 0.8); font-size: 0.85rem; line-height: 1.4; } /* Radio button styling */ .stRadio > div { background: rgba(255, 255, 255, 0.1); backdrop-filter: blur(10px); border-radius: 10px; padding: 0.75rem; border: 1px solid rgba(255, 255, 255, 0.2); margin-bottom: 1rem; } .stRadio > div > label { color: white !important; font-weight: 600; } /* Text input styling */ .stTextInput > div > div > input { background: rgba(0, 0, 0, 0.3) !important; backdrop-filter: blur(10px) !important; border: 2px solid rgba(255, 255, 255, 0.3) !important; border-radius: 12px !important; color: white !important; padding: 0.75rem !important; font-size: 1rem !important; transition: all 0.3s ease !important; } .stTextInput > div > div > input:focus { border-color: #ffd93d !important; box-shadow: 0 0 15px rgba(255, 217, 61, 0.3) !important; } .stTextInput > div > div > input::placeholder { color: rgba(255, 255, 255, 0.6) !important; } .stTextInput > label { color: white !important; font-weight: 600 !important; margin-bottom: 0.5rem !important; } /* Button styling */ .stButton > button { background: linear-gradient(45deg, #ff6b6b, #ffd93d, #6bcf7f) !important; background-size: 200% 200% !important; color: white !important; border: none !important; border-radius: 15px !important; padding: 0.75rem 2rem !important; font-size: 1.1rem !important; font-weight: 600 !important; box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2) !important; transition: all 0.3s ease !important; text-transform: uppercase !important; letter-spacing: 1px !important; width: 100% !important; animation: gradientButton 3s ease infinite !important; } @keyframes gradientButton { 0% { background-position: 0% 50%; } 50% { background-position: 100% 50%; } 100% { background-position: 0% 50%; } } .stButton > button:hover { transform: translateY(-2px) !important; box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3) !important; } /* Loading animation */ .loading-container { display: flex; justify-content: center; align-items: center; flex-direction: column; padding: 1rem; } .loading-spinner { width: 40px; height: 40px; border: 3px solid rgba(255, 255, 255, 0.3); border-top: 3px solid #ffd93d; border-radius: 50%; animation: spin 1s linear infinite; margin-bottom: 0.5rem; } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } /* Output styling */ .output-container { background: rgba(0, 0, 0, 0.3); backdrop-filter: blur(15px); border-radius: 12px; padding: 1rem; margin-top: 1rem; border: 1px solid rgba(255, 255, 255, 0.2); animation: fadeIn 0.6s ease-out; } @keyframes fadeIn { from { opacity: 0; transform: scale(0.95); } to { opacity: 1; transform: scale(1); } } /* Progress indicator */ .progress-bar { width: 100%; height: 4px; background: rgba(255, 255, 255, 0.2); border-radius: 2px; overflow: hidden; margin: 1rem 0; } .progress-fill { height: 100%; background: linear-gradient(90deg, #ff6b6b, #ffd93d, #6bcf7f); border-radius: 2px; animation: progressMove 2s ease infinite; } @keyframes progressMove { 0% { width: 0%; } 50% { width: 70%; } 100% { width: 100%; } } /* Responsive design */ @media (max-width: 768px) { .main-grid { grid-template-columns: 1fr; gap: 0.5rem; } .feature-grid { grid-template-columns: 1fr; } .main-title { font-size: 2rem; } .header-stats { flex-direction: column; gap: 0.5rem; } } </style> """, unsafe_allow_html=True) # API endpoints CUSTOM_TASK_URL = "http://localhost:8000/task" PUBLIC_ASK_URL = "http://localhost:8001/ask" # --- Fetch real-time stats from backend --- def fetch_stats(): try: resp = requests.get("http://localhost:8000/stats", timeout=5) if resp.status_code == 200: return resp.json() except Exception: pass return { "active_sessions": None, "queries_processed": None, "response_time": None, "success_rate": None, "todays_queries": None, "uptime": None } # (Auto-refresh code removed due to TypeError) # Mode selection (move up so we know which backend is selected) st.markdown("### 🎯 Choose Your AI Backend") mode = st.radio("", ["Custom MCP", "Public MCP"], horizontal=True, key="ai_backend_radio") # Fetch stats for selected backend if mode == "Custom MCP": stats = fetch_stats() else: def fetch_public_stats(): try: resp = requests.get("http://localhost:8001/stats", timeout=5) if resp.status_code == 200: return resp.json() except Exception: pass return { "active_sessions": None, "queries_processed": None, "response_time": None, "success_rate": None, "todays_queries": None, "uptime": None } stats = fetch_public_stats() # Header with stats (real-time) st.markdown(f""" <div class="header-stats"> <div>πŸš€ AI Processing Active</div> <div>⚑ Response Time: {stats['response_time'] if stats['response_time'] is not None else 'N/A'}s</div> <div>πŸ”’ Secure Connection</div> <div>🌟 Uptime: {stats['uptime'] if stats['uptime'] is not None else 'N/A'}%</div> </div> """, unsafe_allow_html=True) # Create main grid layout col1, col2, col3 = st.columns([1, 2, 1]) with col1: # Left sidebar content with real-time stats for selected backend st.markdown(f""" <div class="sidebar-card"> <h4>πŸ“Š Real-time Stats ({mode})</h4> <p>Active Sessions: <span class="stat-number">{stats['active_sessions'] if stats['active_sessions'] is not None else 'N/A'}</span></p> <p>Queries Processed: <span class="stat-number">{stats['queries_processed'] if stats['queries_processed'] is not None else 'N/A'}</span></p> <p>Response Time: <span class="stat-number">{stats['response_time'] if stats['response_time'] is not None else 'N/A'}s</span></p> </div> """, unsafe_allow_html=True) st.markdown(""" <div class="sidebar-card"> <h4>🎯 AI Capabilities</h4> <p>βœ“ Natural Language Processing</p> <p>βœ“ Code Generation</p> <p>βœ“ Data Analysis</p> <p>βœ“ Creative Writing</p> <p>βœ“ Problem Solving</p> </div> """, unsafe_allow_html=True) st.markdown(""" <div class="sidebar-card"> <h4>πŸ”§ System Status</h4> <p>🟒 Custom MCP: Online</p> <p>🟒 Public MCP: Online</p> <p>🟒 Database: Connected</p> <p>🟒 API Gateway: Active</p> </div> """, unsafe_allow_html=True) with col2: # Main content area st.markdown('<div class="main-content">', unsafe_allow_html=True) # Title and subtitle st.markdown('<h1 class="main-title">πŸš€ Agentic AI Demo</h1>', unsafe_allow_html=True) st.markdown('<p class="subtitle">Powered by Gemini β€’ Experience the Future of AI Intelligence</p>', unsafe_allow_html=True) # Feature cards st.markdown(""" <div class="feature-grid"> <div class="feature-card"> <div class="feature-icon">πŸ”§</div> <div class="feature-title">Custom MCP</div> <div class="feature-description">Advanced task processing with specialized tools</div> </div> <div class="feature-card"> <div class="feature-icon">🌐</div> <div class="feature-title">Public MCP</div> <div class="feature-description">General-purpose AI with broad knowledge</div> </div> </div> """, unsafe_allow_html=True) # User input st.markdown("### πŸ’¬ Enter Your Query") user_input = st.text_input("", placeholder="Ask me anything... I'm powered by advanced AI!", label_visibility="collapsed") # Run button if st.button("πŸš€ Process Query"): if not user_input: st.error("⚠️ Please enter a query to continue.") else: # Use a placeholder for the loading animation loading_placeholder = st.empty() loading_placeholder.markdown(""" <div class="loading-container"> <div class="loading-spinner"></div> <div style="color: white; font-size: 0.9rem;">Processing your request...</div> </div> <div class="progress-bar"> <div class="progress-fill"></div> </div> """, unsafe_allow_html=True) time.sleep(0.5) try: if mode == "Custom MCP": with st.spinner("Creating task..."): res = requests.post( CUSTOM_TASK_URL, json={"input": user_input, "tools": ["sample_tool"]}, timeout=30 ) if res.status_code != 201: loading_placeholder.empty() st.error(f"❌ Error creating task: {res.text}") else: task_id = res.json().get("task_id") with st.spinner("Executing task..."): run_res = requests.post(f"{CUSTOM_TASK_URL}/{task_id}/run", timeout=60) loading_placeholder.empty() if run_res.status_code == 200: st.markdown('<div class="output-container">', unsafe_allow_html=True) st.success("βœ… Custom MCP Processing Complete!") output = run_res.json().get("output", "No output received") st.markdown(f""" <div style="color: white; line-height: 1.6; margin-top: 0.5rem;"> {output} </div> """, unsafe_allow_html=True) st.markdown('</div>', unsafe_allow_html=True) else: st.error(f"❌ Error running task: {run_res.text}") else: with st.spinner("Querying Public MCP..."): res = requests.post(PUBLIC_ASK_URL, json={"query": user_input}, timeout=60) loading_placeholder.empty() if res.status_code == 200: st.markdown('<div class="output-container">', unsafe_allow_html=True) st.success("βœ… Public MCP Processing Complete!") response = res.json().get("response", "No response received") st.markdown(f""" <div style="color: white; line-height: 1.6; margin-top: 0.5rem;"> {response} </div> """, unsafe_allow_html=True) st.markdown('</div>', unsafe_allow_html=True) else: st.error(f"❌ Error from Public MCP: {res.text}") except requests.exceptions.Timeout: loading_placeholder.empty() st.error("⏱️ Request timed out. Please try again.") except requests.exceptions.ConnectionError: loading_placeholder.empty() st.error("πŸ”Œ Connection error. Please check if the backend services are running.") except Exception as e: loading_placeholder.empty() st.error(f"πŸ’₯ Unexpected error: {str(e)}") st.markdown('</div>', unsafe_allow_html=True) with col3: # Right sidebar content st.markdown(""" <div class="sidebar-card"> <h4>πŸ† Recent Activity</h4> <p>β€’ Code generation completed</p> <p>β€’ Data analysis in progress</p> <p>β€’ Creative writing finished</p> <p>β€’ API integration successful</p> </div> """, unsafe_allow_html=True) st.markdown(""" <div class="sidebar-card"> <h4>πŸ’‘ Pro Tips</h4> <p>πŸ“ Be specific in your queries</p> <p>🎯 Use clear, concise language</p> <p>πŸ” Try different AI backends</p> <p>⚑ Experiment with complex tasks</p> </div> """, unsafe_allow_html=True) st.markdown(f""" <div class="sidebar-card"> <h4>πŸ“ˆ Usage Analytics ({mode})</h4> <p>Today's Queries: <span class="stat-number">{stats['todays_queries'] if stats['todays_queries'] is not None else 'N/A'}</span></p> <p>Success Rate: <span class="stat-number">{stats['success_rate'] if stats['success_rate'] is not None else 'N/A'}%</span></p> <p>Avg. Response: <span class="stat-number">{stats['response_time'] if stats['response_time'] is not None else 'N/A'}s</span></p> </div> """, unsafe_allow_html=True) st.markdown(""" <div class="sidebar-card"> <h4>🌟 Features</h4> <p>πŸš€ High-speed processing</p> <p>πŸ”’ Enterprise security</p> <p>πŸ“Š Real-time monitoring</p> <p>🎨 Custom workflows</p> </div> """, unsafe_allow_html=True) # Footer st.markdown(""" <div style="text-align: center; color: rgba(255, 255, 255, 0.8); margin-top: 1rem; padding: 1rem; background: rgba(0, 0, 0, 0.2); backdrop-filter: blur(10px);"> <p>Powered by Prodigal AI Pvt. Ltd. β€’ Β© 2025 β€’ Built with ❀️ using Streamlit β€’ Real-time Processing Active</p> </div> """, unsafe_allow_html=True)

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/itsDurvank/Mcp_server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server