预算管理协议服务

一个为AI代理提供原始数据访问的预算管理协议服务,支持复杂查询、AI驱动的预算分析和对话式财务管理。

  • by dattmavis
  • JavaScript
  • 本地部署
  • 2 星标
  • 更新于
在 GitHub 查看 dattmavis/actual-budget-mcp

使用说明

实际预算MCP

一个模型上下文协议(MCP)服务器,允许AI代理访问您的原始数据 实际预算问一些关于你的支出的复杂问题,获得人工智能驱动的预算分析,并通过对话管理你的财务。

这有什么作用

此MCP将您的实际预算作为与AI项目一起使用的工具包。

特性

数据访问

  • 列出所有有余额和活动计数的账户
  • 获取预算类别和支出明细
  • 灵活过滤查询交易(日期、类别、收款人、账户)
  • 查看特定类别的余额和预算状态
  • 分析不同时期的支出趋势
  • 查找未分类的交易

预算管理

  • 按名称或ID设置类别预算
  • 对批量交易进行分类
  • 创建新交易
  • 更新交易详细信息(收款人、金额、日期、备注)
  • 删除交易和类别
  • 与银行账户同步

智能聚合

  • 获取任何日期范围的支出总额
  • 计算平均交易金额
  • 比较不同时期的支出
  • 跟踪帐户活动
  • 查看历史账户余额
  • 分析一段时间内的支出趋势

高级功能

  • 并发请求的种族条件预防
  • 自动预算初始化和管理
  • 银行同步支持
  • 余额历史跟踪
  • 强大的错误处理和恢复

用例

“本月我的五大支出类别是什么?”

克劳德打电话来 get_spending_by_category() 并呈现排序后的列表。

“我超出预算了吗?”

克劳德打电话来 get_budget_totals(),比较支出与预算,并提醒您。

“我比上个月多花了多少钱?”

克劳德打电话来 get_total_spending() 并计算两者的差值。

“查找所有未分类的餐厅交易,并将其归类为餐饮”

Claude发现交易 get_uncategorized_transactions(),按收款人筛选,然后用 set_transaction_category().

“为我刚买的咖啡创建交易”

克劳德打电话来 create_transaction() 您提供的详细信息。

“过去三个月我的消费趋势如何?”

克劳德打电话来 get_total_spending() 并生成趋势分析。

安装

需求

  • Node.js 18+
  • 本地或远程运行的实际预算服务器
  • Claude Code或ChatGPT(支持MCP)

设置

  1. 克隆或下载此存储库

    git clone https://github.com/yourusername/actual-budget-mcp.git
    cd actual-budget-mcp
    
  2. 安装依赖项

    npm install
    
  3. 配置环境变量

    cp .env.example .env
    
  4. 编辑 .env 与您的实际预算详细信息

    ACTUAL_DATA_DIR=../actual-budget-cli/actual-data
    ACTUAL_BUDGET_ID=My-Finances-42bc5bf
    ACTUAL_SERVER_URL=http://localhost:5006
    ACTUAL_PASSWORD=your-password-here
    

配置

所有配置都通过环境变量进行管理 .env 文件。复制 .env.example 开始吧。

环境变量

变量 必填 默认 描述
ACTUAL_BUDGET_ID 是 -- 实际预算中的预算ID
ACTUAL_PASSWORD 是 -- 服务器身份验证密码
ACTUAL_SERVER_URL 没有 http://localhost:5006 实际预算服务器URL
ACTUAL_DATA_DIR 没有 ../actual-budget-cli/actual-data 本地预算数据路径
READ_ONLY 没有 false 禁用写入操作(设置为 true 或 1)

只读模式

启用只读模式以防止AI修改您的预算数据。启用后,所有突变工具都将禁用:

只读模式下禁用的工具:

  • set_category_budget -无法设置类别预算
  • set_category_budget_by_id -无法按ID设置预算
  • set_transaction_category -无法对交易进行分类
  • update_transaction -无法修改交易记录
  • create_transaction -无法创建新交易
  • delete_transaction -无法删除交易记录
  • delete_category -无法删除类别

要启用只读模式,请在 .env:

READ_ONLY=true

所有数据访问工具仍然完全可用。尝试调用变异工具将返回错误。

