Skip to main content
Glama
norman-finance

Norman Finance MCP Server

Official

generate_finanzamt_preview

Generate a PDF preview of a tax report for the Finanzamt. Verify the preview before submission using the provided file link. Includes line items, totals, and a summary based on the report data.

Instructions

Generate a test Finanzamt preview for a tax report.

Args:
    report_id: Public ID of the tax report
    
Returns:
    Generate a PDF preview of the tax report. 
    Always suggest to check the preview before sending it to the Finanzamt.
    Always include the path to the generated PDF file as a link to open the file from local file system.
    Get the report data from @get_tax_report and show line items and totals.
      You could add short summary based on the report data.
    Ask follow up question to file the tax report to the Finanzamt @submit_tax_report. Don't send the report to the Finanzamt without the user confirmation.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
report_idYes

Implementation Reference

  • Main handler function for the generate_finanzamt_preview tool. Calls the Norman API to generate a PDF preview of a tax report, converts the first page to a resized PNG image, and returns it as an MCP Image object.
    @mcp.tool()
    async def generate_finanzamt_preview(
        ctx: Context,
        report_id: str = Field(description="Public ID of the tax report to generate a preview for")
    ) -> Image:
        """
        Generate a test Finanzamt preview for a tax report and return it as an image.
        
        Args:
            report_id: Public ID of the tax report
            
        Returns:
            The tax report preview as an image in PNG format
        """
        api = ctx.request_context.lifespan_context["api"]
        
        # Validate report_id
        if not report_id or not isinstance(report_id, str) or not report_id.strip():
            raise ValueError("Invalid report ID")
        
        preview_url = urljoin(
            config.api_base_url,
            f"api/v1/taxes/reports/{report_id}/generate-preview/"
        )
    
        try:
            response = requests.post(
                preview_url,
                headers={"Authorization": f"Bearer {api.access_token}"},
                timeout=config.NORMAN_API_TIMEOUT
            )
            response.raise_for_status()
            
            # The response contains raw PDF bytes
            if isinstance(response.content, bytes) and len(response.content) > 0:
                # Convert PDF to image
                images = convert_from_bytes(response.content, dpi=150)
                
                # Get the first page as PIL Image
                first_page = images[0]
                
                # Convert to RGB and resize if needed to keep file size manageable
                first_page = first_page.convert('RGB')
                
                # Calculate new dimensions while maintaining aspect ratio
                width, height = first_page.size
                max_dim = 1000
                if width > max_dim or height > max_dim:
                    if width > height:
                        new_width = max_dim
                        new_height = int(height * (max_dim / width))
                    else:
                        new_height = max_dim
                        new_width = int(width * (max_dim / height))
                    first_page = first_page.resize((new_width, new_height), PILImage.LANCZOS)
                
                # Save as PNG to bytes buffer
                buffer = io.BytesIO()
                first_page.save(buffer, format="PNG", optimize=True)
                buffer.seek(0)
                
                # Return as Image
                return Image(data=buffer.getvalue(), format="png")
            else:
                raise ValueError("Preview generation failed or invalid response format")
        except requests.exceptions.RequestException as e:
            logger.error(f"Failed to generate tax report preview: {str(e)}")
            if hasattr(e, 'response') and e.response is not None:
                logger.error(f"Response: {e.response.text}")
            raise ValueError(f"Failed to generate tax report preview: {str(e)}")
        except Exception as e:
            logger.error(f"Error generating tax report preview: {str(e)}")
            raise ValueError(f"Error generating tax report preview: {str(e)}")
  • Calls register_tax_tools(server) as part of the overall tool registration in the MCP server setup within create_app function.
    register_client_tools(server)
    register_invoice_tools(server)
    register_tax_tools(server)
    register_transaction_tools(server)
    register_document_tools(server)
    register_company_tools(server)
    register_prompts(server)
    register_resources(server)
  • Input schema: report_id (str, required, description provided). Output: Image type from mcp.types.
    async def generate_finanzamt_preview(
        ctx: Context,
        report_id: str = Field(description="Public ID of the tax report to generate a preview for")
    ) -> Image:
  • Function that registers all tax tools, including generate_finanzamt_preview, by defining them with @mcp.tool() decorators inside it.
    def register_tax_tools(mcp):
        """Register all tax-related tools with the MCP server."""

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/norman-finance/norman-mcp-server'

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