SAP B1 ServiceLayer MCP Server
SAP B1 ServiceLayer MCP Server
用于将 AI 助手(opencode、Claude 等)连接到本地网络中的 SAP Business One 10.0 ServiceLayer 的 MCP(Model Context Protocol)服务器。可通过 npx 直接从此 GitHub 仓库运行,无需在 PC 上安装任何东西。
功能特性
默认只读:设置
SAP_B1_READONLY=true(默认)时,仅注册查询类工具(GET)。写入类工具(POST/PATCH/DELETE)在服务器上不存在,也无法被调用。完全发现:
sap_list_entities、sap_get_entity_schema和sap_list_actions查询GET /$metadata(每个进程仅下载一次并缓存),并公开 ServiceLayer 的约 140 个 CRUD 实体(包括用户表@和 UDO)以及数百个服务方法。可选写入模式:设置
SAP_B1_READONLY=false时,将为 ServiceLayer 实体启用sap_create、sap_update、sap_delete,并为服务方法启用sap_call_action(这些操作可能产生副作用)。通过
npx github:运行:无需手动安装。会话管理:使用
CompanyDB/用户名/密码隐式登录,B1SESSION+ROUTEIDcookie 保存在内存中(支持多节点 ServiceLayer),遇到401自动重新登录,并在进程关闭时保证注销(另有sap_logout工具)。自签名 TLS:通过
SAP_B1_VERIFY_TLS=false支持 ServiceLayer 的自签名证书(在本地环境中很常见)。无遥测、无外部调用:HTTP 客户端仅指向配置的 URL(
SAP_B1_SERVER_URL)。安全限制:每次查询的
top限制为 200 条记录。
Related MCP server: SAP Business One MCP Server
工具
读取(始终可用)
工具 | 说明 |
| 对任意 OData 实体的通用 GET,支持 |
| 列出 ServiceLayer 暴露的所有 OData 实体(来自 |
| 实体的架构:属性(类型/键)以及 navigationProperties(可用于 |
| 列出服务方法(function imports,例如 |
| 通过 |
| 业务伙伴(客户/供应商),可按 |
| 目录中的物料 |
| 销售订单;在 v1 中行( |
| 按 |
| 当前会话的状态 |
| 显式关闭会话 |
写入(仅当 SAP_B1_READONLY=false 时)
工具 | 说明 |
| 在实体中创建记录( |
| 按键更新记录( |
| 按键删除记录( |
| 调用服务方法( |
要求
Node.js 18+
SAP Business One 10.0,并启用 ServiceLayer(典型路径
https://<host>:50000/b1s/v1)opencode(或任何 MCP 客户端)
配置(环境变量)
变量 | 必填 | 默认值 | 说明 |
| 是 | - | ServiceLayer 的基础 URL(例如: |
| 是 | - | CompanyDB 名称(例如: |
| 是 | - | ServiceLayer 用户 |
| 是 | - | 用户密码 |
| 否 |
| 设为 |
| 否 |
| 设为 |
| 否 |
| 每次查询 |
与 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。
安全性
凭据和会话 cookie 永远不会记录在日志中。
进程仅与
SAP_B1_SERVER_URL通信。在
READONLY=true模式下,写入工具不会被注册:按设计,无法创建/更新/删除记录。启动时校验配置:缺少
SAP_B1_SERVER_URL、SAP_B1_DATABASE、SAP_B1_USERNAME或SAP_B1_PASSWORD时,进程中止并给出明确提示。实体名称经过校验(
^[A-Za-z][A-Za-z0-9_]*$):无法注入路径(例如BusinessPartners/...)。OData 中的键值和筛选条件已转义(单引号加倍):包含
'的id或ItemCode不会破坏 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/DeliveryNotes→SAPB1.Document。sap_get_entity_schema会自动解析真实类型。文档行:在 v1 中是 复杂集合(
DocumentLines、DocumentInstallments),会内联在响应中;$expand仅适用于 navigationProperties(架构会列出这些属性,例如BusinessPartner、Currency)。财务字段:在 v1 中
BusinessPartners没有Balance;请使用CurrentAccountBalance、OpenOrdersBalance、OpenDeliveryNotesBalance。发票没有BalanceDue:未结余额为DocTotal − PaidToDate。旧版 v1 中没有
ItemStock或/sql_query:sap_get_stock会以发现的真实库存实体发出提示;sap_sql_query返回明确错误。v3 function imports 带有
IsBindable="true"的会被列为bound(不能独立调用),以免污染sap_list_actions。
配方:余额账龄报告(30/60/90)
无需 SQL,仅使用 sap_query(适用于任何 v1/v2):
未结发票(如果很多,使用
skip按 ≤200 条分批翻页):sap_query('Invoices', filter='PaidToDate lt DocTotal', select='CardCode,CardName,DocNum,DocDate,DocDueDate,DocTotal,PaidToDate,DocumentStatus,ControlAccount')对每张发票:
saldo = DocTotal − PaidToDate;días = hoy − DocDueDate。按 0-30 / 31-60 / 61-90 / 90+ 区间和客户分组(或按
ControlAccount查看总账科目视图)。按客户/科目的合计:
sap_get_business_partners包含CurrentAccountBalance(当前余额)和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-mcpThis server cannot be deployed
Maintenance
Related MCP Connectors
Any REST/SOAP/GraphQL/OData/SQL API as MCP tools for Claude & ChatGPT. 299 connectors: SAP, ERP.
Connect any AI agent to 1,000+ apps and 27,000+ actions through one remote MCP server (OAuth).
Connect any AI assistant to Odoo 16–19 via OAuth 2.0 + PKCE. 400 free calls, no local install.
- ZapierOAuthcom.zapier
Hosted MCP server connecting AI assistants to 9,000+ apps and 40,000+ actions via Zapier.
Related MCP Servers
- FlicenseAqualityDmaintenanceEnables 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.1112-
- FlicenseNot gradedqualityDmaintenanceEnables 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-
- FlicenseNot gradedqualityCmaintenanceEnables interaction with SAP Business One Service Layer through MCP, providing tools for querying entities, checking sessions, and executing OData requests with optional write protection.-
- AlicenseNot gradedqualityAmaintenanceEnables AI assistants and n8n workflows to interact with SAP S/4HANA and ECC systems via OData, IDoc, and RFC/BAPI, with governed read-only-by-default access and multiple authentication types.3ISC