Jaspers Hub

jaspers / yfinance

pluginOfficialReviewed★ 0↓ 11

yfinance: Free Yahoo Finance market data (quotes, history, fundamentals, options, news, movers) via a bundled MCP server, with five views.

1.3 KB
1// What every tool answers: text for the model, and structuredContent with a `rows` array, since rows
2// are the one shape a view can read (the app keeps them as a dataset, the rest as its meta).
3
4export type ToolResult = {
5 [key: string]: unknown
6 content: { type: 'text'; text: string }[]
7 structuredContent: Record<string, unknown> & { rows: unknown[] }
8}
9
10/** About how much text a tool answers with; lines past it are left out, and the text says how many. */
11export const TEXT_MAX = 30_000
12
13export function toolResult(text: string, structured: Record<string, unknown> & { rows: unknown[] }): ToolResult {
14 return { content: [{ type: 'text', text }], structuredContent: structured }
15}
16
17/** The head, then as many lines as fit, then `more(n)` when n lines were left out. */
18export function capped(head: string[], lines: string[], more: (left: number) => string, max = TEXT_MAX): string {
19 const out = [...head]
20 let size = out.join('\n').length
21 let kept = 0
22 for (const line of lines) {
23 if (size + line.length + 1 > max) break
24 out.push(line)
25 size += line.length + 1
26 kept++
27 }
28 if (kept < lines.length) out.push(more(lines.length - kept))
29 return out.join('\n')
30}
31
32/** The parts that have something in them, joined. */
33export function parts(...items: (string | null | undefined | false)[]): string {
34 return items.filter((item): item is string => typeof item === 'string' && item !== '').join(', ')
35}