Get Unapproved Transactions
ynab_get_unapproved_transactionsRetrieve unapproved transactions from a YNAB budget. Initial fetch covers the past 3 days; subsequent calls return only new or changed transactions since the last query.
Instructions
Gets unapproved transactions from a budget. First time pulls last 3 days, subsequent pulls use server knowledge to get only changes.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| budgetId | No | The ID of the budget to fetch transactions for (optional, defaults to the budget set in the YNAB_BUDGET_ID environment variable) |
Implementation Reference
- The execute function that fetches unapproved transactions from the YNAB API and returns them formatted.
export async function execute(input: GetUnapprovedTransactionsInput, api: ynab.API) { try { const budgetId = getBudgetId(input.budgetId); console.error(`Getting unapproved transactions for budget ${budgetId}`); const response = await api.transactions.getTransactions( budgetId, undefined, ynab.GetTransactionsTypeEnum.Unapproved ); // Transform the transactions to a more readable format const transactions = response.data.transactions .filter((transaction) => !transaction.deleted) .map((transaction) => ({ id: transaction.id, date: transaction.date, amount: (transaction.amount / 1000).toFixed(2), // Convert milliunits to actual currency memo: transaction.memo, approved: transaction.approved, account_name: transaction.account_name, payee_name: transaction.payee_name, category_name: transaction.category_name, transfer_account_id: transaction.transfer_account_id, transfer_transaction_id: transaction.transfer_transaction_id, matched_transaction_id: transaction.matched_transaction_id, import_id: transaction.import_id, })); return { content: [{ type: "text" as const, text: JSON.stringify({ transactions, transaction_count: transactions.length, }, null, 2) }] }; } catch (error) { console.error("Error getting unapproved transactions:", error); return { content: [{ type: "text" as const, text: JSON.stringify({ success: false, error: getErrorMessage(error), }, null, 2) }] }; } } - Input schema using zod - defines optional budgetId parameter.
export const inputSchema = { budgetId: z.string().optional().describe("The ID of the budget to fetch transactions for (optional, defaults to the budget set in the YNAB_BUDGET_ID environment variable)"), }; - src/index.ts:39-43 (registration)Registration of the tool with the MCP server, binding name, description, inputSchema, and execute handler.
server.registerTool(GetUnapprovedTransactionsTool.name, { title: "Get Unapproved Transactions", description: GetUnapprovedTransactionsTool.description, inputSchema: GetUnapprovedTransactionsTool.inputSchema, }, async (input) => GetUnapprovedTransactionsTool.execute(input, api)); - Helper function that resolves the budget ID from input param or env var, with error handling.
function getBudgetId(inputBudgetId?: string): string { const budgetId = inputBudgetId || process.env.YNAB_BUDGET_ID || ""; if (!budgetId) { throw new Error("No budget ID provided. Please provide a budget ID or set the YNAB_BUDGET_ID environment variable."); } return budgetId; } - src/tools/errorUtils.ts:5-39 (helper)Utility used by the execute function to extract error messages from various error types including YNAB API errors.
export function getErrorMessage(error: unknown): string { // Handle standard Error objects if (error instanceof Error) { return error.message; } // Handle YNAB API error responses which have the structure: // { error: { id: '...', name: '...', detail: '...' } } if ( typeof error === 'object' && error !== null && 'error' in error && typeof (error as any).error === 'object' ) { const ynabError = (error as any).error; if (ynabError.detail) { return ynabError.detail; } if (ynabError.name) { return ynabError.name; } } // Fallback: try to stringify the error try { const stringified = JSON.stringify(error); if (stringified !== '{}') { return stringified; } } catch { // Ignore stringify errors } return 'Unknown error occurred'; }