Skip to main content
Glama

GetAbapAST

Parse ABAP source code to generate its Abstract Syntax Tree (AST) in JSON format for analysis or transformation.

Instructions

[read-only] Parse ABAP code and return AST (Abstract Syntax Tree) in JSON format.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
codeYesABAP source code to parse
filePathNoOptional file path to write the result to

Implementation Reference

  • Tool definition and input schema for 'GetAbapAST'. Defines the tool name, description, and inputSchema requiring 'code' (ABAP source string) with optional 'filePath'.
    export const TOOL_DEFINITION = {
      name: 'GetAbapAST',
      available_in: ['onprem', 'cloud'] as const,
      description:
        '[read-only] Parse ABAP code and return AST (Abstract Syntax Tree) in JSON format.',
      inputSchema: {
        type: 'object',
        properties: {
          code: {
            type: 'string',
            description: 'ABAP source code to parse',
          },
          filePath: {
            type: 'string',
            description: 'Optional file path to write the result to',
          },
        },
        required: ['code'],
      },
    } as const;
  • Main handler function 'handleGetAbapAST'. Validates input, instantiates SimpleAbapASTGenerator to parse ABAP code into an AST, optionally writes result to file, and returns content as JSON string.
    export async function handleGetAbapAST(context: HandlerContext, args: any) {
      const { connection, logger } = context;
      try {
        if (!args?.code) {
          throw new McpError(ErrorCode.InvalidParams, 'ABAP code is required');
        }
    
        const astGenerator = new SimpleAbapASTGenerator();
        const ast = astGenerator.parseToAST(args.code);
        logger?.debug('Generated AST for provided ABAP code');
    
        const result = {
          isError: false,
          content: [
            {
              type: 'text',
              text: JSON.stringify(ast, null, 2),
            },
          ],
        };
    
        if (args.filePath) {
          logger?.debug(`Writing AST result to file: ${args.filePath}`);
          writeResultToFile(JSON.stringify(ast, null, 2), args.filePath);
        }
    
        return result;
      } catch (error) {
        logger?.error('Failed to generate ABAP AST', error as any);
        return {
          isError: true,
          content: [
            {
              type: 'text',
              text: error instanceof Error ? error.message : String(error),
            },
          ],
        };
      }
    }
  • SimpleAbapASTGenerator class that parses ABAP source code (placeholder implementation) by analyzing structures, includes, classes, methods, data declarations, and forms using regex-based pattern matching.
    class SimpleAbapASTGenerator {
      public parseToAST(code: string): any {
        try {
          // This is a placeholder implementation until ANTLR is properly configured
          // It provides basic structure analysis
          const lines = code.split('\n');
          const ast = {
            type: 'abapSource',
            sourceLength: code.length,
            lineCount: lines.length,
            structures: this.analyzeStructures(code),
            includes: this.findIncludes(code),
            classes: this.findClasses(code),
            methods: this.findMethods(code),
            dataDeclarations: this.findDataDeclarations(code),
            forms: this.findForms(code),
          };
    
          return ast;
        } catch (error) {
          throw new Error(
            `Failed to parse ABAP code: ${error instanceof Error ? error.message : String(error)}`,
          );
        }
      }
    
      private analyzeStructures(code: string): any[] {
        const structures: any[] = [];
        const lines = code.split('\n');
    
        for (let i = 0; i < lines.length; i++) {
          const line = lines[i].trim().toLowerCase();
    
          if (line.startsWith('class ')) {
            structures.push({
              type: 'class',
              line: i + 1,
              content: lines[i].trim(),
            });
          } else if (line.startsWith('method ')) {
            structures.push({
              type: 'method',
              line: i + 1,
              content: lines[i].trim(),
            });
          } else if (line.startsWith('form ')) {
            structures.push({
              type: 'form',
              line: i + 1,
              content: lines[i].trim(),
            });
          } else if (line.startsWith('function ')) {
            structures.push({
              type: 'function',
              line: i + 1,
              content: lines[i].trim(),
            });
          }
        }
    
        return structures;
      }
    
      private findIncludes(code: string): string[] {
        const includeRegex = /include\s+([a-zA-Z0-9_/<>]+)/gi;
        const matches = code.match(includeRegex) || [];
        return matches.map((match) => match.replace(/include\s+/i, '').trim());
      }
    
      private findClasses(code: string): any[] {
        const classRegex =
          /class\s+([a-zA-Z0-9_]+)\s+(definition|implementation)/gi;
        const classes: Array<{ name: string; type: string; position: number }> = [];
        let match: RegExpExecArray | null = classRegex.exec(code);
    
        while (match !== null) {
          classes.push({
            name: match[1],
            type: match[2].toLowerCase(),
            position: match.index,
          });
          match = classRegex.exec(code);
        }
    
        return classes;
      }
    
      private findMethods(code: string): any[] {
        const methodRegex = /methods?\s+([a-zA-Z0-9_]+)/gi;
        const methods: any[] = [];
        let match: RegExpExecArray | null = methodRegex.exec(code);
    
        while (match !== null) {
          methods.push({
            name: match[1],
            position: match.index,
          });
          match = methodRegex.exec(code);
        }
    
        return methods;
      }
    
      private findDataDeclarations(code: string): any[] {
        const dataRegex = /data:?\s+([a-zA-Z0-9_]+)/gi;
        const declarations: Array<{ name: string; position: number }> = [];
        let match: RegExpExecArray | null = dataRegex.exec(code);
    
        while (match !== null) {
          declarations.push({
            name: match[1],
            position: match.index,
          });
          match = dataRegex.exec(code);
        }
    
        return declarations;
      }
    
      private findForms(code: string): any[] {
        const formRegex = /form\s+([a-zA-Z0-9_]+)/gi;
        const forms: any[] = [];
        let match: RegExpExecArray | null = formRegex.exec(code);
    
        while (match !== null) {
          forms.push({
            name: match[1],
            position: match.index,
          });
          match = formRegex.exec(code);
        }
    
        return forms;
      }
    }
  • Registration of 'GetAbapAST' in the SystemHandlersGroup. Maps the toolDefinition (GetAbapAST_Tool) to the handler function (handleGetAbapAST) within the handler group.
    {
      toolDefinition: GetAbapAST_Tool,
      handler: (args: any) => handleGetAbapAST(this.context, args),
    },
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries full burden. It only states read-only and output format, lacking details on errors, performance, or other behavioral traits beyond basic safety.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, front-loaded sentence that conveys all essential information without redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool returns complex AST JSON but the description only states the format, not the structure. Adequate for familiar users but incomplete for full understanding.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the description adds no additional meaning beyond the schema descriptions for 'code' and 'filePath'. Baseline of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool parses ABAP code and returns an AST in JSON format, with a read-only hint. It distinguishes from sibling 'Get...' tools by specifying the exact resource and output format.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

While the description indicates read-only parsing, it does not explicitly guide when to use this tool versus alternatives like GetAbapSemanticAnalysis. No exclusions or context are provided.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/fr0ster/mcp-abap-adt'

If you have feedback or need assistance with the MCP directory API, please join our Discord server