create_abap_class
Creates a new ABAP class with source code in the SAP system, activates it, and defaults to local objects ($TMP) when no transport is needed.
Instructions
Create a new ABAP class in the SAP system. Creates the class, writes source code, and activates it. By default creates in $TMP (local objects, no transport required).
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Class name (must start with Z or Y, e.g. ZCL_MY_CLASS) | |
| description | Yes | Short description of the class (max 70 chars) | |
| source | Yes | ABAP class source code. Must include CLASS definition and IMPLEMENTATION. | |
| package | No | Development package (default: $TMP for local objects) | |
| system_id | No | SAP system ID (e.g. DEV). Omit to use default system. |
Implementation Reference
- src/adt-client.ts:837-937 (handler)The createAbapClass method in AdtClient executes the actual tool logic: creates the class shell via POST to /sap/bc/adt/oo/classes, locks it, writes source code, activates it, and unlocks it.
async createAbapClass(name: string, description: string, source: string, pkg = "$TMP"): Promise<string> { await this.fetchStatefulCsrf(); const log: string[] = []; const nameLower = name.toLowerCase(); const nameUpper = name.toUpperCase(); try { // 1. Create class shell const xml = `<?xml version="1.0" encoding="UTF-8"?> <class:abapClass xmlns:class="http://www.sap.com/adt/oo/classes" xmlns:adtcore="http://www.sap.com/adt/core" adtcore:type="CLAS/OC" adtcore:description="${this.escapeXml(description)}" adtcore:language="EN" adtcore:name="${nameUpper}" adtcore:masterLanguage="EN" adtcore:responsible="${this.config.username.toUpperCase()}"> <adtcore:packageRef adtcore:name="${pkg}"/> </class:abapClass>`; const createResp = await this.http.post("/sap/bc/adt/oo/classes", xml, { headers: this.statefulHeaders({ "Content-Type": "application/vnd.sap.adt.oo.classes.v2+xml; charset=utf-8", Accept: "application/vnd.sap.adt.oo.classes.v2+xml", }), validateStatus: () => true, }); if (createResp.status >= 400) { const errData = createResp.data as string; const msgMatch = errData.match(/<msg:shortText>([\s\S]*?)<\/msg:shortText>/); log.push(`Failed to create class ${nameUpper} (HTTP ${createResp.status}): ${msgMatch?.[1] ?? errData.substring(0, 500)}`); return log.join("\n"); } log.push(`Created class ${nameUpper} in package ${pkg}`); // 2. Lock const lockResp = await this.http.post( `/sap/bc/adt/oo/classes/${nameLower}?_action=LOCK&accessMode=MODIFY`, "", { headers: this.statefulHeaders(), responseType: "text", validateStatus: () => true } ); const lockData = lockResp.data as string; const lockMatch = lockData.match(/<LOCK_HANDLE>([^<]+)<\/LOCK_HANDLE>/); if (!lockMatch?.[1]) { log.push(`Failed to lock class (HTTP ${lockResp.status}): ${lockData.substring(0, 500)}`); return log.join("\n"); } const lockHandle = lockMatch[1]; log.push("Locked for editing"); // 3. Write source await this.http.put( `/sap/bc/adt/oo/classes/${nameLower}/source/main?lockHandle=${encodeURIComponent(lockHandle)}`, source, { headers: this.statefulHeaders({ "Content-Type": "text/plain; charset=utf-8" }), responseType: "text", } ); log.push("Source code written"); // 4. Activate (while still locked) const activateBody = `<?xml version="1.0" encoding="UTF-8"?> <adtcore:objectReferences xmlns:adtcore="http://www.sap.com/adt/core"> <adtcore:objectReference adtcore:uri="/sap/bc/adt/oo/classes/${nameLower}" adtcore:name="${nameUpper}"/> </adtcore:objectReferences>`; const actResp = await this.http.post( "/sap/bc/adt/activation?method=activate&preauditRequested=true", activateBody, { headers: this.statefulHeaders({ "Content-Type": "application/xml", Accept: "application/xml", }), responseType: "text", validateStatus: () => true, } ); const actData = actResp.data as string; if (actData.includes('activationExecuted="true"')) { log.push("Activated successfully"); } else { const msgMatch = actData.match(/<msg:shortText>([\s\S]*?)<\/msg:shortText>/); log.push(`Activation: ${msgMatch?.[1] ?? `HTTP ${actResp.status}`}`); } // 5. Unlock (after activation) await this.http.post( `/sap/bc/adt/oo/classes/${nameLower}?_action=UNLOCK&lockHandle=${encodeURIComponent(lockHandle)}`, "", { headers: this.statefulHeaders(), responseType: "text" } ); log.push("Unlocked"); } finally { await this.endStatefulSession(); } return log.join("\n"); } - src/mcp-server.ts:1315-1319 (handler)The CallToolRequestSchema handler dispatches 'create_abap_class' by parsing args with CreateClassSchema and calling client.createAbapClass().
case "create_abap_class": { const { name: className, description, source, package: pkg } = CreateClassSchema.parse(args); const log = await client.createAbapClass(className, description, source, pkg ?? "$TMP"); return { content: [{ type: "text", text: log }] }; } - src/mcp-server.ts:43-48 (schema)CreateClassSchema Zod schema defines the input validation for create_abap_class: name, description, source, and optional package.
const CreateClassSchema = z.object({ name: z.string(), description: z.string(), source: z.string(), package: z.string().optional(), }); - src/mcp-server.ts:314-328 (registration)Tool registration in ListToolsRequestSchema: defines name 'create_abap_class', description, and inputSchema with name, description, source, package, and system_id properties.
{ name: "create_abap_class", description: "Create a new ABAP class in the SAP system. Creates the class, writes source code, and activates it. By default creates in $TMP (local objects, no transport required).", inputSchema: { type: "object" as const, properties: { name: { type: "string", description: "Class name (must start with Z or Y, e.g. ZCL_MY_CLASS)" }, description: { type: "string", description: "Short description of the class (max 70 chars)" }, source: { type: "string", description: "ABAP class source code. Must include CLASS definition and IMPLEMENTATION." }, package: { type: "string", description: "Development package (default: $TMP for local objects)" }, ...SYSTEM_ID_PROP, }, required: ["name", "description", "source"], }, },