Skip to main content
Glama
ivossos

FCCS MCP Agentic Server

by ivossos

generate_report_script

Create Python script templates for custom FCCS reporting to query financial data by accounts, entities, periods, years, and scenarios, generating HTML, PDF, or CSV outputs.

Instructions

Generate a Python script template for custom FCCS reporting / Gerar script Python para relatorio customizado

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
script_nameYesName of the script file (without .py extension)
report_typeNoType of report (default: HTML)
descriptionNoDescription of what the report does
accountsNoList of account names to query
entitiesNoList of entity names to query
periodsNoList of periods to query (e.g., ['Jan', 'Feb', 'Dec'])
yearsNoList of years to query (e.g., ['FY24', 'FY25'])
scenariosNoList of scenarios to query (e.g., ['Actual', 'Budget'])

Implementation Reference

  • Async handler function registered for the tool, which delegates to the script generator function.
    async def generate_report_script(
        script_name: str,
        report_type: str = "HTML",
        description: str = "Custom FCCS report",
        accounts: Optional[list[str]] = None,
        entities: Optional[list[str]] = None,
        periods: Optional[list[str]] = None,
        years: Optional[list[str]] = None,
        scenarios: Optional[list[str]] = None
    ) -> dict[str, Any]:
        """Generate a Python script template for custom FCCS reporting / Gerar script Python para relatorio customizado.
    
        Args:
            script_name: Name of the script file (without .py extension).
            report_type: Type of report - HTML, PDF, or CSV (default: HTML).
            description: Description of what the report does.
            accounts: List of account names to query.
            entities: List of entity names to query.
            periods: List of periods to query (e.g., ['Jan', 'Feb', 'Dec']).
            years: List of years to query (e.g., ['FY24', 'FY25']).
            scenarios: List of scenarios to query (e.g., ['Actual', 'Budget']).
    
        Returns:
            dict: Path to generated script and summary.
        """
        return _generate_report_script(
            script_name=script_name,
            report_type=report_type,
            description=description,
            accounts=accounts,
            entities=entities,
            periods=periods,
            years=years,
            scenarios=scenarios
        )
  • Core implementation that generates a complete Python script template for running FCCS reports, including data collection, HTML generation, etc.
    def generate_report_script(
        script_name: str,
        report_type: str = "HTML",
        description: str = "Custom FCCS report",
        accounts: Optional[list[str]] = None,
        entities: Optional[list[str]] = None,
        periods: Optional[list[str]] = None,
        years: Optional[list[str]] = None,
        scenarios: Optional[list[str]] = None
    ) -> dict[str, Any]:
        """Generate a Python script template for custom FCCS reporting.
        
        Args:
            script_name: Name of the script file (without .py extension).
            report_type: Type of report - HTML, PDF, or CSV (default: HTML).
            description: Description of what the report does.
            accounts: List of account names to query.
            entities: List of entity names to query.
            periods: List of periods to query (e.g., ['Jan', 'Feb', 'Dec']).
            years: List of years to query (e.g., ['FY24', 'FY25']).
            scenarios: List of scenarios to query (e.g., ['Actual', 'Budget']).
        
        Returns:
            dict: Path to generated script and summary.
        """
        try:
            # Ensure script name ends with .py
            if not script_name.endswith('.py'):
                script_name = f"{script_name}.py"
            
            # Default values
            accounts = accounts or ["FCCS_Net Income"]
            entities = entities or ["FCCS_Total Geography"]
            periods = periods or ["Dec"]
            years = years or ["FY25"]
            scenarios = scenarios or ["Actual"]
            
            script_base_name = script_name.replace('.py', '')
            
            # Build script content using string concatenation to avoid f-string nesting issues
            script_lines = [
                f'"""Generate {description}."""',
                '',
                'import asyncio',
                'import sys',
                'from pathlib import Path',
                'from datetime import datetime',
                'from typing import Optional, Dict, List',
                '',
                '# Add parent directory to path',
                'sys.path.insert(0, str(Path(__file__).parent.parent))',
                '',
                'from fccs_agent.config import load_config',
                'from fccs_agent.agent import initialize_agent, close_agent',
                'from fccs_agent.tools.data import smart_retrieve',
                'from fccs_agent.utils.cache import load_members_from_cache',
                '',
                '',
                'async def get_account_value(',
                '    account: str,',
                '    entity: str,',
                '    period: str,',
                '    year: str,',
                '    scenario: str = "Actual"',
                ') -> Optional[float]:',
                '    """Get account value for specific dimensions."""',
                '    try:',
                '        result = await smart_retrieve(',
                '            account=account,',
                '            entity=entity,',
                '            period=period,',
                '            years=year,',
                '            scenario=scenario',
                '        )',
                '        if result.get("status") == "success":',
                '            data = result.get("data", {})',
                '            rows = data.get("rows", [])',
                '            if rows and rows[0].get("data"):',
                '                value = rows[0]["data"][0]',
                '                return float(value) if value is not None else None',
                '    except Exception as e:',
                '        print(f"[ERROR] Failed to get {account} for {entity}: {e}")',
                '    return None',
                '',
                '',
                'async def collect_data() -> Dict:',
                '    """Collect data for the report."""',
                '    print("Collecting data...")',
                '    data = {}',
                '    ',
                f'    accounts = {repr(accounts)}',
                f'    entities = {repr(entities)}',
                f'    periods = {repr(periods)}',
                f'    years = {repr(years)}',
                f'    scenarios = {repr(scenarios)}',
                '    ',
                '    for account in accounts:',
                '        for entity in entities:',
                '            for period in periods:',
                '                for year in years:',
                '                    for scenario in scenarios:',
                '                        key = f"{account}|{entity}|{period}|{year}|{scenario}"',
                '                        value = await get_account_value(account, entity, period, year, scenario)',
                '                        data[key] = {',
                '                            "account": account,',
                '                            "entity": entity,',
                '                            "period": period,',
                '                            "year": year,',
                '                            "scenario": scenario,',
                '                            "value": value',
                '                        }',
                '                        if value is not None:',
                '                            print(f"[OK] {account} - {entity} - {period} {year} ({scenario}): ${value:,.2f}")',
                '    ',
                '    return data',
                '',
                '',
                'def generate_html_report(data: Dict) -> str:',
                '    """Generate HTML report."""',
                '    timestamp = datetime.now().strftime(\'%Y%m%d_%H%M%S\')',
                f'    filename = f"{script_base_name}_{{timestamp}}.html"',
                '    ',
                '    # Build HTML content',
                '    html_parts = ["""<!DOCTYPE html>',
                '<html>',
                '<head>',
                '    <meta charset="UTF-8">',
                f'    <title>{description}</title>',
                '    <style>',
                '        body { font-family: Arial, sans-serif; margin: 40px; background-color: #f5f5f5; }',
                '        .container { background-color: white; padding: 40px; box-shadow: 0 0 10px rgba(0,0,0,0.1); }',
                '        h1 { color: #1f4788; border-bottom: 3px solid #1f4788; padding-bottom: 10px; }',
                '        h2 { color: #2c5aa0; margin-top: 30px; }',
                '        table { width: 100%; border-collapse: collapse; margin: 20px 0; }',
                '        th { background-color: #1f4788; color: white; padding: 12px; text-align: left; }',
                '        td { padding: 10px; border: 1px solid #ddd; }',
                '        tr:nth-child(even) { background-color: #f9f9f9; }',
                '        .positive { color: #2d5016; font-weight: bold; }',
                '        .negative { color: #8b0000; font-weight: bold; }',
                '        .footer { margin-top: 40px; padding-top: 20px; border-top: 1px solid #ddd; color: #666; font-size: 12px; }',
                '    </style>',
                '</head>',
                '<body>',
                '    <div class="container">',
                f'        <h1>{description}</h1>',
                '        <p><strong>Generated:</strong> {datetime.now().strftime(\'%B %d, %Y %H:%M:%S\')}</p>',
                '        <h2>Report Data</h2>',
                '        <table>',
                '            <thead>',
                '                <tr>',
                '                    <th>Account</th>',
                '                    <th>Entity</th>',
                '                    <th>Period</th>',
                '                    <th>Year</th>',
                '                    <th>Scenario</th>',
                '                    <th style="text-align: right;">Value ($)</th>',
                '                </tr>',
                '            </thead>',
                '            <tbody>',
                '"""]',
                '    ',
                '    # Add data rows',
                '    for key, item in data.items():',
                '        value = item.get("value")',
                '        value_class = "positive" if value and value >= 0 else "negative"',
                '        value_display = f"${value:,.2f}" if value is not None else "N/A"',
                '        html_parts.append(f"""',
                '                <tr>',
                '                    <td>{item[\'account\']}</td>',
                '                    <td>{item[\'entity\']}</td>',
                '                    <td>{item[\'period\']}</td>',
                '                    <td>{item[\'year\']}</td>',
                '                    <td>{item[\'scenario\']}</td>',
                '                    <td style="text-align: right;" class="{value_class}">{value_display}</td>',
                '                </tr>',
                '""")',
                '    ',
                '    html_parts.append("""',
                '            </tbody>',
                '        </table>',
                '        <div class="footer">',
                '            <p><strong>FCCS Custom Report</strong></p>',
                '            <p>Data from Oracle EPM Cloud Financial Consolidation and Close (FCCS)</p>',
                '            <p>Generated: {datetime.now().strftime(\'%Y-%m-%d %H:%M:%S\')}</p>',
                '        </div>',
                '    </div>',
                '</body>',
                '</html>',
                '""")',
                '    ',
                '    html_content = "".join(html_parts)',
                '    ',
                '    # Save file',
                '    filepath = Path(filename)',
                '    with open(filepath, "w", encoding="utf-8") as f:',
                '        f.write(html_content)',
                '    ',
                '    return str(filepath.absolute())',
                '',
                '',
                'async def generate_report():',
                '    """Main function to generate the report."""',
                '    print("=" * 80)',
                f'    print("GENERATING {description.upper()}")',
                '    print("=" * 80)',
                '    print()',
                '    ',
                '    try:',
                '        config = load_config()',
                '        await initialize_agent(config)',
                '        print("[OK] Connected to FCCS")',
                '        print()',
                '        ',
                '        # Collect data',
                '        data = await collect_data()',
                '        print()',
                '        print(f"[OK] Collected {len(data)} data points")',
                '        print()',
                '        ',
                '        # Generate report',
                '        print("Generating report...")',
                '        report_path = generate_html_report(data)',
                '        ',
                '        print()',
                '        print("=" * 80)',
                '        print(f"[SUCCESS] Report generated: {report_path}")',
                '        print("=" * 80)',
                '        print()',
                '        ',
                '        await close_agent()',
                '        ',
                '    except Exception as e:',
                '        print(f"\\n[ERROR] {e}")',
                '        import traceback',
                '        traceback.print_exc()',
                '        sys.exit(1)',
                '',
                '',
                'if __name__ == "__main__":',
                '    asyncio.run(generate_report())',
                ''
            ]
            
            script_content = '\n'.join(script_lines)
            
            # Save script to scripts directory
            scripts_dir = Path("scripts")
            scripts_dir.mkdir(exist_ok=True)
            
            script_path = scripts_dir / script_name
            with open(script_path, "w", encoding="utf-8") as f:
                f.write(script_content)
            
            return {
                "status": "success",
                "data": {
                    "script_path": str(script_path.absolute()),
                    "filename": script_name,
                    "message": "Python script template generated successfully",
                    "note": f"Script saved to {script_path}. Run with: python {script_path}"
                }
            }
            
        except Exception as e:
            return {
                "status": "error",
                "error": f"Failed to generate script: {str(e)}"
            }
  • Input schema definition for the tool in TOOL_DEFINITIONS.
        "name": "generate_report_script",
        "description": "Generate a Python script template for custom FCCS reporting / Gerar script Python para relatorio customizado",
        "inputSchema": {
            "type": "object",
            "properties": {
                "script_name": {
                    "type": "string",
                    "description": "Name of the script file (without .py extension)",
                },
                "report_type": {
                    "type": "string",
                    "enum": ["HTML", "PDF", "CSV"],
                    "description": "Type of report (default: HTML)",
                },
                "description": {
                    "type": "string",
                    "description": "Description of what the report does",
                },
                "accounts": {
                    "type": "array",
                    "items": {"type": "string"},
                    "description": "List of account names to query",
                },
                "entities": {
                    "type": "array",
                    "items": {"type": "string"},
                    "description": "List of entity names to query",
                },
                "periods": {
                    "type": "array",
                    "items": {"type": "string"},
                    "description": "List of periods to query (e.g., ['Jan', 'Feb', 'Dec'])",
                },
                "years": {
                    "type": "array",
                    "items": {"type": "string"},
                    "description": "List of years to query (e.g., ['FY24', 'FY25'])",
                },
                "scenarios": {
                    "type": "array",
                    "items": {"type": "string"},
                    "description": "List of scenarios to query (e.g., ['Actual', 'Budget'])",
                },
            },
            "required": ["script_name"],
        },
    },
  • Tool handler registration in the central TOOL_HANDLERS dictionary.
    "generate_report_script": reports.generate_report_script,

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/ivossos/fccs-mcp-ag-server'

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