'''import gradio as gr import requests import json import plotly.graph_objects as go import plotly.express as px from fastapi import FastAPI from typing import Dict, Any, Optional import os from datetime import datetime # Custom CSS for MoneyMate branding CUSTOM_CSS = """ .gradio-container { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); font-family: 'Inter', sans-serif; } .main-header { text-align: center; color: white; margin-bottom: 2rem; } .money-card { background: rgba(255, 255, 255, 0.95); border-radius: 15px; padding: 1.5rem; margin: 1rem 0; box-shadow: 0 8px 32px rgba(31, 38, 135, 0.37); backdrop-filter: blur(4px); border: 1px solid rgba(255, 255, 255, 0.18); } .modal-branding { background: linear-gradient(45deg, #ff6b6b, #4ecdc4); -webkit-background-clip: text; -webkit-text-fill-color: transparent; font-weight: bold; text-align: center; margin-top: 1rem; } .advice-box { background: #f8f9ff; border-left: 4px solid #667eea; padding: 1rem; margin: 1rem 0; border-radius: 8px; } .quick-action-btn { background: linear-gradient(45deg, #667eea, #764ba2); color: white; border: none; border-radius: 25px; padding: 0.5rem 1rem; margin: 0.25rem; cursor: pointer; transition: all 0.3s ease; } .quick-action-btn:hover { transform: translateY(-2px); box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4); } """ # MCP Server configuration class MCPServer: def __init__(self): self.tools = { "salary_breakdown": self.salary_breakdown, "investment_advice": self.investment_advice, "expense_analysis": self.expense_analysis, "savings_goal": self.savings_goal } def salary_breakdown(self, salary: float, expenses: Dict[str, float]) -> Dict[str, Any]: """Break down salary using 50/30/20 rule with Indian context""" needs = salary * 0.5 # 50% for needs wants = salary * 0.3 # 30% for wants savings = salary * 0.2 # 20% for savings/investments return { "breakdown": { "needs": needs, "wants": wants, "savings": savings }, "recommendations": self._get_indian_recommendations(salary) } def investment_advice(self, age: int, salary: float, risk_appetite: str) -> Dict[str, Any]: """Provide investment advice for Indian market""" equity_percentage = min(100 - age, 80) # Age-based equity allocation debt_percentage = 100 - equity_percentage return { "allocation": { "equity": equity_percentage, "debt": debt_percentage }, "instruments": self._get_indian_instruments(risk_appetite) } def expense_analysis(self, expenses: Dict[str, float]) -> Dict[str, Any]: """Analyze expenses and provide optimization suggestions""" total_expenses = sum(expenses.values()) analysis = {} for category, amount in expenses.items(): percentage = (amount / total_expenses) * 100 analysis[category] = { "amount": amount, "percentage": percentage, "status": self._categorize_expense(category, percentage) } return {"analysis": analysis, "suggestions": self._get_optimization_tips()} def savings_goal(self, goal_amount: float, timeline_months: int, current_savings: float) -> Dict[str, Any]: """Calculate monthly savings needed for a goal""" remaining_amount = goal_amount - current_savings monthly_required = remaining_amount / timeline_months if timeline_months > 0 else 0 return { "monthly_required": monthly_required, "total_goal": goal_amount, "timeline": timeline_months, "feasibility": "achievable" if monthly_required < 15000 else "challenging" } def _get_indian_recommendations(self, salary: float) -> list: """Get India-specific financial recommendations""" recommendations = [ "Build emergency fund of 6-12 months expenses", "Start SIP in diversified equity mutual funds", "Consider ELSS funds for tax saving under 80C", "Open PPF account for long-term tax-free returns" ] if salary > 50000: recommendations.append("Consider NPS for additional retirement planning") if salary > 100000: recommendations.append("Explore direct equity investment after gaining knowledge") return recommendations def _get_indian_instruments(self, risk_appetite: str) -> list: """Get Indian investment instruments based on risk appetite""" instruments = { "conservative": ["PPF", "NSC", "FD", "Debt Mutual Funds"], "moderate": ["Balanced Mutual Funds", "ELSS", "Gold ETF", "Corporate Bonds"], "aggressive": ["Large Cap Funds", "Mid Cap Funds", "Small Cap Funds", "Direct Equity"] } return instruments.get(risk_appetite.lower(), instruments["moderate"]) def _categorize_expense(self, category: str, percentage: float) -> str: """Categorize expense as optimal, high, or low""" thresholds = { "rent": (25, 35), "food": (15, 25), "transport": (10, 15), "utilities": (5, 10), "entertainment": (5, 15) } if category.lower() in thresholds: low, high = thresholds[category.lower()] if percentage < low: return "low" elif percentage > high: return "high" return "optimal" def _get_optimization_tips(self) -> list: """Get expense optimization tips""" return [ "Use public transport or carpool to reduce transport costs", "Cook at home more often to save on food expenses", "Use energy-efficient appliances to reduce utility bills", "Set a monthly entertainment budget and stick to it", "Review and cancel unused subscriptions" ] # Initialize MCP Server mcp_server = MCPServer() # Modal backend URL (replace with your actual Modal deployment URL) MODAL_BACKEND_URL = os.getenv("MODAL_BACKEND_URL", "https://kaustubhme0--moneymate-backend-fastapi-app.modal.run") def call_modal_backend(user_input: str, context: Dict[str, Any] = None) -> str: """Call Modal backend for AI-powered financial advice""" try: payload = { "user_input": user_input, "context": context or {} } response = requests.post( f"{MODAL_BACKEND_URL}/financial_advice", json=payload, timeout=30 ) if response.status_code == 200: return response.json().get("advice", "Unable to get advice at the moment.") else: return "Sorry, I'm having trouble connecting to the financial advisor. Please try again." except requests.exceptions.RequestException as e: return f"Connection error: {str(e)}. Please check your internet connection." def create_salary_breakdown_chart(salary: float, needs: float, wants: float, savings: float): """Create a pie chart for salary breakdown""" labels = ['Needs (50%)', 'Wants (30%)', 'Savings (20%)'] values = [needs, wants, savings] colors = ['#ff6b6b', '#4ecdc4', '#45b7d1'] fig = go.Figure(data=[go.Pie( labels=labels, values=values, hole=0.4, marker_colors=colors, textinfo='label+percent', textfont_size=12 )]) fig.update_layout( title=f"Salary Breakdown for ₹{salary:,.0f}", font=dict(size=14), showlegend=True, height=400 ) return fig def create_expense_analysis_chart(expenses: Dict[str, float]): """Create a bar chart for expense analysis""" categories = list(expenses.keys()) amounts = list(expenses.values()) fig = go.Figure([go.Bar( x=categories, y=amounts, marker_color='#667eea', text=[f"₹{amount:,.0f}" for amount in amounts], textposition='auto' )]) fig.update_layout( title="Monthly Expense Breakdown", xaxis_title="Categories", yaxis_title="Amount (₹)", font=dict(size=12), height=400 ) return fig def process_financial_query( salary: float, rent: float, food: float, transport: float, utilities: float, entertainment: float, other: float, savings_goal: str, user_question: str ) -> tuple: """Process user's financial query and return advice with visualizations""" # Calculate totals total_expenses = rent + food + transport + utilities + entertainment + other remaining_salary = salary - total_expenses # Create expense dictionary expenses = { "Rent": rent, "Food": food, "Transport": transport, "Utilities": utilities, "Entertainment": entertainment, "Other": other } # Get salary breakdown using 50/30/20 rule breakdown = mcp_server.salary_breakdown(salary, expenses) needs = breakdown["breakdown"]["needs"] wants = breakdown["breakdown"]["wants"] savings = breakdown["breakdown"]["savings"] # Create charts salary_chart = create_salary_breakdown_chart(salary, needs, wants, savings) expense_chart = create_expense_analysis_chart(expenses) # Prepare context for Modal backend context = { "salary": salary, "expenses": expenses, "total_expenses": total_expenses, "remaining_salary": remaining_salary, "savings_goal": savings_goal, "breakdown": breakdown } # Get AI advice if user_question.strip(): advice = call_modal_backend(user_question, context) else: advice = call_modal_backend(f"Analyze my finances: Salary ₹{salary}, Total expenses ₹{total_expenses}", context) # Create summary summary = f""" ## 💰 Financial Summary **Monthly Salary:** ₹{salary:,.0f} **Total Expenses:** ₹{total_expenses:,.0f} **Remaining Amount:** ₹{remaining_salary:,.0f} ### 📊 Recommended Allocation (50/30/20 Rule) - **Needs (50%):** ₹{needs:,.0f} - **Wants (30%):** ₹{wants:,.0f} - **Savings (20%):** ₹{savings:,.0f} ### 🎯 Status {'✅ Good job! You have money left over.' if remaining_salary > 0 else '⚠️ You are overspending. Consider reducing expenses.'} """ return salary_chart, expense_chart, summary, advice def handle_quick_question(question: str, salary: float = 50000) -> str: """Handle pre-defined quick questions""" context = {"salary": salary} return call_modal_backend(question, context) # Create Gradio interface def create_moneymate_app(): with gr.Blocks(css=CUSTOM_CSS, title="MoneyMate - Your Financial Assistant") as app: # Header gr.HTML("""

💰 MoneyMate

Your Personal Financial Assistant for Smart Money Management

""") with gr.Row(): with gr.Column(scale=1): gr.HTML('
') gr.Markdown("### 💼 Your Financial Details") salary_input = gr.Number( label="Monthly Salary (₹)", value=50000, minimum=0, step=1000 ) gr.Markdown("#### Monthly Expenses") rent_input = gr.Number(label="Rent (₹)", value=15000, minimum=0) food_input = gr.Number(label="Food (₹)", value=8000, minimum=0) transport_input = gr.Number(label="Transport (₹)", value=3000, minimum=0) utilities_input = gr.Number(label="Utilities (₹)", value=2000, minimum=0) entertainment_input = gr.Number(label="Entertainment (₹)", value=4000, minimum=0) other_input = gr.Number(label="Other Expenses (₹)", value=3000, minimum=0) savings_goal_input = gr.Textbox( label="Savings Goal", placeholder="e.g., Emergency fund, Vacation, House down payment", value="Emergency fund" ) user_question_input = gr.Textbox( label="Ask MoneyMate", placeholder="e.g., How should I invest my savings? What's the best way to save for a house?", lines=3 ) analyze_btn = gr.Button("Analyze My Finances 📊", variant="primary", size="large") gr.HTML('
') # Quick action buttons gr.HTML('
') gr.Markdown("### 🚀 Quick Questions") with gr.Row(): quick_btn1 = gr.Button("💡 Investment Tips", size="small") quick_btn2 = gr.Button("🏠 Save for House", size="small") with gr.Row(): quick_btn3 = gr.Button("✈️ Plan Vacation", size="small") quick_btn4 = gr.Button("🚗 Buy a Car", size="small") gr.HTML('
') with gr.Column(scale=2): gr.HTML('
') # Output components with gr.Tab("📊 Salary Breakdown"): salary_chart_output = gr.Plot() with gr.Tab("💸 Expense Analysis"): expense_chart_output = gr.Plot() with gr.Tab("📋 Summary"): summary_output = gr.Markdown() with gr.Tab("🤖 AI Advice"): advice_output = gr.Markdown(value="Click 'Analyze My Finances' to get personalized advice!") gr.HTML('
') # Event handlers analyze_btn.click( fn=process_financial_query, inputs=[ salary_input, rent_input, food_input, transport_input, utilities_input, entertainment_input, other_input, savings_goal_input, user_question_input ], outputs=[salary_chart_output, expense_chart_output, summary_output, advice_output] ) # Quick question handlers quick_btn1.click( fn=lambda s: handle_quick_question("What are the best investment options for a beginner in India?", s), inputs=[salary_input], outputs=[advice_output] ) quick_btn2.click( fn=lambda s: handle_quick_question("How should I save for buying a house in India?", s), inputs=[salary_input], outputs=[advice_output] ) quick_btn3.click( fn=lambda s: handle_quick_question("What's the best way to save for a vacation?", s), inputs=[salary_input], outputs=[advice_output] ) quick_btn4.click( fn=lambda s: handle_quick_question("How should I plan to buy a car with my salary?", s), inputs=[salary_input], outputs=[advice_output] ) # Footer gr.HTML("""

Made with ❤️ for Agents & MCP Hackathon 2025

🏆 Track 1 — MCP Tool / Server

""") return app # FastAPI wrapper for MCP compatibility app_fastapi = FastAPI() # Create and mount Gradio app gradio_app = create_moneymate_app() # MCP endpoints @app_fastapi.post("/mcp/tools") async def list_tools(): """List available MCP tools""" return { "tools": [ { "name": "salary_breakdown", "description": "Break down salary using 50/30/20 rule", "inputSchema": { "type": "object", "properties": { "salary": {"type": "number"}, "expenses": {"type": "object"} } } }, { "name": "investment_advice", "description": "Get investment advice for Indian market", "inputSchema": { "type": "object", "properties": { "age": {"type": "integer"}, "salary": {"type": "number"}, "risk_appetite": {"type": "string"} } } } ] } @app_fastapi.post("/mcp/call_tool") async def call_tool(request: dict): """Call MCP tool""" tool_name = request.get("name") arguments = request.get("arguments", {}) if tool_name in mcp_server.tools: result = mcp_server.tools[tool_name](**arguments) return {"content": [{"type": "text", "text": json.dumps(result, indent=2)}]} else: return {"error": f"Tool {tool_name} not found"} # Mount Gradio app gr.mount_gradio_app(app_fastapi, gradio_app, path="/") if __name__ == "__main__": gradio_app.launch( server_name="0.0.0.0", server_port=7860, share=True )''' import gradio as gr import requests import json import plotly.graph_objects as go import plotly.express as px from fastapi import FastAPI from typing import Dict, Any, Optional import os from datetime import datetime from utils import ( validate_salary, validate_expenses, calculate_50_30_20_breakdown, calculate_emergency_fund_target, calculate_sip_returns, get_tax_saving_instruments, get_investment_allocation_by_age, calculate_goal_based_savings, get_expense_optimization_tips, format_currency, get_financial_milestones_by_age, calculate_retirement_corpus ) # Custom CSS for MoneyMate branding CUSTOM_CSS = """ .gradio-container { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); font-family: 'Inter', sans-serif; } .main-header { text-align: center; color: white; margin-bottom: 2rem; } .money-card { background: rgba(255, 255, 255, 0.95); border-radius: 15px; padding: 1.5rem; margin: 1rem 0; box-shadow: 0 8px 32px rgba(31, 38, 135, 0.37); backdrop-filter: blur(4px); border: 1px solid rgba(255, 255, 255, 0.18); } .modal-branding { background: linear-gradient(45deg, #ff6b6b, #4ecdc4); -webkit-background-clip: text; -webkit-text-fill-color: transparent; font-weight: bold; text-align: center; margin-top: 1rem; } .advice-box { background: #f8f9ff; border-left: 4px solid #667eea; padding: 1rem; margin: 1rem 0; border-radius: 8px; } .quick-action-btn { background: linear-gradient(45deg, #667eea, #764ba2); color: white; border: none; border-radius: 25px; padding: 0.5rem 1rem; margin: 0.25rem; cursor: pointer; transition: all 0.3s ease; } .quick-action-btn:hover { transform: translateY(-2px); box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4); } """ # Modal backend URL MODAL_BACKEND_URL = os.getenv("MODAL_BACKEND_URL", "https://kaustubhme0--moneymate-backend-fastapi-app.modal.run") def call_modal_financial_advice(user_input: str, context: Dict[str, Any] = None) -> str: """Call Modal backend for AI-powered financial advice""" try: payload = { "user_input": user_input, "context": context or {} } response = requests.post( f"{MODAL_BACKEND_URL}/financial_advice", json=payload, timeout=60 ) if response.status_code == 200: return response.json().get("advice", "Unable to get advice at the moment.") else: return "Sorry, I'm having trouble connecting to the financial advisor. Please try again." except requests.exceptions.RequestException as e: return f"Connection error: {str(e)}. Please check your internet connection." def call_modal_analyze_expenses(expenses: Dict[str, float], salary: float) -> Dict[str, Any]: """Call Modal backend for expense analysis""" try: payload = { "expenses": expenses, "salary": salary } response = requests.post( f"{MODAL_BACKEND_URL}/analyze_expenses", json=payload, timeout=30 ) if response.status_code == 200: return response.json().get("analysis", {}) else: # Fallback to local utils function return {} except requests.exceptions.RequestException: # Fallback to local utils function return {} def call_modal_calculate_returns(monthly_investment: float, annual_return: float, years: int) -> Dict[str, Any]: """Call Modal backend for investment return calculations""" try: payload = { "monthly_investment": monthly_investment, "annual_return_rate": annual_return, "years": years } response = requests.post( f"{MODAL_BACKEND_URL}/calculate_returns", json=payload, timeout=30 ) if response.status_code == 200: return response.json().get("returns", {}) else: # Fallback to local utils function return calculate_sip_returns(monthly_investment, annual_return, years) except requests.exceptions.RequestException: # Fallback to local utils function return calculate_sip_returns(monthly_investment, annual_return, years) def check_modal_health() -> Dict[str, Any]: """Check Modal backend health""" try: response = requests.get(f"{MODAL_BACKEND_URL}/health", timeout=10) if response.status_code == 200: return response.json() else: return {"status": "unhealthy", "message": "Backend not responding"} except requests.exceptions.RequestException as e: return {"status": "error", "message": str(e)} def create_salary_breakdown_chart(salary: float, needs: float, wants: float, savings: float): """Create a pie chart for salary breakdown""" labels = ['Needs (50%)', 'Wants (30%)', 'Savings (20%)'] values = [needs, wants, savings] colors = ['#ff6b6b', '#4ecdc4', '#45b7d1'] fig = go.Figure(data=[go.Pie( labels=labels, values=values, hole=0.4, marker_colors=colors, textinfo='label+percent', textfont_size=12 )]) fig.update_layout( title=f"Salary Breakdown for ₹{salary:,.0f}", font=dict(size=14), showlegend=True, height=400 ) return fig def create_expense_analysis_chart(expenses: Dict[str, float]): """Create a bar chart for expense analysis""" categories = list(expenses.keys()) amounts = list(expenses.values()) fig = go.Figure([go.Bar( x=categories, y=amounts, marker_color='#667eea', text=[f"₹{amount:,.0f}" for amount in amounts], textposition='auto' )]) fig.update_layout( title="Monthly Expense Breakdown", xaxis_title="Categories", yaxis_title="Amount (₹)", font=dict(size=12), height=400 ) return fig def create_investment_projection_chart(monthly_investment: float, years: int): """Create investment projection chart using Modal backend""" returns_data = call_modal_calculate_returns(monthly_investment, 12.0, years) if not returns_data: return go.Figure() # Create year-wise projection years_list = list(range(1, years + 1)) investment_values = [] for year in years_list: year_data = call_modal_calculate_returns(monthly_investment, 12.0, year) investment_values.append(year_data.get('future_value', 0)) fig = go.Figure() fig.add_trace(go.Scatter( x=years_list, y=investment_values, mode='lines+markers', name='Investment Growth', line=dict(color='#667eea', width=3), marker=dict(size=8) )) fig.update_layout( title=f"SIP Growth Projection (₹{monthly_investment:,.0f}/month @ 12% annual return)", xaxis_title="Years", yaxis_title="Amount (₹)", font=dict(size=12), height=400 ) return fig def process_financial_query( salary: float, rent: float, food: float, transport: float, utilities: float, entertainment: float, other: float, savings_goal: str, user_question: str ) -> tuple: """Process user's financial query with enhanced Modal integration""" # Validate inputs using utils salary_valid, salary_msg = validate_salary(salary) if not salary_valid: return None, None, f"❌ {salary_msg}", "Please fix the salary amount and try again." # Calculate totals total_expenses = rent + food + transport + utilities + entertainment + other remaining_salary = salary - total_expenses # Create expense dictionary expenses = { "rent": rent, "food": food, "transport": transport, "utilities": utilities, "entertainment": entertainment, "other": other } # Validate expenses using utils expenses_valid, expenses_msg, warnings = validate_expenses(expenses, salary) if not expenses_valid: return None, None, f"❌ {expenses_msg}", "Please adjust your expenses and try again." # Get salary breakdown using utils breakdown = calculate_50_30_20_breakdown(salary) needs = breakdown["needs"] wants = breakdown["wants"] savings = breakdown["savings"] # Get expense analysis from Modal backend modal_analysis = call_modal_analyze_expenses(expenses, salary) # Get optimization tips from utils optimization_tips = get_expense_optimization_tips(expenses, salary) # Create charts salary_chart = create_salary_breakdown_chart(salary, needs, wants, savings) expense_chart = create_expense_analysis_chart({k.title(): v for k, v in expenses.items()}) # Calculate emergency fund target using utils emergency_fund = calculate_emergency_fund_target(total_expenses) # Prepare context for Modal backend context = { "salary": salary, "expenses": expenses, "total_expenses": total_expenses, "remaining_salary": remaining_salary, "savings_goal": savings_goal, "breakdown": breakdown, "emergency_fund": emergency_fund, "optimization_tips": optimization_tips[:3] # Top 3 tips } # Get AI advice from Modal if user_question.strip(): advice = call_modal_financial_advice(user_question, context) else: advice = call_modal_financial_advice(f"Analyze my finances: Salary ₹{salary}, Total expenses ₹{total_expenses}", context) # Create enhanced summary summary = f""" ## 💰 Financial Summary **Monthly Salary:** ₹{salary:,.0f} **Total Expenses:** ₹{total_expenses:,.0f} **Remaining Amount:** ₹{remaining_salary:,.0f} ### 📊 Recommended Allocation (50/30/20 Rule) - **Needs (50%):** ₹{needs:,.0f} - **Wants (30%):** ₹{wants:,.0f} - **Savings (20%):** ₹{savings:,.0f} ### 🎯 Status {'✅ Good job! You have money left over.' if remaining_salary > 0 else '⚠️ You are overspending. Consider reducing expenses.'} ### 🚨 Emergency Fund Target **Target Amount:** ₹{emergency_fund['target_amount']:,.0f} ({emergency_fund['months_coverage']} months) ### 💡 Quick Optimization Tips {chr(10).join(f"• {tip}" for tip in optimization_tips[:3])} ### ⚠️ Warnings {chr(10).join(f"• {warning}" for warning in warnings) if warnings else "No warnings - you're doing great!"} """ return salary_chart, expense_chart, summary, advice def calculate_sip_projection(monthly_investment: float, annual_return: float, years: int) -> tuple: """Calculate and visualize SIP projections using Modal backend""" if monthly_investment <= 0 or years <= 0: return None, "Please enter valid investment amount and timeline." # Get returns data from Modal backend returns_data = call_modal_calculate_returns(monthly_investment, annual_return, years) if not returns_data: return None, "Unable to calculate returns. Please try again." # Create projection chart projection_chart = create_investment_projection_chart(monthly_investment, years) # Create summary summary = f""" ## 📈 SIP Investment Projection **Monthly Investment:** ₹{monthly_investment:,.0f} **Annual Return:** {annual_return}% **Investment Period:** {years} years ### 💰 Projected Results - **Total Invested:** ₹{returns_data.get('total_invested', 0):,.0f} - **Future Value:** ₹{returns_data.get('future_value', 0):,.0f} - **Returns Generated:** ₹{returns_data.get('returns', 0):,.0f} - **Return Percentage:** {returns_data.get('return_percentage', 0):.1f}% ### 🎯 Wealth Creation Your ₹{monthly_investment:,.0f} monthly investment will grow to ₹{returns_data.get('future_value', 0):,.0f} in {years} years! """ return projection_chart, summary def handle_quick_question(question: str, salary: float = 50000) -> str: """Handle pre-defined quick questions""" context = {"salary": salary} return call_modal_financial_advice(question, context) def show_health_status() -> str: """Show Modal backend health status""" health = check_modal_health() if health.get("status") == "healthy": return "✅ Backend is healthy and running!" else: return f"❌ Backend issue: {health.get('message', 'Unknown error')}" # Create Gradio interface def create_moneymate_app(): with gr.Blocks(css=CUSTOM_CSS, title="MoneyMate - Your Financial Assistant") as app: # Header gr.HTML("""

