Skip to main content
Glama
BobGod

WeChat Publisher MCP

by BobGod

wechat_query_status

Check WeChat Official Account article publishing status and view statistics using message ID and account credentials.

Instructions

查询文章发布状态和统计数据

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
msgIdYes消息ID
appIdYes微信公众号AppID
appSecretYes微信公众号AppSecret

Implementation Reference

  • src/server.js:74-108 (registration)
    Registration of the wechat_query_status tool, including input schema definition and thin wrapper handler that delegates to WeChatStatus.query
    server.registerTool(
      "wechat_query_status",
      {
        description: "查询文章发布状态和统计数据",
        inputSchema: {
          msgId: z.string().describe("消息ID"),
          appId: z.string().describe("微信公众号AppID"),
          appSecret: z.string().describe("微信公众号AppSecret")
        }
      },
      async (params) => {
        const { msgId, appId, appSecret } = params;
        logger.info(`Querying status for message: ${msgId}`);
        
        try {
          // 调用实际的查询逻辑
          const result = await WeChatStatus.query({
            msgId,
            appId,
            appSecret
          });
          
          return result;
        } catch (error) {
          logger.error(`查询失败: ${error.message}`);
          return {
            content: [{
              type: "text",
              text: `❌ 查询失败: ${error.message}`
            }],
            isError: true
          };
        }
      }
    );
  • Core handler implementation for wechat_query_status: performs parameter validation, initializes WeChatAPI, queries publish status, formats detailed response with stats, handles errors.
    static async query(params) {
      const startTime = Date.now();
      
      try {
        logger.info('开始查询状态', { msgId: params.msgId });
        
        // 1. 参数验证
        const validation = validateStatusParams(params);
        if (!validation.valid) {
          throw new Error(`参数验证失败: ${validation.errors.join(', ')}`);
        }
    
        const { msgId, appId, appSecret } = params;
    
        // 2. 初始化微信API
        logger.debug('初始化微信API');
        const wechatAPI = new WeChatAPI(appId, appSecret);
    
        // 3. 查询发布状态
        logger.debug('查询发布状态', { msgId });
        const statusData = await wechatAPI.getPublishStatus(msgId);
    
        const executionTime = Date.now() - startTime;
        logger.info('状态查询成功', { 
          msgId,
          status: statusData.publish_status,
          executionTime: `${executionTime}ms` 
        });
    
        // 4. 构建成功响应
        const successMessage = this.buildStatusMessage(statusData, executionTime, msgId);
    
        return {
          content: [{
            type: "text",
            text: successMessage
          }]
        };
    
      } catch (error) {
        const executionTime = Date.now() - startTime;
        logger.error('状态查询失败', {
          msgId: params.msgId,
          error: error.message,
          executionTime: `${executionTime}ms`,
          stack: error.stack
        });
        
        return {
          content: [{
            type: "text",
            text: this.buildErrorMessage(error)
          }],
          isError: true
        };
      }
    }
  • Low-level helper that performs the actual HTTP request to WeChat API endpoint /cgi-bin/freepublish/get to retrieve publish status and article stats.
    async getPublishStatus(msgId) {
      logger.info('开始查询发布状态', { msgId, appId: this.appId });
      
      // 检查是否为明确的测试模式(只有以test_开头的msgId才使用模拟数据)
      if (msgId && msgId.toString().startsWith('test_')) {
        logger.info('测试模式:返回模拟状态数据', { msgId });
        return {
          errcode: 0,
          errmsg: 'ok',
          publish_status: 1, // 发布成功
          article_detail: {
            count: 1,
            item: [{
              article_id: msgId,
              title: '测试文章标题',
              author: '测试作者',
              digest: '这是一篇测试文章',
              content: '',
              content_source_url: '',
              url: `https://mp.weixin.qq.com/s/test_${msgId}`,
              publish_time: Math.floor(Date.now() / 1000),
              stat_info: {
                read_num: 0,  // 测试模式不显示虚假阅读量
                like_num: 0,
                comment_num: 0,
                share_num: 0
              }
            }]
          }
        };
      }
      
      // 对于真实的msgId,始终调用真实的微信API
      const accessToken = await this.getAccessToken();
      logger.debug('获取到access_token,准备查询状态', { tokenLength: accessToken.length });
      
      try {
        logger.debug('调用微信API查询发布状态', { 
          msgId, 
          api: 'freepublish/get' 
        });
        
        const response = await axios.post(
          `https://api.weixin.qq.com/cgi-bin/freepublish/get?access_token=${accessToken}`,
          { publish_id: msgId },
          { timeout: 15000 }
        );
    
        logger.debug('微信API响应', { 
          errcode: response.data.errcode,
          errmsg: response.data.errmsg,
          hasArticleDetail: !!response.data.article_detail
        });
    
        if (response.data.errcode === 0) {
          logger.info('状态查询成功', { 
            msgId,
            status: response.data.publish_status,
            articleCount: response.data.article_detail?.count || 0
          });
          return response.data;
        } else {
          // 如果是文章不存在或权限问题,返回更友好的错误信息
          if (response.data.errcode === 40007) {
            throw new Error(`文章不存在或已被删除 (错误码: ${response.data.errcode})`);
          } else if (response.data.errcode === 40001) {
            throw new Error(`access_token无效,请检查AppID和AppSecret (错误码: ${response.data.errcode})`);
          } else {
            throw new Error(`查询发布状态失败: ${response.data.errmsg} (错误码: ${response.data.errcode})`);
          }
        }
      } catch (error) {
        logger.error('状态查询失败', { 
          msgId,
          error: error.message,
          isAxiosError: !!error.response
        });
        
        if (error.response) {
          const errorData = error.response.data;
          throw new Error(`微信API调用失败: ${errorData.errmsg || error.message} (HTTP状态: ${error.response.status})`);
        } else if (error.code === 'ECONNABORTED') {
          throw new Error('请求超时,请检查网络连接后重试');
        } else {
          throw new Error(`网络请求失败: ${error.message}`);
        }
      }
    }
  • Runtime input schema validation for wechat_query_status parameters: checks required fields, formats, lengths for msgId, appId, appSecret.
    function validateStatusParams(params) {
      const errors = [];
      
      // 必需参数检查
      if (!params.msgId || typeof params.msgId !== 'string' || params.msgId.trim() === '') {
        errors.push('msgId参数是必需的,且不能为空字符串');
      }
      
      if (!params.appId || typeof params.appId !== 'string' || params.appId.trim() === '') {
        errors.push('appId参数是必需的,且不能为空字符串');
      }
      
      if (!params.appSecret || typeof params.appSecret !== 'string' || params.appSecret.trim() === '') {
        errors.push('appSecret参数是必需的,且不能为空字符串');
      }
      
      // 格式验证
      if (params.msgId && !isValidMsgId(params.msgId)) {
        errors.push('msgId格式不正确,应该是数字字符串');
      }
      
      // AppID格式验证
      if (params.appId && !params.appId.startsWith('wx')) {
        errors.push('AppID格式错误,应该以"wx"开头');
      }
      
      if (params.appId && params.appId.length !== 18) {
        errors.push('AppID长度应该为18个字符');
      }
      
      // AppSecret格式验证
      if (params.appSecret && params.appSecret.length !== 32) {
        errors.push('AppSecret长度应该为32个字符');
      }
      
      return {
        valid: errors.length === 0,
        errors
      };
    }
  • Zod-based input schema definition for the tool registration, specifying required string parameters.
    description: "查询文章发布状态和统计数据",
    inputSchema: {
      msgId: z.string().describe("消息ID"),
      appId: z.string().describe("微信公众号AppID"),
      appSecret: z.string().describe("微信公众号AppSecret")
    }
Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/BobGod/wechat-publisher-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server