@mcpcn/mcp-notification 1.0.19 → 1.1.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 (2) hide show
  1. package/dist/index.js +15 -82
  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,21 @@ 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?._meta, ['chatSessionId', 'chatSessionID']) ??
16
+ pick(request?.params?.meta, ['chatSessionId', 'chatSessionID']) ??
17
+ pick(request?._meta, ['chatSessionId', 'chatSessionID']));
52
18
  }
53
19
  async function postJson(path, body, chatSessionId) {
54
20
  const headers = { 'Content-Type': 'application/json', Accept: 'application/json' };
55
- if (chatSessionId) {
21
+ if (chatSessionId)
56
22
  headers['chatSessionId'] = chatSessionId;
57
- headers['x-chat-session-id'] = chatSessionId;
58
- }
59
- const payload = chatSessionId ? { ...body, chatSessionId } : body;
60
23
  let lastError;
61
24
  for (let attempt = 0; attempt < 3; attempt++) {
62
25
  try {
63
26
  const resp = await fetch(`${API_BASE}${path}`, {
64
27
  method: 'POST',
65
28
  headers,
66
- body: JSON.stringify(payload),
29
+ body: JSON.stringify(body),
67
30
  });
68
31
  if (!resp.ok) {
69
32
  const text = await resp.text().catch(() => '');
@@ -88,16 +51,12 @@ async function postJson(path, body, chatSessionId) {
88
51
  }
89
52
  async function getJson(path, chatSessionId) {
90
53
  const headers = { Accept: 'application/json' };
91
- if (chatSessionId) {
54
+ if (chatSessionId)
92
55
  headers['chatSessionId'] = chatSessionId;
93
- }
94
56
  let lastError;
95
57
  for (let attempt = 0; attempt < 3; attempt++) {
96
58
  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 });
59
+ const resp = await fetch(`${API_BASE}${path}`, { headers });
101
60
  if (!resp.ok) {
102
61
  const text = await resp.text().catch(() => '');
103
62
  const msg = `HTTP 错误: ${resp.status} ${resp.statusText}${text ? ` | 响应体: ${text.slice(0, 500)}` : ''}`;
@@ -145,6 +104,7 @@ class ReminderServer {
145
104
  intervalSec: { type: 'number' },
146
105
  timeOfDay: { type: 'string', description: '例如 18:00 或 18:00:00' },
147
106
  tzOffsetMin: { type: 'number', description: '时区偏移分钟,例如北京为 480' },
107
+ chatSessionId: { type: 'string' },
148
108
  },
149
109
  required: ['content', 'repeat'],
150
110
  additionalProperties: false,
@@ -155,7 +115,7 @@ class ReminderServer {
155
115
  description: '获取设备的提醒列表(仅未触发的 scheduled)。',
156
116
  inputSchema: {
157
117
  type: 'object',
158
- properties: {},
118
+ properties: { chatSessionId: { type: 'string' } },
159
119
  required: [],
160
120
  additionalProperties: false,
161
121
  },
@@ -165,41 +125,14 @@ class ReminderServer {
165
125
  description: '取消指定提醒。',
166
126
  inputSchema: {
167
127
  type: 'object',
168
- properties: { id: { type: 'string' } },
128
+ properties: { id: { type: 'string' }, chatSessionId: { type: 'string' } },
169
129
  required: ['id'],
170
130
  additionalProperties: false,
171
131
  },
172
132
  },
173
133
  ],
174
134
  }));
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) => {
135
+ this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
203
136
  try {
204
137
  if (!request.params.arguments || typeof request.params.arguments !== 'object') {
205
138
  throw new McpError(ErrorCode.InvalidParams, '无效的参数');
@@ -208,8 +141,8 @@ class ReminderServer {
208
141
  const args = request.params.arguments;
209
142
  const chatSessionId = resolveChatSessionId(request);
210
143
  if (!chatSessionId) {
211
- console.error('工具未在请求中检测到 chatSessionId');
212
- const baseMsg = '解析设备失败: chatSessionId不能为空,工具暂无法使用';
144
+ console.error('通知工具未在请求中检测到 chatSessionId(meta.chatSessionId)');
145
+ const baseMsg = '解析设备失败: chatSessionId不能为空,通知工具暂无法使用';
213
146
  const errText = name === 'set_reminder'
214
147
  ? `设置失败:${baseMsg}`
215
148
  : name === 'list_reminders'
@@ -220,7 +153,7 @@ class ReminderServer {
220
153
  return { content: [{ type: 'text', text: errText }], isError: true };
221
154
  }
222
155
  else {
223
- console.error(`工具接收到 chatSessionId: ${chatSessionId}`);
156
+ console.error(`通知工具接收到 chatSessionId: ${chatSessionId}`);
224
157
  }
225
158
  if (name === 'set_reminder') {
226
159
  const params = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mcpcn/mcp-notification",
3
- "version": "1.0.19",
3
+ "version": "1.1.1",
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
  }