AI 帮我写 SAP OData 服务并发布

让 AI 帮我写 SAP OData 服务:MCP + CDS 视图全自动查询 T001 公司代码并落盘本地

前言:本文记录一次完整的"AI Agent + MCP 直连 SAP"实战------从登录 SAP、创建 CDS 视图实体、发布 OData 服务,到把 T001 表 450 条公司代码数据全量拉取并保存为本地 JSON/CSV 文件的全过程。全程在 Trae(AI IDE)中通过 MCP 工具完成,SAP 侧仅需手动点一次"发布"。


文章目录

  • [让 AI 帮我写 SAP OData 服务:MCP + CDS 视图全自动查询 T001 公司代码并落盘本地](#让 AI 帮我写 SAP OData 服务:MCP + CDS 视图全自动查询 T001 公司代码并落盘本地)
    • 一、背景与目标
    • 二、技术方案选型
    • 三、实战步骤
      • [3.1 登录 SAP:healthcheck → odata_connect-选择开发角色的Agent](#3.1 登录 SAP:healthcheck → odata_connect-[选择开发角色的Agent])
      • [3.2 确认系统版本与表结构(禁止猜字段!)](#3.2 确认系统版本与表结构(禁止猜字段!))
      • [3.3 创建 CDS 视图实体 ZC_T001](#3.3 创建 CDS 视图实体 ZC_T001)
      • [3.4 创建服务定义 ZSD_T001](#3.4 创建服务定义 ZSD_T001)
      • [3.5 发布服务绑定 ZSB_T001(唯一的手动步骤)](#3.5 发布服务绑定 ZSB_T001(唯一的手动步骤))
      • [3.6 验证服务并拉取数据-选择业务查询的Agent](#3.6 验证服务并拉取数据-[选择业务查询的Agent])
      • [3.7 落盘本地](#3.7 落盘本地)
    • 四、成果总览
    • 五、踩坑清单(重点收藏)
    • [六、关键安全设计:开发与业务双 Agent 分离](#六、关键安全设计:开发与业务双 Agent 分离)
    • 七、总结

一、背景与目标

作为 ABAP 开发者,我们经常遇到这种需求:"把某张配置表的数据开放成 OData 接口给外部系统用"。传统流程是 SEGW 建工程、建实体、写 DPC 代码、注册服务,一套下来半小时起步。

这次我尝试让 AI Agent 通过 MCP(Model Context Protocol)直接操作 SAP,目标:

  1. 登录 SAP(S/4HANA,ABAP 7.57)
  2. 创建一个查询 T001(公司代码主数据)的 OData 服务
  3. 调用该服务拉取全量数据,存入本地文件

二、技术方案选型

SAP 侧建 OData 服务有两条经典路线:

方案 协议 适用场景 工作量
RAP(CDS 视图 + Service Definition/Binding) V4/V2 ABAP Cloud / 新开发(推荐) 低,声明式
SEGW + DPC 扩展类 V2 Standard ABAP 维护存量 高,需写代码

本系统是 ABAP 7.57(S/4HANA 2022 平台),毫不犹豫选 RAP。链路如下:

复制代码
CDS 视图实体 → Service Definition → Service Binding → OData 端点
   (数据层)        (暴露什么)           (协议+URL)

三、实战步骤

3.1 登录 SAP:healthcheck → odata_connect-选择开发角色的Agent

MCP 的 SAP 连接遵循固定入口顺序:先 healthcheck 确认通道状态,再 odata_connect 统一登录(自动级联建立 ADT 数据通道)。

json 复制代码
// healthcheck 返回(节选)
{
  "status": "healthy",
  "channels": {
    "odata": { "role": "统一登录入口(仅 odata_connect)" },
    "adt":   { "role": "查表/视图/源码/对象管理" }
  },
  "order": ["ODATA", "ADT"]
}
json 复制代码
// odata_connect 返回(节选)
{
  "status": "success",
  "sessionId": "odata-1792137628814",
  "connectionInfo": {
    "baseUrl": "https://xxx:44300/sap/opu/odata/sap/",
    "profileName": "XXXXX",
    "loggedIn": true
  },
  "cascade": { "status": "S", "channelsOk": ["ODATA", "ADT"] }
}

⚠️ 踩坑:登录返回 HTTP 401 凭据无效,不要反复重试密码------检查发现是会话缓存问题,重新发起 odata_connect 即恢复。

3.2 确认系统版本与表结构(禁止猜字段!)

AI 写 ABAP 代码最大的风险是"凭印象猜字段名"。本流程强制遵循一条铁律:写 SELECT 前必须先查 DD03L 确认字段。

先查系统版本:

sql 复制代码
SELECT version FROM svers   -- 返回 757,即 ABAP 7.57

再查 T001 的真实字段(节选):

sql 复制代码
SELECT fieldname, keyflag, rollname, datatype, leng
FROM dd03l WHERE tabname = 'T001'
字段 键 类型 长度 含义
MANDT X CLNT 3 集团
BUKRS X CHAR 4 公司代码
BUTXT CHAR 25 公司名称
ORT01 CHAR 25 城市
LAND1 CHAR 3 国家
WAERS CUKY 5 货币
SPRAS LANG 1 语言
STCEG CHAR 20 VAT 注册号
FIKRS CHAR 4 资金管理范围
KTOPL CHAR 4 科目表

3.3 创建 CDS 视图实体 ZC_T001

通过 MCP 的 sap_object_create(action=ddls) 创建,注意字段全部用业务语义别名(OData 属性名会更友好):

cds 复制代码
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: '公司代码视图 (T001)'
@OData.publish: true
define view entity ZC_T001 as select from t001
{
      key bukrs as CompanyCode,
          butxt as CompanyCodeName,
          ort01 as City,
          land1 as CountryKey,
          waers as Currency,
          spras as LanguageKey,
          txjcd as TaxJurisdictionCode,
          stceg as VatRegistrationNumber,
          fikrs as FundsManagementArea,
          ktopl as ChartOfAccounts
}

⚠️ 踩坑 1:第一版加了 @ObjectModel.usageType:{ dataClass: #MASTER_DATA, ... },激活时报 Invalid annotation enum value '#MASTER_DATA'------该系统版本不认此枚举值,删掉即可。

⚠️ 踩坑 2:写源码必须走完整流程 lock → write → unlock → activate,跳步会报缺 lockHandle。激活成功后建议回查 REPOSRC 确认 R3STATE='A'(activated:true 不等于真激活)。

3.4 创建服务定义 ZSD_T001

cds 复制代码
@EndUserText.label: 'T001 公司代码查询服务'
define service ZSD_T001 {
  expose ZC_T001 as CompanyCode;
}

一行 expose 搞定,CompanyCode 就是最终 URL 里的实体集名。此对象 MCP 一次创建即激活成功。

3.5 发布服务绑定 ZSB_T001(唯一的手动步骤)

这是本次唯一的"非自动化"环节。MCP 的 sap_object_create(action=raw) 创建 SRVB 对象时报 Can't create service binding with incomplete data------因为 ADT 创建服务绑定必须同时指定绑定类型 (V2 UI / V4 UI / Web API),而 MCP 未暴露该参数;@OData.publish: true 在 REST 激活路径下也不会触发注册表写入。

于是在 ADT Eclipse 中手动完成(约 30 秒):

  1. File → New → Other ABAP Repository Object → Service Binding
  2. 名称 ZSB_T001,包 $TMP
  3. Binding Type 选 OData V2 - Web API(做纯数据接口选 Web API,不要选 UI)
  4. Service Definition 关联 ZSD_T001 → 激活 → 点 Publish

3.6 验证服务并拉取数据-选择业务查询的Agent

发布完成后,通过 MCP 的 OData 消费工具验证:

json 复制代码
// metadata 确认服务已可用
{
  "service_url": "https://xxx:44300/sap/opu/odata/sap/ZSB_T001/",
  "schema_namespace": "cds_zsd_t001",
  "entity_sets": [{ "name": "CompanyCode", "ops": ["list", "get", "count"] }]
}

数据总量 450 条,服务端单页上限 100 条,用 $top/$skip 并行拉 5 页:

复制代码
GET /ZSB_T001/CompanyCode?$top=100&$skip=0    → 100 条
GET /ZSB_T001/CompanyCode?$top=100&$skip=100  → 100 条
...(共 5 页,450 条,按主键去重校验无重复)

样例数据:

CompanyCode CompanyCodeName City Country Currency
0001 SAP A.G. Walldorf DE EUR
0007 SAP CN 上海 CN CNY
0009 合盛硅业股份有限公司 宁波 CN CNY
3310 广州西行电子科技有限公司 广州 CN CNY

3.7 落盘本地

PowerShell 一段脚本合并 5 页数据,输出两种格式:

  • t001_data.json(231 KB):完整结构化数据 + 元信息(服务名、抽取时间、总数)
  • t001_data.csv(32 KB):10 列表格,Excel 直接打开
powershell 复制代码
$all = 合并5页JSON.value
$unique = $all | Sort-Object CompanyCode -Unique   # 450 条,无重复
$out | ConvertTo-Json -Depth 5 | Out-File t001_data.json -Encoding utf8
$unique | Export-Csv t001_data.csv -NoTypeInformation -Encoding UTF8

四、成果总览

步骤 对象/产出 方式 耗时占比
登录 SAP OData + ADT 双通道会话 MCP 全自动 极短
确认版本/字段 ABAP 7.57 + T001 字段清单 MCP 全自动 极短
CDS 视图 ZC_T001 已激活(含 2 次踩坑修正) MCP 全自动 短
服务定义 ZSD_T001 已激活 MCP 全自动 极短
服务绑定 ZSB_T001 已发布 V2 Web API ADT 手动 唯一人工环节
数据拉取 450 条,5 页并行 MCP 全自动 短
本地落盘 JSON 231KB + CSV 32KB 脚本 极短

五、踩坑清单(重点收藏)

  1. Invalid annotation enum value '#MASTER_DATA' :@ObjectModel.usageType 枚举值与系统版本不兼容,直接删注解。
  2. SRVB 无法通过 ADT REST 裸创建 :Can't create service binding with incomplete data,缺绑定类型参数,用 Eclipse 手动发布最稳。
  3. @OData.publish: true 不生效:REST 通道激活不触发后台注册任务,不要指望它替代 Service Binding。
  4. Unknown column name:猜字段名必翻车(如 DD03L 没有 DDTEXT、SVERS 没有 EXTRELEASE),永远先查 DD03L。
  5. MCP 工具参数不能凭记忆 :同一工具不同版本参数名可能变化(如 objectName vs objectUrl),调用前先读 descriptor schema。
  6. 同错不重试第 3 次:同一错误出现 2 次立即换路径,避免无限循环。

六、关键安全设计:开发与业务双 Agent 分离

本次实战中间切换了两次 Agent ,这不是随意的操作,而是一次刻意的权限与角色分离设计:

阶段 Agent / 通道 SAP 账号 职责 权限特征
开发阶段 ADT 开发通道(odata_connect 级联 ADT) 开发用户 创建 CDS 视图、服务定义、激活对象 有开发权限(SE80/ADT 写对象),不应该有大批量业务数据查询权限
业务阶段 OData 消费通道(sap_odata_serve) 业务用户 调用已发布服务、拉取数据、落盘 只有 OData 消费权限,无法创建/修改任何仓库对象

为什么要这么分?想象一个反面场景:如果让一个"全能 Agent"拿着开发权限去跑业务查询,一旦 Prompt 被注入(比如读到了一个恶意网页内容,指示它 DELETE 数据或修改标准代码),破坏面是全系统的。而通道分离后:

  1. 爆炸半径可控:开发通道只暴露对象管理类工具,业务通道只暴露 OData 消费工具------即便某个 Agent 被"带偏",它能做的事情被 MCP 工具集硬性框死;
  2. 审计清晰:SAP 侧登录日志(SM19/STAD)能明确区分"谁在做开发变更、谁在拉业务数据",两个账号对应两条审计线索;
  3. 符合最小权限原则 :业务用户永远不需要 ADT 写权限,开发用户也不需要 S_RFC/OData 消费授权。

实际操作中的体验:开发完成后 MCP 服务器直接从 mcp_sap_http_sse_adt 切换到 mcp_sap_http_sse_bus,后者以业务用户身份(request-headers 注入凭据)连接,sap_status 一查确认身份已切换,直接进入数据消费阶段------对 AI 来说就是换了一套工具集,对权限体系来说就是换了一个"人"。

💡 这也是给准备落地 "AI + SAP" 的团队的建议:不要给 AI 一个超级用户。按场景拆分 MCP Server 实例、绑定不同的 SAP 角色,是成本最低的 AI 治理手段。

七、总结

这次实战验证了 "AI Agent + MCP" 操作 SAP 的可行性:约 90% 的步骤(登录、建模、编码、激活、查询、落盘)可全自动完成,仅服务绑定发布需要人工点一下。对于批量暴露配置表/主数据接口这类标准化需求,效率提升非常明显。

后续可扩展方向:

  • 给服务绑定加 ZCL_ 查询类做复杂逻辑(替代纯 CDS 直通)
  • 用 $filter/$select 做 OData 侧按需查询
  • 把整套流程封装成 Skill,实现"一句话建 OData 服务"

相关推荐
Austin_YB1 个月前
SAP AI助手 安装部署全流程指南
sap ai助手
Austin_YB1 个月前
基于 MCP 协议的 SAP AI 助手实战
sap ai助手