Skip to main content
Glama
sigaihealth

RealVest Real Estate MCP Server

refinance.js17.3 kB
/** * Refinance Calculator * Analyzes whether refinancing makes financial sense */ export class RefinanceCalculator { getSchema() { return { type: 'object', properties: { current_loan: { type: 'object', properties: { original_balance: { type: 'number', minimum: 0, description: 'Original loan amount' }, current_balance: { type: 'number', minimum: 0, description: 'Current loan balance' }, interest_rate: { type: 'number', minimum: 0, maximum: 100, description: 'Current interest rate (%)' }, monthly_payment: { type: 'number', minimum: 0, description: 'Current monthly payment (P&I)' }, years_remaining: { type: 'number', minimum: 0, maximum: 30, description: 'Years remaining on current loan' }, months_paid: { type: 'number', minimum: 0, description: 'Months already paid' } }, required: ['current_balance', 'interest_rate', 'monthly_payment', 'years_remaining'] }, new_loan: { type: 'object', properties: { interest_rate: { type: 'number', minimum: 0, maximum: 100, description: 'New interest rate (%)' }, loan_term_years: { type: 'number', minimum: 1, maximum: 30, description: 'New loan term in years' }, closing_costs: { type: 'number', minimum: 0, description: 'Total closing costs' }, points: { type: 'number', minimum: 0, maximum: 10, description: 'Discount points' }, cash_out: { type: 'number', minimum: 0, description: 'Cash-out amount (if any)' } }, required: ['interest_rate', 'loan_term_years'] }, property_info: { type: 'object', properties: { current_value: { type: 'number', minimum: 0, description: 'Current property value' }, property_type: { type: 'string', enum: ['primary_residence', 'investment_property', 'second_home'], description: 'Type of property' } } }, analysis_options: { type: 'object', properties: { tax_bracket: { type: 'number', minimum: 0, maximum: 100, description: 'Marginal tax bracket (%)' }, investment_return: { type: 'number', minimum: 0, maximum: 100, description: 'Expected return on investments (%)' }, planning_horizon_years: { type: 'number', minimum: 1, maximum: 30, description: 'How long you plan to keep property' } } } }, required: ['current_loan', 'new_loan'] }; } calculate(params) { const { current_loan, new_loan, property_info = {}, analysis_options = {} } = params; // Set defaults const tax_bracket = analysis_options.tax_bracket || 25; const investment_return = analysis_options.investment_return || 7; const planning_horizon_years = analysis_options.planning_horizon_years || new_loan.loan_term_years; const closing_costs = new_loan.closing_costs || (current_loan.current_balance * 0.02); const points_cost = (new_loan.points || 0) * current_loan.current_balance / 100; // Calculate new loan amount const new_loan_amount = current_loan.current_balance + (new_loan.cash_out || 0) + (closing_costs + points_cost); // Calculate new monthly payment const new_rate_monthly = new_loan.interest_rate / 100 / 12; const new_term_months = new_loan.loan_term_years * 12; const new_monthly_payment = this.calculateMonthlyPayment( new_loan_amount, new_rate_monthly, new_term_months ); // Monthly savings const monthly_savings = current_loan.monthly_payment - new_monthly_payment; // Calculate break-even const total_upfront_costs = closing_costs + points_cost; const simple_breakeven_months = monthly_savings > 0 ? Math.ceil(total_upfront_costs / monthly_savings) : null; // Calculate interest savings const current_total_interest = this.calculateTotalInterest( current_loan.current_balance, current_loan.interest_rate / 100 / 12, current_loan.years_remaining * 12 ); const new_total_interest = this.calculateTotalInterest( new_loan_amount, new_rate_monthly, new_term_months ); const interest_savings = current_total_interest - new_total_interest; // NPV analysis const npv_analysis = this.calculateNPV( current_loan, new_loan, new_loan_amount, new_monthly_payment, monthly_savings, total_upfront_costs, investment_return, planning_horizon_years ); // LTV analysis const ltv_analysis = property_info.current_value ? { current_ltv: (current_loan.current_balance / property_info.current_value * 100).toFixed(1), new_ltv: (new_loan_amount / property_info.current_value * 100).toFixed(1), max_conventional_ltv: property_info.property_type === 'investment_property' ? 75 : 80, pmi_required: property_info.property_type === 'primary_residence' && (new_loan_amount / property_info.current_value) > 0.80 } : null; // Calculate effective interest rate (after tax deduction if applicable) const effective_rate_analysis = { current_effective_rate: current_loan.interest_rate * (1 - tax_bracket / 100), new_effective_rate: new_loan.interest_rate * (1 - tax_bracket / 100), tax_deduction_applicable: property_info.property_type !== 'primary_residence' || new_loan_amount <= 750000 }; // Decision metrics const should_refinance = this.evaluateRefinance( monthly_savings, simple_breakeven_months, npv_analysis.net_present_value, planning_horizon_years, current_loan.interest_rate, new_loan.interest_rate ); // Alternative scenarios const scenarios = this.calculateScenarios( current_loan, new_loan, property_info, new_loan_amount ); return { loan_comparison: { current_loan: { balance: current_loan.current_balance, rate: current_loan.interest_rate, monthly_payment: current_loan.monthly_payment, years_remaining: current_loan.years_remaining, total_remaining_interest: current_total_interest }, new_loan: { amount: new_loan_amount, rate: new_loan.interest_rate, monthly_payment: new_monthly_payment, term_years: new_loan.loan_term_years, total_interest: new_total_interest, closing_costs: closing_costs, points_cost: points_cost } }, financial_impact: { monthly_savings: monthly_savings, annual_savings: monthly_savings * 12, total_interest_savings: interest_savings, upfront_costs: total_upfront_costs, net_lifetime_savings: interest_savings - total_upfront_costs }, break_even_analysis: { simple_breakeven_months: simple_breakeven_months, simple_breakeven_years: simple_breakeven_months ? (simple_breakeven_months / 12).toFixed(1) : null, true_breakeven_months: npv_analysis.true_breakeven_months, roi_at_breakeven: simple_breakeven_months ? ((monthly_savings * 12) / total_upfront_costs * 100).toFixed(1) : null }, npv_analysis: npv_analysis, ltv_analysis: ltv_analysis, effective_rate_analysis: effective_rate_analysis, decision: { should_refinance: should_refinance.decision, confidence: should_refinance.confidence, primary_reason: should_refinance.primary_reason, risk_factors: should_refinance.risk_factors }, scenarios: scenarios, recommendations: this.generateRecommendations( should_refinance, monthly_savings, simple_breakeven_months, planning_horizon_years, ltv_analysis, current_loan, new_loan ) }; } calculateMonthlyPayment(principal, monthlyRate, months) { if (monthlyRate === 0) return principal / months; return principal * monthlyRate * Math.pow(1 + monthlyRate, months) / (Math.pow(1 + monthlyRate, months) - 1); } calculateTotalInterest(principal, monthlyRate, months) { const monthlyPayment = this.calculateMonthlyPayment(principal, monthlyRate, months); return (monthlyPayment * months) - principal; } calculateNPV(currentLoan, newLoan, newLoanAmount, newPayment, monthlySavings, upfrontCosts, investmentReturn, horizonYears) { const monthlyReturn = investmentReturn / 100 / 12; const horizonMonths = Math.min(horizonYears * 12, currentLoan.years_remaining * 12); let npv = -upfrontCosts; let trueBreakevenMonth = null; let cumulativeSavings = -upfrontCosts; // Calculate present value of monthly savings for (let month = 1; month <= horizonMonths; month++) { const pv = monthlySavings / Math.pow(1 + monthlyReturn, month); npv += pv; cumulativeSavings += monthlySavings; if (trueBreakevenMonth === null && cumulativeSavings > 0) { trueBreakevenMonth = month; } } // Add value of lower balance at end of horizon if selling if (horizonYears < newLoan.loan_term_years) { const currentBalance = this.calculateRemainingBalance( currentLoan.current_balance, currentLoan.interest_rate / 100 / 12, currentLoan.years_remaining * 12, horizonMonths ); const newBalance = this.calculateRemainingBalance( newLoanAmount, newLoan.interest_rate / 100 / 12, newLoan.loan_term_years * 12, horizonMonths ); const balanceDifference = currentBalance - newBalance; const pvBalanceDiff = balanceDifference / Math.pow(1 + monthlyReturn, horizonMonths); npv += pvBalanceDiff; } return { net_present_value: npv, true_breakeven_months: trueBreakevenMonth, total_cash_flow_benefit: monthlySavings * horizonMonths - upfrontCosts, irr: this.calculateIRR(upfrontCosts, monthlySavings, horizonMonths) }; } calculateRemainingBalance(principal, monthlyRate, totalMonths, monthsPaid) { const monthlyPayment = this.calculateMonthlyPayment(principal, monthlyRate, totalMonths); let balance = principal; for (let i = 0; i < monthsPaid; i++) { const interestPayment = balance * monthlyRate; const principalPayment = monthlyPayment - interestPayment; balance -= principalPayment; } return Math.max(0, balance); } calculateIRR(initialCost, monthlySavings, months) { // Simple IRR approximation const totalReturn = monthlySavings * months; const gain = totalReturn - initialCost; const avgAnnualReturn = (gain / initialCost) / (months / 12); return avgAnnualReturn * 100; } evaluateRefinance(monthlySavings, breakevenMonths, npv, planningHorizon, currentRate, newRate) { const rateDrop = currentRate - newRate; let decision = false; let confidence = 'low'; let primaryReason = ''; const riskFactors = []; // Strong indicators for refinancing if (rateDrop >= 0.75 && breakevenMonths && breakevenMonths <= 36 && npv > 0) { decision = true; confidence = 'high'; primaryReason = 'Significant rate reduction with reasonable break-even'; } else if (rateDrop >= 0.5 && breakevenMonths && breakevenMonths <= 24 && npv > 0) { decision = true; confidence = 'high'; primaryReason = 'Good rate reduction with quick break-even'; } else if (monthlySavings > 200 && breakevenMonths && breakevenMonths <= 48) { decision = true; confidence = 'medium'; primaryReason = 'Substantial monthly savings'; } else if (npv > 10000) { decision = true; confidence = 'medium'; primaryReason = 'Strong positive NPV'; } // Risk factors if (breakevenMonths && breakevenMonths > planningHorizon * 12) { riskFactors.push('Break-even exceeds planning horizon'); confidence = 'low'; } if (rateDrop < 0.5) { riskFactors.push('Minimal rate improvement'); } if (breakevenMonths && breakevenMonths > 60) { riskFactors.push('Very long break-even period'); decision = false; } if (monthlySavings < 50) { riskFactors.push('Minimal monthly savings'); decision = false; } return { decision, confidence, primary_reason: primaryReason, risk_factors: riskFactors }; } calculateScenarios(currentLoan, newLoan, propertyInfo, newLoanAmount) { const scenarios = []; // No cash-out scenario if (newLoan.cash_out > 0) { const noCashOutAmount = currentLoan.current_balance + (newLoan.closing_costs || currentLoan.current_balance * 0.02) + ((newLoan.points || 0) * currentLoan.current_balance / 100); const noCashOutPayment = this.calculateMonthlyPayment( noCashOutAmount, newLoan.interest_rate / 100 / 12, newLoan.loan_term_years * 12 ); scenarios.push({ name: 'No Cash-Out Refinance', loan_amount: noCashOutAmount, monthly_payment: noCashOutPayment, monthly_savings: currentLoan.monthly_payment - noCashOutPayment }); } // Different term scenarios const terms = [15, 20, 30].filter(t => t !== newLoan.loan_term_years); terms.forEach(term => { const payment = this.calculateMonthlyPayment( newLoanAmount, newLoan.interest_rate / 100 / 12, term * 12 ); scenarios.push({ name: `${term}-Year Term`, loan_amount: newLoanAmount, monthly_payment: payment, monthly_savings: currentLoan.monthly_payment - payment, total_interest: this.calculateTotalInterest( newLoanAmount, newLoan.interest_rate / 100 / 12, term * 12 ) }); }); // Rate scenarios [-0.25, 0.25].forEach(rateAdjust => { const adjustedRate = newLoan.interest_rate + rateAdjust; const payment = this.calculateMonthlyPayment( newLoanAmount, adjustedRate / 100 / 12, newLoan.loan_term_years * 12 ); scenarios.push({ name: `${adjustedRate.toFixed(2)}% Rate`, loan_amount: newLoanAmount, monthly_payment: payment, monthly_savings: currentLoan.monthly_payment - payment }); }); return scenarios; } generateRecommendations(shouldRefinance, monthlySavings, breakevenMonths, planningHorizon, ltvAnalysis, currentLoan, newLoan) { const recommendations = []; if (shouldRefinance.decision) { recommendations.push({ category: 'Action', priority: 'high', message: `Proceed with refinance - ${shouldRefinance.primary_reason}` }); if (monthlySavings > 0) { recommendations.push({ category: 'Savings Strategy', priority: 'medium', message: `Invest the $${monthlySavings.toFixed(0)} monthly savings for compound growth` }); } } else { recommendations.push({ category: 'Action', priority: 'high', message: 'Refinancing not recommended at this time' }); if (currentLoan.interest_rate - newLoan.interest_rate < 0.5) { recommendations.push({ category: 'Alternative', priority: 'medium', message: 'Wait for rates to drop at least 0.5% below current rate' }); } } // Break-even recommendations if (breakevenMonths && breakevenMonths > 36) { recommendations.push({ category: 'Timing', priority: 'medium', message: 'Consider negotiating lower closing costs to improve break-even' }); } // LTV recommendations if (ltvAnalysis) { if (ltvAnalysis.new_ltv > 80 && ltvAnalysis.pmi_required) { recommendations.push({ category: 'Cost Reduction', priority: 'high', message: 'Consider larger down payment to avoid PMI' }); } if (ltvAnalysis.new_ltv > ltvAnalysis.max_conventional_ltv) { recommendations.push({ category: 'Loan Type', priority: 'high', message: 'May need jumbo or portfolio loan for this LTV' }); } } // Planning horizon if (breakevenMonths && planningHorizon * 12 < breakevenMonths) { recommendations.push({ category: 'Risk', priority: 'high', message: `You may sell before reaching break-even (${(breakevenMonths/12).toFixed(1)} years)` }); } // Rate environment if (newLoan.interest_rate > 7) { recommendations.push({ category: 'Market Timing', priority: 'medium', message: 'Consider waiting if rates are expected to decline' }); } return recommendations; } }

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/sigaihealth/realvestmcp'

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