Web Beancount 推出 MCP 服务器——从 Claude、Cursor 以及任何你已经在用的 AI 工具与你的账本对话
让你的记账数据与你的 AI 工作流相遇。无需复制粘贴。无需导出。只管开口问。
今天,Web Beancount 发布 Beancount MCP 服务器——一个 Model Context Protocol(MCP)端点,让你可以将你的 Beancount 账本直接连接到 Claude Desktop、Claude Code、Cursor、Windsurf 或任何其他兼容 MCP 的 AI 客户端。高级用户第一次可以在他们日常使用的 AI 工具中直接提出记账问题、运行 BQL 查询,甚至编辑账本文件——无需切换标签页或离开工作流。
纯文本的 Beancount 文件之所以强大,恰恰因为它们只是文件。但要回答"我上个季度在旅行上花了多少钱?",你仍然需要懂 BQL 语法、知道文件在哪里,并把结果复制到聊天里。Beancount MCP 服务器彻底消除了这种摩擦。
在你的 AI 客户端中配置好 Beancount MCP 服务器后,你可以:
- 询问"我今天的净资产是多少?",并从你真实的账本中获得实时答案
- 请求一份上个月支出的汇总,让 AI 为你编写 BQL 查询
- 让 AI 添加一笔交易,并看着它把改动提交到你账本的 git 仓库
- 浏览并阅读你的
.beancount文件,全程无需离开你的编辑器
该服务器以账本为范围:每个 MCP 会话都使用 OAuth 2.1 精确授权访问某一个账本。像 Claude Code 这样的客户端会自动发现并完成授权流程——无需手动管理令牌。你的账本仍然留在它原本所在的地方,即 Web Beancount 后端:AI 客户端向我们的服务器发送结构化的工具调用,服务器代表你读取或编辑你的账本并返回结果。MCP 服务器本身除了你的 AI 客户端对话中已经保存的内容之外,不存储任何东西。
Beancount MCP 服务器今天起面向所有 Web Beancount 用户开放。
快速开始
Beancount MCP 服务器现已上线。不到一分钟就能把它添加到你的 AI 客户端。
MCP 服务器 URL
https://beancount.io/api-gateway/mcpClaude Code(推荐——完整的 OAuth 2.1 流程,无需令牌)
claude mcp add --transport http beancount https://beancount.io/api-gateway/mcp首次使用时,Claude Code 会打开一个浏览器窗口。浏览器提示就是你选择要连接哪个账本的地方——批准一次,凭据便会自动刷新。有不止一个账本?以不同的名称再次添加该服务器(claude mcp add --transport http beancount-business https://beancount.io/api-gateway/mcp),并在它各自的提示中授权另一个账本。
Claude Desktop / Cursor / Windsurf / Zed
将该服务器添加到你客户端的 MCP 配置中(claude_desktop_config.json 或等效文件)。支持 OAuth 2.1 的客户端会在首次使用时打开同样的浏览器提示——在那里选择你的账本:
{
"mcpServers": {
"beancount": {
"url": "https://beancount.io/api-gateway/mcp"
}
}
}如果你的客户端还不支持 OAuth 流程,从你的 beancount.io 账户设置中生成一个静态令牌(范围限定于一个账本),并将其作为请求头传入:
{
"mcpServers": {
"beancount": {
"url": "https://beancount.io/api-gateway/mcp",
"headers": { "Authorization": "Bearer <your-token>" }
}
}
}还没有 Web Beancount 账户?在 beancount.io 注册——你的账本只差一次 git push。
常见问题
用户常见问题
什么是 MCP,它对 Beancount 为何重要?
MCP(Model Context Protocol,模型上下文协议)是一项开放标准,让 AI 助手能够以结构化、安全的方式调用外部工具和数据源。可以把它想象成 AI 的 USB 接口:AI 不再靠猜测或要求你粘贴数据,而是直接连接到你的系统。对 Beancount 用户来说,这意味着你的 AI 客户端可以查询你真实的账本数据、读取你实际的文件,并做出精确的编辑——而不是猜测它们可能包含什么。
哪些 AI 客户端可以配合 Beancount MCP 服务器使用?
任何支持 OAuth 2.1 的兼容 MCP 的客户端都可以开箱即用。Beancount MCP 服务器实现了带 PKCE 的完整 OAuth 2.1 授权流程,因此像 Claude Code 这样的客户端会自动发现服务器的授权端点并提示你登录——无需手动复制令牌或进行配置。一旦你批准访问,客户端就会自动存储并刷新凭据。
已知支持 MCP + OAuth 2.1 的客户端包括 Claude Code CLI、Claude Desktop、Cursor、Windsurf 和 Zed。随着 MCP 生态的发展,任何遵循 OAuth 2.1 MCP 规范的新客户端都能正常工作,我们这边无需任何改动。
我如何连接我的账本?
对于支持 OAuth 2.1 的客户端(如 Claude Code):
- 将 Beancount MCP 服务器 URL 添加到你客户端的 MCP 配置中。
- 客户端会自动打开一个浏览器窗口以授权访问。
- 用你的 Web Beancount 账户登录,并选择你想授予访问权限的账本。
- 完成——从这里开始,客户端会负责令牌的存储和刷新。
对于不支持 OAuth 2.1 的客户端,从你的 Web Beancount 账户设置中生成一个静态令牌(范围限定于一个账本),并将其作为 Authorization: Bearer 请求头传入。
这和仪表盘里的"Ask AI"聊天功能是一回事吗?
它们共享相同的底层账本工具(BQL 查询、文件读写),但 MCP 服务器是一个不同的入口。仪表盘的 Ask AI 功能是一个托管的聊天体验,背后是由 Cloudflare 支持的 Claude Code 沙箱。MCP 服务器则是一个协议端点,你可以从自己选择的 AI 客户端连接过来——为你提供更多控制权、更多模型,以及与现有工作流更深度的集成。
AI 究竟能对我的账本做什么?
MCP 服务器暴露了四个工具:
| Tool | What it does |
|---|---|
runBqlQuery | 执行 BQL(Beancount Query Language)以查询余额、交易、账户 |
listLedgerFiles | 浏览你账本仓库的目录结构 |
readLedgerFiles | 读取 .beancount 文件及其他账本文档的内容 |
editLedgerFiles | 在一次原子性的 git 提交中创建、更新、替换或删除文件 |
AI 可以组合使用这些工具:发现你的文件结构、读取相关文件以获取上下文、编写 BQL 查询来回答你的问题,或提出并提交一处修改。
AI 会在我不知情的情况下修改我的账本吗?
文件编辑需要 AI 客户端调用 editLedgerFiles,并附上对其所做改动的描述。行为规范的 MCP 客户端(包括 Claude Code)会在执行前把这一点呈现给你。编辑还支持 dry_run 模式,它会预览确切的改动而不写入任何内容,因此你的客户端可以先向你展示一份 diff。而且每一次提交的改动都是你账本仓库中一次真实的 git 提交,所以你拥有完整的审计轨迹,并且可以用标准的 git 工具还原任何改动。
我的数据会被发送给第三方吗?
你的账本数据流经 Web Beancount 后端(它本就在管理你的账本),并作为结构化结果返回给你的 AI 客户端。你所使用的 AI 模型(例如 Claude)会像接收任何其他上下文一样接收这些工具结果。除了你的 AI 客户端对话中已经保存的内容之外,MCP 服务器不存储任何数据。
每个令牌都以账本为范围——这是什么意思?
当你授权 MCP 服务器时,你会选择授予对哪个账本的访问权限。该会话只能访问那个账本。如果你有多个账本,你需要为它们分别授权各自的会话。这限制了影响范围:为你个人账本创建的会话无法触及你的企业账本。
MCP 服务器需要 Fava 网页界面处于运行状态吗?
不需要。MCP 服务器与由 Web Beancount 基础设施管理的内部 Fava API 通信(Fava 是驱动你 beancount.io 账本的网页界面)。你不需要打开 Fava 界面或让它可访问。
如果我撤销了 MCP 访问权限会怎样?
正在进行的 MCP 会话会在下一次工具调用时收到 401 错误。支持 OAuth 2.1 的客户端会自动尝试重新授权,提示你再次登录。
深入幕后
献给对技术好奇的读者——这个服务器是如何构建的。
为什么选择 MCP,而不是为每个 AI 工具构建我们自己的 API/插件?
MCP 是正在兴起的标准,并且已经得到所有主流 AI 编辑器的支持。构建一个合规的 MCP 服务器让我们一次性获得与整个生态的兼容性,而不必为 Claude、Cursor、Windsurf 以及下个季度会推出的任何工具分别维护集成。协议负责处理发现、工具 schema 和流式传输——我们专注于领域逻辑。
为什么用 OAuth 2.1 而不是静态 API 密钥?
带 PKCE 的 OAuth 2.1 是 MCP 规范为远程服务器推荐的方案,也是像 Claude Code 这样的客户端原生实现的方案。实际好处是:用户永远不必接触令牌。客户端通过我们的 .well-known/oauth-protected-resource 元数据端点发现授权服务器、完成 PKCE,并自动管理刷新。静态令牌仍作为后备方案受支持,供那些尚未实现完整流程的客户端使用。
为什么用 Streamable HTTP 而不是 SSE 或 stdio 传输?
Streamable HTTP 是为通过 HTTPS 运行的远程服务器设计的 MCP 传输方式。stdio 用于本地进程。SSE(较旧的 MCP 传输方式)正被弃用,转而采用 Streamable HTTP。我们的用户从与我们服务器并不在同一位置的 AI 客户端连接过来,因此 Streamable HTTP 是正确且面向未来的选择。
为什么 MCP 会话是无状态的(没有 sessionIdGenerator)?
我们设置 sessionIdGenerator: undefined,使每个请求完全无状态——工具调用之间不会分配或保留任何服务器端会话状态。这符合 Streamable HTTP 规范的无状态模式,并让服务器在无需会话亲和性的情况下可以水平扩展。工具上下文(账本身份、Fava API 客户端)会在每次请求时从经过验证的 OIDC 令牌中重新构建。
账本访问验证是如何工作的?
在 OIDC 令牌验证之后,resolveLedgerAccess 会通过 Fava API 检查已认证的用户是否确实拥有对所请求账本的访问权限。这可以防止某个账本的有效令牌被用来探测另一个用户的账本(在签名令牌之上的纵深防御)。
editLedgerFiles 会提交到哪里?
它会调用 Fava API 上的 changeLedgerFiles,后者会在该账本的 Gitea 仓库中创建一次 git 提交,提交信息为 AI edit: <description>。该描述来自 AI 填写的 description 字段——在行为规范的 MCP 客户端中会在执行前呈现给用户。
editLedgerFiles 上的 dry_run 选项是什么?
dry_run: true 会验证所有文件操作(检查文件是否存在、确认 str_replace 的原始字符串恰好匹配一次),并返回将要提交内容的预览——而不实际写入 git。这对于想在提交前向用户展示 diff 的 AI 客户端很有用。
AI 客户端可见的错误面是怎样的?
工具错误以 { isError: true, content: [{ type: "text", text: "..." }] } 的形式返回——这是 MCP SDK 的结构化错误格式。AI 客户端会以文本形式收到错误信息,并可以自行决定如何处理(重试、报告给用户等)。HTTP 层面的认证失败(401)会包含一个指向 OAuth 受保护资源元数据的 WWW-Authenticate 请求头,因此合规的客户端可以自动重新发起授权流程。