Skip to main content
Glama
index.ts2.42 kB
// Orchestrator for spending-by-category tool import { CallToolResult } from '@modelcontextprotocol/sdk/types.js'; import { SpendingByCategoryInputParser } from './input-parser.js'; import { SpendingByCategoryDataFetcher } from './data-fetcher.js'; import { CategoryMapper } from '../../core/mapping/category-mapper.js'; import { TransactionGrouper } from '../../core/aggregation/transaction-grouper.js'; import { GroupAggregator } from '../../core/aggregation/group-by.js'; import { SpendingByCategoryReportGenerator } from './report-generator.js'; import { success, errorFromCatch } from '../../utils/response.js'; import type { SpendingByCategoryInput } from './input-parser.js'; import { zodToJsonSchema } from 'zod-to-json-schema'; import { SpendingByCategoryArgsSchema, type SpendingByCategoryArgs, ToolInput, type Account } from '../../types.js'; export const schema = { name: 'spending-by-category', description: 'Get spending breakdown by category for a specified date range', inputSchema: zodToJsonSchema(SpendingByCategoryArgsSchema) as ToolInput, }; export async function handler(args: SpendingByCategoryArgs): Promise<CallToolResult> { try { const input: SpendingByCategoryInput = new SpendingByCategoryInputParser().parse(args); const { startDate, endDate, accountId, includeIncome } = input; const { accounts, categories, categoryGroups, transactions } = await new SpendingByCategoryDataFetcher().fetchAll( accountId, startDate, endDate ); const categoryMapper = new CategoryMapper(categories, categoryGroups); const spendingByCategory = new TransactionGrouper().groupByCategory( transactions, (categoryId) => categoryMapper.getCategoryName(categoryId), (categoryId) => categoryMapper.getGroupInfo(categoryId), includeIncome ); const sortedGroups = new GroupAggregator().aggregateAndSort(spendingByCategory); let accountLabel = 'Accounts: All on-budget accounts'; if (accountId) { const account: Account | undefined = accounts.find((a) => a.id === accountId); accountLabel = `Account: ${account ? account.name : accountId}`; } const markdown = new SpendingByCategoryReportGenerator().generate( sortedGroups, { start: startDate, end: endDate }, accountLabel, includeIncome ); return success(markdown); } catch (err) { return errorFromCatch(err); } }

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/s-stefanov/actual-mcp'

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