Skip to main content
Glama

get_work_item

Retrieve PingCode work item details by entering its identifier such as #12345, 12345, or LFY-123 to access project management data.

Instructions

通过 PingCode 工作项编号获取详情。支持格式:#12345、12345、LFY-123 等。

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
identifierYes工作项编号,如 #12345、12345 或 LFY-123

Implementation Reference

  • Core handler function for the 'get_work_item' tool. Fetches work item details from PingCode API, formats the data into a readable string with structured fields, generates AI directives for single-task mode and bug analysis workflow, and returns formatted response.
    export async function getWorkItem(identifier: string): Promise<{
      success: boolean;
      data?: string;
      workItem?: WorkItemData;
      aiDirectives?: AiDirectives;
      nextRequiredAction?: NextRequiredAction;
      error?: string;
    }> {
      try {
        // 使用增强版 API 获取带成员名称的工作项
        const item = await pingcodeClient.getWorkItemWithDetails(identifier);
    
        if (!item) {
          return {
            success: false,
            error: `未找到编号为 ${identifier} 的工作项`,
          };
        }
    
        const workItem = formatWorkItem(item);
        
        // 根据工作项类型推荐 commit type
        const typeMap: Record<string, string> = {
          '缺陷': 'fix',
          '需求': 'feat',
          '用户故事': 'feat',
          '任务': 'chore',
          '史诗': 'feat',
        };
        const suggestedType = typeMap[workItem.type.value] || 'chore';
        const suggestedMsg = `#${workItem.id.value} ${suggestedType}: ${workItem.title.value}`;
    
        const requiredFirstOutput = `🔒 单任务模式:处理 ${workItem.id.value},完成后立即询问 commit`;
    
        const aiDirectives: AiDirectives = {
          mode: 'single_task',
          work_item_id: workItem.id.value,
          stop_after_fix: true,
          ask_commit_after_fix: true,
          wait_user_reply_before_next_item: true,
          forbidden_actions: [
            'get_other_work_item_before_commit_decision',
            'batch_fetch_multiple_work_items_in_parallel',
            'modify_multiple_work_items',
          ],
          required_first_output: requiredFirstOutput,
          commit: {
            suggested_message: suggestedMsg,
            options: ['use_suggested', 'user_provided', 'skip'],
          },
        };
    
        // 判断是否为缺陷类型
        const isBug = workItem.type.value === '缺陷';
    
        // Bug 分析流程提示(仅当类型为缺陷时添加)
        const bugAnalysisPrompt = isBug ? [
          '',
          '🐛 **[缺陷分析流程 - 强制执行]**',
          '',
          '## 核心原则:证据驱动,禁止假设',
          '',
          '### 第一步:穷举现象 → 提取搜索词',
          '从标题/截图/日志/描述/评论中提取**所有**异常(不能只看最明显的)。',
          '每个现象提取 1-2 个**代码搜索关键词**(函数名、错误信息、变量名等)。',
          '',
          '### 第二步:筛选相关现象',
          '问自己:这个异常**是否会导致**用户最终看到的问题?',
          '- 如果能建立因果链 → 保留,继续分析',
          '- 如果只是时间上巧合 → 标记为"疑似无关",暂时跳过',
          '- 不确定 → 先分析最明显相关的,再回头验证',
          '',
          '### 第三步:定位直接代码',
          '用筛选后的关键词搜索代码,找到**直接产生**该现象的代码行。',
          '搜索范围要足够广,不要局限在你假设的位置。',
          '',
          '### 第四步:向上追溯调用链',
          '从第三步的代码向上追溯:谁调用了它?在什么条件下触发?',
          '直到找到**用户操作**或**外部输入**为止。',
          '',
          '### 第五步:验证因果关系',
          '**关键验证**:这条调用链走到底,是否**真的会产生**用户看到的最终现象?',
          '- 如果是 → 进入修复',
          '- 如果不是 → 回到第一步,分析其他现象',
          '',
          '### 第六步:确定阻断点并修复',
          '在调用链中选择**最合适的阻断点**进行修复。',
          '',
          '---',
          '',
          '## 追踪链强制输出(修复前必须完成)',
          '',
          '```',
          '最终现象:[用户实际看到的问题是什么]',
          '相关异常:[哪些日志/报错与最终现象有因果关系]',
          '排除异常:[哪些报错判断为无关,为什么]',
          '搜索词:[用于代码搜索的关键词]',
          '直接代码:[file:line - 哪行代码产生了这个现象]',
          '调用链:[调用者1] → [调用者2] → [直接代码]',
          '因果验证:[这条链如何导致最终现象]',
          '阻断点:[在哪里修复,为什么选这里]',
          '```',
          '',
          '⛔ **禁止**:',
          '- 追踪链未完成就给修复方案',
          '- 追踪链中出现"可能"、"也许"、"应该是"',
          '- 跳过搜索直接假设问题位置',
          '- 把时间上巧合的报错当作原因',
          '',
        ].join('\n') : '';
    
        // 给 AI 的提示词(文本兜底:即使客户端不读取 aiDirectives,也尽量让模型遵守)
        const aiPrompt = [
          '---',
          '🛑🛑🛑 **[AI 强制指令 - 必须首先执行]** 🛑🛑🛑',
          '',
          '以下规则是 pingcode-mcp 的交互协议(不是普通备注)。',
          bugAnalysisPrompt,
          '**单任务模式已激活,违反以下规则将导致工作流失败:**',
          '1. **STOP**:完成本工作项的代码修改后,必须立即停止所有操作',
          '2. **ASK**:停止后必须询问用户是否创建 commit(提供:使用建议 / 用户输入 / 不提交)',
          '3. **WAIT**:必须等待用户回复后,才能处理下一个工作项',
          '4. **禁止**:禁止同时修改多个工作项;禁止批量完成后统一询问;禁止在用户回复前获取下一个工作项',
          '',
          `**开始前确认**:AI 必须先输出 "${requiredFirstOutput}"`,
          '',
          '**内容解析**:描述与评论冲突以评论为准;多条更新按时间倒序;图片可能包含关键信息',
          '',
          '**Commit 信息**:',
          `- 建议 commit:${suggestedMsg}`,
          '---',
          '',
        ].join('\n');
    
        return {
          success: true,
          data: aiPrompt + getWorkItemString(workItem),
          workItem,
          aiDirectives,
          nextRequiredAction: {
            type: 'announce_single_task_mode',
            blocked_until_user_reply: false,
            required_output: requiredFirstOutput,
          },
        };
      } catch (error: any) {
        return {
          success: false,
          error: error.message,
        };
      }
    }
  • src/index.ts:58-72 (registration)
    Registration of the 'get_work_item' tool in the MCP server's ListTools handler, defining name, description, and input schema.
    {
      name: 'get_work_item',
      description:
        '通过 PingCode 工作项编号获取详情。支持格式:#12345、12345、LFY-123 等。',
      inputSchema: {
        type: 'object',
        properties: {
          identifier: {
            type: 'string',
            description: '工作项编号,如 #12345、12345 或 LFY-123',
          },
        },
        required: ['identifier'],
      },
    },
  • MCP server CallToolRequestSchema dispatch handler for 'get_work_item', extracts identifier argument, calls the implementation getWorkItem, and formats the MCP response with text content and structured data.
    case 'get_work_item': {
      const identifier = (args as { identifier: string }).identifier;
      const result = await getWorkItem(identifier);
      
      if (!result.success) {
        return {
          content: [{ type: 'text', text: `错误: ${result.error}` }],
          isError: true,
        };
      }
    
      return {
        content: [
          {
            type: 'text',
            text: result.data!,
            // 结构化数据:供 MCP 客户端/模型可靠读取
            data: {
              work_item: result.workItem,
              ai_directives: result.aiDirectives,
              next_required_action: result.nextRequiredAction,
            },
          },
        ] as any,
      };
    }
  • Type definitions for FieldData and WorkItemData used for structured output of the work item details in the tool response.
    export interface FieldData {
      label: string;
      value: string;
    }
    
    /**
     * 工作项格式化后的数据结构
     */
    export interface WorkItemData {
      /**编号 */
      id: FieldData;
      /**标题 */
      title: FieldData;
      /** 类型 */
      type: FieldData;
      /** 状态 */
      state: FieldData;
      /** 优先级 */
      priority: FieldData;
      /** 负责人 */
      assignee: FieldData;
      /** 创建人 */
      createdBy: FieldData;
      /** 创建时间 */
      createdAt: FieldData;
      /** 更新时间 */
      updatedAt: FieldData;
      /** 描述 */
      description: FieldData;
      /** 附件列表 */
      attachments: Array<{ name: string; url: string }>;
      /** 评论列表 */
      comments: Array<{ author: string; time: string; content: string }>;
    }
  • Helper function to convert formatted WorkItemData into a human-readable Markdown string for the tool response.
    function getWorkItemString(data: WorkItemData): string {
      const lines: string[] = [
        `## ${data.id.value} - ${data.title.value}`,
        '',
        `- **${data.type.label}**: ${data.type.value}`,
        `- **${data.state.label}**: ${data.state.value}`,
        `- **${data.priority.label}**: ${data.priority.value}`,
        `- **${data.assignee.label}**: ${data.assignee.value}`,
      ];
    
      if (data.createdBy.value) {
        lines.push(`- **${data.createdBy.label}**: ${data.createdBy.value}`);
      }
      if (data.createdAt.value) {
        lines.push(`- **${data.createdAt.label}**: ${data.createdAt.value}`);
      }
      if (data.updatedAt.value) {
        lines.push(`- **${data.updatedAt.label}**: ${data.updatedAt.value}`);
      }
    
      if (data.description.value) {
        lines.push('', `### ${data.description.label}`, '', data.description.value);
      }
    
      if (data.attachments.length > 0) {
        lines.push('', '### 附件', '');
        data.attachments.forEach((att) => {
          if (att.url) {
            lines.push(`- [${att.name}](${att.url})`);
          } else {
            lines.push(`- ${att.name}`);
          }
        });
      }
    
      if (data.comments.length > 0) {
        lines.push('', `### 评论 (${data.comments.length})`, '');
        data.comments.forEach((comment, index) => {
          lines.push(`**${index + 1}. ${comment.author}** (${comment.time}):`);
          lines.push(`> ${comment.content}`);
          lines.push('');
        });
      }
    
      return lines.join('\n');
    }

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/ratatatat1/pingcode-mcp'

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