内容
# MCP-RFC 桥接器用于 SAP ABAP(仅限 RFC / SAProuter / ECC R3)
一个 MCP 服务器,允许 MCP 客户端(例如 Claude Code)通过 **RFC** 而不是 ADT/HTTP 与 SAP ABAP 对象一起工作。因为它支持 RFC + SAProuter,所以它可以访问那些没有公开 HTTP/ADT 端点的系统 - 包括经典 ECC / R/3。
> 灵感来自 SAP 社区博客“在仅限 RFC / SAProuter 系统上(甚至 ECC R/3)使用 Claude 进行 SAP ABAP 开发”。这是独立的原型实现 - 不是官方 SAP 或 Anthropic 产品。
## 架构
```
Claude Code --stdio/MCP--> server.py (FastMCP)
|
sap/tools.py (封装标准 SAP 函数)
|
sap/connection.py (pyrfc 连接,重连)
|
sap/config.py (.env -> 连接参数,SAProuter)
|
pyrfc --RFC/SAProuter--> SAP 系统
```
## 公开的工具
| 工具 | 用途 | 需要写入? |
| --- | --- | --- |
| `sap_ping` | 测试连接,系统信息 | 否 |
| `sap_read_table` | 读取表格(RFC_READ_TABLE) | 否 |
| `sap_read_program` | 读取 ABAP 报告源 | 否 |
| `sap_read_function_module` | 读取 FM 源 + 接口 | 否 |
| `sap_read_class` | 读取类/接口源 | 否 |
| `sap_read_method` | 读取类的一个方法 | 否 |
| `sap_class_api` | 公共 API 仅限(+ 依赖 API) | 否 |
| `sap_dead_code` | 包中未使用的扫描方法 | 否 |
| `sap_search_objects` | 搜索 TADIR 存储库对象 | 否 |
| `sap_ddic_info` | 描述表格/结构字段 | 否 |
| `sap_list_dumps` | 最近的 ST22 运行时错误 | 否 |
| `sap_list_transports` | 列出传输请求(E070) | 否 |
| `sap_read_transport` | 一个传输 + 其对象列表 | 否 |
| `sap_where_used` | 通过 WBCROSSGT 索引的 where-used | 否 |
| `sap_read_screen` | 读取 Dynpro 定义(通过 Z-FM) | 否 |
| `sap_read_gui_status` | 读取 GUI 状态/CUA(通过 Z-FM) | 否 |
| `sap_syntax_check` | 语法检查源,无需保存(Z-FM) | 否 |
| `sap_read_cds` | 读取 CDS/DDL 源(Z-FM) | 否 |
| `sap_textpool_read` | 读取程序文本元素(Z-FM) | 否 |
| `sap_run_unit_tests` | 为类运行 ABAP 单元测试(Z-FM) | 否 |
| `sap_run_atc` | 运行 ATC 检查(Z-FM 存根) | 否 |
| `sap_adt_dispatch` | 原始 ZMCP_ADT_DISPATCH 调用 | 读取:否 / 写入:**是** |
| `sap_activate` | 激活非活动对象(Z-FM) | **是** |
| `sap_textpool_write` | 写入程序文本元素(Z-FM) | **是** |
| `sap_write_program` | 创建/更新程序(非活动) | **是** |
| `sap_run_rfc` | 调用任意 RFC-enabled FM | **是** |
### 自定义调度器 `ZMCP_ADT_DISPATCH`
上述 Z-FM 工具通过自定义 RFC-enabled FM **`ZMCP_ADT_DISPATCH`** (函数组 `ZMCP_ADT_UTILS`)路由到 SAP 系统 - 这是功能未公开的 RFC FM 的逃生阀。它在 SAP 内部运行,因此可以调用非远程工作台 API(`SYNTAX-CHECK`、`RS_WORKING_OBJECTS_ACTIVATE`、`READ/INSERT TEXTPOOL`、`DDDDLSRC`、`ABAP Unit`、`ATC`)并返回 JSON。
在您要驱动的 SAP 系统上安装 `abap/` 中的两个 FM(参见 `abap/README.md` 获取接口和逐步设置)。操作 → 工具映射:
| 操作 | 工具 | 底层 ABAP |
| --- | --- | --- |
| `SYNTAX_CHECK` | `sap_syntax_check` | `SYNTAX-CHECK FOR` |
| `READ_DDLS` | `sap_read_cds` | `SELECT … FROM DDDDLSRC` |
| `RUN_UNIT_TESTS` | `sap_run_unit_tests` | `CL_AUCV_TEST_RUNNER_STANDARD` |
| `ATC_CHECK` | `sap_run_atc` | `CL_SATC_API_FACTORY` (存根 - 填写) |
| `ACTIVATE` | `sap_activate` | `RS_WORKING_OBJECTS_ACTIVATE` |
| `DYNPRO_*` / `CUA_*` | `sap_read_screen` / `sap_read_gui_status` | `RPY_DYNPRO_*` / `RS_CUA_INTERNAL_*` |
`RUN_UNIT_TESTS` 和 `ATC_CHECK` 使用发布敏感的类 API - 验证/调整您的系统中的 ABAP(`ATC_CHECK` 作为显式存根提供)。所有写入操作都通过相同的 `SAP_ALLOW_WRITE` 保护。
**文本元素** 使用单独的专用 FM **`ZMCP_ADT_TEXTPOOL`** (相同的函数组),由 `sap_textpool_read` / `sap_textpool_write` 驱动。将其标记为 SE37 中的 Remote-Enabled 以使用它。`sap_textpool_write` 默认到 `WRITE_INACTIVE` (分段;发布时在程序激活时),匹配“在激活之前不生效”的模型;传递 `active=true` 直接写入。
除非 `SAP_ALLOW_WRITE=true`,否则写入工具被禁用。
**敏感表格策略:** `sap_read_table` 拒绝包含凭证/PII 的表格(USR02、PA0*、SECSTORE* 等)。通过 `.env` 中的 `SAP_TABLE_BLOCKLIST` (逗号分隔,`*` 通配符)覆盖模式列表。
**写入的包白名单:** 设置 `SAP_ALLOWED_PACKAGES` (例如 `$TMP,ZPK_SANDBOX*` )以将 `sap_write_program` 限制到特定包。取消设置 = 无包限制(仅 `SAP_ALLOW_WRITE` 适用)。
**FM 拒绝列表:** `sap_run_rfc` 拒绝高风险函数模块(OS 命令执行、任意 ABAP、大规模删除、原始 SQL、用户管理、文件传输、内核管理)即使 `SAP_ALLOW_WRITE=true`。通过 `.env` 中的 `SAP_FM_DENYLIST` (逗号分隔,`*` 通配符)覆盖模式列表。
## 项目布局
```
MCP_SAP_PRIVATE/
bootstrap.bat 复制到新机器:克隆存储库 + 运行设置
setup.ps1 / setup.bat 安装程序 + MCP 注册
README.md
mcp/ MCP 服务器(它需要运行的所有内容)
server.py MCP 服务器入口点(FastMCP,stdio)
test_connection.py 独立连接检查
requirements.txt
.env / .env.example 基本/共享设置(实际 .env 被 git 忽略)
profiles/ 每个 SAP 系统的配置文件(多系统)
ds4.env.example 系统配置文件模板
sap/ Python 包(桥接器)
config.py .env -> pyrfc 参数,SAProuter,SDK 发现
connection.py pyrfc 包装器,重连,DLL 注册
tools.py 每个 MCP 工具后面的 FM 包装器
vendor/ 第三方 / 许可二进制文件
nwrfcsdk/ SAP NW RFC SDK(捆绑,自动检测)
pyrfc-3.3.1-*.whl 预构建的 pyrfc 轮子(离线安装)
abap/ 安装到 SAP 系统的 ABAP(可重用)
README.md 安装指南 + FM 接口
zmcp_adt_dispatch.abap ZMCP_ADT_DISPATCH(屏幕,语法,激活,...)
zmcp_adt_textpool.abap ZMCP_ADT_TEXTPOOL(文本元素)
```
## 通过 git 部署(克隆并运行)
此存储库适用于 **私有** git 远程:SAP NW RFC SDK(`mcp/vendor/nwrfcsdk`)和 pyrfc 轮子已提交,因此新的克隆运行无需任何 SAP 门户下载。**不** 提交秘密 - `.env` 和 `mcp/profiles/*.env` 被 git 忽略;每个机器在本地填写它们。
### 首次推送(一次,从此文件夹)
```powershell
git init
git add .
git commit -m "SAP MCP-RFC 桥接器"
git remote add origin https://github.com/ChinhHN-DEV/MCP_SAP_PRIVATE.git
git push -u origin main
```
> 提交包括约 60 MB 的 SDK。保持远程 **私有** - SDK 已获得许可,不得公开。
### 在新机器上(一条命令)
编辑 `REPO=` 行到 **`bootstrap.bat`**,复制该文件到新机器并运行它(或 `bootstrap.bat <git-url>`)。它克隆存储库并运行 `setup.ps1`。之后,创建您的连接配置文件:
```powershell
# 单个系统:
复制 mcp\.env.example mcp\.env # 然后编辑
# 或多系统:
复制 mcp\profiles\ds4.env.example mcp\profiles\ds4.env # 然后编辑,重新运行 setup.ps1
```
## 在新机器上快速安装
复制整个文件夹,然后从内部运行 **一个** 命令:
```powershell
# Windows (PowerShell)
powershell -ExecutionPolicy Bypass -File .\setup.ps1
```
… 或直接双击 `setup.bat`。
`setup.ps1` 查找 Python,安装 `python-dotenv` + `mcp`,安装匹配的 `pyrfc` 轮子(来自 `vendor/` 或下载正确的轮子),验证捆绑的 SDK,创建 `.env` 从模板,并使用此文件夹的当前绝对路径注册 `sap-rfc` MCP 服务器与 Claude Code - 因此无论文件夹移动到哪里,它都有效。之后只需编辑 `.env` 并运行 `python mcp\test_connection.py`。手动步骤下面相同。
## 多个 SAP 系统
为每个系统运行一个 MCP 服务器,每个系统由 **配置文件** 文件选择。Claude Code 然后看到单独的、命名空间的工具集(`mcp__sap-ds4__…`、`mcp__sap-qa4__…`)并通过服务器名称选择正确的系统。
1. 将每个系统的登录信息放在 `mcp/profiles/<name>.env`(复制 `mcp/profiles/ds4.env.example`):
```
profiles/ds4.env # DEV,SAP_ALLOW_WRITE=true
profiles/qa4.env # QA, 只读
profiles/prd.env # PROD, 只读
```
共享策略(`SAP_TABLE_BLOCKLIST`、`SAP_FM_DENYLIST` 等)保留在基本 `.env` 中;每个配置文件 **覆盖** 基本配置文件并包含该系统的凭证 + `SAP_ALLOW_WRITE`。
2. 运行 `setup.ps1` - 它为每个配置文件注册一个服务器 `sap-<name>`(如果没有配置文件,则回落到 `.env` 中的单个 `sap-rfc`)。
3. 测试特定系统:
```powershell
python mcp\test_connection.py --profile qa4
```
配置文件优先级:`--env-file <path>` > `--profile <name>` > `SAP_PROFILE` 环境变量 > 基本 `.env`。`sap_ping` 报告哪个配置文件已回答。
保持 DEV 可写,QA/PROD 只读(`SAP_ALLOW_WRITE=false`),以便自动区分系统。
## 设置(手动)
### 1. SAP NW RFC SDK(pyrfc 的先决条件)
`pyrfc` 包装 **SAP NetWeaver RFC SDK**(从 SAP 支持门户获得许可)。此存储库在 `mcp/vendor/nwrfcsdk` 中捆绑 **Windows** SDK,运行时自动检测并注册(通过 `os.add_dll_directory`)。无需编辑 PATH。要使用不同的 SDK 位置,请设置 `SAPNWRFC_HOME` - 它优先于捆绑的副本。
#### SDK 的 OS 运行时先决条件(SAP 注意 2573790)
NW RFC SDK DLL 需要 **Microsoft Visual C++ 2015-2022 Redistributable x64**(`vcruntime140.dll`)存在 - 没有它,`import pyrfc` 将失败并出现神秘的加载错误。`setup.ps1` 警告并链接安装程序,如果它丢失。
### 2. 安装 Python 依赖项
`pyrfc` 没有适用于最新 Python 的 PyPI 轮子,因此在 `mcp/vendor/` 中提供匹配的预构建轮子:
```powershell
python -m pip install python-dotenv mcp
python -m pip install mcp/vendor/pyrfc-3.3.1-cp312-cp312-win_amd64.whl
```
轮子是 `cp312 / win_amd64`(Python 3.12,Windows 64 位),来自 `SAP-archive/PyRFC` GitHub 版本。对于不同的 Python 版本,从那里获取匹配的轮子。
### 3. 配置连接
```powershell
复制-Item mcp\.env.example mcp\.env
# 然后编辑 .env
```
SAProuter 示例 - 将完整的路由放入 `SAP_ASHOST`:
```
SAP_ASHOST=/H/saprouter.example.com/S/3299/H/sapappserver.internal
SAP_SYSNR=00
```
… 或保留纯主机并单独设置路由器前缀:
```
SAP_ASHOST=sapappserver.internal
SAP_SYSNR=00
SAP_SAPROUTER=/H/saprouter.example.com/S/3299
```
### 4. 测试连接性(不需要 MCP)
```powershell
python mcp\test_connection.py
```
### 5. 将服务器注册到 Claude Code
```powershell
claude mcp add sap-rfc -- python "c:\Users\Administrator\Desktop\MCP_SAP_PRIVATE\mcp\server.py"
```
或添加到您的 MCP 客户端配置文件:
```json
{
"mcpServers": {
"sap-rfc": {
"command": "python",
"args": ["c:\\Users\\Administrator\\Desktop\\MCP_SAP_PRIVATE\\mcp\\server.py"]
}
}
}
```
## 安全
* **默认只读。** 保持 `SAP_ALLOW_WRITE=false` 除非您打算修改对象,并且仅在 **DEV** 系统上启用写入。
* 写入被保存为 **INACTIVE** - 写入生效前必须在 SAP 中激活。
* 使用具有 **最低** 授权要求的 RFC 用户。
* `.env` 包含凭证 - 它被 git 忽略;永远不要提交它。
## 验证
读取工具(`sap_ping`、`sap_read_table`、`sap_read_program`、`sap_read_function_module`、`sap_read_class`、`sap_search_objects`)已针对通过 SAProuter 访问的 **S/4HANA 系统(SAP_BASIS 758)** 进行端到端验证。类源使用远程启用的 `SIW_RFC_READ_CLIF_SOURCE`。
## 与纯 RFC 相比的限制
* 只有 **远程启用** 的函数模块可以通过 RFC 调用。许多工作台 FM(例如 `SEO_*` 类 API,ABAP `SYNTAX-CHECK`)**不是** RFC 启用的,因此一些 ADT 样式的功能根本无法通过这种方式访问。
* **CDS/DDL 源读取在测试系统上不可用** 通过纯 RFC - 没有返回 DDL 源文本的远程启用 FM。使用 ADT 进行此操作。
* **对象激活和语法检查** 同样未连接:没有干净的远程启用 FM 被发现在测试版本上。因此,写入始终保持 **INACTIVE**;在 SAP GUI/ADT 中激活。
* `RFC_READ_TABLE` 无法选择行宽超过 512 字节或长/深字段;长 WHERE 子句自动包装到 72 字符的 OPTIONS 行限制。
* FM 可用性/接口仍然可以按版本变化 - 在目标上验证。