关于 monarchmoney
monarchmoney 是用于访问 Monarch Money 财务数据的 Node.js/TypeScript 库和 MCP 服务,提供账户、交易、预算及现金流的类型化操作,涵盖读取和写入。
主要功能
- 01账户和交易的类型化 API 方法
- 02预算、现金流、持仓和余额数据
- 03电子邮件 OTP 与 MFA 认证流程
- 04保存并复用会话令牌
- 05自动分页及瞬时错误重试
- 06用于读取和修改数据的 30 个 MCP 工具
适用场景
- 01为应用获取财务数据
- 02通过 MCP 客户端查看交易、预算或现金流
- 03通过 AI Agent 修改交易和账户设置
MCP 相关
内置 MCP 服务提供 30 个用于读取和写入 Monarch Money 数据的工具。MCP 客户端可访问账户、交易、预算、现金流及受支持的修改操作。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
30收录的工具列表 · 更新于 2 周前
此工具无需参数。
详细介绍
Monarch Money (Node.js)
用于访问 Monarch Money 数据的 Node.js/TypeScript 库。
**免责声明:**此项目为非官方项目,与 Monarch Money 无关。
安装
npm install @hakimelek/monarchmoney
需要 Node.js 18+(使用原生 fetch 和 AbortSignal.timeout)。
快速开始
import {
MonarchMoney,
EmailOtpRequiredException,
RequireMFAException,
} from "@hakimelek/monarchmoney";
const mm = new MonarchMoney();
try {
await mm.login("[email protected]", "password");
} catch (e) {
if (e instanceof EmailOtpRequiredException) {
// Monarch sent a verification code to your email
const code = await promptUser("Enter the code from your email:");
await mm.submitEmailOtp("[email protected]", "password", code);
} else if (e instanceof RequireMFAException) {
// TOTP-based MFA is enabled on the account
await mm.multiFactorAuthenticate("[email protected]", "password", "123456");
}
}
// Fetch data — fully typed responses
const { accounts } = await mm.getAccounts();
console.log(accounts[0].displayName, accounts[0].currentBalance);
身份验证
Monarch 的 API 要求新设备/会话进行电子邮件验证(OTP),即使已禁用 MFA 也不例外。此库通过不同的异常类型处理此情况,以便你的应用做出相应响应。
使用电子邮件 OTP 处理登录
try {
await mm.login(email, password);
} catch (e) {
if (e instanceof EmailOtpRequiredException) {
// A code was sent to the user's email — prompt them for it
const code = await yourApp.promptForEmailCode();
await mm.submitEmailOtp(email, password, code);
}
}
使用 MFA 密钥(自动 TOTP)
await mm.login("email", "password", {
mfaSecretKey: "YOUR_BASE32_SECRET",
});
MFA 密钥是 Monarch Money 中 Settings > Security > Enable MFA 下的“Two-factor text code”。
会话持久化与令牌复用
成功登录后(包括电子邮件 OTP 验证),你可以保存令牌,避免每次运行时都重新进行身份验证:
// Save token after login
mm.saveSession(); // writes to .mm/mm_session.json (mode 0o600)
// Next time, login() loads the saved session automatically
await mm.login(email, password); // uses saved token, no network call
// Or pass the token directly (skip login entirely)
const mm = new MonarchMoney({ token: "your-saved-token" });
mm.saveSession(); // save to disk
mm.loadSession(); // load from disk
mm.deleteSession(); // remove the file
mm.setToken("..."); // set token programmatically
交互式 CLI
await mm.interactiveLogin(); // prompts for email, password, email OTP or MFA code
API
所有方法都会返回类型化响应。在编辑器中将鼠标悬停在任意方法上,即可查看完整的 JSDoc 和类型信息。
读取方法
| 方法 | 返回值 | 说明 |
|---|---|---|
getAccounts() | GetAccountsResponse | 所有已关联的账户 |
getAccountTypeOptions() | GetAccountTypeOptionsResponse | 可用的账户类型/子类型 |
getRecentAccountBalances(startDate?) | GetRecentAccountBalancesResponse | 每日余额(默认:过去 31 天) |
getAccountSnapshotsByType(startDate, timeframe) | GetSnapshotsByAccountTypeResponse | 按类型划分的快照("year" / "month") |
getAggregateSnapshots(options?) | GetAggregateSnapshotsResponse | 一段时间内的总净值 |
getAccountHoldings(accountId) | GetAccountHoldingsResponse | 券商账户中的证券 |
getAccountHistory(accountId) | AccountHistorySnapshot[] | 每日余额历史记录 |
getInstitutions() | GetInstitutionsResponse | 已关联的金融机构 |
getBudgets(startDate?, endDate?) | GetBudgetsResponse | 含实际数据的预算(默认:上个月至下个月) |
getSubscriptionDetails() | GetSubscriptionDetailsResponse | 套餐状态(试用、高级版等) |
getTransactionsSummary() | GetTransactionsSummaryResponse | 汇总摘要 |
getTransactions(options?) | GetTransactionsResponse | 支持完整筛选的交易记录 |
getAllTransactions(options?) | Transaction[] | 所有符合条件的交易记录(自动分页) |
getTransactionPages(options?) | AsyncGenerator<Transaction[]> | 逐页生成数据的异步生成器 |
getTransactionCategories() | GetTransactionCategoriesResponse | 所有类别 |
getTransactionCategoryGroups() | GetTransactionCategoryGroupsResponse | 类别组 |
getTransactionDetails(id) | typed response | 单笔交易详情 |
getTransactionSplits(id) | typed response | 交易的拆分项 |
getTransactionTags() | GetTransactionTagsResponse | 所有标签 |
getCashflow(options?) | GetCashflowResponse | 按类别、分组和商家划分的现金流 |
getCashflowSummary(options?) | GetCashflowSummaryResponse | 收入、支出、储蓄和储蓄率 |
getRecurringTransactions(start?, end?) | GetRecurringTransactionsResponse | 即将发生的定期交易 |
isAccountsRefreshComplete(ids?) | boolean | 检查刷新状态 |
写入方法
| 方法 | 返回值 | 说明 |
|---|---|---|
createManualAccount(params) | CreateManualAccountResponse | 创建手动账户 |
updateAccount(id, updates) | UpdateAccountResponse | 更新账户设置/余额 |
deleteAccount(id) | DeleteAccountResponse | 删除账户 |
requestAccountsRefresh(ids) | boolean | 启动刷新(非阻塞) |
requestAccountsRefreshAndWait(opts?) | boolean | 刷新并轮询,直至完成 |
createTransaction(params) | CreateTransactionResponse | 创建交易 |
updateTransaction(id, updates) | UpdateTransactionResponse | 更新交易 |
deleteTransaction(id) | boolean | 删除交易 |
updateTransactionSplits(id, splits) | UpdateTransactionSplitResponse | 管理拆分项 |
createTransactionCategory(params) | CreateCategoryResponse | 创建类别 |
deleteTransactionCategory(id, moveTo?) | boolean | 删除类别 |
deleteTransactionCategories(ids) | (boolean | Error)[] | 批量删除 |
createTransactionTag(name, color) | CreateTransactionTagResponse | 创建标签 |
setTransactionTags(txId, tagIds) | SetTransactionTagsResponse | 为交易设置标签 |
setBudgetAmount(params) | SetBudgetAmountResponse | 设置/清除预算 |
uploadAccountBalanceHistory(id, csv) | void | 上传余额历史记录 CSV |
错误处理
import {
MonarchMoneyError, // base class for all errors
EmailOtpRequiredException, // email verification code needed — call submitEmailOtp()
RequireMFAException, // TOTP MFA required — call multiFactorAuthenticate()
LoginFailedException, // bad credentials or auth error (includes .statusCode)
RequestFailedException, // API/GraphQL failure (includes .statusCode, .graphQLErrors)
} from "@hakimelek/monarchmoney";
try {
await mm.login(email, password);
} catch (e) {
if (e instanceof EmailOtpRequiredException) {
// e.code === "EMAIL_OTP_REQUIRED"
// Prompt user for the code sent to their email
const code = await getCodeFromUser();
await mm.submitEmailOtp(email, password, code);
} else if (e instanceof RequireMFAException) {
// e.code === "MFA_REQUIRED"
// Prompt for TOTP code or use mfaSecretKey
} else if (e instanceof LoginFailedException) {
// e.code === "LOGIN_FAILED", e.statusCode
console.error("Login failed:", e.message);
}
}
try {
await mm.getAccounts();
} catch (e) {
if (e instanceof RequestFailedException) {
console.error(e.statusCode); // HTTP status, if applicable
console.error(e.graphQLErrors); // GraphQL errors array, if applicable
console.error(e.code); // "HTTP_ERROR" | "REQUEST_FAILED"
}
}
配置
const mm = new MonarchMoney({
sessionFile: ".mm/mm_session.json", // session file path
timeout: 10, // API timeout in seconds
token: "pre-existing-token", // skip login
retry: {
maxRetries: 3, // retry on 429/5xx (default: 3, set 0 to disable)
baseDelayMs: 500, // base delay with exponential backoff + jitter
},
rateLimit: {
requestsPerSecond: 10, // token-bucket throttle (default: 0 = unlimited)
},
});
mm.setTimeout(30); // change timeout later
重试机制会自动处理暂时性故障(429 Too Many Requests、500、502、503、504),采用指数退避并加入抖动。对于 429 响应,会遵循 Retry-After 标头。
自动分页
getTransactions() 返回单页数据。对于大型数据集,请使用自动分页辅助方法:
// Async generator — yields one page at a time (memory-efficient)
for await (const page of mm.getTransactionPages({ startDate: "2025-01-01", endDate: "2025-12-31" })) {
for (const tx of page) {
console.log(tx.merchant?.name, tx.amount);
}
}
// Or collect everything into a flat array
const all = await mm.getAllTransactions({
startDate: "2025-01-01",
endDate: "2025-12-31",
pageSize: 100, // transactions per page (default: 100)
});
console.log(`${all.length} total transactions`);
这两种方法都接受与 getTransactions() 相同的筛选选项(日期范围、类别、账户、标签等)。
刷新进度
使用 onProgress 回调跟踪账户刷新进度:
await mm.requestAccountsRefreshAndWait({
timeout: 300,
delay: 10,
onProgress: ({ completed, total, elapsedMs }) => {
console.log(`${completed}/${total} accounts refreshed (${(elapsedMs / 1000).toFixed(0)}s)`);
},
});
MCP 服务(AI Agent 集成)
此软件包内置了一个 Model Context Protocol 服务,包含 30 个工具,可让 AI 助手通过 Claude Desktop、Cursor 和任何兼容 MCP 的客户端访问你的 Monarch Money 数据。
设置
-
使用此库登录,获取 Monarch Money 身份验证令牌(参见身份验证),并保存
mm.token。 -
将其添加到 MCP 客户端配置中(例如 Claude Desktop 的
claude_desktop_config.json):
{
"mcpServers": {
"monarch-money": {
"command": "npx",
"args": ["@hakimelek/monarchmoney"],
"env": {
"MONARCH_TOKEN": "your-token-here"
}
}
}
}
或者直接运行:
MONARCH_TOKEN=your-token npx @hakimelek/monarchmoney
可用工具
读取(18 个工具): get_accounts、get_account_holdings、get_account_history、get_account_type_options、get_recent_account_balances、get_aggregate_snapshots、get_institutions、get_budgets、get_subscription_details、get_transactions、get_transactions_summary、get_transaction_details、get_transaction_categories、get_transaction_category_groups、get_transaction_tags、get_cashflow、get_cashflow_summary、get_recurring_transactions
写入(12 个工具): create_transaction、update_transaction、delete_transaction、create_manual_account、update_account、delete_account、refresh_accounts、is_refresh_complete、set_budget_amount、create_transaction_tag、set_transaction_tags、create_transaction_category
每个工具都提供带说明的类型化参数,因此 AI Agent 能准确了解应传入哪些参数。
项目结构
src/
index.ts — public exports
client.ts — MonarchMoney class with all API methods
mcp.ts — MCP server (30 tools for AI agents)
errors.ts — error classes (MonarchMoneyError hierarchy)
endpoints.ts — API URL constants
queries.ts — all GraphQL query/mutation strings
types.ts — TypeScript interfaces for all API responses
测试
npm test # run tests once
npm run test:watch # run tests in watch mode
npm run test:coverage # run with coverage report
测试使用 Vitest,无需真实的 API 凭据(必要时会对 fetch 进行模拟)。
测试 API 连接(连接到线上 api.monarch.com):
npm run build
# Login with email + password (will prompt for email OTP code if required)
[email protected] MONARCH_PASSWORD=yourpassword npm run test:connection
# Use a saved token (skips login)
MONARCH_TOKEN=your-token npm run test:connection -- --token
可将这些值设置在 .env 文件中,以方便使用(参见 .env.example)。
常见问题
如果我通过 Google 登录 Monarch,该如何使用?
在 Monarch 账户的 Settings > Security 中设置密码,然后在此库中使用该密码。
为什么 Monarch 每次登录时都会要求输入电子邮件验证码?
Monarch 要求对新设备或未识别的设备进行电子邮件验证。登录后,使用 mm.saveSession() 保存会话令牌,或存储 mm.token——后续运行将重用该令牌,无需重新验证。
此库的比较
目前有多种非官方的 Monarch Money 集成。以下是 @hakimelek/monarchmoney 的表现。
生态概览
| @hakimelek/monarchmoney | monarch-money-api (pbassham) | monarchmoney (keithah) | monarchmoney (hammem) | |
|---|---|---|---|---|
| 平台 | Node.js / TypeScript | Node.js / JavaScript | Node.js / TypeScript | Python |
| npm 每周下载量 | — | ~440 | ~130 | 不适用(pip:~103K/月) |
| 运行时依赖 | 1(speakeasy) | 5 | 7 | 3 |
| TypeScript 类型 | 完整(每种响应) | 无 | 有 | 不适用 |
| 电子邮件 OTP 流程 | 有 | 无 | 无 | 无 |
| MFA / TOTP | 有 | 有 | 有 | 有 |
| 会话持久化 | 有(0o600 权限) | 有 | 有(AES-256) | 有 |
| 交互式 CLI 登录 | 有 | 有 | 有 | 有 |
| HTTP 客户端 | 原生 fetch | node-fetch | node-fetch + graphql-request | aiohttp |
| 错误层级 | 4 种类型化异常 | 通用抛出 | 通用抛出 | 1 种异常 |
| 读取方法 | 20 | 15 | ~20 | ~16 |
| 写入方法 | 14 | 9 | ~12 | ~10 |
| 速率限制 | 有 | 无 | 有 | 无 |
| 退避重试 | 有 | 无 | 有 | 无 |
| 自动分页 | 有 | 无 | 无 | 无 |
| 同时支持 CJS + ESM | 有 | 无 | 有 | 无 |
| 刷新进度事件 | 有 | 无 | 无 | 无 |
| 内置 MCP 服务 | 有(30 个工具) | 无 | 无 | 无 |
此库的优势
依赖精简。 运行时依赖只有 1 个,而 JS/TS 替代方案有 5–7 个。原生 fetch 意味着 Node 18+ 无需 HTTP polyfill。
支持电子邮件 OTP。 Monarch 现在要求对未识别的设备进行电子邮件验证,即使 MFA 已关闭也是如此。这是唯一一个能处理完整 EmailOtpRequiredException → submitEmailOtp() 流程的 Node.js 库。缺少此功能时,从新环境首次登录会导致自动化脚本中断。
全面类型化。 每种 API 响应都有专用的 TypeScript 接口——导出了 50 多种类型,涵盖账户、交易、持仓、现金流、预算、定期项目和变更。monarch-money-api 包完全没有类型。
结构化错误处理。 提供四种不同的异常类(LoginFailedException、RequireMFAException、EmailOtpRequiredException、RequestFailedException),并包含错误代码和状态代码。竞品会抛出通用错误或字符串。
更全面的写入功能。 包含 updateTransaction()、setBudgetAmount()、uploadAccountBalanceHistory()、getCashflow()、getCashflowSummary() 和 getRecurringTransactions()——这些功能在 monarch-money-api 中均不可用。
简洁、扁平的 API。 一个类,直接调用方法,无需学习子对象或冗长的层级。导入 MonarchMoney,调用方法,即可获得类型化结果。
参与贡献
欢迎贡献。请确保 TypeScript 编译无误(npm run build)且测试通过(npm test)。
许可证
MIT
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。