Skip to main content
Glama
marco-looy

Pega DX MCP Server

by marco-looy

get_assignment

Fetch assignment details including form structure, required fields, available actions, and eTag to support subsequent operations after case creation.

Instructions

Get assignment details including form fields, required fields, available actions, and eTag. Used BETWEEN case creation and action performance. Returns form structure, action IDs, and eTag needed for subsequent operations. Required fields marked with "required": true in view config (uiResources.resources.views). Pessimistic locking may apply.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
assignmentIDYesAssignment ID from create_case (nextAssignmentInfo.ID) or perform_assignment_action. Format: ASSIGN-WORKLIST {caseID}!{processID}. Example: ASSIGN-WORKLIST PBANK-LOAN-WORK V-76003!REVIEW_FLOW
viewTypeNoUI resources to return. "form" (recommended): field metadata and view structure. "page": full page UI metadata. Both include required field markers in view config.form
pageNameNoIf provided, returns view metadata for the pageName view (only used when viewType is "page")
sessionCredentialsNoOptional session-specific credentials. If not provided, uses environment variables. Supports two authentication modes: (1) OAuth mode - provide baseUrl, clientId, and clientSecret, or (2) Token mode - provide baseUrl and accessToken.

Implementation Reference

  • GetAssignmentTool.execute() - Main handler that validates params, calls pegaClient.getAssignment(), formats result via formatSuccessResponse (overridden).
    async execute(params) {
      const { assignmentID, viewType = 'form', pageName } = params;
      let sessionInfo = null;
    
      try {
        // Initialize session configuration if provided
        sessionInfo = this.initializeSessionConfig(params);
    
        // Basic parameter validation using base class
        const requiredValidation = this.validateRequiredParams(params, ['assignmentID']);
        if (requiredValidation) {
          return requiredValidation;
        }
    
        // Validate enum parameters using base class
        const enumValidation = this.validateEnumParams(params, {
          viewType: ['form', 'page']
        });
        if (enumValidation) {
          return enumValidation;
        }
    
        // Validate pageName usage
        if (pageName && viewType !== 'page') {
          return {
            error: 'pageName parameter can only be used when viewType is set to "page".'
          };
        }
    
        // Execute with standardized error handling
        return await this.executeWithErrorHandling(
          `Assignment Details: ${assignmentID}`,
          async () => await this.pegaClient.getAssignment(assignmentID.trim(), {
            viewType,
            pageName
          }),
          { assignmentID, viewType, pageName, sessionInfo }
        );
      } catch (error) {
        return {
          content: [{
            type: 'text',
            text: `## Error: Assignment Details\n\n**Unexpected Error**: ${error.message}\n\n${sessionInfo ? `**Session**: ${sessionInfo.sessionId} (${sessionInfo.authMode} mode)\n` : ''}*Error occurred at: ${new Date().toISOString()}*`
          }]
        };
      }
  • getDefinition() - Schema/definition for the 'get_assignment' MCP tool including input parameters.
    static getDefinition() {
      return {
        name: 'get_assignment',
        description: 'Get assignment details including form fields, required fields, available actions, and eTag. Used BETWEEN case creation and action performance. Returns form structure, action IDs, and eTag needed for subsequent operations. Required fields marked with "required": true in view config (uiResources.resources.views). Pessimistic locking may apply.',
        inputSchema: {
          type: 'object',
          properties: {
            assignmentID: {
              type: 'string',
              description: 'Assignment ID from create_case (nextAssignmentInfo.ID) or perform_assignment_action. Format: ASSIGN-WORKLIST {caseID}!{processID}. Example: ASSIGN-WORKLIST PBANK-LOAN-WORK V-76003!REVIEW_FLOW'
            },
            viewType: {
              type: 'string',
              enum: ['form', 'page'],
              description: 'UI resources to return. "form" (recommended): field metadata and view structure. "page": full page UI metadata. Both include required field markers in view config.',
              default: 'form'
            },
            pageName: {
              type: 'string',
              description: 'If provided, returns view metadata for the pageName view (only used when viewType is "page")'
            },
            sessionCredentials: getSessionCredentialsSchema()
          },
          required: ['assignmentID']
        }
      };
    }
  • Discovery-based registration via configurable-tool-loader: scans src/tools/assignments/, imports get-assignment.js, finds GetAssignmentTool, registers it as 'get_assignment'.
    async loadToolFile(categoryPath, filename, category) {
      const filePath = resolve(categoryPath, filename);
      const fileUrl = pathToFileURL(filePath).href;
      
      try {
        const module = await import(fileUrl);
        
        // Find the tool class in the module
        const ToolClass = this.findToolClass(module);
        if (!ToolClass) {
          return {
            loaded: false,
            toolName: filename.replace('.js', ''),
            reason: 'No valid tool class found'
          };
        }
        
        // Validate tool class
        const validationResult = this.validateToolClass(ToolClass, category, filename);
        if (!validationResult.valid) {
          return {
            loaded: false,
            toolName: filename.replace('.js', ''),
            reason: validationResult.reason
          };
        }
        
        // Get tool name from definition
        const toolName = ToolClass.getDefinition().name;
        
        // Check if tool should be loaded based on configuration
        if (!toolConfig.isToolEnabled(toolName, category)) {
          return {
            loaded: false,
            toolName: toolName,
            reason: 'disabled in configuration'
          };
        }
        
        // Create and register tool instance
        const toolInstance = new ToolClass();
        
        this.loadedTools.set(toolName, {
          instance: toolInstance,
          class: ToolClass,
          category: category,
          filename: filename
        });
        
        return {
          loaded: true,
          tool: toolInstance,
          toolName: toolName
        };
      } catch (error) {
        throw new Error(`Failed to import ${filename}: ${error.message}`);
      }
    }
  • Overrides BaseTool.formatSuccessResponse to produce rich markdown output for assignment details including case info, actions table, UI fields, eTag, and next-step guidance.
    formatSuccessResponse(operation, data, options = {}) {
      const { assignmentID, viewType, sessionInfo } = options;
    
      let response = `## ${operation}\n\n`;
    
      response += `*Operation completed at: ${new Date().toISOString()}*\n\n`;
    
      // Session Information (if applicable)
      if (sessionInfo) {
        response += `### Session Information\n`;
        response += `- **Session ID**: ${sessionInfo.sessionId}\n`;
        response += `- **Authentication Mode**: ${sessionInfo.authMode.toUpperCase()}\n`;
        response += `- **Configuration Source**: ${sessionInfo.configSource}\n\n`;
      }
      
      if (data.data) {
        // Display assignment information
        if (data.assignmentInfo || data.data.assignmentInfo) {
          const assignmentInfo = data.assignmentInfo || data.data.assignmentInfo;
          response += '### Assignment Information\n';
          response += `- **Assignment ID**: ${assignmentInfo.ID || assignmentID}\n`;
          response += `- **Assignment Type**: ${assignmentInfo.assignmentType || 'N/A'}\n`;
          response += `- **Instructions**: ${assignmentInfo.instructions || 'N/A'}\n`;
          response += `- **Assigned To**: ${assignmentInfo.assignedTo || 'N/A'}\n`;
          response += `- **Due Date**: ${assignmentInfo.dueDate || 'N/A'}\n`;
          response += `- **Priority**: ${assignmentInfo.priority || 'N/A'}\n`;
          response += `- **Status**: ${assignmentInfo.status || 'N/A'}\n`;
          
          if (assignmentInfo.stepPageName) {
            response += `- **Step Page**: ${assignmentInfo.stepPageName}\n`;
          }
          
          if (assignmentInfo.stepDescription) {
            response += `- **Step Description**: ${assignmentInfo.stepDescription}\n`;
          }
        }
    
        // Display case information if available
        if (data.data.caseInfo) {
          const caseInfo = data.data.caseInfo;
          response += '\n### Associated Case Information\n';
          response += `- **Case ID**: ${caseInfo.ID || 'N/A'}\n`;
          response += `- **Case Type**: ${caseInfo.caseTypeName || 'N/A'}\n`;
          response += `- **Case Status**: ${caseInfo.status || 'N/A'}\n`;
          response += `- **Stage**: ${caseInfo.stage || 'N/A'}\n`;
          response += `- **Step**: ${caseInfo.step || 'N/A'}\n`;
          response += `- **Urgency**: ${caseInfo.urgency || 'N/A'}\n`;
          response += `- **Created**: ${caseInfo.createTime || 'N/A'}\n`;
          response += `- **Last Updated**: ${caseInfo.lastUpdateTime || 'N/A'}\n`;
        }
    
        // Display available actions if present
        // Actions can be in data.actions or data.data.caseInfo.assignments[0].actions
        let actions = data.actions;
    
        if (!actions || actions.length === 0) {
          // Try alternate location
          const assignments = data.data?.caseInfo?.assignments;
          if (assignments && assignments.length > 0 && assignments[0].actions) {
            actions = assignments[0].actions;
          }
        }
    
        if (actions && actions.length > 0) {
          response += '\n### ⚠️ Available Actions - CASE SENSITIVE!\n\n';
          response += '**Action IDs are case-sensitive. Copy the exact ID from the table below:**\n\n';
          response += '| Action ID | Display Name | Type |\n';
          response += '|-----------|--------------|------|\n';
    
          actions.forEach((action) => {
            const actionID = action.ID || 'Unknown';
            const actionName = action.name || actionID;
            const actionType = action.type || 'Action';
            response += `| \`${actionID}\` | ${actionName} | ${actionType} |\n`;
          });
          response += '\n';
    
          // Show actionButtons if available (recommended actions from UI)
          if (data.uiResources?.actionButtons) {
            const actionButtons = data.uiResources.actionButtons;
            const mainButtons = actionButtons.main || [];
            const secondaryButtons = actionButtons.secondary || [];
    
            if (mainButtons.length > 0 || secondaryButtons.length > 0) {
              response += '**🎯 Recommended Actions (from UI):**\n\n';
    
              if (mainButtons.length > 0) {
                response += 'Primary Actions (submit buttons):\n';
                mainButtons.forEach(button => {
                  response += `- \`${button.actionID}\` - ${button.name}\n`;
                });
                response += '\n';
              }
    
              if (secondaryButtons.length > 0) {
                response += 'Secondary Actions (cancel, save, etc.):\n';
                secondaryButtons.forEach(button => {
                  response += `- \`${button.actionID}\` - ${button.name}\n`;
                });
                response += '\n';
              }
            }
          }
    
          // Display navigation steps for screen flows (if available)
          if (data.uiResources?.navigation?.steps) {
            response += '\n### Screen Flow Navigation\n\n';
            response += '**This is a multi-step screen flow. Current step progress:**\n\n';
            response += '| Step | Action ID | Status |\n';
            response += '|------|-----------|--------|\n';
    
            data.uiResources.navigation.steps.forEach(step => {
              const status = step.visited_status === 'success' ? '✅' :
                             step.visited_status === 'current' ? '🔄 CURRENT' : '⭕';
              response += `| ${step.name} | \`${step.actionID}\` | ${status} |\n`;
            });
            response += '\n**Use the Action ID of the CURRENT step for `perform_assignment_action`**\n\n';
          }
        }
    
        // Display assignment content if available
        if (data.data.content && Object.keys(data.data.content).length > 0) {
          response += '\n### Assignment Content\n';
          for (const [key, value] of Object.entries(data.data.content)) {
            response += `- **${key}**: ${value}\n`;
          }
        }
      }
    
      // Display UI resources info if viewType is specified
      if (data.uiResources) {
        // PRIORITY: Show current step fields first (fields actually editable in this step)
        const currentStepFields = extractFieldsForCurrentView(data.uiResources);
        if (currentStepFields.length > 0) {
          response += formatCurrentStepFields(currentStepFields);
        }
    
        // Show all case fields in a collapsed/secondary section
        const allFieldMetadata = extractFieldMetadata(data.uiResources);
        if (allFieldMetadata.length > 0 && allFieldMetadata.length !== currentStepFields.length) {
          response += `\n<details>\n<summary>📋 All Case Fields (${allFieldMetadata.length} total - click to expand)</summary>\n`;
          response += formatFieldMetadata(allFieldMetadata);
          response += `</details>\n`;
        }
      }
    
      // Display eTag if available for future operations
      if (data.etag) {
        response += '\n### Operation Support\n';
        response += `- eTag captured: ${data.etag}\n`;
        response += '- Ready for assignment action operations\n';
      }
    
      // Display locking information if applicable
      if (data.lockInfo || data.data.lockInfo) {
        const lockInfo = data.lockInfo || data.data.lockInfo;
        response += '\n### Case Locking Status\n';
        if (lockInfo.locked) {
          response += '- **Status**: Case is now locked (pessimistic locking)\n';
          response += `- **Locked By**: ${lockInfo.lockedBy || 'Current user'}\n`;
          response += '- **Note**: Case will remain locked until assignment is completed or explicitly unlocked\n';
        } else {
          response += '- **Status**: No locking applied\n';
        }
      }
    
      // Add workflow guidance
      // Get actions for example (check both locations)
      let exampleActions = data.actions;
      if (!exampleActions || exampleActions.length === 0) {
        const assignments = data.data?.caseInfo?.assignments;
        if (assignments && assignments.length > 0 && assignments[0].actions) {
          exampleActions = assignments[0].actions;
        }
      }
    
      response += '\n### Next Steps\n\n';
      response += '**To complete this assignment**:\n\n';
      response += '1. **Identify Required Fields**: Look for "required": true in the UI Resources view config above\n';
      response += '2. **Prepare Field Values**: Gather values for all required fields\n';
      response += '3. **Optional - Progressive Filling**: Use `refresh_assignment_action` to fill and validate fields progressively\n';
      response += '4. **Submit Assignment**: Use `perform_assignment_action` with:\n';
      response += '   - Assignment ID: The assignment ID from above\n';
      response += '   - **Action ID: Copy the EXACT action ID from "Available Actions" table** (case-sensitive!)\n\n';
    
      if (exampleActions && exampleActions.length > 0 && exampleActions[0].ID) {
        response += `**Example:**\n`;
        response += `\`\`\`javascript\n`;
        response += `perform_assignment_action({\n`;
        response += `  assignmentID: "${assignmentID}",\n`;
        response += `  actionID: "${exampleActions[0].ID}",  // ⚠️ Copy exactly from table above!\n`;
        response += `  content: { /* your field values */ }\n`;
        response += `})\n`;
        response += `\`\`\`\n\n`;
      }
    
      response += '**Helpful Tools**:\n';
      response += '- `refresh_assignment_action`: Update fields progressively with real-time validation\n';
      response += '- `perform_assignment_action`: Submit completed assignment\n';
      response += '- `get_assignment_action`: Get details about a specific action\n\n';
    
      return response;
    }
  • PegaClient.getAssignment() - Router that delegates to the version-specific API client (v1 or v2) to fetch assignment details.
    async getAssignment(assignmentID, options = {}) {
      return this.client.getAssignment(assignmentID, options);
    }
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden. It mentions 'Pessimistic locking may apply' and explains the eTag requirement, which are useful behavioral traits. However, it does not explicitly confirm that the operation is read-only.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is three sentences, front-loaded with the main purpose, and each sentence adds value without unnecessary detail. It is efficient and well-structured.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given 4 parameters, nested objects, and no output schema, the description adequately covers the return values ('form structure, action IDs, and eTag') and explains the viewType parameter. It could elaborate slightly on pageName but is generally complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description adds some context (e.g., assignmentID format example, explanation of 'required' field markers), but most parameter details are already in the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Get assignment details including form fields, required fields, available actions, and eTag.' It also specifies the usage context 'BETWEEN case creation and action performance,' which distinguishes it from sibling tools like get_assignment_action and perform_assignment_action.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description indicates the tool is used between case creation and action performance, providing context. However, it does not explicitly state when not to use it or name alternative tools such as get_assignment_action for action-specific details.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

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/marco-looy/pega-dx-mcp'

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