chaimi-keep-mcp 3.3.3-beta.11 → 3.3.3-beta.13

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.
package/SKILL.md CHANGED
@@ -128,15 +128,19 @@ chaimi-keep-mcp ⭐ 本Skill
128
128
  └─ get_skill() 获取 SKILL.md 规范
129
129
  └─ references/response-templates.md 了解回复模板
130
130
 
131
- 第2步:拿Token
132
- └─ 文字记账:get_text_parse_prompt() 获取 Token 和解析模板
133
- └─ 小票记账:get_parse_prompt() 获取 Token 和解析模板
131
+ 第2步:拿凭证
132
+ └─ 文字记账:get_text_parse_prompt() 获取凭证和解析模板
133
+ └─ 小票记账:get_parse_prompt() 获取凭证和解析模板
134
+
135
+ 【强制流程】必须先调用此工具,让 AI 解析用户输入
136
+ 此工具会返回解析结果,你只需将结果原样传给 save_expense/save_income
137
+ ⚠️ 禁止自行解析或提取任何字段,必须让 AI 处理
134
138
 
135
139
  第3步:AI解析
136
- └─ 按模板解析用户输入,生成结构化数据 + _requestToken
140
+ └─ 按模板解析用户输入,生成结构化数据 + _flowmate
137
141
 
138
142
  第4步:执行记账
