UNPKG

dingtalk-mcp-calendar

Version:

DingTalk Calendar MCP Server - TypeScript implementation for AI assistants

849 lines (764 loc) 27.1 kB
server: name: dingtalk-calendar securitySchemes: - id: DingTalkAuth type: apiKey in: header name: x-acs-dingtalk-access-token tools: - name: addAttendee description: "向指定日程添加参与者,支持批量添加多人,可设置参与者类型和通知方式" args: - name: attendeesToAdd description: "需要添加的参与者列表,包含unionId和参与类型" type: array required: true items: type: object position: body - name: calendarId description: "日历ID,使用'primary'表示主日历" type: string required: true position: path - name: chatNotification description: "是否发送单聊通知" type: boolean position: body - name: eventId description: "日程ID" type: string required: true position: path - name: id description: "参与者的unionId" type: string position: body - name: isOptional description: "是否为可选参与者(true=可选,false=必须)" type: boolean position: body - name: pushNotification description: "是否发送弹窗提醒" type: boolean position: body - name: userId description: "日程创建者的userId" type: string required: true position: path - name: x-client-token description: "幂等性校验令牌,避免重复请求" type: string position: header requestTemplate: url: https://api.dingtalk.com/v1.0/calendar/users/{userId}/calendars/{calendarId}/events/{eventId}/attendees method: POST headers: - key: Content-Type value: application/json security: id: DingTalkAuth responseTemplate: body: | # 日程参与者添加结果 {{if .success}} **操作成功** - 已成功向日程添加参与者 **日程信息**: - 日程ID: {{.eventId}} - 操作时间: {{.timestamp}} **添加的参与者**: {{range $i, $attendee := .attendees}} {{add $i 1}}. {{$attendee.displayName}} - unionId: {{$attendee.id}} - 参与类型: {{if $attendee.isOptional}}可选参与{{else}}必须参与{{end}} - 通知状态: {{if $attendee.notified}}已通知{{else}}未通知{{end}} {{end}} {{if .notifications}} **通知发送状态**: - 单聊通知: {{if .notifications.chatSent}}已发送{{else}}未发送{{end}} - 弹窗提醒: {{if .notifications.pushSent}}已发送{{else}}未发送{{end}} {{end}} {{else}} **操作失败** - {{.error}} **错误详情**: {{.errorMessage}} {{end}} - name: createEvent description: "创建新的日程,支持设置时间、参与者、提醒等完整功能" args: - name: userId description: "日程创建者的userId" type: string required: true position: path - name: calendarId description: "日历ID,使用'primary'表示主日历" type: string required: true position: path - name: summary description: "日程标题" type: string required: true position: body - name: start description: "日程开始时间" type: object required: true position: body - name: end description: "日程结束时间" type: object required: true position: body - name: description description: "日程描述内容" type: string position: body - name: isAllDay description: "是否为全天日程" type: boolean position: body - name: attendees description: "参与者列表" type: array items: type: object position: body requestTemplate: url: https://api.dingtalk.com/v1.0/calendar/users/{userId}/calendars/{calendarId}/events method: POST security: id: DingTalkAuth responseTemplate: body: | # 日程创建结果 {{if .success}} **日程创建成功** **日程信息**: - 📅 标题: {{.summary}} - 🆔 日程ID: {{.id}} - 开始时间: {{.start.dateTime | formatTime}} - 结束时间: {{.end.dateTime | formatTime}} - 📍 类型: {{if .isAllDay}}全天日程{{else}}定时日程{{end}} {{if .description}} - 📝 描述: {{.description}} {{end}} {{if .location}} - 📍 地点: {{.location.displayName}} {{end}} {{if .attendees}} **参与者** ({{len .attendees}}人): {{range $i, $attendee := .attendees}} {{add $i 1}}. {{$attendee.displayName}}{{if $attendee.isOptional}} (可选){{end}} {{end}} {{end}} **访问方式**: - 日程链接: {{.webLink}} {{if .onlineMeeting}} - 会议链接: {{.onlineMeeting.joinUrl}} {{end}} {{else}} **日程创建失败** - {{.error}} **错误详情**: {{.errorMessage}} {{end}} - name: deleteEvent description: "删除指定日程,组织者删除将通知所有参与者,参与者删除仅从自己日历移除" args: - name: calendarId description: "日历ID,使用'primary'表示主日历" type: string required: true position: path - name: eventId description: "要删除的日程ID" type: string required: true position: path - name: pushNotification description: "是否发送弹窗通知" type: boolean position: query - name: userId description: "执行删除操作的userId" type: string required: true position: path - name: x-client-token description: "幂等性校验令牌" type: string position: header requestTemplate: url: https://api.dingtalk.com/v1.0/calendar/users/{userId}/calendars/{calendarId}/events/{eventId}?pushNotification=Boolean method: DELETE security: id: DingTalkAuth responseTemplate: body: | # 日程删除结果 {{if .success}} **日程删除成功** **删除信息**: - 日程ID: {{.eventId}} - 删除者: {{.deletedBy}} - 删除时间: {{.deletedAt | formatTime}} - 影响范围: {{if .isOrganizer}}所有参与者(组织者删除){{else}}仅自己(参与者退出){{end}} {{if .notifications}} **通知状态**: {{if .isOrganizer}} - 取消通知已发送给 {{.notifications.notifiedCount}} 位参与者 {{end}} - 弹窗提醒: {{if .notifications.pushSent}}已发送{{else}}未发送{{end}} {{end}} {{else}} **日程删除失败** - {{.error}} **错误详情**: {{.errorMessage}} {{end}} - name: getEventsView description: "查询指定时间范围内的日程视图,支持循环日程展开显示" args: - name: calendarId description: "日历ID,使用'primary'表示主日历" type: string required: true position: path - name: maxAttendees description: "每个日程返回的参与者数量上限(默认100,最大100)" type: integer position: query - name: maxResults description: "返回的日程数量上限(默认100,最大100)" type: integer position: query - name: nextToken description: "分页标记,用于获取下一页数据" type: string position: query - name: timeMax description: "查询结束时间(ISO-8601格式)" type: string position: query - name: timeMin description: "查询开始时间(ISO-8601格式)" type: string position: query - name: userId description: "要查询的userId" type: string required: true position: path requestTemplate: url: https://api.dingtalk.com/v1.0/calendar/users/{userId}/calendars/{calendarId}/eventsview?timeMin=String&timeMax=String&maxResults=Long&nextToken=String method: GET security: id: DingTalkAuth responseTemplate: body: | # 📅 日程视图查询结果 {{if .events}} **查询范围**: {{.timeMin | formatTime}} {{.timeMax | formatTime}} **找到日程**: {{len .events}} 个{{if .hasMore}}(显示部分,还有更多){{end}} {{range $i, $event := .events}} ## {{add $i 1}}. {{$event.summary}} **⏰ 时间**: {{$event.start.dateTime | formatTime}} - {{$event.end.dateTime | formatTime}} {{if $event.isAllDay}}**📅 类型**: 全天日程{{end}} {{if $event.location}}**📍 地点**: {{$event.location.displayName}}{{end}} {{if $event.description}}**📝 描述**: {{$event.description | truncate 100}}{{end}} {{if $event.attendees}}**👥 参与者**: {{len $event.attendees}}人{{end}} {{if $event.seriesMasterId}}**🔄 循环**: 这是循环日程的一个实例{{end}} {{end}} {{if .nextToken}} --- **📄 分页信息**: 使用 nextToken "{{.nextToken}}" 获取更多结果 {{end}} {{else}} 📭 **暂无日程** 指定时间范围内没有找到任何日程。 {{end}} - name: getEventDetails description: "获取指定日程的详细信息,包含完整的参与者、位置、描述等信息" args: - name: calendarId description: "日历ID,使用'primary'表示主日历" type: string required: true position: path - name: eventId description: "日程ID" type: string required: true position: path - name: userId description: "查询者的userId" type: string required: true position: path - name: maxAttendees description: "返回的参与者数量上限(默认100,最大100)" type: integer position: query requestTemplate: url: https://api.dingtalk.com/v1.0/calendar/users/{userId}/calendars/{calendarId}/events/{eventId}?maxAttendees=Long method: GET security: id: DingTalkAuth responseTemplate: body: | # 📅 日程详情 ## {{.summary}} **基本信息**: - 🆔 日程ID: {{.id}} - 开始时间: {{.start.dateTime | formatTime}} - 结束时间: {{.end.dateTime | formatTime}} - 📅 类型: {{if .isAllDay}}全天日程{{else}}定时日程{{end}} - 👤 创建者: {{.organizer.displayName}} - 📊 状态: {{.status}} {{if .description}} **📝 详细描述**: {{.description}} {{end}} {{if .location}} **📍 会议地点**: {{.location.displayName}} {{end}} {{if .onlineMeeting}} **💻 在线会议**: - 会议链接: {{.onlineMeeting.joinUrl}} - 会议ID: {{.onlineMeeting.conferenceId}} {{end}} {{if .attendees}} **👥 参与者** ({{len .attendees}}人): {{range $i, $attendee := .attendees}} {{add $i 1}}. {{$attendee.displayName}} - 状态: {{$attendee.responseStatus}}{{if $attendee.isOptional}} (可选参与){{end}} {{if $attendee.comment}}- 备注: {{$attendee.comment}}{{end}} {{end}} {{end}} {{if .recurrence}} **🔄 重复设置**: {{.recurrence | formatRecurrence}} {{end}} {{if .reminders}} **⏰ 提醒设置**: {{range $reminder := .reminders}} - {{$reminder.method}}: 提前{{$reminder.minutes}}分钟 {{end}} {{end}} - name: listAttendees description: "获取指定日程的所有参与者列表及其状态信息" args: - name: calendarId description: "日历ID,使用'primary'表示主日历" type: string required: true position: path - name: eventId description: "日程ID" type: string required: true position: path - name: maxResults description: "返回的参与者数量上限(默认100,最大500)" type: integer position: query - name: nextToken description: "分页标记,用于获取下一页数据" type: string position: query - name: userId description: "查询者的userId" type: string required: true position: path requestTemplate: url: https://api.dingtalk.com/v1.0/calendar/users/{userId}/calendars/{calendarId}/events/{eventId}/attendees?maxResults=Long&nextToken=String method: GET security: id: DingTalkAuth responseTemplate: body: | # 👥 日程参与者列表 **日程**: {{.eventSummary}} **参与者总数**: {{.totalCount}}人{{if .hasMore}}(显示部分){{end}} {{range $i, $attendee := .attendees}} ## {{add $i 1}}. {{$attendee.displayName}} - 🆔 unionId: {{$attendee.id}} - 📧 邮箱: {{$attendee.email}} - 📱 状态: {{if eq $attendee.responseStatus "accepted"}} 已接受{{else if eq $attendee.responseStatus "declined"}}❌ 已拒绝{{else if eq $attendee.responseStatus "tentative"}}❓ 待定{{else}}⏳ 未回复{{end}} - 👤 类型: {{if $attendee.isOptional}}可选参与者{{else}}必须参与者{{end}} {{if $attendee.comment}}- 💬 备注: {{$attendee.comment}}{{end}} {{if $attendee.isOrganizer}}- 🎯 **组织者**{{end}} {{end}} {{if .nextToken}} --- **📄 分页信息**: 使用 nextToken "{{.nextToken}}" 获取更多参与者 {{end}} - name: listEvents description: "查询指定时间范围内的日程列表,支持分页和增量同步" args: - name: calendarId description: "日历ID,使用'primary'表示主日历" type: string required: true position: path - name: maxAttendees description: "每个日程返回的参与者数量上限(默认100)" type: integer position: query - name: maxResults description: "返回的日程数量上限(默认100,最大100)" type: integer position: query - name: nextToken description: "分页标记,用于获取下一页数据" type: string position: query - name: seriesMasterId description: "重复日程的主日程ID,用于查询特定循环日程" type: string position: query - name: showDeleted description: "是否包含已删除的日程" type: boolean position: query - name: syncToken description: "同步标记,用于增量数据同步" type: string position: query - name: timeMax description: "查询结束时间(ISO-8601格式)" type: string position: query - name: timeMin description: "查询开始时间(ISO-8601格式)" type: string position: query - name: userId description: "要查询的userId" type: string required: true position: path requestTemplate: url: https://api.dingtalk.com/v1.0/calendar/users/{userId}/calendars/{calendarId}/events?timeMin=String&timeMax=String&showDeleted=Boolean&maxResults=Integer&maxAttendees=Integer&nextToken=String&syncToken=String method: GET security: id: DingTalkAuth responseTemplate: body: | # 📋 日程列表 {{if .events}} **查询时间**: {{if .timeMin}}{{.timeMin | formatTime}}{{else}}不限{{end}} {{if .timeMax}}{{.timeMax | formatTime}}{{else}}不限{{end}} **日程数量**: {{len .events}}个{{if .hasMore}}(显示部分){{end}} {{range $i, $event := .events}} ## {{add $i 1}}. {{$event.summary}} - 🆔 ID: {{$event.id}} - 时间: {{$event.start.dateTime | formatTime}} - {{$event.end.dateTime | formatTime}} {{if $event.isAllDay}}- 📅 全天日程{{end}} {{if $event.location}}- 📍 地点: {{$event.location.displayName}}{{end}} {{if $event.attendees}}- 👥 参与者: {{len $event.attendees}}人{{end}} {{if $event.recurrenceId}}- 🔄 这是循环日程的实例{{end}} {{if $event.status}}- 📊 状态: {{$event.status}}{{end}} {{end}} {{if .nextToken}} **📄 分页**: 使用 nextToken "{{.nextToken}}" 获取更多 {{end}} {{if .syncToken}} **🔄 同步**: 使用 syncToken "{{.syncToken}}" 进行增量同步 {{end}} {{else}} 📭 **暂无日程** 指定时间范围内没有找到任何日程。 {{end}} - name: updateEvent description: "修改现有日程的信息,支持更新标题、时间、参与者、地点等任意字段,仅需要组织者权限" args: - name: calendarId description: "日历ID,使用'primary'表示主日历" type: string required: true position: path - name: eventId description: "要修改的日程ID" type: string required: true position: path - name: userId description: "日程组织者的userId" type: string required: true position: path - name: summary description: "日程标题" type: string position: body - name: description description: "日程描述" type: string position: body - name: start description: "日程开始时间" type: object position: body - name: end description: "日程结束时间" type: object position: body - name: location description: "日程地点" type: object position: body - name: attendees description: "参与者列表" type: array items: type: object position: body - name: isAllDay description: "是否为全天日程" type: boolean position: body - name: reminders description: "提醒设置" type: array items: type: object position: body - name: recurrence description: "重复设置" type: object position: body - name: onlineMeetingInfo description: "在线会议设置" type: object position: body - name: x-client-token description: "幂等性校验令牌" type: string position: header requestTemplate: url: https://api.dingtalk.com/v1.0/calendar/users/{userId}/calendars/{calendarId}/events/{eventId} method: PUT headers: - key: Content-Type value: application/json security: id: DingTalkAuth responseTemplate: body: | # ✏️ 日程修改结果 {{if .success}} **日程修改成功** **更新后的日程信息**: - 📅 标题: {{.summary}} - 🆔 日程ID: {{.id}} - 开始时间: {{.start.dateTime | formatTime}} - 结束时间: {{.end.dateTime | formatTime}} - 📍 类型: {{if .isAllDay}}全天日程{{else}}定时日程{{end}} {{if .description}} - 📝 描述: {{.description}} {{end}} {{if .location}} - 📍 地点: {{.location.displayName}} {{end}} **修改的内容**: {{range $change := .changes}} - {{$change.field}}: {{$change.oldValue}} {{$change.newValue}} {{end}} {{if .attendees}} **参与者** ({{len .attendees}}人): {{range $i, $attendee := .attendees}} {{add $i 1}}. {{$attendee.displayName}}{{if $attendee.isOptional}} (可选){{end}} {{end}} {{end}} {{if .onlineMeeting}} **在线会议**: - 会议链接: {{.onlineMeeting.joinUrl}} {{end}} {{else}} **日程修改失败** - {{.error}} **错误详情**: {{.errorMessage}} {{end}} - name: removeAttendee description: "从指定日程中移除参与者,支持批量移除多人" args: - name: attendeesToRemove description: "需要移除的参与者列表" type: array items: type: object position: body - name: calendarId description: "日历ID,使用'primary'表示主日历" type: string required: true position: path - name: eventId description: "日程ID" type: string required: true position: path - name: id description: "要移除的unionId" type: string position: body - name: userId description: "日程创建者的userId" type: string required: true position: path - name: x-client-token description: "幂等性校验令牌" type: string position: header requestTemplate: url: https://api.dingtalk.com/v1.0/calendar/users/{userId}/calendars/{calendarId}/events/{eventId}/attendees/remove method: POST headers: - key: Content-Type value: application/json security: id: DingTalkAuth responseTemplate: body: | # 👥➖ 日程参与者移除结果 {{if .success}} **操作成功** - 已从日程中移除参与者 **日程信息**: - 日程ID: {{.eventId}} - 操作时间: {{.timestamp}} **移除的参与者**: {{range $i, $attendee := .removedAttendees}} {{add $i 1}}. {{$attendee.displayName}} - unionId: {{$attendee.id}} - 移除原因: {{$attendee.reason}} {{end}} **剩余参与者数量**: {{.remainingCount}} {{if .notifications}} **通知状态**: {{if .notifications.attendeesNotified}} - 已向移除的参与者发送通知 {{end}} {{end}} {{else}} **操作失败** - {{.error}} **错误详情**: {{.errorMessage}} {{end}} - name: searchUser description: "在企业组织中搜索用户,支持按姓名、邮箱、手机号等关键词查找" args: - name: query_word description: "搜索关键词(姓名、邮箱、手机号等)" type: string required: true position: body - name: dept_id description: "限定搜索的部门ID,不填则搜索整个企业" type: number position: body - name: offset description: "分页偏移量(从0开始)" type: number position: body - name: size description: "返回结果数量(最大50)" type: number position: body - name: only_active description: "是否只搜索激活状态的用户" type: boolean position: body requestTemplate: url: https://api.dingtalk.com/v1.0/contact/users/search method: POST headers: - key: Content-Type value: application/json security: id: DingTalkAuth responseTemplate: body: | # 🔍 用户搜索结果 {{if .users}} **搜索关键词**: "{{.query}}" {{if .deptName}}**搜索范围**: {{.deptName}}{{else}}**搜索范围**: 全企业{{end}} **找到用户**: {{len .users}}个{{if .hasMore}}(显示部分){{end}} {{range $i, $user := .users}} ## {{add $i 1}}. {{$user.name}} - 🆔 unionId: {{$user.unionid}} - 📧 邮箱: {{$user.email}} - 📱 手机: {{$user.mobile}} - 🏢 部门: {{$user.deptName}} - 💼 职位: {{$user.title}} - 📊 状态: {{if $user.active}} 激活{{else}}❌ 未激活{{end}} {{if $user.avatar}}- 📷 头像: {{$user.avatar}}{{end}} {{end}} {{if .hasMore}} --- **📄 分页信息**: 还有更多结果,使用 offset={{.nextOffset}} 获取更多 {{end}} {{else}} 🔍 **未找到用户** 关键词"{{.query}}"没有匹配到任何用户,请尝试: - 检查关键词拼写 - 使用更准确的姓名或邮箱 - 扩大搜索范围(不限制部门) {{end}} - name: getUserDetails description: "获取指定用户的详细信息,包含完整的个人资料和组织架构信息" args: - name: userid description: "用户的userId" type: string required: true position: body - name: language description: "返回信息的语言(zh_CN=中文,en_US=英文)" type: string position: body requestTemplate: url: https://oapi.dingtalk.com/topapi/v2/user/get method: POST headers: - key: Content-Type value: application/json security: id: DingTalkAuth responseTemplate: body: | # 👤 用户详细信息 {{if .user}} ## {{.user.name}} **基本信息**: - 🆔 unionId: {{.user.unionid}} - 📧 邮箱: {{.user.email}} - 📱 手机: {{.user.mobile}} - 🏢 工号: {{.user.jobNumber}} - 💼 职位: {{.user.title}} - 📊 状态: {{if .user.active}} 激活{{else}}❌ 未激活{{end}} {{if .user.avatar}} **头像**: {{.user.avatar}} {{end}} **组织架构**: {{range $i, $dept := .user.departments}} {{add $i 1}}. {{$dept.name}} - 部门ID: {{$dept.id}} {{if $dept.isLeader}}- 🎯 **部门负责人**{{end}} {{if $dept.isMainDept}}- 🏠 **主部门**{{end}} {{end}} {{if .user.extension}} **扩展信息**: {{range $key, $value := .user.extension}} - {{$key}}: {{$value}} {{end}} {{end}} **账号信息**: - 创建时间: {{.user.hiredDate | formatTime}} {{if .user.workPlace}}- 工作地点: {{.user.workPlace}}{{end}} {{if .user.remark}}- 备注: {{.user.remark}}{{end}} {{else}} **用户不存在** 用户ID "{{.userid}}" 未找到,请检查: - 用户ID是否正确 - 用户是否已被删除 - 是否有权限访问该用户信息 {{end}}