Skip to main content
Glama

get_calendar_summary

Summarize new-issue municipal bond calendar by grouping dimension. Returns count and total par per group sorted by par descending for quick top-level analysis.

Instructions

Aggregate the new-issue calendar by a grouping dimension. Returns count and total par per group, sorted by par descending. Perfect for slides: 'NY leads this week at $1.2B across 8 deals; hospitals and schools dominate the sector mix.'

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
group_byNostate
top_nNo

Implementation Reference

  • Tool registration and schema for get_calendar_summary as part of list_tools(). Defines input properties: group_by (enum of state/sector/tax_status/bank_qualified/sale_method, defaults to state) and top_n (integer, defaults to 10).
    Tool(
        name="get_calendar_summary",
        description=(
            "Aggregate the new-issue calendar by a grouping dimension. Returns "
            "count and total par per group, sorted by par descending. Perfect "
            "for slides: 'NY leads this week at $1.2B across 8 deals; hospitals "
            "and schools dominate the sector mix.'"
        ),
        inputSchema={
            "type": "object",
            "properties": {
                "group_by": {
                    "type": "string",
                    "enum": ["state", "sector", "tax_status", "bank_qualified", "sale_method"],
                    "default": "state",
                },
                "top_n": {"type": "integer", "default": 10},
            },
        },
    ),
  • Handler implementation inside _dispatch(): fetches the full calendar via fetch_calendar(), groups rows by the specified dimension (state/sector/tax_status/bank_qualified/sale_method), aggregates count and total_par per group, sorts by par descending, and returns top_n groups.
    if name == "get_calendar_summary":
        cal = await fetch_calendar()
        rows = cal["all"]
        group_by = args.get("group_by", "state")
        key_map = {
            "state": lambda r: r.get("State", "?"),
            "sector": lambda r: r.get("_sector", "?"),
            "tax_status": lambda r: r.get("Tax Status", "?"),
            "bank_qualified": lambda r: r.get("Bank Qualified", "?"),
            "sale_method": lambda r: "—see sale_method split in pulse—",
        }
        keyer = key_map.get(group_by, key_map["state"])
        agg: dict[str, dict[str, Any]] = {}
        for r in rows:
            k = keyer(r)
            slot = agg.setdefault(k, {"count": 0, "total_par": 0.0})
            slot["count"] += 1
            slot["total_par"] += float(r.get("_principal_num", "0") or 0)
        out = sorted(
            [
                {"group": k, "count": v["count"],
                 "total_par_usd": v["total_par"],
                 "total_par_formatted": _fmt_amount(v["total_par"])}
                for k, v in agg.items()
            ],
            key=lambda x: x["total_par_usd"], reverse=True,
        )[: int(args.get("top_n", 10))]
        return {"group_by": group_by, "groups": out, "total_deals": len(rows)}
  • server.py:422-755 (registration)
    Tool is registered inside the list_tools() handler of the MCP server. Returned as part of the Tool list from @server.list_tools().
        Tool(
            name="get_calendar_summary",
            description=(
                "Aggregate the new-issue calendar by a grouping dimension. Returns "
                "count and total par per group, sorted by par descending. Perfect "
                "for slides: 'NY leads this week at $1.2B across 8 deals; hospitals "
                "and schools dominate the sector mix.'"
            ),
            inputSchema={
                "type": "object",
                "properties": {
                    "group_by": {
                        "type": "string",
                        "enum": ["state", "sector", "tax_status", "bank_qualified", "sale_method"],
                        "default": "state",
                    },
                    "top_n": {"type": "integer", "default": 10},
                },
            },
        ),
        Tool(
            name="classify_sector",
            description=(
                "Classify a muni bond issue description into a sector using the same "
                "keyword rules the calendar tool uses. Useful to show Marciano the "
                "classifier is deterministic, not a black box."
            ),
            inputSchema={
                "type": "object",
                "properties": {
                    "description": {"type": "string"},
                },
                "required": ["description"],
            },
        ),
        Tool(
            name="get_recent_sales",
            description=(
                "Most actively traded muni CUSIPs right now from EMMA's "
                "/TradeData grid — description, coupon, maturity, high/low "
                "price & yield, trade count, total trade amount, and a link "
                "to each security's EMMA detail page. Use this to gauge "
                "live-market color for comparable deals."
            ),
            inputSchema={
                "type": "object",
                "properties": {"limit": {"type": "integer", "default": 25}},
            },
        ),
        Tool(
            name="get_recent_preliminary_statements",
            description=(
                "Recent Preliminary Official Statements (POS) — pre-pricing "
                "documents filed right before a deal comes to market. This "
                "is the leading edge of the new-issue pipeline. Each row "
                "links to the filing PDF and the issuer page."
            ),
            inputSchema={
                "type": "object",
                "properties": {
                    "limit": {"type": "integer", "default": 25},
                    "issuer_contains": {
                        "type": "string",
                        "description": "Filter issuer (auto-expanded for abbreviations)",
                    },
                },
            },
        ),
        Tool(
            name="get_recent_annual_reports",
            description=(
                "Recent issuer annual financial reports filed as continuing "
                "disclosures — the source for post-issuance updated obligor "
                "financials (revenue, operating income, debt-service coverage)."
            ),
            inputSchema={
                "type": "object",
                "properties": {
                    "limit": {"type": "integer", "default": 25},
                    "issuer_contains": {"type": "string"},
                },
            },
        ),
        Tool(
            name="search_issuers_by_state",
            description=(
                "List municipal issuers for a state (all 9k+ rows, not just "
                "page 1) and filter by name. Feed the issuer_id into "
                "get_issuer_outstanding_bonds or get_issuer_profile to drill "
                "down. IMPORTANT: the `contains` filter auto-expands your "
                "query into every EMMA abbreviation variant (hospital→HOSP, "
                "authority→AUTH, children→CHLDN, senior→SR, community→CMNTY, "
                "etc.) — always search in natural English, never in the "
                "telegraphic form. For hospital/senior-living/charter-school "
                "obligors, search the CONDUIT, not the obligor: e.g. CHLA "
                "bonds are filed under CALIFORNIA PUB FIN AUTH HEALTH CARE "
                "FACS REV — found by searching `contains=\"health care "
                "facilities\"`. See the emma://rules/EMMA_ABBREVIATIONS.md "
                "resource for the full variant map and conduit cheat sheet."
            ),
            inputSchema={
                "type": "object",
                "properties": {
                    "state": {"type": "string", "description": "2-letter state code"},
                    "contains": {
                        "type": "string",
                        "description": "Case-insensitive name filter",
                    },
                    "limit": {"type": "integer", "default": 50},
                },
                "required": ["state"],
            },
        ),
        Tool(
            name="get_issuer_outstanding_bonds",
            description=(
                "List an issuer's outstanding bond issues from their EMMA profile — "
                "issue description, dated date, maturity range. The most reliable "
                "drill-down on any issuer."
            ),
            inputSchema={
                "type": "object",
                "properties": {
                    "issuer_id": {
                        "type": "string",
                        "description": "EMMA issuer GUID (from search_issuers_by_state)",
                    },
                    "issuer_url": {
                        "type": "string",
                        "description": "Any EMMA issuer URL (from emma_quick_search; can be a QuickSearch/Navigate redirect)",
                    },
                    "limit": {"type": "integer", "default": 25},
                },
            },
        ),
        Tool(
            name="get_issuer_profile",
            description=(
                "Full issuer profile: name, outstanding issues, attempted fetch of "
                "Official Statements, Pre-Sale docs, Continuing Disclosures, and "
                "Recent Trades. EMMA loads the latter via tab interaction; empty "
                "sections are reported honestly rather than guessed at."
            ),
            inputSchema={
                "type": "object",
                "properties": {
                    "issuer_id": {"type": "string", "description": "EMMA issuer GUID"},
                    "issuer_url": {
                        "type": "string",
                        "description": "Any EMMA issuer URL (from emma_quick_search)",
                    },
                },
            },
        ),
        Tool(
            name="get_security_details",
            description=(
                "Pull security-level fields for a 9-digit CUSIP: issuer, coupon, "
                "maturity, dated date, par. CUSIPs that are redeemed / matured / "
                "pre-refunded return a clear 'no records' response — try a "
                "currently-outstanding CUSIP from get_issuer_outstanding_bonds."
            ),
            inputSchema={
                "type": "object",
                "properties": {"cusip": {"type": "string"}},
                "required": ["cusip"],
            },
        ),
        Tool(
            name="emma_quick_search",
            description=(
                "**START HERE** when the user names a specific obligor, issuer, "
                "or keyword. Uses EMMA's global quick search (the same box in "
                "EMMA's header) which indexes BOTH long-form and obligor-in-"
                "parens names — so 'Childrens Hospital' finds "
                "'CALIFORNIA HEALTH FACILITIES FINANCING AUTHORITY (LUCILE "
                "SALTER PACKARD CHILDRENS HOSPITAL AT STANFORD)' without "
                "needing the conduit-issuer chase. Returns matching issuers "
                "(across all states) and matching specific issues. Each "
                "issuer row has a URL you can feed into "
                "get_issuer_outstanding_bonds."
            ),
            inputSchema={
                "type": "object",
                "properties": {
                    "query": {
                        "type": "string",
                        "description": "Natural-language search: obligor name, issuer name, CUSIP, state, or keyword",
                    },
                    "limit": {"type": "integer", "default": 25},
                },
                "required": ["query"],
            },
        ),
        Tool(
            name="get_issue_details",
            description=(
                "Full IssueView page for a given IssueView URL — per-CUSIP "
                "detail (par at issuance, coupon, maturity, initial offering "
                "price, current LT rating, price, yield, and ratings from "
                "Fitch, KBRA, Moody's, S&P), the Official Statement PDF link, "
                "and recent trade activity. This is the single most "
                "information-dense page on EMMA for modeling a specific deal."
            ),
            inputSchema={
                "type": "object",
                "properties": {
                    "issue_url": {
                        "type": "string",
                        "description": "EMMA IssueView URL (https://emma.msrb.org/IssueView/Details/P#####)",
                    }
                },
                "required": ["issue_url"],
            },
        ),
        Tool(
            name="get_recent_continuing_disclosures",
            description=(
                "Recent continuing-disclosure filings (audited financials, "
                "material events, rating changes, quarterly operating data). "
                "Each row has a direct link to the filed PDF. This is where "
                "post-issuance credit work lives — ratings today, not at "
                "issuance; updated obligor financials for modeling."
            ),
            inputSchema={
                "type": "object",
                "properties": {
                    "limit": {"type": "integer", "default": 50},
                    "disclosure_contains": {
                        "type": "string",
                        "description": "Filter disclosure description (auto-expanded for EMMA abbreviations)",
                    },
                    "issuer_contains": {
                        "type": "string",
                        "description": "Filter issuer name (auto-expanded for EMMA abbreviations)",
                    },
                },
            },
        ),
        Tool(
            name="extract_pdf_text",
            description=(
                "Extract text from a previously-downloaded OS PDF so you can "
                "pull financials, debt service tables, obligor financials, "
                "rating language, bond purpose, sources-and-uses, etc. into "
                "an Excel model. Works best on OS PDFs saved via "
                "download_official_statement."
            ),
            inputSchema={
                "type": "object",
                "properties": {
                    "path": {
                        "type": "string",
                        "description": "Absolute path to the saved PDF",
                    },
                    "pages": {
                        "type": "string",
                        "description": "Page range like '1-20' or '45,46,47' (optional — default: all)",
                    },
                    "max_chars": {
                        "type": "integer",
                        "default": 120000,
                        "description": "Cap on returned characters to protect context",
                    },
                },
                "required": ["path"],
            },
        ),
        Tool(
            name="get_recent_official_statements",
            description=(
                "List the EMMA Recent Official Statements grid — the 10 most "
                "recently filed OS documents across the muni market, with issuer, "
                "series, dated date, and a link back to the issuer. Feed a row's "
                "issue_url into get_official_statement_pdf to grab the PDF URL."
            ),
            inputSchema={
                "type": "object",
                "properties": {"limit": {"type": "integer", "default": 10}},
            },
        ),
        Tool(
            name="get_official_statement_pdf",
            description=(
                "Given an EMMA IssueView/Details/P##### URL, return the direct "
                "Official Statement PDF URL (and issue title). This is the "
                "canonical primary-source OS — use it before quoting coupons, "
                "maturities, or call features."
            ),
            inputSchema={
                "type": "object",
                "properties": {
                    "issue_url": {
                        "type": "string",
                        "description": "EMMA IssueView URL (https://emma.msrb.org/IssueView/Details/P#####)",
                    }
                },
                "required": ["issue_url"],
            },
        ),
        Tool(
            name="download_official_statement",
            description=(
                "Download an Official Statement PDF from EMMA to local disk. "
                "Pass either a direct PDF URL or an IssueView URL (the tool will "
                "resolve it to the PDF link). Returns file path + size. Use when "
                "the banker wants the OS to attach to a deck or read offline."
            ),
            inputSchema={
                "type": "object",
                "properties": {
                    "url": {
                        "type": "string",
                        "description": "Either a direct .pdf URL or an IssueView/Details/P##### URL",
                    },
                    "filename": {
                        "type": "string",
                        "description": "Optional filename (without extension)",
                    },
                },
                "required": ["url"],
            },
        ),
        Tool(
            name="get_market_pulse",
            description=(
                "Snapshot of this week's muni primary market: total par, deal count, "
                "top 5 states, top 5 sectors, top 5 lead managers if available, "
                "competitive-vs-negotiated split. Built entirely from the live "
                "new-issue calendar — one call, boardroom-ready."
            ),
            inputSchema={"type": "object", "properties": {}},
        ),
    ]
  • Helper function fetch_calendar() that loads the new-issue calendar from EMMA via headless browser, enriches rows with sector classification and parsed principal amount (_principal_num), and caches the result. It is called by get_calendar_summary to get the rows to aggregate.
    async def fetch_calendar() -> dict[str, list[dict[str, str]]]:
        """Fetch the full new-issue calendar and return structured rows from each
        subtable (all / competitive / negotiated / recent sales). Enriches every
        row with inferred sector."""
        cache_key = "_calendar"
        if (cached := cache_get(cache_key)) is not None:
            return cached
    
        tables = await load_tables(f"{EMMA_BASE}/ToolsAndResources/NewIssueCalendar")
    
        def _pull(table_id: str) -> list[dict[str, str]]:
            t = tables.get(table_id, {})
            rows = structured(t.get("header", []), t.get("rows", []))
            for r in rows:
                desc = r.get("Issuer Name/Issue Description", "")
                r["_sector"] = classify_sector(desc)
                r["_principal_num"] = str(_parse_amount(r.get("Principal Amount ($)", "")))
            return rows
    
        payload = {
            "all": _pull("tblAllUpcomingIssues"),
            "competitive": _pull("tblCompetitiveUpcomingIssues"),
            "negotiated": _pull("tblNegotiatedUpcomingIssues"),
            "recent_sales": _pull("tblRecentSales"),
        }
        cache_put(cache_key, payload)
        return payload
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the burden. It describes the aggregation behavior, return fields (count and total par), and sorting order. It does not cover edge cases or performance, but the main behavior is transparent.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is extremely concise with two sentences and a quote. It front-loads the purpose and provides a concrete example, earning every word. No wasted content.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema, the description adequately explains return structure (count, total par). It covers the tool's purpose. However, it lacks details on how top_n affects results, which is a minor gap. Overall, it's mostly complete for a simple summary tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It mentions 'grouping dimension' but does not explain the group_by parameter or top_n. The enum values are listed in schema but not described, and top_n is entirely omitted. This is a significant gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it aggregates the new-issue calendar by a grouping dimension and returns count and total par per group, sorted by par descending. It distinguishes from sibling tools like get_new_issue_calendar by focusing on summary.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description includes a concrete use case ('Perfect for slides'), providing clear context for when to use this tool. It does not explicitly exclude alternatives or mention when not to use, but the example gives sufficient guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

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/ark9164-create/blaylock-emma-mcp'

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