handleValidateObject.ts•7.43 kB
/**
* ValidateObject Handler - Validate ABAP object name via ADT API
*
* Uses validateObjectName from @mcp-abap-adt/adt-clients/core for all operations.
* Connection management handled internally.
*/
import { AxiosResponse } from '../lib/utils';
import { return_error, return_response, logger, getManagedConnection } from '../lib/utils';
import { CrudClient } from '@mcp-abap-adt/adt-clients';
export const TOOL_DEFINITION = {
name: "ValidateObject",
description: "Validate an ABAP object name before creation. Checks if the name is valid and available. Returns validation result with success status and message. Can use session_id and session_state from GetSession to maintain the same session.",
inputSchema: {
type: "object",
properties: {
object_name: {
type: "string",
description: "Object name to validate (e.g., ZCL_MY_CLASS, Z_MY_PROGRAM, ZIF_MY_INTERFACE)"
},
object_type: {
type: "string",
description: "Object type: 'class', 'program', 'interface', 'function_group', 'table', 'structure', 'view', 'domain', 'data_element', 'package'",
enum: ["class", "program", "interface", "function_group", "table", "structure", "view", "domain", "data_element", "package"]
},
session_id: {
type: "string",
description: "Session ID from GetSession. If not provided, a new session will be created."
},
session_state: {
type: "object",
description: "Session state from GetSession (cookies, csrf_token, cookie_store). Required if session_id is provided.",
properties: {
cookies: { type: "string" },
csrf_token: { type: "string" },
cookie_store: { type: "object" }
}
}
},
required: ["object_name", "object_type"]
}
} as const;
interface ValidateObjectArgs {
object_name: string;
object_type: string;
session_id?: string;
session_state?: {
cookies?: string;
csrf_token?: string;
cookie_store?: Record<string, string>;
};
}
/**
* Main handler for ValidateObject MCP tool
*
* Uses validateObjectName from @mcp-abap-adt/adt-clients/core for all operations
* Connection management handled internally
*/
export async function handleValidateObject(args: any) {
try {
const {
object_name,
object_type,
session_id,
session_state
} = args as ValidateObjectArgs;
// Validation
if (!object_name || !object_type) {
return return_error(new Error('object_name and object_type are required'));
}
const validTypes = ['class', 'program', 'interface', 'function_group', 'table', 'structure', 'view', 'domain', 'data_element', 'package'];
if (!validTypes.includes(object_type.toLowerCase())) {
return return_error(new Error(`Invalid object_type. Must be one of: ${validTypes.join(', ')}`));
}
const connection = getManagedConnection();
const validationClient = new CrudClient(connection);
// Restore session state if provided
if (session_id && session_state) {
connection.setSessionState({
cookies: session_state.cookies || null,
csrfToken: session_state.csrf_token || null,
cookieStore: session_state.cookie_store || {}
});
} else {
// Ensure connection is established
await connection.connect();
}
const objectName = object_name.toUpperCase();
logger.info(`Starting object validation: ${objectName} (type: ${object_type})`);
try {
// Validate object using specific validation method based on type
let result: any;
switch (object_type.toLowerCase()) {
case 'program':
await validationClient.validateProgram(objectName);
result = validationClient.getValidationResult();
break;
case 'class':
await validationClient.validateClass(objectName);
result = validationClient.getValidationResult();
break;
case 'interface':
await validationClient.validateInterface(objectName);
result = validationClient.getValidationResult();
break;
case 'function_group':
await validationClient.validateFunctionGroup(objectName);
result = validationClient.getValidationResult();
break;
case 'table':
await validationClient.validateTable(objectName);
result = validationClient.getValidationResult();
break;
case 'structure':
await validationClient.validateStructure(objectName);
result = validationClient.getValidationResult();
break;
case 'view':
await validationClient.validateView(objectName);
result = validationClient.getValidationResult();
break;
case 'domain':
await validationClient.validateDomain(objectName);
result = validationClient.getValidationResult();
break;
case 'data_element':
await validationClient.validateDataElement(objectName);
result = validationClient.getValidationResult();
break;
case 'package':
await validationClient.validatePackage(objectName, ''); // package needs superPackage parameter
result = validationClient.getValidationResult();
break;
default:
throw new Error(`Unsupported object type: ${object_type}`);
}
// Get updated session state after validation
const updatedSessionState = connection.getSessionState();
logger.info(`✅ ValidateObject completed: ${objectName}`);
logger.info(` Valid: ${result.valid}, Message: ${result.message}`);
return return_response({
data: JSON.stringify({
success: result.valid,
object_name: objectName,
object_type,
validation_result: result,
session_id: session_id || null,
session_state: updatedSessionState ? {
cookies: updatedSessionState.cookies,
csrf_token: updatedSessionState.csrfToken,
cookie_store: updatedSessionState.cookieStore
} : null,
message: result.valid
? `Object name ${objectName} is valid and available`
: `Object name ${objectName} validation failed: ${result.message}`
}, null, 2)
} as AxiosResponse);
} catch (error: any) {
logger.error(`Error validating object ${objectName}:`, error);
// Parse error message
let errorMessage = `Failed to validate object: ${error.message || String(error)}`;
if (error.response?.status === 404) {
errorMessage = `Object ${objectName} not found.`;
} else if (error.response?.data && typeof error.response.data === 'string') {
try {
const { XMLParser } = require('fast-xml-parser');
const parser = new XMLParser({
ignoreAttributes: false,
attributeNamePrefix: '@_'
});
const errorData = parser.parse(error.response.data);
const errorMsg = errorData['exc:exception']?.message?.['#text'] || errorData['exc:exception']?.message;
if (errorMsg) {
errorMessage = `SAP Error: ${errorMsg}`;
}
} catch (parseError) {
// Ignore parse errors
}
}
return return_error(new Error(errorMessage));
}
} catch (error: any) {
return return_error(error);
}
}