💰 MoneyMate

Your Personal Financial Assistant for Smart Money Management

""") with gr.Tabs(): # Main Financial Analysis Tab with gr.Tab("💼 Financial Analysis"): with gr.Row(): with gr.Column(scale=1): gr.HTML('
') gr.Markdown("### 💼 Your Financial Details") salary_input = gr.Number( label="Monthly Salary (₹)", value=50000, minimum=0, step=1000 ) gr.Markdown("#### Monthly Expenses") rent_input = gr.Number(label="Rent (₹)", value=15000, minimum=0) food_input = gr.Number(label="Food (₹)", value=8000, minimum=0) transport_input = gr.Number(label="Transport (₹)", value=3000, minimum=0) utilities_input = gr.Number(label="Utilities (₹)", value=2000, minimum=0) entertainment_input = gr.Number(label="Entertainment (₹)", value=4000, minimum=0) other_input = gr.Number(label="Other Expenses (₹)", value=3000, minimum=0) savings_goal_input = gr.Textbox( label="Savings Goal", placeholder="e.g., Emergency fund, Vacation, House down payment", value="Emergency fund" ) user_question_input = gr.Textbox( label="Ask MoneyMate", placeholder="e.g., How should I invest my savings? What's the best way to save for a house?", lines=3 ) analyze_btn = gr.Button("Analyze My Finances 📊", variant="primary", size="large") health_btn = gr.Button("Check Backend Status 🔍", variant="secondary", size="small") health_status = gr.Textbox(label="Status", interactive=False) gr.HTML('
') # Quick action buttons gr.HTML('
') gr.Markdown("### 🚀 Quick Questions") with gr.Row(): quick_btn1 = gr.Button("💡 Investment Tips", size="small") quick_btn2 = gr.Button("🏠 Save for House", size="small") with gr.Row(): quick_btn3 = gr.Button("✈️ Plan Vacation", size="small") quick_btn4 = gr.Button("🚗 Buy a Car", size="small") gr.HTML('
') with gr.Column(scale=2): gr.HTML('
') # Output components with gr.Tab("📊 Salary Breakdown"): salary_chart_output = gr.Plot() with gr.Tab("💸 Expense Analysis"): expense_chart_output = gr.Plot() with gr.Tab("📋 Summary"): summary_output = gr.Markdown() with gr.Tab("🤖 AI Advice"): advice_output = gr.Markdown(value="Click 'Analyze My Finances' to get personalized advice!") gr.HTML('
') # SIP Calculator Tab with gr.Tab("📈 SIP Calculator"): with gr.Row(): with gr.Column(scale=1): gr.Markdown("### 📈 SIP Investment Calculator") monthly_investment_input = gr.Number( label="Monthly Investment (₹)", value=5000, minimum=500, step=500 ) annual_return_input = gr.Number( label="Expected Annual Return (%)", value=12.0, minimum=1.0, maximum=30.0, step=0.5 ) years_input = gr.Number( label="Investment Period (Years)", value=10, minimum=1, maximum=50, step=1 ) calculate_sip_btn = gr.Button("Calculate SIP Returns 📊", variant="primary") with gr.Column(scale=2): sip_chart_output = gr.Plot() sip_summary_output = gr.Markdown() # Event handlers analyze_btn.click( fn=process_financial_query, inputs=[ salary_input, rent_input, food_input, transport_input, utilities_input, entertainment_input, other_input, savings_goal_input, user_question_input ], outputs=[salary_chart_output, expense_chart_output, summary_output, advice_output] ) calculate_sip_btn.click( fn=calculate_sip_projection, inputs=[monthly_investment_input, annual_return_input, years_input], outputs=[sip_chart_output, sip_summary_output] ) health_btn.click( fn=show_health_status, outputs=[health_status] ) # Quick question handlers quick_btn1.click( fn=lambda s: handle_quick_question("What are the best investment options for a beginner in India?", s), inputs=[salary_input], outputs=[advice_output] ) quick_btn2.click( fn=lambda s: handle_quick_question("How should I save for buying a house in India?", s), inputs=[salary_input], outputs=[advice_output] ) quick_btn3.click( fn=lambda s: handle_quick_question("What's the best way to save for a vacation?", s), inputs=[salary_input], outputs=[advice_output] ) quick_btn4.click( fn=lambda s: handle_quick_question("How should I plan to buy a car with my salary?", s), inputs=[salary_input], outputs=[advice_output] ) # Footer gr.HTML("""

Made with ❤️ for Agents & MCP Hackathon 2025

🏆 Track 1 — MCP Tool / Server

""") return app if __name__ == "__main__": app = create_moneymate_app() app.launch( server_name="0.0.0.0", server_port=7860, share=True )