sap-b1-mcp-server
Version:
SAP Business One Service Layer MCP Server
195 lines • 6.7 kB
JavaScript
import { z } from 'zod';
// Configuration schema validation
const configSchema = z.object({
serverUrl: z.string().url('Invalid SAP B1 Service Layer URL'),
database: z.string().min(1, 'Database name is required'),
username: z.string().min(1, 'Username is required'),
password: z.string().min(1, 'Password is required'),
sessionTimeout: z.number().min(1).max(1440).optional() // 1-1440 minutes
});
// Environment variables schema
const envSchema = z.object({
SAP_B1_SERVER_URL: z.string().optional(),
SAP_B1_DATABASE: z.string().optional(),
SAP_B1_USERNAME: z.string().optional(),
SAP_B1_PASSWORD: z.string().optional(),
SAP_B1_SESSION_TIMEOUT: z.string().optional(),
MCP_TRANSPORT: z.enum(['stdio', 'http', 'streaming-http']).optional().default('stdio'),
MCP_HTTP_PORT: z.string().optional(),
MCP_HTTP_HOST: z.string().optional(),
MCP_API_KEY: z.string().optional(),
MCP_REQUIRE_API_KEY: z.string().optional(),
MCP_HTTP_CORS: z.string().optional(),
NODE_ENV: z.enum(['development', 'production', 'test']).optional().default('development')
});
export class ConfigManager {
config = null;
/**
* Load configuration from environment variables and config file
*/
async loadConfig(configPath) {
// Parse environment variables
const env = envSchema.parse(process.env);
let sapConfig;
// Try to load from config file if provided
if (configPath) {
try {
const fileConfig = await this.loadConfigFromFile(configPath);
sapConfig = fileConfig;
}
catch (error) {
console.warn(`Failed to load config from file: ${configPath}. Using environment variables.`);
sapConfig = this.loadConfigFromEnv(env);
}
}
else {
sapConfig = this.loadConfigFromEnv(env);
}
// Validate SAP configuration
const validatedSapConfig = configSchema.parse(sapConfig);
// Build complete configuration
this.config = {
sap: validatedSapConfig,
transport: {
type: env.MCP_TRANSPORT,
http: (env.MCP_TRANSPORT === 'http' || env.MCP_TRANSPORT === 'streaming-http') ? {
port: env.MCP_HTTP_PORT ? parseInt(env.MCP_HTTP_PORT) : 3000,
host: env.MCP_HTTP_HOST || 'localhost',
apiKey: env.MCP_API_KEY,
requireApiKey: env.MCP_REQUIRE_API_KEY ? env.MCP_REQUIRE_API_KEY.toLowerCase() === 'true' : true,
cors: env.MCP_HTTP_CORS ? env.MCP_HTTP_CORS.toLowerCase() === 'true' : true
} : undefined
},
environment: env.NODE_ENV
};
return this.config;
}
/**
* Get current configuration
*/
getConfig() {
if (!this.config) {
throw new Error('Configuration not loaded. Call loadConfig() first.');
}
return this.config;
}
/**
* Get SAP B1 configuration
*/
getSAPConfig() {
return this.getConfig().sap;
}
/**
* Validate configuration without loading
*/
static validateConfig(config) {
try {
configSchema.parse(config);
return { valid: true, errors: [] };
}
catch (error) {
if (error instanceof z.ZodError) {
return {
valid: false,
errors: error.errors.map(e => `${e.path.join('.')}: ${e.message}`)
};
}
return {
valid: false,
errors: [error instanceof Error ? error.message : 'Unknown validation error']
};
}
}
/**
* Create example configuration file
*/
static createExampleConfig() {
return {
serverUrl: 'https://your-sap-server:50000/b1s/v1',
database: 'YOUR_COMPANY_DB',
username: 'manager',
password: 'your-password',
sessionTimeout: 30
};
}
/**
* Load configuration from JSON file
*/
async loadConfigFromFile(filePath) {
const fs = await import('fs/promises');
const fileContent = await fs.readFile(filePath, 'utf-8');
const config = JSON.parse(fileContent);
return config;
}
/**
* Load configuration from environment variables
*/
loadConfigFromEnv(env) {
if (!env.SAP_B1_SERVER_URL || !env.SAP_B1_DATABASE || !env.SAP_B1_USERNAME || !env.SAP_B1_PASSWORD) {
throw new Error('Missing required environment variables: SAP_B1_SERVER_URL, SAP_B1_DATABASE, SAP_B1_USERNAME, SAP_B1_PASSWORD');
}
return {
serverUrl: env.SAP_B1_SERVER_URL,
database: env.SAP_B1_DATABASE,
username: env.SAP_B1_USERNAME,
password: env.SAP_B1_PASSWORD,
sessionTimeout: env.SAP_B1_SESSION_TIMEOUT ? parseInt(env.SAP_B1_SESSION_TIMEOUT) : 30
};
}
/**
* Mask sensitive information in configuration for logging
*/
static maskSensitiveConfig(config) {
return {
serverUrl: config.serverUrl,
database: config.database,
username: config.username,
password: '***masked***',
sessionTimeout: config.sessionTimeout
};
}
/**
* Get configuration summary for display
*/
getConfigSummary() {
const config = this.getConfig();
return {
sap: ConfigManager.maskSensitiveConfig(config.sap),
transport: config.transport,
environment: config.environment
};
}
/**
* Check if configuration is for production
*/
isProduction() {
return this.getConfig().environment === 'production';
}
/**
* Check if configuration is for development
*/
isDevelopment() {
return this.getConfig().environment === 'development';
}
/**
* Check if HTTP transport is enabled
*/
isHttpTransport() {
const type = this.getConfig().transport.type;
return type === 'http' || type === 'streaming-http';
}
/**
* Check if streaming HTTP transport is enabled
*/
isStreamingHttpTransport() {
return this.getConfig().transport.type === 'streaming-http';
}
/**
* Get HTTP configuration if enabled
*/
getHttpConfig() {
const config = this.getConfig();
return config.transport.type === 'http' && config.transport.http ? config.transport.http : null;
}
}
//# sourceMappingURL=config.js.map