Skip to main content
Glama

show_earnings

Fetch upcoming earnings for all holdings, or retrieve historical and upcoming earnings for a specific ticker.

Instructions

Fetch earnings calendar. Without a ticker, returns upcoming earnings for all held tickers. With a ticker, returns history + upcoming.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
tickerNoTicker symbol. Omit to get upcoming earnings for all holdings.
weeksNoLook-ahead window in weeks (default: 4)
historyNoInclude past quarters (only applies when ticker is provided)

Implementation Reference

  • Handler function for the show_earnings MCP tool. Fetches earnings calendar from Finnhub. With a ticker, returns history (optional) + upcoming earnings. Without a ticker, returns upcoming earnings for all held tickers in the portfolio.
    async ({ ticker, weeks, history }) => {
      const apiKey = getFinnhubKey();
      if (!apiKey)
        return err('Finnhub API key not configured. Run: firma config set finnhub-key <key>');
      try {
        const client = createFinnhubClient(apiKey);
        const today = toDateStr(new Date());
        const future = toDateStr(new Date(Date.now() + weeks * 7 * 86_400_000));
    
        if (ticker) {
          const from = history ? toDateStr(new Date(Date.now() - 365 * 86_400_000)) : today;
          const res = await client.getEarningsCalendar(from, future, ticker.toUpperCase());
          return ok((res.earningsCalendar ?? []).sort((a, b) => b.date.localeCompare(a.date)));
        }
    
        const db = getDb();
        const tickers = getActiveTickers(db.select().from(transactions).all());
    
        if (tickers.length === 0) return ok([]);
    
        const results = await Promise.all(
          tickers.map((t) =>
            client
              .getEarningsCalendar(today, future, t)
              .then((r) => r.earningsCalendar ?? [])
              .catch(() => []),
          ),
        );
        return ok(results.flat().sort((a, b) => a.date.localeCompare(b.date)));
      } catch (e) {
        return err(e instanceof Error ? e.message : 'Failed to fetch earnings');
      }
    },
  • Input schema for show_earnings: optional ticker string, weeks (1-52, default 4), and history boolean (default false) to include past quarters.
    {
      ticker: z
        .string()
        .optional()
        .describe('Ticker symbol. Omit to get upcoming earnings for all holdings.'),
      weeks: z
        .number()
        .int()
        .min(1)
        .max(52)
        .default(4)
        .describe('Look-ahead window in weeks (default: 4)'),
      history: z
        .boolean()
        .default(false)
        .describe('Include past quarters (only applies when ticker is provided)'),
    },
  • Registration of 'show_earnings' tool via server.tool() inside the registerStockTools function.
    server.tool(
      'show_earnings',
      'Fetch earnings calendar. Without a ticker, returns upcoming earnings for all held tickers. With a ticker, returns history + upcoming.',
      {
        ticker: z
          .string()
          .optional()
          .describe('Ticker symbol. Omit to get upcoming earnings for all holdings.'),
        weeks: z
          .number()
          .int()
          .min(1)
          .max(52)
          .default(4)
          .describe('Look-ahead window in weeks (default: 4)'),
        history: z
          .boolean()
          .default(false)
          .describe('Include past quarters (only applies when ticker is provided)'),
      },
      async ({ ticker, weeks, history }) => {
        const apiKey = getFinnhubKey();
        if (!apiKey)
          return err('Finnhub API key not configured. Run: firma config set finnhub-key <key>');
        try {
          const client = createFinnhubClient(apiKey);
          const today = toDateStr(new Date());
          const future = toDateStr(new Date(Date.now() + weeks * 7 * 86_400_000));
    
          if (ticker) {
            const from = history ? toDateStr(new Date(Date.now() - 365 * 86_400_000)) : today;
            const res = await client.getEarningsCalendar(from, future, ticker.toUpperCase());
            return ok((res.earningsCalendar ?? []).sort((a, b) => b.date.localeCompare(a.date)));
          }
    
          const db = getDb();
          const tickers = getActiveTickers(db.select().from(transactions).all());
    
          if (tickers.length === 0) return ok([]);
    
          const results = await Promise.all(
            tickers.map((t) =>
              client
                .getEarningsCalendar(today, future, t)
                .then((r) => r.earningsCalendar ?? [])
                .catch(() => []),
            ),
          );
          return ok(results.flat().sort((a, b) => a.date.localeCompare(b.date)));
        } catch (e) {
          return err(e instanceof Error ? e.message : 'Failed to fetch earnings');
        }
      },
    );
  • Import and invocation of registerStockTools from stock.ts where show_earnings is registered on the MCP server.
    import { registerStockTools } from './tools/stock.ts';
    import { registerPrompts } from './prompts.ts';
    
    const server = new McpServer(
      { name: 'firma', version: FIRMA_VERSION },
      { instructions: SERVER_INSTRUCTIONS },
    );
    
    registerPortfolioTools(server);
    registerReportTools(server);
    registerMutateTools(server);
    registerSnapshotTools(server);
    registerStockTools(server);
Behavior4/5

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

No annotations are provided, so the description carries full burden. It discloses conditional behavior based on ticker presence and explains the weeks and history parameters. However, it does not explicitly state that the operation is read-only, though this is implied by 'fetch'.

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?

Two sentences, front-loaded with the main purpose, followed by conditional details. Every word is necessary and efficient.

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

Completeness3/5

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

No output schema is provided, and the description omits details on what the return data looks like (e.g., dates, earnings values). For a fetch tool, this is a notable gap. The description covers parameter behavior well but lacks output structure.

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

Parameters4/5

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

Schema description coverage is 100%, so baseline is 3. The description adds value by explaining the conditional behavior of ticker omission and constraints on history (only with ticker). This enhances understanding beyond the schema.

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 'Fetch earnings calendar' and distinguishes two modes: without ticker returns upcoming for all held tickers, with ticker returns history and upcoming. This provides a specific verb+resource pair and differentiates from sibling tools like show_dividend or show_financials.

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

Usage Guidelines3/5

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

The description implies when to use (earnings calendar needs) but does not provide explicit guidance on when not to use or contrast with alternatives like show_financials. It lacks explicit context for selecting this tool over siblings.

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/evan-moon/firma'

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