Skip to main content
Glama
leonardows1

SAP B1 ServiceLayer MCP Server

by leonardows1

SAP B1 ServiceLayer MCP Server

Servidor MCP (Model Context Protocol) para conectar asistentes de IA (opencode, Claude, etc.) al ServiceLayer de SAP Business One 10.0, en red local. Ejecutable con npx desde este repositorio de GitHub, sin instalar nada en el PC.

Características

  • Solo lectura por defecto: con SAP_B1_READONLY=true (default) solo se registran tools de consulta (GET). Los tools de escritura (POST/PATCH/DELETE) no existen en el servidor y no pueden llamarse.

  • Descubrimiento total: sap_list_entities, sap_get_entity_schema y sap_list_actions consultan GET /$metadata (descargado una sola vez por proceso y cacheado) y exponen las ~140 entidades CRUD (incluidas tablas de usuario @ y UDOs) y los cientos de métodos de servicio del ServiceLayer.

  • Modo escritura opcional: con SAP_B1_READONLY=false se habilitan sap_create, sap_update, sap_delete para entidades del ServiceLayer y sap_call_action para métodos de servicio (pueden tener efectos colaterales).

  • Ejecución vía npx github:: sin instalación manual.

  • Sesión gestionada: login implícito con CompanyDB/usuario/contraseña, cookies B1SESSION + ROUTEID mantenidas en memoria (soporta ServiceLayer multi-nodo), re-login automático ante 401 y logout garantizado al cerrarse el proceso (además del tool sap_logout).

  • TLS autofirmado: soporte para certificados autofirmados del ServiceLayer (típico en entornos locales) mediante SAP_B1_VERIFY_TLS=false.

  • Sin telemetría ni llamadas externas: el cliente HTTP apunta exclusivamente a la URL configurada (SAP_B1_SERVER_URL).

  • Límites de seguridad: top acotado a 200 registros por consulta.

Related MCP server: BTP MCP Server

Tools

Lectura (siempre disponibles)

Tool

Descripción

sap_query

GET genérico a cualquier entidad OData con select, filter, top (≤200), skip, orderby, expand

sap_list_entities

Lista todas las entidades OData expuestas por el ServiceLayer (desde $metadata, cacheado); incluye tablas de usuario (@) y UDOs. filter opcional para acotar

sap_get_entity_schema

Esquema de una entidad: propiedades (tipos/claves) y navigationProperties (válidas para $expand); resuelve entity sets que comparten EntityType

sap_list_actions

Lista los métodos de servicio (function imports, ej: CompanyService_GetCompanyInfo) con sus parámetros

sap_sql_query

SQL de solo lectura (SELECT/WITH; INSERT/UPDATE/DELETE/DDL rechazados) vía POST /sql_query — solo en ServiceLayer v2/FP recientes; en v1 antiguos responde error claro

sap_get_business_partners

Socios de negocio (clientes/proveedores), filtro por card_type

sap_get_items

Artículos del catálogo

sap_get_sales_orders

Pedidos de venta; en v1 las líneas (DocumentLines) vienen incluidas sin expand (expand es solo v2)

sap_get_stock

Stock de un artículo por ItemCode (+ WarehouseCode opcional); error claro si ItemStock no existe en el ServiceLayer (v1 antiguos)

sap_session_status

Estado de la sesión activa

sap_logout

Cierre explícito de la sesión

Escritura (solo si SAP_B1_READONLY=false)

Tool

Descripción

sap_create

Crea un registro en una entidad (POST)

sap_update

Actualiza un registro por su clave (PATCH)

sap_delete

Elimina un registro por su clave (DELETE)

sap_call_action

Invoca un método de servicio (POST); puede tener efectos colaterales (Cancel, UpdateCompanyInfo, Import...)

Requisitos

  • Node.js 18+

  • SAP Business One 10.0 con ServiceLayer habilitado (ruta típica https://<host>:50000/b1s/v1)

  • opencode (o cualquier cliente MCP)

Configuración (variables de entorno)

Variable

Requerida

Default

Descripción

SAP_B1_SERVER_URL

-

URL base del ServiceLayer (ej: https://<host>:50000/b1s/v1)

SAP_B1_DATABASE

-

Nombre de la CompanyDB (ej: SBODEMO_XX)

SAP_B1_USERNAME

-

Usuario del ServiceLayer

SAP_B1_PASSWORD

-

Contraseña del usuario

SAP_B1_READONLY

No

true

false habilita los tools de escritura

SAP_B1_VERIFY_TLS

No

true

false para certificados autofirmados

SAP_B1_MAX_TOP

No

200

Límite máximo de top por consulta

Uso con opencode

En opencode.json del proyecto:

{
  "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
    }
  }
}

