🚀 Jarvis — 个人财务MCP服务器 + 代理
Jarvis是一个用于个人财务跟踪的模型上下文协议(MCP)服务器,由Notion数据库提供支持。它包含一个由大语言模型(LLM)驱动的代理(Gemini),可将自然语言解析为结构化的工具调用。
⚠️ 重要提示
本项目与特定的Notion工作区紧密耦合:
Jarvis Notion站点
数据库模式、关系和公式均在Notion中配置。要使用此项目,请复制Notion模板后继续操作。
🚀 快速开始
1. 前提条件
- Node.js 18+
- 具备API集成功能的Notion账户
- Gemini API密钥
2. Notion数据库设置
在Notion中创建6个具有以下模式的数据库:
| 数据库 |
必需属性 |
| 支出 |
标题、金额(数字)、日期(日期)、账户(关联→账户)、类别(关联→类别)、资金账户(关联→账户)、已结清(复选框)、结清方(关联→付款)、已支付金额(数字)、备注(富文本) |
| 收入 |
标题、金额(数字)、日期(日期)、账户(关联→账户)、类别(关联→类别)、预分解金额(数字)、预算(关联→预算规则)、备注(富文本) |
| 付款 |
标题、金额(数字)、日期(日期)、转出账户(关联→账户)、转入账户(关联→账户)、已结清支出(关联→支出)、备注(富文本) |
| 账户 |
标题、账户类型(选择:信用卡/支票账户/储蓄账户/投资账户)、初始余额(数字)、分类账余额(公式)、信用卡预留金额(汇总)、可用支出金额(公式)、总收入(汇总)、总支出(汇总)、总入账金额(汇总)、总出账金额(汇总) |
| 类别 |
标题(类别名称:食品杂货、外出就餐、Lyft等) |
| 预算规则 |
标题(规则名称)、账户(关联→账户)、百分比(0 - 1之间的数字) |
3. 环境变量
将 env.example 复制到 .env 并填写以下内容:
NOTION_API_KEY=secret_xxx
EXPENSES_DB_ID=xxx
INCOME_DB_ID=xxx
PAYMENTS_DB_ID=xxx
ACCOUNTS_DB_ID=xxx
CATEGORIES_DB_ID=xxx
BUDGET_RULES_DB_ID=xxx
GEMINI_API_KEY=xxx
PORT=3000
AGENT_PORT=4000
MCP_BASE_URL=http://localhost:3000
4. 安装与运行
npm install
npm run mcp
npm run agent
✨ 主要特性
- 统一的
add_transaction:一个工具即可处理支出、收入和付款。
- 账户级余额计算:信用卡欠款通过总支出减去总付款计算,而非单个支出的结清状态。
- 自动结清付款:添加付款时,自动将匹配的未结清支出标记为已结清(更新资金账户预留金额)。
- 类别验证:未知类别会被转换为“其他”。
- 类别缓存:从Notion获取类别,缓存时间为5分钟。
- 与LLM无关的设计:代理层可以将Gemini替换为任何大语言模型。
- 批量操作:高效地批量更新交易和类别。
📦 安装指南
1. 前提条件
- Node.js 18+
- 具备API集成功能的Notion账户
- Gemini API密钥
2. Notion数据库设置
在Notion中创建6个具有特定模式的数据库,具体模式见上文“快速开始”部分。
3. 环境变量
复制 env.example 到 .env 并填写相关信息,包括Notion API密钥、数据库ID、Gemini API密钥等。
4. 安装与运行
npm install
npm run mcp
npm run agent
💻 使用示例
基础用法
MCP服务器 (localhost:3000)
POST /mcp
Content-Type: application/json
Accept: application/json, text/event-stream
{
"jsonrpc": "2.0",
"id": "1",
"method": "tools/call",
"params": {
"name": "add_transaction",
"arguments": {
"amount": 12.34,
"transaction_type": "expense",
"account": "sapphire",
"funding_account": "checkings",
"category": "groceries",
"date": "2026-01-10",
"note": "Trader Joes"
}
}
}
代理服务器 (localhost:4000)
POST /chat
Content-Type: application/json
{
"message": "spent $12.34 on groceries at Trader Joes yesterday"
}
响应:
{
"reply": "added expense of $12.34 to sapphire (category: groceries).",
"meta": {
"action": { "action": "add_transaction", "args": {...} },
"mcp": {...}
}
}
高级用法
可以根据实际需求调整请求参数,例如批量添加交易、更新交易类别等。以下是批量添加交易的示例:
POST /mcp
Content-Type: application/json
Accept: application/json, text/event-stream
{
"jsonrpc": "2.0",
"id": "1",
"method": "tools/call",
"params": {
"name": "add_transactions_batch",
"arguments": {
"transactions": [
{
"amount": 10.0,
"transaction_type": "expense",
"account": "sapphire",
"funding_account": "checkings",
"category": "groceries",
"date": "2026-01-10",
"note": "Trader Joes"
},
{
"amount": 20.0,
"transaction_type": "income",
"account": "checkings",
"category": "salary",
"date": "2026-01-11",
"note": "Monthly salary"
}
]
}
}
}
📚 详细文档
MCP工具参考
交易
| 工具 |
描述 |
关键参数 |
add_transaction |
添加支出、收入或付款 |
金额、交易类型、账户、类别、日期、备注、资金账户、转出账户、转入账户 |
add_transactions_batch |
批量添加多个交易 |
交易列表[] |
类别
| 工具 |
描述 |
关键参数 |
get_categories |
列出有效类别(缓存) |
— |
get_uncategorized_transactions |
获取类别为“其他”的支出 |
— |
update_transaction_category |
更新一项支出的类别 |
支出ID、类别 |
update_transaction_categories_batch |
批量更新类别 |
更新列表[] |
预算
| 工具 |
描述 |
关键参数 |
set_budget_rule |
创建/更新预算分配 |
预算名称、预算列表[](账户 + 百分比) |
split_paycheck |
按规则拆分总工资 |
总金额、预算名称、日期 |
API端点
MCP服务器 (localhost:3000)
POST /mcp
Content-Type: application/json
Accept: application/json, text/event-stream
{
"jsonrpc": "2.0",
"id": "1",
"method": "tools/call",
"params": {
"name": "add_transaction",
"arguments": {
"amount": 12.34,
"transaction_type": "expense",
"account": "sapphire",
"funding_account": "checkings",
"category": "groceries",
"date": "2026-01-10",
"note": "Trader Joes"
}
}
}
代理服务器 (localhost:4000)
POST /chat
Content-Type: application/json
{
"message": "spent $12.34 on groceries at Trader Joes yesterday"
}
响应:
{
"reply": "added expense of $12.34 to sapphire (category: groceries).",
"meta": {
"action": { "action": "add_transaction", "args": {...} },
"mcp": {...}
}
}
有效账户
| 类型 |
值 |
| 所有账户 |
支票账户、短期储蓄账户、账单账户、自由无限信用卡、蓝宝石信用卡、经纪账户、罗斯个人退休账户、Spaxx |
| 资金账户 |
支票账户、账单账户、短期储蓄账户 |
| 信用卡 |
蓝宝石信用卡、自由无限信用卡 |
余额模型
账户余额通过Notion公式在账户级别进行计算,而非通过汇总单个支出状态。
分类账余额 公式
if(account_type == "credit",
total_expenses - total_payments_in,
starting_balance + total_income - total_payments_out - total_expenses
)
- 信用卡:欠款 = 消费 - 已收到的付款。付款会立即全额减少余额,无论单个支出是否结清。
- 借记卡/储蓄账户:余额 = 初始余额 + 收入 - 支出 - 直接费用。
信用卡预留金额(汇总)
汇总 资金账户 为此账户的信用卡支出的 欠款金额。显示资金账户(如支票账户)为未支付的信用卡支出预留了多少金额。
可用支出金额(公式)
ledger_balance - reserved_for_cc
支出结清(对账)
通过API创建付款时,payments.ts 会自动结清匹配的支出(先结清最早的支出)。这会设置每个支出的 已支付金额,从而减少 欠款金额(公式:金额 - 已支付金额),进而减少资金账户的 信用卡预留金额。结清操作 对于资金账户的准确性至关重要,但 不影响信用卡的 分类账余额。
示例自然语言输入(代理)
| 输入 |
推断操作 |
| "spent $12 on groceries" |
add_transaction(支出) |
| "hunt paid 2500" |
split_paycheck(预算:hunt) |
| "paid $300 to sapphire" |
add_transaction(付款) |
| "what categories can I use?" |
get_categories |
| "show me uncategorized" |
get_uncategorized_transactions |
🔧 技术细节
架构
┌───────────────────────────────────────────────────────────────────┐
│ 用户输入 │
│ "spent $12 on groceries at Trader Joes" │
└───────────────────────────────────────────────────────────────────┘
│
▼
┌───────────────────────────────────────────────────────────────────┐
│ 代理服务器 (端口 4000) │
│ POST /chat │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ Gemini客户端 (gemini_client.ts) 或LLM提供商 │ │
│ │ - 将自然语言解析为结构化操作 │ │
│ │ - 推断:操作类型、金额、类别、账户等 │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ MCP客户端 (mcp_client.ts) │ │
│ │ - 通过JSON-RPC调用MCP工具 │ │
│ └─────────────────────────────────────────────────────────────┘ │
└───────────────────────────────────────────────────────────────────┘
│
▼
┌───────────────────────────────────────────────────────────────────┐
│ MCP服务器 (端口 3000) │
│ POST /mcp │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 注册工具 (server.ts) │ │
│ │ - add_transaction - get_categories │ │
│ │ - add_transactions_batch - get_uncategorized_transactions │ │
│ │ - set_budget_rule - update_transaction_category │ │
│ │ - split_paycheck - update_transaction_categories_batch │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 服务层 │ │
│ │ - transactions.ts (add_transaction, batch) │ │
│ │ - payments.ts (create_payment, auto-clear expenses) │ │
│ │ - categories.ts (get/update uncategorized) │ │
│ │ - budgets.ts (set_budget_rule, split_paycheck) │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ Notion层 (notion/client.ts, notion/utils.ts) │ │
│ │ - API客户端 + 数据库ID │ │
│ │ - 类别缓存 + 验证 │ │
│ │ - 账户/预算规则查找 │ │
│ └─────────────────────────────────────────────────────────────┘ │
└───────────────────────────────────────────────────────────────────┘
│
▼
┌───────────────────────────────────────────────────────────────────┐
│ Notion数据库 │
│ - 支出数据库 - 收入数据库 - 付款数据库 │
│ - 账户数据库 - 类别数据库 - 预算规则数据库 │
└───────────────────────────────────────────────────────────────────┘
项目结构
jarvis/
├── src/
│ ├── mcp/ # MCP服务器 (端口 3000)
│ │ ├── server.ts # Express + MCP工具注册
│ │ ├── constants.ts # 共享账户枚举 + 验证器
│ │ ├── notion/
│ │ │ ├── client.ts # Notion API客户端 + 数据库ID
│ │ │ ├── types.ts # 数据源API的类型包装器
│ │ │ └── utils.ts # 辅助工具:类别缓存、查找
│ │ └── services/
│ │ ├── transactions.ts # add_transaction, batch
│ │ ├── payments.ts # create_payment, auto-clear
│ │ ├── categories.ts # uncategorized + updates
│ │ └── budgets.ts # 预算规则 + 工资拆分
│ │
│ └── agent/ # 代理服务器 (端口 4000)
│ ├── agent_server.ts # Express /chat端点
│ ├── mcp_client.ts # MCP的JSON-RPC客户端
│ └── llm/
│ ├── gemini_client.ts # Gemini提示 + 操作解析器
│ └── claude_prompt.md # Claude系统提示参考
│
├── package.json
├── tsconfig.json
├── .env # 环境变量 (未提交)
└── README.md
开发
npm run typecheck
npm run mcp
npm run agent
📄 许可证
本项目采用MIT许可证。