chaimi-bookkeeping-mcp 2.3.2 → 2.3.4
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/2.3.4 +0 -0
- package/README.md +11 -0
- package/package.json +1 -1
- package/server.js +45 -31
package/2.3.4
ADDED
|
File without changes
|
package/README.md
CHANGED
|
@@ -141,6 +141,17 @@ AI 会自动调用 `save_income` 工具记录收入。
|
|
|
141
141
|
|
|
142
142
|
## 更新日志
|
|
143
143
|
|
|
144
|
+
### v2.3.3 (2026-04-08)
|
|
145
|
+
- **修正** 版本号统一为 v2.3.3(包含 v2.3.2 的所有修复)
|
|
146
|
+
|
|
147
|
+
### v2.3.2 (2026-04-08)
|
|
148
|
+
- **修复** `server.js` 中 `CURRENT_VERSION` 未定义错误,统一使用 `MCP_VERSION`
|
|
149
|
+
- **修复** 所有工具的 `userMessage` 添加默认值,防止显示 `undefined`
|
|
150
|
+
|
|
151
|
+
### v2.3.1 (2026-04-08)
|
|
152
|
+
- **修复** `bin/cli.js` 版本号显示问题,改为动态读取 package.json
|
|
153
|
+
- **优化** OAuth 授权流程,轮询间隔缩短为 2 秒
|
|
154
|
+
|
|
144
155
|
### v2.3.0 (2026-04-08)
|
|
145
156
|
- **修复** `save_receipt` 的 `items` 参数解析 bug,支持 JSON 字符串自动转换
|
|
146
157
|
- **优化** `source` 字段规范:`save_expense`→`mcp_txt_expense`、`save_income`→`mcp_txt_income`、`save_receipt`→`mcp_receipt`
|
package/package.json
CHANGED
package/server.js
CHANGED
|
@@ -72,7 +72,7 @@ function initOAuthManager() {
|
|
|
72
72
|
const server = new Server(
|
|
73
73
|
{
|
|
74
74
|
name: 'chaimi-bookkeeping-mcp',
|
|
75
|
-
version:
|
|
75
|
+
version: MCP_VERSION,
|
|
76
76
|
},
|
|
77
77
|
{
|
|
78
78
|
capabilities: {
|
|
@@ -108,23 +108,21 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
108
108
|
*/
|
|
109
109
|
{
|
|
110
110
|
name: 'save_expense',
|
|
111
|
-
description: '保存单商品消费记录(AI
|
|
111
|
+
description: '保存单商品消费记录(AI文字记账)。只需提供商品名称和金额,其他参数自动填充。示例:name="午餐", amount=35',
|
|
112
112
|
inputSchema: {
|
|
113
113
|
type: 'object',
|
|
114
114
|
properties: {
|
|
115
|
-
name: { type: 'string', description: '
|
|
116
|
-
amount: { type: 'number', description: '
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
apiProvider: { type: 'string', description: 'AI 提供商' },
|
|
124
|
-
rawInput: { type: 'string', description: '用户原始输入' },
|
|
115
|
+
name: { type: 'string', description: '商品名称(必填)' },
|
|
116
|
+
amount: { type: 'number', description: '金额(必填)' },
|
|
117
|
+
category: { type: 'string', description: '分类(可选,如:餐饮、食品、交通)' },
|
|
118
|
+
store: { type: 'string', description: '商家名称(可选)' },
|
|
119
|
+
note: { type: 'string', description: '备注(可选)' },
|
|
120
|
+
agentType: { type: 'string', description: 'Agent 类型(可选,如:workbuddy、claude、cursor)' },
|
|
121
|
+
apiProvider: { type: 'string', description: 'AI 提供商(可选)' },
|
|
122
|
+
rawInput: { type: 'string', description: '用户原始输入(可选)' },
|
|
125
123
|
mcp_version: { type: 'string', description: 'MCP Server 版本号(自动填充)' },
|
|
126
124
|
},
|
|
127
|
-
required: ['name', 'amount'
|
|
125
|
+
required: ['name', 'amount'],
|
|
128
126
|
},
|
|
129
127
|
},
|
|
130
128
|
{
|
|
@@ -491,7 +489,11 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
491
489
|
|
|
492
490
|
// 格式化输出
|
|
493
491
|
if (result.success) {
|
|
494
|
-
|
|
492
|
+
const displayName = processedArgs.name || '未知商品';
|
|
493
|
+
const displayAmount = processedArgs.amount || 0;
|
|
494
|
+
const displayCategory = processedArgs.category || '其他';
|
|
495
|
+
const displayStore = processedArgs.store || '-';
|
|
496
|
+
userMessage = `✅ 记账成功\n\n| 商品 | 金额 | 分类 | 商家 |\n|------|------|------|------|\n| ${displayName} | ${displayAmount}元 | ${displayCategory} | ${displayStore} |\n\n已保存到你的柴米记账小程序数据库。`;
|
|
495
497
|
}
|
|
496
498
|
break;
|
|
497
499
|
}
|
|
@@ -533,8 +535,10 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
533
535
|
// 格式化输出
|
|
534
536
|
if (result.success) {
|
|
535
537
|
const totalAmount = processedArgs.totalAmount || processedArgs.items?.reduce((sum, item) => sum + (item.amount || 0), 0) || 0;
|
|
536
|
-
const itemsList = processedArgs.items?.map(item => `• ${item.name} - ${item.amount}元`).join('\n');
|
|
537
|
-
|
|
538
|
+
const itemsList = processedArgs.items?.map(item => `• ${item.name || '未知商品'} - ${item.amount || 0}元`).join('\n') || '暂无商品明细';
|
|
539
|
+
const storeName = processedArgs.store || '-';
|
|
540
|
+
const category = processedArgs.items?.[0]?.category || '其他';
|
|
541
|
+
userMessage = `✅ 小票记录成功\n\n| 项目 | 内容 |\n|------|------|\n| 商家 | ${storeName} |\n| 金额 | ${totalAmount}元 |\n| 分类 | ${category} |\n\n商品明细:\n${itemsList}\n\n已保存到你的柴米记账小程序数据库。`;
|
|
538
542
|
}
|
|
539
543
|
break;
|
|
540
544
|
}
|
|
@@ -571,7 +575,11 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
571
575
|
|
|
572
576
|
// 格式化输出
|
|
573
577
|
if (result.success) {
|
|
574
|
-
|
|
578
|
+
const displayName = processedArgs.name || '未知来源';
|
|
579
|
+
const displayAmount = processedArgs.amount || 0;
|
|
580
|
+
const displayCategory = processedArgs.category || '其他';
|
|
581
|
+
const displayStore = processedArgs.store || '-';
|
|
582
|
+
userMessage = `✅ 收入记录成功\n\n| 来源 | 金额 | 分类 | 付款方 |\n|------|------|------|--------|\n| ${displayName} | ${displayAmount}元 | ${displayCategory} | ${displayStore} |`;
|
|
575
583
|
}
|
|
576
584
|
break;
|
|
577
585
|
}
|
|
@@ -586,7 +594,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
586
594
|
}
|
|
587
595
|
|
|
588
596
|
// 添加版本信息提示
|
|
589
|
-
userMessage += `\n\n---\n📦 柴米记账 MCP v${
|
|
597
|
+
userMessage += `\n\n---\n📦 柴米记账 MCP v${MCP_VERSION}`;
|
|
590
598
|
|
|
591
599
|
return {
|
|
592
600
|
content: [
|
|
@@ -671,26 +679,32 @@ function calculateMarketPrice(amount, weightStr) {
|
|
|
671
679
|
function convertParams(toolName, args) {
|
|
672
680
|
switch (toolName) {
|
|
673
681
|
case 'save_expense': {
|
|
674
|
-
|
|
682
|
+
// 必填参数校验
|
|
683
|
+
if (!args.name || typeof args.name !== 'string' || args.name.trim() === '') {
|
|
684
|
+
throw new Error('缺少必填参数:name(商品名称)');
|
|
685
|
+
}
|
|
686
|
+
if (args.amount === undefined || args.amount === null) {
|
|
687
|
+
throw new Error('缺少必填参数:amount(金额)');
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
const name = sanitizeString(args.name, 100);
|
|
675
691
|
const amount = validateAmount(args.amount);
|
|
676
|
-
// 优先使用传入的 marketPrice,如果没有则自动计算
|
|
677
|
-
const marketPrice = sanitizeString(args.marketPrice, 50) || calculateMarketPrice(amount, weight);
|
|
678
692
|
|
|
679
693
|
return {
|
|
694
|
+
name: name,
|
|
695
|
+
originalName: name,
|
|
680
696
|
amount: amount,
|
|
697
|
+
price: amount, // 单价默认等于金额
|
|
698
|
+
quantity: 1, // 数量默认为1
|
|
681
699
|
category: sanitizeString(args.category, 50) || '其他',
|
|
682
|
-
|
|
683
|
-
originalName: sanitizeString(args.originalName, 200) || sanitizeString(args.name, 100),
|
|
684
|
-
store: sanitizeString(args.store, 100),
|
|
700
|
+
store: sanitizeString(args.store, 100) || '',
|
|
685
701
|
type: 'expense',
|
|
686
|
-
unit:
|
|
687
|
-
weight:
|
|
688
|
-
marketPrice:
|
|
689
|
-
price: validateAmount(args.price),
|
|
690
|
-
quantity: validateQuantity(args.quantity),
|
|
702
|
+
unit: '',
|
|
703
|
+
weight: '',
|
|
704
|
+
marketPrice: '',
|
|
691
705
|
date: args.date,
|
|
692
|
-
note: sanitizeString(args.note, 500),
|
|
693
|
-
rawInput: sanitizeString(args.rawInput, 1000),
|
|
706
|
+
note: sanitizeString(args.note, 500) || '',
|
|
707
|
+
rawInput: sanitizeString(args.rawInput, 1000) || '',
|
|
694
708
|
agentType: args.agentType || '',
|
|
695
709
|
apiProvider: args.apiProvider || '',
|
|
696
710
|
mcp_version: args.mcp_version || MCP_VERSION,
|