@mcpcn/mcp-notification 1.0.20 → 1.1.2

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 +18 -86
  2. package/package.json +2 -3
package/dist/index.js CHANGED
@@ -1,8 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { Server } from '@modelcontextprotocol/sdk/server/index.js';
3
3
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
4
- import { ErrorCode, ListToolsRequestSchema, McpError } from '@modelcontextprotocol/sdk/types.js';
5
- import { z } from 'zod';
4
+ import { CallToolRequestSchema, ErrorCode, ListToolsRequestSchema, McpError } from '@modelcontextprotocol/sdk/types.js';
6
5
  const API_BASE = process.env.REMINDER_API_BASE || 'https://www.mcpcn.cc/api';
7
6
  function resolveChatSessionId(request) {
8
7
  const pick = (obj, keys) => {
@@ -13,57 +12,23 @@ function resolveChatSessionId(request) {
13
12
  }
14
13
  return undefined;
15
14
  };
16
- const direct = pick(request?.params?._meta, ['chatSessionId', 'chatSessionID']) ||
17
- pick(request?.params?.meta, ['chatSessionId', 'chatSessionID']) ||
18
- pick(request?.meta, ['chatSessionId', 'chatSessionID']) ||
19
- pick(request?._meta, ['chatSessionId', 'chatSessionID']);
20
- if (direct)
21
- return direct;
22
- const inArgs = pick(request?.params?.arguments?._meta, ['chatSessionId', 'chatSessionID']) ||
23
- pick(request?.params?.arguments?.meta, ['chatSessionId', 'chatSessionID']) ||
24
- pick(request?.params?.arguments, ['chatSessionId', 'chatSessionID']);
25
- if (inArgs)
26
- return inArgs;
27
- const scan = (obj, keys, maxDepth = 3) => {
28
- const queue = [obj];
29
- const seen = new Set();
30
- let depth = 0;
31
- while (queue.length && depth <= maxDepth) {
32
- const cur = queue.shift();
33
- if (!cur || typeof cur !== 'object' || seen.has(cur)) {
34
- depth++;
35
- continue;
36
- }
37
- seen.add(cur);
38
- for (const k of keys) {
39
- const v = cur[k];
40
- if (typeof v === 'string' && v)
41
- return v;
42
- }
43
- for (const v of Object.values(cur)) {
44
- if (v && typeof v === 'object')
45
- queue.push(v);
46
- }
47
- depth++;
48
- }
49
- return undefined;
50
- };
51
- return scan(request, ['chatSessionId', 'chatSessionID']);
15
+ return (pick(request?.params?.arguments, ['chatSessionId', 'chatSessionID']) ??
16
+ pick(request?.meta, ['chatSessionId', 'chatSessionID']) ??
17
+ pick(request?.params?._meta, ['chatSessionId', 'chatSessionID']) ??
18
+ pick(request?.params?.meta, ['chatSessionId', 'chatSessionID']) ??
19
+ pick(request?._meta, ['chatSessionId', 'chatSessionID']));
52
20
  }
