内容
# 实际MCP
本仓库包含一个可源代码构建的实际预算MCP服务器,位于[`mcp-server/`](./mcp-server)。该服务器通过MCP公开实际预算数据和写入工作流,包括预算、核对、调度管理、交易导入、起始余额修复和转移感知交易创建。
## 主要包
- [`mcp-server/`](./mcp-server) 是产品包。
- [`mcp-server/README.md`](./mcp-server/README.md) 是安装、配置、客户端设置和工具清单的权威指南。
- [`docs/engineering-notes.md`](./docs/engineering-notes.md) 包含面向贡献者的实现笔记。
## 公共与私有布局
本仓库按照以下简单规则组织:
- 公共的、可共享的项目资产保留在跟踪的路径中,例如 `mcp-server/`、`docs/`、`.github/` 和根配置文件。
- 私有的财务导出、核对草稿文件、备份和本地特有工件位于 `.local-reconciliation/` 下,该目录被git忽略。
- 本地运行时缓存,如 `.actual-data/`、`.playwright-cli/` 和 `tmp/`,也是私有的,不应提交。
如果您需要为特定预算工作文件的位置,请将其放在 `.local-reconciliation/` 下,而不是创建新的顶级文件夹。
## 快速入门
```bash
git clone <您的仓库网址>
cd actual-mcp
pnpm install
pnpm --filter actual-mcp build
pnpm --filter actual-mcp test
```
## 使用Docker Compose进行快速入门
为了在不安装Node或pnpm的情况下进行更简单的本地开发设置,您可以使用Docker Compose:
1. 克隆仓库:`git clone <您的仓库网址>` 和 `cd actual-mcp`
2. 复制环境模板:`cp .env.example .env`
3. 在 `.env` 中填写所需的值
4. 运行服务:`docker-compose up` (或 `docker compose up`)
这将构建服务器,在开发模式下启动它,并将其暴露在端口3000上。
有关包特定设置和MCP客户端配置,请参阅 [`mcp-server/README.md`](./mcp-server/README.md)。
## Render部署
本仓库已经在 [`render.yaml`](./render.yaml) 中包含了一个Render Blueprint,用于将MCP服务器部署为Web服务。
在您想要在Render上托管MCP服务器本身时使用此Blueprint:
1. 将此仓库构建并推送到GitHub。
2. 在Render中,从仓库创建一个新的Blueprint或Web服务。
3. 设置 `ACTUAL_SERVER_URL`、`ACTUAL_PASSWORD` 或 `ACTUAL_SESSION_TOKEN`、`ACTUAL_BUDGET_SYNC_ID` 和 `BEARER_TOKEN`。
4. 部署并使用 `/health` 和 `/ready` 进行平台检查。
Render Workflows SDK是与此仓库中的MCP服务器运行时分开的产品。像这样的代码:
```ts
import { task } from "@renderinc/sdk/workflows";
```
用于使用 `render workflows init --language node` 创建的后台工作流作业,而不是用于 [`mcp-server/src/index.ts`](./mcp-server/src/index.ts) 下的MCP服务器入口点,该入口点现在启动stdio模式或基于Hono的远程HTTP运行时。
如果您想要两者:
- 保留此仓库和 `render.yaml` 以部署MCP服务器
- 为后台作业创建单独的Render Workflows项目
- 根据需要让工作流调用已部署的MCP服务器或其他API
## Docker Compose
对于使用Docker Compose进行本地开发或自托管:
1. 复制示例环境文件并设置您的凭证:
```bash
cp mcp-server/.env.example .env
# 使用您的ACTUAL_SERVER_URL、ACTUAL_PASSWORD、ACTUAL_BUDGET_SYNC_ID和BEARER_TOKEN编辑.env
```
2. 启动服务器:
```bash
docker compose up
```
服务器在端口3000上以远程HTTP模式启动,并启用写入访问。
3. 使用额外的日志进行开发:
```bash
docker compose -f docker-compose.yml -f docker-compose.dev.yml up
```
预算数据保存在一个命名的Docker卷(`actual-data`)中。使用 `/health` 进行活动检查,使用 `/ready` 进行就绪检查。
## 安全性和公开准备
- 在共享仓库之前,轮换任何已公开的凭证、承载令牌、同步ID和本地检查令牌。
- 在推送公共分支之前,重写git历史记录以删除以前提交的包含机密的文件或值。
- 运行 `pre-commit run --all-files` 和 `pnpm --filter actual-mcp public:check` 以验证工作树是否安全公开。
- 仅在 `.local-reconciliation/` 下保留私有核对数据、报表导出、备份zip文件和临时审计输出。
## 仓库布局
```text
.
+-- mcp-server/ # 公共产品代码和包脚本
+-- docs/ # 公共贡献者文档
+-- .github/ # 公共CI和仓库自动化
+-- .local-reconciliation/ # 私有本地财务工作空间(已忽略)
+-- .actual-data/ # 私有本地实际缓存/状态(已忽略)
+-- tmp/ # 私有临时输出(已忽略)
+-- render.yaml # 公共部署蓝图
`-- .pre-commit-config.yaml # 公共仓库卫生检查
```
## 分支保护
强烈建议在仓库的 `main` 分支上启用分支保护,以强制执行代码质量和安全标准。
配置分支保护时,请启用以下必需状态检查:
- `CI Pass` (此作业汇总了Lint、类型检查、测试、构建和Docker构建检查的结果)
- `Analyze (javascript-typescript)` (来自CodeQL)
这可以防止合并具有失败测试、回归或高严重性漏洞的代码。
## 架构
系统由三个主要组件组成,通过模型上下文协议(MCP)或Actual的内部同步进行通信:
```text
+-----------------------+ +-------------------+ +-------------+
| 实际预算服务器 | <---> | 实际MCP服务器 | <---> | MCP客户端 |
| (Node.js/SQLite) | 同步 | (Hono/HTTP/stdio) | MCP | (Claude, |
+-----------------------+ +-------------------+ | 光标...) |
```
### 可流式HTTP传输和预算范围
在远程HTTP模式下运行服务器时,服务器为每个经过身份验证的可流式HTTP会话分配一个MCP服务器实例(`McpServer`)。但是,实际客户端库(`@actual-app/api`)及其连接仍然是**进程全局的**。空闲会话通过 `MCP_SESSION_TTL_MINUTES` 自动修剪,但每个活动会话仍然共享**一个加载的预算**、缓存层、同步循环和连接健康探测。
### 工具结构
工具、提示和资源使用 `src/mcp/` 下的声明式MCP注册进行结构化。这允许显式的安全注释、结构化的工具结果和客户端的轻松发现。
## 部署
### Render部署
在部署到Render的免费层或标准Web服务时,请注意**临时磁盘限制**。由于Actual使用SQLite,存储在MCP服务器实例上的本地数据将在重启时丢失。
**解决方案:** 确保您同步到持久的实际预算服务器。MCP服务器充当临时客户端。设置一个非零的 `AUTO_SYNC_INTERVAL_MINUTES` 以保持缓存读取的新鲜度。
### 环境变量
| 变量 | 描述 | 默认值 |
|----------|-------------|---------|
| `ACTUAL_SERVER_URL` | 您的实际预算服务器网址 | |
| `ACTUAL_PASSWORD` | 实际服务器密码(使用此密码或 `ACTUAL_SESSION_TOKEN`) | |
| `ACTUAL_SESSION_TOKEN` | 身份验证的会话令牌(使用此令牌或 `ACTUAL_PASSWORD`) | |
| `ACTUAL_BUDGET_SYNC_ID` | 您的预算同步ID | |
| `BEARER_TOKEN` | 客户端连接MCP服务器在HTTP模式下所需的令牌 | |
| `PORT` | MCP HTTP服务器端口 | 3000 |
| `MCP_SESSION_TTL_MINUTES`| 空闲HTTP会话被修剪的时间 | |
| `AUTO_SYNC_INTERVAL_MINUTES`| 自动同步间隔 | 5 |
| `MCP_ALLOWED_ORIGINS` | 浏览器客户端的允许来源头列表 | |
| `LOG_LEVEL` | Pino日志级别(`trace`、`debug`、`info`、`warn`、`error`) | `info` |
| `MCP_RATE_LIMIT_RPM` | 每分钟每个承载令牌在 `/mcp` 上的最大请求数 | 60 |
### 常见生产配置
- **反向代理:** 在服务器前面终止TLS(例如,使用Nginx、Caddy或平台负载均衡器),并将承载令牌视为完全的读写机密。
- **网络限制:** 使用反向代理或平台控制限制对MCP服务器的网络访问。仅允许受信任的MCP客户端。
## 故障排除
- **冷启动后预算未加载:** 在远程设置中,与Actual的连接可能会断开或休眠。使用 `/reconnect` 端点或等待自动健康探测重新建立连接。
- **CORS错误:** 如果从基于Web的客户端使用HTTP传输,请确保在环境中设置 `MCP_ALLOWED_ORIGINS` 以允许客户端的来源。
- **速率限制错误:** 如果遇到速率限制,可以调整 `MCP_RATE_LIMIT_RPM` (默认为每分钟60个请求),或确保客户端没有激进地轮询。
- **健康检查:** 使用 `/health` 端点进行标准活动检查,使用 `/ready` 验证Actual连接准备情况。
## 开发
### 使用Docker Compose在本地运行
您可以使用Docker Compose在本地运行MCP服务器与其他服务一起:
```yaml
version: '3'
services:
actual-mcp:
build:
context: .
dockerfile: mcp-server/Dockerfile
ports:
- "3000:3000"
environment:
- ACTUAL_SERVER_URL=https://actual.example.com
- ACTUAL_PASSWORD=your-password
- ACTUAL_BUDGET_SYNC_ID=your-sync-id
- BEARER_TOKEN=your-secure-token
```
### 运行测试
要运行测试套件,请从根目录使用工作区 `test` 脚本:
```bash
pnpm --filter actual-mcp test
```
对于针对实际工具表面的烟雾测试:
```bash
pnpm --filter actual-mcp test:tools:all
```
### 添加新工具
1. 在 `mcp-server/src/mcp/tools/` 下创建新模块。
2. 使用Zod定义工具的输入模式。
3. 在 `mcp-server/src/mcp/tools/index.ts` 中注册工具,确保声明是否需要写入访问或高级权限。
## 工具参考
以下是所有可用的MCP工具及其输入参数和示例输出的列表。
### 只读核心
- **`audit-historical-transfers`**: 审计已导入的交易以获取严格的历史转移候选者。
- *输入:* 无
- *输出示例:* `{"type": "audit-results", "data": [{"id": "...", "amount": 1000}]}`
- **`audit-uncategorized-transactions`**: 大规模审计未分类的交易。
- *输入:* 无
- *输出示例:* `{"type": "audit-results", "data": [{"id": "...", "payee": "Unknown"}]}`
- **`balance-history`**: 跟踪账户余额随时间的变化,生成月快照。
- *输入:* `accountId`
- *输出示例:* `{"accountId": "...", "history": [{"month": "2024-01", "balance": 1000}]}`
- **`get-account-balance`**: 检查特定账户的当前或历史余额。
- *输入:* `accountId`
- *输出示例:* `{"accountId": "...", "balance": 5000}`
- **`get-accounts`**: 列出所有账户及其当前余额。
- *输入:* 无
- *输出示例:* `[{"id": "...", "name": "Checking", "balance": 5000}]`
- **`get-budget-month`**: 查看特定月份的预算详情。
- *输入:* `month`(YYYY-MM)
- *输出示例:* `{"month": "2024-01", "income": 5000, "budgeted": 4000}`
- **`get-financial-insights`**: 获取预先分析的财务健康总结。
- *输入:* 无
- *输出示例:* `{"health": "good", "insights": ["Savings rate is 20%"]}`
- **`get-grouped-categories`**: 按组列出所有预算类别。
- *输入:* 无
- *输出示例:* `[{"id": "...", "name": "Bills", "categories": [{"id": "...", "name": "Rent"}]}]`
- **`get-payees`**: 列出所有商家和付款人,或搜索特定商家。
- *输入:* `search`(可选)
- *输出示例:* `[{"id": "...", "name": "Grocery Store"}]`
- **`get-rules`**: 列出自动分类规则。
- *输入:* 无
- *输出示例:* `[{"id": "...", "conditions": [...], "actions": [...]}]`
- **`get-schedules`**: 检索所有重复交易计划。
- *输入:* 无
- *输出示例:* `[{"id": "...", "name": "Rent", "amount": 1000}]`
- **`get-tags`**: 列出Actual Budget中的所有标签,或搜索特定标签。
- *输入:* `search`(可选)
- *输出示例:* `[{"id": "...", "name": "Travel"}]`
- **`get-transactions`**: 查询和过滤交易历史。
- *输入:* `accountId`(可选)、`limit`(可选)、`offset`(可选)
- *输出示例:* `{"transactions": [{"id": "...", "amount": -5000, "date": "2024-01-01"}]}`
- **`monthly-summary`**: 生成高级别的财务概述。
- *输入:* `months`(可选)
- *输出示例:* `{"summary": {"income": 15000, "expenses": 12000}}`
- **`recommend-budget-plan`**: 分析最近的预算历史并推荐类别目标。
- *输入:* `month`(YYYY-MM)
- *输出示例:* `{"recommendations": [{"categoryId": "...", "amount": 500}]}`
- **`spending-by-category`**: 按类别划分支出。
- *输入:* `month`(YYYY-MM)
- *输出示例:* `{"breakdown": [{"categoryId": "...", "amount": -2000}]}`
### 写入核心
- **`apply-budget-plan`**: 将类别预算建议应用于目标月份。
- *输入:* `month`、`recommendations`
- *输出示例:* `{"status": "success", "applied": 5}`
- **`apply-historical-transfers`**: 将严格的历史转移候选链接为实际转移。
- *输入:* `candidates`
- *输出示例:* `{"status": "success", "linked": 2}`
- **`create-schedule`**: 创建新的重复交易计划。
- *输入:* `name`、`amount`、`frequency`
- *输出示例:* `{"id": "...", "name": "New Schedule"}`
- **`create-transaction`**: 向账户添加新交易。
- *输入:* `accountId`、`date`、`amount`(以分表示)、`payeeName`、`categoryId`
- *输出示例:* `{"id": "...", "amount": -1000}`
- **`delete-schedule`**: 删除重复交易计划。
- *输入:* `id`
- *输出示例:* `{"status": "success"}`
- **`delete-transaction`**: 永久删除交易。
- *输入:* `id`
- *输出示例:* `{"status": "success"}`
- **`import-transaction-batch`**: 将结构化的交易批次导入Actual Budget。
- *输入:* `accountId`、`transactions`
- *输出示例:* `{"status": "success", "imported": 10}`
- **`import-transactions`**: 从连接的银行账户同步交易。
- *输入:* `accountId`
- *输出示例:* `{"status": "success", "synced": 5}`
- **`manage-category`**: 创建、更新或删除类别。
- *输入:* `action`、`id`(可选)、`name`(可选)、`groupId`(可选)
- *输出示例:* `{"status": "success", "category": {"id": "..."}}`
- **`manage-category-group`**: 创建、更新或删除类别组。
- *输入:* `action`、`id`(可选)、`name`(可选)
- *输出示例:* `{"status": "success", "group": {"id": "..."}}`
- **`manage-payee`**: 创建、更新或删除付款人。
- *输入:* `action`、`id`(可选)、`name`(可选)
- *输出示例:* `{"status": "success", "payee": {"id": "..."}}`
- **`manage-rule`**: 创建、更新或删除规则。
- *输入:* `action`、`id`(可选)、`conditions`(可选)、`actions`(可选)
- *输出示例:* `{"status": "success", "rule": {"id": "..."}}`
- **`manage-tag`**: 创建、更新或删除标签。
- *输入:* `action`、`id`(可选)、`name`(可选)
- *输出示例:* `{"status": "success", "tag": {"id": "..."}}`
- **`merge-payees`**: 合并重复的付款人。
- *输入:* `targetId`、`mergeIds`
- *输出示例:* `{"status": "success", "merged": 3}`
- **`reconcile-account`**: 将账户与对账单余额进行比较。
- *输入:* `accountId`、`statementBalance`
- *输出示例:* `{"status": "success", "reconciled": true}`
- **`set-account-starting-balance`**: 为现有账户创建或更新单一起始余额交易。
- *输入:* `accountId`、`balance`
- *输出示例:* `{"status": "success", "transactionId": "..."}`
- **`set-budget`**: 设置或更新特定月份的类别预算金额。
- *输入:* `month`、`categoryId`、`amount`
- *输出示例:* `{"status": "success", "updated": true}`
- **`update-schedule`**: 更新现有的重复交易计划。
- *输入:* `id`、`fields`
- *输出示例:* `{"status": "success", "schedule": {"id": "..."}}`
- **`update-transaction`**: 修改现有交易。
- *输入:* `id`、`fields`
- *输出示例:* `{"status": "success", "transaction": {"id": "..."}}`
### 高级(`--enable-advanced`)
- **`close-account`**: 关闭Actual Budget中的账户。
- *输入:* `accountId`
- *输出示例:* `{"status": "success", "closed": true}`
- **`get-budget-files`**: 列出所有可用的预算文件。
- *输入:* 无
- *输出示例:* `[{"id": "...", "name": "My Budget"}]`
- **`hold-budget`**: 保留下个月的预算金额。
- *输入:* `month`、`amount`
- *输出示例:* `{"status": "success", "held": true}`
- **`manage-account`**: 创建、更新或删除账户。
- *输入:* `action`、`id`(可选)、`name`(可选)、`type`(可选)
- *输出示例:* `{"status": "success", "account": {"id": "..."}}`
- **`reopen-account`**: 重新打开已关闭的账户。
- *输入:* `accountId`
- *输出示例:* `{"status": "success", "reopened": true}`
- **`reset-budget-hold`**: 重置(清除)特定月份的预算保留。
- *输入:* `month`
- *输出示例:* `{"status": "success", "reset": true}`
- **`switch-budget`**: 切换到不同的预算文件。
- *输入:* `id`(预算同步ID)
- *输出示例:* `{"status": "success", "switched": true}`
MCP 配置
以下是此 MCP Server 的配置信息,可直接复制到 Cursor 或其他 MCP 客户端中使用。
mcp.json
连接信息
猜你喜欢
暂无推荐服务器