From 24ed309f52205f611627c3ca4dd49e85b6fc53ce Mon Sep 17 00:00:00 2001 From: Matteo Date: Tue, 29 Sep 2026 13:33:10 +0200 Subject: [PATCH] SAP S/4HANA in the README ERP table; worked examples; satellite docs pages - README (en, de, ja, zh-CN): SAP S/4HANA (HANA SQL) and SAP S/4HANA (OData) rows in the ERP table, sap-hana-mcp-server in the repository list. Both on-premise S/4HANA connectors were missing from it. - docs/connectors/sap-hana.md: three example questions with the sap_guide SQL; the store is called Marketplace now. - Satellites: content//doc-.md becomes docs/.md and is listed under Guides in the README. sap-hana-mcp-server gets use cases, architecture, security and a comparison page. --- README.de.md | 4 +- README.ja.md | 4 +- README.md | 4 +- README.zh-CN.md | 4 +- docs/connectors/sap-hana.md | 39 +++++++++++- .../sap-hana-mcp-server/doc-architecture.md | 33 ++++++++++ .../sap-hana-mcp-server/doc-comparison.md | 13 ++++ .../sap-hana-mcp-server/doc-security.md | 30 +++++++++ .../sap-hana-mcp-server/doc-use-cases.md | 61 +++++++++++++++++++ scripts/satellites/lib.mjs | 4 ++ scripts/satellites/readme.mjs | 21 +++++++ 11 files changed, 212 insertions(+), 5 deletions(-) create mode 100644 scripts/satellites/content/sap-hana-mcp-server/doc-architecture.md create mode 100644 scripts/satellites/content/sap-hana-mcp-server/doc-comparison.md create mode 100644 scripts/satellites/content/sap-hana-mcp-server/doc-security.md create mode 100644 scripts/satellites/content/sap-hana-mcp-server/doc-use-cases.md diff --git a/README.de.md b/README.de.md index f5dc8f6e..c7fff083 100644 --- a/README.de.md +++ b/README.de.md @@ -141,6 +141,8 @@ Fertige Adapter für die ERP-Systeme, in denen die meisten Fragen zu Aufträgen, |---|---|---|---| | [SAP Business One](https://anythingmcp.com/de/guides/connect-sap-business-one-to-claude) | Weltweit | 12 | Geschäftspartner, Artikel, Aufträge, Rechnungen, Angebote, Lieferungen; Kundenaufträge anlegen | | [SAP S/4HANA Cloud](https://anythingmcp.com/de/guides/connect-sap-s4hana-cloud-to-claude) | Weltweit | 15 | Geschäftspartner, Kundenaufträge und Bestellungen, Fakturen, Lieferungen, Buchungsbelege | +| [SAP S/4HANA (HANA SQL)](https://anythingmcp.com/de/guides/connect-sap-hana-to-claude) | Weltweit | 10 | S/4HANA On-Premise und Private Cloud direkt aus HANA gelesen, mit SAPs Data Dictionary und CDS-Views als Tools; nur lesend | +| [SAP S/4HANA (OData)](https://anythingmcp.com/de/guides/odata-to-mcp) † | Weltweit | 7 | OData-Services des Gateways mit SAPs Bezeichnungen: Buchungszeilen, Fakturen, Kundenaufträge, Geschäftspartner, Bestand, Produkte | | [Odoo](https://anythingmcp.com/de/guides/connect-odoo-to-claude) | Weltweit | 11 | Jedes Modell: Partner, Kundenaufträge, Rechnungen, Produkte; anlegen und ändern | | [Microsoft Dynamics NAV](https://anythingmcp.com/de/guides/connect-dynamics-nav-to-claude) | Weltweit | 6 | Jede veröffentlichte OData-Seite: Kunden, Artikel, Kundenaufträge; anlegen und ändern | | [ERPNext](https://anythingmcp.com/de/guides/connect-erpnext-to-claude) | Weltweit | 11 | Jeder DocType: Kunden, Kundenaufträge, Rechnungen, Artikel, Lagerbestand | @@ -158,7 +160,7 @@ Fertige Adapter für die ERP-Systeme, in denen die meisten Fragen zu Aufträgen, † Auf Basis der veröffentlichten API-Dokumentation des Herstellers erstellt und noch nicht mit einem echten Mandanten getestet. Wenn du eines dieser Systeme einsetzt, freuen wir uns sehr über einen Erfahrungsbericht oder einen Fix. -**Repositories:** [erp-mcp-server](https://github.com/HelpCode-ai/erp-mcp-server) · [weclapp-mcp-server](https://github.com/kochfreiburg/weclapp-mcp-server) · [odoo-mcp-server](https://github.com/keysersoft/odoo-mcp-server) · [sap-mcp-server](https://github.com/HelpCode-ai/sap-mcp-server) · [sap-business-one-mcp-server](https://github.com/HelpCode-ai/sap-business-one-mcp-server) · [xentral-mcp-server](https://github.com/kochfreiburg/xentral-mcp-server) +**Repositories:** [erp-mcp-server](https://github.com/HelpCode-ai/erp-mcp-server) · [weclapp-mcp-server](https://github.com/kochfreiburg/weclapp-mcp-server) · [odoo-mcp-server](https://github.com/keysersoft/odoo-mcp-server) · [sap-mcp-server](https://github.com/HelpCode-ai/sap-mcp-server) · [sap-hana-mcp-server](https://github.com/HelpCode-ai/sap-hana-mcp-server) · [sap-business-one-mcp-server](https://github.com/HelpCode-ai/sap-business-one-mcp-server) · [xentral-mcp-server](https://github.com/kochfreiburg/xentral-mcp-server) **Dein ERP ist nicht dabei, oder es ist eine Eigenentwicklung bzw. läuft on-premises?** Binde es über seine [REST-API](#openapi--rest-api-to-mcp), seine [SOAP-Dienste](#soap--wsdl-to-mcp) oder direkt über seine [SQL-Datenbank](#sql-database-to-mcp) an, mit reinem Lesezugriff. So betreibt [KOCH Freiburg](https://www.kochfreiburg.de/) sein ERP im Produktivbetrieb. diff --git a/README.ja.md b/README.ja.md index a693b21b..738aa9f0 100644 --- a/README.ja.md +++ b/README.ja.md @@ -141,6 +141,8 @@ Postman v2.1 のコレクションをインポートすると、フォルダー |---|---|---|---| | [SAP Business One](https://anythingmcp.com/ja/guides/connect-sap-business-one-to-claude) | グローバル | 12 | 取引先、品目、注文、請求書、見積、納品。受注の作成 | | [SAP S/4HANA Cloud](https://anythingmcp.com/ja/guides/connect-sap-s4hana-cloud-to-claude) | グローバル | 15 | 取引先、受注と発注、請求伝票、出荷、仕訳 | +| [SAP S/4HANA (HANA SQL)](https://anythingmcp.com/guides/connect-sap-hana-to-claude) | グローバル | 10 | オンプレミスと Private Cloud の S/4HANA を HANA から直接読み取り、SAP のデータディクショナリと CDS ビューをツールとして提供。読み取り専用 | +| [SAP S/4HANA (OData)](https://anythingmcp.com/guides/odata-to-mcp) † | グローバル | 7 | SAP のラベル付きの Gateway OData サービス: 仕訳明細、請求伝票、受注、取引先、在庫、品目 | | [Odoo](https://anythingmcp.com/ja/guides/connect-odoo-to-claude) | グローバル | 11 | 任意のモデル(取引先、受注、請求書、製品)。作成と更新 | | [Microsoft Dynamics NAV](https://anythingmcp.com/ja/guides/connect-dynamics-nav-to-claude) | グローバル | 6 | 公開済みの任意の OData ページ(顧客、品目、受注)。作成と更新 | | [ERPNext](https://anythingmcp.com/ja/guides/connect-erpnext-to-claude) | グローバル | 11 | 任意の DocType(顧客、受注、請求書、品目、在庫) | @@ -158,7 +160,7 @@ Postman v2.1 のコレクションをインポートすると、フォルダー † ベンダーが公開している API ドキュメントを基に作成しており、実際のテナントではまだ検証していません。これらのシステムをお使いの方からの報告や修正を歓迎します。 -**リポジトリ:** [erp-mcp-server](https://github.com/HelpCode-ai/erp-mcp-server) · [weclapp-mcp-server](https://github.com/kochfreiburg/weclapp-mcp-server) · [odoo-mcp-server](https://github.com/keysersoft/odoo-mcp-server) · [sap-mcp-server](https://github.com/HelpCode-ai/sap-mcp-server) · [sap-business-one-mcp-server](https://github.com/HelpCode-ai/sap-business-one-mcp-server) · [xentral-mcp-server](https://github.com/kochfreiburg/xentral-mcp-server) +**リポジトリ:** [erp-mcp-server](https://github.com/HelpCode-ai/erp-mcp-server) · [weclapp-mcp-server](https://github.com/kochfreiburg/weclapp-mcp-server) · [odoo-mcp-server](https://github.com/keysersoft/odoo-mcp-server) · [sap-mcp-server](https://github.com/HelpCode-ai/sap-mcp-server) · [sap-hana-mcp-server](https://github.com/HelpCode-ai/sap-hana-mcp-server) · [sap-business-one-mcp-server](https://github.com/HelpCode-ai/sap-business-one-mcp-server) · [xentral-mcp-server](https://github.com/kochfreiburg/xentral-mcp-server) **お使いの ERP が一覧にない場合や、独自開発・オンプレミスの ERP の場合は?** その [REST API](#openapi--rest-api-to-mcp) や [SOAP サービス](#soap--wsdl-to-mcp)を通じて、または [SQL データベース](#sql-database-to-mcp)に直接、読み取り専用で接続できます。[KOCH Freiburg](https://www.kochfreiburg.de/) は、この方法で自社の ERP を本番環境で接続しています。 diff --git a/README.md b/README.md index bc355c54..15ffbee8 100644 --- a/README.md +++ b/README.md @@ -128,6 +128,8 @@ Ready adapters for the ERPs behind most order, stock and invoice questions. Inst |---|---|---|---| | [SAP Business One](https://anythingmcp.com/guides/connect-sap-business-one-to-claude) | Global | 12 | Business partners, items, orders, invoices, quotations, deliveries; create sales orders | | [SAP S/4HANA Cloud](https://anythingmcp.com/guides/connect-sap-s4hana-cloud-to-claude) | Global | 15 | Business partners, sales and purchase orders, billing documents, deliveries, journal entries | +| [SAP S/4HANA (HANA SQL)](https://anythingmcp.com/guides/connect-sap-hana-to-claude) | Global | 10 | S/4HANA on-premise and Private Cloud read straight from HANA, with SAP's data dictionary and CDS views as tools; read-only | +| [SAP S/4HANA (OData)](https://anythingmcp.com/guides/odata-to-mcp) † | Global | 7 | Gateway OData services with SAP's labels: journal entry items, billing documents, sales orders, business partners, stock, products | | [Odoo](https://anythingmcp.com/guides/connect-odoo-to-claude) | Global | 11 | Any model: partners, sales orders, invoices, products; create and update | | [Microsoft Dynamics NAV](https://anythingmcp.com/guides/connect-dynamics-nav-to-claude) | Global | 6 | Any published OData page: customers, items, sales orders; create and update | | [ERPNext](https://anythingmcp.com/guides/connect-erpnext-to-claude) | Global | 11 | Any DocType: customers, sales orders, invoices, items, stock | @@ -145,7 +147,7 @@ Ready adapters for the ERPs behind most order, stock and invoice questions. Inst † Built from the vendor's published API documentation and not yet exercised against a live tenant. If you run one of these, a report or a fix is very welcome. -**Repositories:** [erp-mcp-server](https://github.com/HelpCode-ai/erp-mcp-server) · [weclapp-mcp-server](https://github.com/kochfreiburg/weclapp-mcp-server) · [odoo-mcp-server](https://github.com/keysersoft/odoo-mcp-server) · [sap-mcp-server](https://github.com/HelpCode-ai/sap-mcp-server) · [sap-business-one-mcp-server](https://github.com/HelpCode-ai/sap-business-one-mcp-server) · [xentral-mcp-server](https://github.com/kochfreiburg/xentral-mcp-server) +**Repositories:** [erp-mcp-server](https://github.com/HelpCode-ai/erp-mcp-server) · [weclapp-mcp-server](https://github.com/kochfreiburg/weclapp-mcp-server) · [odoo-mcp-server](https://github.com/keysersoft/odoo-mcp-server) · [sap-mcp-server](https://github.com/HelpCode-ai/sap-mcp-server) · [sap-hana-mcp-server](https://github.com/HelpCode-ai/sap-hana-mcp-server) · [sap-business-one-mcp-server](https://github.com/HelpCode-ai/sap-business-one-mcp-server) · [xentral-mcp-server](https://github.com/kochfreiburg/xentral-mcp-server) **Your ERP isn't listed, or it's a custom or on-prem build?** Connect it through its [REST API](#openapi--rest-api-to-mcp), [SOAP services](#soap--wsdl-to-mcp) or straight to its [SQL database](#sql-database-to-mcp), read-only. That is how [KOCH Freiburg](https://www.kochfreiburg.de/) runs its ERP in production. diff --git a/README.zh-CN.md b/README.zh-CN.md index 9ab18086..47f09328 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -141,6 +141,8 @@ docker compose up -d |---|---|---|---| | [SAP Business One](https://anythingmcp.com/zh/guides/connect-sap-business-one-to-claude) | 全球 | 12 | 业务伙伴、物料、订单、发票、报价单、交货单;创建销售订单 | | [SAP S/4HANA Cloud](https://anythingmcp.com/zh/guides/connect-sap-s4hana-cloud-to-claude) | 全球 | 15 | 业务伙伴、销售订单和采购订单、开票凭证、交货单、会计分录 | +| [SAP S/4HANA (HANA SQL)](https://anythingmcp.com/guides/connect-sap-hana-to-claude) | 全球 | 10 | 直接从 HANA 读取本地部署和 Private Cloud 的 S/4HANA,以 SAP 数据字典和 CDS 视图作为工具;只读 | +| [SAP S/4HANA (OData)](https://anythingmcp.com/guides/odata-to-mcp) † | 全球 | 7 | 带 SAP 标签的 Gateway OData 服务:会计分录行、开票凭证、销售订单、业务伙伴、库存、产品 | | [Odoo](https://anythingmcp.com/zh/guides/connect-odoo-to-claude) | 全球 | 11 | 任意模型:合作伙伴、销售订单、发票、产品;可创建和更新 | | [Microsoft Dynamics NAV](https://anythingmcp.com/zh/guides/connect-dynamics-nav-to-claude) | 全球 | 6 | 任意已发布的 OData 页面:客户、物料、销售订单;可创建和更新 | | [ERPNext](https://anythingmcp.com/zh/guides/connect-erpnext-to-claude) | 全球 | 11 | 任意 DocType:客户、销售订单、发票、物料、库存 | @@ -158,7 +160,7 @@ docker compose up -d † 根据供应商公开的 API 文档构建,尚未在实际运行的租户上测试。如果你正在使用其中某个系统,非常欢迎提交问题反馈或修复。 -**代码仓库:** [erp-mcp-server](https://github.com/HelpCode-ai/erp-mcp-server) · [weclapp-mcp-server](https://github.com/kochfreiburg/weclapp-mcp-server) · [odoo-mcp-server](https://github.com/keysersoft/odoo-mcp-server) · [sap-mcp-server](https://github.com/HelpCode-ai/sap-mcp-server) · [sap-business-one-mcp-server](https://github.com/HelpCode-ai/sap-business-one-mcp-server) · [xentral-mcp-server](https://github.com/kochfreiburg/xentral-mcp-server) +**代码仓库:** [erp-mcp-server](https://github.com/HelpCode-ai/erp-mcp-server) · [weclapp-mcp-server](https://github.com/kochfreiburg/weclapp-mcp-server) · [odoo-mcp-server](https://github.com/keysersoft/odoo-mcp-server) · [sap-mcp-server](https://github.com/HelpCode-ai/sap-mcp-server) · [sap-hana-mcp-server](https://github.com/HelpCode-ai/sap-hana-mcp-server) · [sap-business-one-mcp-server](https://github.com/HelpCode-ai/sap-business-one-mcp-server) · [xentral-mcp-server](https://github.com/kochfreiburg/xentral-mcp-server) **你的 ERP 不在列表中,或者是定制开发、本地部署的系统?** 可以通过它的 [REST API](#openapi--rest-api-to-mcp)、[SOAP 服务](#soap--wsdl-to-mcp) 连接,也可以以只读方式直接连接它的 [SQL 数据库](#sql-database-to-mcp)。[KOCH Freiburg](https://www.kochfreiburg.de/) 在生产环境中就是这样接入其 ERP 的。 diff --git a/docs/connectors/sap-hana.md b/docs/connectors/sap-hana.md index 8689a21d..c8fe601c 100644 --- a/docs/connectors/sap-hana.md +++ b/docs/connectors/sap-hana.md @@ -38,7 +38,7 @@ User and password go in the connector's credentials (encrypted), not in the URL. ## SAP S/4HANA (HANA SQL) adapter -Install it from the catalog (Connectors → Store → *SAP S/4HANA (HANA SQL)*). Its tools: +Install it from the catalog (Connectors → Marketplace → *SAP S/4HANA (HANA SQL)*). Its tools: | Tool | What it gives the model | |------|------------------------| @@ -92,6 +92,43 @@ Before you connect a production system, check two things with your SAP account t - **Licence.** Direct SQL access to the ABAP schema by a third-party application is governed by your SAP HANA licence. A runtime licence bundled with S/4HANA usually does not cover it; a full-use licence does. In SAP's private cloud offerings the database user and network path must be requested from SAP. - **Network.** The HANA SQL port is normally reachable only inside the company network or the SAP private cloud landing zone. Run AnythingMCP there, or reach it through a VPN, and add the host to `SSRF_ALLOWED_HOSTS` (the outbound guard blocks private addresses by default). +### Example questions + +Three questions end to end, with the SQL from the `recipes` chapter of `sap_guide` (client `100`, company code `1010`, fiscal year 2025). The model states the assumptions it made, such as the revenue account range, and asks to confirm them. The step-by-step guide with screenshots is at [anythingmcp.com/guides/connect-sap-hana-to-claude](https://anythingmcp.com/guides/connect-sap-hana-to-claude). + +**"What was our revenue per posting period in 2025?"** `sap_guide` → `sap_org_structure` → `sap_query` on the Universal Journal. Revenue is a credit, so the sum is negated: + +```sql +SELECT POPER, RHCUR AS CURRENCY, -SUM(HSL) AS REVENUE +FROM ACDOCA +WHERE RCLNT = '100' AND RLDNR = '0L' AND RBUKRS = '1010' AND GJAHR = '2025' + AND RACCT BETWEEN '0040000000' AND '0049999999' -- revenue accounts: confirm the range +GROUP BY POPER, RHCUR ORDER BY POPER; +``` + +**"Which customers have invoices more than 60 days overdue?"** Open customer items at the key date, aged by net due date: + +```sql +SELECT KUNNR, RHCUR AS CURRENCY, + SUM(HSL) AS OPEN_AMOUNT, + SUM(CASE WHEN NETDT < '20251101' THEN HSL ELSE 0 END) AS OVERDUE_OVER_60 +FROM ACDOCA +WHERE RCLNT = '100' AND RLDNR = '0L' AND RBUKRS = '1010' AND KOART = 'D' AND POPER <> '000' + AND BUDAT <= '20251231' AND (AUGDT = '00000000' OR AUGDT > '20251231') +GROUP BY KUNNR, RHCUR ORDER BY OVERDUE_OVER_60 DESC LIMIT 20; +``` + +**"Who were our top 10 customers by net sales in 2025?"** From billing documents, not from the journal, where the customer sits on the receivable line. `sap_field_values('VBRK', 'VBTYP')` first, to tell invoices from credit memos: + +```sql +SELECT k.KUNAG, c.NAME1, k.WAERK, SUM(p.NETWR) AS NET_SALES +FROM VBRK k JOIN VBRP p ON p.MANDT = k.MANDT AND p.VBELN = k.VBELN +LEFT JOIN KNA1 c ON c.MANDT = k.MANDT AND c.KUNNR = k.KUNAG +WHERE k.MANDT = '100' AND k.FKDAT BETWEEN '20250101' AND '20251231' + AND k.FKSTO = '' AND k.VBTYP = 'M' +GROUP BY k.KUNAG, c.NAME1, k.WAERK ORDER BY NET_SALES DESC LIMIT 10; +``` + ### Live check The adapter's tests include a live suite that runs every tool against a real system: diff --git a/scripts/satellites/content/sap-hana-mcp-server/doc-architecture.md b/scripts/satellites/content/sap-hana-mcp-server/doc-architecture.md new file mode 100644 index 00000000..d9234257 --- /dev/null +++ b/scripts/satellites/content/sap-hana-mcp-server/doc-architecture.md @@ -0,0 +1,33 @@ +# Architecture + +```mermaid +flowchart LR + subgraph clients[AI client] + claude[Claude] + chatgpt[ChatGPT] + copilot[Copilot / Cursor] + end + subgraph net[Your network] + amcp[AnythingMCP
roles, audit log, read-only] + subgraph sap[SAP S/4HANA] + hana[(HANA
SAPHANADB)] + end + end + claude -- MCP over HTTPS, OAuth --> amcp + chatgpt -- MCP over HTTPS --> amcp + copilot -- MCP, API key --> amcp + amcp -- SQL over TLS, read-only user --> hana +``` + +- **AnythingMCP** runs with Docker Compose on a host that reaches the HANA SQL port. It holds the connector, its encrypted credentials, the MCP roles and the audit log in its own PostgreSQL. +- **The connector** opens a session per call with the bundled `hdb` driver (or SAP's `@sap/hana-client`, installed by you), sets `CDS_CLIENT` from the SAP client, switches the transaction to read-only, runs one statement and closes the session. +- **The tools** are fixed, read-only queries on SAP's dictionary (`DD02L`, `DD03L`, `DD04T`, `DD07T`, `DD08L`, the CDS annotations) and organization tables, a static guide to the data model, and `sap_query` for the model's own `SELECT`. +- **The client** only sees tool names, descriptions and results. It never connects to HANA. + +## One request + +1. The user asks Claude "Which customers are more than 60 days overdue?". +2. Claude calls `sap_guide` (no database access), then `sap_org_structure` for the company codes. +3. It looks up the right table and fields with the dictionary tools, then calls `sap_query` with a `SELECT` on `ACDOCA`. +4. AnythingMCP checks the role, runs the statement read-only with the row cap and timeout, logs the call and returns the rows. +5. Claude answers, stating the key date and currency it used. diff --git a/scripts/satellites/content/sap-hana-mcp-server/doc-comparison.md b/scripts/satellites/content/sap-hana-mcp-server/doc-comparison.md new file mode 100644 index 00000000..d5758d56 --- /dev/null +++ b/scripts/satellites/content/sap-hana-mcp-server/doc-comparison.md @@ -0,0 +1,13 @@ +# Compared with other ways to reach SAP + +| | This connector (HANA SQL) | SAP S/4HANA (OData) connector | SAP Joule with Claude | A generic HANA MCP server | +|---|---|---|---|---| +| Reads | Any table or CDS view the database user may read | The Gateway services the SAP user may call | Defined by SAP | Any table the user may read | +| SAP authorizations | Not applied: the database grants are the boundary | Checked by SAP on every call | SAP-managed | Not applied | +| Knows SAP's data model | Yes: data dictionary, CDS views, a guide to the model | Yes: SAP's labels from `$metadata` | SAP-managed | No: raw table and column names | +| Where you use it | Claude, ChatGPT, Copilot, Cursor | Claude, ChatGPT, Copilot, Cursor | Inside SAP's applications | Depends on the server | +| Runs | Self-hosted, next to SAP | Self-hosted, next to SAP | On SAP's Business AI platform | Depends on the server | + +**HANA SQL or OData?** SQL is strong for totals over millions of rows and analysis across modules, and needs a HANA licence that allows third-party SQL. OData keeps SAP's authorization checks and reaches only published services. Both run side by side in the same AnythingMCP. + +**And Joule?** Joule is SAP's own assistant inside SAP's applications, and SAP and Anthropic have announced Claude on SAP's Business AI platform. This connector goes the other way: SAP data inside the AI client your people already use, on a system you run yourself. The two do not exclude each other. More: [SAP Joule or a direct MCP connection](https://anythingmcp.com/vs/sap-joule). diff --git a/scripts/satellites/content/sap-hana-mcp-server/doc-security.md b/scripts/satellites/content/sap-hana-mcp-server/doc-security.md new file mode 100644 index 00000000..f2fc97d1 --- /dev/null +++ b/scripts/satellites/content/sap-hana-mcp-server/doc-security.md @@ -0,0 +1,30 @@ +# Security and permissions + +## What the connector enforces + +- **Read-only in HANA itself.** Every session runs `SET TRANSACTION READ ONLY` before the statement. On top of that, a guard lets only a single `SELECT` or `WITH … SELECT` through and refuses `SELECT … INTO` and locking reads (`FOR UPDATE`, `FOR SHARE`). +- **1,000 rows at most**, streamed, so a large `SELECT *` never lands in memory. +- **A statement timeout**, 60 seconds by default (up to 600 with `statementTimeout`). The session is closed and HANA cancels the statement. +- **Denied tables.** SAP's HR tables (`PA####`, `PB####`, `PCL#`, `HRP####`) and user and password tables (`USR##`, `USH##`, `RFCDES`, `SSF_PSE_D`) are refused even if the database user may read them. The list is in the connector settings. +- **Credentials** are encrypted with AES-256-GCM and never shown to the model. + +## What you decide + +- **The database grants are the real boundary.** SQL does not apply SAP's application authorizations (company code, sales organization, HR checks): whatever the database user can read, the model can read. Grant `SELECT` on the dictionary tables and on the business tables your use cases need, not on the whole schema. +- **A server-side cap** with a workload class mapped to the user: + + ```sql + CREATE WORKLOAD CLASS "AMCP_READER_WC" SET 'STATEMENT TIMEOUT' = '60', 'STATEMENT MEMORY LIMIT' = '20'; + CREATE WORKLOAD MAPPING "AMCP_READER_WM" WORKLOAD CLASS "AMCP_READER_WC" SET 'USER NAME' = 'AMCP_READER'; + ``` + +- **Who sees which tools.** Assign the connector to an MCP server whose role whitelists only the tools a group may use. Every call is in the audit log with input, output, duration and status. +- **Your licence.** Direct SQL access to the ABAP schema by a third-party application is governed by your SAP HANA licence. A runtime licence bundled with S/4HANA usually does not cover it; a full-use licence does. + +## Network + +The HANA SQL port is normally reachable only inside the company network or SAP's private cloud landing zone. AnythingMCP runs there, and the host goes into `SSRF_ALLOWED_HOSTS` because private addresses are refused by default. For claude.ai and ChatGPT only the MCP endpoint needs to be published over HTTPS, never the HANA port. Claude Code, Cursor and Copilot also work against a local instance. + +## What leaves your network + +Tool results. When a user asks a question, the rows `sap_query` returns become part of that conversation with the AI provider (Anthropic, OpenAI, Microsoft), under the terms of the plan you use. Credentials, the connection string and tables nobody asked about do not. Choose the plan and the tools accordingly, and strip fields you do not want to leave the network with a response mapping. diff --git a/scripts/satellites/content/sap-hana-mcp-server/doc-use-cases.md b/scripts/satellites/content/sap-hana-mcp-server/doc-use-cases.md new file mode 100644 index 00000000..ee67beaa --- /dev/null +++ b/scripts/satellites/content/sap-hana-mcp-server/doc-use-cases.md @@ -0,0 +1,61 @@ +# Use cases + +What people ask, and what the connector does to answer. The SQL comes from the `recipes` chapter of `sap_guide`; client `100`, company code `1010` and fiscal year 2025 stand in for yours. The model states the assumptions it made, such as the revenue account range, and asks you to confirm them. + +## Revenue per posting period + +> "What was our revenue per posting period in 2025?" + +Tools: `sap_guide` → `sap_org_structure` → `sap_query`. Table: `ACDOCA` (Universal Journal), leading ledger `0L`, amounts in company code currency. Revenue is a credit, so the sum is negated. + +```sql +SELECT POPER, RHCUR AS CURRENCY, -SUM(HSL) AS REVENUE +FROM ACDOCA +WHERE RCLNT = '100' AND RLDNR = '0L' AND RBUKRS = '1010' AND GJAHR = '2025' + AND RACCT BETWEEN '0040000000' AND '0049999999' -- revenue accounts: confirm the range +GROUP BY POPER, RHCUR ORDER BY POPER; +``` + +## Overdue receivables + +> "Which customers have invoices more than 60 days overdue, and how much?" + +Open customer items at a key date (`KOART = 'D'`, not cleared by then), aged by net due date `NETDT`. Period `000` holds carried-forward balances and is left out. + +```sql +SELECT KUNNR, RHCUR AS CURRENCY, + SUM(HSL) AS OPEN_AMOUNT, + SUM(CASE WHEN NETDT >= '20251231' THEN HSL ELSE 0 END) AS NOT_DUE, + SUM(CASE WHEN NETDT < '20251231' AND NETDT >= '20251101' THEN HSL ELSE 0 END) AS OVERDUE_1_60, + SUM(CASE WHEN NETDT < '20251101' THEN HSL ELSE 0 END) AS OVERDUE_OVER_60 +FROM ACDOCA +WHERE RCLNT = '100' AND RLDNR = '0L' AND RBUKRS = '1010' AND KOART = 'D' AND POPER <> '000' + AND BUDAT <= '20251231' AND (AUGDT = '00000000' OR AUGDT > '20251231') +GROUP BY KUNNR, RHCUR ORDER BY OVERDUE_OVER_60 DESC LIMIT 20; +``` + +## Top customers + +> "Who were our top 10 customers by net sales in 2025?" + +From billing documents, not from the journal: in `ACDOCA` the customer sits on the receivable line, not on the revenue line. The model reads the values of `VBRK.VBTYP` first (`sap_field_values`) to tell invoices from credit memos and cancellations. + +```sql +SELECT k.KUNAG, c.NAME1, k.WAERK, SUM(p.NETWR) AS NET_SALES +FROM VBRK k JOIN VBRP p ON p.MANDT = k.MANDT AND p.VBELN = k.VBELN +LEFT JOIN KNA1 c ON c.MANDT = k.MANDT AND c.KUNNR = k.KUNAG +WHERE k.MANDT = '100' AND k.FKDAT BETWEEN '20250101' AND '20251231' + AND k.FKSTO = '' AND k.VBTYP = 'M' +GROUP BY k.KUNAG, c.NAME1, k.WAERK ORDER BY NET_SALES DESC LIMIT 10; +``` + +## More questions by area + +- **Finance:** DSO for the quarter (open receivables over revenue of the same days, corrected for VAT), P&L accounts per period, balance of inventory accounts at period end. +- **Sales:** net sales per month from billing, open sales orders per customer, rejected order items. +- **Procurement:** purchase orders past their delivery date, per supplier. +- **Inventory:** goods movements per movement type and plant (`MATDOC`), materials with stock and no movement. +- **Master data:** customers without a VAT number, duplicate names in the customer master. +- **The system itself:** which company codes, plants and sales organizations exist; which CDS views are released and analytical for a topic. + +The step-by-step setup with screenshots: [Connect SAP S/4HANA to Claude via SAP HANA](https://anythingmcp.com/guides/connect-sap-hana-to-claude). diff --git a/scripts/satellites/lib.mjs b/scripts/satellites/lib.mjs index b098d873..5545c434 100644 --- a/scripts/satellites/lib.mjs +++ b/scripts/satellites/lib.mjs @@ -445,6 +445,10 @@ export function buildSatellite(sat, ctx) { } const prompts = content.en?.prompts; if (prompts) files['examples/prompts.md'] = `# Example prompts: ${sat.system}\n\n${prompts}\n`; + // content//doc-.md → docs/.md, listed in the README. + for (const [name, body] of Object.entries(content.en ?? {})) { + if (name.startsWith('doc-')) files[`docs/${name.slice(4)}.md`] = `${body}\n`; + } for (const e of entries) files[`adapter/${e.adapter.slug}.json`] = pretty(e.adapter); files['docker-compose.yml'] = buildCompose(readFileSync(join(root, 'docker-compose.quickstart.yml'), 'utf8'), sat); diff --git a/scripts/satellites/readme.mjs b/scripts/satellites/readme.mjs index b5bdd990..d382f34b 100644 --- a/scripts/satellites/readme.mjs +++ b/scripts/satellites/readme.mjs @@ -60,6 +60,7 @@ const T = { '**SSO, RBAC and SCIM** are included in the self-hosted build.', ], faq: 'FAQ', + guides: 'Guides', trouble: 'Troubleshooting', troubleRows: [ ['`401` / `403` from the vendor', 'The credentials are wrong or lack rights. Re-enter them on the connector page; the import runs a test call and shows the result.'], @@ -118,6 +119,7 @@ const T = { '**SSO, RBAC und SCIM** sind in der selbst gehosteten Version enthalten.', ], faq: 'FAQ', + guides: 'Anleitungen', trouble: 'Fehlerbehebung', troubleRows: [ ['`401` / `403` vom Hersteller', 'Zugangsdaten falsch oder ohne Rechte. Auf der Connector-Seite neu eintragen; der Import macht einen Testaufruf und zeigt das Ergebnis.'], @@ -192,6 +194,24 @@ function header(sat, ctx, t, title, taglineText) { ].join('\n'); } +/** The satellite's docs/.md pages (content//doc-.md), as a list. */ +function docsList(content, lang) { + // Readers want the use cases first; anything not listed keeps file order. + const ORDER = ['doc-use-cases', 'doc-architecture', 'doc-security', 'doc-comparison']; + const rank = (n) => (ORDER.includes(n) ? ORDER.indexOf(n) : ORDER.length); + const docs = Object.entries(content.en ?? {}) + .filter(([n]) => n.startsWith('doc-')) + .sort(([a], [b]) => rank(a) - rank(b)); + if (!docs.length) return null; + const prefix = lang === 'en' ? '' : '../'; + return docs + .map(([n, body]) => { + const title = (body.match(/^#\s+(.+)$/m)?.[1] ?? n.slice(4)).trim(); + return `- [${title}](${prefix}docs/${n.slice(4)}.md)`; + }) + .join('\n'); +} + function connectorReadme(sat, ctx) { const { adapters, content, lang, config } = ctx; const t = T[lang]; @@ -260,6 +280,7 @@ function connectorReadme(sat, ctx) { '', t.securityItems(tools.length - writes.length, writes).map((s) => `- ${s}`).join('\n'), '', + ...(docsList(content, lang) ? [`## ${t.guides}`, '', docsList(content, lang), ''] : []), `## ${t.faq}`, '', faq,