execute_sql
Execute ABAP SQL queries on SAP systems. Use standard syntax like SELECT ... UP TO n ROWS to retrieve table results directly.
Instructions
Execute an ABAP SQL query on the SAP system and return results as a table. Use standard ABAP SQL syntax (e.g. SELECT vbeln, erdat FROM vbak UP TO 10 ROWS).
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | ABAP SQL query | |
| system_id | No | SAP system ID (e.g. DEV). Omit to use default system. |
Implementation Reference
- src/mcp-server.ts:942-950 (registration)Tool registration in the ListToolsRequestSchema handler, defining the 'execute_sql' tool with a single required 'query' string parameter and an optional 'system_id'.
{ name: "execute_sql", description: "Execute an ABAP SQL query on the SAP system and return results as a table. Use standard ABAP SQL syntax (e.g. SELECT vbeln, erdat FROM vbak UP TO 10 ROWS).", inputSchema: { type: "object" as const, properties: { query: { type: "string", description: "ABAP SQL query" }, ...SYSTEM_ID_PROP }, required: ["query"], }, }, - src/mcp-server.ts:1520-1525 (handler)The CallToolRequestSchema handler for 'execute_sql'. Parses args via SqlSchema, calls client.executeFreestyleSql(), then parses the XML result into a formatted table using parseSqlResultXml().
case "execute_sql": { const { query } = SqlSchema.parse(args); const xml = await client.executeFreestyleSql(query); const table = parseSqlResultXml(xml); return { content: [{ type: "text", text: table }] }; } - src/mcp-server.ts:18-18 (schema)Zod schema (SqlSchema) defining the input validation for the execute_sql tool. Expects a single 'query' string.
const SqlSchema = z.object({ query: z.string() }); - src/adt-client.ts:83-90 (helper)AdtClient.executeFreestyleSql() - sends the SQL query to the SAP ADT endpoint /sap/bc/adt/datapreview/freestyle via POST with CSRF token handling.
async executeFreestyleSql(query: string): Promise<string> { const response = await this.postWithCsrf( "/sap/bc/adt/datapreview/freestyle", query, "application/vnd.sap.adt.datapreview.table.v1+xml" ); return response.data as string; } - src/sql-parser.ts:40-82 (helper)Helper function that parses the ADT data preview XML response into a formatted text table with column headers, separators, and rows.
export function parseSqlResultXml(xml: string): string { const columns = extractColumns(xml); if (columns.length === 0) return "No results returned."; const totalRows = extractTotalRows(xml); const queryTime = extractQueryTime(xml); const rowCount = columns[0].values.length; const maxWidth = 40; const colWidths = columns.map((col) => { const maxVal = col.values.reduce( (max, v) => Math.max(max, v.length), col.name.length ); return Math.min(maxVal, maxWidth); }); const padRight = (s: string, w: number) => s.length > w ? s.substring(0, w - 1) + "~" : s.padEnd(w); const header = columns .map((col, i) => padRight(col.name, colWidths[i])) .join(" | "); const separator = colWidths.map((w) => "-".repeat(w)).join("-+-"); const rows: string[] = []; for (let r = 0; r < rowCount; r++) { const row = columns .map((col, i) => padRight(col.values[r] ?? "", colWidths[i])) .join(" | "); rows.push(row); } const lines = [ `${rowCount} row(s) returned (${totalRows} total, ${queryTime}s)`, "", header, separator, ...rows, ]; return lines.join("\n"); }