部署

在本地运行以进行测试

npm start

服务器监听stdin/stdout。按 Ctrl+C 停止。

Docker部署

使用Docker构建和运行

塑造形象:

docker build -t actual-budget-mcp .

运行容器:

docker run -d \
  --name actual-budget-mcp \
  --restart unless-stopped \
  -e ACTUAL_BUDGET_ID=My-Finances-42bc5bf \
  -e ACTUAL_PASSWORD=your-password \
  -e ACTUAL_SERVER_URL=http://actual-budget:5006 \
  actual-budget-mcp

Docker Compose(推荐)

创建 .env 使用您的配置文件:

ACTUAL_BUDGET_ID=My-Finances-42bc5bf
ACTUAL_PASSWORD=your-password
ACTUAL_SERVER_URL=http://localhost:5006
READ_ONLY=false

启动容器:

docker-compose up -d

查看日志:

docker-compose logs -f actual-budget-mcp

停止容器:

docker-compose down

VPS部署

  1. SSH到您的VPS

    ssh user@your-vps.com
    
  2. 克隆仓库

    git clone https://github.com/yourusername/actual-budget-mcp.git
    cd actual-budget-mcp
    
  3. 创建 .env 将您的凭据归档

    cp .env.example .env
    nano .env
    

    用你的实际值更新。

  4. 从Docker Compose开始

    docker-compose up -d
    
  5. 连接到Claude/ChatGPT

    MCP在容器内的stdin/stdout上运行。要在本地计算机上与Claude Code或ChatGPT一起使用它,您有两个选择:

    选项A:SSH隧道(推荐)

    这将通过SSH转发MCP stdio:

    # On your local machine, connect via SSH tunnel to the VPS-running MCP
    # Configure Claude/ChatGPT MCP server with:
    Command: ssh
    Arguments: user@your-vps.com -N "docker exec -i actual-budget-mcp node index.mjs"
    

    选项B:本地开发副本

    保持本地副本运行以进行开发,将更新的代码部署到VPS:

    # Local machine runs for Claude/ChatGPT
    npm start
    
    # VPS runs production instance
    docker-compose up -d
    

集装箱健康与监测

检查集装箱状态:

docker-compose ps

查看日志:

docker-compose logs -f --tail 50 actual-budget-mcp

需要时重新启动:

docker-compose restart actual-budget-mcp

网络配置

如果实际预算也在同一VPS上的Docker中运行,请更新 docker-compose.yml:

services:
  actual-budget-mcp:
    # ... other config
    environment:
      - ACTUAL_SERVER_URL=http://actual-budget:5006  # Use container name
    networks:
      - actual-budget-network

  actual-budget:
    # Your Actual Budget container config
    networks:
      - actual-budget-network

networks:
  actual-budget-network:
    driver: bridge

然后使用:

docker-compose up -d

工具参考

数据访问工具

get_accounts

返回所有具有余额、类型和活动计数的帐户。

// Returns
[
  {
    id: "acct_123",
    name: "Checking",
    type: "bank",
    balance: 4250.50,
    offBudget: false,
    transactionCount: 42
  },
  ...
]

get_categories

返回所有预算类别。

// Returns
[
  {
    id: "cat_456",
    name: "Groceries",
    isGroup: false,
    isHidden: false,
    budgeted: 500.00
  },
  ...
]

get_category_by_id(categoryId)

返回特定类别的详细信息。

// Returns
{
  id: "cat_456",
  name: "Groceries",
  budgeted: 500.00,
  spent: 380.25,
  balance: 119.75,
  isGroup: false,
  isHidden: false
}

get_transactions(filters?)

返回具有可选筛选功能的交易记录。

// Parameters
{
  category: "cat_456",           // Filter by category ID
  account: "acct_123",            // Filter by account ID
  payee: "whole foods",           // Partial match on payee name
  startDate: "2026-02-01",        // YYYY-MM-DD format
  endDate: "2026-02-28",
  limit: 100,                     // Default: 100
  excludeChild: true              // Exclude split transactions (default: true)
}

// Returns
[
  {
    id: "txn_789",
    date: "2026-02-04",
    account: "acct_123",
    payee: "Whole Foods",
    category: "cat_456",
    amount: 47.50,
    notes: "",
    isTransfer: false
  },
  ...
]