139
- └─ 调用工具(save_expense/income/receipt,带上 _requestToken
143
+ └─ 调用工具(save_expense/income/receipt,带上 _flowmate
140
144
  └─ 根据 _templateLocation 使用模板渲染美学回复
141
145
  ```
142
146
 
package/bin/record.js ADDED
@@ -0,0 +1,57 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * 柴米AI记账 - 直接记账 CLI
4
+ * 一步完成:解析文本 → 分类 → 调用云函数存储
5
+ */
6
+
7
+ const { callMcpHub } = require('../utils/api');
8
+ const { getToken } = require('../utils/auth');
9
+ const { parseText } = require('../utils/parser');
10
+
11
+ async function record(text, options = {}) {
12
+ try {
13
+ // 1. 解析文本
14
+ const parsed = await parseText(text);
15
+
16
+ // 2. 确定类型(收入/支出)
17
+ const type = options.type || parsed.type || 'expense';
18
+
19
+ // 3. 获取 token
20
+ const token = await getToken();
21
+
22
+ // 4. 调用云函数存储
23
+ const result = await callMcpHub(type === 'income' ? 'addIncome' : 'addExpense', {
24
+ ...parsed,
25
+ type,
26
+ rawInput: text
27
+ }, token);
28
+
29
+ if (result.success) {
30
+ console.log('✅ 记账成功!');
31
+ console.log(`金额:¥${parsed.amount}`);
32
+ console.log(`分类:${parsed.category}`);
33
+ console.log(`商品:${parsed.name}`);
34
+ } else {
35
+ console.error('❌ 记账失败:', result.error);
36
+ process.exit(1);
37
+ }
38
+ } catch (error) {
39
+ console.error('❌ 错误:', error.message);
40
+ process.exit(1);
41
+ }
42
+ }
43
+
44
+ // 解析命令行参数
45
+ const args = process.argv.slice(2);
46
+ const text = args[0];
47
+ const typeFlag = args.find(arg => arg.startsWith('--type='));
48
+ const type = typeFlag ? typeFlag.split('=')[1] : null;
49
+
50
+ if (!text) {
51
+ console.log('用法: chaimi-keep record "<记账文本>" [--type=income|expense]');
52
+ console.log('示例: chaimi-keep record "中午吃饭花了35元"');
53
+ console.log('示例: chaimi-keep record "工资收入5000" --type=income');
54
+ process.exit(1);
55
+ }
56
+
57
+ record(text, { type });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chaimi-keep-mcp",
3
- "version": "3.3.3-beta.11",
3
+ "version": "3.3.3-beta.13",
4
4
  "description": "柴米AI记账 MCP Server - 支持 Claude、Cursor、OpenClaw、WorkBuddy 等 AI 工具直接记账",
5
5
  "main": "server.js",
6
6
  "bin": {
package/server.js CHANGED
@@ -259,7 +259,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
259
259
  },
260
260
  {
261
261
  name: 'save_expense',
262
- description: '【文本记账-支出】用户提及支出/消费时用此工具。前置:必须先调用get_skill获取规范,再调用get_text_parse_prompt获取Token和解析模板。用法:mcporter call 柴米AI记账.save_expense _requestToken="RT..." name="午餐" amount=35 category="餐饮" rawInput="午餐35元"。注意:上传图片请用save_receipt',
262
+ description: '【文本记账-支出】用户提及支出/消费时用此工具。前置:必须先调用get_skill获取规范,再调用get_text_parse_prompt获取凭证和解析模板。用法:mcporter call 柴米AI记账.save_expense _flowmate="SOLINWANG..." name="午餐" amount=35 category="餐饮" rawInput="午餐35元"。注意:上传图片请用save_receipt',
263
263
  inputSchema: {
264
264
  type: 'object',
265
265
  properties: {
@@ -275,13 +275,14 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
275
275
  agentType: { type: 'string', description: '【必填】Agent类型,如:claude-desktop、cursor、openclaw、workbuddy、trae' },
276
276
  apiProvider: { type: 'string', description: '【必填】AI服务提供商,如:anthropic、openai、doubao、aliyun' },
277
277
  rawInput: { type: 'string', description: '【必填】用户的原始输入内容,用于记录用户原始请求' },
278
+ _flowmate: { type: 'string', description: '【必填】流程凭证,从get_text_parse_prompt获取的myflowmate值' },
278
279
  },
279
- required: ['name', 'amount', 'category', 'agentType', 'apiProvider', 'rawInput'],
280
+ required: ['name', 'amount', 'category', 'agentType', 'apiProvider', 'rawInput', '_flowmate'],
280
281
  },
281
282
  },
282
283
  {
283
284
  name: 'save_receipt',
284
- description: '【图片记账-小票】用户上传小票/发票/收据图片时用此工具。前置:必须先调用get_skill获取规范,再调用get_parse_prompt获取Token和解析模板。用法:mcporter call 柴米AI记账.save_receipt _requestToken="RT..." store="超市" totalAmount=156.5 items="[...]"。注意:文字描述请用save_expense/save_income',
285
+ description: '【图片记账-小票】用户上传小票/发票/收据图片时用此工具。前置:必须先调用get_skill获取规范,再调用get_parse_prompt获取凭证和解析模板。用法:mcporter call 柴米AI记账.save_receipt _flowmate="SOLINWANG..." store="超市" totalAmount=156.5 items="[...]"。注意:文字描述请用save_expense/save_income',
285
286
  inputSchema: {
286
287
  type: 'object',
287
288
  properties: {
@@ -322,8 +323,9 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
322
323
  agentType: { type: 'string', description: '【必填】Agent类型:claude-desktop、cursor、openclaw、workbuddy、trae' },
323
324
  apiProvider: { type: 'string', description: '【必填】AI服务提供商:anthropic、openai、doubao、aliyun' },
324
325
  rawInput: { type: 'string', description: '【必填】用户的原始输入内容' },
326
+ _flowmate: { type: 'string', description: '【必填】流程凭证,从get_parse_prompt获取的myflowmate值' },
325
327
  },
326
- required: ['store', 'items', 'storeCategory', 'storeSubCategory', 'agentType', 'apiProvider', 'rawInput'],
328
+ required: ['store', 'items', 'storeCategory', 'storeSubCategory', 'agentType', 'apiProvider', 'rawInput', '_flowmate'],
327
329
  },
328
330
  },
329
331
  {
@@ -409,7 +411,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
409
411
  },
410
412
  {
411
413
  name: 'save_income',
412
- description: '【文本记账-收入】用户提及收入关键词(工资、红包、转账、退款等)时用此工具。前置:必须先调用get_skill获取规范,再调用get_text_parse_prompt获取Token和解析模板。用法:mcporter call 柴米AI记账.save_income _requestToken="RT..." name="红包" amount=100 category="礼金" rawInput="收红包100元"',
414
+ description: '【文本记账-收入】用户提及收入关键词(工资、红包、转账、退款等)时用此工具。前置:必须先调用get_skill获取规范,再调用get_text_parse_prompt获取凭证和解析模板。用法:mcporter call 柴米AI记账.save_income _flowmate="SOLINWANG..." name="红包" amount=100 category="礼金" rawInput="收红包100元"',
413
415
  inputSchema: {
414
416
  type: 'object',
415
417
  properties: {
@@ -422,13 +424,14 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
422
424
  agentType: { type: 'string', description: '【必填】Agent类型,如:claude-desktop、cursor、openclaw、workbuddy、trae' },
423
425
  apiProvider: { type: 'string', description: '【必填】AI服务提供商,如:anthropic、openai、doubao、aliyun' },
424
426
  rawInput: { type: 'string', description: '【必填】用户的原始输入内容,用于记录用户原始请求' },
427
+ _flowmate: { type: 'string', description: '【必填】流程凭证,从get_text_parse_prompt获取的myflowmate值' },
425
428
  },
426
- required: ['name', 'amount', 'category', 'agentType', 'apiProvider', 'rawInput'],
429
+ required: ['name', 'amount', 'category', 'agentType', 'apiProvider', 'rawInput', '_flowmate'],
427
430
  },
428
431
  },
429
432
  {
430
433
  name: 'get_text_parse_prompt',
431
- description: '【不调用100%失败】获取文字记账解析的Prompt模板和requestToken。⚠️ 文字/语音记账必须先调用此工具获取Token,AI解析时必须返回_requestToken字段,否则save_expense/save_income会报MISSING_TOKEN错误!',
434
+ description: '【不调用100%失败】获取文字记账解析的Prompt模板和流程凭证。⚠️ 文字/语音记账必须先调用此工具获取凭证,AI解析时必须返回_flowmate字段,否则save_expense/save_income会报MISSING_TOKEN错误!',
432
435
  inputSchema: {
433
436
  type: 'object',
434
437
  properties: {
@@ -439,7 +442,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
439
442
  },
440
443
  {
441
444
  name: 'get_parse_prompt',
442
- description: '【不调用100%失败】获取小票图片解析的Prompt模板和requestToken。⚠️ 小票记账必须先调用此工具获取Token,AI解析时必须返回_requestToken字段,否则save_receipt会报MISSING_TOKEN错误!',
445
+ description: '【不调用100%失败】获取小票图片解析的Prompt模板和流程凭证。⚠️ 小票记账必须先调用此工具获取凭证,AI解析时必须返回_flowmate字段,否则save_receipt会报MISSING_TOKEN错误!',
443
446
  inputSchema: {
444
447
  type: 'object',
445
448
  properties: {
@@ -1625,8 +1628,8 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
1625
1628
  systemPrompt: promptResult.data.systemPrompt,
1626
1629
  userPromptTemplate: promptResult.data.userPromptTemplate,
1627
1630
  examples: promptResult.data.examples,
1628
- requestToken: promptResult.data.requestToken,
1629
- instructions: '请将 systemPrompt 作为 system message,把小票图片作为 user message,调用你的大模型进行解析。解析完成后,调用 save_receipt 工具保存结果。⚠️ 注意:AI解析结果必须包含 _requestToken 字段!'
1631
+ myflowmate: promptResult.data.myflowmate,
1632
+ instructions: '请将 systemPrompt 作为 system message,把小票图片作为 user message,调用你的大模型进行解析。解析完成后,调用 save_receipt 工具保存结果。⚠️ 注意:AI解析结果必须包含 _flowmate 字段!'
1630
1633
  }
1631
1634
  };
1632
1635
  // 【新增】返回模板位置信息(Server只返回原始数据,Agent使用模板渲染)
@@ -1653,7 +1656,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
1653
1656
  prompt: promptResult.data.prompt,
1654
1657
  currentDate: promptResult.data.currentDate,
1655
1658
  currentTime: promptResult.data.currentTime,
1656
- requestToken: promptResult.data.requestToken,
1659
+ myflowmate: promptResult.data.myflowmate,
1657
1660
  instructions: promptResult.data.instructions
1658
1661
  }
1659
1662
  };
@@ -2121,7 +2124,7 @@ function convertParams(toolName, args) {
2121
2124
  apiProvider: sanitizeString(args.apiProvider, 50) || '',
2122
2125
  mcpVersion: MCP_VERSION,
2123
2126
  source: 'mcp_txt_expense',
2124
- _requestToken: args._requestToken,
2127
+ _flowmate: args._flowmate,
2125
2128
  };
2126
2129
  }
2127
2130
 
@@ -2178,11 +2181,11 @@ function convertParams(toolName, args) {
2178
2181
  source: 'mcp_receipt',
2179
2182
  storeCategory: sanitizeString(args.storeCategory, 50) || '其他',
2180
2183
  storeSubCategory: sanitizeString(args.storeSubCategory, 50) || '其他',
2181
- _requestToken: args._requestToken,
2184
+ _flowmate: args._flowmate,
2182
2185
  };
2183
2186
  }
2184
2187
 
2185
- case 'get_expenses': {
2188
+ case 'save_receipt': {
2186
2189
  // 【新增】支持 period 参数
2187
2190
  const periodDates = args.period ? parsePeriod(args.period) : {};
2188
2191
  return {
@@ -2220,7 +2223,7 @@ function convertParams(toolName, args) {
2220
2223
  apiProvider: sanitizeString(args.apiProvider, 50) || '',
2221
2224
  mcpVersion: MCP_VERSION,
2222
2225
  source: 'mcp_txt_income',
2223
- _requestToken: args._requestToken,
2226
+ _flowmate: args._flowmate,
2224
2227
  };
2225
2228
 
2226
2229
  default:
@@ -0,0 +1,15 @@
1
+ /**
2
+ * 分类标准化映射器
3
+ * 将 Agent 提取的关键词映射到标准分类
4
+ * 确保分类一致性,便于后续统计
5
+ */
6
+
7
+ // 标准分类列表
8
+ const STANDARD_CATEGORIES = [
9
+ '餐饮', '购物', '交通', '蔬菜', '水果', '零食', '运动', '通讯', '服饰', '美容',
10
+ '住房', '孩子', '长辈', '社交', '旅行', '烟酒', '数码', '汽车', '医疗', '办公',
11
+ '学习', '宠物', '礼金', '亲友', '日用', '休闲娱乐', '维修', '居家', '饮品', '鲜花',
12
+ '追星', '首饰', '借出', '保险', '网络虚拟', '生活缴费', '转账', '书籍', '捐赠', '彩票', '快递', '其他'
13
+ ];
14
+
15
+ // 关键词到