mcpField
G
GuniWeb SAP MCP

GuniWeb SAP MCP

ローカル
github.comビジネス・マーケティング32 週間前に更新

GuniWeb SAP MCP について

GuniWeb SAP MCPは、OData、IDoc、RFC/BAPIを通じて、n8nのワークフローや他のMCPクライアントをSAP S/4HANAおよびECCに接続します。人が管理するワークフローを想定し、書き込みは既定で無効、サーバーやトークン単位で権限を制限できます。

主な機能

  1. 01OData V2/V4の操作
  2. 02IDocの送受信
  3. 03RFC/BAPIによるSAP呼び出し
  4. 04サービス検出と段階的なメタデータ取得
  5. 05書き込みの既定無効化と権限制御

活用シーン

  1. 01n8nワークフローからSAPデータを照会
  2. 02ODataで業務レコードを作成・更新
  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 が構築・保守しています。

Model Context Protocol(MCP)を使用して、OData V2、V4、IDoc、RFC/BAPI 経由で n8n のワークフローを SAP S/4HANA および ECC に接続します。AI が支援し、人が管理するワークフロー向けに作られています。呼び出す SAP API とその順序はワークフローの作成者が決定し、LLM はパラメーターを抽出、マッピング、入力します。書き込みはデフォルトで無効になっており、サーバーごと、トークンごとに明示的に有効化します。

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 -- バージョンの自動検出により、読み取り、クエリ、作成、更新、削除を行います
  • ディープインサート -- 1 回のリクエストで親エンティティと子エンティティを作成します
  • 関数インポート(V2)とアクション/関数(V4) -- SAP のビジネスロジックを実行します
  • バッチ操作 -- 1 つの $batch リクエストで複数の操作を行います
  • 自然言語から OData クエリへ -- 自然言語のクエリを構造化された OData フィルターに変換します
  • IDoc の送受信 -- HTTP/XML ベースで、RFC への依存はありません
検出とインテリジェンス
  • サービス検出 -- 16 のビジネスドメインカテゴリを使って OData サービスを自動検出します
  • 段階的メタデータ -- サービスカタログ -> エンティティセット -> プロパティ -> クエリ
  • スマートクエリルーティング -- LLM によるツール選択のための、ドメインベースのルーティングリソース
  • 判断ツリー形式のツール説明 -- 「使用する場合/使用しない場合」のブロックで LLM を案内します