get_transaction_by_id(transactionId)

按ID返回单个交易。

get_budget_totals

返回总体预算摘要。

// Returns
{
  totalBudgeted: 4500.00,
  totalSpent: 3680.25,
  remaining: 819.75,
  totalBalance: 12450.50
}

get_spending_by_category(filters?)

按类别返回支出明细,按支出金额降序排列。

// Parameters
{
  startDate: "2026-01-01",   // Optional
  endDate: "2026-01-31"
}

// Returns
[
  {
    id: "cat_456",
    name: "Groceries",
    budgeted: 500.00,
    spent: 450.75,
    balance: 49.25,
    remaining: 49.25,
    transactionCount: 12
  },
  ...
]

get_total_spending(filters?)

返回某个日期范围的合计支出总额。

// Parameters
{
  startDate: "2026-02-01",   // Optional
  endDate: "2026-02-28"
}

// Returns
{
  totalSpent: 1850.50,
  transactionCount: 34,
  avgTransaction: 54.43,
  dateRange: {
    startDate: "2026-02-01",
    endDate: "2026-02-28"
  }
}

get_uncategorized_transactions(limit?)

返回没有类别的交易。

// Parameters
{
  limit: 100  // Default: 100
}

// Returns
[
  {
    id: "txn_789",
    date: "2026-02-04",
    account: "acct_123",
    payee: "Unknown Store",
    amount: 25.00,
    notes: ""
  },
  ...
]

get_account_transactions(accountId, limit?)

返回特定帐户的交易记录。

// Parameters
{
  accountId: "acct_123",  // Required - Account ID
  limit: 100             // Optional - Default: 100, max recommended: 500
}

// Returns
[
  {
    id: "txn_789",
    date: "2026-02-04",
    payee: "Whole Foods",
    category: "cat_456",
    amount: 47.50,
    notes: "Weekly groceries"
  },
  ...
]

get_payees

返回预算中的所有收款人。

// Returns
[
  {
    id: "payee_123",
    name: "Whole Foods"
  },
  {
    id: "payee_456",
    name: "Starbucks"
  },
  ...
]

突变工具

set_category_budget(categoryName, amount)

按名称设置类别的预算。

// Parameters
{
  categoryName: "Groceries",  // Required - Case-insensitive category name
  amount: 600.00              // Required - Budget amount in dollars
}

// Returns
{
  success: true,
  category: "Groceries",
  newBudget: 600.00
}

// Error Example
{
  success: false,
  error: "Category 'InvalidCategory' not found"
}

set_category_budget_by_id(categoryId, amount)

按ID(比名称更可靠)为类别设置预算。

// Parameters
{
  categoryId: "cat_456",  // Required - Category ID
  amount: 600.00          // Required - Budget amount in dollars
}

// Returns
{
  success: true,
  category: "Groceries",
  newBudget: 600.00
}

set_transaction_category(transactionId, categoryNameOrId)

对交易进行分类(接受类别名称或ID)。

// Parameters
{
  transactionId: "txn_789",      // Required - Transaction ID to categorize
  categoryNameOrId: "Groceries"  // Required - Category name or ID
}

// Returns
{
  success: true,
  transactionId: "txn_789",
  category: "Groceries"
}

// Error if transaction not found
{
  success: false,
  error: "Transaction with ID 'txn_invalid' not found"
}

update_transaction(transactionId, updates)

修改交易详细信息(收款人、金额、日期、票据或类别)。

// Parameters
{
  transactionId: "txn_789",        // Required - Transaction ID
  payee: "Whole Foods Market",     // Optional - New payee name
  category: "cat_456",             // Optional - New category (ID or name)
  amount: 50.00,                   // Optional - New amount in dollars
  date: "2026-02-04",              // Optional - New date (YYYY-MM-DD)
  notes: "Weekly groceries"        // Optional - New notes
}

// Returns
{
  success: true,
  transactionId: "txn_789",
  updates: {
    payee: "Whole Foods Market",
    category: "cat_456",
    amount: 50.00,
    date: "2026-02-04",
    notes: "Weekly groceries"
  }
}

create_transaction(transaction)

在预算中创建新交易。

