@mcpcn/mcp-notification 1.1.7 → 1.1.9

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/dist/index.js +23 -22
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -32,7 +32,7 @@ async function postJson(path, body, chatSessionId) {
32
32
  });
33
33
  if (!resp.ok) {
34
34
  const text = await resp.text().catch(() => '');
35
- const msg = `HTTP 错误: ${resp.status} ${resp.statusText}${text ? ` | 响应体: ${text.slice(0, 500)}` : ''}`;
35
+ const msg = `HTTP error: ${resp.status} ${resp.statusText}${text ? ` | Body: ${text.slice(0, 500)}` : ''}`;
36
36
  if (resp.status >= 500 && attempt < 2) {
37
37
  await new Promise((r) => setTimeout(r, 300 * (attempt + 1)));
38
38
  continue;
@@ -49,7 +49,7 @@ async function postJson(path, body, chatSessionId) {
49
49
  }
50
50
  }
51
51
  }
52
- throw new Error(`执行失败: ${lastError?.message}`);
52
+ throw new Error(`Execution failed: ${lastError?.message}`);
53
53
  }
54
54
  async function getJson(path, chatSessionId) {
55
55
  const headers = { Accept: 'application/json' };
@@ -61,7 +61,7 @@ async function getJson(path, chatSessionId) {
61
61
  const resp = await fetch(`${API_BASE}${path}`, { headers });
62
62
  if (!resp.ok) {
63
63
  const text = await resp.text().catch(() => '');
64
- const msg = `HTTP 错误: ${resp.status} ${resp.statusText}${text ? ` | 响应体: ${text.slice(0, 500)}` : ''}`;
64
+ const msg = `HTTP error: ${resp.status} ${resp.statusText}${text ? ` | Body: ${text.slice(0, 500)}` : ''}`;
65
65
  if (resp.status >= 500 && attempt < 2) {
66
66
  await new Promise((r) => setTimeout(r, 300 * (attempt + 1)));
67
67
  continue;
@@ -78,7 +78,7 @@ async function getJson(path, chatSessionId) {
78
78
  }
79
79
  }
80
80
  }
81
- throw new Error(`执行失败: ${lastError?.message}`);
81
+ throw new Error(`Execution failed: ${lastError?.message}`);
82
82
  }
83
83
  class ReminderServer {
84
84
  constructor() {
@@ -95,16 +95,16 @@ class ReminderServer {
95
95
  tools: [
96
96
  {
97
97
  name: 'set_reminder',
98
- description: '设置通知提醒,支持一次性、按间隔循环、每日循环;一次性提醒需提供triggerAt或delaySec,或提供timeOfDay用于推算,优先提供delaySec。',
98
+ description: '设置通知提醒,支持一次性、按间隔循环、每日循环。规则:当用户表述为具体某天/今天/明天/后天/某日期某时间等,请选择repeat=none;优选将具体日期时间直接计算为RFC3339并填入triggerAt,或仅提供timeOfDay让服务端自动推算到最近一次的该时间(若当天已过则推算到明天)。只有当用户明确说“每天/每日/每晚/每早/每隔X时间”时,才使用repeat=dailyrepeat=interval。一次性提醒可提供triggerAt或delaySec,或提供timeOfDay用于推算,优先使用delaySec。',
99
99
  inputSchema: {
100
100
  type: 'object',
101
101
  properties: {
102
102
  content: { type: 'string', minLength: 1, description: '提醒内容,例如 “开会”。' },
103
- repeat: { type: 'string', enum: ['none', 'interval', 'daily'], default: 'none', description: '提醒类型:none 一次性、interval 按间隔、daily 每日。' },
103
+ repeat: { type: 'string', enum: ['none', 'interval', 'daily'], default: 'none', description: '提醒类型:none 一次性(包含“今天/明天/某天”的语义)、interval 按间隔、daily 每日(仅当用户明确要求“每天”时使用)。' },
104
104
  delaySec: { type: 'number', minimum: 1, description: '一次性提醒相对延迟秒数,例如 300 表示5分钟后触发。与triggerAt二选一。' },
105
105
  triggerAt: { type: 'string', description: '一次性提醒绝对时间,RFC3339 格式,例如 2025-11-21T08:00:00+08:00。' },
106
106
  intervalSec: { type: 'number', minimum: 1, description: '按间隔循环的间隔秒数,例如 3600 表示每小时提醒一次。仅repeat=interval时必需。' },
107
- timeOfDay: { type: 'string', pattern: '^\\d{1,2}:\\d{2}(:\\d{2})?$', description: '一天中的时间,格式 HH:mm 或 HH:mm:ss,例如 08:00 或 08:00:00。repeat=daily时必需;repeat=none且未提供triggerAt/delaySec时用于推算。' },
107
+ timeOfDay: { type: 'string', pattern: '^\\d{1,2}:\\d{2}(:\\d{2})?$', description: '一天中的时间,格式 HH:mm 或 HH:mm:ss,例如 08:00 或 08:00:00。repeat=daily时必需;repeat=none且未提供triggerAt/delaySec时用于推算。典型用法:用户说“明天早上8点”,请选择repeat=none并设置timeOfDay="08:00",服务端会自动推算到最近的08:00。' },
108
108
  tzOffsetMin: { type: 'number', description: '时区偏移分钟,例如北京为 480;不提供时默认使用本机时区。' },
109
109
  chatSessionId: { type: 'string', minLength: 1, description: '设备会话标识,由宿主环境传入。' },
110
110
  },
@@ -131,6 +131,7 @@ class ReminderServer {
131
131
  examples: [
132
132
  { content: '开会', repeat: 'none', triggerAt: '2025-11-21T08:00:00+08:00' },
133
133
  { content: '喝水', repeat: 'none', delaySec: 300 },
134
+ { content: '出发去10号线', repeat: 'none', timeOfDay: '08:00', tzOffsetMin: 480 },
134
135
  { content: '站立休息', repeat: 'interval', intervalSec: 1800 },
135
136
  { content: '打卡', repeat: 'daily', timeOfDay: '09:00', tzOffsetMin: 480 },
136
137
  ],
@@ -162,7 +163,7 @@ class ReminderServer {
162
163
  try {
163
164
  console.error('[调试] request.params keys = ' + JSON.stringify(Object.keys(request.params || {})));
164
165
  if (!request.params.arguments || typeof request.params.arguments !== 'object') {
165
- throw new McpError(ErrorCode.InvalidParams, '无效的参数');
166
+ throw new McpError(ErrorCode.InvalidParams, 'Invalid parameters');
166
167
  }
167
168
  const name = request.params.name;
168
169
  const args = request.params.arguments;
@@ -170,13 +171,13 @@ class ReminderServer {
170
171
  const chatSessionId = resolveChatSessionId(request);
171
172
  if (!chatSessionId) {
172
173
  console.error('通知工具未在请求中检测到 chatSessionId(meta.chatSessionId)');
173
- const baseMsg = '解析设备失败: chatSessionId不能为空,通知工具暂无法使用';
174
+ const baseMsg = 'Device parsing failed: chatSessionId is required; notification tool unavailable';
174
175
  const errText = name === 'set_reminder'
175
- ? `设置失败:${baseMsg}`
176
+ ? `Set failed: ${baseMsg}`
176
177
  : name === 'list_reminders'
177
- ? `获取失败:${baseMsg}`
178
+ ? `Fetch failed: ${baseMsg}`
178
179
  : name === 'cancel_reminder'
179
- ? `取消失败:${baseMsg}`
180
+ ? `Cancel failed: ${baseMsg}`
180
181
  : baseMsg;
181
182
  return { content: [{ type: 'text', text: errText }], isError: true };
182
183
  }
@@ -202,13 +203,13 @@ class ReminderServer {
202
203
  if (typeof params.timeOfDay === 'string' && params.timeOfDay.trim()) {
203
204
  const m = params.timeOfDay.trim().match(/^\s*(\d{1,2}):(\d{2})(?::(\d{2}))?\s*$/);
204
205
  if (!m) {
205
- return { content: [{ type: 'text', text: '设置失败:timeOfDay格式应为HH:mmHH:mm:ss' }], isError: true };
206
+ return { content: [{ type: 'text', text: 'Set failed: timeOfDay must be HH:mm or HH:mm:ss' }], isError: true };
206
207
  }
207
208
  const hh = parseInt(m[1], 10);
208
209
  const mi = parseInt(m[2], 10);
209
210
  const ss = m[3] ? parseInt(m[3], 10) : 0;
210
211
  if (hh < 0 || hh > 23 || mi < 0 || mi > 59 || ss < 0 || ss > 59) {
211
- return { content: [{ type: 'text', text: '设置失败:timeOfDay格式应为HH:mmHH:mm:ss' }], isError: true };
212
+ return { content: [{ type: 'text', text: 'Set failed: timeOfDay must be HH:mm or HH:mm:ss' }], isError: true };
212
213
  }
213
214
  const offsetMin = typeof params.tzOffsetMin === 'number' ? params.tzOffsetMin : -new Date().getTimezoneOffset();
214
215
  const nowUtc = Date.now();
@@ -238,7 +239,7 @@ class ReminderServer {
238
239
  console.error(`自动计算triggerAt: ${params.triggerAt}`);
239
240
  }
240
241
  else {
241
- return { content: [{ type: 'text', text: '设置失败:必须提供triggerAtdelaySec,或提供timeOfDay用于推算' }], isError: true };
242
+ return { content: [{ type: 'text', text: 'Set failed: provide triggerAt or delaySec, or timeOfDay to derive' }], isError: true };
242
243
  }
243
244
  }
244
245
  if (needSingleTrigger && hasDelay && !hasTrigger) {
@@ -262,7 +263,7 @@ class ReminderServer {
262
263
  }
263
264
  const resp = await postJson('/reminder/set', params, chatSessionId);
264
265
  if (resp.code !== 0) {
265
- return { content: [{ type: 'text', text: `设置失败:${resp.msg}` }], isError: true };
266
+ return { content: [{ type: 'text', text: `Set failed: ${resp.msg}` }], isError: true };
266
267
  }
267
268
  const triggerAt = resp.data?.triggerAt;
268
269
  const offsetMin = typeof params.tzOffsetMin === 'number' ? params.tzOffsetMin : -new Date().getTimezoneOffset();
@@ -292,7 +293,7 @@ class ReminderServer {
292
293
  content: [
293
294
  {
294
295
  type: 'text',
295
- text: JSON.stringify({ id: resp.data?.id, triggerAt: resp.data?.triggerAt, triggerAtLocal, msg: resp.msg || '设置成功' }, null, 2),
296
+ text: JSON.stringify({ id: resp.data?.id, triggerAt: resp.data?.triggerAt, triggerAtLocal, msg: resp.msg || 'Set succeeded' }, null, 2),
296
297
  },
297
298
  ],
298
299
  isError: false,
@@ -301,7 +302,7 @@ class ReminderServer {
301
302
  if (name === 'list_reminders') {
302
303
  const resp = await getJson(`/reminder/list`, chatSessionId);
303
304
  if (resp.code !== 0) {
304
- return { content: [{ type: 'text', text: `获取失败:${resp.msg}` }], isError: true };
305
+ return { content: [{ type: 'text', text: `Fetch failed: ${resp.msg}` }], isError: true };
305
306
  }
306
307
  const offsetMin = typeof args?.tzOffsetMin === 'number' ? args.tzOffsetMin : -new Date().getTimezoneOffset();
307
308
  const formatOffset = (min) => {
@@ -360,16 +361,16 @@ class ReminderServer {
360
361
  const params = { id: String(args.id || '') };
361
362
  const resp = await postJson(`/reminder/cancel`, params, chatSessionId);
362
363
  if (resp.code !== 0) {
363
- return { content: [{ type: 'text', text: `取消失败:${resp.msg}` }], isError: true };
364
+ return { content: [{ type: 'text', text: `Cancel failed: ${resp.msg}` }], isError: true };
364
365
  }
365
- return { content: [{ type: 'text', text: resp.msg || '取消成功' }], isError: false };
366
+ return { content: [{ type: 'text', text: resp.msg || 'Cancel succeeded' }], isError: false };
366
367
  }
367
- throw new McpError(ErrorCode.MethodNotFound, `未知工具: ${name}`);
368
+ throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
368
369
  }
369
370
  catch (error) {
370
371
  if (error instanceof McpError)
371
372
  throw error;
372
- throw new McpError(ErrorCode.InternalError, `执行失败: ${error.message}`);
373
+ throw new McpError(ErrorCode.InternalError, `Execution failed: ${error.message}`);
373
374
  }
374
375
  });
375
376
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mcpcn/mcp-notification",
3
- "version": "1.1.7",
3
+ "version": "1.1.9",
4
4
  "description": "系统通知MCP服务器",
5
5
  "packageManager": "yarn@1.22.22",
6
6
  "main": "dist/index.js",