update_transaction
Update an existing transaction's details by ID, modifying only specified fields like quantity or price, while preserving card identity and transaction type.
Instructions
Update an existing transaction by ID. Only the fields supplied are changed. Card identity and type (BUY/SELL) cannot be changed via this endpoint - delete and re-create instead. Requires IWMM_API_KEY.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | Transaction ID from list_transactions. | |
| patch | Yes |
Implementation Reference
- src/tools/transactions.ts:57-67 (handler)The updateTransactionTool definition: name 'update_transaction', input schema (id + patch object), and handler that sends a PATCH to /api/v1/transactions/{id} with the patch body.
export const updateTransactionTool = { name: "update_transaction", description: "Update an existing transaction by ID. Only the fields supplied are changed. Card identity and type (BUY/SELL) cannot be changed via this endpoint - delete and re-create instead. Requires IWMM_API_KEY.", inputSchema: z.object({ id: z.number().int().min(1).describe("Transaction ID from list_transactions."), patch: transactionUpdate, }), handler: ({ id, patch }: { id: number; patch: z.infer<typeof transactionUpdate> }) => apiFetch({ path: `/api/v1/transactions/${id}`, method: "PATCH", body: patch, authenticated: true }), }; - src/tools/transactions.ts:20-27 (schema)The 'transactionUpdate' Zod schema defining the optional fields that can be patched: quantity, pricePerUnit, date, source, fees, notes.
const transactionUpdate = z.object({ quantity: z.number().int().min(1).optional(), pricePerUnit: z.number().min(0).optional(), date: z.string().optional(), source: z.string().optional(), fees: z.number().min(0).optional(), notes: z.string().optional(), }); - src/tools/index.ts:48-93 (registration)The 'tools' array in src/tools/index.ts registers updateTransactionTool as one of the available tools. It is also exported via the toolsByName lookup.
export const tools: ToolDefinition[] = [ // Read-only (no auth) searchCardsTool, getCardTool, getCardPricesTool, getCardPriceHistoryTool, searchSetsTool, getSetTool, listSetCardsTool, getSealedProductsTool, // Inventory (auth) listInventoryTool, getInventoryQuantitiesTool, addInventoryTool, updateInventoryTool, removeInventoryTool, // Transactions (auth) listTransactionsTool, recordTransactionTool, updateTransactionTool, deleteTransactionTool, getCostBasisTool, // Portfolio (auth; most are Premium-gated) getPortfolioSummaryTool, getPortfolioHistoryTool, getCardPerformanceTool, getCashFlowTool, getRealizedGainsTool, getPortfolioBreakdownTool, refreshPortfolioTool, // Price alerts (auth) listAlertsTool, createAlertTool, updateAlertTool, deleteAlertTool, // Notifications (auth) listNotificationsTool, getUnreadCountTool, markNotificationReadTool, markAllNotificationsReadTool, ]; export const toolsByName: Record<string, ToolDefinition> = Object.fromEntries( tools.map((t) => [t.name, t]), ); - src/tools/index.ts:90-92 (registration)The 'toolsByName' map provides runtime lookup by tool name, used by the MCP server to dispatch calls.
export const toolsByName: Record<string, ToolDefinition> = Object.fromEntries( tools.map((t) => [t.name, t]), ); - src/api-client.ts:26-67 (helper)The apiFetch helper that handles HTTP requests. The update_transaction handler calls this with method PATCH, path /api/v1/transactions/{id}, the patch body, and authenticated=true.
export async function apiFetch<T = unknown>(req: ApiRequest): Promise<T> { const url = new URL(req.path, config.baseUrl); if (req.query) { for (const [k, v] of Object.entries(req.query)) { if (v !== undefined && v !== null && v !== "") { url.searchParams.set(k, String(v)); } } } const headers: Record<string, string> = { Accept: "application/json", "User-Agent": "iwantmymtg-mcp/0.0.1", }; if (req.authenticated) { const { requireApiKey } = await import("./config.js"); headers["Authorization"] = `Bearer ${requireApiKey()}`; } if (req.body !== undefined) { headers["Content-Type"] = "application/json"; } const res = await fetch(url, { method: req.method ?? "GET", headers, body: req.body !== undefined ? JSON.stringify(req.body) : undefined, }); if (!res.ok) { const text = await res.text(); throw new ApiError(res.status, text, { limit: res.headers.get("X-RateLimit-Limit") ?? undefined, remaining: res.headers.get("X-RateLimit-Remaining") ?? undefined, reset: res.headers.get("X-RateLimit-Reset") ?? undefined, }); } if (res.status === 204) return undefined as T; return (await res.json()) as T; }