// Parameters (required: account, payee, amount, date)
{
  account: "acct_123",           // Required - Account ID to post transaction to
  payee: "Starbucks",            // Required - Payee name
  amount: 5.75,                  // Required - Amount in dollars (positive or negative)
  date: "2026-02-04",            // Required - Date in YYYY-MM-DD format
  category: "Coffee",            // Optional - Category name or ID
  notes: "Tuesday morning coffee" // Optional - Transaction notes
}

// Returns
{
  success: true,
  transactionId: "txn_new_999"
}

// Error if account not found
{
  success: false,
  error: "Account 'acct_invalid' not found"
}

delete_transaction(transactionId)

从预算中永久删除交易。

// Parameters
{
  transactionId: "txn_789"  // Required - Transaction ID to delete
}

// Returns
{
  success: true,
  transactionId: "txn_789",
  message: "Transaction deleted: Whole Foods ($47.50)"
}

// Error if not found
{
  success: false,
  error: "Transaction with ID 'txn_invalid' not found"
}

delete_category(categoryId)

永久删除预算类别。此类别中的交易不会被删除。

// Parameters
{
  categoryId: "cat_456"  // Required - Category ID to delete
}

// Returns
{
  success: true,
  categoryId: "cat_456",
  categoryName: "Groceries",
  message: "Category 'Groceries' deleted"
}

// Error if not found or can't delete
{
  success: false,
  error: "Cannot delete category 'Groceries': category contains active transactions"
}

先进工具

get_balance_history(accountId, limit?)

根据交易记录获取账户的历史余额进度。

// Parameters
{
  accountId: "acct_123",  // Required - Account ID
  limit: 30              // Optional - Number of recent transactions (default: 30)
}

// Returns
[
  {
    date: "2026-01-25",
    transaction: "Direct Deposit",
    amount: 2500.00,
    balance: 5250.50
  },
  {
    date: "2026-01-26",
    transaction: "Whole Foods",
    amount: -47.50,
    balance: 5203.00
  },
  ...
]

run_bank_sync()

启动与已连接银行账户的同步。

// Parameters
(none)

// Returns
{
  success: true,
  message: "Bank sync initiated",
  timestamp: "2026-02-04T13:45:30.123Z",
  syncStatus: {
    accountsSynced: 3,
    lastSyncTime: "2026-02-04T13:45:00Z"
  }
}

// Error if sync fails
{
  success: false,
  error: "Bank sync failed: Connection to bank server timed out"
}

错误处理

所有变异工具都以这种格式返回错误:

{
  success: false,
  error: "Description of what went wrong"
}

常见错误:

  • "Category '...' not found" -类别名称/ID不存在
  • "Transaction with ID '...' not found" -交易ID不存在
  • "Account '...' not found" -帐户ID不存在
  • "ACTUAL_BUDGET_ID environment variable is required" -配置问题
  • "Connection refused" -实际预算服务器未运行

故障排除

“找不到模块'@actual app/api'”

  • 跑 npm install
  • 验证Node.js版本是否为18+

“ACTUAL_BUDGET_ID环境变量是必需的”

  • 创建 .env 文件(复制自 .env.example)
  • 集 ACTUAL_BUDGET_ID=your-budget-id

“连接被拒绝本地主机:5006”

  • 验证实际预算服务器是否正在运行
  • 检查 ACTUAL_SERVER_URL 在 .env 是正确的

MCP未出现在Claude/ChatGPT中

  • 在MCP配置中使用绝对路径(非相对路径)
  • 添加服务器后重新启动Claude Code或ChatGPT
  • 检查服务器是否启动: npm start 不应显示错误

交易未出现

  • 验证您查询的帐户/类别ID是否正确
  • 使用 get_accounts() 和 get_categories() 列出可用ID
  • 如果使用,请检查日期过滤器 startDate/endDate

“工具在只读模式下禁用”

  • 检查是否 READ_ONLY=true 在你的 .env 文件
  • 集 READ_ONLY=false 或删除变量以启用写入操作
  • 所有数据访问工具都以只读模式工作,只有突变被禁用

许可证

麻省理工学院

支持

有关问题、疑问或功能请求,请在GitHub上打开问题或参阅 实际预算文件.