chaimi-keep-mcp 3.1.34 → 3.1.36-beta.1

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 (4) hide show
  1. package/README.md +6 -0
  2. package/SKILL.md +34 -0
  3. package/package.json +1 -1
  4. package/server.js +60 -36
package/README.md CHANGED
@@ -141,6 +141,12 @@ AI 会自动调用 `save_income` 工具记录收入。
141
141
 
142
142
  ## 更新日志
143
143
 
144
+ ### v3.1.35 (2026-04-15)
145
+ - **新增** 商品子分类支持:`subCategory` 字段,支持叶菜类、根茎类、猪肉类等超市细分类目
146
+ - **新增** 计价单位支持:`unit` 字段,支持元/500g、元/个、元/盒、元/袋等多种单位
147
+ - **新增** 市场单价支持:`marketPrice` 字段,用于记录单价数值
148
+ - **优化** 字段描述:更贴近超市购物场景的分类描述
149
+
144
150
  ### v3.1.34 (2026-04-14)
145
151
  - **修复** 日期/时区处理:纯日期格式默认使用12:00,不再使用当前服务器时间
146
152
  - **优化** SKILL.md 精简:从385行精简到176行,聚焦Agent必须执行的行为规范
package/SKILL.md CHANGED
@@ -99,6 +99,36 @@ argument-hint: "[记账内容]"
99
99
 
100
100
  **必填字段:** `name`、`amount`、`category`、`date`
101
101
 
102
+ **可选字段:**
103
+ - `subCategory`:子分类(可选)
104
+ - `unit`:单位(可选)
105
+ - `marketPrice`:市场单价(可选)
106
+
107
+ ---
108
+
109
+ ### 收入记账(save_income)
110
+
111
+ **流程:**
112
+ 1. 调用 `get_text_parse_prompt()` 获取解析 Prompt
113
+ 2. 使用 Prompt 解析用户输入,获取 JSON 结果
114
+ 3. 调用 `save_income` 保存(传入所有解析结果字段)
115
+
116
+ **Agent 必须执行的时间语义解析:**
117
+ | 用户说法 | 解析为 |
118
+ |---------|--------|
119
+ | "工资"、"收入" | 09:00(默认工作时间) |
120
+ | "红包"、"奖金" | 具体时间或当前时间 |
121
+ | 无时间信息 | 使用当前时间 |
122
+
123
+ **重要:** 最终传入的 `date` 参数必须包含时间部分,格式:`2026-04-14T09:00:00+08:00`
124
+
125
+ **必填字段:** `name`、`amount`、`category`、`date`
126
+
127
+ **可选字段:**
128
+ - `subCategory`:子分类(可选)
129
+ - `unit`:单位(可选)
130
+ - `marketPrice`:市场单价(可选)
131
+
102
132
  ---
103
133
 
104
134
  ### 小票记账(save_receipt)
@@ -117,6 +147,10 @@ argument-hint: "[记账内容]"
117
147
  - `originalAmount`:原价(优惠前)
118
148
  - `discountAmount`:优惠金额
119
149
  - `items`:商品数组,每个商品必须有 `name`、`amount`、`price`、`quantity`、`category`
150
+ - `category`:主分类(如:蔬菜、肉类、水果、水产,常见超市购物分类)
151
+ - `subCategory`:子分类(如:叶菜类、根茎类、猪肉类,超市细分类目),推荐填写
152
+ - `unit`:计价单位(如:元/500g、元/个、元/盒、元/袋)
153
+ - `marketPrice`:单价,根据 unit 计算,如 unit=元/500g,则 marketPrice=金额÷重量(g)×500
120
154
 
121
155
  ---
122
156
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chaimi-keep-mcp",
3
- "version": "3.1.34",
3
+ "version": "3.1.36-beta.1",
4
4
  "description": "柴米记账 MCP Server - 支持 Claude、Cursor、OpenClaw、WorkBuddy 等 AI 工具直接记账",
5
5
  "main": "server.js",
