get_tax_info_from_web
Retrieve official French tax information from government websites like impots.gouv.fr for specific tax topics and years.
Instructions
Get tax information from official French government websites like impots.gouv.fr, service-public.fr, or legifrance.gouv.fr
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| tax_topic | Yes | ||
| year | No |
Implementation Reference
- french_tax_mcp/server.py:83-86 (registration)Registration of the 'get_tax_info_from_web' tool using the @mcp.tool decorator.@mcp.tool( name="get_tax_info_from_web", description="Get tax information from official French government websites like impots.gouv.fr, service-public.fr, or legifrance.gouv.fr", )
- french_tax_mcp/server.py:87-130 (handler)The primary handler function that executes the tool logic. It maps the tax topic to specific scrapers (currently only tax_brackets) or returns an error for unimplemented topics.async def get_tax_info_from_web(tax_topic: str, ctx: Context, year: Optional[int] = None) -> Optional[Dict]: """Get tax information from official French government websites. Args: tax_topic: The tax topic to search for (e.g., 'tranches_impot', 'pinel', 'lmnp') year: Optional tax year (defaults to current year if not specified) ctx: MCP context for logging and state management Returns: Dict: Dictionary containing the tax information retrieved from the website """ try: # This is a placeholder implementation # The actual implementation will be more complex and will use specialized scrapers # Set default year to current year if not specified if year is None: year = datetime.now().year await ctx.info(f"Retrieving information about {tax_topic} for year {year}") # Map topic to appropriate scraper if tax_topic.lower() in ["tranches_impot", "baremes", "tax_brackets"]: # Use tax brackets scraper (lazy import) from french_tax_mcp.scrapers.impots_scraper import get_tax_brackets result = await get_tax_brackets(year) return result else: # Generic response for now return { "status": "error", "message": f"Information for {tax_topic} not yet implemented", "year": year, } except Exception as e: await ctx.error(f"Failed to get tax information from web: {e}") return { "status": "error", "message": f"Error retrieving information: {str(e)}", "topic": tax_topic, "year": year, }
- Supporting function imported and called by the handler for 'tranches_impot' topics. Uses MarkItDown scraper with fallback to hardcoded data.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) 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 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)" }