ynab_update_transaction
Update an existing transaction by providing a transaction ID and any fields to change: amount, date, payee, category, memo, cleared status, or approval.
Instructions
Update an existing transaction. Only specified fields will be updated.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| result | Yes |
Implementation Reference
- src/ynab_mcp_server/server.py:365-403 (handler)The async function that handles the 'ynab_update_transaction' tool. It builds an updates dict from optional fields, converts dollars to milliunits if amount is provided, calls client.update_transaction(), and returns a formatted result string.
async def ynab_update_transaction(params: UpdateTransactionInput) -> str: """Update an existing transaction. Only specified fields will be updated.""" try: updates = {} if params.amount is not None: updates["amount"] = dollars_to_milliunits(params.amount) if params.date is not None: updates["date"] = params.date if params.payee_name is not None: updates["payee_name"] = params.payee_name if params.category_id is not None: updates["category_id"] = params.category_id if params.memo is not None: updates["memo"] = params.memo if params.cleared is not None: updates["cleared"] = params.cleared.value if params.approved is not None: updates["approved"] = params.approved if not updates: return "Error: No fields to update. Specify at least one field to change." async with YNABClient() as client: transaction = await client.update_transaction( params.budget_id, params.transaction_id, **updates, ) result = "## Transaction Updated\n\n" result += f"- **ID**: `{transaction['id']}`\n" result += f"- **Date**: {transaction['date']}\n" result += f"- **Amount**: {format_currency(transaction['amount'])}\n" result += f"- **Payee**: {transaction.get('payee_name', 'N/A')}\n" return result except Exception as e: return format_error(e) - src/ynab_mcp_server/server.py:355-363 (registration)The @mcp.tool() decorator that registers 'ynab_update_transaction' as an MCP tool with annotations for title, readOnlyHint, destructiveHint, idempotentHint, and openWorldHint.
@mcp.tool( name="ynab_update_transaction", annotations={ "title": "Update Transaction", "readOnlyHint": False, "destructiveHint": False, "idempotentHint": True, "openWorldHint": False, } - Pydantic model UpdateTransactionInput defining the schema for the tool's input parameters: transaction_id (required), plus optional fields amount, date, payee_name, category_id, memo, cleared, approved. Extends BudgetIdInput which provides budget_id.
class UpdateTransactionInput(BudgetIdInput): """Input for updating an existing transaction.""" transaction_id: str = Field(..., description="The transaction ID to update") amount: Optional[float] = Field(default=None, description="New amount in dollars") date: Optional[str] = Field(default=None, description="New date (YYYY-MM-DD)", pattern=r"^\d{4}-\d{2}-\d{2}$") payee_name: Optional[str] = Field(default=None, description="New payee name", max_length=200) category_id: Optional[str] = Field(default=None, description="New category ID") memo: Optional[str] = Field(default=None, description="New memo", max_length=500) cleared: Optional[ClearedStatus] = Field(default=None, description="New cleared status") approved: Optional[bool] = Field(default=None, description="New approved status") - src/ynab_mcp_server/models.py:96-100 (schema)ClearedStatus enum used by the schema, with values CLEARED='cleared', UNCLEARED='uncleared', RECONCILED='reconciled'.
class ClearedStatus(str, Enum): """Transaction cleared status.""" CLEARED = "cleared" UNCLEARED = "uncleared" RECONCILED = "reconciled" - src/ynab_mcp_server/server.py:40-42 (helper)Helper function dollars_to_milliunits used in the handler to convert dollar amounts to YNAB milliunits (1000 milliunits = $1.00).
def dollars_to_milliunits(dollars: float) -> int: """Convert dollars to YNAB milliunits (1000 milliunits = $1.00).""" return int(round(dollars * 1000))