6
6
  "bin": {
package/server.js CHANGED
@@ -139,16 +139,19 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
139
139
  properties: {
140
140
  name: { type: 'string', description: '商品名称(必填)' },
141
141
  amount: { type: 'number', description: '金额(必填)' },
142
- category: { type: 'string', description: '分类(必填,如:餐饮、食品、交通)' },
142
+ category: { type: 'string', description: '【必填】分类,如:餐饮、食品、交通' },
143
+ subCategory: { type: 'string', description: '子分类(可选)' },
144
+ unit: { type: 'string', description: '单位(可选)' },
145
+ marketPrice: { type: 'string', description: '市场单价(可选)' },
143
146
  store: { type: 'string', description: '商家名称(可选)' },
144
147
  date: { type: 'string', description: '消费时间(ISO格式)(可选)' },
145
148
  note: { type: 'string', description: '备注(可选)' },
146
- agentType: { type: 'string', description: '【推荐自动填充】Agent类型,如:claude-desktop、cursor、openclaw、workbuddy、trae' },
147
- apiProvider: { type: 'string', description: '【推荐自动填充】AI服务提供商,如:anthropic、openai、doubao、aliyun' },
148
- rawInput: { type: 'string', description: '【推荐自动填充】用户的原始输入内容,用于记录用户原始请求' },
149
+ agentType: { type: 'string', description: '【必填】Agent类型,如:claude-desktop、cursor、openclaw、workbuddy、trae' },
150
+ apiProvider: { type: 'string', description: '【必填】AI服务提供商,如:anthropic、openai、doubao、aliyun' },
151
+ rawInput: { type: 'string', description: '【必填】用户的原始输入内容,用于记录用户原始请求' },
149
152
  mcp_version: { type: 'string', description: 'MCP Server 版本号(自动填充)' },
150
153
  },
151
- required: ['name', 'amount'],
154
+ required: ['name', 'amount', 'category', 'agentType', 'apiProvider', 'rawInput'],
152
155
  },
153
156
  },
154
157
  {
@@ -175,74 +178,94 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
175
178
  originalName: { type: 'string', description: '原始商品名称(含规格)' },
176
179
  price: { type: 'number', description: '【必填】单价' },
177
180
  quantity: { type: 'number', description: '【必填】数量' },
178
- unit: { type: 'string', description: '单位,如:斤、个、份' },
181
+ unit: { type: 'string', description: '【必填】计价单位(如:元/500g、元/个、元/盒、元/袋)' },
179
182
  amount: { type: 'number', description: '【必填】金额,必须等于 price × quantity' },
180
183
  weight: { type: 'string', description: '重量' },
181
- marketPrice: { type: 'string', description: '市场单价(元/500g' },
182
- category: { type: 'string', description: '(必填)分类,如:餐饮、食品、购物' },
184
+ marketPrice: { type: 'string', description: '【必填】单价数值,根据unit计算,如unit=元/500g,则marketPrice=金额÷重量(g)×500' },
185
+ category: { type: 'string', description: '【必填】主分类(如:蔬菜、肉类、水果、水产,常见超市购物分类)' },
186
+ subCategory: { type: 'string', description: '子分类(如:叶菜类、根茎类、猪肉类,超市细分类目),推荐填写' },
183
187
  },
184
- required: ['name', 'amount', 'price', 'quantity'],
188
+ required: ['name', 'amount', 'price', 'quantity', 'unit', 'marketPrice', 'category'],
185
189
  },
186
190
  },
187
- agentType: { type: 'string', description: '【自动填充】Agent类型:claude-desktop、cursor、openclaw、workbuddy、trae' },
188
- apiProvider: { type: 'string', description: '【自动填充】AI服务提供商:anthropic、openai、doubao、aliyun' },
189
- rawInput: { type: 'string', description: '【自动填充】用户的原始输入内容' },
191
+ agentType: { type: 'string', description: '【必填】Agent类型:claude-desktop、cursor、openclaw、workbuddy、trae' },
192
+ apiProvider: { type: 'string', description: '【必填】AI服务提供商:anthropic、openai、doubao、aliyun' },
193
+ rawInput: { type: 'string', description: '【必填】用户的原始输入内容' },
190
194
  mcp_version: { type: 'string', description: '【自动填充】MCP Server版本号' },
191
195
  },
192
- required: ['store', 'items'],
196
+ required: ['store', 'items', 'agentType', 'apiProvider', 'rawInput'],
193
197
  },
