Skip to main content
Glama
handleUpdateDomain.tsâ€ĸ7.63 kB
/** * UpdateDomain Handler - Update Existing ABAP Domain * * Uses DomainBuilder from @mcp-abap-adt/adt-clients for all operations. * Session and lock management handled internally by builder. * * Workflow: lock -> update -> check -> unlock -> (activate) */ import { McpError, ErrorCode, AxiosResponse } from '../lib/utils'; import { return_error, return_response, logger, getManagedConnection } from '../lib/utils'; import { validateTransportRequest } from '../utils/transportValidation.js'; import { CrudClient } from '@mcp-abap-adt/adt-clients'; export const TOOL_DEFINITION = { name: "UpdateDomain", description: `Update an existing ABAP domain in SAP system. Workflow: 1. Acquires lock on the domain 2. Updates domain with provided parameters (complete replacement) 3. Performs syntax check 4. Unlocks domain 5. Optionally activates domain (default: true) 6. Returns updated domain details Note: All provided parameters completely replace existing values. Use GetDomain first to see current values if needed.`, inputSchema: { type: "object", properties: { domain_name: { type: "string", description: "Domain name to update (e.g., ZZ_TEST_0001)" }, description: { type: "string", description: "New domain description (optional)" }, package_name: { type: "string", description: "Package name (e.g., ZOK_LOCAL, $TMP for local objects)" }, transport_request: { type: "string", description: "Transport request number (e.g., E19K905635). Required for transportable packages." }, datatype: { type: "string", description: "Data type: CHAR, NUMC, DATS, TIMS, DEC, INT1, INT2, INT4, INT8, CURR, QUAN, etc." }, length: { type: "number", description: "Field length (max depends on datatype)" }, decimals: { type: "number", description: "Decimal places (for DEC, CURR, QUAN types)" }, conversion_exit: { type: "string", description: "Conversion exit routine name (without CONVERSION_EXIT_ prefix)" }, lowercase: { type: "boolean", description: "Allow lowercase input" }, sign_exists: { type: "boolean", description: "Field has sign (+/-)" }, value_table: { type: "string", description: "Value table name for foreign key relationship" }, activate: { type: "boolean", description: "Activate domain after update (default: true)", default: true }, fixed_values: { type: "array", description: "Array of fixed values for domain value range", items: { type: "object", properties: { low: { type: "string", description: "Fixed value (e.g., '001', 'A')" }, text: { type: "string", description: "Description text for the fixed value" } }, required: ["low", "text"] } } }, required: ["domain_name", "package_name"] } } as const; interface DomainArgs { domain_name: string; description?: string; package_name: string; transport_request?: string; datatype?: string; length?: number; decimals?: number; conversion_exit?: string; lowercase?: boolean; sign_exists?: boolean; value_table?: string; activate?: boolean; fixed_values?: Array<{ low: string; text: string }>; } /** * Main handler for UpdateDomain tool * * Uses DomainBuilder from @mcp-abap-adt/adt-clients for all operations * Session and lock management handled internally by builder */ export async function handleUpdateDomain(args: any) { try { if (!args?.domain_name) { throw new McpError(ErrorCode.InvalidParams, 'Domain name is required'); } if (!args?.package_name) { throw new McpError(ErrorCode.InvalidParams, 'Package name is required'); } // Validate transport_request: required for non-$TMP packages validateTransportRequest(args.package_name, args.transport_request); const typedArgs = args as DomainArgs; const connection = getManagedConnection(); const domainName = typedArgs.domain_name.toUpperCase(); logger.info(`Starting domain update: ${domainName}`); try { // Create client const client = new CrudClient(connection); const shouldActivate = typedArgs.activate !== false; // Default to true if not specified // Validate await client.validateDomain(domainName); // Lock await client.lockDomain(domainName); const lockHandle = client.getLockHandle(); try { // Update with properties const properties = { datatype: typedArgs.datatype, length: typedArgs.length, decimals: typedArgs.decimals, conversion_exit: typedArgs.conversion_exit, lowercase: typedArgs.lowercase, sign_exists: typedArgs.sign_exists, value_table: typedArgs.value_table, fixed_values: typedArgs.fixed_values }; await client.updateDomain(domainName, properties, lockHandle); // Check await client.checkDomain(domainName); // Unlock await client.unlockDomain(domainName, lockHandle); // Activate if requested if (shouldActivate) { await client.activateDomain(domainName); } } catch (error) { // Try to unlock on error try { await client.unlockDomain(domainName, lockHandle); } catch (unlockError) { logger.error('Failed to unlock domain after error:', unlockError); } throw error; } // Get domain details from update result const updateResult = client.getUpdateResult(); let domainDetails = null; if (updateResult?.data && typeof updateResult.data === 'object' && 'domain_details' in updateResult.data) { domainDetails = (updateResult.data as any).domain_details; } return return_response({ data: JSON.stringify({ success: true, domain_name: domainName, package: typedArgs.package_name, transport_request: typedArgs.transport_request, status: shouldActivate ? 'active' : 'inactive', message: `Domain ${domainName} updated${shouldActivate ? ' and activated' : ''} successfully`, domain_details: domainDetails }) } as AxiosResponse); } catch (error: any) { logger.error(`Error updating domain ${domainName}:`, error); // Handle specific error cases if (error.message?.includes('not found') || error.response?.status === 404) { throw new McpError( ErrorCode.InvalidParams, `Domain ${domainName} not found.` ); } if (error.message?.includes('locked') || error.response?.status === 403) { throw new McpError( ErrorCode.InternalError, `Domain ${domainName} is locked by another user or session. Please try again later.` ); } const errorMessage = error.response?.data ? (typeof error.response.data === 'string' ? error.response.data : JSON.stringify(error.response.data)) : error.message || String(error); throw new McpError( ErrorCode.InternalError, `Failed to update domain ${domainName}: ${errorMessage}` ); } } catch (error: any) { if (error instanceof McpError) { throw error; } return return_error(error); } }

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