Skip to main content
Glama
leonardows1

SAP B1 ServiceLayer MCP Server

by leonardows1

SAP B1 ServiceLayer MCP Server

SAP Business One 10.0のServiceLayerにローカルネットワークで接続するためのMCP(Model Context Protocol)サーバー。GitHubリポジトリからnpxで実行でき、PCに何もインストールする必要はありません。

特徴

  • デフォルトは読み取り専用: SAP_B1_READONLY=true(デフォルト)の場合、クエリツール(GET)のみが登録されます。書き込みツール(POST/PATCH/DELETE)はサーバーに存在せず、呼び出すことはできません。

  • 完全なディスカバリ: sap_list_entitiessap_get_entity_schemasap_list_actionsGET /$metadata(プロセスごとに一度だけダウンロードされキャッシュされる)を参照し、約140のCRUDエンティティ(ユーザーテーブル@やUDOを含む)とServiceLayerの数百のサービスメソッドを公開します。

  • オプションの書き込みモード: SAP_B1_READONLY=falseの場合、ServiceLayerエンティティ用のsap_createsap_updatesap_deleteと、サービスメソッド用のsap_call_actionが有効になります(副作用がある可能性があります)。

  • npx github:による実行: 手動インストールは不要です。

  • セッション管理: CompanyDB/ユーザー名/パスワードによる暗黙のログイン、B1SESSION + ROUTEIDクッキーをメモリに保持(マルチノードServiceLayerをサポート)、401に対する自動再ログイン、プロセス終了時の確実なログアウトsap_logoutツールに加えて)。

  • 自己署名TLS: SAP_B1_VERIFY_TLS=falseにより、ServiceLayerの自己署名証明書(ローカル環境で一般的)をサポートします。

  • テレメトリや外部呼び出しなし: HTTPクライアントは設定されたURL(SAP_B1_SERVER_URL)のみを指します。

  • セキュリティ制限: topはクエリごとに200レコードに制限されます。

Related MCP server: BTP MCP Server

ツール

読み取り(常に利用可能)

Tool

説明

sap_query

任意のODataエンティティへの汎用GET。selectfiltertop(≤200)、skiporderbyexpandをサポート

sap_list_entities

ServiceLayerが公開するすべてのODataエンティティを一覧表示($metadataから、キャッシュ済み)。ユーザーテーブル(@)とUDOを含む。絞り込み用のfilterオプション

sap_get_entity_schema

エンティティのスキーマ: プロパティ(型/キー)とnavigationProperties$expandに有効)。EntityTypeを共有するエンティティセットを解決

sap_list_actions

サービスメソッド(function imports、例: CompanyService_GetCompanyInfo)とそのパラメータを一覧表示

sap_sql_query

読み取り専用SQL(SELECT/WITH。INSERT/UPDATE/DELETE/DDLは拒否)をPOST /sql_query経由で実行 — 最近のServiceLayer v2/FPのみ。古いv1では明確なエラーを返す

sap_get_business_partners

取引先(顧客/仕入先)。card_typeによるフィルタ

sap_get_items

カタログの品目

sap_get_sales_orders

販売注文。v1では明細(DocumentLines)はexpandなしで含まれます(expandはv2のみ)

sap_get_stock

ItemCodeによる品目の在庫(+ オプションでWarehouseCode)。ServiceLayerにItemStockが存在しない場合(古いv1)は明確なエラー

sap_session_status

アクティブなセッションの状態

sap_logout

セッションの明示的な終了

書き込み(SAP_B1_READONLY=falseの場合のみ)

Tool

説明

sap_create