194
198
  },
195
199
  {
196
200
  name: 'get_expenses',
197
- description: '查询消费记录',
201
+ description: '查询消费记录。支持按日期范围、分类、商家、来源等多维度筛选',
198
202
  inputSchema: {
199
203
  type: 'object',
200
204
  properties: {
201
- limit: { type: 'number', description: '返回数量限制', default: 10 },
202
- source: { type: 'string', description: '来源筛选' },
205
+ limit: { type: 'number', description: '返回数量限制,默认10条,最大100', default: 10 },
206
+ skip: { type: 'number', description: '跳过条数,用于分页', default: 0 },
207
+ startDate: { type: 'string', description: '开始日期(ISO格式,如:2026-04-01)' },
208
+ endDate: { type: 'string', description: '结束日期(ISO格式,如:2026-04-30)' },
209
+ category: { type: 'string', description: '按分类筛选(如:餐饮、食品、交通)' },
210
+ subCategory: { type: 'string', description: '按子分类筛选(如:叶菜类、猪肉类)' },
211
+ store: { type: 'string', description: '按商家名称筛选' },
212
+ source: { type: 'string', description: '按来源筛选(如:mcp_txt_expense、mcp_receipt)' },
213
+ keyword: { type: 'string', description: '按商品名称关键词搜索' },
214
+ orderBy: { type: 'string', description: '排序方式:date_desc(默认)、date_asc、amount_desc、amount_asc', enum: ['date_desc', 'date_asc', 'amount_desc', 'amount_asc'], default: 'date_desc' },
203
215
  },
204
216
  },
205
217
  },
206
218
  {
207
219
  name: 'get_receipt_list',
208
- description: '获取小票列表',
220
+ description: '获取小票列表。支持按日期范围、商家、金额等多维度筛选',
209
221
  inputSchema: {
210
222
  type: 'object',
211
223
  properties: {
212
- limit: { type: 'number', description: '返回数量限制', default: 5 },
224
+ limit: { type: 'number', description: '返回数量限制,默认5条,最大50', default: 5 },
225
+ skip: { type: 'number', description: '跳过条数,用于分页', default: 0 },
226
+ startDate: { type: 'string', description: '开始日期(ISO格式,如:2026-04-01)' },
227
+ endDate: { type: 'string', description: '结束日期(ISO格式,如:2026-04-30)' },
228
+ store: { type: 'string', description: '按商家名称筛选' },
229
+ minAmount: { type: 'number', description: '最小金额筛选' },
230
+ maxAmount: { type: 'number', description: '最大金额筛选' },
231
+ orderBy: { type: 'string', description: '排序方式:date_desc(默认)、date_asc、amount_desc、amount_asc', enum: ['date_desc', 'date_asc', 'amount_desc', 'amount_asc'], default: 'date_desc' },
213
232
  },
214
233
  },
215
234
  },
216
235
  {
217
236
  name: 'get_statistics',
218
- description: '获取消费统计',
237
+ description: '获取消费统计。支持按年月、日期范围统计,可查看分类占比、消费趋势等',
219
238
  inputSchema: {
220
239
  type: 'object',
221
240
  properties: {
222
- yearMonth: { type: 'string', description: '年月(如:2026-03' },
223
- type: { type: 'string', description: '统计类型:item/receipt/category' },
241
+ yearMonth: { type: 'string', description: '年月(如:2026-03),与startDate/endDate二选一' },
242
+ startDate: { type: 'string', description: '开始日期(ISO格式),与yearMonth二选一' },
243
+ endDate: { type: 'string', description: '结束日期(ISO格式),与yearMonth二选一' },
244
+ type: { type: 'string', description: '统计维度:item(商品明细)、receipt(小票汇总)、category(分类统计)、daily(每日趋势)、store(商家统计)', enum: ['item', 'receipt', 'category', 'daily', 'store'], default: 'category' },
245
+ category: { type: 'string', description: '按特定分类筛选统计' },
246
+ store: { type: 'string', description: '按特定商家筛选统计' },
247
+ groupBy: { type: 'string', description: '分组方式:category(分类)、date(日期)、store(商家)', enum: ['category', 'date', 'store'] },
224
248
  },
225
- required: ['yearMonth'],
226
249
  },
227
250
  },
