Skip to main content
Glama
marco-looy
by marco-looy

add_case_attachments

Attach files or URLs to Pega cases at any lifecycle stage using uploaded file IDs or direct links, with atomic operation ensuring all attachments succeed or none are added.

Instructions

Attach files and/or URLs to a Pega case regardless of the context or stage of the case lifecycle. Can attach temporary uploaded files using their IDs (from upload_attachment tool), or add URL/link attachments directly. Supports multiple attachments in a single atomic operation - if any attachment fails, no attachments are added to the case.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
caseIDYesCase ID. Example: "MYORG-APP-WORK C-1001". Complete identifier including spaces."OSIEO3-DOCSAPP-WORK T-561003". a complete case identifier including spaces and special characters.
attachmentsYesArray of attachment objects to add to the case. Can contain file attachments (using temporary attachment IDs from upload_attachment tool) and/or URL attachments. All attachments must be successfully processed or none will be attached (atomic operation).
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

  • Main handler function that orchestrates the tool execution: parameter validation, session initialization, API call to pegaClient.addCaseAttachments, and error handling with custom formatted responses.
    async execute(params) { const { caseID, attachments } = params; let sessionInfo = null; try { sessionInfo = this.initializeSessionConfig(params); // Basic parameter validation using base class const requiredValidation = this.validateRequiredParams(params, ['caseID', 'attachments']); if (requiredValidation) { return this.createErrorResponse(`Add Attachments to Case: ${caseID || 'UNKNOWN'}`, { message: requiredValidation.error }, { caseID, attachments }); } // Additional comprehensive parameter validation for complex logic const validationResult = this.validateParameters(caseID, attachments); if (!validationResult.valid) { return this.createErrorResponse(`Add Attachments to Case: ${caseID}`, { message: validationResult.error }, { caseID, attachments }); } // Execute with standardized error handling return await this.executeWithErrorHandling( `Add Attachments to Case: ${caseID}`, async () => await this.pegaClient.addCaseAttachments(caseID, attachments), { caseID, attachments, sessionInfo } ); } catch (error) { return { content: [{ type: 'text', text: `## Error: Add Attachments to Case\n\n**Unexpected Error**: ${error.message}\n\n${sessionInfo ? `**Session**: ${sessionInfo.sessionId} (${sessionInfo.authMode} mode)\n` : ''}*Error occurred at: ${new Date().toISOString()}*` }] }; } }
  • Static method providing the tool's MCP definition: name, description, and detailed input schema specifying caseID and attachments (array of File or URL objects).
    static getDefinition() { return { name: 'add_case_attachments', description: 'Attach files and/or URLs to a Pega case regardless of the context or stage of the case lifecycle. Can attach temporary uploaded files using their IDs (from upload_attachment tool), or add URL/link attachments directly. Supports multiple attachments in a single atomic operation - if any attachment fails, no attachments are added to the case.', inputSchema: { type: 'object', properties: { caseID: { type: 'string', description: 'Case ID. Example: "MYORG-APP-WORK C-1001". Complete identifier including spaces."OSIEO3-DOCSAPP-WORK T-561003". a complete case identifier including spaces and special characters.' }, attachments: { type: 'array', description: 'Array of attachment objects to add to the case. Can contain file attachments (using temporary attachment IDs from upload_attachment tool) and/or URL attachments. All attachments must be successfully processed or none will be attached (atomic operation).', items: { type: 'object', properties: { type: { type: 'string', enum: ['File', 'URL'], description: 'Attachment type. "File" for file attachments or "URL" for URL/link attachments.' }, category: { type: 'string', enum: ['File', 'URL'], description: 'Attachment category. Must match the type ("File" or "URL").' }, ID: { type: 'string', description: 'Temporary attachment ID returned from upload_attachment tool (required for File type). Example: "450b7275-8868-43ca-9827-bcfd9ec1b54b". Note: Temporary attachments expire after 2 hours if not linked to a case.' }, url: { type: 'string', description: 'URL/link to attach to the case (required for URL type). Example: "https://www.google.com". a valid URL format.' }, name: { type: 'string', description: 'Display name for the URL attachment (required for URL type). Example: "google". This will be shown as the attachment name in the case.' } }, required: ['type', 'category'] }, minItems: 1, maxItems: 50 }, sessionCredentials: getSessionCredentialsSchema() }, required: ['caseID', 'attachments'] } }; }
  • Comprehensive validation helper for caseID and attachments: checks format, array length (1-50), and delegates to validateAttachmentObject for each item.
    validateParameters(caseID, attachments) { // Validate caseID if (!caseID || typeof caseID !== 'string' || caseID.trim() === '') { return { valid: false, error: 'Invalid caseID parameter. Case ID must be a non-empty string containing the full case handle.' }; } // Validate attachments array if (!attachments || !Array.isArray(attachments)) { return { valid: false, error: 'Invalid attachments parameter. Attachments must be a non-empty array of attachment objects.' }; } if (attachments.length === 0) { return { valid: false, error: 'Attachments array cannot be empty. Please provide at least one attachment to add to the case.' }; } if (attachments.length > 50) { return { valid: false, error: 'Too many attachments provided. Maximum of 50 attachments can be added in a single operation.' }; } // Validate each attachment object for (let i = 0; i < attachments.length; i++) { const attachment = attachments[i]; const attachmentValidation = this.validateAttachmentObject(attachment, i); if (!attachmentValidation.valid) { return attachmentValidation; } } return { valid: true }; }
  • Validates individual attachment objects: ensures type/category match ('File'/'URL'), required fields (ID for File, url/name for URL), URL format, no extra properties.
    validateAttachmentObject(attachment, index) { if (!attachment || typeof attachment !== 'object') { return { valid: false, error: `Invalid attachment at index ${index}. Each attachment must be an object with required properties.` }; } const { type, category } = attachment; // Validate required type field if (!type || typeof type !== 'string') { return { valid: false, error: `Missing or invalid 'type' field in attachment at index ${index}. Type must be either "File" or "URL".` }; } // Validate required category field if (!category || typeof category !== 'string') { return { valid: false, error: `Missing or invalid 'category' field in attachment at index ${index}. Category must match the type ("File" or "URL").` }; } // Validate File attachment if (type === 'File') { if (category !== 'File') { return { valid: false, error: `Invalid category for File attachment at index ${index}. Category must be "File" when type is "File".` }; } const { ID } = attachment; if (!ID || typeof ID !== 'string' || ID.trim() === '') { return { valid: false, error: `Missing or invalid 'ID' field in File attachment at index ${index}. ID must be a non-empty string containing the temporary attachment ID from upload_attachment tool.` }; } // Check for unexpected properties const allowedProps = ['type', 'category', 'ID']; const extraProps = Object.keys(attachment).filter(prop => !allowedProps.includes(prop)); if (extraProps.length > 0) { return { valid: false, error: `Unexpected properties in File attachment at index ${index}: ${extraProps.join(', ')}. File attachments only support: type, category, ID.` }; } } // Validate URL attachment else if (type === 'URL') { if (category !== 'URL') { return { valid: false, error: `Invalid category for URL attachment at index ${index}. Category must be "URL" when type is "URL".` }; } const { url, name } = attachment; if (!url || typeof url !== 'string' || url.trim() === '') { return { valid: false, error: `Missing or invalid 'url' field in URL attachment at index ${index}. URL must be a non-empty string containing a valid URL.` }; } // Basic URL format validation try { new URL(url.trim()); } catch (urlError) { return { valid: false, error: `Invalid URL format in URL attachment at index ${index}: "${url}". Please provide a valid URL (Example: "https://www.example.com").` }; } if (!name || typeof name !== 'string' || name.trim() === '') { return { valid: false, error: `Missing or invalid 'name' field in URL attachment at index ${index}. Name must be a non-empty string for the display name of the URL attachment.` }; } // Check for unexpected properties const allowedProps = ['type', 'category', 'url', 'name']; const extraProps = Object.keys(attachment).filter(prop => !allowedProps.includes(prop)); if (extraProps.length > 0) { return { valid: false, error: `Unexpected properties in URL attachment at index ${index}: ${extraProps.join(', ')}. URL attachments only support: type, category, url, name.` }; } } // Invalid type else { return { valid: false, error: `Invalid attachment type "${type}" at index ${index}. Type must be either "File" or "URL".` }; } return { valid: true }; }
  • PegaClient wrapper method called by the tool handler to perform the actual API call to add attachments to a case.
    async addCaseAttachments(caseID, attachments) { return this.client.addCaseAttachments(caseID, attachments);

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