sap-b1-mcp-server
Version:
SAP Business One Service Layer MCP Server
564 lines (440 loc) ⢠13 kB
Markdown
A professional TypeScript MCP (Model Context Protocol) server that integrates with SAP Business One Service Layer API. This server provides efficient, session-managed access to SAP B1 data through a comprehensive set of MCP tools.
## Features
- **Session Management**: Intelligent session handling with automatic renewal to avoid repeated logins
- **Comprehensive API Coverage**: Support for business partners, items, sales orders, invoices, and custom queries
- **Multiple Transport Options**: STDIO, HTTP, and Streaming HTTP (SSE) with API key authentication
- **Production Ready**: Professional error handling, logging, and configuration management
- **Type Safe**: Full TypeScript implementation with comprehensive type definitions
- **Efficient**: Reuses sessions and implements proper caching strategies
## Prerequisites
- **Bun** >= 1.0.0 ([Install Bun](https://bun.sh/))
- **Node.js** >= 18 (for Node.js compatibility mode)
- **SAP Business One** with Service Layer enabled
```bash
bun install
bun run build
```
Set up your SAP B1 connection using environment variables:
```bash
export SAP_B1_SERVER_URL="https://your-sap-server:50000/b1s/v1"
export SAP_B1_DATABASE="YOUR_COMPANY_DB"
export SAP_B1_USERNAME="manager"
export SAP_B1_PASSWORD="your-password"
export SAP_B1_SESSION_TIMEOUT="30"
```
Or create a `config.json` file (see [Configuration](
**STDIO Transport (default for MCP clients):**
```bash
bun start
```
**š„ Streaming HTTP Transport (production HTTP with full MCP support + API key auth):**
```bash
export MCP_TRANSPORT=streaming-http
export MCP_API_KEY="your-secure-api-key"
bun start
```
**Basic HTTP Transport (health monitoring only):**
```bash
export MCP_TRANSPORT=http
bun start
```
```bash
bun run docker:build
cp .env.docker .env
bun run docker:compose:up
```
The Docker image is highly optimized (~50-80MB) using Alpine Linux and Bun runtime. See [DOCKER.md](DOCKER.md) for complete Docker deployment guide.
### Docker Features
- **Minimal size**: Multi-stage build with Alpine base
- **Security hardened**: Non-root user, read-only filesystem
- **Health checks**: Built-in container health monitoring
- **Resource optimized**: Memory and CPU limits
- **Production ready**: Kubernetes and Docker Compose configs
## š„ **Streaming HTTP Transport (NEW!)**
Full production-ready HTTP transport with complete MCP protocol support:
**Key Features:**
- ā
**Full MCP Protocol**: All 14 tools work over HTTP
- š **API Key Authentication**: Secure access with configurable keys
- š” **Server-Sent Events (SSE)**: Real-time streaming communication
- š”ļø **Production Security**: CORS, request validation, connection management
- š **Monitoring**: Health checks, connection stats, performance metrics
**Quick Start:**
```bash
# Configure streaming HTTP
export MCP_TRANSPORT=streaming-http
export MCP_API_KEY=your-secure-api-key-here
bun start
curl -H "X-API-Key: your-key" http://localhost:3000/mcp/auth
```
**Complete Documentation:** See [STREAMING-HTTP.md](STREAMING-HTTP.md) for full API documentation, examples, and integration guides.
The server supports configuration through environment variables or a JSON configuration file.
| Variable | Required | Description | Default |
|----------|----------|-------------|---------|
| `SAP_B1_SERVER_URL` | ā
| SAP B1 Service Layer URL | - |
| `SAP_B1_DATABASE` | ā
| Company database name | - |
| `SAP_B1_USERNAME` | ā
| SAP B1 username | - |
| `SAP_B1_PASSWORD` | ā
| SAP B1 password | - |
| `SAP_B1_SESSION_TIMEOUT` | ā | Session timeout in minutes | `30` |
| `MCP_TRANSPORT` | ā | Transport type (`stdio` or `http`) | `stdio` |
| `MCP_HTTP_PORT` | ā | HTTP server port | `3000` |
| `MCP_HTTP_HOST` | ā | HTTP server host | `localhost` |
| `LOG_LEVEL` | ā | Log level (`ERROR`, `WARN`, `INFO`, `DEBUG`) | `INFO` |
| `NODE_ENV` | ā | Environment (`development`, `production`, `test`) | `development` |
### Configuration File
Create a `config.json` file in the project root:
```json
{
"serverUrl": "https://your-sap-server:50000/b1s/v1",
"database": "YOUR_COMPANY_DB",
"username": "manager",
"password": "your-password",
"sessionTimeout": 30
}
```
Run with configuration file:
```bash
bun start config.json
```
Establish a new session with SAP Business One.
**Parameters:**
- `force` (boolean, optional): Force new login even if session exists
**Example:**
```json
{
"force": false
}
```
Terminate the current SAP Business One session.
Check the validity and details of the current session.
Retrieve customers/vendors with optional filtering.
**Parameters:**
- `filter` (string): OData $filter expression
- `select` (string): Fields to select
- `orderby` (string): Sort expression
- `top` (number): Max records
- `skip` (number): Skip records
- `cardType` (string): Filter by type (`cCustomer`, `cSupplier`, `cLid`)
**Examples:**
```json
{
"filter": "CardType eq 'cCustomer'",
"select": "CardCode,CardName,EmailAddress",
"top": 10
}
```
```json
{
"cardType": "cCustomer",
"filter": "CardName contains 'Microsoft'",
"orderby": "CardName asc"
}
```
Create a new business partner.
**Example:**
```json
{
"CardName": "New Customer Corp",
"CardType": "cCustomer",
"EmailAddress": "contact@newcustomer.com",
"Phone1": "555-0123",
"Address": "123 Business St",
"ZipCode": "12345"
}
```
Update an existing business partner.
**Example:**
```json
{
"CardCode": "C20000",
"updates": {
"Phone1": "555-9999",
"EmailAddress": "newemail@customer.com"
}
}
```
Retrieve items with optional filtering.
**Example:**
```json
{
"filter": "SalesItem eq 'tYES' and QuantityOnStock gt 0",
"select": "ItemCode,ItemName,QuantityOnStock,Price",
"orderby": "ItemName asc"
}
```
Create a new item.
**Example:**
```json
{
"ItemName": "New Product",
"SalesItem": "tYES",
"PurchaseItem": "tYES",
"InventoryItem": "tYES"
}
```
Retrieve sales orders with optional filtering.
**Example:**
```json
{
"filter": "DocDate ge '2024-01-01' and CardCode eq 'C20000'",
"expand": "DocumentLines",
"orderby": "DocDate desc"
}
```
Create a new sales order.
**Example:**
```json
{
"CardCode": "C20000",
"DocDate": "2024-01-15",
"DocDueDate": "2024-02-15",
"Comments": "Urgent order",
"DocumentLines": [
{
"ItemCode": "A00001",
"Quantity": 5,
"Price": 100.00
},
{
"ItemCode": "A00002",
"Quantity": 2,
"Price": 250.00
}
]
}
```
Retrieve invoices with optional filtering.
Create a new invoice.
**Example:**
```json
{
"CardCode": "C20000",
"DocDate": "2024-01-15",
"DocumentLines": [
{
"BaseType": 17,
"BaseEntry": 123,
"BaseLine": 0,
"Quantity": 5
}
]
}
```
Execute custom OData queries against any SAP B1 entity.
**Parameters:**
- `entityType` (string): Entity to query (e.g., `BusinessPartners`, `Items`, `Orders`)
- `filter`, `select`, `expand`, `orderby`, `top`, `skip`: OData query options
**Example:**
```json
{
"entityType": "Orders",
"filter": "DocTotal gt 1000 and DocDate ge '2024-01-01'",
"select": "DocEntry,DocNum,CardCode,DocTotal,DocDate",
"expand": "DocumentLines",
"orderby": "DocTotal desc",
"top": 50
}
```
Execute cross-join queries for complex data relationships.
**Example:**
```json
{
"entities": ["BusinessPartners", "Orders"],
"filter": "BusinessPartners/CardCode eq Orders/CardCode",
"select": "BusinessPartners/CardName,Orders/DocTotal"
}
```
```bash
{
"tool": "sap_get_business_partners",
"arguments": {
"cardType": "cCustomer",
"filter": "CardName contains 'Tech'",
"select": "CardCode,CardName,Phone1,EmailAddress",
"top": 10
}
}
```
```bash
{
"tool": "sap_create_order",
"arguments": {
"CardCode": "C20000",
"Comments": "Monthly recurring order",
"DocumentLines": [
{
"ItemCode": "SERVICE-01",
"Quantity": 1,
"Price": 1500.00,
"ItemDescription": "Monthly Service Package"
}
]
}
}
```
```bash
{
"tool": "sap_query",
"arguments": {
"entityType": "Orders",
"filter": "DocStatus eq 'bost_Open' and DocDate ge '2024-01-01'",
"select": "DocEntry,DocNum,CardCode,CardName,DocTotal,DocDate",
"expand": "DocumentLines($select=ItemCode,Quantity,Price,LineTotal)",
"orderby": "DocDate desc,DocTotal desc",
"top": 25
}
}
```
```
src/
āāā index.ts
āāā transports/
ā āāā http.ts
ā āāā stdio.ts
āāā sap/
ā āāā client.ts
ā āāā session.ts
ā āāā types.ts
āāā tools/
ā āāā auth.ts
ā āāā master-data.ts
ā āāā documents.ts
ā āāā queries.ts
āāā utils/
āāā config.ts
āāā logger.ts
```
The server provides comprehensive error handling:
- **SAP API Errors**: Wrapped with meaningful messages
- **Session Management**: Automatic renewal on expiration
- **Network Issues**: Retry logic for transient failures
- **Validation**: Input validation with clear error messages
- **Logging**: Structured logging for debugging
- Passwords and session IDs are masked in logs
- Input sanitization prevents injection attacks
- Session cookies are handled securely
- HTTPS is supported for production deployments
```bash
bun run build
```
```bash
bun run dev
```
```bash
bun run typecheck
```
```bash
bun run docker:build
bun run docker:run
bun run docker:run:stdio
bun run docker:compose:up
bun run docker:compose:down
bun run docker:compose:logs
bun run docker:health
```
1. **Set Production Environment:**
```bash
export NODE_ENV=production
export LOG_LEVEL=INFO
```
2. **Use HTTPS for SAP Connection:**
```bash
export SAP_B1_SERVER_URL="https://your-sap-server:50000/b1s/v1"
```
3. **Configure Session Timeout:**
```bash
export SAP_B1_SESSION_TIMEOUT=60
```
4. **Run with Process Manager:**
**Docker (Recommended):**
```bash
bun run docker:compose:up
kubectl apply -f k8s-deployment.yaml
```
**Traditional Process Managers:**
```bash
pm2 start --interpreter bun dist/index.js --name sap-mcp-server
bun start
systemctl start sap-mcp-server
```
When using HTTP transport, the server provides additional endpoints:
- `GET /health` - Health check
- `GET /info` - Server information
- `POST /message` - MCP message endpoint
Client connection URL: `http://localhost:3000/message`
1. **Connection Refused**: Check SAP B1 Service Layer URL and network connectivity
2. **Authentication Failed**: Verify username, password, and database name
3. **Session Expired**: The server auto-renews sessions, but manual login may be needed
4. **OData Errors**: Check filter syntax and field names
```bash
export LOG_LEVEL=DEBUG
bun start
```
```bash
curl http://localhost:3000/health # For HTTP transport
```
MIT
For issues and feature requests, please check the repository documentation or contact the development team.