228
251
  {
229
252
  name: 'save_income',
230
- description: '保存收入记录(工资、奖金、红包等)',
253
+ description: '保存收入记录(工资、奖金、红包等)。⚠️ 重要:必须先调用 get_text_parse_prompt 解析,然后传入所有解析结果字段',
231
254
  inputSchema: {
232
255
  type: 'object',
233
256
  properties: {
234
- name: { type: 'string', description: '收入来源(如:工资、奖金、红包)' },
235
- amount: { type: 'number', description: '收入金额' },
257
+ name: { type: 'string', description: '收入来源(如:工资、奖金、红包)(必填)' },
258
+ amount: { type: 'number', description: '收入金额(必填)' },
236
259
  category: { type: 'string', description: '(必填)收入分类(如:工资、奖金、投资)' },
237
- store: { type: 'string', description: '付款方(如:公司名称)' },
238
- date: { type: 'string', description: '收入时间(ISO格式)(可选)' },
239
- note: { type: 'string', description: '备注' },
240
- agentType: { type: 'string', description: '【推荐自动填充】Agent类型,如:claude-desktop、cursor、openclaw、workbuddy、trae' },
241
- apiProvider: { type: 'string', description: '【推荐自动填充】AI服务提供商,如:anthropic、openai、doubao、aliyun' },
242
- rawInput: { type: 'string', description: '【推荐自动填充】用户的原始输入内容,用于记录用户原始请求' },
260
+ store: { type: 'string', description: '付款方(如:公司名称)(可选)' },
261
+ date: { type: 'string', description: '收入时间(ISO格式,必须包含时间部分,如:2026-04-14T09:00:00+08:00)(可选)' },
262
+ note: { type: 'string', description: '备注(可选)' },
263
+ agentType: { type: 'string', description: '【必填】Agent类型,如:claude-desktop、cursor、openclaw、workbuddy、trae' },
264
+ apiProvider: { type: 'string', description: '【必填】AI服务提供商,如:anthropic、openai、doubao、aliyun' },
265
+ rawInput: { type: 'string', description: '【必填】用户的原始输入内容,用于记录用户原始请求' },
243
266
  mcp_version: { type: 'string', description: 'MCP Server 版本号(自动填充)' },
244
267
  },
245
- required: ['name', 'amount'],
268
+ required: ['name', 'amount', 'category', 'agentType', 'apiProvider', 'rawInput'],
246
269
  },
247
270
  },
248
271
  {
@@ -529,7 +552,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
529
552
  readAt: new Date().toISOString(),
530
553
  validFor: '5分钟'
531
554
  },
532
- message: '✅ Skill 定义已获取,有效期5分钟\n\n请仔细阅读上述 Skill 文档,然后执行记账操作。'
555
+ message: `✅ Skill 定义已获取,有效期5分钟\n\n【重要】完整的 Skill 文档内容在 result.data.skill 字段中,请仔细阅读以下内容,然后严格按照 Skill 文档执行记账操作:\n\n${'='.repeat(60)}\n${skillContent}\n${'='.repeat(60)}`
533
556
  };
534
557
  userMessage = result.message;
535
558
  break;
@@ -1194,12 +1217,13 @@ function convertParams(toolName, args) {
1194
1217
  price: amount,
1195
1218
  quantity: 1,
1196
1219
  category: sanitizeString(args.category, 50) || '其他',
1220
+ subCategory: sanitizeString(args.subCategory, 50) || '',
1221
+ unit: sanitizeString(args.unit, 20) || '',
1222
+ weight: '',
1223
+ marketPrice: sanitizeString(args.marketPrice, 50) || '',
1197
1224
  store: sanitizeString(args.store, 100) || '',
1198
1225
  date: formatDateWithTimezone(args.date),
1199
1226
  transactionType: 'expense',
1200
- unit: '',
1201
- weight: '',
1202
- marketPrice: '',
1203
1227
  note: sanitizeString(args.note, 500) || '',
1204
1228
  rawInput: sanitizeString(args.rawInput, 1000) || '',
1205
1229
  agentType: args.agentType || '',