1. 当 SAProuter 只放行 RFCClaude 就被挡在 ADT 门外如果你在 SAP ABAP 项目现场待过大概率见过这种网络拓扑开发机连不进应用服务器的 ICM HTTP/HTTPS 端口所有流量必须经过 SAProuter而 saprouttab 里只开了 DIAG、Gateway、RFC 这几条 NI 协议路由。SAP GUI 登录正常Eclipse ADT 也能打开包、类、CDS View但一旦换成基于 HTTP 的自动化工具curl 打 ICM 端口超时Node.js 的 ADT Client 报连接失败vsp 这类把 ADT 能力通过 MCP 暴露给 Claude 的 Server 同样连不上。表面看很矛盾Eclipse ADT 明明能用为什么 Claude 用不了原因在于 Eclipse ADT 在这种受限网络里并没有走普通 HTTP 到 ICM而是把 ADT 的 HTTP 请求封装进 RFC经由 SAProuter 允许的 RFC 通道调用系统里的标准 Function ModuleSADT_REST_RFC_ENDPOINT。这个 FM 属于SAP_BASIS下的BC-DWB-AIE组件描述是 Endpoint for ADT REST Framework导入参数REQUEST、导出参数RESPONSE是 Remote-Enabled Module。也就是说系统侧本来就存在一条「ADT over RFC」的暗道只是 HTTP-only 的 AI 工具不知道。这篇要解决的问题很具体在 RFC-only 与 SAProuter 隔离的企业内网里怎么让 Claude 真正参与 SAP ABAP 开发而不是停在离线生成示例代码的阶段。思路是本地起一个 HTTP 到 RFC 的桥把 vsp 发出的 ADT HTTP 请求转成 RFC 调用再通过 TaoToken 统一 Key 把 Claude 侧的模型通道接进来。适合谁手上有 Eclipse ADT 可用、但 HTTP 到 ICM 被挡的 ABAP 开发者以及想给团队搭一套可控 AI 结对环境的架构同学。2. TaoToken 前置统一 Key 与 API 通道桥接解决的是「Claude 到 SAP」这一段网络路径但 Claude 本身要能稳定调用模型还需要一个统一的模型入口。TaoToken 在这里承担的角色是统一 Key 与 API 通道你不用在 Cline、CC Switch、Claude Code 之间分别维护不同的模型配置而是用一套 Key 走同一个 API 入口把模型对话、编码补全、Agent 调用都收敛到一处。对 ABAP 场景来说这一点比普通 Web 开发更重要。SAP 项目现场经常是内网隔离、代理受限、证书链复杂如果每个工具都要单独配一套模型通道排障成本会成倍上升。统一入口之后模型侧出问题只需要查一个地方网络侧出问题就集中在桥接和 SAProuter 这一段边界清晰。接入前先在 TaoToken 控制台创建 API Key地址是 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite 。创建好之后模型对话可以在 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite 验证长期编码和 Agent 场景建议看 Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite 。接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 控制台在 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite 。官网入口https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。注意TaoToken 是模型 API 通道不替代 SAP 侧的授权体系。桥接层进入 SAP 用的是 RFC 用户模型侧用的是 API Key两者职责分开审计时也更容易追溯。3. 可复制配置settings.json 与 config.toml 骨架这一节给出两个可直接改的配置骨架。第一个是 Cline / Claude Code 这类工具的settings.json第二个是 CC Switch 或类似多环境切换工具的config.toml。两者都指向 TaoToken 的统一 API 入口同时把本地桥接端口作为 ADT 访问地址。先看settings.json。核心是把模型 provider 指向 TaoToken 的 API 地址把 API Key 用环境变量注入避免明文写死在仓库里。ADT 侧则通过SAP_URL指向本地桥接端口让 vsp 以为自己在访问一个普通 ADT HTTP 服务。{ modelProvider: { name: taotoken, baseUrl: https://taotoken.net/api, apiKeyEnv: TAOTOKEN_API_KEY, model: claude-sonnet }, mcpServers: { sap-adt-rfc: { command: C:\\path\\to\\x64\\python.exe, args: [C:\\path\\to\\adt-rfc-bridge\\vsp_launch.py], env: { BRIDGE_PORT: 8410, RFC_ASHOST: 10.0.0.1, RFC_SYSNR: 00, RFC_CLIENT: 100, RFC_USER: YOUR_RFC_USER, RFC_PASSWD: your-rfc-password, RFC_SAPROUTER: /H/router.example.com/S/3299, ADT_CLIENT: C:\\path\\to\\vsp.exe, SAP_URL: http://127.0.0.1:8410, SAP_USER: YOUR_RFC_USER, SAP_PASSWORD: your-rfc-password, SAP_CLIENT: 100 } } } }再看config.toml适合 CC Switch 这类需要多环境切换的场景。每个 SAP Client 分配一个独立端口DEV 100 用 8410QAS 200 用 8420一个桥对应一个 RFC 用户、一个 Client、一个端口不混用也不暴露到局域网。[taotoken] base_url https://taotoken.net/api api_key_env TAOTOKEN_API_KEY default_model claude-sonnet [bridge.dev100] bridge_port 8410 rfc_ashost 10.0.0.1 rfc_sysnr 00 rfc_client 100 rfc_user YOUR_RFC_USER rfc_passwd_env SAP_DEV100_PASSWD rfc_saprouter /H/router.example.com/S/3299 sap_url http://127.0.0.1:8410 [bridge.qas200] bridge_port 8420 rfc_ashost 10.0.0.2 rfc_sysnr 00 rfc_client 200 rfc_user YOUR_RFC_USER rfc_passwd_env SAP_QAS200_PASSWD rfc_saprouter /H/router.example.com/S/3299 sap_url http://127.0.0.1:8420桥接程序的核心逻辑很小但很精准。它在本机监听 HTTP 地址拿到请求后组装SADT_REST_REQUEST通过 PyRFC 调用SADT_REST_RFC_ENDPOINT再把SADT_REST_RESPONSE转回 HTTP 响应。下面这段是桥接核心的示意不是完整实现但能看清数据流。def adt_call(method, uri, headers, body): # SADT_REST_RFC_ENDPOINT 对 HEAD 支持不理想转成 GETHTTP 层再丢弃 body fm_method GET if method HEAD else method req { REQUEST_LINE: {METHOD: fm_method, URI: uri, VERSION: HTTP/1.1}, HEADER_FIELDS: [{NAME: k, VALUE: v} for (k, v) in headers], MESSAGE_BODY: body or b, } with _lock: conn get_conn() res conn.call(SADT_REST_RFC_ENDPOINT, REQUESTreq) r res[RESPONSE] code int(r[STATUS_LINE][STATUS_CODE]) out_headers [(h[NAME], h[VALUE]) for h in r[HEADER_FIELDS]] return code, r[STATUS_LINE][REASON_PHRASE], out_headers, r[MESSAGE_BODY]PyRFC 连接参数里SAProuter 用/H/host/S/port格式传入这是 SAP NW RFC SDK 要求的写法不能塞进 HTTP proxy 配置。from pyrfc import Connection conn Connection( ashost10.0.0.1, sysnr00, client100, userYOUR_RFC_USER, passwdyour-rfc-password, saprouter/H/router.example.com/S/3299, )4. 验证请求从 RFC 连通到 ABAP 补全配置写完不要直接上 Claude按层次往上验证出错时才知道卡在哪一层。第一步验证 PyRFC 能否加载这一步失败基本是原生库或位数问题不是 SAP 用户密码错。python -c from pyrfc import Connection; print(pyrfc ok)第二步用STFC_CONNECTION验证 RFC 基本连通。这个 FM 是 SAP 标准测试函数能返回说明 SAProuter、Gateway、RFC 用户这条链路已经通了。from pyrfc import Connection conn Connection( ashost10.0.0.1, sysnr00, client100, userYOUR_RFC_USER, passwdyour-rfc-password, saprouter/H/router.example.com/S/3299, ) result conn.call(STFC_CONNECTION, REQUTEXTping) print(result[ECHOTEXT])第三步启动桥接程序确认本地端口在监听。python adt_rfc_bridge.py # 期望输出类似bridge listening on http://127.0.0.1:8410 - SAProuter backend第四步做一次 ADT Discovery验证 HTTP 到 RFC 再到 ADT REST Framework 的链路。能返回application/atomsvcxml一类响应说明桥接层工作正常。curl -i http://127.0.0.1:8410/sap/bc/adt/discovery第五步把 vsp 和 Claude 接上去让 Claude 读一个真实 ABAP 对象。比如让它搜索某个 Z 包下所有调用特定 Function Module 的 Report或者读取一个 RAP Behavior Implementation 分析 EML 调用逻辑。如果 Claude 能返回真实对象内容而不是凭空生成说明整条链路已经打通。ABAP 侧的重构结果可以用下面这段作为参照按团队规范 ABAP 代码块用 sql 包裹。Claude 通过 ADT 读到真实代码后可以建议把查询逻辑抽到类方法里便于后续单元测试。REPORT z_demo_product_lookup. PARAMETERS p_matnr TYPE matnr OBLIGATORY. CLASS lcl_product_reader DEFINITION FINAL. PUBLIC SECTION. TYPES BEGIN OF ty_product, matnr TYPE mara-matnr, mtart TYPE mara-mtart, meins TYPE mara-meins, END OF ty_product. CLASS-METHODS read_product IMPORTING iv_matnr TYPE matnr RETURNING VALUE(rs_product) TYPE ty_product RAISING cx_sy_open_sql_db. ENDCLASS. CLASS lcl_product_reader IMPLEMENTATION. METHOD read_product. SELECT SINGLE matnr, mtart, meins FROM mara WHERE matnr iv_matnr INTO rs_product. ENDMETHOD. ENDCLASS. START-OF-SELECTION. DATA(ls_product) lcl_product_readerread_product( p_matnr ). IF ls_product-matnr IS INITIAL. MESSAGE Product not found TYPE S DISPLAY LIKE E. RETURN. ENDIF. WRITE / ls_product-matnr. WRITE / ls_product-mtart. WRITE / ls_product-meins.5. 本篇常见错排查DLL load failed导入 PyRFC 时报这个错多半不是 SAP 用户密码问题而是本机原生库加载路径或位数不匹配。SAP NW RFC SDK 是原生库Python 解释器、PyRFC Wheel、SDK 位数必须一致。Windows 上最省心的组合是 x64 Python、x64 SAP NW RFC SDK、匹配版本的 PyRFC。Python 3.8 之后 Windows DLL 搜索机制有变化PATH 不再按旧方式搜索 DLL必要时显式设置 SDK 的 lib 目录。route permission deniedSAProuter 根据路由权限表判断连接能否建立权限不满足时返回这个错误。这时不要反复改 HTTP proxy 配置要回到 saprouttab 检查允许的端口和路由串。/H/router.example.com/S/3299/H/appserver.example.local/S/3300这种字符串不是 HTTP Proxy 地址塞进HTTPS_PROXY或 Node.js 的 proxy 配置只会得到各种连接失败。HTTP HEAD 探测失败部分 ADT 客户端会发 HEAD 请求做探测但SADT_REST_RFC_ENDPOINT对 HEAD 支持不理想。桥接层把 HEAD 转成 GET 发给 FM再在本地 HTTP 层丢弃 Body客户端仍然收到符合预期的 HEAD 响应。X-CSRF-Token 缺失普通 HTTP 场景里 ADT 客户端写操作前会先取 CSRF Token。RFC 场景不依赖同样的 HTTP Session 机制SADT_REST_RFC_ENDPOINT已经在 RFC 登录上下文里完成身份认证。若客户端坚持等待 Token桥接层可以在 fetch 请求时合成一个占位 Token让 vsp 这类 HTTP-only 客户端不会因为缺 Token 拒绝写操作。账号锁定每次 ADT 调用背后可能伴随 RFC 登录密码错误还不断重试很容易触发 SAP 用户锁定。认证错误立即停下修正.env或 MCP 配置后再试不做自动重试循环。桥接端口暴露桥只监听127.0.0.1不要暴露到局域网。.env和日志里可能含有 URI、Header 等敏感信息本地保管不要提交到仓库。6. 把模型通道和 SAP 通道分开治理这套方案里有两个独立的通道需要分别治理。模型侧走 TaoToken 统一 Key排障和接入参考 API Keys 与接入文档https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite 和 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 。验证模型是否正常用模型对话页面https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite 。长期编码和 Agent 场景看 Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite 。SAP 侧走 RFC 用户和 ADT 授权桥接层不绕过任何 SAP 授权S_RFC、ADT Resource Authorization、包权限、对象锁、传输请求控制仍然生效。生产系统建议只读写操作做成显式开关可写包范围限制在$TMP、Z*或约定命名空间内。多人共享同一个桥会导致 SAP 侧审计混淆企业级方案应该考虑 Destination Service、Cloud Connector、Principal Propagation 这类身份传递机制让每个实际用户的身份可追溯。最后留一个实际经验桥接程序复用一个串行化 RFC 连接简单且对锁友好但不适合大量并发客户端同时轰击一个桥。一个桥对应一个 SAP 用户、一个 Client、一个端口这个约束在配置阶段就定好后面排障会省很多事。