mcpField
G
GuniWeb SAP MCP

GuniWeb SAP MCP

本地服务
github.com商业与营销32 周前更新

关于 GuniWeb SAP MCP

GuniWeb SAP MCP 是供 n8n 工作流及其他 MCP 客户端使用的 SAP S/4HANA 和 ECC 服务,可通过 OData、IDoc 与 RFC/BAPI 操作 SAP。它采用人工治理的工作流设计,写操作默认关闭,并支持按服务器和令牌限制权限。

主要功能

  1. 01支持 OData V2/V4 操作
  2. 02发送和接收 IDoc
  3. 03通过 RFC/BAPI 调用 SAP
  4. 04发现服务并渐进读取元数据
  5. 05写操作默认关闭并支持权限限制

适用场景

  1. 01在 n8n 工作流中查询 SAP 数据
  2. 02通过 OData 创建或更新业务记录
  3. 03在配置的 SAP 系统间选择目标并限制访问

MCP 相关

该 MCP 服务将 SAP S/4HANA 和 ECC 的 OData、IDoc 及 RFC/BAPI 能力开放为工具,供 n8n 和其他 MCP 客户端调用。支持 stdio 与 Streamable HTTP 传输。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"guniweb-guniweb-sap": {
"command": "npx",
"args": [
"-y",
"guniweb-sap-mcp"
],
"env": {
"SAP_BASE_URL": "<SAP_BASE_URL>",
"SAP_AUTH_TYPE": "<SAP_AUTH_TYPE>",
"SAP_CLIENT": "<SAP_CLIENT>",
"SAP_USERNAME": "<SAP_USERNAME>",
"SAP_PASSWORD": "<SAP_PASSWORD>",
"SAP_MCP_DEMO": "<SAP_MCP_DEMO>"
}
}
}
}
启动命令npx -y guniweb-sap-mcp
需要配置的环境变量
SAP_BASE_URLBase URL of the SAP system, including any path segment in front of /sap/opu/odata (e.g. https://s4.example.com or https://gateway.example.com/prefix)
SAP_AUTH_TYPE密钥Authentication type: basic, oauth2, apikey, ias, xsuaa, btp-principal, saml-bearer
SAP_CLIENTSAP client (Mandant). Appended to every request — a client-dependent Gateway answers 401 without it
SAP_USERNAMESAP user for basic authentication
SAP_PASSWORD密钥Password for basic authentication
SAP_MCP_DEMOSet to true to start a built-in mock S/4HANA instead of connecting to a real system. No SAP_* configuration needed — for trying the server out

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
npmguniweb-sap-mcp0.10.0

工具

还没有获取到工具列表

本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。

详细介绍

GuniWeb SAP S/4HANA 与 ECC MCP 服务

专为 n8n 设计,可在任何 MCP 宿主中使用。免费使用,由 GuniWeb 构建并维护。

通过模型上下文协议(MCP),使用 OData V2、V4、IDoc 和 RFC/BAPI 将 n8n 工作流连接到 SAP S/4HANA 和 ECC。专为AI 辅助、人工治理的工作流打造:工作流作者决定调用哪些 SAP API 以及调用顺序;大模型负责提取、映射和填充参数。默认禁用写入功能,只有针对每个服务和令牌明确启用后才会开启。

graph LR
    n8n["n8n workflow<br/>AI-assisted, human-governed"] -->|MCP Protocol| MCP["guniweb-sap-mcp<br/>22 Tools &bull; 8 Auth Types"]
    MCP -->|"OData V2/V4<br/>IDoc XML<br/>RFC/BAPI"| SAP["SAP S/4HANA & ECC"]
    MCP -->|"OAuth2 / JWT"| BTP["SAP BTP"]
    BTP --> SAP

    style n8n fill:#4a90d9,color:#fff,stroke:#3a7bc8
    style MCP fill:#2d2d2d,color:#fff,stroke:#555
    style SAP fill:#1a6fb5,color:#fff,stroke:#0f5a9d
    style BTP fill:#e8a317,color:#fff,stroke:#c88d14

功能

OData 与 IDoc
  • OData V2 + V4 CRUD —— 使用自动版本检测进行读取、查询、创建、更新和删除
  • 深度插入 —— 在一个请求中创建父实体及子实体
  • Function Imports(V2)与 Actions/Functions(V4) —— 触发 SAP 业务逻辑
  • 批量操作 —— 在单个 $batch 请求中执行多个操作
  • 自然语言转 OData 查询 —— 将自然语言查询转换为结构化 OData 筛选条件
  • IDoc 发送与接收 —— 基于 HTTP/XML,无需依赖 RFC
发现与智能
  • 服务发现 —— 自动发现 OData 服务,包含 16 个业务领域类别
  • 渐进式元数据 —— 服务目录 -> 实体集 -> 属性 -> 查询
  • 智能查询路由 —— 基于领域的路由资源,用于大模型选择工具
  • 决策树式工具描述 —— 通过“适用场景 / 不适用场景”说明引导大模型
受治理的工具可见性
  • 四级工具注册表 —— Core / OData / IDoc / RFC 层级,按需启用
  • sap_enable_tools —— 大模型可在运行时启用其他工具层级,但受你设置的限制
  • 默认只读(自 0.2.2 起) —— 写入工具需要 --allow-write
  • 按令牌策略(0.3.0) —— 每个 Bearer 令牌均可设置 readOnly 和工具层级上限,且只会进一步收紧限制
  • IDoc / RFC 自动禁用 —— 缺少相应配置时隐藏对应工具
  • MCP 注释 —— 全部 22 个工具均带有 readOnlyHint、destructiveHint 和 idempotentHint
身份验证(8 种类型)
graph TB
    subgraph Technical["Technical User Auth"]
        basic["basic<br/><i>Direct S/4HANA</i>"]
        userbasic["user-basic<br/><i>Personal SAP login per request</i>"]
        oauth2["oauth2<br/><i>BTP Client Credentials</i>"]
        apikey["apikey<br/><i>Sandbox / Testing</i>"]
    end
    subgraph Enterprise["Enterprise Auth (OIDC)"]
        ias["ias<br/><i>SAP IAS Token</i>"]
        xsuaa["xsuaa<br/><i>SAP XSUAA Token</i>"]
    end
    subgraph Principal["Principal Propagation<br/><i>End-user identity forwarded to SAP</i>"]
        btp["btp-principal<br/><i>JWT Bearer Exchange<br/>via Destination Service</i>"]
        saml["saml-bearer<br/><i>SAML 2.0 Assertion<br/>+ RSA-SHA256 Signing</i>"]
    end

    style Technical fill:#2a5f8f,color:#fff,stroke:#1a4f7f
    style Enterprise fill:#5b8c5a,color:#fff,stroke:#4b7c4a
    style Principal fill:#8b5e3c,color:#fff,stroke:#7b4e2c
基础设施
  • 两种传输模式 —— stdio 和 Streamable HTTP(旧版 SSE 传输已于 0.8.0 中移除)
  • 命名目标(0.3.0) —— 一个服务可连接多个 SAP 系统;每个 n8n 凭据使用一个 Bearer 令牌来选择系统及其权限。仍支持静态 API 密钥
  • 支持 Docker —— 使用 Docker Compose 部署 n8n + SAP MCP sidecar
  • 零遥测 —— 服务只会与您配置的 SAP/BTP 端点通信,不会连接其他任何地方。不收集使用统计信息,不进行更新检查,也不发送崩溃报告
  • 1267 项测试 —— 通过 GitHub Actions CI/CD 执行单元测试、集成测试和端到端测试

快速开始

无需 SAP 系统即可试用:--demo

手头没有 SAP 系统?使用内置的模拟 S/4HANA 启动服务,然后从 n8n 或任意 MCP 客户端试用所有工具:

npx guniweb-sap-mcp --demo                                   # stdio — n8n MCP Client in command mode
npx guniweb-sap-mcp --demo --transport http --port 8808      # HTTP — n8n MCP Client with URL http://localhost:8808/mcp
npx guniweb-sap-mcp --demo --allow-write                     # also try sap_create / sap_update / sap_delete / sap_batch

演示模式会在 localhost 上启动一个内存中的 OData V2 网关(包含三个使用真实 SAP 字段名称的服务——API_BUSINESS_PARTNER、API_SALES_ORDER_SRV、API_PRODUCT_SRV;约 20 个业务伙伴、15 个含行项目的销售订单、10 个产品),并将服务指向该网关。在关键功能上,它的行为与 Gateway 一致:目录发现、$metadata、$filter/$expand/分页、CSRF 令牌、ETag、深度插入、函数导入、带有更改集的 $batch、SAP 风格的错误负载。只有示例数据——数据并非真实数据,不会离开你的机器;进程结束后,所有更改都会消失。也可使用 SAP_MCP_DEMO=true(例如在 Docker 中)。使用演示环境构建的工作流,在将 --demo 替换为你的 SAP_* 配置后即可用于真实系统。

1. 安装
npm install -g guniweb-sap-mcp

或者将其作为容器运行:docker run --rm -p 8808:8808 -e SAP_MCP_DEMO=true ghcr.io/guniweb/guniweb-sap-mcp:latest

2. 配置
export SAP_BASE_URL=https://your-sap-system.example.com
export SAP_AUTH_TYPE=basic
export SAP_USERNAME=your-user
export SAP_PASSWORD=your-password
export SAP_CLIENT=100   # do not omit: without it a client-dependent Gateway
                        # answers 401 "Anmeldung fehlgeschlagen", which looks
                        # like a wrong password but is not one
3. 运行
# stdio (default) -- for n8n MCP Client in command mode
guniweb-sap-mcp

# HTTP -- for n8n MCP Client in URL mode or Docker
guniweb-sap-mcp --transport http --port 8808

# With tool tier control
guniweb-sap-mcp --transport http --port 8808 --tiers core,odata
guniweb-sap-mcp --transport http --port 8808 --allow-write   # writes are OFF by default

# Production: authenticate the MCP endpoint AND the inbound IDoc webhook
guniweb-sap-mcp --transport http --port 8808 --api-key <mcp-key> --webhook-secret <idoc-secret>
作为容器运行
# Look around first — mock S/4HANA inside the container, no SAP system needed
docker run --rm -p 8808:8808 -e SAP_MCP_DEMO=true ghcr.io/guniweb/guniweb-sap-mcp:latest

# Against a real system (pin the version in production)
docker run -d --name sap-mcp -p 8808:8808 --env-file .env \
  ghcr.io/guniweb/guniweb-sap-mcp:<version>

# Flags go straight to the server — writes stay off unless you say so
docker run -d -p 8808:8808 --env-file .env \
  ghcr.io/guniweb/guniweb-sap-mcp:<version> --allow-write

此镜像基于已发布的 npm 包构建,而非通过另一条构建路径构建——容器中运行的内容,就是通过 npm install 安装的产物,因此两者不会出现偏差。镜像内默认使用 8808 端口进行 HTTP 传输(SAP_MCP_TRANSPORT / SAP_MCP_PORT);它以非 root 用户身份运行,在 /healthz 提供健康检查,并通过构建来源证明发布,支持 linux/amd64 和 linux/arm64。

不包含:RFC/BAPI。该路径需要 SAP NW RFC SDK,而 SAP 仅向客户授予该 SDK 的许可,因此无法将其打包到公开镜像中。其他功能——OData V2/V4、通过 HTTP/XML 传输的 IDoc——均可正常使用。如需使用 RFC,请在主机上安装 SDK,然后通过 npm 运行服务(SAP ECC 设置)。

仓库中提供了一个 docker-compose.yml,可将 n8n 与服务一同运行。

生产环境加固
变量 / 标志默认值描述
--tool-timeout / SAP_MCP_TOOL_TIMEOUT30(秒)单次完整工具调用的时间预算,无论它会发出多少个 SAP 请求。超时后,客户端会收到有效的 MCP 响应,其中包含 truncated: true 和通俗易懂的原因说明——连接绝不会一直挂起。分页读取会返回目前已获取的页面。0 会禁用此预算(启动时会记录警告)
SAP_HTTP_TIMEOUT_MS30000单个出站 SAP 请求的超时时间(毫秒)。网关挂起时会快速失败并返回结构化的 TIMEOUT 错误,而不会让 n8n Agent 陷入等待。超时时间受上述工具预算的剩余时长限制
--cache-dir / SAP_CACHE_DIR(未设置 = 仅保存在内存中)将目录和元数据缓存持久化到磁盘,避免重启后重新获取。未设置时,每次重启都会重新读取完整目录——对于拥有一千多个服务的系统,这种冷启动会导致客户端超时。n8n 会在传输错误时清除自己的客户端条目,因此重启并不少见
SAP_CA_CERT(未设置)为你的 SAP 证书签名的根 CA 的路径——这是文档中提供的绕过企业 PKI 问题的方法。此证书会同步到 NODE_EXTRA_CA_CERTS。建议使用此设置,而不是 SAP_TLS_VERIFY=false;后者会禁用检查,而非解决问题
--concurrency / SAP_CONCURRENCY5在无法避免多个 SAP 请求时,限制同时发出的请求数
--allow-write / SAP_MCP_ALLOW_WRITE(未设置 = 只读)从 0.2.2 起,服务默认只读。 在设置此选项之前,不会注册 sap_create、sap_update、sap_delete、sap_function 和 sap_idoc_send;Agent 看不到的工具,就不会意外调用。仍接受 --read-only,现在它只是描述默认行为
SAP_JWT_ISSUER(未设置 = 不验证)用于验证传入用户令牌的 JWKS 签发者。未设置时,令牌只会被解码,生成的身份会标记为 verified: false——将其转发给 SAP 是安全的(SAP 会自行验证),但不能据此做本地决策。设置后,验证失败的令牌会被拒绝并返回 401,而不会静默降级为技术用户
SAP_WEBHOOK_SECRET / --webhook-secret(未设置 = 公开访问 + 启动时警告)入站 IDoc Webhook 的共享密钥。接受 Authorization: Bearer <secret> 或 HTTP Basic 身份验证(其密码必须与密钥相同;这与 SAP SM59 HTTP 目标匹配)
SAP_WEBHOOK_HOST / --webhook-host所有接口独立 IDoc Webhook(stdio 模式)的绑定地址。使用反向代理时请设置为 127.0.0.1
SAP_WEBHOOK_MAX_BODY_BYTES10485760(10 MB)IDoc 负载超出此大小时,在将其缓冲到内存之前返回 413

在 HTTP 传输模式下,/idoc 路由挂载在 MCP 端口上:设置了 --webhook-secret 时,该路由会独立于 --api-key 进行身份验证(因此 SAP 可以使用 Basic 身份验证,而 n8n 使用 Bearer 密钥);未设置时,若配置了 --api-key,该路由会受其保护——若两者都未配置,则该路由公开访问(服务会在启动时记录警告)。

两项超时都必须低于你所用设置中最短的客户端限制。常见限制:Cloudflare 等反向代理会在 100 秒时中止(524),n8n 的 MCP 客户端传输限制为 300 秒。若预算高于最短限制,它永远不会生效,因为客户端会先放弃。

跟踪缓慢的工具调用

每次工具调用完成时都会记录一行日志,其中包含一个关联 ID;该 ID 也会出现在它触发的每个 SAP 请求中:

{"correlationId":"a3f19c8b2d04","tool":"sap_discover_services","outcome":"ok","durationMs":842,"sapCalls":1,"resultBytes":18422}

然后运行 grep a3f19c8b2d04,即可查看这次调用的完整情况,包括它产生了多少个 SAP 请求。outcome 的值可以是 ok、error、timeout(超出预算)或 aborted(客户端断开连接)。

随请求发送 W3C traceparent 标头,其跟踪 ID 会以 traceId 的形式出现在同一行日志中,这样便可从调用应用程序,经由 n8n,一直跟踪到 SAP 请求。该标头只会记录到日志中。无效的标头会被忽略,也永远不会转发给 SAP(详情)。

level: 50 表示确实出了问题。 预期的非 2xx 响应——来自目录路径探测的 404,以及系统不支持 V4 目录时的 V4 目录尝试所返回的 404——会以 info 级别记录,并带有 "expected": true,而不是以 error 级别记录。在生产系统上的测量结果显示:运行 96 小时以上后,日志中唯一一条 error 级别记录就是这条误报。因此,对 level: 50 设置告警是有意义的;以前,这种告警只会带来噪声。

出现故障时

test-connection 会遍历整个链路,并报告第一个失败的阶段——DNS、TLS(包括证书链)、身份验证、客户端(Mandant)和目录。失败之后的阶段会标记为 skipped,绝不会报告为通过。相同的五个阶段也会在启动时记录一次,因此容器日志无需调用任何内容,就能显示连接状态。

每个错误响应都包含错误分类(如有,则包括 SAP 错误代码)、通俗易懂的说明和后续操作——没有任何工具会返回 "Unknown error"。以下三种情况过去都需要单独诊断:

SAP 返回的内容服务端告知你的内容
403,带有 /IWFND/MED/170服务尚未注册——请在 /IWFND/MAINT_SERVICE 中激活。这不是授权问题,尽管返回了 403
401,附带 HTML 登录页面是否设置了 sap-client?如果没有,依赖客户端的 Gateway 会以看似密码错误的方式拒绝登录
UNABLE_TO_GET_ISSUER_CERT_LOCALLY证书链不完整;请通过 SAP_CA_CERT 提供根 CA。错误说明中会指出颁发 CA

如果启用了 SAP_TLS_VERIFY=false,每个工具结果都会附带相关警告,而不只是启动日志。在第一天之后就没人注意到的禁用检查,往往会一直保留数年;促使我们开展这项工作的生产系统就设置了这一选项,却一直没人发现。

Streamable HTTP 是无状态的

--transport http 以无状态模式提供 MCP 服务:每个请求都是独立的,服务端既不会发出,也不会要求提供 mcp-session-id 标头。服务端没有可恢复的会话,因此客户端随时都可以重新连接,而不会丢失状态。

必须使用会话 ID 的客户端——它们会从初始化响应中读取 mcp-session-id,并在后续请求中发送该 ID——无法与此服务配合使用。n8n MCP Client、Claude Desktop 和 MCP Inspector 均可在不使用会话 ID 的情况下正常工作。

旧版 --transport sse 模式已在 0.8.0 中移除;请使用 http。

多个 SAP 系统:destinations.json

SAP_* 变量描述的是一个 SAP 系统。若要让一个服务连接多个系统——例如在生产系统旁运行一个测试客户端,或让一个 n8n 连接多个客户的系统——请将连接信息放入 destinations.json,并让服务指向该文件:

guniweb-sap-mcp --transport http --port 8808 --destinations /config/destinations.json
# or: SAP_MCP_DESTINATIONS=/config/destinations.json
{
  "version": 1,
  "destinations": {
    "default": {
      "baseUrl": "https://s4prod.example.com",
      "authType": "basic",
      "username": "MCP_USER",
      "password": "${S4PROD_PASSWORD}",
      "sapClient": "100"
    },
    "s4test": {
      "baseUrl": "https://s4test.example.com",
      "authType": "basic",
      "username": "MCP_USER",
      "password": "${S4TEST_PASSWORD}",
      "sapClient": "200"
    }
  }
}
  • 一条目 = 一个连接。 每个条目接受的字段与 SAP_* 变量完全相同(authType 及其凭据、sapClient、baseUrl)——每个目标都支持所有身份验证类型。
  • 每个请求使用个人 SAP 登录信息——"authType": "user-basic":目标仅记录系统和客户端信息;每个请求都会附带 SAP 用户名和密码(X-SAP-Username/X-SAP-Password;在 n8n 中使用 GuniWeb SAP 节点的凭据)。每个人在 SAP 中都以自己的身份操作——授权、变更文档和审计跟踪记录的都是真实用户,不会共用技术账号。没有技术用户回退机制(未提供登录信息时返回 401),缓存按用户隔离,密码绝不会写入日志。仅支持 HTTP 传输。详情请参阅设置指南。
  • 机密信息不会写入文件。 任何字符串都可以包含 ${VARIABLE};加载时会从环境中解析该变量(Docker secrets、.env)。无法解析占位符会导致文件无效——否则,空密码会引发来自 SAP 的误导性 401 错误。
  • 热重载。 文件会受到监视;文件变更会在下一个请求时生效,无需重启。执行 kill -HUP <pid> 可强制重新加载。无效文件绝不会替换正在运行的配置——错误会写入日志,最后一份有效配置继续生效。
  • 向后兼容。 不使用 --destinations 时,行为不变:SAP_* 变量构成唯一目标 default。使用该文件时,如果文件未定义 default,则会将已设置的 SAP_* 变量添加为 default——因此安装迁移过程不会出现中断。
  • 由哪个目标响应? 不带令牌时,使用名为 default 的目标(或唯一目标)。带令牌时,使用令牌指定的目标——见下文。

令牌:每个 n8n 凭据使用一个 Bearer 值来选择系统。 n8n MCP Client 只发送一个 Authorization 标头,因此令牌可同时完成两项工作——验证请求并选择目标。SAP 密码不会离开服务端;n8n 只保存令牌。

{
  "version": 1,
  "destinations": { "s4prod": { "...": "..." }, "s4test": { "...": "..." } },
  "tokens": [
    { "hash": "sha256:9f2c…", "destination": "s4prod", "label": "n8n prod workflows" },
    { "hash": "sha256:1a7e…", "destination": "s4test", "label": "n8n dev", "revoked": false }
  ]
}
  • 文件中只保存 SHA-256 哈希值;明文令牌(gsm_<destination>_<random>)由 tokens issue 仅打印一次,之后无法找回。将它填入 MCP Client 节点的 n8n Bearer Auth 凭据中。一旦至少存在一个令牌,不带有效令牌的请求就会收到 401——--api-key 仍可同时使用,并服务于 default 目标。
  • 对所有条目进行恒定时间查找;"revoked": true 会在下一个请求时停用令牌(热重载,无需重启)。一分钟内失败 10 次后,客户端地址会收到带有 Retry-After 的 429——有效令牌也不例外,以此抑制猜测(反向代理才是实施实际速率限制的合适位置)。令牌绝不会写入日志;拒绝请求时会记录地址和原因。 管理文件——无需手动编辑。 同一个二进制文件包含管理命令;每条命令在写入前都会像服务端一样验证结果(绝不会留下无法加载的文件),以原子方式写入,正在运行的服务会在下一个请求时应用变更:
export SAP_MCP_DESTINATIONS=/config/destinations.json      # or --destinations <path> on each call

guniweb-sap-mcp destinations add s4prod --base-url https://s4prod.example.com --auth-type basic \
    --username MCP_USER --password '${S4PROD_PASSWORD}' --sap-client 100
guniweb-sap-mcp destinations add legacy --from-env         # copy the current SAP_* environment (migration)
guniweb-sap-mcp destinations list                          # names, URLs, auth type, client, token count — never secrets

guniweb-sap-mcp tokens issue s4prod --label "n8n prod" --read-only --tiers core,odata
#   → prints the plain token ONCE on stdout (everything else goes to stderr, so TOKEN=$(…) works)
guniweb-sap-mcp tokens list                                # label, destination, hash prefix, policy, status
guniweb-sap-mcp tokens revoke "n8n prod"                   # by label or ≥ 8 hex chars of the hash
guniweb-sap-mcp destinations remove s4test [--force]       # refuses while tokens point at it, unless --force

--set field=value 支持任何身份验证类型(--auth-type oauth2 --set clientId=… --set clientSecret='${BTP_SECRET}' --set tokenServiceUrl=…);${ENV_VAR} 值会根据当前环境进行检查(可使用 --allow-missing-env 跳过,例如变量只存在于容器内部时)。在 Docker 中,请在容器内运行这些命令,以确保它们访问相同的文件和环境:docker compose exec sap-mcp guniweb-sap-mcp tokens issue s4prod。

  • 每个令牌的权限 — "policy": { "readOnly": true, "tiers": ["core", "odata"] }。策略只会限制权限:即使服务以 --allow-write 运行,readOnly: true 也会隐藏该令牌的写入工具(readOnly: false 无法解除只读服务的限制);tiers 则是上限——该令牌看不到范围以外的层级,sap_enable_tools 也无法启用这些层级。tools/list 会针对每个请求进行筛选,因此只读令牌的 Agent 根本不会看到 sap_create。

  • 按令牌和目标分别设置速率限制 — 适用于循环调用的 AI Agent,也能避免超出 SAP API 配额。在令牌的 policy 中设置 "rateLimit": { "requestsPerMinute": 60, "maxConcurrent": 4 } 可限制该令牌;在目标中设置同一对象,则会限制所有调用者对该 SAP 系统的总调用量。只有工具调用会计入限制(tools/list 不收费);超出限制时,服务会返回 429 和 Retry-After,并提示触发的限制。达到 maxConcurrent 时,调用会先在 FIFO 队列中等待空闲时段,最长等待 --rate-limit-max-wait 秒(默认值为 60,0 = 立即返回 429);等待期间断开连接的调用者会离开队列。requestsPerMinute 不会触发等待。默认不设置任何限制。仅支持 HTTP 传输。无需手动编辑即可设置:guniweb-sap-mcp tokens limit "n8n agent" --rate-per-minute 60、guniweb-sap-mcp destinations limit s4prod --max-concurrent 4(--clear 可移除限制),或在 tokens issue 中使用 --rate-per-minute/--max-concurrent。

管理 API——通过 HTTP 执行相同操作(自助服务)。 使用 --admin-token <secret>(或 SAP_MCP_ADMIN_TOKEN,至少 16 个字符,例如 openssl rand -base64 32)后,服务会在 /admin 下提供 CLI 的各项操作,方便通过 n8n 工作流为新客户开通访问权限、运行脚本或供人员使用 curl 操作,无需登录主机 Shell:

guniweb-sap-mcp --transport http --port 8808 --destinations /config/destinations.json --admin-token "$ADMIN"

A="Authorization: Bearer $ADMIN"; J="Content-Type: application/json"; U=http://localhost:8808/admin
curl -H "$A" $U/destinations                                    # list — never secrets
curl -H "$A" -H "$J" -X PUT $U/destinations/s4prod \           # create (201) or replace (200)
     -d '{"baseUrl":"https://s4prod.example.com","authType":"basic","username":"MCP_USER","password":"${S4PROD_PASSWORD}","sapClient":"100"}'
curl -H "$A" -H "$J" -X POST $U/tokens \                       # → { "token": "gsm_s4prod_…", … } — shown ONCE
     -d '{"destination":"s4prod","label":"n8n prod","readOnly":true,"tiers":["core","odata"]}'
curl -H "$A" $U/tokens                                          # label, destination, hash prefix, policy, status
curl -H "$A" -X DELETE "$U/tokens/n8n%20prod"                   # revoke by label or hash prefix
curl -H "$A" -X DELETE "$U/destinations/s4test?force=true"      # remove; without force it refuses while tokens exist
  • 密钥分开,入口也分开。 管理密钥只能访问 /admin;n8n 令牌和 --api-key 只能访问 /mcp。泄露的 n8n 令牌无法创建更多访问权限,管理密钥也无法读取 SAP 数据。错误密钥会按客户端地址计数(每分钟失败 10 次后返回 429);每次变更都会记录操作、目标和客户端地址——绝不记录令牌或密钥。未设置 --admin-token 时,/admin/* 会返回 404。
  • 立即生效。 每次写入都会像 CLI 一样进行验证,以原子方式写入,并在响应前重新加载运行中的配置("reloaded": true)。如果服务无法加载已写入的内容——通常是因为写入了只有你的 Shell 才知道的 ${VAR},且使用了 ?allowMissingEnv=true——响应会显示 "reloaded": false 及错误信息,并继续使用上一次有效配置。
  • 无需 SAP 配置即可启动。 设置 --admin-token 后,即使 destinations.json 尚不存在且未设置任何 SAP_*,服务也会启动:创建第一个目标(以及令牌,或名为 default 的目标)之前,/mcp 会返回 503。docker run … -e SAP_MCP_ADMIN_TOKEN=… -e SAP_MCP_DESTINATIONS=/config/destinations.json 即可完成首次启动。
  • 将 API 放在与 /mcp 相同的反向代理/TLS 后面;管理密钥与其他凭据一样,通过 Bearer 请求头传递。

轮换令牌和 SAP 密码——逐步说明哪些操作需要重启、哪些不需要:设置指南 → 轮换凭据。

4. 与 n8n 搭配使用
  1. 添加一个 AI Agent 节点,并为其添加一个 MCP Client Tool 子节点
  2. 将 MCP Client URL 设置为 http://sap-mcp:8808/mcp(Docker)或 http://localhost:8808/mcp,并配置一个包含 API 密钥或目标令牌的 Bearer Auth 凭据
  3. AI Agent 节点会自动发现 SAP 工具。它能看到哪些工具由你决定,而不是由模型决定:默认仅提供只读工具,只有使用 --allow-write 才会提供写入工具,单令牌策略还可以进一步限制工具。请将工作流设计为由人工编写的确定性流程——LLM 负责填入参数

SAP ECC 设置

ECC NetWeaver 后端需要在快速入门之外进行额外设置。MCP 服务支持 ECC 6.0+(EHP 7+)的 OData V2、OData V4、IDoc HTTP/XML 和 RFC/BAPI。仅使用云端 S/4HANA 租户时,无需参阅本节。

1. 激活 NetWeaver Gateway

在事务代码 SICF 中,激活 /sap/opu/odata/ 下的标准 ICF 服务。然后使用事务代码 /IWFND/MAINT_SERVICE 注册你想公开的 OData 服务。

MCP 服务的目录自动发现会依次探测三个路径,并缓存首个返回 200 的路径:

  • /sap/opu/odata/IWFND/CATALOGSERVICE;v=2/ServiceCollection(S/4HANA 默认路径)
  • /sap/opu/odata/iwfnd/CATALOGSERVICE;v=2/ServiceCollection(ECC 小写路径)
  • /sap/opu/odata/IWFND/CATALOGSERVICE/ServiceCollection(ECC EHP 7 v=1)

如果网关使用非标准挂载路径,可通过 ODATA_V2_CATALOG_PATH 覆盖。

2. 安装 SAP NW RFC SDK(仅适用于 RFC/BAPI 工具)

rfc 工具层需要此 SDK。如果你只使用 OData 或 IDoc,可跳过此步骤。

Linux:

tar xzf nwrfcsdk_linux.tgz -C /usr/sap/
export LD_LIBRARY_PATH=/usr/sap/nwrfcsdk/lib:$LD_LIBRARY_PATH
npm install node-rfc

macOS:

tar xzf nwrfcsdk_darwin.tgz -C /usr/sap/
export DYLD_LIBRARY_PATH=/usr/sap/nwrfcsdk/lib:$DYLD_LIBRARY_PATH
npm install node-rfc

node-rfc 声明为 optionalDependencies——如果缺少 SDK,服务会在启动时记录一条 Pino 警告,并跳过 RFC 工具层。OData 和 IDoc 工具仍可正常使用。

3. ECC 专用环境变量

除快速入门中记录的变量外:

变量必需描述
ODATA_V2_CATALOG_PATH否(自动发现)覆盖目录路径,例如 /sap/opu/odata/iwfnd/CATALOGSERVICE;v=2/ServiceCollection
SAP_TLS_VERIFY否(默认为 true)在使用自签名证书的 ECC 场景中,设为 false 可禁用 TLS 证书验证
SAP_CLIENT_CERT_PATH用于 X.509 客户端证书PEM 编码的客户端证书路径,例如 /etc/sap/client.crt
SAP_CLIENT_KEY_PATH用于 X.509 客户端证书PEM 编码的私钥路径(可通过提示词提供密码)
SAP_SNC_QOP用于 SNC(RFC)SNC 保护质量级别:1(仅身份验证)、2(完整性)、3/8/9(加密)
SAP_SNC_MYNAME用于 SNC(RFC)本地 SNC 名称,例如 p:CN=mcp-server, O=GuniWeb
SAP_SNC_PARTNERNAME用于 SNC(RFC)后端 SNC 名称,例如 p:CN=SAPSERVER, O=ACME
SAP_SNC_LIB用于 SNC(RFC)SNC 库路径(.so / .dylib / .dll),例如 /usr/sap/sapcrypto/libsapcrypto.so

可用工具(22)

核心层(始终启用)
工具描述
test-connection分阶段诊断连接(DNS → TLS → 身份验证 → 客户端 → 目录);指出首个失败阶段
sap_list_services列出 OData 服务中的实体集(分页,默认 50)
sap_discover_services按类别筛选和搜索,发现所有服务
sap_get_metadata检查实体类型、属性、键,以及 SAP 对每个实体集允许的操作(创建/更新/删除)
OData 层(默认启用)
工具描述
sap_read读取单个实体或实体集合
sap_query使用 OData $filter、$select、$expand 和分页进行查询(默认 top 为 50)
sap_nl_query使用结构化筛选条件进行自然语言查询
sap_create创建实体(支持深层插入和草稿服务)
sap_update更新实体(自动处理 ETag)
sap_delete删除实体(自动处理 ETag)
sap_function调用 V2 函数导入或 V4 操作/函数
sap_batch在单个批处理中执行多个操作
IDoc 层(通过 sap_enable_tools 按需启用)
工具描述
sap_idoc_send通过 HTTP/XML 向 SAP 发送 IDoc
sap_idoc_list_received列出通过 webhook 接收的 IDoc
sap_idoc_status检查 IDoc 处理状态
sap_idoc_discover发现可用的 IDoc 类型
RFC 层(通过 sap_enable_tools 按需启用,需要 SAP NW RFC SDK)
工具描述
sap_rfc_call使用经过 zod 验证的参数调用任意启用 RFC 的函数模块
sap_rfc_metadata获取函数模块签名(导入/导出/表/异常)
sap_bapi_call调用 BAPI,解析 BAPIRET2 返回表,并固定连接以供后续提交使用
sap_bapi_commit在固定的会话中调用 BAPI_TRANSACTION_COMMIT
sap_rfc_search_functions通过 RFC_FUNCTION_SEARCH 按名称模式查找函数模块
元工具
工具描述
sap_enable_tools在运行时启用/停用工具层

架构

graph TB
    subgraph n8n["n8n"]
        Agent["AI Agent + LLM"]
        MCPClient["MCP Client Tool"]
        Agent --> MCPClient
    end

    subgraph Server["guniweb-sap-mcp"]
        Transport["Transport<br/>stdio | HTTP"]
        UserCtx["UserContext<br/>Extraction"]
        Registry["ToolRegistryManager<br/>Core | OData | IDoc"]
        Tools["17 MCP Tools<br/>3 Resources &bull; 3 Prompts"]
        OData["ODataClient<br/>V2/V4 Auto-Detect"]
        Discovery["Service Discovery<br/>16 Domain Categories"]
        NLQuery["NL-to-OData<br/>Filter Builder"]
        HTTP["SapHttpClient<br/>CSRF &bull; Redirect &bull; Auth"]
        Auth["Auth Layer<br/>8 Auth Types"]
        Cache["Per-User Token Cache<br/>LRU &bull; SHA-256"]

        Transport --> UserCtx
        Transport --> Registry
        Registry --> Tools
        Tools --> OData
        Tools --> Discovery
        Tools --> NLQuery
        OData --> HTTP
        Discovery --> HTTP
        NLQuery --> OData
        HTTP --> Auth
        Auth --> Cache
    end

    subgraph SAP["SAP Backend"]
        S4["S/4HANA<br/>OData V2/V4"]
        IDoc["IDoc<br/>HTTP/XML"]
        BTPSuite["BTP Integration<br/>Suite"]
        DestSvc["Destination<br/>Service"]
        TokenSvc["XSUAA / IAS<br/>Token Service"]
    end

    MCPClient -->|MCP Protocol| Transport
    HTTP -->|Direct| S4
    HTTP -->|Via BTP| BTPSuite
    BTPSuite --> S4
    HTTP --> IDoc
    Auth -->|Token Exchange| DestSvc
    Auth -->|OIDC / OAuth2| TokenSvc
    DestSvc --> S4

    style n8n fill:#e8f4fd,stroke:#4a90d9
    style Server fill:#f5f5f5,stroke:#555
    style SAP fill:#e8f0fe,stroke:#1a6fb5
集成路径
graph LR
    subgraph Path1["Path 1: Direct"]
        n1["n8n"] -->|MCP| s1["MCP Server"] -->|Basic Auth| sap1["SAP S/4HANA"]
    end

    subgraph Path2["Path 2: BTP Client Credentials"]
        n2["n8n"] -->|MCP| s2["MCP Server"] -->|OAuth2| btp2["BTP Suite"] --> sap2["SAP S/4HANA"]
        s2 -->|CC Flow| tok2["XSUAA"]
    end

    subgraph Path3["Path 3: BTP Principal Propagation"]
        n3["n8n + JWT"] -->|MCP| s3["MCP Server"] -->|JWT Exchange| dest3["Destination Svc"] --> sap3["SAP S/4HANA"]
    end

    subgraph Path4["Path 4: SAML Bearer (no BTP)"]
        n4["n8n + JWT"] -->|MCP| s4["MCP Server"] -->|"SAML Assertion<br/>RSA-SHA256"| sap4["SAP OAuth2<br/>Endpoint"]
    end

    style Path1 fill:#e8f4fd,stroke:#4a90d9
    style Path2 fill:#fef9e7,stroke:#e8a317
    style Path3 fill:#eafaf1,stroke:#5b8c5a
    style Path4 fill:#fdf2e9,stroke:#8b5e3c
请求流程(OData 写入)
sequenceDiagram
    participant LLM as LLM (via n8n)
    participant Tool as MCP Tool
    participant Registry as ToolRegistry
    participant OData as ODataClient
    participant HTTP as SapHttpClient
    participant SAP as SAP Gateway

    LLM->>Tool: sap_create(serviceUrl, entitySet, data)
    Tool->>Registry: isToolVisible?
    Registry-->>Tool: yes
    Tool->>OData: create(entitySet, data)
    OData->>HTTP: request(POST, url, data)

    Note over HTTP,SAP: CSRF Token Fetch
    HTTP->>SAP: GET /sap/opu/odata/sap/SRV/<br/>x-csrf-token: fetch<br/>sap-client: 324
    SAP-->>HTTP: x-csrf-token: TOKEN<br/>set-cookie: SESSION

    Note over HTTP,SAP: Mutating Request
    HTTP->>SAP: POST /sap/opu/odata/sap/SRV/EntitySet<br/>x-csrf-token: TOKEN<br/>Cookie: SESSION
    SAP-->>HTTP: 201 Created + entity data

    HTTP-->>OData: response
    OData-->>Tool: created entity
    Tool-->>LLM: JSON result via MCP

支持的 SAP 系统

该 MCP 服务支持以下 SAP 后端。连接器是否可用取决于目标系统;先决条件请参阅脚注。

连接器ECC 6.0+ (EHP 7+)S/4HANA 本地部署S/4HANA Cloud(Public)
OData V2✅ 支持 1✅ 支持✅ 支持
OData V4⚠️ 部分支持 2✅ 支持✅ 支持
IDoc(HTTP/XML)✅ 支持 1✅ 支持❌ 不适用 3
RFC/BAPI✅ 支持 145✅ 支持 45❌ 不适用 3

此外,还经过了以下系统的验证:

  • SAP BTP Integration Suite(作为 S/4HANA Cloud RFC/IDoc 路径的中间层)
  • SAP API Business Hub Sandbox

文档

  • 设置指南 -- 安装、全部 8 种身份验证类型、CLI 参数、命名目标和令牌、Docker 部署
  • 架构 -- 技术架构、请求流程、设计决策
  • API 参考 -- 全部 22 个工具、资源和提示词及其参数
  • 示例 -- SAP 工作流示例及分步说明
  • SAP 接口,逐个工具介绍 -- 22 个工具分别调用哪个 SAP 端点、哪些内容受到限制、哪些数据会离开你的网络 — 适用于 Basis 团队、许可证管理员和审计人员
  • 变更日志 · 版本发布 · 问题 · 讨论

治理:如何遵循 SAP 的规则

  • 仅使用标准集成接口。 服务通过 NetWeaver Gateway 使用 OData V2/V4、通过 HTTP/XML 使用 IDoc,以及使用 RFC/BAPI —— 这些都是有文档记录且受支持的 SAP 系统接入方式(逐个工具查看清单)。不使用 UI 自动化或未记录的接口,也不批量复制 SAP 数据。内置分页限制和时间预算,避免单次工具调用演变成对 Gateway 的负载测试。
  • 写入路径受治理且可审计。 默认只读;只有显式指定 --allow-write 才会启用写入工具;各令牌策略只能施加限制,不能放宽限制;每次工具调用都会写入一条日志,并生成一个关联 ID,该 ID 也会出现在它触发的每个 SAP 请求中。这正是“由人治理”可验证的原因:决定哪些地方可以写入的是工作流作者,而不是模型。
  • 自动创建文档前,有两件事需要先确认。 SAP 的 API 使用政策包含有关自主生成式 API 使用的条款 —— 应将工作流构建为由 LLM 辅助的确定性、人工编写的步骤序列,而不是开放式自主 Agent(本服务正是为此而设计的)。此外,自动创建的业务文档(例如销售订单)可能适用你所在租户的 SAP Digital Access 许可要求 —— 上线前请与 SAP 客户团队确认。以上内容均不构成法律建议;但这两点都是审计人员会询问的问题。

背后团队以及如何获取帮助

guniweb-sap-mcp 由 GuniWeb 构建并维护。GuniWeb 是一家咨询公司,拥有自己的解决方案:让流程顺畅运作,让系统伴随您共同成长。GuniWeb 为中型企业优化业务流程,凭借 20 多年的实践经验,提供战略咨询和切实落地的实施服务,让企业不只是变得更数字化,而是运营得更好。此服务就是其中一项解决方案:它已在客户的生产环境中运行,并用于教学和研究。npm 上的编译包依据 ISC 许可证免费使用;源代码不公开。

  • 社区——可通过 Issues 和 Discussions 提出问题、报告错误和分享想法,我们会尽力回应。请参阅 SUPPORT.md。
  • 生产环境支持——维护订阅服务,提供优先修复、适配 SAP 版本变更以及直接沟通渠道;写入路径还可选择附带响应时间 SLA:guniweb.de/sap-mcp
  • SAP MCP 检查——我们会在正式上线前检查您的 n8n/SAP 配置(身份验证、治理、工具可见性、性能):guniweb.de/sap-mcp

联系方式:[email protected]。安全问题:请参阅 SECURITY.md,并留意其中关于零遥测的承诺。

技术

构建所用技术:

  • MCP TypeScript SDK v1.x
  • axios -- 处理 CSRF 和重定向的 HTTP 客户端
  • jose -- 用于 IAS/XSUAA 身份验证的 JWT/JWKS 验证
  • fast-xml-parser -- IDoc XML 和 SAML 断言构建
  • Zod v4 -- 模式验证
  • pino -- 结构化 JSON 日志记录
  • tsup -- ESM 打包
  • TypeScript 5.9、Node.js >= 22.18.0

SAP、S/4HANA、ECC、NetWeaver、ABAP 是 SAP SE 在德国及其他国家/地区的商标或注册商标。本项目与 SAP SE 无关联。

许可证

ISC

Footnotes

  1. 必须激活 NetWeaver Gateway ICF 服务(事务代码 SICF)。请参阅SAP ECC 设置。 ↩ ↩2 ↩3

  2. ECC 中的 OData V4 很少见;大多数 ECC NetWeaver Gateway 服务都使用 V2。S/4HANA 默认使用 V4。 ↩

  3. S/4HANA Cloud Public Edition 不向外部使用方开放 RFC 或传统 IDoc-HTTP。请使用 SAP BTP Integration Suite 作为中间层。 ↩ ↩2

  4. 主机上需要安装 SAP NW RFC SDK 7.50+。node-rfc 声明为 optionalDependencies;如果缺少 SDK,服务会发出启动警告并以降级模式运行。 ↩ ↩2

  5. SNC 库(SAP_SNC_LIB)因操作系统而异(.so / .dylib / .dll),必须单独安装。 ↩ ↩2

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。