Skip to main content
Glama

calculate_income_tax

Calculate French income tax using net taxable income and household composition to determine tax liability based on official government data.

Instructions

Calculate French income tax based on net taxable income and household composition

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
net_taxable_incomeYes
household_partsNo
yearNo
ctxNo

Implementation Reference

  • Registration of the calculate_income_tax tool using MCP decorator
    @mcp.tool( name="calculate_income_tax", description="Calculate French income tax based on net taxable income and household composition", )
  • MCP tool handler: wrapper function that invokes the analyzer's calculate_income_tax and handles errors/context logging
    async def calculate_income_tax_wrapper( net_taxable_income: float, household_parts: float = 1.0, year: Optional[int] = None, ctx: Optional[Context] = None, ) -> Optional[Dict]: """Calculate income tax based on net taxable income and household composition. Args: net_taxable_income: Net taxable income in euros household_parts: Number of household parts (quotient familial) year: Tax year (defaults to current year) ctx: MCP context for logging Returns: Dict: Dictionary containing tax calculation details """ try: if ctx: await ctx.info(f"Calculating income tax for {net_taxable_income}€ with {household_parts} parts") result = await calculate_income_tax(net_taxable_income, household_parts, year) return result except Exception as e: if ctx: await ctx.error(f"Failed to calculate income tax: {e}") return { "status": "error", "message": f"Error calculating income tax: {str(e)}", }
  • Core logic in IncomeTaxAnalyzer class: fetches tax brackets, applies quotient familial, computes progressive tax
    async def calculate_income_tax( self, net_taxable_income: float, household_parts: float = 1.0, year: Optional[int] = None, ) -> Dict: """Calculate income tax based on net taxable income and household composition. Args: net_taxable_income: Net taxable income in euros household_parts: Number of household parts (quotient familial) year: Tax year (defaults to current year) Returns: Dictionary containing tax calculation details """ # Set default year to current year if not specified current_year = datetime.now().year tax_year = year or current_year - 1 # Default to previous year for tax declarations logger.info( f"Calculating income tax for {net_taxable_income}€ with {household_parts} parts for year {tax_year}" ) try: # Get tax brackets brackets_response = await get_tax_brackets(tax_year) if brackets_response["status"] != "success": return { "status": "error", "message": f"Failed to retrieve tax brackets: {brackets_response.get('message', 'Unknown error')}", "year": tax_year, } brackets = brackets_response["data"]["brackets"] # Calculate income tax tax_result = self._calculate_tax(net_taxable_income, household_parts, brackets) # Log data source data_source = brackets_response.get("source", "unknown") logger.info(f"Tax calculation completed using data from: {data_source}") return { "status": "success", "data": { "year": tax_year, "net_taxable_income": net_taxable_income, "household_parts": household_parts, "income_per_part": tax_result["income_per_part"], "tax_per_part": tax_result["tax_per_part"], "total_tax": tax_result["total_tax"], "average_tax_rate": tax_result["average_tax_rate"], "marginal_tax_rate": tax_result["marginal_tax_rate"], "bracket_details": tax_result["bracket_details"], "brackets_source": data_source, }, "message": f"Successfully calculated income tax for {tax_year} using {data_source}", } except Exception as e: logger.error(f"Error calculating income tax: {e}") return { "status": "error", "message": f"Failed to calculate income tax: {str(e)}", "year": tax_year, }
  • Top-level convenience function delegating to singleton IncomeTaxAnalyzer instance
    async def calculate_income_tax( net_taxable_income: float, household_parts: float = 1.0, year: Optional[int] = None, ) -> Dict: """Calculate income tax based on net taxable income and household composition. Args: net_taxable_income: Net taxable income in euros household_parts: Number of household parts (quotient familial) year: Tax year (defaults to current year) Returns: Dictionary containing tax calculation details """ return await income_tax_analyzer.calculate_income_tax(net_taxable_income, household_parts, year)
  • Private method implementing progressive tax bracket calculation with household quotient adjustment
    def _calculate_tax( self, net_taxable_income: float, household_parts: float, brackets: List[Dict], ) -> Dict: """Calculate income tax based on brackets. Args: net_taxable_income: Net taxable income in euros household_parts: Number of household parts (quotient familial) brackets: List of tax brackets Returns: Dictionary containing tax calculation details """ # Calculate income per part income_per_part = net_taxable_income / household_parts # Calculate tax per part tax_per_part = 0 bracket_details = [] marginal_tax_rate = 0 for i, bracket in enumerate(brackets): min_value = bracket["min"] max_value = bracket["max"] if bracket["max"] is not None else float("inf") rate = bracket["rate"] / 100 # Convert percentage to decimal if income_per_part > min_value: # Calculate taxable amount in this bracket taxable_in_bracket = min(income_per_part, max_value) - min_value tax_in_bracket = taxable_in_bracket * rate tax_per_part += tax_in_bracket bracket_details.append( { "bracket": i + 1, "min": min_value, "max": max_value if max_value != float("inf") else None, "rate": bracket["rate"], "taxable_amount": taxable_in_bracket, "tax_amount": tax_in_bracket, } ) # Update marginal tax rate if this is the highest bracket used if income_per_part <= max_value or max_value == float("inf"): marginal_tax_rate = bracket["rate"] # Calculate total tax total_tax = tax_per_part * household_parts # Calculate average tax rate average_tax_rate = (total_tax / net_taxable_income) * 100 if net_taxable_income > 0 else 0 return { "income_per_part": income_per_part, "tax_per_part": tax_per_part, "total_tax": total_tax, "average_tax_rate": average_tax_rate, "marginal_tax_rate": marginal_tax_rate, "bracket_details": bracket_details, }

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/cornelcroi/french-tax-mcp'

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