create_abap_program
Create a new ABAP program in an SAP system by providing a name, source code, and description. The program is automatically activated and can be stored in a specified package or local objects ($TMP). Optionally, target a specific system ID.
Instructions
Create a new ABAP program/report in the SAP system. Creates the program, writes source code, and activates it. By default creates in $TMP (local objects, no transport required).
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Program name (must start with Z or Y, e.g. ZHANZ_TEST) | |
| description | Yes | Short description of the program (max 70 chars) | |
| source | Yes | ABAP source code. Must start with REPORT statement. | |
| 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:650-736 (handler)The `createAbapProgram` method on the AdtClient class — the actual handler that creates an ABAP program via SAP ADT REST API. It: 1) creates the program shell via POST, 2) locks the object, 3) writes source code via PUT, 4) unlocks, 5) activates the program.
async createAbapProgram(name: string, description: string, source: string, pkg = "$TMP"): Promise<string> { await this.fetchStatefulCsrf(); const log: string[] = []; try { // 1. Create program shell const xml = `<?xml version="1.0" encoding="UTF-8"?> <program:abapProgram xmlns:program="http://www.sap.com/adt/programs/programs" xmlns:adtcore="http://www.sap.com/adt/core" adtcore:type="PROG/P" adtcore:description="${this.escapeXml(description)}" adtcore:language="EN" adtcore:name="${name.toUpperCase()}" adtcore:masterLanguage="EN" adtcore:responsible="${this.config.username.toUpperCase()}"> <adtcore:packageRef adtcore:name="${pkg}"/> </program:abapProgram>`; await this.http.post("/sap/bc/adt/programs/programs", xml, { headers: this.statefulHeaders({ "Content-Type": "application/vnd.sap.adt.programs.programs+xml; charset=utf-8", Accept: "application/vnd.sap.adt.programs.programs+xml", }), }); log.push(`Created program ${name.toUpperCase()} in package ${pkg}`); // 2. Lock const lockResp = await this.http.post( `/sap/bc/adt/programs/programs/${name.toLowerCase()}?_action=LOCK&accessMode=MODIFY`, "", { headers: this.statefulHeaders(), responseType: "text" } ); const lockMatch = (lockResp.data as string).match(/<LOCK_HANDLE>([^<]+)<\/LOCK_HANDLE>/); const lockHandle = lockMatch?.[1]; if (!lockHandle) throw new Error("Failed to obtain lock handle"); log.push("Locked for editing"); // 3. Write source await this.http.put( `/sap/bc/adt/programs/programs/${name.toLowerCase()}/source/main?lockHandle=${encodeURIComponent(lockHandle)}`, source, { headers: this.statefulHeaders({ "Content-Type": "text/plain; charset=utf-8" }), responseType: "text", } ); log.push("Source code written"); // 4. Unlock await this.http.post( `/sap/bc/adt/programs/programs/${name.toLowerCase()}?_action=UNLOCK&lockHandle=${encodeURIComponent(lockHandle)}`, "", { headers: this.statefulHeaders(), responseType: "text" } ); log.push("Unlocked"); // 5. Activate 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/programs/programs/${name.toLowerCase()}" adtcore:name="${name.toUpperCase()}"/> </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 if (actData.includes("<msg:shortText>")) { const msgMatch = actData.match(/<msg:shortText>([\s\S]*?)<\/msg:shortText>/); log.push(`Activation warning: ${msgMatch?.[1] ?? "check messages"}`); } else { log.push(`Activation response: ${actResp.status}`); } } finally { await this.endStatefulSession(); } return log.join("\n"); } - src/mcp-server.ts:1309-1313 (handler)The `create_abap_program` case in the CallToolRequestSchema handler. Parses input with CreateProgramSchema, then calls `client.createAbapProgram(progName, description, source, pkg ?? "$TMP")`.
case "create_abap_program": { const { name: progName, description, source, package: pkg } = CreateProgramSchema.parse(args); const log = await client.createAbapProgram(progName, description, source, pkg ?? "$TMP"); return { content: [{ type: "text", text: log }] }; } - src/mcp-server.ts:23-28 (schema)The `CreateProgramSchema` Zod schema defining the input validation for create_abap_program: name (string), description (string), source (string), and optional package (string).
const CreateProgramSchema = z.object({ name: z.string(), description: z.string(), source: z.string(), package: z.string().optional(), }); - src/mcp-server.ts:299-313 (registration)Tool registration entry in the ListToolsRequestSchema handler. Declares the tool name 'create_abap_program', its description, and input schema with properties: name, description, source, package, and system_id.
{ name: "create_abap_program", description: "Create a new ABAP program/report in the SAP system. Creates the program, 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: "Program name (must start with Z or Y, e.g. ZHANZ_TEST)" }, description: { type: "string", description: "Short description of the program (max 70 chars)" }, source: { type: "string", description: "ABAP source code. Must start with REPORT statement." }, package: { type: "string", description: "Development package (default: $TMP for local objects)" }, ...SYSTEM_ID_PROP, }, required: ["name", "description", "source"], }, },