ABAP-ADT-API MCP-Server

by mario-andreschak
Verified
import { McpError, ErrorCode } from "@modelcontextprotocol/sdk/types.js"; import { BaseHandler } from './BaseHandler.js'; import type { ToolDefinition } from '../types/tools.js'; import { ADTClient } from "abap-adt-api"; export class TransportHandlers extends BaseHandler { getTools(): ToolDefinition[] { return [ { name: 'transportInfo', description: 'Get transport information for an object source', inputSchema: { type: 'object', properties: { objSourceUrl: { type: 'string', description: 'URL of the object source' }, devClass: { type: 'string', description: 'Development class', optional: true }, operation: { type: 'string', description: 'Transport operation', optional: true } }, required: ['objSourceUrl'] } }, { name: 'createTransport', description: 'Create a new transport request', inputSchema: { type: 'object', properties: { objSourceUrl: { type: 'string', description: 'URL of the object source' }, REQUEST_TEXT: { type: 'string', description: 'Description of the transport request' }, DEVCLASS: { type: 'string', description: 'Development class' }, transportLayer: { type: 'string', description: 'Transport layer', optional: true } }, required: ['objSourceUrl', 'REQUEST_TEXT', 'DEVCLASS'] } }, { name: 'hasTransportConfig', description: 'Check if transport configuration exists', inputSchema: { type: 'object', properties: {} } }, { name: 'transportConfigurations', description: 'Retrieves transport configurations.', inputSchema: { type: 'object', properties: {} } }, { name: 'getTransportConfiguration', description: 'Retrieves a specific transport configuration.', inputSchema: { type: 'object', properties: { url: { type: 'string', description: 'The URL of the transport configuration.' } }, required: ['url'] } }, { name: 'setTransportsConfig', description: 'Sets transport configurations.', inputSchema: { type: 'object', properties: { uri: { type: 'string', description: 'The URI for the transport configuration.' }, etag: { type: 'string', description: 'The ETag for the transport configuration.' }, config: { type: 'string', description: 'The transport configuration.' } }, required: ['uri', 'etag', 'config'] } }, { name: 'createTransportsConfig', description: 'Creates transport configurations.', inputSchema: { type: 'object', properties: {} } }, { name: 'userTransports', description: 'Retrieves transports for a user.', inputSchema: { type: 'object', properties: { user: { type: 'string', description: 'The user.' }, targets: { type: 'boolean', description: 'Whether to include target systems.', optional: true } }, required: ['user'] } }, { name: 'transportsByConfig', description: 'Retrieves transports by configuration.', inputSchema: { type: 'object', properties: { configUri: { type: 'string', description: 'The configuration URI.' }, targets: { type: 'boolean', description: 'Whether to include target systems.', optional: true } }, required: ['configUri'] } }, { name: 'transportDelete', description: 'Deletes a transport.', inputSchema: { type: 'object', properties: { transportNumber: { type: 'string', description: 'The transport number.' } }, required: ['transportNumber'] } }, { name: 'transportRelease', description: 'Releases a transport.', inputSchema: { type: 'object', properties: { transportNumber: { type: 'string', description: 'The transport number.' }, ignoreLocks: { type: 'boolean', description: 'Whether to ignore locks.', optional: true }, IgnoreATC: { type: 'boolean', description: 'Whether to ignore ATC checks.', optional: true } }, required: ['transportNumber'] } }, { name: 'transportSetOwner', description: 'Sets the owner of a transport.', inputSchema: { type: 'object', properties: { transportNumber: { type: 'string', description: 'The transport number.' }, targetuser: { type: 'string', description: 'The target user.' } }, required: ['transportNumber', 'targetuser'] } }, { name: 'transportAddUser', description: 'Adds a user to a transport.', inputSchema: { type: 'object', properties: { transportNumber: { type: 'string', description: 'The transport number.' }, user: { type: 'string', description: 'The user to add.' } }, required: ['transportNumber', 'user'] } }, { name: 'systemUsers', description: 'Retrieves a list of system users.', inputSchema: { type: 'object', properties: {} } }, { name: 'transportReference', description: 'Retrieves a transport reference.', inputSchema: { type: 'object', properties: { pgmid: { type: 'string', description: 'The program ID.' }, obj_wbtype: { type: 'string', description: 'The object type.' }, obj_name: { type: 'string', description: 'The object name.' }, tr_number: { type: 'string', description: 'The transport number.', optional: true } }, required: ['pgmid', 'obj_wbtype', 'obj_name'] } } ]; } async handle(toolName: string, args: any): Promise<any> { switch (toolName) { case 'transportInfo': return this.handleTransportInfo(args); case 'createTransport': return this.handleCreateTransport(args); case 'hasTransportConfig': return this.handleHasTransportConfig(args); case 'transportConfigurations': return this.handleTransportConfigurations(args); case 'getTransportConfiguration': return this.handleGetTransportConfiguration(args); case 'setTransportsConfig': return this.handleSetTransportsConfig(args); case 'createTransportsConfig': return this.handleCreateTransportsConfig(args); case 'userTransports': return this.handleUserTransports(args); case 'transportsByConfig': return this.handleTransportsByConfig(args); case 'transportDelete': return this.handleTransportDelete(args); case 'transportRelease': return this.handleTransportRelease(args); case 'transportSetOwner': return this.handleTransportSetOwner(args); case 'transportAddUser': return this.handleTransportAddUser(args); case 'systemUsers': return this.handleSystemUsers(args); case 'transportReference': return this.handleTransportReference(args); default: throw new McpError(ErrorCode.MethodNotFound, `Unknown transport tool: ${toolName}`); } } async handleTransportInfo(args: any): Promise<any> { const startTime = performance.now(); try { const transportInfo = await this.adtclient.transportInfo( args.objSourceUrl, args.devClass, args.operation ); this.trackRequest(startTime, true); return { content: [ { type: 'text', text: JSON.stringify({ status: 'success', transportInfo }) } ] }; } catch (error: any) { this.trackRequest(startTime, false); throw new McpError( ErrorCode.InternalError, `Failed to get transport info: ${error.message || 'Unknown error'}` ); } } async handleCreateTransport(args: any): Promise<any> { const startTime = performance.now(); try { const transportResult = await this.adtclient.createTransport( args.objSourceUrl, args.REQUEST_TEXT, args.DEVCLASS, args.transportLayer ); this.trackRequest(startTime, true); return { content: [ { type: 'text', text: JSON.stringify({ status: 'success', transportNumber: transportResult, message: 'Transport created successfully' }) } ] }; } catch (error: any) { this.trackRequest(startTime, false); throw new McpError( ErrorCode.InternalError, `Failed to create transport: ${error.message || 'Unknown error'}` ); } } async handleHasTransportConfig(args: any): Promise<any> { const startTime = performance.now(); try { const hasConfig = await this.adtclient.hasTransportConfig(); this.trackRequest(startTime, true); return { content: [ { type: 'text', text: JSON.stringify({ status: 'success', hasConfig }) } ] }; } catch (error: any) { this.trackRequest(startTime, false); throw new McpError( ErrorCode.InternalError, `Failed to check transport config: ${error.message || 'Unknown error'}` ); } } async handleTransportConfigurations(args: any): Promise<any> { const startTime = performance.now(); try { const configurations = await this.adtclient.transportConfigurations(); this.trackRequest(startTime, true); return { content: [ { type: 'text', text: JSON.stringify({ status: 'success', configurations }) } ] }; } catch (error: any) { this.trackRequest(startTime, false); throw new McpError( ErrorCode.InternalError, `Failed to get transport configurations: ${error.message || 'Unknown error'}` ); } } async handleGetTransportConfiguration(args: any): Promise<any> { const startTime = performance.now(); try { const configuration = await this.adtclient.getTransportConfiguration(args.url); this.trackRequest(startTime, true); return { content: [ { type: 'text', text: JSON.stringify({ status: 'success', configuration }) } ] }; } catch (error: any) { this.trackRequest(startTime, false); throw new McpError( ErrorCode.InternalError, `Failed to get transport configuration: ${error.message || 'Unknown error'}` ); } } async handleSetTransportsConfig(args: any): Promise<any> { const startTime = performance.now(); try { const result = await this.adtclient.setTransportsConfig(args.uri, args.etag, args.config); this.trackRequest(startTime, true); return { content: [ { type: 'text', text: JSON.stringify({ status: 'success', result }) } ] }; } catch (error: any) { this.trackRequest(startTime, false); throw new McpError( ErrorCode.InternalError, `Failed to set transports config: ${error.message || 'Unknown error'}` ); } } async handleCreateTransportsConfig(args: any): Promise<any> { const startTime = performance.now(); try { const result = await this.adtclient.createTransportsConfig(); this.trackRequest(startTime, true); return { content: [ { type: 'text', text: JSON.stringify({ status: 'success', result }) } ] }; } catch (error: any) { this.trackRequest(startTime, false); throw new McpError( ErrorCode.InternalError, `Failed to create transports config: ${error.message || 'Unknown error'}` ); } } async handleUserTransports(args: any): Promise<any> { const startTime = performance.now(); try { const transports = await this.adtclient.userTransports(args.user, args.targets); this.trackRequest(startTime, true); return { content: [ { type: 'text', text: JSON.stringify({ status: 'success', transports }) } ] }; } catch (error: any) { this.trackRequest(startTime, false); throw new McpError( ErrorCode.InternalError, `Failed to get user transports: ${error.message || 'Unknown error'}` ); } } async handleTransportsByConfig(args: any): Promise<any> { const startTime = performance.now(); try { const transports = await this.adtclient.transportsByConfig(args.configUri, args.targets); this.trackRequest(startTime, true); return { content: [ { type: 'text', text: JSON.stringify({ status: 'success', transports }) } ] }; } catch (error: any) { this.trackRequest(startTime, false); throw new McpError( ErrorCode.InternalError, `Failed to get transports by config: ${error.message || 'Unknown error'}` ); } } async handleTransportDelete(args: any): Promise<any> { const startTime = performance.now(); try { const result = await this.adtclient.transportDelete(args.transportNumber); this.trackRequest(startTime, true); return { content: [ { type: 'text', text: JSON.stringify({ status: 'success', result }) } ] }; } catch (error: any) { this.trackRequest(startTime, false); throw new McpError( ErrorCode.InternalError, `Failed to delete transport: ${error.message || 'Unknown error'}` ); } } async handleTransportRelease(args: any): Promise<any> { const startTime = performance.now(); try { const result = await this.adtclient.transportRelease(args.transportNumber, args.ignoreLocks, args.IgnoreATC); this.trackRequest(startTime, true); return { content: [ { type: 'text', text: JSON.stringify({ status: 'success', result }) } ] }; } catch (error: any) { this.trackRequest(startTime, false); throw new McpError( ErrorCode.InternalError, `Failed to release transport: ${error.message || 'Unknown error'}` ); } } async handleTransportSetOwner(args: any): Promise<any> { const startTime = performance.now(); try { const result = await this.adtclient.transportSetOwner(args.transportNumber, args.targetuser); this.trackRequest(startTime, true); return { content: [ { type: 'text', text: JSON.stringify({ status: 'success', result }) } ] }; } catch (error: any) { this.trackRequest(startTime, false); throw new McpError( ErrorCode.InternalError, `Failed to set transport owner: ${error.message || 'Unknown error'}` ); } } async handleTransportAddUser(args: any): Promise<any> { const startTime = performance.now(); try { const result = await this.adtclient.transportAddUser(args.transportNumber, args.user); this.trackRequest(startTime, true); return { content: [ { type: 'text', text: JSON.stringify({ status: 'success', result }) } ] }; } catch (error: any) { this.trackRequest(startTime, false); throw new McpError( ErrorCode.InternalError, `Failed to add user to transport: ${error.message || 'Unknown error'}` ); } } async handleSystemUsers(args: any): Promise<any> { const startTime = performance.now(); try { const users = await this.adtclient.systemUsers(); this.trackRequest(startTime, true); return { content: [ { type: 'text', text: JSON.stringify({ status: 'success', users }) } ] }; } catch (error: any) { this.trackRequest(startTime, false); throw new McpError( ErrorCode.InternalError, `Failed to get system users: ${error.message || 'Unknown error'}` ); } } async handleTransportReference(args: any): Promise<any> { const startTime = performance.now(); try { const reference = await this.adtclient.transportReference(args.pgmid, args.obj_wbtype, args.obj_name, args.tr_number); this.trackRequest(startTime, true); return { content: [ { type: 'text', text: JSON.stringify({ status: 'success', reference }) } ] }; } catch (error: any) { this.trackRequest(startTime, false); throw new McpError( ErrorCode.InternalError, `Failed to get transport reference: ${error.message || 'Unknown error'}` ); } } }