Skip to main content
Glama
henrysouchien

edgar-mcp

get_filing_sections

Extract specific narrative sections and tables from SEC 10-K or 10-Q filings for financial analysis and research.

Instructions

Parse qualitative sections from SEC 10-K or 10-Q filings and return narrative/tables with metadata.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
tickerYes
yearYes
quarterYes
sectionsNo
formatNosummary
max_wordsNo
tables_onlyNo
outputNofile

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Implementation Reference

  • _proxy_get_filing_sections: Core handler implementation that proxies requests to remote EDGAR API, processes sections data, handles tables_only filtering, manages file output mode, and writes markdown files when output='file'.
    def _proxy_get_filing_sections(args: dict) -> dict:
        """Proxy filing sections to remote API, with local file-write for output='file'."""
        output_mode = args.get("output", "file")
        sections_list = args.get("sections")
        tables_only = args.get("tables_only", False)
    
        # Build remote API params
        params = {
            "ticker": args["ticker"],
            "year": args["year"],
            "quarter": args["quarter"],
            "format": args.get("format", "summary"),
        }
        if sections_list:
            params["sections"] = ",".join(sections_list)
    
        if output_mode == "file":
            # Fetch full untruncated text for file output
            params["format"] = "full"
            params["max_words"] = "none"
        else:
            max_words = args.get("max_words", 3000)
            params["max_words"] = str(max_words) if max_words is not None else "none"
    
        result = _call_api("/api/sections", params)
    
        if result.get("status") != "success":
            return result
    
        # Normalize section-level table counts for both inline and file modes.
        for section in result.get("sections", {}).values():
            if not isinstance(section, dict):
                continue
            tables = section.get("tables", []) or []
            nonempty_tables = [t for t in tables if (t or "").strip()]
            section["table_count"] = len(nonempty_tables)
        total_tables = sum(
            s.get("table_count", 0)
            for s in result.get("sections", {}).values()
            if isinstance(s, dict)
        )
        if not isinstance(result.get("metadata"), dict):
            result["metadata"] = {}
        result["metadata"]["total_table_count"] = total_tables
    
        # Strip narrative text if tables_only requested
        if tables_only:
            for section in result.get("sections", {}).values():
                if not isinstance(section, dict):
                    continue
                section.pop("text", None)
                table_words = 0
                for table in section.get("tables", []) or []:
                    table_text = (table or "").strip()
                    if table_text:
                        table_words += len(table_text.split())
                section["word_count"] = table_words
    
        if output_mode != "file":
            return result
    
        # Write sections to local markdown file
        ticker = _safe_filename_part(str(args["ticker"]).upper(), "ticker")
        year = int(args["year"])
        quarter = int(args["quarter"])
        filing_type = result.get("filing_type", "")
        sections_data = result.get("sections", {})
    
        FILE_OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
    
        # Build filename
        if sections_list:
            safe_keys = [_safe_filename_part(key, "section") for key in sorted(sections_list)]
            keys_part = "_".join(safe_keys)
            filename = f"{ticker}_{quarter}Q{year % 100:02d}_{keys_part}.md"
        else:
            filename = f"{ticker}_{quarter}Q{year % 100:02d}_sections.md"
        file_path = (FILE_OUTPUT_DIR / filename).resolve()
        root_dir = FILE_OUTPUT_DIR.resolve()
        if not file_path.is_relative_to(root_dir):
            return {"status": "error", "message": "Invalid output path"}
        if _deadline_expired(args):
            return {"status": "error", "message": "Request timed out before file output could be written"}
    
        # Build markdown
        total_words = sum(s.get("word_count", 0) for s in sections_data.values())
        section_keys = ", ".join(sections_data.keys()) if sections_data else "none"
        lines = [
            f"# {ticker} {filing_type} - Q{quarter} FY{year}: Filing Sections",
            f"> Sections: {section_keys} | Total words: {total_words:,} | Total tables: {total_tables:,}",
            "---",
        ]
        for section in sections_data.values():
            header = section.get("header", "Unknown Section")
            lines.append(f"## SECTION: {header}")
            lines.append(f"**Word count:** {section.get('word_count', 0):,}")
            lines.append(f"**Table count:** {section.get('table_count', 0):,}")
            if not tables_only:
                text = section.get("text", "").strip()
                if text:
                    lines.append(text)
            tables = section.get("tables", [])
            if tables:
                lines.append("### TABLES")
                for table in tables:
                    table_text = (table or "").strip()
                    if table_text:
                        lines.append(table_text)
            lines.append("---")
        if lines and lines[-1] == "---":
            lines.pop()
    
        file_path.write_text("\n".join(lines).strip() + "\n", encoding="utf-8")
    
        # Return summary (no full text inline) + file_path
        summary_sections = {
            key: {
                "header": s.get("header"),
                "word_count": s.get("word_count", 0),
                "table_count": s.get("table_count", 0),
            }
            for key, s in sections_data.items()
        }
        return {
            "status": "success",
            "ticker": ticker,
            "year": year,
            "quarter": quarter,
            "filing_type": filing_type,
            "output": "file",
            "file_path": str(file_path.resolve()),
            "hint": "Use Read tool with file_path. Grep '^## SECTION:' for anchors.",
            "sections": summary_sections,
            "sections_found": list(sections_data.keys()),
            "metadata": {
                "total_word_count": total_words,
                "total_words": total_words,
                "total_table_count": total_tables,
                "section_count": len(sections_data),
            },
        }
  • get_filing_sections: Public MCP tool definition decorated with @mcp.tool() that exposes the filing sections API. Defines input parameters (ticker, year, quarter, sections, format, max_words, tables_only, output) and delegates to _run_tool_guarded.
    @mcp.tool()
    async def get_filing_sections(
        ticker: str,
        year: int,
        quarter: int,
        sections: list[str] | None = None,
        format: Literal["summary", "full"] = "summary",
        max_words: int | None = 3000,
        tables_only: bool = False,
        output: Literal["inline", "file"] = "file",
    ) -> dict:
        """
        Parse qualitative sections from SEC 10-K or 10-Q filings and return
        narrative/tables with metadata.
        """
        args = {
            "ticker": ticker,
            "year": year,
            "quarter": quarter,
            "format": format,
            "max_words": max_words,
            "tables_only": tables_only,
            "output": output,
        }
        if sections:
            args["sections"] = sections
        return await _run_tool_guarded("get_filing_sections", args)
  • Tool registration in _TOOL_DISPATCH and _TOOL_TIMEOUT dictionaries mapping 'get_filing_sections' to its handler function (_proxy_get_filing_sections) and timeout value (60 seconds).
    _TOOL_DISPATCH = {
        "get_filings": _proxy_get_filings,
        "get_financials": _proxy_get_financials,
        "get_metric": _proxy_get_metric,
        "list_metrics": _proxy_list_metrics,
        "search_metrics": _proxy_search_metrics,
        "get_filing_sections": _proxy_get_filing_sections,
    }
    
    _TOOL_TIMEOUT = {
        "get_filings": 30,
        "get_financials": 60,
        "get_metric": 30,
        "list_metrics": 45,
        "search_metrics": 45,
        "get_filing_sections": 60,
    }

Tool Definition Quality

Score is being calculated. Check back soon.

Install Server

Other Tools

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/henrysouchien/edgar-mcp'

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