# SAP Business One Service Layer MCP Server

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

## Quick Start

### 1. Installation

```bash
bun install
bun run build
```

### 2. Configuration

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](#configuration) section below).

### 3. Run the Server

**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
```

## Docker Deployment

### Quick Docker Start

```bash
# Build the optimized Docker image
bun run docker:build

# Configure environment
cp .env.docker .env
# Edit .env with your SAP B1 credentials

# Run with Docker Compose (recommended)
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

# Test the API
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.

## Configuration

The server supports configuration through environment variables or a JSON configuration file.

### Environment Variables

| 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
```

## Available Tools

### Authentication & Session Management

#### `sap_login`
Establish a new session with SAP Business One.

**Parameters:**
- `force` (boolean, optional): Force new login even if session exists

**Example:**
```json
{
  "force": false
}
```

#### `sap_logout`
Terminate the current SAP Business One session.

#### `sap_session_status`
Check the validity and details of the current session.

### Master Data Operations

#### `sap_get_business_partners`
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"
}
```

#### `sap_create_business_partner`
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"
}
```

#### `sap_update_business_partner`
Update an existing business partner.

**Example:**
```json
{
  "CardCode": "C20000",
  "updates": {
    "Phone1": "555-9999",
    "EmailAddress": "newemail@customer.com"
  }
}
```

#### `sap_get_items`
Retrieve items with optional filtering.

**Example:**
```json
{
  "filter": "SalesItem eq 'tYES' and QuantityOnStock gt 0",
  "select": "ItemCode,ItemName,QuantityOnStock,Price",
  "orderby": "ItemName asc"
}
```

#### `sap_create_item`
Create a new item.

**Example:**
```json
{
  "ItemName": "New Product",
  "SalesItem": "tYES",
  "PurchaseItem": "tYES",
  "InventoryItem": "tYES"
}
```

### Document Operations

#### `sap_get_orders`
Retrieve sales orders with optional filtering.

**Example:**
```json
{
  "filter": "DocDate ge '2024-01-01' and CardCode eq 'C20000'",
  "expand": "DocumentLines",
  "orderby": "DocDate desc"
}
```

#### `sap_create_order`
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
    }
  ]
}
```

#### `sap_get_invoices`
Retrieve invoices with optional filtering.

#### `sap_create_invoice`
Create a new invoice.

**Example:**
```json
{
  "CardCode": "C20000",
  "DocDate": "2024-01-15",
  "DocumentLines": [
    {
      "BaseType": 17,
      "BaseEntry": 123,
      "BaseLine": 0,
      "Quantity": 5
    }
  ]
}
```

### Query Operations

#### `sap_query`
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
}
```

#### `sap_cross_join`
Execute cross-join queries for complex data relationships.

**Example:**
```json
{
  "entities": ["BusinessPartners", "Orders"],
  "filter": "BusinessPartners/CardCode eq Orders/CardCode",
  "select": "BusinessPartners/CardName,Orders/DocTotal"
}
```

## Usage Examples

### Basic Customer Lookup

```bash
# Using with Claude or other MCP clients
{
  "tool": "sap_get_business_partners",
  "arguments": {
    "cardType": "cCustomer",
    "filter": "CardName contains 'Tech'",
    "select": "CardCode,CardName,Phone1,EmailAddress",
    "top": 10
  }
}
```

### Creating a Sales Order

```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"
      }
    ]
  }
}
```

### Complex Query

```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
  }
}
```

## Architecture

```
src/
├── index.ts              # Main server entry point
├── transports/
│   ├── http.ts          # HTTP transport implementation  
│   └── stdio.ts         # STDIO transport implementation
├── sap/
│   ├── client.ts        # SAP B1 API client
│   ├── session.ts       # Session management
│   └── types.ts         # SAP B1 TypeScript types
├── tools/
│   ├── auth.ts          # Authentication tools
│   ├── master-data.ts   # Master data tools
│   ├── documents.ts     # Document tools
│   └── queries.ts       # Query tools
└── utils/
    ├── config.ts        # Configuration management
    └── logger.ts        # Logging utilities
```

## Error Handling

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

## Security Considerations

- Passwords and session IDs are masked in logs
- Input sanitization prevents injection attacks
- Session cookies are handled securely
- HTTPS is supported for production deployments

## Development

### Building

```bash
bun run build
```

### Development Mode (with hot reload)

```bash
bun run dev
```

### Type Checking

```bash
bun run typecheck
```

### Docker Commands

```bash
# Build Docker image
bun run docker:build

# Run with HTTP transport
bun run docker:run

# Run with STDIO transport  
bun run docker:run:stdio

# Docker Compose operations
bun run docker:compose:up    # Start services
bun run docker:compose:down  # Stop services
bun run docker:compose:logs  # View logs

# Health check
bun run docker:health
```

## Production Deployment

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  # Longer timeout for production
   ```

4. **Run with Process Manager:**

   **Docker (Recommended):**
   ```bash
   # Production with Docker Compose
   bun run docker:compose:up
   
   # Or Kubernetes deployment
   kubectl apply -f k8s-deployment.yaml
   ```

   **Traditional Process Managers:**
   ```bash
   # Using PM2 with Bun
   pm2 start --interpreter bun dist/index.js --name sap-mcp-server
   
   # Or run directly with Bun
   bun start
   
   # Or using systemd service
   systemctl start sap-mcp-server
   ```

## HTTP Transport Usage

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`

## Troubleshooting

### Common Issues

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

### Debug Logging

```bash
export LOG_LEVEL=DEBUG
bun start
```

### Health Check

```bash
curl http://localhost:3000/health  # For HTTP transport
```

## License

MIT

## Support

For issues and feature requests, please check the repository documentation or contact the development team.