create_interface
Create ABAP interfaces in SAP systems by specifying name, description, and source code. Optionally select a package; defaults to local objects ($TMP) with automatic activation.
Instructions
Create a new ABAP interface in the SAP system. Creates the interface, writes source code, and activates it. By default creates in $TMP (local objects, no transport required).
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Interface name (must start with Z or Y, e.g. ZIF_MY_INTERFACE) | |
| description | Yes | Short description of the interface (max 70 chars) | |
| source | Yes | ABAP interface source code. Must include INTERFACE definition. | |
| 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/mcp-server.ts:53-58 (schema)Zod schema for the create_interface tool's input parameters (name, description, source, optional package).
const CreateInterfaceSchema = z.object({ name: z.string(), description: z.string(), source: z.string(), package: z.string().optional(), }); - src/mcp-server.ts:342-356 (registration)Registration of the create_interface tool in the MCP tools list with its name, description, and input schema.
{ name: "create_interface", description: "Create a new ABAP interface in the SAP system. Creates the interface, 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: "Interface name (must start with Z or Y, e.g. ZIF_MY_INTERFACE)" }, description: { type: "string", description: "Short description of the interface (max 70 chars)" }, source: { type: "string", description: "ABAP interface source code. Must include INTERFACE definition." }, package: { type: "string", description: "Development package (default: $TMP for local objects)" }, ...SYSTEM_ID_PROP, }, required: ["name", "description", "source"], }, }, - src/mcp-server.ts:1327-1331 (handler)Handler that parses parameters via CreateInterfaceSchema and delegates to AdtClient.createInterface().
case "create_interface": { const { name: intfName, description, source, package: pkg } = CreateInterfaceSchema.parse(args); const log = await client.createInterface(intfName, description, source, pkg ?? "$TMP"); return { content: [{ type: "text", text: log }] }; } - src/adt-client.ts:1038-1138 (helper)The actual implementation of createInterface on AdtClient: posts XML to /sap/bc/adt/oo/interfaces to create the shell, locks, writes source to /sap/bc/adt/oo/interfaces/{name}/source/main, activates, then unlocks.
async createInterface(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 interface shell const xml = `<?xml version="1.0" encoding="UTF-8"?> <intf:abapInterface xmlns:intf="http://www.sap.com/adt/oo/interfaces" xmlns:adtcore="http://www.sap.com/adt/core" adtcore:type="INTF/OI" 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}"/> </intf:abapInterface>`; const createResp = await this.http.post("/sap/bc/adt/oo/interfaces", xml, { headers: this.statefulHeaders({ "Content-Type": "application/vnd.sap.adt.oo.interfaces.v2+xml; charset=utf-8", Accept: "application/vnd.sap.adt.oo.interfaces.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 interface ${nameUpper} (HTTP ${createResp.status}): ${msgMatch?.[1] ?? errData.substring(0, 500)}`); return log.join("\n"); } log.push(`Created interface ${nameUpper} in package ${pkg}`); // 2. Lock const lockResp = await this.http.post( `/sap/bc/adt/oo/interfaces/${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 interface (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/interfaces/${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/interfaces/${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/interfaces/${nameLower}?_action=UNLOCK&lockHandle=${encodeURIComponent(lockHandle)}`, "", { headers: this.statefulHeaders(), responseType: "text" } ); log.push("Unlocked"); } finally { await this.endStatefulSession(); } return log.join("\n"); }