@mcp-abap-adt/connection
Version:
ABAP connection layer for MCP ABAP ADT server
525 lines (394 loc) • 17.5 kB
Markdown
# @mcp-abap-adt/connection
[](https://stand-with-ukraine.pp.ua)
ABAP connection layer for MCP ABAP ADT server. Provides a unified interface for connecting to SAP ABAP systems via ADT (ABAP Development Tools) protocol, supporting both on-premise (Basic Auth) and cloud (JWT/OAuth2) authentication methods.
## Key Features
- 🔐 **Multiple Authentication Methods**:
- Basic Auth for on-premise SAP systems
- JWT/OAuth2 for SAP BTP ABAP Environment
- SAML session cookies for pre-authenticated enterprise flows
- 🔄 **Token Management**:
- Token refresh is handled by `@mcp-abap-adt/auth-broker` package
- Connection package focuses on HTTP communication only
- 💾 **Session Management**:
- Session headers management (cookies, CSRF tokens)
- Session state persistence is handled by `@mcp-abap-adt/auth-broker` package
- 🏗️ **Clean Architecture**:
- Abstract base class for common HTTP/session logic
- Auth-type specific implementations (BaseAbapConnection, JwtAbapConnection, SamlAbapConnection)
- Proper separation of concerns - no JWT logic in base class
- 🔌 **Realtime Transport Scaffold**:
- Generic `GenericWebSocketTransport` with pluggable WS factory
- Reusable for debugger/traces and other event-driven flows
- 📝 **Custom Logging**: Pluggable logger interface for integration with any logging system
- 🛠️ **CLI Tool**: See [JWT Auth Tools](./docs/JWT_AUTH_TOOLS.md) for obtaining SAP BTP tokens
- 📦 **TypeScript**: Full TypeScript support with type definitions included
- ⚡ **Timeout Management**: Configurable timeouts for different operation types
## Architecture
The package uses a clean separation of concerns:
- **`AbstractAbapConnection`** (abstract, internal only):
- Common HTTP request logic
- Session management (cookies, CSRF tokens)
- CSRF token fetching with retry
- Auth-agnostic - knows nothing about Basic or JWT
- **`BaseAbapConnection`** (concrete, exported):
- Basic Authentication implementation
- Simple connect() - fetches CSRF token
- Suitable for on-premise SAP systems
- **`JwtAbapConnection`** (concrete, exported):
- JWT/OAuth2 Authentication implementation
- Simple connect() - establishes connection with JWT token
- Suitable for SAP BTP ABAP Environment
- Token refresh handled by auth-broker package
- **`SamlAbapConnection`** (concrete, exported):
- Session-cookie-based authentication (`authType: "saml"`)
- Uses existing SSO/SAML session cookies
- Fetches CSRF token and executes ADT requests in same HTTP model
- **`GenericWebSocketTransport`** (concrete, exported):
- Transport abstraction for realtime WS message flows
- Pluggable factory, envelope-based send/receive
- Intended for higher-level debugger/trace session orchestration
## Responsibilities and Design Principles
### Core Development Principle
**Interface-Only Communication**: This package follows a fundamental development principle: **all interactions with external dependencies happen ONLY through interfaces**. The code knows **NOTHING beyond what is defined in the interfaces**.
This means:
- Does not know about concrete implementation classes from other packages
- Does not know about internal data structures or methods not defined in interfaces
- Does not make assumptions about implementation behavior beyond interface contracts
- Does not access properties or methods not explicitly defined in interfaces
This principle ensures:
- **Loose coupling**: Connection classes are decoupled from concrete implementations in other packages
- **Flexibility**: New implementations can be added without modifying connection classes
- **Testability**: Easy to mock dependencies for testing
- **Maintainability**: Changes to implementations don't affect connection classes
### Package Responsibilities
This package is responsible for:
1. **HTTP communication with SAP systems**: Makes HTTP requests to SAP ABAP systems via ADT protocol
2. **Authentication handling**: Supports Basic Auth and JWT/OAuth2 authentication methods
3. **Session management**: Manages cookies, CSRF tokens, and session state
4. **Error handling**: Handles HTTP errors and connection issues
#### What This Package Does
- **Provides connection abstraction**: `AbapConnection` interface for interacting with SAP systems
- **Handles HTTP requests**: Makes requests to SAP ADT endpoints with proper headers and authentication
- **Manages sessions**: Handles cookies, CSRF tokens, and session state persistence
#### What This Package Does NOT Do
- **Does NOT obtain tokens**: Token acquisition is handled by `@mcp-abap-adt/auth-providers` and `@mcp-abap-adt/auth-broker`
- **Does NOT store tokens**: Token storage is handled by `@mcp-abap-adt/auth-stores`
- **Does NOT refresh tokens**: Token refresh is handled by `@mcp-abap-adt/auth-broker`
- **Does NOT orchestrate authentication**: Token lifecycle management is handled by `@mcp-abap-adt/auth-broker`
- **Does NOT know about destinations**: Destination-based authentication is handled by consumers
- **Does NOT handle OAuth2 flows**: OAuth2 flows are handled by token providers
### External Dependencies
This package interacts with external packages **ONLY through interfaces**:
- **Logger interface**: Uses `ILogger` interface for logging - does not know about concrete logger implementation
- **No direct dependencies on auth packages**: All token-related operations are handled through configuration (`SapConfig`) passed by consumers
## Documentation
- 📦 **[Installation Guide](./docs/INSTALLATION.md)** - Setup and installation instructions
- 📚 **[Usage Guide](./docs/USAGE.md)** - Detailed usage examples and API documentation
- 💡 **[Examples](./examples/)** - Working code examples
## Features
- 🔐 **Multiple Authentication Methods**: Basic Auth for on-premise systems, JWT/OAuth2 for SAP BTP ABAP Environment
- 💾 **Session Management**: Session headers management (cookies, CSRF tokens) for HTTP communication
- 📝 **Custom Logging**: Pluggable logger interface for integration with any logging system (optional)
- 📦 **TypeScript**: Full TypeScript support with type definitions included
- ⚡ **Timeout Management**: Configurable timeouts for different operation types
- 🌐 **Network Error Detection**: Automatic detection and proper handling of network-level errors (connection refused, timeout, DNS failures)
## Installation
```bash
npm install @mcp-abap-adt/connection
```
For detailed installation instructions, see [Installation Guide](./docs/INSTALLATION.md).
## Quick Start
### Basic Usage (On-Premise)
```typescript
import { createAbapConnection, SapConfig } from "@mcp-abap-adt/connection";
const config: SapConfig = {
url: "https://your-sap-system.com",
client: "100",
authType: "basic",
username: "your-username",
password: "your-password",
};
// Create a simple logger
const logger = {
info: (msg: string, meta?: any) => console.log(msg, meta),
error: (msg: string, meta?: any) => console.error(msg, meta),
warn: (msg: string, meta?: any) => console.warn(msg, meta),
debug: (msg: string, meta?: any) => console.debug(msg, meta),
};
// Create connection
const connection = createAbapConnection(config, logger);
// Make ADT request
const response = await connection.makeAdtRequest({
method: "GET",
url: "/sap/bc/adt/programs/programs/your-program",
});
```
### Cloud Usage (JWT/OAuth2)
```typescript
import { createAbapConnection, SapConfig } from "@mcp-abap-adt/connection";
// JWT configuration
const config: SapConfig = {
url: "https://your-instance.abap.cloud.sap",
client: "100", // Optional
authType: "jwt",
jwtToken: "your-jwt-token-here", // Obtained via OAuth2 flow
};
const logger = {
info: (msg: string, meta?: any) => console.log(msg, meta),
error: (msg: string, meta?: any) => console.error(msg, meta),
warn: (msg: string, meta?: any) => console.warn(msg, meta),
debug: (msg: string, meta?: any) => console.debug(msg, meta),
};
// Logger is optional - if not provided, no logging output
const connection = createAbapConnection(config, logger);
// Note: Token refresh is handled by @mcp-abap-adt/auth-broker package
const response = await connection.makeAdtRequest({
method: "GET",
url: "/sap/bc/adt/programs/programs/your-program",
});
```
### SSO Usage (SAML Session Cookies)
```typescript
import { createAbapConnection, SapConfig } from "@mcp-abap-adt/connection";
const config: SapConfig = {
url: "https://your-sap-system.com",
authType: "saml",
sessionCookies: "MYSAPSSO2=...; SAP_SESSIONID=...",
};
const connection = createAbapConnection(config, logger);
const response = await connection.makeAdtRequest({
method: "GET",
url: "/sap/bc/adt/programs/programs/your-program",
});
```
### Cloud Usage with Automatic Token Refresh
For automatic token refresh on 401/403 errors, inject `ITokenRefresher`:
```typescript
import { JwtAbapConnection, SapConfig } from "@mcp-abap-adt/connection";
import type { ITokenRefresher } from "@mcp-abap-adt/interfaces";
// Token refresher provides token acquisition and refresh
// (created by @mcp-abap-adt/auth-broker or custom implementation)
const tokenRefresher: ITokenRefresher = {
getToken: async () => { /* return current token */ },
refreshToken: async () => { /* refresh and return new token */ },
};
// JWT configuration
const config: SapConfig = {
url: "https://your-instance.abap.cloud.sap",
authType: "jwt",
jwtToken: await tokenRefresher.getToken(), // Get initial token
};
// Create connection with token refresher - 401/403 handled automatically
const connection = new JwtAbapConnection(config, logger, undefined, tokenRefresher);
// Requests automatically retry with refreshed token on auth errors
const response = await connection.makeAdtRequest({
method: "GET",
url: "/sap/bc/adt/programs/programs/your-program",
});
```
### Stateful Sessions
For operations that require session state (e.g., object modifications), you can enable stateful sessions:
```typescript
import { createAbapConnection } from "@mcp-abap-adt/connection";
const connection = createAbapConnection(config, logger);
// Enable stateful session mode (adds x-sap-adt-sessiontype: stateful header)
connection.setSessionType("stateful");
// Make requests - SAP will maintain session state
await connection.makeAdtRequest({
method: "POST",
url: "/sap/bc/adt/objects/domains",
data: { /* domain data */ },
});
// Note: Session state persistence is handled by @mcp-abap-adt/auth-broker package
```
### Custom Logger
```typescript
import { ILogger } from "@mcp-abap-adt/connection";
class MyLogger implements ILogger {
info(message: string, meta?: any): void {
// Your logging implementation
}
error(message: string, meta?: any): void {
// Your logging implementation
}
warn(message: string, meta?: any): void {
// Your logging implementation
}
debug(message: string, meta?: any): void {
// Your logging implementation
}
csrfToken(action: "fetch" | "retry" | "success" | "error", message: string, meta?: any): void {
// CSRF token specific logging
}
tlsConfig(rejectUnauthorized: boolean): void {
// TLS configuration logging
}
}
const logger = new MyLogger();
const connection = createAbapConnection(config, logger);
```
## CLI Tool
The package includes a CLI tool for authenticating with SAP BTP using service keys:
### Installation Options
- **Local project install**
```bash
npm install @mcp-abap-adt/connection --save-dev
npx sap-abap-auth auth -k path/to/service-key.json
```
- **Global install**
```bash
npm install -g @mcp-abap-adt/connection
sap-abap-auth auth -k path/to/service-key.json
```
- **On-demand (npx)**
```bash
npx @mcp-abap-adt/connection sap-abap-auth auth -k path/to/service-key.json
```
### Usage
```bash
# Show help
sap-abap-auth --help
# Authenticate with service key
sap-abap-auth auth -k service-key.json
# Specify browser
sap-abap-auth auth -k service-key.json --browser chrome
# Custom output file
sap-abap-auth auth -k service-key.json --output .env.production
```
### Options
- `-k, --key <path>` - Path to service key JSON file (required)
- `-b, --browser <name>` - Browser to open (chrome, edge, firefox, system, none)
- `-o, --output <path>` - Path to output .env file (default: .env)
- `-h, --help` - Show help message
### Using via `npx` (without global install)
If `@mcp-abap-adt/connection` is listed as a dependency in your project, you can invoke the CLI directly:
```bash
npx sap-abap-auth auth -k service-key.json
```
This works even when you do not install the package globally. For one-off usage, you can also run:
```bash
npx @mcp-abap-adt/connection sap-abap-auth auth -k service-key.json
```
This will download the package on demand and execute the CLI.
## API Reference
### Types
#### `SapConfig`
Configuration for SAP ABAP connection.
```typescript
type SapConfig = {
url: string;
client?: string;
authType: "basic" | "jwt" | "saml";
// For basic auth
username?: string;
password?: string;
// For JWT auth
jwtToken?: string;
// For SAML session cookies
sessionCookies?: string;
};
```
#### `AbapConnection`
Main interface for ABAP connections.
```typescript
interface AbapConnection {
makeAdtRequest(options: AbapRequestOptions): Promise<AxiosResponse>;
reset(): void;
setSessionType(type: "stateless" | "stateful"): void; // Switch session type
getSessionMode(): "stateless" | "stateful"; // Get current session mode
getSessionId(): string | null; // Get current session ID
}
```
**Session Management:**
- `setSessionType(type)`: Programmatically switch between stateful and stateless modes
- `getSessionMode()`: Returns current session mode
- `getSessionId()`: Returns the current session ID (auto-generated UUID)
#### `ILogger`
Logger interface for custom logging implementations.
```typescript
interface ILogger {
info(message: string, meta?: any): void;
error(message: string, meta?: any): void;
warn(message: string, meta?: any): void;
debug(message: string, meta?: any): void;
csrfToken?(action: "fetch" | "retry" | "success" | "error", message: string, meta?: any): void;
tlsConfig?(rejectUnauthorized: boolean): void;
}
```
### Functions
#### `createAbapConnection(config, logger?, sessionId?)`
Factory function to create an ABAP connection instance.
```typescript
function createAbapConnection(
config: SapConfig,
logger?: ILogger | null,
sessionId?: string
): AbapConnection;
```
#### `CSRF_CONFIG` and `CSRF_ERROR_MESSAGES`
**New in 0.1.13+:** Exported constants for consistent CSRF token handling across different connection implementations.
```typescript
import { CSRF_CONFIG, CSRF_ERROR_MESSAGES } from '@mcp-abap-adt/connection';
// CSRF_CONFIG contains:
// - RETRY_COUNT: number (default: 3)
// - RETRY_DELAY: number (default: 1000ms)
// - ENDPOINT: string (default: '/sap/bc/adt/core/discovery')
// - REQUIRED_HEADERS: { 'x-csrf-token': 'fetch', 'Accept': 'application/atomsvc+xml' }
// CSRF_ERROR_MESSAGES contains:
// - FETCH_FAILED(attempts: number, cause: string): string
// - NOT_IN_HEADERS: string
// - REQUIRED_FOR_MUTATION: string
```
**Use case:** When implementing custom connection classes (e.g., Cloud SDK-based), you can use these constants to ensure consistent CSRF token handling:
```typescript
import { CSRF_CONFIG, CSRF_ERROR_MESSAGES } from '@mcp-abap-adt/connection';
async function fetchCsrfToken(baseUrl: string): Promise<string> {
const csrfUrl = `${baseUrl}${CSRF_CONFIG.ENDPOINT}`;
for (let attempt = 0; attempt <= CSRF_CONFIG.RETRY_COUNT; attempt++) {
try {
const response = await yourHttpClient.get(csrfUrl, {
headers: CSRF_CONFIG.REQUIRED_HEADERS
});
const token = response.headers['x-csrf-token'];
if (!token) {
if (attempt < CSRF_CONFIG.RETRY_COUNT) {
await new Promise(resolve => setTimeout(resolve, CSRF_CONFIG.RETRY_DELAY));
continue;
}
throw new Error(CSRF_ERROR_MESSAGES.NOT_IN_HEADERS);
}
return token;
} catch (error) {
if (attempt >= CSRF_CONFIG.RETRY_COUNT) {
throw new Error(
CSRF_ERROR_MESSAGES.FETCH_FAILED(
CSRF_CONFIG.RETRY_COUNT + 1,
error instanceof Error ? error.message : String(error)
)
);
}
await new Promise(resolve => setTimeout(resolve, CSRF_CONFIG.RETRY_DELAY));
}
}
}
```
See [PR Proposal](./PR_PROPOSAL_CSRF_CONFIG.md) for more details.
## Requirements
- Node.js >= 18.0.0
- Access to SAP ABAP system (on-premise or BTP)
## Changelog
See [CHANGELOG.md](./CHANGELOG.md) for detailed version history and breaking changes.
**Latest version: 0.2.0**
- Removed token refresh functionality (handled by `@mcp-abap-adt/auth-broker`)
- Removed session storage functionality (handled by `@mcp-abap-adt/auth-broker`)
- Logger is now optional
- See [CHANGELOG.md](./CHANGELOG.md) for full details
## Documentation
- [Examples](./examples/README.md) - Working code examples
- [Changelog](./CHANGELOG.md) - Version history and release notes
## License
MIT
## Repository
https://github.com/fr0ster/mcp-abap-adt
## Related Projects
- [mcp-abap-adt](https://github.com/fr0ster/mcp-abap-adt) - Main MCP server for ABAP ADT