Skip to main content
Glama
handleCreateFunctionModule.ts6.39 kB
/** * CreateFunctionModule Handler - ABAP Function Module Creation via ADT API * * Uses FunctionModuleBuilder from @mcp-abap-adt/adt-clients for all operations. * Session and lock management handled internally by builder. * * Workflow: validate -> create -> lock -> update -> check -> unlock -> (activate) */ import { 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: "CreateFunctionModule", description: "Create a new ABAP function module within an existing function group. Uses stateful session with LOCK/UNLOCK workflow for source code upload.", inputSchema: { type: "object", properties: { function_group_name: { type: "string", description: "Parent function group name (e.g., ZTEST_FG_001)" }, function_module_name: { type: "string", description: "Function module name (e.g., Z_TEST_FUNCTION_001). Must follow SAP naming conventions (start with Z or Y, max 30 chars)." }, source_code: { type: "string", description: "ABAP source code for the function module including signature (FUNCTION name IMPORTING/EXPORTING ... ENDFUNCTION)." }, description: { type: "string", description: "Optional description for the function module" }, transport_request: { type: "string", description: "Transport request number (e.g., E19K905635). Required for transportable packages." }, activate: { type: "boolean", description: "Whether to activate the function module after creation (default: true)", default: true } }, required: ["function_group_name", "function_module_name", "source_code"] } }; interface CreateFunctionModuleArgs { function_group_name: string; function_module_name: string; source_code: string; // Required: no default generation description?: string; transport_request?: string; activate?: boolean; } /** * Main handler for CreateFunctionModule MCP tool * * Uses FunctionModuleBuilder from @mcp-abap-adt/adt-clients for all operations * Session and lock management handled internally by builder */ export async function handleCreateFunctionModule(args: any) { try { // Validate required parameters if (!args?.function_group_name) { return return_error(new Error('function_group_name is required')); } if (!args?.function_module_name) { return return_error(new Error('function_module_name is required')); } if (!args?.source_code) { return return_error(new Error('source_code is required')); } // Validate transport_request: required for non-$TMP packages try { validateTransportRequest(args.package_name, args.transport_request); } catch (error) { return return_error(error as Error); } const typedArgs = args as CreateFunctionModuleArgs; const connection = getManagedConnection(); const functionGroupName = typedArgs.function_group_name.toUpperCase(); const functionModuleName = typedArgs.function_module_name.toUpperCase(); logger.info(`Starting function module creation: ${functionModuleName} in ${functionGroupName}`); try { // Create client const client = new CrudClient(connection); const shouldActivate = typedArgs.activate !== false; // Default to true if not specified // Validate await client.validateFunctionModule(functionModuleName, functionGroupName); // Create // Note: Package name inherited from parent function group await client.createFunctionModule( functionModuleName, functionGroupName, typedArgs.description || functionModuleName, '', // packageName inherited from function group typedArgs.transport_request ); // Lock await client.lockFunctionModule(functionModuleName, functionGroupName); const lockHandle = client.getLockHandle(); // Update with source code await client.updateFunctionModule(functionModuleName, functionGroupName, typedArgs.source_code, lockHandle); // Check await client.checkFunctionModule(functionModuleName, functionGroupName); // Unlock await client.unlockFunctionModule(functionModuleName, functionGroupName, lockHandle); // Activate if requested if (shouldActivate) { await client.activateFunctionModule(functionModuleName, functionGroupName); } logger.info(`✅ CreateFunctionModule completed successfully: ${functionModuleName}`); return return_response({ data: JSON.stringify({ success: true, function_module_name: functionModuleName, function_group_name: functionGroupName, transport_request: typedArgs.transport_request || 'local', activated: shouldActivate, message: `Function module ${functionModuleName} created successfully${shouldActivate ? ' and activated' : ''}` }) } as AxiosResponse); } catch (error: any) { logger.error(`Error creating function module ${functionModuleName}:`, error); // Check if function module already exists if (error.message?.includes('already exists') || error.response?.status === 409) { return return_error(new Error(`Function module ${functionModuleName} already exists in group ${functionGroupName}. Please delete it first or use a different name.`)); } if (error.response?.status === 404) { return return_error(new Error(`Function group ${functionGroupName} not found. Create the function group first.`)); } if (error.response?.status === 400) { return return_error(new Error(`Bad request. Check if function module name is valid and function group exists.`)); } 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 create function module ${functionModuleName}: ${errorMessage}`)); } } catch (error: any) { 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