edit_txn
Update a transaction's details by ID. Only supplied fields are changed, leaving others intact.
Instructions
Update fields of an existing transaction by id. Only provided fields are changed.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | ||
| ticker | No | ||
| date | No | YYYY-MM-DD | |
| type | No | ||
| shares | No | ||
| price | No | ||
| reason | No | Why this trade? (free-form) |
Implementation Reference
- apps/mcp/src/tools/mutate.ts:61-72 (handler)Handler function that updates transaction fields by id. Only provided fields are changed. Returns updated transaction or error if not found.
async ({ id, ticker, ...rest }) => { const db = getDb(); const fields = { ...(ticker !== undefined ? { ticker: ticker.toUpperCase() } : {}), ...rest, }; if (Object.keys(fields).length === 0) return err('No fields to update'); const res = db.update(transactions).set(fields).where(eq(transactions.id, id)).run(); if (res.changes === 0) return err(`Transaction #${id} not found`); const updated = db.select().from(transactions).where(eq(transactions.id, id)).get(); return ok(updated); }, - apps/mcp/src/tools/mutate.ts:52-60 (schema)Zod schema defining input parameters: id (required positive int), ticker/date/type/shares/price/reason (all optional).
{ id: z.number().int().positive(), ticker: z.string().optional(), date: z.string().optional().describe('YYYY-MM-DD'), type: z.enum(['buy', 'sell', 'deposit', 'dividend', 'tax']).optional(), shares: z.number().positive().optional(), price: z.number().min(0).optional(), reason: z.string().nullable().optional().describe('Why this trade? (free-form)'), }, - apps/mcp/src/tools/mutate.ts:49-73 (registration)Tool registration via server.tool() inside registerMutateTools, called from apps/mcp/src/index.ts:21.
server.tool( 'edit_txn', 'Update fields of an existing transaction by id. Only provided fields are changed.', { id: z.number().int().positive(), ticker: z.string().optional(), date: z.string().optional().describe('YYYY-MM-DD'), type: z.enum(['buy', 'sell', 'deposit', 'dividend', 'tax']).optional(), shares: z.number().positive().optional(), price: z.number().min(0).optional(), reason: z.string().nullable().optional().describe('Why this trade? (free-form)'), }, async ({ id, ticker, ...rest }) => { const db = getDb(); const fields = { ...(ticker !== undefined ? { ticker: ticker.toUpperCase() } : {}), ...rest, }; if (Object.keys(fields).length === 0) return err('No fields to update'); const res = db.update(transactions).set(fields).where(eq(transactions.id, id)).run(); if (res.changes === 0) return err(`Transaction #${id} not found`); const updated = db.select().from(transactions).where(eq(transactions.id, id)).get(); return ok(updated); }, ); - apps/mcp/src/helpers.ts:67-69 (helper)Helper function returning a success response with JSON content.
export const ok = (data: unknown) => ({ content: [{ type: 'text' as const, text: JSON.stringify(data, null, 2) }], }); - apps/mcp/src/helpers.ts:71-74 (helper)Helper function returning an error response with isError flag.
export const err = (msg: string) => ({ content: [{ type: 'text' as const, text: `Error: ${msg}` }], isError: true, });