dingtalk-mcp 1.1.4 → 1.1.5

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/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # 钉钉MCP Server
2
2
 
3
3
 
4
+
4
5
  ## 🚀 功能特性
5
6
  - 钉钉通讯录
6
7
  - 钉钉部门管理
@@ -13,6 +14,7 @@
13
14
  - 钉钉应用管理
14
15
  - 钉钉服务窗
15
16
  - 钉钉项目管理
17
+ - 钉钉日志
16
18
 
17
19
  ## 如何使用
18
20
  ```json
@@ -38,19 +40,20 @@
38
40
  2. DINGTALK_Client_Secret
39
41
  3. ACTIVE_PROFILES,激活哪些钉钉MCP服务,逗号风格,如果是ALL则激活全部。可选集合
40
42
 
41
- | ProfileId | Description | Permission |
42
- |-----------------------------|--------------------|-------------------------------------------------|
43
- | dingtalk-contacts | 钉钉通讯录,默认激活 |
44
- | dingtalk-department | 钉钉部门管理 |
45
- | dingtalk-robot-send-message | 钉钉机器人发消息/DING,默认激活 | 需要企业内机器人发送消息权限 |
46
- | dingtalk-honor | 钉钉企业文化荣誉 |
47
- | dingtalk-tasks | 钉钉待办 | Todo.Todo.Write<br>Todo.Todo.Read |
48
- | dingtalk-calendar | 钉钉日程 |
49
- | dingtalk-checkin | 钉钉签到 |
43
+ | ProfileId | Description | Permission |
44
+ |-----------------------------|--------------------|--------------------------------------------------|
45
+ | dingtalk-contacts | 钉钉通讯录,默认激活 | qyapi_addresslist_search qyapi_get_member
46
+ | dingtalk-department | 钉钉部门管理 |qyapi_get_department_list qyapi_get_department_member
47
+ | dingtalk-robot-send-message | 钉钉机器人发消息/DING,默认激活 | 需要企业内机器人发送消息权限 <br/>Premium.Ding.Write |
48
+ | dingtalk-honor | 钉钉企业文化荣誉 |OrgCulture.Honor.Read OrgCulture.Honor.Read
49
+ | dingtalk-tasks | 钉钉待办 | Todo.Todo.Write<br>Todo.Todo.Read |
50
+ | dingtalk-calendar | 钉钉日程 |Calendar.Event.Write Calendar.Event.Read Calendar.EventSchedule.Read
51
+ | dingtalk-checkin | 钉钉签到 |qyapi_checkin_read
50
52
  | dingtalk-notice | 钉钉工作通知 |
51
53
  | dingtalk-app-manage | 钉钉应用管理 | qyapi_microapp_manage<br>qyapi_get_microapp_list |
52
- | dingtalk-service-window | 钉钉服务窗 | |
53
- | dingtalk-teambition | 钉钉项目管理 | |
54
+ | dingtalk-service-window | 钉钉服务窗 | OfficialAccount.Message.Send OfficialAccount.Contact.Read OfficialAccount.Account.Read |
55
+ | dingtalk-teambition | 钉钉项目管理 | Project.Project.Write.All Project.Project.Read.All Project.Task.Write.All Project.Task.Read.All |
56
+ | dingtalk-report | 钉钉日志 | qyapi_report_statistics qyapi_report_manage qyapi_report_query |
54
57
 
55
58
  4. ROBOT_CODE,用于发消息/DING的机器人Code
56
59
  5. ROBOT_ACCESS_TOKEN,群自定义机器人ACCESS_TOKEN,用于自定义机器人发消息
@@ -0,0 +1,423 @@
1
+ server:
2
+ name: dingtalk-report
3
+ description: 钉钉日志
4
+ tools:
5
+ - name: createReport
6
+ description: |
7
+ 创建并发送工作日志到指定接收人。
8
+
9
+ 【重要提示】contents参数格式复杂,必须严格按照以下格式构造:
10
+
11
+ 1. 每个content对象必须包含5个字段:content_type, sort, type, content, key
12
+ 2. content_type固定为"markdown"
13
+ 3. sort和type的值需要从getTemplateDetail接口获取
14
+ 4. key为字段名称,content为实际填写的内容
15
+
16
+ 【使用流程】
17
+ 1. 先调用getTemplateDetail获取模板字段信息
18
+ 2. 根据返回的fields构造contents数组
19
+ 3. 调用本接口创建日志
20
+
21
+ 【完整示例】
22
+ 对于"空白日志"模板:
23
+ {
24
+ "template_id": "1740b290d90f07517b0d3b14da2b4b7b",
25
+ "contents": [
26
+ {
27
+ "content_type": "markdown",
28
+ "sort": 0,
29
+ "type": 1,
30
+ "content": "今天完成了项目开发工作",
31
+ "key": "内容"
32
+ }
33
+ ],
34
+ "userid": "0420131813787933",
35
+ "to_chat": true,
36
+ "dd_from": "MCP_ASSISTANT",
37
+ "to_userids": ["0420131813787933"]
38
+ }
39
+
40
+ 【常见参数组合】
41
+ - 发送给自己:to_userids=["自己的userid"], to_chat=true
42
+ - 发送给他人:to_userids=["他人userid1", "他人userid2"], to_chat=true
43
+ - 发送到群:to_cids=["群id1"], to_chat=false
44
+ requestTemplate:
45
+ method: POST
46
+ url: https://oapi.dingtalk.com/topapi/report/create
47
+ args:
48
+ - name: template_id
49
+ type: string
50
+ required: true
51
+ position: body
52
+ description: |
53
+ 模板ID,从getTemplateDetail接口的result.id字段获取。
54
+ 示例值:"1740b290d90f07517b0d3b14da2b4b7b"
55
+ - name: contents
56
+ type: array
57
+ required: true
58
+ position: body
59
+ description: |
60
+ 日志内容数组,必须严格按照以下JSON Schema构造:
61
+
62
+ 每个数组元素是一个对象,包含以下必需字段:
63
+ - content_type: 固定值"markdown"
64
+ - sort: 数字,字段排序(从模板详情获取)
65
+ - type: 数字,字段类型(从模板详情获取,通常为1)
66
+ - content: 字符串,实际填写的内容,支持Markdown格式,最长1000字符
67
+ - key: 字符串,字段名称(从模板详情的field_name获取)
68
+
69
+ 构造方法:
70
+ 1. 调用getTemplateDetail获取模板fields
71
+ 2. 对于每个field,创建一个content对象:
72
+ {
73
+ "content_type": "markdown",
74
+ "sort": field.sort,
75
+ "type": field.type,
76
+ "content": "你要填写的内容",
77
+ "key": field.field_name
78
+ }
79
+ items:
80
+ type: object
81
+ required:
82
+ - content_type
83
+ - sort
84
+ - type
85
+ - content
86
+ - key
87
+ properties:
88
+ content_type:
89
+ type: string
90
+ enum: ["markdown"]
91
+ description: 内容类型,固定值"markdown"
92
+ sort:
93
+ type: number
94
+ description: 字段排序序号,必须从getTemplateDetail的result.fields[].sort获取
95
+ type:
96
+ type: number
97
+ description: 字段类型,必须从getTemplateDetail的result.fields[].type获取(1=文本类型)
98
+ content:
99
+ type: string
100
+ maxLength: 1000
101
+ description: 实际填写的内容,支持Markdown语法,最长1000字符
102
+ key:
103
+ type: string
104
+ description: 字段名称,必须从getTemplateDetail的result.fields[].field_name获取
105
+ - name: userid
106
+ type: string
107
+ required: true
108
+ position: body
109
+ description: |
110
+ 创建日志的员工userId。
111
+ 示例值:"0420131813787933"
112
+ - name: to_userids
113
+ type: array
114
+ required: false
115
+ position: body
116
+ description: |
117
+ 日志发送到的员工userId列表(可选)。
118
+ 如果不指定,日志只保存不发送。
119
+ 示例值:["0420131813787933", "其他userid"]
120
+ items:
121
+ type: string
122
+ description: 员工的userId
123
+ - name: to_chat
124
+ type: boolean
125
+ required: true
126
+ position: body
127
+ description: |
128
+ 发送日志到员工时是否发送单聊消息。
129
+ - true: 发送日志消息给指定用户
130
+ - false: 不单独发送消息
131
+ 通常设置为true以确保接收人能收到通知。
132
+ - name: to_cids
133
+ type: array
134
+ required: false
135
+ position: body
136
+ description: |
137
+ 日志要发送到的群ID列表(可选)。
138
+ 注意:群必须是在日志模板中预先配置好的接收群。
139
+ 示例值:["群id1", "群id2"]
140
+ items:
141
+ type: string
142
+ description: 群聊的ID
143
+ - name: dd_from
144
+ type: string
145
+ required: true
146
+ position: body
147
+ description: |
148
+ 日志来源标识,自定义的唯一来源标识。
149
+ 建议使用有意义的标识,如"MCP_ASSISTANT"、"AUTO_REPORT"等。
150
+ 示例值:"MCP_ASSISTANT"
151
+
152
+ - name: saveReportDraft
153
+ description: |
154
+ 保存日志内容供后续编辑和发送(草稿功能)。
155
+
156
+ 此接口用于保存日志内容但不立即发送,可以后续在钉钉中编辑和发送。
157
+ contents参数格式与createLog相同,必须包含完整的字段结构。
158
+
159
+ 【使用场景】
160
+ - 需要保存日志但暂不发送
161
+ - 创建模板供后续使用
162
+ - 批量准备多个日志内容
163
+
164
+ 【参数格式】与createLog的contents参数完全相同
165
+ requestTemplate:
166
+ method: POST
167
+ url: https://oapi.dingtalk.com/topapi/report/savecontent
168
+ args:
169
+ - name: template_id
170
+ type: string
171
+ required: true
172
+ position: body
173
+ description: |
174
+ 模板ID,从getTemplateDetail接口的result.id字段获取。
175
+ 示例值:"1740b290d90f07517b0d3b14da2b4b7b"
176
+ - name: contents
177
+ type: array
178
+ required: true
179
+ position: body
180
+ description: |
181
+ 日志内容数组,格式与createLog接口的contents参数完全相同。
182
+
183
+ 每个数组元素必须包含:
184
+ - content_type: "markdown"
185
+ - sort: 从模板详情获取的字段排序
186
+ - type: 从模板详情获取的字段类型
187
+ - content: 实际内容
188
+ - key: 字段名称
189
+ items:
190
+ type: object
191
+ required:
192
+ - content_type
193
+ - sort
194
+ - type
195
+ - content
196
+ - key
197
+ properties:
198
+ content_type:
199
+ type: string
200
+ enum: ["markdown"]
201
+ description: 内容类型,固定值"markdown"
202
+ sort:
203
+ type: number
204
+ description: 字段排序序号
205
+ type:
206
+ type: number
207
+ description: 字段类型(1=文本类型)
208
+ content:
209
+ type: string
210
+ maxLength: 1000
211
+ description: 实际填写的内容
212
+ key:
213
+ type: string
214
+ description: 字段名称
215
+ - name: userid
216
+ type: string
217
+ required: true
218
+ position: body
219
+ description: |
220
+ 创建日志的员工userId。
221
+ 示例值:"0420131813787933"
222
+ - name: dd_from
223
+ type: string
224
+ required: true
225
+ position: body
226
+ description: |
227
+ 日志来源标识,自定义的唯一标识。
228
+ 示例值:"MCP_ASSISTANT"
229
+
230
+ - name: getLogList
231
+ description: |
232
+ 查询用户发出的日志列表。
233
+
234
+ 可以根据时间范围、模板名称、用户等条件查询日志列表。
235
+ 支持分页查询,适用于批量处理和数据分析。
236
+
237
+ 【使用场景】
238
+ - 查看个人的日志历史
239
+ - 统计团队日志数据
240
+ - 查找特定时间段的日志
241
+
242
+ 【时间参数说明】
243
+ - start_time和end_time最多相隔180天
244
+ - 时间格式为Unix时间戳(毫秒)
245
+ - 可使用JavaScript的Date.now()或new Date().getTime()获取
246
+
247
+ 【查询示例】
248
+ 查询最近7天的所有日志:
249
+ {
250
+ "start_time": 1703145600000, // 7天前的时间戳
251
+ "end_time": 1703750400000, // 当前时间戳
252
+ "cursor": 0,
253
+ "size": 10
254
+ }
255
+ requestTemplate:
256
+ method: POST
257
+ url: https://oapi.dingtalk.com/topapi/report/list
258
+ args:
259
+ - name: start_time
260
+ type: number
261
+ required: true
262
+ position: body
263
+ description: |
264
+ 查询的日志创建开始时间,Unix时间戳(毫秒)。
265
+ 注意:与end_time间隔不能超过180天。
266
+ 示例值:1703145600000(2023-12-21的时间戳)
267
+ - name: end_time
268
+ type: number
269
+ required: true
270
+ position: body
271
+ description: |
272
+ 查询的日志创建结束时间,Unix时间戳(毫秒)。
273
+ 必须大于start_time,且间隔不超过180天。
274
+ 示例值:1703750400000(2023-12-28的时间戳)
275
+ - name: template_name
276
+ type: string
277
+ required: false
278
+ position: body
279
+ description: |
280
+ 要查询的模板名称(可选)。
281
+ 不传则查询所有模板的日志。
282
+ 示例值:"日报"、"周报"、"空白日志"
283
+ - name: userid
284
+ type: string
285
+ required: false
286
+ position: body
287
+ description: |
288
+ 员工的userId(可选)。
289
+ 不传则查询所有员工的日志(需要权限)。
290
+ 示例值:"0420131813787933"
291
+ - name: cursor
292
+ type: number
293
+ required: true
294
+ position: body
295
+ description: |
296
+ 查询游标,用于分页。
297
+ 初始查询传入0,后续从上一次响应的next_cursor获取。
298
+ 示例值:0
299
+ - name: size
300
+ type: number
301
+ required: true
302
+ position: body
303
+ description: |
304
+ 每页数据量,范围1-20。
305
+ 建议使用10以获得较好的性能。
306
+ 示例值:10
307
+ - name: modified_start_time
308
+ type: number
309
+ required: false
310
+ position: body
311
+ description: |
312
+ 查询的日志修改开始时间,Unix时间戳(毫秒)(可选)。
313
+ 用于查询在特定时间段内被修改过的日志。
314
+ - name: modified_end_time
315
+ type: number
316
+ required: false
317
+ position: body
318
+ description: |
319
+ 查询的日志修改结束时间,Unix时间戳(毫秒)(可选)。
320
+ 与modified_start_time配合使用。
321
+
322
+ - name: getTemplateList
323
+ description: |
324
+ 获取用户可见的日志模板列表。
325
+
326
+ 返回当前用户有权限查看和使用的所有日志模板。
327
+ 模板包含基本信息如名称、ID等,不包含详细字段信息。
328
+
329
+ 【使用场景】
330
+ - 查看可用的日志模板
331
+ - 获取模板基本信息
332
+ - 为用户选择提供模板列表
333
+
334
+ 【返回信息】
335
+ - template_list: 模板列表
336
+ - 每个模板包含:name(名称)、report_code(ID)等
337
+
338
+ 【后续操作】
339
+ 获取到模板列表后,可使用getTemplateDetail获取具体模板的字段信息。
340
+ requestTemplate:
341
+ method: POST
342
+ url: https://oapi.dingtalk.com/topapi/report/template/listbyuserid
343
+ args:
344
+ - name: userid
345
+ type: string
346
+ required: false
347
+ position: body
348
+ description: |
349
+ 员工的userId(可选)。
350
+ 不传表示获取所有日志模板。
351
+ 传入userid则获取该用户有权限的模板。
352
+ 示例值:"0420131813787933"
353
+ - name: offset
354
+ type: number
355
+ required: false
356
+ position: body
357
+ description: |
358
+ 分页偏移量,从0开始(可选)。
359
+ 用于分页查询,默认为0。
360
+ 示例值:0
361
+ - name: size
362
+ type: number
363
+ required: false
364
+ position: body
365
+ description: |
366
+ 分页大小,范围1-100(可选)。
367
+ 默认值为100,建议使用默认值获取所有模板。
368
+ 示例值:100
369
+
370
+ - name: getTemplateDetail
371
+ description: |
372
+ 查看日志模板的详细字段和配置信息。
373
+
374
+ 返回模板的完整字段定义,这是构造createLog的contents参数的关键信息。
375
+ 每个字段包含field_name、sort、type等属性,用于构造正确的日志内容。
376
+
377
+ 【重要性】
378
+ 此接口是使用createLog的前置条件!必须先获取模板详情才能正确构造contents参数。
379
+
380
+ 【返回字段说明】
381
+ - fields数组:模板的所有字段定义
382
+ - 每个field包含:
383
+ - field_name: 字段名称(用于contents的key)
384
+ - sort: 排序序号(用于contents的sort)
385
+ - type: 字段类型(用于contents的type,1=文本)
386
+
387
+ 【使用示例】
388
+ 1. 调用此接口获取模板详情
389
+ 2. 根据返回的fields构造contents数组
390
+ 3. 调用createLog创建日志
391
+
392
+ 对于"空白日志"模板的响应示例:
393
+ {
394
+ "fields": [
395
+ {
396
+ "field_name": "内容",
397
+ "sort": 0,
398
+ "type": 1
399
+ }
400
+ ],
401
+ "id": "1740b290d90f07517b0d3b14da2b4b7b",
402
+ "name": "空白日志"
403
+ }
404
+ requestTemplate:
405
+ method: POST
406
+ url: https://oapi.dingtalk.com/topapi/report/template/getbyname
407
+ args:
408
+ - name: template_name
409
+ type: string
410
+ required: true
411
+ position: body
412
+ description: |
413
+ 模板名称,必须是已存在的模板名称。
414
+ 可以从getTemplateList接口的返回结果中获取准确的模板名称。
415
+ 示例值:"空白日志"、"日报"、"周报"
416
+ - name: userid
417
+ type: string
418
+ required: true
419
+ position: body
420
+ description: |
421
+ 操作该接口的员工userId。
422
+ 必须是有权限查看该模板的用户ID。
423
+ 示例值:"0420131813787933"
@@ -2,6 +2,7 @@ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
2
2
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
3
3
  import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
4
4
  import { ServiceWindowMessageBuilder } from './utils/messageBuilder.js'
5
+ import { LogMessageBuilder } from './utils/logBuilder.js'
5
6
  import axios from 'axios';
6
7
  import * as yaml from 'js-yaml';
7
8
  import fs from 'fs';
@@ -76,9 +77,7 @@ export class DingTalkMCPServer {
76
77
  );
77
78
  if (this.tools && this.tools.length > 0) {
78
79
  console.error(`Loaded ${this.tools.length} tools from config`);
79
- console.error(`Tools:\r\n${this.tools.map(t => t.name + ', ' + t.description).join('\r\n')}`);
80
- }else{
81
- throw new Error('No tools found in config, tools is empty');
80
+ console.error(`Tools:\r\n${this.tools.map(t => t.name + ', '+ t.requestTemplate.method+' ' + t.requestTemplate.url + ', ' + t.description).join('\r\n')}`);
82
81
  }
83
82
  }
84
83
  catch (error) {
@@ -444,6 +443,8 @@ export class DingTalkMCPServer {
444
443
  return ServiceWindowMessageBuilder.buildSendServiceWindowMarkdownBody(args);
445
444
  }else if (tool.name === 'batchSendServiceWindowMessage'){
446
445
  return ServiceWindowMessageBuilder.buildBatchSendServiceWindowMarkdownBody(args);
446
+ }else if (tool.name === 'createLog' || tool.name === 'saveLogDraft'){
447
+ return LogMessageBuilder.buildBody(args);
447
448
  }
448
449
 
449
450
 
@@ -0,0 +1,16 @@
1
+ /**
2
+ * ServiceWindow Message Builder - 核心特色功能
3
+ * 简化复杂的服务窗消息格式构建
4
+ */
5
+ export class LogMessageBuilder {
6
+ /**
7
+ * 构建服务窗消息体
8
+ * @param message 用户友好的消息参数
9
+ * @returns 钉钉API标准格式的消息体
10
+ */
11
+ static buildBody(message) {
12
+ return {
13
+ create_report_param: message
14
+ }
15
+ }
16
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dingtalk-mcp",
3
- "version": "1.1.4",
3
+ "version": "1.1.5",
4
4
  "description": "DingTalk MCP Server - A TypeScript-based MCP server for DingTalk integration",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",