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
| Name | Required | Description | Default |
|---|---|---|---|
| ticker | No | Ticker symbol. Omit to get upcoming earnings for all holdings. | |
| weeks | No | Look-ahead window in weeks (default: 4) | |
| history | No | Include past quarters (only applies when ticker is provided) |
Implementation Reference
- apps/mcp/src/tools/stock.ts:329-361 (handler)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'); } }, - apps/mcp/src/tools/stock.ts:312-328 (schema)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)'), }, - apps/mcp/src/tools/stock.ts:309-362 (registration)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'); } }, ); - apps/mcp/src/index.ts:11-23 (registration)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);