管理されたツールの公開範囲
  • 4 階層のツールレジストリ -- Core/OData/IDoc/RFC の階層を必要に応じて有効化できます
  • sap_enable_tools -- LLM は、設定された上限の範囲内で、実行時に追加のツール階層を有効化できます
  • デフォルトで読み取り専用(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
インフラストラクチャ
  • 2 種類のトランスポートモード -- stdio と Streamable HTTP(従来の SSE トランスポートは 0.8.0 で削除されました)
  • 名前付き接続先(0.3.0) -- 1 つのサーバーで複数の SAP システムを使用できます。n8n の認証情報ごとの Bearer トークンでシステムと権限を選択します。静的 API キーも引き続きサポートされます
  • Docker 対応 -- n8n + SAP MCP サイドカー用の Docker Compose
  • テレメトリーなし -- サーバーは設定した SAP/BTP エンドポイントとのみ通信します。利用統計、更新確認、クラッシュレポートはありません
  • 1267 件のテスト -- GitHub Actions による CI/CD を用いたユニット、統合、E2E テスト

クイックスタート

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

デモでは、インメモリの OData V2 ゲートウェイを localhost で起動し(実際の SAP フィールド名を使用した 3 つのサービス — API_BUSINESS_PARTNER、API_SALES_ORDER_SRV、API_PRODUCT_SRV。ビジネスパートナー約 20 件、明細付き受注 15 件、製品 10 件)、サーバーの接続先に設定します。カタログ検出、$metadata、$filter/$expand/ページング、CSRF トークン、ETag、ディープインサート、関数インポート、変更セットを含む $batch、SAP 形式のエラーペイロードなど、必要な動作は Gateway と同様です。サンプルデータのみを使用し、実データはなく、マシンの外部にデータが送信されることもありません。変更はプロセスの終了時に失われます。Docker などでは SAP_MCP_DEMO=true も使用できます。デモ用に作成したワークフローは、--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 はこれを顧客にのみライセンスしているため、公開イメージには含められません。それ以外の OData V2/V4、HTTP/XML 経由の IDoc はすべて利用できます。RFC を使用する場合は、ホストに SDK をインストールし、npm からサーバーを実行してください(SAP ECC のセットアップ)。

サーバーと n8n を並べて起動する docker-compose.yml がリポジトリにあります。

本番環境向けの堅牢化
変数/フラグデフォルト値説明
--tool-timeout / SAP_MCP_TOOL_TIMEOUT30(秒)SAP リクエストの回数にかかわらず、ツール呼び出し全体に割り当てる時間です。期限が切れると、クライアントには truncated: true と平易な理由を含む有効な MCP レスポンスが返され、接続がハングすることはありません。ページ分割された読み取りでは、取得済みのページが返されます。0 を指定すると時間制限が無効になります(起動時に警告がログに記録されます)
SAP_HTTP_TIMEOUT_MS30000単一の SAP 送信リクエストのタイムアウト(ミリ秒)です。応答のないゲートウェイは、n8n エージェントを停止させることなく、構造化された TIMEOUT エラーですぐに失敗します。上記のツール時間制限の残り時間を上限とします
--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 は、この設定を有効にするまで登録されません。エージェントから見えないツールは、誤って呼び出されることもありません。--read-only も引き続き受け付けますが、現在はデフォルトの動作を示すだけです
SAP_JWT_ISSUER(未設定=検証なし)受信したユーザートークンの検証に使用する JWKS の発行者です。設定しない場合、トークンはデコードのみされ、生成される ID には 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 とは独立して認証されます(n8n が Bearer キーを使用している間も、SAP の Basic 認証を利用できます)。設定しない場合は、--api-key が設定されていればその認証が適用されます。どちらも設定されていなければ認証なしとなり、サーバーは起動時に警告をログに記録します。

どちらのタイムアウトも、セットアップ内で最も短いクライアント制限を下回る必要があります。一般的な制限の例:Cloudflare などのリバースプロキシは 100 秒で中断します(524)。n8n の MCP クライアントトランスポートは 300 秒です。最も短い制限を超える時間を設定しても、クライアントが先に諦めるため、効果はありません。

時間のかかるツール呼び出しのトレース

各ツール呼び出しは、完了時に1行ログを出力します。この行には相関 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 ヘッダーを送信すると、同じ行に traceId としてトレース ID が表示されます。これにより、呼び出し元アプリケーションから n8n を経由して SAP リクエストに至るまでジョブを追跡できます。このヘッダーはログに記録されるだけです。無効な値は無視され、SAP に転送されることはありません(詳細)。

level: 50 は、実際に問題が発生していることを意味します。 カタログパスの探索で発生する 404 や、V4 カタログがないシステムでの V4 カタログの試行など、想定内の非 2xx 応答は error ではなく、"expected": true とともに info でログに記録されます。本番システムでの測定では、96時間を超える稼働中に、ログに記録された error レベルのエントリは誤検知だったこの1件だけでした。そのため、level: 50 に対するアラートには意味があります。以前はノイズしか発生しませんでした。

問題が発生した場合

test-connection は接続経路全体をたどり、最初に失敗した段階を報告します。DNS、TLS(証明書チェーンを含む)、認証、クライアント(Mandant)、カタログが対象です。失敗した段階より後の段階は、成功としてではなく、skipped として報告されます。同じ5つの段階は起動時にも一度ログに記録されるため、何も呼び出さなくてもコンテナログで接続状態を確認できます。

すべてのエラー応答には、分類、該当する場合は SAP エラーコード、平易なメッセージ、次に行うべき操作が含まれます。どのツールも "Unknown error" と回答することはありません。これまでは個別の診断が必要だった3つのケースを紹介します。

SAP からの応答サーバーからの案内
/IWFND/MED/170 を伴う 403サービスが登録されていません。/IWFND/MAINT_SERVICE で有効化してください。403 ですが、認可の問題ではありません
HTML のログオンページを伴う 401sap-client が設定されていますか?設定されていない場合、クライアント依存の Gateway は、パスワードの誤りのように見える形でログオンを拒否します
UNABLE_TO_GET_ISSUER_CERT_LOCALLY証明書チェーンが不完全です。ルート CA を SAP_CA_CERT で指定してください。メッセージには発行元 CA の名前が表示されます

SAP_TLS_VERIFY=false が有効な場合、起動時のログだけでなく、すべてのツール結果に警告が含まれます。初日以降は誰の目にも触れない無効化されたチェックは、何年もそのままになりがちです。この対応のきっかけとなった本番システムでも設定されていましたが、誰も気づいていませんでした。

Streamable HTTP はステートレスです

--transport http は MCP をステートレスモードで提供します。各リクエストは自己完結しており、サーバーは mcp-session-id ヘッダーを発行も要求もしません。再開できるサーバー側セッションはないため、クライアントは状態を失うことなく、いつでも再接続できます。

セッション ID を必須とするクライアント、つまり初期化レスポンスから mcp-session-id を読み取り、後続のリクエストで送り返すクライアントは、このサーバーに接続すると失敗します。n8n MCP Client、Claude Desktop、MCP Inspector は、いずれもセッション ID なしで動作します。

レガシーな --transport sse モードは 0.8.0 で削除されました。http を使用してください。

複数の SAP システム:destinations.json

SAP_* 変数が記述するのは1つの SAP システムです。1つのサーバーを複数のシステムに接続するには、たとえば本番システムとテストクライアントを並行して使用する場合や、1つの 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"
    }
  }
}
  • 1 つのエントリーにつき 1 つの接続です。 各エントリーで指定できるフィールドは、SAP_* 変数とまったく同じです(authType とその認証情報、sapClient、baseUrl)。すべての認証タイプを接続先ごとに使用できます。
  • リクエストごとに個人の SAP ログインを使用します — "authType": "user-basic":接続先が保持するのはシステムとクライアントの情報だけです。SAP のユーザー名とパスワードは各リクエストで送信します(X-SAP-Username/X-SAP-Password。n8n では GuniWeb SAP node の認証情報を使用します)。各ユーザーは SAP 上で自分自身として操作します。実際のユーザーに紐づく権限、変更文書、監査証跡が残り、共有の技術アカウントは不要です。技術ユーザーへのフォールバックはありません(ログイン情報がない場合は 401)。ユーザーごとにキャッシュされ、パスワードがログに記録されることはありません。HTTP トランスポートのみ対応しています。詳細はセットアップガイドをご覧ください。
  • シークレットをファイルに保存しません。 任意の文字列に ${VARIABLE} を含めることができ、読み込み時に環境変数から解決されます(Docker シークレット、.env)。解決できないプレースホルダーがある場合、ファイルは無効になります。空のパスワードでは、SAP から誤解を招く 401 が返されてしまうためです。
  • ホットリロードに対応しています。 ファイルが監視され、変更は再起動なしで次のリクエストから反映されます。kill -HUP <pid> で強制的に再読み込みできます。無効なファイルが実行中の設定に置き換わることはありません。エラーがログに記録され、最後に有効だった設定が引き続き適用されます。
  • 後方互換性があります。 --destinations を指定しない場合、動作に変更はありません。SAP_* 変数が唯一の接続先 default になります。ファイルを指定した場合、ファイル内で default が定義されていなければ、SAP_*(設定されている場合)が default として追加されます。これにより、サービスを中断することなく移行できます。
  • どの接続先が応答しますか? トークンがない場合は、default(または唯一の接続先)が選ばれます。トークンがある場合は、トークンに対応する接続先が選ばれます。詳しくは以下をご覧ください。

