Skip to main content
Glama
aroesec

moneybags

by aroesec

Moneybags

一个自托管的个人财务账本,你可以直接与它对话。

导入对账单或同步你的银行。交易首先按规则分类,其次由模型分类,你每次的修正都会教会一条规则,这样同一个商户就不会被错误分类两次。然后用自然语言询问你的资金情况——Moneybags 运行一个 MCP 服务器,所以 Claude 可以直接读取你的账本。

"How much did I spend on groceries in August?"
"I just bought coffee, about six dollars"
"That Venmo payment was for tree work, not uncategorized"

一次部署,一个所有者。你的交易存储在你自己的数据库中,你的 API 密钥归你所有,中间没有任何服务。


这是什么,以及这不是什么

它是一个账本,适合那些希望自己的财务数据存储在自己控制的数据库中的人,带有一个可以被纠正的分类器,以及一个不是简单挂在仪表盘上的聊天机器人的对话界面。

它不是一个带有移动客户端和支持团队的预算应用。没有注册、没有多租户、没有托管版本。如果你想要一个家人可以在手机上登录的应用,请使用 Monarch 或 YNAB——说实话,它们在这方面做得很好,而这不是本项目的目标。

运行它的成本就是你的数据库和 API 密钥的成本。对于使用 Neon 免费套餐且仅上传对账单的个人账本来说,成本为零。

Related MCP server: OpenCoffer

为什么设计如此

这个代码库中几乎每一个艰难的决定都是为了不悄悄丢钱。不是崩溃——而是丢失。一个丢失类别的账本很烦人;一个丢失了 6000 美元却仍然平衡的账本是危险的,因为它看起来是正确的。

以下是由此得出的规则:

金钱是整数分。 模式中是 bigint,TypeScript 中是 number。浮点数只出现在格式化边界。任何地方都不会对浮点数求和。

负数表示钱已离开。 应用于解析、存储、账本计算和 UI,因此一个时期的净现金流就是简单的 SUM(amount_cents),无需逐行分支。如果导入适配器搞反了这一点,就会产生一个内部一致但完全错误的账本,这就是为什么适配器被反复强调这一点。

is_transfer 不是类别。 它表示这笔钱已经在本账本的其他地方被计算过——要么是注明对方账户的内部转账,要么是信用卡还款(其消费也已导入)。它绝不是用于 Venmo、Zelle、Cash App、ATM 取款或储蓄存款。离开的钱就是支出,无论通过什么渠道。

支付渠道不是商户。 “Venmo”告诉你钱是如何流动的,却无法告诉你买了什么。这些行会立即被计为支出——这样未回答的问题就不会悄悄减少当月总额——并排队等待你标记。一个回答就会教会一条以对手方为键的规则。

手动分类永远不会被覆盖。 每次自动处理都会过滤 classification_source <> 'manual'。你的回答优先于任何规则和任何模型。

去重基于指纹,而非对账单。 sha256(account, date, amount, normalized description) 并带有唯一索引。可以按任意顺序上传重叠的对账单;已存在的行会被跳过。账户是指纹的一部分,这就是为什么一旦你有多个账户,未分类的导入会被拒绝。

收入只能以一种方式丢失。 总额按符号拆分,因此正金额无论归入哪个类别都算作收入——不完美的类别仍然有效,分类失败也不会造成损失。is_transfer 是唯一的失败点,因此规则只能在模式明确指明付款或指明对方账户时,才将其设置为流入。pnpm db:audit-income 列出所有流入以及当前可能排除流入的规则。

分类器拒绝猜测。 规则先运行。剩下的交给模型。任何仍未解决的内容都会进入审核队列,而不是给出一个自信的错误答案——而且结构上无法承载用途的描述会完全跳过模型,因为模型每次都会回答“未知”,却要付出代价。

设置

Node 20+、pnpm 和一个 Postgres 数据库。

git clone https://github.com/YOUR-USERNAME/moneybags && cd moneybags
pnpm install
cp .env.example .env.local

填写三件事:

# 1. Your database
DATABASE_URL="postgresql://..."

# 2. A session secret
node -e "console.log(require('crypto').randomBytes(32).toString('base64url'))"

# 3. A password
pnpm auth:hash 'the password you want'      # prints APP_PASSWORD_HASH=...

然后:

pnpm db:migrate
pnpm db:seed        # idempotent; seeds the category taxonomy
pnpm dev

这就是一个可用的账本,支持 CSV 对账单导入。以下所有内容都是可选的,应用会如实说明每项功能带来的价值。

可选:模型

设置 AI_API_KEY。你将获得模型辅助分类(针对规则无法识别的商户)、书面洞察以及 PDF/图片对账单读取功能。

没有它,规则仍然可以分类,未匹配的行会进入审核队列,CSV 导入不受影响。这是一种受支持的使用方式,而不是一个残缺的版本。

任何提供商都可以——Anthropic、OpenAI、OpenRouter、Groq,或本地的 Ollama 或 LM Studio。参见 docs/ai.md。PDF 读取需要 Anthropic;其他功能在任何地方都可用。

可选:银行同步

