UNPKG

@perk-net/pushplus-mcp-server

Version:

PushPlus MCP Server - 通过 Model Context Protocol 提供 PushPlus 推送消息功能,支持微信、邮箱等多渠道推送

212 lines 7.27 kB
/** * PushPlus API 客户端模块 * 提供 PushPlus 推送服务的 TypeScript 接口 */ import { z } from 'zod'; // PushPlus API 响应模式定义 export const PushPlusResponseSchema = z.object({ code: z.number(), msg: z.string(), data: z.string().optional(), count: z.number().optional() }); // 推送消息参数模式定义 export const PushMessageSchema = z.object({ token: z.string().describe('用户令牌,32位字符串'), title: z.string().describe('消息标题,最大长度100'), content: z.string().describe('具体消息内容,根据template参数进行渲染'), topic: z.string().optional().describe('群组编码,不填仅发送给自己'), template: z.enum(['html', 'txt', 'json', 'markdown', 'cloudMonitor', 'jenkins', 'route', 'pay']).default('html').describe('发送消息模板'), channel: z.enum(['wechat', 'webhook', 'cp', 'mail', 'sms']).default('wechat').describe('发送渠道'), to: z.string().optional().describe('好友令牌,微信公众号渠道填写好友令牌,企业微信渠道填写企业微信用户id。多人用逗号隔开,实名用户最多10人,会员100人'), pre: z.string().optional().describe('预处理编码,仅供会员使用。可提前自定义代码来修改消息内容'), webhook: z.string().url().optional().describe('第三方webhook地址'), callbackUrl: z.string().url().optional().describe('消息回调地址'), timestamp: z.number().optional().describe('毫秒时间戳,用于防重复') }); // 消息状态查询参数 export const MessageStatusQuerySchema = z.object({ token: z.string(), messageId: z.string() }); /** * PushPlus API 客户端类 */ export class PushPlusClient { defaultToken; baseUrl = 'https://www.pushplus.plus/send'; queryUrl = 'https://www.pushplus.plus/query'; constructor(defaultToken) { this.defaultToken = defaultToken; } /** * 发送推送消息 * @param message 消息参数 * @returns 推送结果 */ async sendMessage(message) { const token = message.token || this.defaultToken; if (!token) { throw new Error('缺少 PushPlus token,请在消息参数中提供或在初始化时设置默认token'); } const payload = { token, title: message.title, content: message.content, template: message.template || 'html', channel: message.channel || 'wechat', topic: message.topic, to: message.to, pre: message.pre, webhook: message.webhook, callbackUrl: message.callbackUrl, timestamp: message.timestamp }; // 验证参数 const validatedPayload = PushMessageSchema.parse(payload); try { const response = await fetch(this.baseUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', 'User-Agent': 'PushPlus-MCP-Server/1.0.1' }, body: JSON.stringify(validatedPayload) }); if (!response.ok) { throw new Error(`HTTP请求失败: ${response.status} ${response.statusText}`); } const data = await response.json(); return PushPlusResponseSchema.parse(data); } catch (error) { if (error instanceof z.ZodError) { throw new Error(`参数验证失败: ${error.errors.map(e => e.message).join(', ')}`); } throw new Error(`发送消息失败: ${error instanceof Error ? error.message : String(error)}`); } } /** * 查询消息发送状态 * @param query 查询参数 * @returns 消息状态 */ async queryMessageStatus(query) { const token = query.token || this.defaultToken; if (!token) { throw new Error('缺少 PushPlus token'); } const payload = MessageStatusQuerySchema.parse({ ...query, token }); try { const response = await fetch(this.queryUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', 'User-Agent': 'PushPlus-MCP-Server/1.0.1' }, body: JSON.stringify(payload) }); if (!response.ok) { throw new Error(`HTTP请求失败: ${response.status} ${response.statusText}`); } const data = await response.json(); return PushPlusResponseSchema.parse(data); } catch (error) { if (error instanceof z.ZodError) { throw new Error(`参数验证失败: ${error.errors.map(e => e.message).join(', ')}`); } throw new Error(`查询消息状态失败: ${error instanceof Error ? error.message : String(error)}`); } } /** * 快速发送文本消息 * @param title 消息标题 * @param content 消息内容 * @param options 可选参数 * @returns 推送结果 */ async sendTextMessage(title, content, options) { return this.sendMessage({ title, content, template: 'txt', ...options }); } /** * 快速发送HTML消息 * @param title 消息标题 * @param content HTML内容 * @param options 可选参数 * @returns 推送结果 */ async sendHtmlMessage(title, content, options) { return this.sendMessage({ title, content, template: 'html', ...options }); } /** * 快速发送Markdown消息 * @param title 消息标题 * @param content Markdown内容 * @param options 可选参数 * @returns 推送结果 */ async sendMarkdownMessage(title, content, options) { return this.sendMessage({ title, content, template: 'markdown', ...options }); } /** * 快速发送JSON消息 * @param title 消息标题 * @param content JSON内容 * @param options 可选参数 * @returns 推送结果 */ async sendJsonMessage(title, content, options) { return this.sendMessage({ title, content, template: 'json', ...options }); } /** * 设置默认token * @param token PushPlus token */ setDefaultToken(token) { this.defaultToken = token; } /** * 获取当前默认token(脱敏显示) * @returns 脱敏的token字符串 */ getDefaultTokenMasked() { if (!this.defaultToken) { return '未设置'; } return this.defaultToken.slice(0, 8) + '***' + this.defaultToken.slice(-4); } /** * 验证token格式 * @param token 待验证的token * @returns 是否有效 */ static isValidToken(token) { // PushPlus token 通常是32位字符串 return /^[a-zA-Z0-9]{32}$/.test(token); } } //# sourceMappingURL=pushplus.js.map