トークン:n8n の認証情報ごとに 1 つの Bearer 値を使用して、システムを選択します。 n8n MCP Client が送信する Authorization ヘッダーは 1 つだけなので、トークンはリクエストの認証と接続先の選択という 2 つの役割を同時に果たします。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 認証情報に設定します。トークンが 1 つでも存在すると、有効なトークンのないリクエストには 401 が返されます。--api-key は引き続き併用でき、default 接続先に対して機能します。
  • すべてのエントリーに対して一定時間で検索します。"revoked": true にすると、次のリクエストからトークンが無効になります(ホットリロードに対応しているため、再起動は不要です)。1 分以内に 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"] }。ポリシーは常に制限するだけです。readOnly: true にすると、サーバーが --allow-write で実行されていても、そのトークンでは書き込みツールが表示されません(readOnly: false にしても読み取り専用サーバーで書き込みを有効にはできません)。また、tiers は上限です。指定された範囲外の階層はそのトークンでは表示されず、sap_enable_tools で有効にすることもできません。tools/list はリクエストごとにフィルタリングされるため、読み取り専用トークンを使うエージェントには、そもそも sap_create が表示されません。

  • トークンごと、および接続先ごとのレート制限 — ループ内で呼び出す AI エージェント向けで、SAP API のクォータを超えないようにするための機能です。トークンの policy に "rateLimit": { "requestsPerMinute": 60, "maxConcurrent": 4 } を指定すると、そのトークンに制限が適用されます。同じオブジェクトを接続先に指定すると、その SAP システムを利用するすべての呼び出し元にまとめて制限が適用されます。カウント対象はツール呼び出しのみです(tools/list は無料です)。制限を超えると、サーバーは制限名を示すヒントと Retry-After を含む 429 を返します。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)を指定すると、サーバーは CLI の操作を /admin 配下に公開します。ホスト上のシェルを使わずに、新しい顧客のアクセス権を設定する n8n ワークフロー、スクリプト、または curl を使う担当者が利用できます。

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 データを読み取ることもできません。誤ったシークレットはクライアントアドレスごとにカウントされ(1 分あたり 10 回失敗すると 429)、変更はすべて操作、対象、クライアントアドレスとともに記録されます。トークンとシークレットは記録されません。--admin-token を指定していない場合、/admin/* は 404 を返します。
  • 変更は即時反映されます。 書き込み時には CLI と同様に検証が行われ、アトミックに書き込まれた後、応答前に稼働中の設定が再読み込みされます("reloaded": true)。サーバーが書き込まれた内容を読み込めない場合(通常は、シェルでしか認識されない ${VAR} を ?allowMissingEnv=true を指定して書き込んだ場合)、エラーとともに "reloaded": false が返され、最後に有効だった設定が引き続き適用されます。
  • SAP の設定がなくても初期設定できます。 --admin-token を指定すると、destinations.json がまだ存在せず、SAP_* も設定されていない場合でもサーバーが起動します。API 経由で最初の接続先(およびトークン、または 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 サーバーは、OData V2、OData V4、IDoc HTTP/XML、RFC/BAPI に対応する ECC 6.0+(EHP 7+)をサポートします。クラウド専用の S/4HANA テナントでは、このセクションは不要です。

1. NetWeaver Gateway を有効化する

トランザクション SICF で、/sap/opu/odata/ 配下の標準 ICF サービスを有効化します。次に、トランザクション /IWFND/MAINT_SERVICE を使用して、公開する OData サービスを登録します。

MCP サーバーのカタログ自動検出は、次の 3 つのパスを順に確認し、最初にヒットした結果を 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 ツール層で必要です。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 環境で TLS 証明書の検証を無効にするには、false に設定します
SAP_CLIENT_CERT_PATHX.509 クライアント証明書の場合PEM エンコードされたクライアント証明書へのパス。例:/etc/sap/client.crt
SAP_CLIENT_KEY_PATHX.509 クライアント証明書の場合PEM エンコードされた秘密鍵へのパス(パスフレーズはプロンプトで任意に指定できます)
SAP_SNC_QOPSNC(RFC)の場合SNC の保護品質レベル:1(認証のみ)、2(整合性)、3/8/9(暗号化)
SAP_SNC_MYNAMESNC(RFC)の場合ローカル SNC 名。例:p:CN=mcp-server, O=GuniWeb
SAP_SNC_PARTNERNAMESNC(RFC)の場合バックエンドの SNC 名。例:p:CN=SAPSERVER, O=ACME
SAP_SNC_LIBSNC(RFC)の場合SNC ライブラリ(.so / .dylib / .dll)へのパス。例:/usr/sap/sapcrypto/libsapcrypto.so

利用可能なツール(22)

コア層(常に有効)
ツール説明
test-connection段階ごとに接続を診断します(DNS → TLS → 認証 → クライアント → カタログ)。最初に失敗した段階を示します
sap_list_servicesOData サービス内のエンティティセットを一覧表示します(ページ分割、デフォルトは 50 件)
sap_discover_servicesカテゴリによる絞り込みと検索を使って、すべてのサービスを検出します
sap_get_metadataエンティティ型、プロパティ、キー、および各エンティティセットで SAP が許可する操作(作成/更新/削除可能か)を確認します
OData 層(デフォルトで有効)
ツール説明
sap_read単一のエンティティまたはコレクションを読み取ります
sap_queryOData の $filter、$select、$expand、ページネーションを使用してクエリを実行します(デフォルトの top は 50)
sap_nl_query構造化フィルターを使用して自然言語でクエリを実行します
sap_createエンティティを作成します(ディープインサートとドラフトサービスをサポート)
sap_updateエンティティを更新します(ETag を自動処理)
sap_deleteエンティティを削除します(ETag を自動処理)
sap_functionV2 の関数インポート、または V4 のアクション/関数を呼び出します
sap_batch複数の操作を 1 つのバッチで実行します
IDoc 層(sap_enable_tools でオンデマンドに有効化)
ツール説明
sap_idoc_sendHTTP/XML を介して SAP に IDoc を送信します
sap_idoc_list_receivedWebhook で受信した IDoc を一覧表示します
sap_idoc_statusIDoc の処理ステータスを確認します
sap_idoc_discover利用可能な IDoc タイプを検出します
RFC 層(sap_enable_tools でオンデマンドに有効化。SAP NW RFC SDK が必要)
ツール説明
sap_rfc_callzod でパラメーターを検証し、RFC 対応の任意の汎用モジュールを呼び出します
sap_rfc_metadata汎用モジュールのシグネチャ(インポート/エクスポート/テーブル/例外)を取得します
sap_bapi_callBAPI を呼び出し、BAPIRET2 の戻りテーブルを解析し、後続のコミット処理のために接続を固定します
sap_bapi_commit固定されたセッションで BAPI_TRANSACTION_COMMIT を呼び出します
sap_rfc_search_functionsRFC_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

ドキュメント

ガバナンス:SAP のルールへの適合

  • 標準の連携インターフェースのみを使用します。 サーバーは NetWeaver Gateway 経由の OData V2/V4、HTTP/XML 経由の IDoc、RFC/BAPI を使用します。これらは SAP システムへの、文書化されサポートされている接続方法です(ツールごとの一覧)。UI の自動操作、未文書化のインターフェース、SAP データの一括複製は行いません。ページング制限と時間予算が組み込まれているため、単一のツール呼び出しが Gateway の負荷テストになることはありません。
  • 書き込み処理は管理され、監査可能です。 デフォルトでは読み取り専用です。書き込みツールは --allow-write を明示した場合にのみ利用でき、トークンごとのポリシーでできるのは制限のみで、範囲を広げることはできません。各ツール呼び出しは相関 ID を含むログを 1 行記録し、その ID は呼び出しによって発生した各 SAP リクエストにも表示されます。これにより「人間の管理下にある」ことを検証できます。書き込み可能な箇所を決めるのはモデルではなく、ワークフローの作成者です。
  • ドキュメントの作成を自動化する前に確認すべきことが 2 つあります。 SAP の API 利用ポリシーには、API の自律的・生成的な利用に関する条項があります。自由に動作する自律型エージェントではなく、LLM の支援を受けながら、人間が作成した決定的な手順としてワークフローを構築してください(このサーバーはまさにその用途を想定して設計されています)。また、自動作成される業務文書(たとえば受注伝票)は、テナントの SAP Digital Access ライセンスの対象となる場合があります。本番稼働の前に、SAP のアカウントチームに確認してください。どちらの記述も法的助言ではありませんが、どちらも監査担当者が尋ねる内容です。

これを支えているのは誰か — サポートを受けるには

guniweb-sap-mcp は、独自のソリューションを提供するコンサルティング会社 GuniWeb が開発・保守しています。その理念は「機能するプロセス、共に成長するシステム」です。GuniWeb は、20 年以上の実務経験をもとに、戦略コンサルティングと現場での実装を通じて中堅企業の業務プロセスを最適化し、企業がデジタル化するだけでなく、より円滑に運営できるよう支援しています。このサーバーもそのソリューションの一つです。顧客の本番環境で稼働しており、教育や研究にも利用されています。npm 上のコンパイル済みパッケージは ISC ライセンスのもとで無料で利用できます。ソースコードは公開されていません。

  • コミュニティ — 質問、バグ報告、アイデアは、ベストエフォートで Issues と Discussions から受け付けています。SUPPORT.md をご覧ください。
  • 本番環境のサポート — 優先的な修正、SAP のリリース変更への互換性対応、直接の問い合わせ窓口を含む保守サブスクリプションを提供しています。書き込み経路に対する応答時間 SLA もオプションで追加できます:guniweb.de/sap-mcp
  • SAP MCP Checkup — 本番稼働前に、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)は OS 固有(.so/.dylib/.dll)で、別途インストールする必要があります。 ↩ ↩2

コメント

MCP は初めてですか?

プロトコルの概要から最初のサーバーの導入まで、よくある疑問にまとめて答えます。

AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。