Skip to main content
Glama
cornelcroi

French Tax MCP Server

by cornelcroi

get_tax_brackets

Retrieve French income tax brackets for a specific year to calculate individual tax liability using official government data.

Instructions

Get income tax brackets (tranches d'imposition) for a specific year

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
yearNo

Implementation Reference

  • MCP decorator registering the get_tax_brackets tool with name and description.
    @mcp.tool(
        name="get_tax_brackets",
        description="Get income tax brackets (tranches d'imposition) for a specific year",
    )
  • The MCP tool handler wrapper for get_tax_brackets. It handles the context, sets default year, imports and calls the scraper implementation, and manages errors.
    async def get_tax_brackets_wrapper(ctx: Context, year: Optional[int] = None) -> Optional[Dict]:
        """Get income tax brackets for a specific year.
    
        Args:
            year: Tax year (defaults to current year if not specified)
            ctx: MCP context for logging and state management
    
        Returns:
            Dict: Dictionary containing the tax brackets and rates
        """
        try:
            # Set default year to current year if not specified
            if year is None:
                year = datetime.now().year
    
            await ctx.info(f"Retrieving tax brackets for year {year}")
    
            # Call the implementation from impots_scraper.py (lazy import)
            from french_tax_mcp.scrapers.impots_scraper import get_tax_brackets
            result = await get_tax_brackets(year)
            return result
        except Exception as e:
            await ctx.error(f"Failed to get tax brackets: {e}")
            return {
                "status": "error",
                "message": f"Error retrieving tax brackets: {str(e)}",
                "year": year,
            }
  • Core implementation of get_tax_brackets. Scrapes tax brackets from service-public.fr using MarkItDown, parses the markdown, and falls back to hardcoded data from constants.
    async def get_tax_brackets(year: Optional[int] = None) -> Dict:
        """Get income tax brackets using MarkItDown scraper with fallback to hardcoded data.
    
        Args:
            year: Tax year (defaults to current year)
    
        Returns:
            Dictionary containing the tax brackets and rates
        """
        try:
            # Try MarkItDown scraper first (more reliable)
            from markitdown import MarkItDown
            
            md = MarkItDown()
            url = "https://www.service-public.fr/particuliers/vosdroits/F1419"
            
            logger.info(f"Fetching tax brackets using MarkItDown from {url}")
            result = md.convert_url(url)
            brackets = _parse_brackets_from_markdown(result.text_content)
            
            if brackets:
                current_year = year or datetime.now().year
                logger.info(f"Successfully parsed {len(brackets)} tax brackets using MarkItDown")
                return {
                    "status": "success",
                    "data": {
                        "year": current_year,
                        "brackets": brackets
                    },
                    "source": "service-public.fr (MarkItDown)"
                }
            
            # Fallback to hardcoded data
            logger.warning("MarkItDown parsing failed, using hardcoded tax brackets")
            return _get_fallback_tax_brackets(year)
            
        except Exception as e:
            logger.error(f"MarkItDown scraping failed: {e}")
            return _get_fallback_tax_brackets(year)
  • Helper function providing hardcoded fallback tax brackets from constants.TAX_BRACKETS.
    def _get_fallback_tax_brackets(year: Optional[int] = None) -> Dict:
        """Get hardcoded tax brackets as fallback."""
        from french_tax_mcp.constants import TAX_BRACKETS
        
        current_year = year or datetime.now().year
        brackets = TAX_BRACKETS.get(current_year, TAX_BRACKETS.get(2024, []))
        
        return {
            "status": "success",
            "data": {
                "year": current_year,
                "brackets": brackets
            },
            "source": "hardcoded (fallback)"
        }
  • Helper function to parse tax bracket data from scraped markdown content using regex.
    def _parse_brackets_from_markdown(content: str) -> List[Dict]:
        """Parse tax brackets from markdown content."""
        brackets = []
        
        # Pattern for tax bracket tables: "De X € à Y € | Z%"
        pattern = r'(\d+(?:\s\d+)*)\s*€.*?(\d+(?:\s\d+)*)\s*€.*?(\d+(?:,\d+)?)\s*%'
        matches = re.findall(pattern, content)
        
        for match in matches:
            try:
                min_str, max_str, rate_str = match
                min_amount = int(min_str.replace(' ', ''))
                max_amount = int(max_str.replace(' ', '')) if max_str != '∞' else None
                rate = float(rate_str.replace(',', '.'))
                
                brackets.append({
                    "min": min_amount,
                    "max": max_amount,
                    "rate": rate
                })
            except ValueError:
                continue
        
        return brackets[:5]  # Limit to reasonable number

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