エンティティにレコードを作成(POST

sap_update

キーでレコードを更新(PATCH

sap_delete

キーでレコードを削除(DELETE

sap_call_action

サービスメソッドを呼び出し(POST)。副作用がある可能性があります(Cancel、UpdateCompanyInfo、Importなど)

要件

  • Node.js 18+

  • SAP Business One 10.0でServiceLayerが有効(一般的なパスはhttps://<host>:50000/b1s/v1

  • opencode(または任意のMCPクライアント)

設定(環境変数)

Variable

必須

デフォルト

説明

SAP_B1_SERVER_URL

はい

-

ServiceLayerのベースURL(例: https://<host>:50000/b1s/v1

SAP_B1_DATABASE

はい

-

CompanyDB名(例: SBODEMO_XX

SAP_B1_USERNAME

はい

-

ServiceLayerのユーザー名

SAP_B1_PASSWORD

はい

-

ユーザーのパスワード

SAP_B1_READONLY

いいえ

true

falseで書き込みツールを有効化

SAP_B1_VERIFY_TLS

いいえ

true

falseで自己署名証明書を許可

SAP_B1_MAX_TOP

いいえ

200

クエリごとのtopの最大制限

opencodeでの使用

プロジェクトのopencode.jsonに:

{
  "mcp": {
    "sap-b1-servicelayer": {
      "type": "local",
      "command": ["npx", "-y", "github:leonardows1/sap-b1-servicelayer-mcp"],
      "environment": {
        "SAP_B1_SERVER_URL": "https://<host>:50000/b1s/v1",
        "SAP_B1_DATABASE": "<CompanyDB>",
        "SAP_B1_USERNAME": "<usuario>",
        "SAP_B1_PASSWORD": "<password>",
        "SAP_B1_SESSION_TIMEOUT": "30",
        "SAP_B1_VERIFY_TLS": "false",
        "SAP_B1_READONLY": "true"
      },
      "enabled": true
    }
  }
}

設定を保存した後、opencodeを再起動してください。

セキュリティ

  • 資格情報とセッションクッキーはログに記録されることはありません。

  • プロセスはSAP_B1_SERVER_URLとのみ通信します。

  • READONLY=trueモードでは書き込みツールは登録されません。設計上、レコードの作成/更新/削除は不可能です。

  • 起動時に設定を検証: SAP_B1_SERVER_URLSAP_B1_DATABASESAP_B1_USERNAMESAP_B1_PASSWORDが欠けている場合、プロセスは明確なメッセージで中止します。

  • エンティティ名は検証済み(^[A-Za-z][A-Za-z0-9_]*$): パスの注入はできません(例: BusinessPartners/...)。

  • キー値とフィルタはODataでエスケープされます(一重引用符を二重化): 'を含むidItemCodeはURLや$filterを壊しません。

  • パスワードはMCPクライアントの設定に平文で残ります。リポジトリを共有する場合はシークレットマネージャーを検討してください。

  • npx github:にはsemverバージョン管理がありません。実行ごとにmainブランチの最新版を取得します。リポジトリを更新した後は、npm cache clean --forceを使用して再読み込みを強制してください。

構造

実用的なヘキサゴナルアーキテクチャ(ESM、フレームワークなし): ドメインとユースケースはMCPトランスポートやHTTPを認識しません。インフラストラクチャはServiceLayerPort(DIP)を実装し、MCPツールは薄いコントローラーです。

sap-b1-servicelayer-mcp/
├── package.json                  # Definición del paquete npm (bin: server.js)
├── server.js                     # Composition root: cablea dependencias y arranca stdio
├── src/
│   ├── config/
│   │   └── config.js             # Configuración desde env, validada e inmutable
│   ├── domain/
│   │   ├── errors.js             # Excepciones tipadas (Configuration/InvalidArgument/ServiceLayer)
│   │   ├── oData.js              # Helpers puros: query string, filtros, clamp de $top, validación de entidad
│   │   └── edmx.js               # Parseo puro de $metadata: entity sets, esquemas, function imports
│   ├── application/
│   │   ├── ports.js              # Puerto ServiceLayerPort (contrato, DIP)
│   │   ├── helpers.js            # ensureOk / ensureSuccess / unwrapValue
│   │   └── services/
│   │       ├── queryService.js   # Consulta GET genérica a entidades OData
│   │       ├── catalogService.js # Socios de negocio y artículos (compone QueryService)
│   │       ├── salesService.js   # Pedidos de venta y stock
│   │       ├── sessionService.js # Estado y cierre de sesión
│   │       ├── writeService.js   # create / update / delete
│   │       ├── metadataService.js # Descubrimiento: $metadata cacheado, entidades, esquemas y actions
│   │       └── sqlService.js     # SQL de solo lectura (SELECT/WITH) vía POST /sql_query
│   └── infrastructure/
│       ├── http/
│       │   ├── httpClient.js     # Cliente HTTP mínimo (http/https)
│       │   ├── cookies.js        # Manipulación pura de cookies de sesión
│       │   └── serviceLayerClient.js # Adaptador del puerto: login, 401, logout
│       └── mcp/
│           ├── result.js         # ok / err / serialize / handle (controladores delgados)
│           └── tools.js          # Registro de tools MCP
├── test/                         # node:test (sin dependencias externas)
│   ├── config.test.js
│   ├── oData.test.js
│   ├── edmx.test.js              # parseo EDMX v3/v4 (entity sets, esquemas, function imports)
│   ├── cookies.test.js
│   ├── client.test.js
│   ├── fakePort.js               # fake tipado del puerto ServiceLayerPort (compartido)
│   ├── services.test.js          # casos de uso con cliente fake (anti-inyección)
│   ├── metadataService.test.js   # descubrimiento y acciones con fake
│   ├── sqlService.test.js        # SQL solo-lectura (rechazos, Service Not Found)
│   └── tools.test.js             # integración MCP in-memory (registro y llamadas)
├── .gitignore
└── README.md

実際のスキーマへの適応(ServiceLayer 10.0 v1で検証済み)

サーバーは各インスタンスの$metadataに動的に適応し、ハードコードされたものはありません。実際のインスタンス(v1、OData v3)で検証された事実:

  • エンティティセットがEntityTypeを共有: Orders/Invoices/DeliveryNotesSAPB1.Documentsap_get_entity_schemaは実際の型を自動的に解決します。

  • ドキュメント明細: v1では複合コレクションDocumentLinesDocumentInstallments)であり、レスポンスにインラインで含まれます。$expandはnavigationPropertiesにのみ適用されます(スキーマにリストされます。例: BusinessPartnerCurrency)。

  • 財務フィールド: v1ではBusinessPartnersBalanceはありません。CurrentAccountBalanceOpenOrdersBalanceOpenDeliveryNotesBalanceを使用します。請求書にはBalanceDueはありません。未収残高はDocTotal − PaidToDateです。

  • 古いv1にはItemStock/sql_queryもありません: sap_get_stockは検出された実際の在庫エンティティで通知します。sap_sql_queryは明確なエラーを返します。

  • v3のfunction importsIsBindable="true"のものはboundとしてリストされ(単独では呼び出し不可)、sap_list_actionsを汚染しません。

レシピ: 残高のエイジングレポート(30/60/90)

SQLなし、sap_queryのみ(任意のv1/v2で動作):

  1. 未払い請求書(多い場合はskipで200件以下のバッチにページング):

    sap_query('Invoices',
      filter='PaidToDate lt DocTotal',
      select='CardCode,CardName,DocNum,DocDate,DocDueDate,DocTotal,PaidToDate,DocumentStatus,ControlAccount')
  2. 各請求書について: saldo = DocTotal − PaidToDate; días = 今日 − DocDueDate

  3. **0-30 / 31-60 / 61-90 / 90+**の範囲と顧客ごとにグループ化(または勘定科目ビューの場合はControlAccountごと)。

  4. 顧客/勘定科目ごとの合計: sap_get_business_partnersCurrentAccountBalance(現在の残高)とCreditLimitを使用。

sap_sql_query(v2)を使用すると、同じレポートはOINV/OINV3/OFRJ/OCRDに対する単一のクエリになります。

開発

npm install     # dependencias
npm test        # tests (node:test)
npm run typecheck  # verificación de tipos estricta (tsc --noEmit sobre JSDoc)
npm start       # arranque local (requiere variables de entorno)

すべてのJSコードはJSDocを介して厳格なTypeScriptで検証されています(checkJs + strict + noUncheckedIndexedAccess)。tsconfig.jsonはビルドステップなしで、サーバーはnodeで直接実行されます。

手動検証(stdio経由のJSON-RPC)

echo '{"jsonrpc":"2.0","method":"tools/list","id":1}' | \
  SAP_B1_SERVER_URL=... SAP_B1_DATABASE=... SAP_B1_USERNAME=... SAP_B1_PASSWORD=... \
  npx -y github:leonardows1/sap-b1-servicelayer-mcp
F
license - not found
Not graded
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • F
    license
    A
    quality
    D
    maintenance
    Enables AI assistants to integrate with SAP systems via OData REST APIs for querying entity sets, performing CRUD operations, and executing function imports. It features automatic service discovery, CSRF token management, and smart connection handling without requiring the SAP RFC SDK.
    11
    12
  • F
    license
    A
    quality
    C
    maintenance
    Enables interaction with SAP S/4HANA systems via OData, allowing service discovery, metadata exploration, field value retrieval, and CRUD operations through natural language.
    4
    5
  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables interaction with SAP Business One via Service Layer REST API to retrieve and create business data such as partners, orders, invoices, items, and stock levels through natural language.
    1

View all related MCP servers

Related MCP Connectors

  • Self-hosted MCP gateway: turn any API, database or MCP server into AI connectors — no code.

  • Odoo ERP for AI agents: hosted OAuth endpoint, gated writes, one endpoint for every instance.

  • Connect your AI assistants to Keboola and expose your data, transformations, SQL queries, ...

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/leonardows1/sap-b1-servicelayer-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server