53
21
  async function postJson(path, body, chatSessionId) {
54
22
  const headers = { 'Content-Type': 'application/json', Accept: 'application/json' };
55
- if (chatSessionId) {
23
+ if (chatSessionId)
56
24
  headers['chatSessionId'] = chatSessionId;
57
- headers['x-chat-session-id'] = chatSessionId;
58
- }
59
- const payload = chatSessionId ? { ...body, chatSessionId } : body;
60
25
  let lastError;
61
26
  for (let attempt = 0; attempt < 3; attempt++) {
62
27
  try {
63
28
  const resp = await fetch(`${API_BASE}${path}`, {
64
29
  method: 'POST',
65
30
  headers,
66
- body: JSON.stringify(payload),
31
+ body: JSON.stringify(body),
67
32
  });
68
33
  if (!resp.ok) {
69
34
  const text = await resp.text().catch(() => '');
@@ -88,16 +53,12 @@ async function postJson(path, body, chatSessionId) {
88
53
  }
89
54
  async function getJson(path, chatSessionId) {
90
55
  const headers = { Accept: 'application/json' };
91
- if (chatSessionId) {
56
+ if (chatSessionId)
92
57
  headers['chatSessionId'] = chatSessionId;
93
- }
94
58
  let lastError;
95
59
  for (let attempt = 0; attempt < 3; attempt++) {
96
60
  try {
97
- const url = new URL(`${API_BASE}${path}`);
98
- if (chatSessionId)
99
- url.searchParams.set('chatSessionId', chatSessionId);
100
- const resp = await fetch(url.toString(), { headers });
61
+ const resp = await fetch(`${API_BASE}${path}`, { headers });
101
62
  if (!resp.ok) {
102
63
  const text = await resp.text().catch(() => '');
103
64
  const msg = `HTTP 错误: ${resp.status} ${resp.statusText}${text ? ` | 响应体: ${text.slice(0, 500)}` : ''}`;
@@ -145,6 +106,7 @@ class ReminderServer {
145
106
  intervalSec: { type: 'number' },
146
107
  timeOfDay: { type: 'string', description: '例如 18:00 或 18:00:00' },
147
108
  tzOffsetMin: { type: 'number', description: '时区偏移分钟,例如北京为 480' },
109
+ chatSessionId: { type: 'string' },
148
110
  },
149
111
  required: ['content', 'repeat'],
150
112
  additionalProperties: false,
@@ -155,7 +117,7 @@ class ReminderServer {
155
117
  description: '获取设备的提醒列表(仅未触发的 scheduled)。',
156
118
  inputSchema: {
157
119
  type: 'object',
158
- properties: {},
120
+ properties: { chatSessionId: { type: 'string' } },
159
121
  required: [],
160
122
  additionalProperties: false,
161
123
  },
@@ -165,46 +127,16 @@ class ReminderServer {
165
127
  description: '取消指定提醒。',
166
128
  inputSchema: {
167
129
  type: 'object',
168
- properties: { id: { type: 'string' } },
130
+ properties: { id: { type: 'string' }, chatSessionId: { type: 'string' } },
169
131
  required: ['id'],
170
132
  additionalProperties: false,
171
133
  },
172
134
  },
173
135
  ],
174
136
  }));
175
- const CallToolWithMetaSchema = z
176
- .object({
177
- jsonrpc: z.literal('2.0'),
178
- method: z.literal('tools/call'),
179
- id: z.union([z.string(), z.number()]),
180
- params: z
181
- .object({
182
- name: z.string(),
183
- arguments: z.any().optional(),
184
- _meta: z
185
- .object({
186
- chatSessionId: z.string().optional(),
187
- chatSessionID: z.string().optional(),
188
- })
189
- .passthrough()
190
- .optional(),
191
- meta: z
192
- .object({
193
- chatSessionId: z.string().optional(),
194
- chatSessionID: z.string().optional(),
195
- })
196
- .passthrough()
197
- .optional(),
198
- })
199
- .passthrough(),
200
- })
201
- .passthrough();
202
- this.server.setRequestHandler(CallToolWithMetaSchema, async (request) => {
203
- try {
204
- console.error('CallToolRequest raw:', JSON.stringify(request));
205
- }
206
- catch { }
137
+ this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
207
138
  try {
139
+ console.error('[调试] request.params keys = ' + JSON.stringify(Object.keys(request.params || {})));
208
140
  if (!request.params.arguments || typeof request.params.arguments !== 'object') {
209
141
  throw new McpError(ErrorCode.InvalidParams, '无效的参数');
210
142
  }
@@ -212,8 +144,8 @@ class ReminderServer {
212
144
  const args = request.params.arguments;
213
145
  const chatSessionId = resolveChatSessionId(request);
214
146
  if (!chatSessionId) {
215
- console.error('工具未在请求中检测到 chatSessionId');
216
- const baseMsg = '解析设备失败: chatSessionId不能为空,工具暂无法使用';
147
+ console.error('通知工具未在请求中检测到 chatSessionId(meta.chatSessionId)');
148
+ const baseMsg = '解析设备失败: chatSessionId不能为空,通知工具暂无法使用';
217
149
  const errText = name === 'set_reminder'
218
150
  ? `设置失败:${baseMsg}`
219
151
  : name === 'list_reminders'
@@ -224,7 +156,7 @@ class ReminderServer {
224
156
  return { content: [{ type: 'text', text: errText }], isError: true };
225
157
  }
226
158
  else {
227
- console.error(`工具接收到 chatSessionId: ${chatSessionId}`);
159
+ console.error(`通知工具接收到 chatSessionId: ${chatSessionId}`);
228
160
  }
229
161
  if (name === 'set_reminder') {
230
162
  const params = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mcpcn/mcp-notification",
3
- "version": "1.0.20",
3
+ "version": "1.1.2",
4
4
  "description": "系统通知MCP服务器",
5
5
  "packageManager": "yarn@1.22.22",
6
6
  "main": "dist/index.js",
@@ -36,7 +36,6 @@
36
36
  "typescript": "^5.7.2"
37
37
  },
38
38
  "dependencies": {
39
- "@modelcontextprotocol/sdk": "^1.10.0",
40
- "zod": "^3.25.76"
39
+ "@modelcontextprotocol/sdk": "^1.10.0"
41
40
  }
42
41
  }