create_transaction
Creates a new transaction for the authenticated user on one of their accounts.
Description
Creates a new transaction for the authenticated user on one of their accounts.
Required fields: name and amount.
category, accountId, and transactedAt can be omitted for intent-first MCP usage defaults.
⚠️ GOLDEN RULE — NEVER infer, guess, default, or invent ANY required field.
Every required field must come DIRECTLY from what the user said. If the user did not
clearly provide a field, STOP and ask them for it — do not proceed with a substitute.
MCP intent defaults:
• If category is omitted, infer it from the transaction name and amount (e.g. "wireless headphones" => GENERAL_MERCHANDISE).
• If transactedAt is omitted, default to today (RFC 3339).
• If accountId is omitted, default to the account named "Main Checking" when available.
If "Main Checking" is not available: use the only accessible account when exactly one exists.
If still ambiguous, ask the user to choose an account.
Edge-case parsing rule for purchases:
• If the user gives a TOTAL amount plus an item/service (e.g. "spent $300 on headphones" or "bought $300 headphones"),
treat both as the same intent: a single purchase with that item name and amount -30000 (cents).
• If quantity is NOT explicitly stated, assume default quantity = 1.
• Do NOT split total into unit price × quantity unless the user explicitly gives quantity or per-item pricing.
Natural-language name is OK (e.g. name="Log $5 coffee") — amount/name/category are inferred.
A trailing "on <account>" in the name (e.g. "Log $5 coffee on checking") selects that account when it matches one.
Optional accountName resolves the account without an ID; an unknown or ambiguous accountName asks which account.
If an identical name+amount exists on the same account within 24 hours, this asks before doubling up unless confirmDuplicate=true.
Examples of what is NOT allowed:
• User says "add a coffee transaction" (no amount) → DO NOT guess an amount. Ask: "How much was it?"
• User says "Log $4.50" (no description) → DO NOT invent a name. Ask: "What was it for?"
• User says "my account" with multiple accounts → DO NOT pick the default. Call list_accounts and ask which one.
Per-field rules:
• accountId: the account the USER explicitly chose. Vague reference + multiple accounts → ask.
• name: a specific label the user gave (e.g. "Coffee", "Rent"). Never a placeholder like "Transaction".
• amount: the exact amount the user stated, in cents ($4.50 → -450 for an expense). Never 0 and never a guess.
• category: inferred when omitted; informal names (e.g. "food", "groceries") auto-map to the closest system category (FOOD_AND_DRINK).
• transactedAt: the date the user gave, as RFC 3339. "today" is fine to resolve to today's date.
RESOLVING MISSING CONTEXT — call the appropriate tool before retrying:
• accountId unknown → call list_accounts; use account.id.
• category unclear → call list_categories; use category.name (only if inference is not suitable).
• tagIds unknown → call list_tags; use tag.id values.
Amounts are in cents. Sign convention: negative for expenses, positive for income.
type (INCOME, EXPENSE, TRANSFER) is optional and inferred from amount/category when omitted.
fileIds defaults to [] when omitted.Input parameters
| Name | Type | Required | Description |
|---|---|---|---|
accountId | string | No | |
accountName | string | No | |
amount | number | No | |
appleCardTransaction | object | No | |
category | string | No | |
categoryId | string | No | |
confirmDuplicate | boolean | No | |
cronExpression | string | No | |
description | string | No | |
endDate | string | No | |
expenseCategory | string | No | |
fileIds | array | No | |
incomeCategory | string | No | |
isExcludedFromAnalytics | boolean | No | |
lineItems | array | No | |
name | string | Yes | |
subcategory | string | No | |
tagIds | array | No | |
tagNames | array | No | |
transactedAt | string | No | |
type | string | No | |
vendorId | string | No | |
vendorName | string | No |