通过 Plaid 连接账户,而不是上传对账单。Plaid 的免费套餐涵盖 10 个连接,并包含交易。

你不需要这个。 对账单上传是使用该应用的完整方式,跳过 Plaid 意味着少一个持有你银行凭据的第三方。参见 docs/plaid.md,其中还解释了开始前值得了解的免费套餐陷阱。

可选:与它对话

设置 → 生成一个 MCP 令牌,然后将任何 MCP 客户端指向 https://your-host/api/mcp,并使用该 Bearer 令牌。有十四个工具用于读取、记录和纠正。故意没有删除工具——听错的指令绝不能销毁记录。

部署

两条有文档记录的路径,没有哪条比另一条更优先:

Docker Compose — 应用加 Postgres,无需其他任何东西:

cp .env.example .env    # set APP_PASSWORD_HASH and SESSION_SECRET
docker compose up -d

Vercel + Neon — 免费套餐,无需运行服务器。

两者都在 docs/deploy.md 中,包括如果你想将其放在 Authelia 或 Tailscale 后面的反向代理设置。

认证

三种方法;至少配置一种,否则应用会拒绝启动,而不是把你的财务信息提供给任何找到 URL 的人。

方法

用途

密码

默认方法。通过 pnpm auth:hash 存储 scrypt 哈希,而不是明文。

OIDC

任何符合标准的提供商——Google、Authentik、Keycloak、Zitadel、Okta。需要允许列表;空列表会拒绝所有人。

受信任的请求头

已经位于 Authelia、oauth2-proxy、Cloudflare Access 或 Tailscale 之后。仅当应用只能通过代理访问时才安全。

登录有速率限制,密码以恒定时间比较,会话是签名的 JWT,可通过 SESSION_VERSION 批量撤销,Plaid 访问令牌在静态时使用 AES-256-GCM 加密。参见 docs/security.md 了解威胁模型以及它保护的内容。

可组合性

交易通过一个边界进入:src/lib/sources。下游的一切——去重、对账、分类、账本——只看到 ParsedTransaction[],无法判断一行是通过上传还是同步到达的。

添加银行、聚合器或棘手的 CSV 方言只是一个适配器,仅此而已:

registerFileSource({
  id: "my-bank",
  label: "My Bank CSV",
  accepts: ({ filename }) => filename.startsWith("mybank-"),
  parse: ({ bytes }) => ({ transactions: parseMyBank(bytes), warnings: [] }),
});

模型提供商也位于同样的接缝之后——在 src/lib/ai 之外不导入任何供应商 SDK。 docs/extending.md 涵盖了分类法、规则、来源、同步提供商和 MCP 工具。

命令

pnpm dev · build · test · typecheck

常规操作

pnpm auth:hash '<password>'

生成 APP_PASSWORD_HASH

pnpm db:migratedb:seed

模式,然后分类法

pnpm db:reclassify

在账本上重新运行流水线,跳过手动行

pnpm db:audit-income

验证没有流入被排除在收入之外

pnpm db:plaid-status

已链接的内容,以及每个账户的同步边界

技术栈

Next.js 15(App Router)、通过 Drizzle 使用 Postgres、Tailwind。Anthropic SDK 和 Plaid SDK 在运行时都是可选的,并且被隔离在接口之后。

贡献

CLAUDE.md 记录了事物为何如此,通常指出导致问题的 bug。在修改 src/lib/classifysrc/lib/reconcile 之前请阅读它——几个回归问题由测试固定,注释说明了如果你撤销它们会破坏什么。

修改分类器时的一般规则:宁可少匹配,也不要过度匹配。 一条永远不会再触发的规则只会导致一次重新纠正。而一条过度匹配的规则会悄悄重写你已经检查过的历史。

许可证

MIT — 参见 LICENSE

这处理真实的财务数据。它不提供任何担保,你的部署、密钥和备份由你负责。

A
license - permissive license
Not graded
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables users to track personal expenses through natural language interactions with comprehensive category support and financial summaries. Provides both local and remote MCP server options with SQLite storage for fast expense management operations.
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables querying personal finance data including accounts, transactions, spending, holdings, net worth, and budgets from your self-hosted OpenCoffer instance. Supports natural language queries through any MCP-compatible client.
    14
    MIT
  • A
    license
    A
    quality
    D
    maintenance
    Personal expense tracker MCP server that enables tracking expenses, income, budgets, and savings goals through natural language.
    10
    MIT
  • F
    license
    Not graded
    quality
    C
    maintenance
    Exposes personal-finance tools like accounts, transactions, spending analysis, budgets, bills, reminders, portfolio, and goals via MCP, enabling any MCP client to query financial data.

View all related MCP servers

Related MCP Connectors

  • Personal finance by conversation: expenses, receipts, statement import, budgets, net worth.

  • Log, query, and edit expenses, budgets, and accounts in Ledgy from any MCP-compatible AI assistant.

  • Ask your AI about bank accounts, spending, debts, holdings, and investment activity.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/aroesec/moneybags'

If you have feedback or need assistance with the MCP directory API, please join our Discord server