@mcp-abap-adt/adt客户

SAP ABAP开发工具(ADT)的TypeScript客户端。
特性
- ✅ 客户端API –简化了常见操作的界面:
- AdtClient –具有自动操作链的高级CRUD API - AdtClientBatch –批处理模式:在单个HTTP往返中执行多个读取操作 - AdtExecutor –通过执行API IExecutor 合同(类/程序,带分析) - AdtRuntimeClient –稳定的运行时操作(ABAP调试器、跟踪、日志、转储) - AdtRuntimeClientBatch –运行时操作的批处理模式 - AdtRuntimeClientExperimental –运行时API正在进行中(例如AMDP调试器) - AdtClientsWS –用于事件驱动工作流的实时WebSocket外观 - AdtAbapGitClient –SAP官方ADT集成abapGit的独立客户端(/sap/bc/adt/abapgit/*);可在云端和现代本地使用(ABAP平台2022+)
- ✅ ABAP单元测试支持 –运行和管理ABAP单元测试(类和CDS视图测试)
- ✅ 状态会话管理 –维护
sap-adt-connection-id跨运营 - ✅ 锁定注册表 –坚持不懈
.locks/active-locks.json使用CLI工具进行恢复 - ✅ TypeScript优先 –具有全面接口的全类型安全
- ✅ 响应标头已标准化 –ADT响应标头可以是非字符串;在解析贡献者的代码之前进行规范化
- ✅ 公共API是客户端+支持类型 –内部构建器和低级实用程序不会从包根导出
责任和设计原则
核心开发原则
仅接口通信该方案遵循一个基本的发展原则: 所有与外部依赖关系的交互都只能通过接口进行代码知道 没有超出接口中定义的内容.
这意味着:
- 不知道其他包中的具体实现类
- 不了解接口中未定义的内部数据结构或方法
- 不假设接口契约之外的实现行为
- 不访问接口中未明确定义的属性或方法
这一原则确保:
- 松散结合:客户端与其他包中的具体实现解耦
- 灵活性:可以添加新的实现,而无需修改客户端
- 可测试性:易于模拟测试依赖关系
- 可维护性:对实现的更改不会影响客户端
包装责任
该包负责:
- ADT运营:提供用于与SAP ABAP开发工具(ADT)交互的高级和低级客户端API
- 对象管理:ABAP对象(类、接口、程序等)的CRUD操作
- 会话管理:使用跨操作维护会话状态
sap-adt-connection-id - 锁管理:使用持久注册表处理对象锁定
这个包有什么作用
- 提供ADT客户端:
AdtClient以及ADT运营的专业客户 - 管理锁:使用持久存储和CLI工具锁定注册表
- 处理请求:通过连接接口向SAP ADT端点发出HTTP请求
- 管理状态:跨链式操作维护对象状态
此软件包不做什么
- 不处理身份验证:身份验证由以下人员处理
@mcp-abap-adt/connection - 不管理连接:连接管理由以下人员处理
@mcp-abap-adt/connection - 不验证标头:标头验证由处理
@mcp-abap-adt/header-validator - 不存储令牌:令牌存储由以下人员处理
@mcp-abap-adt/auth-stores - 不编排身份验证:令牌生命周期由以下人员处理
@mcp-abap-adt/auth-broker
外部依赖
此包与外部包交互 仅通过接口:
@mcp-abap-adt/connection:用途AbapConnectionHTTP请求接口-不知道具体的连接实现- 不直接依赖于其他包:所有交互都是通过定义良好的接口进行的
安装
作为npm包
# Install globally for CLI tools
npm install -g @mcp-abap-adt/adt-clients
# Or install in project
npm install @mcp-abap-adt/adt-clients建筑
公共API
- AdtClient (高级,推荐)
- 通过自动操作链简化CRUD操作 - 工厂模式: client.getClass(), client.getProgram()等等。 - 自动错误处理和资源清理 - 实用功能通过 client.getUtils() - 例子: await client.getClass().create({...}, { activateOnCreate: true })
- AdtRuntime客户端
- ABAP调试、跟踪、转储、日志、提要等的稳定运行时操作 - 工厂访客: getProfiler(), getCrossTrace(), getSt05Trace(), getDebugger(), getApplicationLog(), getAtcLog(), getDdicActivation(), getDumps(), getFeeds(), getSystemMessages(), getGatewayErrorLog() - 例子: await runtimeClient.getDebugger().getAbap().launch()
- 行政执行人
- 基于的类型化执行API IExecutor - 执行人: - getClassExecutor() 为了 classrun - getProgramExecutor() 为了 programrun (内部部署系统) - 方法: run, runWithProfiler, runWithProfiling
- AdtRuntimeClient实验版
- 正在进行的运行时API可能会在没有向后兼容性保证的情况下发生变化 - 当前作用域:AMDP数据预览(AMDP调试器现在是 AdtRuntimeClient.getDebugger().getAmdp()) - 例子: await experimentalRuntime.startAmdpDataPreview(...)
- AdtClientsWS
- 实时请求/事件外观结束 IWebSocketTransport - 包括调试器会话外观:侦听、附加、步骤、堆栈、变量 - 例子: await wsClient.request('debugger.listen', { timeoutSeconds: 30 })
- AdtClientBatch / AdtRuntimeClientBatch
- 在一次HTTP往返中执行多个独立的读取操作 - 使用SAP ADT批处理端点(POST /sap/bc/adt/debugger/batch)与 multipart/mixed 载荷 - 与API相同的工厂 AdtClient / AdtRuntimeClient --记录通话,然后 batchExecute() - 例子: const batch = new AdtClientBatch(connection); batch.getClass().readMetadata({...}); await batch.batchExecute();
支持的对象类型
| 对象类型 | AdtClient |
|---|---|
| 课程(CLAS) | ✅ |
| 行为实施(CLAS) | ✅ |
| 行为定义(BDEF) | ✅ |
| 接口(INTF) | ✅ |
| 程序(PROG) | ✅ |
| 功能组(FUGR) | ✅ |
| 功能模块(FUGR/FF) | ✅ |
| 功能包括(FUGR/I) | ✅ |
| 域名(DOMA) | ✅ |
| 数据元素(DTEL) | ✅ |
| 结构(表格/DS) | ✅ |
| 表格(表格/DT) | ✅ |
| 视图(DDLS) | ✅ |
| 元数据扩展(DDLX) | ✅ |
| 软件包(DEVC) | ✅ |
| 授权字段(SUSO/AUTH) | ✅ |
| 功能切换(FTG2/FT) | ✅ |
| 运输(TRNS) | ✅ |
快速开始
使用AdtClient(推荐-高级CRUD API)
import { createAbapConnection } from '@mcp-abap-adt/connection';
import { AdtClient } from '@mcp-abap-adt/adt-clients';
const connection = createAbapConnection({
url: 'https://your-sap-system.example.com',
client: '100',
authType: 'basic',
username: process.env.SAP_USERNAME!,
password: process.env.SAP_PASSWORD!
}, console);
const client = new AdtClient(connection, console);
// Simple CRUD operations with automatic operation chains
await client.getClass().create({
className: 'ZCL_TEST',
packageName: 'ZPACKAGE',
description: 'Test class'
}, { activateOnCreate: true });
// Utility functions
const utils = client.getUtils();
await utils.searchObjects({ query: 'Z*', objectType: 'CLAS' });
// Where-used with parsed results (recommended)
const result = await utils.getWhereUsedList({
object_name: 'ZCL_TEST',
object_type: 'class',
enableAllTypes: true // Eclipse "select all" behavior
});
console.log(`Found ${result.totalReferences} references`);
for (const ref of result.references) {
console.log(`${ref.name} (${ref.type}) in ${ref.packageName}`);
}
// Where-used with raw XML (legacy)
await utils.getWhereUsed({ object_name: 'ZCL_TEST', object_type: 'class' });使用AdtClientsWS(实时)
import { AdtClientsWS } from '@mcp-abap-adt/adt-clients';
import type { IWebSocketTransport } from '@mcp-abap-adt/adt-clients';
const transport: IWebSocketTransport = createYourTransport();
const wsClient = new AdtClientsWS(transport, console, {
requestTimeoutMs: 30000,
});
await wsClient.connect('wss://your-realtime-endpoint');
const debuggerSession = wsClient.getDebuggerSessionClient();
await debuggerSession.listen({ timeoutSeconds: 60 });
await debuggerSession.step({ action: 'step_over' });使用AdtClientBatch(批读取操作)
AdtClientBatch 通过以下方式在单个HTTP往返中发送多个独立的读取操作 multipart/mixed 批量请求。
import { AdtClientBatch } from '@mcp-abap-adt/adt-clients';
const batch = new AdtClientBatch(connection, console);
// Record operations (not yet executed)
const classPromise = batch.getClass().readMetadata({ className: 'CL_ABAP_TYPEDESCR' });
const domainPromise = batch.getDomain().readMetadata({ domainName: 'MANDT' });
const dePromise = batch.getDataElement().readMetadata({ dataElementName: 'MANDT' });
// Execute all in one HTTP request
await batch.batchExecute();
// Resolve individual results
const classState = await classPromise;
const domainState = await domainPromise;
const deState = await dePromise;批量安全操作 (单步执行,无需等待链式操作):
read(),readMetadata(),readTransport()--单个GETcheck(),validate(),activate()--单POST
不批量安全 (多级链): create(), update(), delete().
通过批处理终结点执行ABAP调试器步骤操作
AdtRuntimeClient 通过调试器批处理请求执行步骤操作(POST /sap/bc/adt/debugger/batch)使用 multipart/mixed 有效载荷。
import { AdtRuntimeClient } from '@mcp-abap-adt/adt-clients';
const runtime = new AdtRuntimeClient(connection);
const abapDebugger = runtime.getDebugger().getAbap();
// Executes stepInto + getStack in one batch request
const batchResponse = await abapDebugger.stepIntoBatch();
// Also available:
await abapDebugger.stepOutBatch();
await abapDebugger.stepContinueBatch();对于非步进操作,请使用 executeAction(action, value?). 步骤操作(stepInto, stepOut, stepContinue)仅保留用于批处理执行。
使用AdtExecutor(执行API)
import { AdtExecutor } from '@mcp-abap-adt/adt-clients';
const executor = new AdtExecutor(connection, console);
// Class execution
await executor.getClassExecutor().run({ className: 'ZCL_MY_CLASSRUN' });
// Program execution (on-premise)
await executor.getProgramExecutor().run({ programName: 'ZMY_EXEC_REPORT' });
// Program execution with profiling
const runWithProfilingResult = await executor.getProgramExecutor().runWithProfiling(
{ programName: 'ZMY_EXEC_REPORT' },
{
profilerParameters: {
allProceduralUnits: true,
sqlTrace: true,
allDbEvents: true,
},
},
);
console.log(runWithProfilingResult.traceId);AdtUtils读取类型安全: readObjectMetadata 和 readObjectSource 接受严格的对象类型联合,以防止无效输入,如 view:ZOBJ.
import type { AdtObjectType, AdtSourceObjectType } from '@mcp-abap-adt/adt-clients';
await utils.readObjectMetadata('DDLS/DF' satisfies AdtObjectType, 'ZOK_I_CDS_TEST');
await utils.readObjectSource('view' satisfies AdtSourceObjectType, 'ZOK_I_CDS_TEST');优点:
- ✅ 简化的API-无需手动锁定/解锁管理
- ✅ 自动操作链(验证→ 创造→ 检查→ lock → 更新→ 解锁→ 激活
- ✅ 一致的错误处理和资源清理
- ✅ CRUD操作和实用函数的分离
- ✅ 对对象就绪的长轮询支持
使用长轮询进行对象准备
这 withLongPolling 参数允许您在创建/更新/激活操作后等待对象可用,将固定超时替换为服务器驱动的等待:
import { AdtClient } from '@mcp-abap-adt/adt-clients';
const client = new AdtClient(connection);
// Create a class
await client.getClass().create({
className: 'ZCL_TEST',
packageName: 'ZPACKAGE',
description: 'Test class'
});
// Wait for object to be ready using long polling
// The server will hold the connection until the object is available
await client.getClass().read(
{ className: 'ZCL_TEST' },
'active',
{ withLongPolling: true }
);
// Now the object is guaranteed to be ready for subsequent operations
await client.getClass().update({
className: 'ZCL_TEST'
}, { sourceCode: updatedCode });长期投票的好处:
- ✅ 没有任意超时 -等待实际对象准备就绪
- ✅ 更快的测试 -当对象快速准备就绪时,不会出现不必要的延迟
- ✅ 更可靠 -服务器驱动的等待确保对象实际可用
- ✅ 自动创建/更新 -
AdtObject实现在内部使用长轮询
注: 长轮询在以下情况下自动使用 create() 和 update() 所有方法 AdtObject 实现以确保对象在继续后续操作之前准备就绪。
创建行为实现类
import { AdtClient } from '@mcp-abap-adt/adt-clients';
const client = new AdtClient(connection);
await client.getBehaviorImplementation().create(
{
className: 'ZBP_OK_I_CDS_TEST',
packageName: 'ZOK_TEST_PKG_01',
behaviorDefinition: 'ZOK_I_CDS_TEST',
description: 'Behavior Implementation for ZOK_I_CDS_TEST',
transportRequest: 'E19K900001'
},
{ activateOnCreate: true }
);开发者工具
ADT发现脚本
该包包含一个用于从ADT发现端点生成文档的工具,其中列出了所有可用的ADT API端点。
目的: 探索可用的ADT API端点并生成降价文档。
用途:
# Generate discovery documentation (default output: docs/architecture/discovery.md)
npm run discovery:markdown
# Custom output file
npm run discovery:markdown -- --output custom-discovery.md
# Custom SAP system URL
npm run discovery:markdown -- --url https://your-system.com
# Custom .env file
npm run discovery:markdown -- --env /path/to/.env它的作用:
- 使用来自的凭据连接到SAP系统
.env文件 - 获取发现终结点:
GET /sap/bc/adt/discovery(通过AdtUtils.discovery()) - 解析XML响应
- 将其转换为具有端点类别、HTTP方法、URL、内容类型和描述的可读markdown
- 将打印精美的发现XML保存在markdown输出旁边
输出:
- 违约:
docs/architecture/discovery.md和docs/architecture/discovery.xml - 自定义:通过指定的路径
--output选项,加discovery.xml在同一目录中
环境变量: 该脚本使用与主包相同的环境变量:
SAP_URL-SAP系统URL(必填)SAP_AUTH_TYPE-身份验证类型:'basic'或'jwt'(默认值:'basic')SAP_USERNAME-基本身份验证的用户名SAP_PASSWORD-基本身份验证密码SAP_JWT_TOKEN-JWT身份验证的JWT令牌SAP_CLIENT-客户编号(可选)
何时使用:
- 探索SAP系统上可用的ADT API端点
- 为ADT API生成最新文档
- 了解ADT发现响应的结构
- 验证特定SAP系统上的端点可用性
看 工具文档 了解完整的细节和选项。
API 参考
AdtClient概述
- ADT对象的工厂访问器:
client.getClass(),client.getProgram(),client.getView(),client.getTable(),client.getRequest(),client.getUtils()等等。 - 每个访问者返回一个
Adt*对象实现IAdtObject操作。 - 看
src/index.ts用于完整类型导出和对象配置。
AdtObject方法(支持长轮询)
全部 AdtObject 实现支持 withLongPolling 读取操作的参数:
// Read with long polling - waits for object to be ready
await adtObject.read(config, 'active', { withLongPolling: true });
// Read metadata with long polling
await adtObject.readMetadata(config, { withLongPolling: true });
// Read metadata with explicit version
await adtObject.readMetadata(config, { version: 'active' });
// Read transport info with long polling
await adtObject.readTransport(config, { withLongPolling: true });何时使用长轮询:
- 之后
create()操作-等待对象可用 - 之后
update()操作-等待更改持久化 - 之后
activate()操作-等待对象在活动版本中可用 - 在测试中-更换固定
setTimeout长轮询延迟以提高可靠性
操作结果存储在返回的状态中(createResult, updateResult, checkResult等等):
const createState = await client.getFunctionModule().create({
functionGroupName: 'ZFGROUP',
functionModuleName: 'ZFM_TEST',
description: 'Test FM',
});
console.log(createState.createResult?.status);接受协商(可选)
某些ADT端点返回 406 当 Accept 标头与系统支持的媒体类型不匹配。客户可以 可选自动校正 Accept 通过使用406响应中返回的支持值重试。
全局启用:
import { AdtClient } from '@mcp-abap-adt/adt-clients';
const client = new AdtClient(connection, console, {
enableAcceptCorrection: true,
});通过环境启用:
ADT_ACCEPT_CORRECTION=true npm test每次读取呼叫覆盖:
await client.getClass().read(
{ className: 'ZCL_TEST' },
'active',
{ accept: 'text/plain' }
);
await client.getClass().readMetadata(
{ className: 'ZCL_TEST' },
{ accept: 'application/vnd.sap.adt.oo.classes.v4+xml', version: 'active' }
);
// Read source without version (initial post-create state)
await client.getClass().read({ className: 'ZCL_TEST' }, undefined);笔记:
- 默认情况下禁用。
- 更正重试一次,并缓存支持的
Accept每个端点。
专业客户
- 管理客户端:批量激活+检查操作
- 锁定客户端:显式锁定/解锁
.locks注册表集成 - 验证客户端:名称验证镜像ADT验证终结点
请参阅TypeScript类型(src/index.ts)用于整个API表面。
类型系统
集中式类型定义
所有类型定义都集中在特定模块中 types.ts 文件夹:
// Import types from module exports
import type {
IClassConfig,
IClassState,
IProgramConfig
} from '@mcp-abap-adt/adt-clients';命名规范
该软件包使用 双重命名约定 以区分API层:
低级参数(snake_case)
由内部ADT API函数使用。
AdtObject配置(camelCase)
被...使用 AdtClient 和 Adt* 对象配置:
interface IClassConfig {
className: string;
packageName?: string;
transportRequest?: string;
description: string;
sourceCode?: string;
}这种双重约定:
- 明确低级/高级区分
- 匹配SAP ADT XML参数命名(
class_name在ADT请求中) - 为JavaScript/TypeScript用户提供熟悉的camelCase
- 允许在每一层进行正确的类型检查
看 架构文档 了解详情。
迁移指南
从超时到长时间投票
从固定超时迁移到长轮询:
该软件包现在使用长轮询(?withLongPolling=true)而不是等待对象就绪的固定超时。这提供了更好的可靠性和更快的执行速度。
// ❌ Before - Using fixed timeouts
await client.getClass().create({ className: 'ZCL_TEST', ... });
await new Promise(resolve => setTimeout(resolve, 2000)); // Fixed delay
await client.getClass().update({ className: 'ZCL_TEST' }, { sourceCode });
// ✅ After - Using long polling
await client.getClass().create({ className: 'ZCL_TEST', ... });
// Long polling is automatically used in create/update methods
await client.getClass().update({ className: 'ZCL_TEST' }, { sourceCode });
// Or explicitly use long polling in read operations
await client.getClass().read(
{ className: 'ZCL_TEST' },
'active',
{ withLongPolling: true }
);优点:
- 无任意延迟-等待实际对象准备就绪
- 对象快速准备就绪时执行速度更快
- 更可靠-服务器驱动的等待确保对象可用
- 自动进入
create()和update()方法
无建筑商API
CrudClient,ReadOnlyClient和生成器类在无生成器的API中被删除。- 使用
AdtClient和那个Adt*物体(client.getClass(),client.getView()等等)。
文档
日志记录和调试
图书馆使用a 5层粒度调试标志系统 对于不同的代码层:
调试环境变量
# Connection package logs (HTTP, sessions, CSRF tokens)
DEBUG_CONNECTORS=true npm test
# Core library logs
DEBUG_ADT_LIBS=true npm test
# Integration test execution logs
DEBUG_ADT_TESTS=true npm test
# E2E integration test logs
DEBUG_ADT_E2E_TESTS=true npm test
# Test helper function logs
DEBUG_ADT_HELPER_TESTS=true npm test
# Enable ALL ADT scopes at once
DEBUG_ADT_TESTS=true npm test记录器接口
所有客户都接受统一 ILogger 接口:
import type { ILogger } from '@mcp-abap-adt/adt-clients';
import { AdtClient } from '@mcp-abap-adt/adt-clients';
// Custom logger example
const logger: ILogger = {
debug: (msg, ...args) => console.debug(msg, ...args),
info: (msg, ...args) => console.info(msg, ...args),
warn: (msg, ...args) => console.warn(msg, ...args),
error: (msg, ...args) => console.error(msg, ...args),
};
const client = new AdtClient(connection, logger);注: 所有记录器方法都是可选的。锁柄始终完整记录(而不是截断)。
看 docs/DEBUG.md 详细的调试指南。
更新日志
看 更改日志.md 获取特定于软件包的发行说明。 最新(0.3.14):已添加 getWhereUsedList() 用于解析使用位置的结果。
测试
集成测试使用YAML配置(src/__tests__/helpers/test-config.yaml)以及 BaseTester 图案。\ 一些ADT端点是特定于系统的;406被视为Accept/标头支持问题,可以通过以下方式明确允许 test_settings.allow_406 或每次测试 params.allow_406 (例如对象结构/节点结构)。
许可证
麻省理工学院
作者
奥列克西·基斯利特西亚
