create_manual_account
Create a new manually-managed account by specifying its type, name, and current balance. Optionally set subtype, currency, institution, or close date.
Instructions
Create a new manually-managed account. (Formerly create_asset.)
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| type | Yes | Primary type of the manual account. | |
| subtype | No | Optional subtype (e.g., retirement, checking, savings). | |
| name | Yes | Name of the account. 1-45 characters. | |
| display_name | No | Display name. If unset, derived from institution_name and name. | |
| balance | Yes | Current balance of the account. | |
| balance_as_of | No | Date or datetime the balance is as of (ISO 8601). | |
| currency | No | Three-letter lowercase currency code (defaults to primary currency). | |
| institution_name | No | Name of the institution holding the account. | |
| closed_on | No | Date the account was closed (YYYY-MM-DD). If set, status is forced to closed. | |
| exclude_from_transactions | No | If true, transactions cannot be assigned to this account. |
Implementation Reference
- src/tools/manual-accounts.ts:148-192 (handler)The async handler function that executes the create_manual_account tool logic. It destructures the input parameters, builds a request body, calls POST /manual_accounts, and returns the response.
async ({ type, subtype, name, display_name, balance, balance_as_of, currency, institution_name, closed_on, exclude_from_transactions, }) => { try { const body: Record<string, unknown> = { type, name, balance: balance.toString(), }; if (subtype !== undefined) body.subtype = subtype; if (display_name !== undefined) body.display_name = display_name; if (balance_as_of !== undefined) body.balance_as_of = balance_as_of; if (currency !== undefined) body.currency = currency; if (institution_name !== undefined) body.institution_name = institution_name; if (closed_on !== undefined) body.closed_on = closed_on; if (exclude_from_transactions !== undefined) body.exclude_from_transactions = exclude_from_transactions; const response = await api.post("/manual_accounts", body); if (!response.ok) { return handleApiError( response, "Failed to create manual account", ); } return dataResponse(await response.json()); } catch (error) { return catchError(error, "Failed to create manual account"); } }, - src/tools/manual-accounts.ts:90-143 (schema)The input schema for create_manual_account, defining all parameters: type (enum), subtype, name, display_name, balance, balance_as_of, currency, institution_name, closed_on, exclude_from_transactions.
inputSchema: { type: manualAccountTypeEnum.describe( "Primary type of the manual account.", ), subtype: z .string() .optional() .describe( "Optional subtype (e.g., retirement, checking, savings).", ), name: z .string() .min(1) .max(45) .describe("Name of the account. 1-45 characters."), display_name: z .string() .optional() .describe( "Display name. If unset, derived from institution_name and name.", ), balance: z.coerce .number() .describe("Current balance of the account."), balance_as_of: z .string() .optional() .describe( "Date or datetime the balance is as of (ISO 8601).", ), currency: z .string() .length(3) .optional() .describe( "Three-letter lowercase currency code (defaults to primary currency).", ), institution_name: z .string() .optional() .describe("Name of the institution holding the account."), closed_on: z .string() .optional() .describe( "Date the account was closed (YYYY-MM-DD). If set, status is forced to closed.", ), exclude_from_transactions: z .boolean() .optional() .describe( "If true, transactions cannot be assigned to this account.", ), }, - src/tools/manual-accounts.ts:85-193 (registration)The registration call: server.registerTool('create_manual_account', ...) which binds the name, description, input schema, annotations, and handler.
server.registerTool( "create_manual_account", { description: "Create a new manually-managed account. (Formerly `create_asset`.)", inputSchema: { type: manualAccountTypeEnum.describe( "Primary type of the manual account.", ), subtype: z .string() .optional() .describe( "Optional subtype (e.g., retirement, checking, savings).", ), name: z .string() .min(1) .max(45) .describe("Name of the account. 1-45 characters."), display_name: z .string() .optional() .describe( "Display name. If unset, derived from institution_name and name.", ), balance: z.coerce .number() .describe("Current balance of the account."), balance_as_of: z .string() .optional() .describe( "Date or datetime the balance is as of (ISO 8601).", ), currency: z .string() .length(3) .optional() .describe( "Three-letter lowercase currency code (defaults to primary currency).", ), institution_name: z .string() .optional() .describe("Name of the institution holding the account."), closed_on: z .string() .optional() .describe( "Date the account was closed (YYYY-MM-DD). If set, status is forced to closed.", ), exclude_from_transactions: z .boolean() .optional() .describe( "If true, transactions cannot be assigned to this account.", ), }, annotations: { idempotentHint: false, }, }, async ({ type, subtype, name, display_name, balance, balance_as_of, currency, institution_name, closed_on, exclude_from_transactions, }) => { try { const body: Record<string, unknown> = { type, name, balance: balance.toString(), }; if (subtype !== undefined) body.subtype = subtype; if (display_name !== undefined) body.display_name = display_name; if (balance_as_of !== undefined) body.balance_as_of = balance_as_of; if (currency !== undefined) body.currency = currency; if (institution_name !== undefined) body.institution_name = institution_name; if (closed_on !== undefined) body.closed_on = closed_on; if (exclude_from_transactions !== undefined) body.exclude_from_transactions = exclude_from_transactions; const response = await api.post("/manual_accounts", body); if (!response.ok) { return handleApiError( response, "Failed to create manual account", ); } return dataResponse(await response.json()); } catch (error) { return catchError(error, "Failed to create manual account"); } }, ); - src/index.ts:12-31 (registration)The import and invocation of registerManualAccountTools in the main entry point, which registers all manual account tools including create_manual_account on the MCP server.
import { registerManualAccountTools } from "./tools/manual-accounts.js"; import { registerPlaidAccountTools } from "./tools/plaid-accounts.js"; import { registerCryptoTools } from "./tools/crypto.js"; import { registerPrompts } from "./prompts.js"; const require = createRequire(import.meta.url); const { version } = require("../package.json"); const server = new McpServer({ name: "lunchmoney-mcp", version, }); registerUserTools(server); registerCategoryTools(server); registerTagTools(server); registerTransactionTools(server); registerRecurringItemsTools(server); registerBudgetTools(server); registerManualAccountTools(server); - src/tools/manual-accounts.ts:11-22 (helper)The manualAccountTypeEnum helper used in the input schema to validate the 'type' field (cash, credit, cryptocurrency, etc.).
const manualAccountTypeEnum = z.enum([ "cash", "credit", "cryptocurrency", "employee compensation", "investment", "loan", "other liability", "other asset", "real estate", "vehicle", ]);