chaimi-bookkeeping-mcp 2.2.4 → 2.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/server.js +101 -4
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chaimi-bookkeeping-mcp",
3
- "version": "2.2.4",
3
+ "version": "2.2.6",
4
4
  "description": "柴米记账 MCP Server - 支持 Claude、Cursor、OpenClaw、WorkBuddy 等 AI 工具直接记账",
5
5
  "main": "server.js",
6
6
  "bin": {
package/server.js CHANGED
@@ -84,9 +84,24 @@ const server = new Server(
84
84
  server.setRequestHandler(ListToolsRequestSchema, async () => {
85
85
  return {
86
86
  tools: [
87
+ {
88
+ name: 'quick_book',
89
+ description: '极简快捷记账 - 自动识别支出/收入,智能匹配分类。输入如:"午餐 30 元"、"工资 8000 元"、"木屋烧烤 35 元"',
90
+ inputSchema: {
91
+ type: 'object',
92
+ properties: {
93
+ name: { type: 'string', description: '商品/服务名称或自然语言描述(必填)' },
94
+ amount: { type: 'number', description: '金额(必填)' },
95
+ category: { type: 'string', description: '分类(可选,系统自动推荐)' },
96
+ store: { type: 'string', description: '商家名称(可选)' },
97
+ note: { type: 'string', description: '备注(可选)' },
98
+ },
99
+ required: ['name', 'amount'],
100
+ },
101
+ },
87
102
  {
88
103
  name: 'save_expense',
89
- description: '保存单商品消费记录(AI文字记账)',
104
+ description: '保存单商品消费记录(AI 文字记账)',
90
105
  inputSchema: {
91
106
  type: 'object',
92
107
  properties: {
@@ -97,8 +112,8 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
97
112
  unit: { type: 'string', description: '单位(如:斤、个、瓶)' },
98
113
  category: { type: 'string', description: '分类(如:餐饮、食品、交通)' },
99
114
  store: { type: 'string', description: '商家名称' },
100
- agentType: { type: 'string', description: 'Agent类型(如:workbuddy、claude、cursor)' },
101
- apiProvider: { type: 'string', description: 'AI提供商' },
115
+ agentType: { type: 'string', description: 'Agent 类型(如:workbuddy、claude、cursor)' },
116
+ apiProvider: { type: 'string', description: 'AI 提供商' },
102
117
  rawInput: { type: 'string', description: '用户原始输入' },
103
118
  },
104
119
  required: ['name', 'amount', 'price', 'quantity'],
@@ -351,8 +366,56 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
351
366
 
352
367
  // 根据工具类型选择处理流程
353
368
  switch (name) {
369
+ case 'quick_book': {
370
+ // 极简快捷记账:自动识别支出/收入,智能匹配分类
371
+ console.log('处理极简快捷记账...');
372
+
373
+ // 1. 判断是支出还是收入
374
+ const isIncome = isIncomeName(args.name);
375
+
376
+ // 2. 智能匹配分类
377
+ const category = args.category || getCategory(args.name);
378
+
379
+ // 3. 自动补全参数
380
+ const completedArgs = {
381
+ name: sanitizeString(args.name, 100),
382
+ amount: validateAmount(args.amount),
383
+ price: args.price || validateAmount(args.amount),
384
+ quantity: args.quantity || 1,
385
+ unit: args.unit || '个',
386
+ category: category,
387
+ store: sanitizeString(args.store, 100) || '未知商家',
388
+ note: sanitizeString(args.note, 500),
389
+ agentType: args.agentType || '',
390
+ apiProvider: args.apiProvider || '',
391
+ rawInput: args.rawInput || args.name,
392
+ };
393
+
394
+ // 4. 根据类型选择接口
395
+ if (isIncome) {
396
+ // 收入记账
397
+ console.log('识别为收入,调用 save_income...');
398
+ const mcpParams = convertParams('save_income', completedArgs);
399
+ result = await callMcpHub('addIncome', mcpParams, token);
400
+
401
+ if (result.success) {
402
+ userMessage = `✅ 记账成功\n\n| 收入来源 | 金额 | 分类 |\n|------|------|------|\n| ${completedArgs.name} | ${completedArgs.amount}元 | ${completedArgs.category || '其他收入'} |\n\n已保存到你的柴米记账小程序数据库。`;
403
+ }
404
+ } else {
405
+ // 支出记账
406
+ console.log('识别为支出,调用 save_expense...');
407
+ const mcpParams = convertParams('save_expense', completedArgs);
408
+ result = await callMcpHub('addExpense', mcpParams, token);
409
+
410
+ if (result.success) {
411
+ userMessage = `✅ 记账成功\n\n| 商品 | 金额 | 分类 | 商家 |\n|------|------|------|------|\n| ${completedArgs.name} | ${completedArgs.amount}元 | ${completedArgs.category || '其他'} | ${completedArgs.store} |\n\n已保存到你的柴米记账小程序数据库。`;
412
+ }
413
+ }
414
+ break;
415
+ }
416
+
354
417
  case 'save_expense': {
355
- // 步骤1:校验数据完整性
418
+ // 步骤 1:校验数据完整性
356
419
  console.log('校验消费数据完整性...');
357
420
  const validationResult = await callMcpPrompt(
358
421
  'validateResult',
@@ -663,6 +726,40 @@ function convertParams(toolName, args) {
663
726
  }
664
727
  }
665
728
 
729
+ // 智能分类:根据商品名称匹配分类
730
+ function getCategory(name) {
731
+ if (!name) return '其他';
732
+
733
+ const categoryMap = {
734
+ '餐饮': ['饭', '菜', '餐', '酒', '饮料', '咖啡', '茶', '早餐', '午餐', '晚餐', '夜宵', '烧烤', '火锅', '快餐', '外卖', '小吃', '奶茶', '面包', '蛋糕'],
735
+ '交通': ['车', '油', '票', '打车', '公交', '地铁', '加油', '停车', '租车', '火车', '飞机', '轮船', '客运'],
736
+ '购物': ['买', '购', '商场', '超市', '衣服', '鞋', '包', '化妆品', '护肤品', '数码', '电器', '家具', '日用品'],
737
+ '娱乐': ['玩', '游戏', '电影', '歌', 'KTV', '酒吧', '旅游', '景点', '门票', '健身', '运动', '书', '音乐'],
738
+ '医疗': ['药', '医', '病', '医院', '诊所', '体检', '疫苗', '牙科', '眼科', '门诊'],
739
+ '教育': ['学', '课', '培训', '考试', '学校', '学费', '教材', '文具', '培训费'],
740
+ '居住': ['房', '租', '物业', '水电', '燃气', '网络', '宽带', '话费', '维修', '装修'],
741
+ '工资': ['工资', '薪水', '奖金', '提成', '分红', '补贴', '津贴', '绩效'],
742
+ '其他收入': ['红包', '转账', '借款', '还款', '退款', '理赔', '中奖', '利息'],
743
+ };
744
+
745
+ for (const [category, keywords] of Object.entries(categoryMap)) {
746
+ if (keywords.some(keyword => name.includes(keyword))) {
747
+ return category;
748
+ }
749
+ }
750
+
751
+ return '其他';
752
+ }
753
+
754
+ // 判断是否为收入
755
+ function isIncomeName(name) {
756
+ if (!name) return false;
757
+
758
+ const incomeKeywords = ['工资', '薪水', '奖金', '提成', '分红', '补贴', '津贴', '绩效', '红包', '转账', '借款', '还款', '退款', '理赔', '中奖', '利息', '收入', '入账', '到账'];
759
+
760
+ return incomeKeywords.some(keyword => name.includes(keyword));
761
+ }
762
+
666
763
  // 获取月份最后一天
667
764
  function getMonthEndDate(yearMonth) {
668
765
  const [year, month] = yearMonth.split('-').map(Number);