UNPKG

actual-mcp

Version:

Actual Budget MCP server exposing API functionality

179 lines 9.71 kB
import { z } from 'zod'; // Type definitions for tool arguments export const GetTransactionsArgsSchema = z.object({ accountId: z.string(), startDate: z.string().optional(), endDate: z.string().optional(), minAmount: z.number().optional(), maxAmount: z.number().optional(), categoryName: z.string().optional(), payeeName: z.string().optional(), limit: z.number().optional(), }); export const SpendingByCategoryArgsSchema = z.object({ startDate: z.string().optional(), endDate: z.string().optional(), accountId: z.string().optional(), includeIncome: z.boolean().optional(), }); export const MonthlySummaryArgsSchema = z.object({ months: z.number().optional().default(3), accountId: z.string().optional(), }); export const BalanceHistoryArgsSchema = z.object({ accountId: z.string(), includeOffBudget: z.boolean().optional().default(false), months: z.number().optional().default(3), }); export const FinancialInsightsArgsSchema = z.object({ startDate: z.string().optional(), endDate: z.string().optional(), }); export const BudgetReviewArgsSchema = z.object({ months: z.number().optional().default(3), }); export const UpdateSubtransactionSchema = z.object({ id: z .string() .optional() .describe('The ID of an existing subtransaction to update. Omit to add a new subtransaction.'), amount: z.number().describe('Required for subtransactions. A currency amount as an integer'), category: z.string().optional().describe('The ID of the category for this subtransaction'), notes: z.string().optional().describe('Any additional notes for this subtransaction'), }); export const UpdateTransactionArgsSchema = z.object({ id: z.string().describe('Required. The ID of the transaction to update'), account: z.string().optional().describe('The ID of the account to move this transaction to'), date: z .string() .regex(/^\d{4}-\d{2}-\d{2}$/, 'date must be in YYYY-MM-DD format') .optional() .describe('Transaction date in YYYY-MM-DD format'), amount: z .number() .optional() .describe('A currency amount as an integer representing the value without decimal places. For example, USD amount of $120.30 would be 12030'), payee: z.string().optional().describe('An existing payee ID'), payee_name: z .string() .optional() .describe('If given, a payee will be created with this name. If this matches an already existing payee, that payee will be used.'), imported_payee: z .string() .optional() .describe('This can be anything. Meant to represent the raw description when importing, allowing the user to see the original value'), category: z.string().optional().describe('The ID of the category to assign to this transaction'), notes: z.string().optional().describe('Any additional notes for the transaction'), imported_id: z .string() .optional() .describe('A unique id usually given by the bank, if importing. Use this to avoid duplicate transactions'), cleared: z.boolean().optional().describe('A flag indicating if the transaction has cleared or not'), subtransactions: z .array(UpdateSubtransactionSchema) .optional() .describe("An array of subtransactions for a split transaction. Replaces existing subtransactions. If amounts don't equal total amount, API call will succeed but error will show in app"), }); // Schema for update data passed to the API (without id, which is passed separately) export const UpdateTransactionDataSchema = UpdateTransactionArgsSchema.omit({ id: true }); export const SubtransactionSchema = z.object({ amount: z.number().describe('Required for subtransactions. A currency amount as an integer'), category: z.string().optional().describe('The ID of the category for this subtransaction'), notes: z.string().optional().describe('Any additional notes for this subtransaction'), }); export const CreateTransactionArgsSchema = z.object({ account: z.string().describe('Required. The ID of the account this transaction belongs to'), date: z .string() .regex(/^\d{4}-\d{2}-\d{2}$/, 'date must be in YYYY-MM-DD format') .describe('Required. Transaction date in YYYY-MM-DD format'), amount: z .number() .describe('Required. A currency amount as an integer representing the value without decimal places. For example, USD amount of $120.30 would be 12030'), payee: z.string().optional().describe('An existing payee ID. This overrides payee_name if both are provided.'), payee_name: z .string() .optional() .describe('If given, a payee will be created with this name. If this matches an already existing payee, that payee will be used.'), imported_payee: z .string() .optional() .describe('This can be anything. Meant to represent the raw description when importing, allowing the user to see the original value'), category: z.string().optional().describe('Recommended. The ID of the category to assign to this transaction'), notes: z.string().optional().describe('Any additional notes for the transaction'), imported_id: z .string() .optional() .describe('A unique id usually given by the bank, if importing. Use this to avoid duplicate transactions'), transfer_id: z .string() .optional() .describe('If a transfer, the id of the corresponding transaction in the other account. Only set this when importing'), transfer_account_id: z .string() .optional() .describe('The ID of the destination account for a transfer. When provided, the transfer payee is automatically resolved and the counterpart transaction is created in the destination account. The amount should be negative (money leaving the source account).'), cleared: z.boolean().optional().describe('A flag indicating if the transaction has cleared or not'), subtransactions: z .array(SubtransactionSchema) .optional() .describe("An array of subtransactions for a split transaction. If amounts don't equal total amount, API call will succeed but error will show in app"), }); // Schema for transaction data passed to the API (without account and transfer_account_id, which are handled separately) export const TransactionDataSchema = CreateTransactionArgsSchema.omit({ account: true, transfer_account_id: true }); // Subtransaction schema for imports — amount is a decimal (e.g. 3.24), converted to integer by the API wrapper export const ImportSubtransactionSchema = z.object({ amount: z .number() .describe('Required. Amount as a decimal number (e.g. 3.24 for $3.24). Negative for expenses, positive for income.'), category: z.string().optional().describe('The ID of the category for this subtransaction'), notes: z.string().optional().describe('Any additional notes for this subtransaction'), }); // Schema for a single transaction item in a bulk import. // Accepts decimal amounts (e.g. 3.24) which are converted to integers by the API wrapper. export const ImportTransactionItemSchema = z.object({ date: z .string() .regex(/^\d{4}-\d{2}-\d{2}$/, 'date must be in YYYY-MM-DD format') .describe('Required. Transaction date in YYYY-MM-DD format'), amount: z .number() .describe('Required. Amount as a decimal number (e.g. 3.24 for $3.24). Negative for expenses, positive for income.'), payee: z.string().optional().describe('An existing payee ID. This overrides payee_name if both are provided.'), payee_name: z .string() .optional() .describe('If given, a payee will be created with this name. If this matches an already existing payee, that payee will be used.'), imported_payee: z .string() .optional() .describe('This can be anything. Meant to represent the raw description when importing, allowing the user to see the original value'), category: z.string().optional().describe('Recommended. The ID of the category to assign to this transaction'), notes: z.string().optional().describe('Any additional notes for the transaction'), imported_id: z .string() .optional() .describe('A unique id usually given by the bank, if importing. Use this to avoid duplicate transactions'), transfer_id: z .string() .optional() .describe('If a transfer, the id of the corresponding transaction in the other account. Only set this when importing'), cleared: z.boolean().optional().describe('A flag indicating if the transaction has cleared or not'), subtransactions: z .array(ImportSubtransactionSchema) .optional() .describe("An array of subtransactions for a split transaction. If amounts don't equal total amount, API call will succeed but error will show in app"), }); export const ImportTransactionsArgsSchema = z.object({ accountId: z.string().describe('Required. The ID of the account to import transactions into'), transactions: z .array(ImportTransactionItemSchema) .min(1) .describe('Required. List of transactions to import. Use imported_id to avoid duplicate imports on repeated runs.'), defaultCleared: z .boolean() .optional() .describe('Default cleared state for all imported transactions (can be overridden per transaction)'), dryRun: z.boolean().optional().describe('If true, validate and preview the import without persisting any changes'), }); //# sourceMappingURL=types.js.map