Skip to main content
Glama
handleUpdateClassSource.tsâ€ĸ5.3 kB
/** * UpdateClassSource Handler - Update Existing ABAP Class Source Code * * Uses ClassBuilder from @mcp-abap-adt/adt-clients for all operations. * Session and lock management handled internally by builder. * * Workflow: lock -> update -> check -> unlock -> (activate) */ import { AxiosResponse } from '../lib/utils'; import { return_error, return_response, encodeSapObjectName, logger, getManagedConnection } from '../lib/utils'; import { XMLParser } from 'fast-xml-parser'; import { CrudClient } from '@mcp-abap-adt/adt-clients'; export const TOOL_DEFINITION = { name: "UpdateClassSource", description: "Update source code of an existing ABAP class. Locks the class, uploads new source code, and unlocks. Optionally activates after update. Use this to modify existing classes without re-creating metadata.", inputSchema: { type: "object", properties: { class_name: { type: "string", description: "Class name (e.g., ZCL_TEST_CLASS_001). Class must already exist." }, source_code: { type: "string", description: "Complete ABAP class source code including CLASS DEFINITION and IMPLEMENTATION sections." }, activate: { type: "boolean", description: "Activate class after source update. Default: false. Set to true to activate immediately, or use ActivateObject for batch activation." } }, required: ["class_name", "source_code"] } } as const; interface UpdateClassSourceArgs { class_name: string; source_code: string; activate?: boolean; } /** * Main handler for UpdateClassSource * * Uses ClassBuilder from @mcp-abap-adt/adt-clients for all operations * Session and lock management handled internally by builder */ export async function handleUpdateClassSource(params: any) { const args: UpdateClassSourceArgs = params; // Validate required parameters if (!args.class_name || !args.source_code) { return return_error(new Error("Missing required parameters: class_name and source_code")); } const className = args.class_name.toUpperCase(); const connection = getManagedConnection(); logger.info(`Starting UpdateClassSource for ${className}`); try { // Create client const client = new CrudClient(connection); // Build operation chain: validate -> lock -> update -> check -> unlock -> (activate) const shouldActivate = args.activate === true; // Default to false if not specified // Validate await client.validateClass(className); // Lock await client.lockClass(className); const lockHandle = client.getLockHandle(); try { // Update source code await client.updateClass(className, args.source_code, lockHandle); // Check await client.checkClass(className); // Unlock await client.unlockClass(className, lockHandle); // Activate if requested if (shouldActivate) { await client.activateClass(className); } } catch (error) { // Try to unlock on error try { await client.unlockClass(className, lockHandle); } catch (unlockError) { logger.error('Failed to unlock class after error:', unlockError); } throw error; } // Parse activation warnings if activation was performed let activationWarnings: string[] = []; if (shouldActivate && client.getActivateResult()) { const activateResponse = client.getActivateResult()!; if (typeof activateResponse.data === 'string' && activateResponse.data.includes('<chkl:messages')) { const parser = new XMLParser({ ignoreAttributes: false, attributeNamePrefix: '@_' }); const result = parser.parse(activateResponse.data); const messages = result?.['chkl:messages']?.['msg']; if (messages) { const msgArray = Array.isArray(messages) ? messages : [messages]; activationWarnings = msgArray.map((msg: any) => `${msg['@_type']}: ${msg['shortText']?.['txt'] || 'Unknown'}` ); } } } // Return success result const stepsCompleted = ['lock', 'update', 'check', 'unlock']; if (shouldActivate) { stepsCompleted.push('activate'); } const result = { success: true, class_name: className, type: 'CLAS/OC', message: shouldActivate ? `Class ${className} source updated and activated successfully` : `Class ${className} source updated successfully (not activated)`, uri: `/sap/bc/adt/oo/classes/${encodeSapObjectName(className).toLowerCase()}`, steps_completed: stepsCompleted, activation_warnings: activationWarnings.length > 0 ? activationWarnings : undefined, source_size_bytes: args.source_code.length }; return return_response({ data: JSON.stringify(result, null, 2), status: 200, statusText: 'OK', headers: {}, config: {} as any }); } catch (error: any) { logger.error(`Error updating class ${className}:`, error); const errorMessage = error.response?.data ? (typeof error.response.data === 'string' ? error.response.data : JSON.stringify(error.response.data)) : error.message || String(error); return return_error(new Error(`Failed to update class ${className}: ${errorMessage}`)); } }

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/fr0ster/mcp-abap-adt'

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