Reiniciar opencode después de guardar la configuración.

Seguridad

  • Credenciales y cookies de sesión nunca se registran en logs.

  • El proceso solo se comunica con SAP_B1_SERVER_URL.

  • En modo READONLY=true los tools de escritura no se registran: es imposible crear/actualizar/eliminar registros, por diseño.

  • Configuración validada al arrancar: faltan SAP_B1_SERVER_URL, SAP_B1_DATABASE, SAP_B1_USERNAME o SAP_B1_PASSWORD → el proceso aborta con mensaje claro.

  • Nombres de entidad validados (^[A-Za-z][A-Za-z0-9_]*$): no se pueden inyectar rutas (ej: BusinessPartners/...).

  • Valores de clave y filtros escapados en OData (comillas simples duplicadas): un id o ItemCode con ' no rompe la URL ni el $filter.

  • La contraseña queda en texto plano en la configuración del cliente MCP. Considerar un secret manager si se comparte el repositorio.

  • npx github: no tiene versionado semver: cada ejecución toma la última versión del branch main. Tras actualizar el repo, usar npm cache clean --force para forzar la recarga.

Estructura

Arquitectura hexagonal pragmática (ESM, sin framework): el dominio y los casos de uso no conocen el transporte MCP ni el HTTP; la infraestructura implementa el puerto ServiceLayerPort (DIP) y los tools MCP son controladores delgados.

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

Adaptación al esquema real (verificado contra ServiceLayer 10.0 v1)

El servidor se adapta dinámicamente al $metadata de cada instancia, sin nada hardcodeado. Hechos verificados en una instancia real (v1, OData v3):

  • Entity sets comparten EntityType: Orders/Invoices/DeliveryNotesSAPB1.Document. sap_get_entity_schema resuelve el tipo real automáticamente.

  • Líneas de documento: en v1 son complex collections (DocumentLines, DocumentInstallments) que vienen inline en la respuesta; $expand solo aplica a navigationProperties (el esquema las lista, ej: BusinessPartner, Currency).

  • Campos financieros: en v1 BusinessPartners no tiene Balance; usa CurrentAccountBalance, OpenOrdersBalance, OpenDeliveryNotesBalance. Las facturas no tienen BalanceDue: el saldo abierto es DocTotal − PaidToDate.

  • Sin ItemStock ni /sql_query en v1 antiguos: sap_get_stock avisa con entidades de stock reales descubiertas; sap_sql_query devuelve error claro.

  • Function imports v3 con IsBindable="true" se listan como bound (no invocables standalone) para no contaminar sap_list_actions.

Receta: reporte de antigüedad de saldos (30/60/90)

Sin SQL, solo con sap_query (funciona en cualquier v1/v2):

  1. Facturas abiertas (paginar con skip en lotes ≤200 si hay muchas):

    sap_query('Invoices',
      filter='PaidToDate lt DocTotal',
      select='CardCode,CardName,DocNum,DocDate,DocDueDate,DocTotal,PaidToDate,DocumentStatus,ControlAccount')
  2. Por cada factura: saldo = DocTotal − PaidToDate; días = hoy − DocDueDate.

  3. Agrupar por rangos 0-30 / 31-60 / 61-90 / 90+ y por cliente (o por ControlAccount para la vista por cuenta contable).

  4. Totales por cliente/cuenta: sap_get_business_partners con CurrentAccountBalance (saldo actual) y CreditLimit.

Con sap_sql_query (v2) el mismo reporte es una sola query sobre OINV/OINV3/OFRJ/OCRD.

Desarrollo

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)

Todo el código JS está verificado con TypeScript estricto vía JSDoc (checkJs + strict + noUncheckedIndexedAccess): tsconfig.json sin build step, el servidor se ejecuta directo con node.

Verificación manual (JSON-RPC por 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-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