Skip to main content
Glama
unnimk75-web

Benefits Agent MCP Server

by unnimk75-web
ben_agent_mcp_server.py15.3 kB
from fastmcp import FastMCP from typing import Dict, List, Optional from datetime import datetime, timedelta import json import os # Initialize FastMCP server for Benefit Agent mcp = FastMCP("Benefit Agent - Healthcare Financial Tracking") # Load mock data from JSON file def load_mock_data(): """Load mock data from JSON file""" json_file = "ben_agent_mcp_server_data.json" # Check if file exists if not os.path.exists(json_file): raise FileNotFoundError(f"Data file not found: {json_file}") with open(json_file, 'r') as f: data = json.load(f) return data # Load data at startup try: MOCK_DATA = load_mock_data() MOCK_MEMBERS = MOCK_DATA["members"] MOCK_DEDUCTIBLES = MOCK_DATA["deductibles"] MOCK_OUT_OF_POCKET = MOCK_DATA["out_of_pocket"] MOCK_BENEFIT_USAGE = MOCK_DATA["benefit_usage"] MOCK_SPENDING = MOCK_DATA["spending_summary"] print("✓ Mock data loaded successfully from ben_agent_mcp_server_data.json") except FileNotFoundError as e: print(f"ERROR: {e}") print("Please ensure ben_agent_mcp_server_data.json is in the same directory as this script") exit(1) except json.JSONDecodeError as e: print(f"ERROR: Invalid JSON format in data file: {e}") exit(1) @mcp.tool() def get_deductible_status(member_id: str, deductible_type: Optional[str] = None) -> Dict: """Get current deductible status showing amounts used and remaining. This tool shows how much of the annual deductible has been met and how much remains for medical and prescription coverage. Args: member_id: The unique identifier for the member (e.g., 'MEM001') deductible_type: Optional filter for specific deductible type. Valid values: 'medical', 'prescription', 'all' Default: 'all' (returns all deductible types) Returns: Dictionary containing deductible information including amounts met and remaining for individual and family deductibles. """ if member_id not in MOCK_MEMBERS: return { "error": "Member not found", "message": f"No member found with ID: {member_id}", "available_members": list(MOCK_MEMBERS.keys()) } member_info = MOCK_MEMBERS[member_id] deductible_data = MOCK_DEDUCTIBLES.get(member_id, {}) if deductible_type and deductible_type.lower() != "all": deductible_type_lower = deductible_type.lower() if deductible_type_lower in deductible_data: filtered_deductible = {deductible_type_lower: deductible_data[deductible_type_lower]} else: return { "error": "Invalid deductible type", "message": f"Deductible type '{deductible_type}' not recognized", "valid_types": list(deductible_data.keys()) } else: filtered_deductible = deductible_data result = { "member_id": member_id, "member_name": member_info["name"], "plan_type": member_info["plan_type"], "plan_year": f"{member_info['plan_year_start']} to {member_info['plan_year_end']}", "deductibles": {}, "query_date": datetime.now().isoformat() } for ded_type, ded_info in filtered_deductible.items(): if ded_type == "medical": result["deductibles"]["medical"] = { "individual": { "total": f"${ded_info['individual_total']}", "met": f"${ded_info['individual_met']}", "remaining": f"${ded_info['individual_total'] - ded_info['individual_met']}", "percent_met": f"{(ded_info['individual_met'] / ded_info['individual_total'] * 100):.1f}%" }, "family": { "total": f"${ded_info['family_total']}", "met": f"${ded_info['family_met']}", "remaining": f"${ded_info['family_total'] - ded_info['family_met']}", "percent_met": f"{(ded_info['family_met'] / ded_info['family_total'] * 100):.1f}%" } } elif ded_type == "prescription": result["deductibles"]["prescription"] = { "total": f"${ded_info['total']}", "met": f"${ded_info['met']}", "remaining": f"${ded_info['total'] - ded_info['met']}", "percent_met": f"{(ded_info['met'] / ded_info['total'] * 100):.1f}%" } return result @mcp.tool() def get_out_of_pocket_status(member_id: str) -> Dict: """Get out-of-pocket maximum status and progress toward annual limit. This tool shows current spending toward the out-of-pocket maximum, which is the most a member will pay in a plan year. Args: member_id: The unique identifier for the member (e.g., 'MEM001') Returns: Dictionary containing out-of-pocket spending details including current amounts, maximums, and remaining amounts before hitting the cap. """ if member_id not in MOCK_MEMBERS: return { "error": "Member not found", "message": f"No member found with ID: {member_id}" } member_info = MOCK_MEMBERS[member_id] oop_data = MOCK_OUT_OF_POCKET.get(member_id, {}) return { "member_id": member_id, "member_name": member_info["name"], "plan_type": member_info["plan_type"], "plan_year": f"{member_info['plan_year_start']} to {member_info['plan_year_end']}", "out_of_pocket": { "individual": { "maximum": f"${oop_data['individual_maximum']}", "current": f"${oop_data['individual_current']}", "remaining": f"${oop_data['individual_maximum'] - oop_data['individual_current']}", "percent_reached": f"{(oop_data['individual_current'] / oop_data['individual_maximum'] * 100):.1f}%" }, "family": { "maximum": f"${oop_data['family_maximum']}", "current": f"${oop_data['family_current']}", "remaining": f"${oop_data['family_maximum'] - oop_data['family_current']}", "percent_reached": f"{(oop_data['family_current'] / oop_data['family_maximum'] * 100):.1f}%" } }, "query_date": datetime.now().isoformat(), "note": "Once out-of-pocket maximum is reached, the plan pays 100% of covered services for the rest of the plan year." } @mcp.tool() def get_benefit_utilization(member_id: str, benefit_category: Optional[str] = None) -> Dict: """Get detailed benefit utilization across medical, dental, vision, and pharmacy. This tool shows how many services or benefits have been used compared to annual limits or allowances. Args: member_id: The unique identifier for the member (e.g., 'MEM001') benefit_category: Optional filter for specific benefit category. Valid values: 'medical', 'dental', 'vision', 'pharmacy', 'all' Default: 'all' (returns all benefit categories) Returns: Dictionary containing utilization details for each benefit category including services used, limits, and remaining allowances. """ if member_id not in MOCK_MEMBERS: return { "error": "Member not found", "message": f"No member found with ID: {member_id}" } member_info = MOCK_MEMBERS[member_id] usage_data = MOCK_BENEFIT_USAGE.get(member_id, {}) if benefit_category and benefit_category.lower() != "all": category_map = { "medical": "medical_visits", "dental": "dental", "vision": "vision", "pharmacy": "pharmacy" } category_key = category_map.get(benefit_category.lower()) if category_key and category_key in usage_data: filtered_usage = {category_key: usage_data[category_key]} else: return { "error": "Invalid benefit category", "message": f"Benefit category '{benefit_category}' not recognized", "valid_categories": ["medical", "dental", "vision", "pharmacy", "all"] } else: filtered_usage = usage_data return { "member_id": member_id, "member_name": member_info["name"], "plan_type": member_info["plan_type"], "plan_year": f"{member_info['plan_year_start']} to {member_info['plan_year_end']}", "benefit_utilization": filtered_usage, "query_date": datetime.now().isoformat() } @mcp.tool() def get_remaining_benefits(member_id: str) -> Dict: """Get summary of remaining benefits with annual limits. This tool highlights benefits that have annual limits (like dental maximums, vision allowances) and shows what remains available for the year. Args: member_id: The unique identifier for the member (e.g., 'MEM001') Returns: Dictionary containing remaining benefits summary with focus on limited benefits like dental annual maximums and vision allowances. """ if member_id not in MOCK_MEMBERS: return { "error": "Member not found", "message": f"No member found with ID: {member_id}" } member_info = MOCK_MEMBERS[member_id] usage_data = MOCK_BENEFIT_USAGE.get(member_id, {}) remaining = { "member_id": member_id, "member_name": member_info["name"], "plan_type": member_info["plan_type"], "remaining_benefits": {} } # Dental remaining if "dental" in usage_data: dental = usage_data["dental"] remaining["remaining_benefits"]["dental"] = { "annual_maximum_remaining": f"${dental['annual_max_total'] - dental['annual_max_used']}", "annual_maximum_total": f"${dental['annual_max_total']}", "preventive_visits_remaining": dental["preventive"]["limit"] - dental["preventive"]["used"] if dental["preventive"]["limit"] else "Unlimited" } # Vision remaining if "vision" in usage_data: vision = usage_data["vision"] remaining["remaining_benefits"]["vision"] = { "eye_exams_remaining": vision["eye_exams"]["limit"] - vision["eye_exams"]["used"], "frame_allowance_remaining": f"${vision['frames']['allowance_total'] - vision['frames']['allowance_used']}", "contact_allowance_remaining": f"${vision['contacts']['allowance_total'] - vision['contacts']['allowance_used']}" } days_remaining = ( datetime.strptime(member_info['plan_year_end'], '%Y-%m-%d') - datetime.now() ).days remaining["days_remaining_in_plan_year"] = days_remaining remaining["query_date"] = datetime.now().isoformat() remaining["reminder"] = f"You have {days_remaining} days left to use these benefits before they reset." return remaining @mcp.tool() def get_spending_summary(member_id: str) -> Dict: """Get comprehensive spending summary across all benefit categories. This tool provides a financial overview of year-to-date spending, deductible progress, and out-of-pocket progress. Args: member_id: The unique identifier for the member (e.g., 'MEM001') Returns: Dictionary containing complete spending summary including total spending, spending by category, deductible status, and out-of-pocket status. """ if member_id not in MOCK_MEMBERS: return { "error": "Member not found", "message": f"No member found with ID: {member_id}" } member_info = MOCK_MEMBERS[member_id] spending_by_category = MOCK_SPENDING.get(member_id, {}) deductible_data = MOCK_DEDUCTIBLES.get(member_id, {}) oop_data = MOCK_OUT_OF_POCKET.get(member_id, {}) total_spending = sum(spending_by_category.values()) # Deductible summary deductible_status = {} if "medical" in deductible_data: med_ded = deductible_data["medical"] deductible_status["medical"] = { "individual_met": f"${med_ded['individual_met']}", "individual_remaining": f"${med_ded['individual_total'] - med_ded['individual_met']}" } if "prescription" in deductible_data: rx_ded = deductible_data["prescription"] deductible_status["prescription"] = { "met": f"${rx_ded['met']}", "remaining": f"${rx_ded['total'] - rx_ded['met']}" } # Out-of-pocket summary oop_status = { "individual": { "current": f"${oop_data['individual_current']}", "remaining": f"${oop_data['individual_maximum'] - oop_data['individual_current']}" }, "family": { "current": f"${oop_data['family_current']}", "remaining": f"${oop_data['family_maximum'] - oop_data['family_current']}" } } return { "member_id": member_id, "member_name": member_info["name"], "plan_type": member_info["plan_type"], "plan_year": f"{member_info['plan_year_start']} to {member_info['plan_year_end']}", "total_spending_ytd": f"${total_spending}", "spending_by_category": { "breakdown": { "medical": f"${spending_by_category.get('medical', 0)}", "dental": f"${spending_by_category.get('dental', 0)}", "vision": f"${spending_by_category.get('vision', 0)}", "pharmacy": f"${spending_by_category.get('pharmacy', 0)}" } }, "deductible_progress": deductible_status, "out_of_pocket_progress": oop_status, "days_remaining_in_plan_year": ( datetime.strptime(member_info['plan_year_end'], '%Y-%m-%d') - datetime.now() ).days, "query_date": datetime.now().isoformat(), "financial_tip": "Consider scheduling needed services before year-end if you've met your deductible or are close to your out-of-pocket maximum." } if __name__ == "__main__": # Run the Benefit Agent MCP server print("Starting Benefit Agent MCP Server...") print("Available tools:") print(" - get_deductible_status: Check deductible amounts used and remaining") print(" - get_out_of_pocket_status: View out-of-pocket maximum progress") print(" - get_benefit_utilization: Detailed usage across all benefit categories") print(" - get_remaining_benefits: Check remaining benefits with annual limits") print(" - get_spending_summary: Comprehensive year-to-date spending overview") print("\nServer running on http://0.0.0.0:8000") mcp.run(transport="sse", port=8000, host="0.0.0.0")

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/unnimk75-web/mcp-benefits-agent'

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