SAP B1 ServiceLayer MCP Server
Allows interaction with SAP Business One ServiceLayer, providing tools for querying OData entities, listing and inspecting schemas from $metadata, executing read-only SQL, and retrieving business partners, items, sales orders, and stock. Optional write mode enables create, update, delete, and invoking service actions.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@SAP B1 ServiceLayer MCP ServerWhat's the current stock for item A001?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
SAP B1 ServiceLayer MCP Server
MCP (Model Context Protocol) server to connect AI assistants (opencode, Claude, etc.) to the SAP Business One 10.0 ServiceLayer, on a local network. Runnable with npx from this GitHub repository, without installing anything on the PC.
Features
Read-only by default: with
SAP_B1_READONLY=true(default) only query tools (GET) are registered. Write tools (POST/PATCH/DELETE) do not exist on the server and cannot be called.Full discovery:
sap_list_entities,sap_get_entity_schemaandsap_list_actionsqueryGET /$metadata(downloaded once per process and cached) and expose the ~140 CRUD entities (including user tables@and UDOs) and the hundreds of ServiceLayer service methods.Optional write mode: with
SAP_B1_READONLY=false,sap_create,sap_update,sap_deleteare enabled for ServiceLayer entities andsap_call_actionfor service methods (which may have side effects).Run via
npx github:: no manual installation.Managed session: implicit login with
CompanyDB/username/password,B1SESSION+ROUTEIDcookies kept in memory (supports multi-node ServiceLayer), automatic re-login on401, and guaranteed logout when the process exits (in addition to thesap_logouttool).Self-signed TLS: support for self-signed ServiceLayer certificates (typical in local environments) via
SAP_B1_VERIFY_TLS=false.No telemetry or external calls: the HTTP client points exclusively to the configured URL (
SAP_B1_SERVER_URL).Security limits:
topcapped at 200 records per query.
Related MCP server: BTP MCP Server
Tools
Read (always available)
Tool | Description |
| Generic GET to any OData entity with |
| Lists all OData entities exposed by the ServiceLayer (from |
| Schema of an entity: properties (types/keys) and navigationProperties (valid for |
| Lists the service methods (function imports, e.g. |
| Read-only SQL ( |
| Business partners (customers/vendors), filter by |
| Catalog items |
| Sales orders; in v1 the lines ( |
| Stock of an item by |
| Active session status |
| Explicit session close |
Write (only if SAP_B1_READONLY=false)
Tool | Description |
| Creates a record in an entity ( |
| Updates a record by its key ( |
| Deletes a record by its key ( |
| Invokes a service method ( |
Requirements
Node.js 18+
SAP Business One 10.0 with ServiceLayer enabled (typical path
https://<host>:50000/b1s/v1)opencode (or any MCP client)
Configuration (environment variables)
Variable | Required | Default | Description |
| Yes | - | ServiceLayer base URL (e.g. |
| Yes | - | CompanyDB name (e.g. |
| Yes | - | ServiceLayer user |
| Yes | - | User password |
| No |
|
|
| No |
|
|
| No |
| Maximum |
Usage with opencode
In the project's 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
}
}
}Restart opencode after saving the configuration.
Security
Credentials and session cookies are never logged.
The process only communicates with
SAP_B1_SERVER_URL.In
READONLY=truemode the write tools are not registered: it is impossible to create/update/delete records, by design.Configuration validated at startup: missing
SAP_B1_SERVER_URL,SAP_B1_DATABASE,SAP_B1_USERNAMEorSAP_B1_PASSWORD→ the process aborts with a clear message.Entity names validated (
^[A-Za-z][A-Za-z0-9_]*$): routes cannot be injected (e.g.BusinessPartners/...).Key values and filters escaped in OData (single quotes doubled): an
idorItemCodewith'does not break the URL or the$filter.The password is stored in plain text in the MCP client configuration. Consider a secret manager if the repository is shared.
npx github:has no semver versioning: each run takes the latest version of themainbranch. After updating the repo, usenpm cache clean --forceto force a reload.
Structure
Pragmatic hexagonal architecture (ESM, no framework): the domain and use
cases do not know about the MCP transport or HTTP; the infrastructure
implements the ServiceLayerPort port (DIP) and the MCP tools are thin
controllers.
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.mdAdaptation to the real schema (verified against ServiceLayer 10.0 v1)
The server dynamically adapts to each instance's $metadata, with nothing
hardcoded. Facts verified on a real instance (v1, OData v3):
Entity sets share an EntityType:
Orders/Invoices/DeliveryNotes→SAPB1.Document.sap_get_entity_schemaresolves the real type automatically.Document lines: in v1 they are complex collections (
DocumentLines,DocumentInstallments) that come inline in the response;$expandonly applies to navigationProperties (the schema lists them, e.g.:BusinessPartner,Currency).Financial fields: in v1
BusinessPartnershas noBalance; useCurrentAccountBalance,OpenOrdersBalance,OpenDeliveryNotesBalance. Invoices have noBalanceDue: the open balance isDocTotal − PaidToDate.No
ItemStockor/sql_queryon old v1:sap_get_stockwarns with real stock entities discovered;sap_sql_queryreturns a clear error.V3 function imports with
IsBindable="true"are listed asbound(not invocable standalone) so they do not pollutesap_list_actions.
Recipe: balance aging report (30/60/90)
Without SQL, using only sap_query (works on any v1/v2):
Open invoices (paginate with
skipin batches ≤200 if there are many):sap_query('Invoices', filter='PaidToDate lt DocTotal', select='CardCode,CardName,DocNum,DocDate,DocDueDate,DocTotal,PaidToDate,DocumentStatus,ControlAccount')For each invoice:
balance = DocTotal − PaidToDate;days = today − DocDueDate.Group by ranges 0-30 / 31-60 / 61-90 / 90+ and by customer (or by
ControlAccountfor the view by G/L account).Totals by customer/account:
sap_get_business_partnerswithCurrentAccountBalance(current balance) andCreditLimit.
With sap_sql_query (v2) the same report is a single query against
OINV/OINV3/OFRJ/OCRD.
Development
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)All the JS code is verified with strict TypeScript via JSDoc
(checkJs + strict + noUncheckedIndexedAccess): tsconfig.json with no
build step, the server runs directly with node.
Manual verification (JSON-RPC over stdio)
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 installed
Maintenance
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
- 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
- AlicenseAqualityCmaintenanceConnects AI agents to SAP BTP platform APIs for service discovery, instance management, and destination queries via natural language.51MIT
- FlicenseAqualityCmaintenanceEnables interaction with SAP S/4HANA systems via OData, allowing service discovery, metadata exploration, field value retrieval, and CRUD operations through natural language.45
- 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
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, ...
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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