@mcp-abap-adt/proxy 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/CHANGELOG.md +89 -0
  2. package/LICENSE +22 -0
  3. package/README.md +234 -0
  4. package/bin/mcp-abap-adt-proxy.js +203 -0
  5. package/dist/index.d.ts +56 -0
  6. package/dist/index.d.ts.map +1 -0
  7. package/dist/index.js +645 -0
  8. package/dist/lib/config.d.ts +33 -0
  9. package/dist/lib/config.d.ts.map +1 -0
  10. package/dist/lib/config.js +196 -0
  11. package/dist/lib/errorHandler.d.ts +69 -0
  12. package/dist/lib/errorHandler.d.ts.map +1 -0
  13. package/dist/lib/errorHandler.js +202 -0
  14. package/dist/lib/logger.d.ts +17 -0
  15. package/dist/lib/logger.d.ts.map +1 -0
  16. package/dist/lib/logger.js +43 -0
  17. package/dist/lib/stores.d.ts +18 -0
  18. package/dist/lib/stores.d.ts.map +1 -0
  19. package/dist/lib/stores.js +22 -0
  20. package/dist/lib/transportConfig.d.ts +18 -0
  21. package/dist/lib/transportConfig.d.ts.map +1 -0
  22. package/dist/lib/transportConfig.js +124 -0
  23. package/dist/proxy/cloudLlmHubProxy.d.ts +61 -0
  24. package/dist/proxy/cloudLlmHubProxy.d.ts.map +1 -0
  25. package/dist/proxy/cloudLlmHubProxy.js +380 -0
  26. package/dist/router/directCloudRouter.d.ts +32 -0
  27. package/dist/router/directCloudRouter.d.ts.map +1 -0
  28. package/dist/router/directCloudRouter.js +179 -0
  29. package/dist/router/headerAnalyzer.d.ts +48 -0
  30. package/dist/router/headerAnalyzer.d.ts.map +1 -0
  31. package/dist/router/headerAnalyzer.js +124 -0
  32. package/dist/router/localBasicRouter.d.ts +23 -0
  33. package/dist/router/localBasicRouter.d.ts.map +1 -0
  34. package/dist/router/localBasicRouter.js +140 -0
  35. package/dist/router/requestInterceptor.d.ts +32 -0
  36. package/dist/router/requestInterceptor.d.ts.map +1 -0
  37. package/dist/router/requestInterceptor.js +82 -0
  38. package/package.json +73 -0
@@ -0,0 +1,196 @@
1
+ "use strict";
2
+ /**
3
+ * Configuration management for MCP ABAP ADT Proxy
4
+ */
5
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ var desc = Object.getOwnPropertyDescriptor(m, k);
8
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
9
+ desc = { enumerable: true, get: function() { return m[k]; } };
10
+ }
11
+ Object.defineProperty(o, k2, desc);
12
+ }) : (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ o[k2] = m[k];
15
+ }));
16
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
17
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
18
+ }) : function(o, v) {
19
+ o["default"] = v;
20
+ });
21
+ var __importStar = (this && this.__importStar) || (function () {
22
+ var ownKeys = function(o) {
23
+ ownKeys = Object.getOwnPropertyNames || function (o) {
24
+ var ar = [];
25
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
26
+ return ar;
27
+ };
28
+ return ownKeys(o);
29
+ };
30
+ return function (mod) {
31
+ if (mod && mod.__esModule) return mod;
32
+ var result = {};
33
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
34
+ __setModuleDefault(result, mod);
35
+ return result;
36
+ };
37
+ })();
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.loadConfig = loadConfig;
40
+ exports.validateConfig = validateConfig;
41
+ const fs = __importStar(require("fs"));
42
+ const path = __importStar(require("path"));
43
+ /**
44
+ * Load configuration from file if exists, otherwise from environment variables
45
+ */
46
+ function loadConfig(configPath) {
47
+ // Try to load from config file first
48
+ if (configPath || process.env.MCP_PROXY_CONFIG) {
49
+ const filePath = configPath || process.env.MCP_PROXY_CONFIG;
50
+ try {
51
+ if (fs.existsSync(filePath)) {
52
+ const configContent = fs.readFileSync(filePath, "utf-8");
53
+ const fileConfig = JSON.parse(configContent);
54
+ return mergeConfig(fileConfig, loadFromEnv());
55
+ }
56
+ }
57
+ catch (error) {
58
+ console.warn(`Failed to load config from file ${filePath}: ${error instanceof Error ? error.message : String(error)}`);
59
+ }
60
+ }
61
+ // Try default config file locations
62
+ const defaultPaths = [
63
+ path.join(process.cwd(), "mcp-proxy-config.json"),
64
+ path.join(process.cwd(), ".mcp-proxy-config.json"),
65
+ path.join(process.env.HOME || process.env.USERPROFILE || "", ".mcp-proxy-config.json"),
66
+ ];
67
+ for (const configPath of defaultPaths) {
68
+ try {
69
+ if (fs.existsSync(configPath)) {
70
+ const configContent = fs.readFileSync(configPath, "utf-8");
71
+ const fileConfig = JSON.parse(configContent);
72
+ return mergeConfig(fileConfig, loadFromEnv());
73
+ }
74
+ }
75
+ catch (error) {
76
+ // Continue to next path
77
+ }
78
+ }
79
+ // Fall back to environment variables only
80
+ return loadFromEnv();
81
+ }
82
+ /**
83
+ * Load configuration from environment variables and command line
84
+ */
85
+ function loadFromEnv() {
86
+ // Parse command line arguments for --btp, --mcp, --mcp-url, and --unsafe
87
+ const btpDestination = getArgValue("--btp");
88
+ const mcpDestination = getArgValue("--mcp");
89
+ const mcpUrl = getArgValue("--mcp-url");
90
+ const unsafe = hasArg("--unsafe") || process.env.MCP_PROXY_UNSAFE === "true";
91
+ return {
92
+ cloudLlmHubUrl: process.env.CLOUD_LLM_HUB_URL || "",
93
+ httpPort: parseInt(process.env.MCP_HTTP_PORT || "3001", 10),
94
+ ssePort: parseInt(process.env.MCP_SSE_PORT || "3002", 10),
95
+ httpHost: process.env.MCP_HTTP_HOST || "0.0.0.0",
96
+ sseHost: process.env.MCP_SSE_HOST || "0.0.0.0",
97
+ logLevel: process.env.LOG_LEVEL || "info",
98
+ btpDestination,
99
+ mcpDestination,
100
+ mcpUrl: mcpUrl || process.env.MCP_URL,
101
+ unsafe,
102
+ maxRetries: parseInt(process.env.MCP_PROXY_MAX_RETRIES || "3", 10),
103
+ retryDelay: parseInt(process.env.MCP_PROXY_RETRY_DELAY || "1000", 10),
104
+ requestTimeout: parseInt(process.env.MCP_PROXY_REQUEST_TIMEOUT || "60000", 10),
105
+ circuitBreakerThreshold: parseInt(process.env.MCP_PROXY_CIRCUIT_BREAKER_THRESHOLD || "5", 10),
106
+ circuitBreakerTimeout: parseInt(process.env.MCP_PROXY_CIRCUIT_BREAKER_TIMEOUT || "60000", 10),
107
+ };
108
+ }
109
+ /**
110
+ * Get argument value from command line
111
+ */
112
+ function getArgValue(argName) {
113
+ const args = process.argv;
114
+ for (let i = 0; i < args.length; i++) {
115
+ if (args[i] === argName && i + 1 < args.length) {
116
+ return args[i + 1];
117
+ }
118
+ if (args[i].startsWith(`${argName}=`)) {
119
+ return args[i].split("=")[1];
120
+ }
121
+ }
122
+ return undefined;
123
+ }
124
+ /**
125
+ * Check if argument exists in command line
126
+ */
127
+ function hasArg(argName) {
128
+ const args = process.argv;
129
+ return args.some(arg => arg === argName || arg.startsWith(`${argName}=`));
130
+ }
131
+ /**
132
+ * Merge file config with environment config (env takes precedence)
133
+ */
134
+ function mergeConfig(fileConfig, envConfig) {
135
+ return {
136
+ cloudLlmHubUrl: envConfig.cloudLlmHubUrl || fileConfig.cloudLlmHubUrl || "",
137
+ httpPort: envConfig.httpPort || fileConfig.httpPort || 3001,
138
+ ssePort: envConfig.ssePort || fileConfig.ssePort || 3002,
139
+ httpHost: envConfig.httpHost || fileConfig.httpHost || "0.0.0.0",
140
+ sseHost: envConfig.sseHost || fileConfig.sseHost || "0.0.0.0",
141
+ logLevel: envConfig.logLevel || fileConfig.logLevel || "info",
142
+ // Command line overrides take precedence
143
+ btpDestination: envConfig.btpDestination ?? fileConfig.btpDestination,
144
+ mcpDestination: envConfig.mcpDestination ?? fileConfig.mcpDestination,
145
+ mcpUrl: envConfig.mcpUrl ?? fileConfig.mcpUrl,
146
+ unsafe: envConfig.unsafe ?? fileConfig.unsafe ?? false,
147
+ maxRetries: envConfig.maxRetries ?? fileConfig.maxRetries ?? 3,
148
+ retryDelay: envConfig.retryDelay ?? fileConfig.retryDelay ?? 1000,
149
+ requestTimeout: envConfig.requestTimeout ?? fileConfig.requestTimeout ?? 60000,
150
+ circuitBreakerThreshold: envConfig.circuitBreakerThreshold ?? fileConfig.circuitBreakerThreshold ?? 5,
151
+ circuitBreakerTimeout: envConfig.circuitBreakerTimeout ?? fileConfig.circuitBreakerTimeout ?? 60000,
152
+ };
153
+ }
154
+ /**
155
+ * Validate configuration
156
+ */
157
+ function validateConfig(config) {
158
+ const errors = [];
159
+ const warnings = [];
160
+ // Cloud LLM Hub URL is only required if we're using proxy functionality
161
+ // For direct cloud and basic auth, it's not needed
162
+ if (!config.cloudLlmHubUrl) {
163
+ warnings.push("CLOUD_LLM_HUB_URL is not set - proxy to cloud-llm-hub will not work");
164
+ }
165
+ else {
166
+ try {
167
+ new URL(config.cloudLlmHubUrl);
168
+ }
169
+ catch {
170
+ errors.push("CLOUD_LLM_HUB_URL must be a valid URL");
171
+ }
172
+ }
173
+ if (config.httpPort < 1 || config.httpPort > 65535) {
174
+ errors.push("MCP_HTTP_PORT must be between 1 and 65535");
175
+ }
176
+ if (config.ssePort < 1 || config.ssePort > 65535) {
177
+ errors.push("MCP_SSE_PORT must be between 1 and 65535");
178
+ }
179
+ if (config.httpPort === config.ssePort) {
180
+ errors.push("MCP_HTTP_PORT and MCP_SSE_PORT must be different");
181
+ }
182
+ if (config.maxRetries && (config.maxRetries < 0 || config.maxRetries > 10)) {
183
+ warnings.push("MCP_PROXY_MAX_RETRIES should be between 0 and 10");
184
+ }
185
+ if (config.retryDelay && (config.retryDelay < 0 || config.retryDelay > 60000)) {
186
+ warnings.push("MCP_PROXY_RETRY_DELAY should be between 0 and 60000ms");
187
+ }
188
+ if (config.requestTimeout && (config.requestTimeout < 1000 || config.requestTimeout > 300000)) {
189
+ warnings.push("MCP_PROXY_REQUEST_TIMEOUT should be between 1000 and 300000ms");
190
+ }
191
+ return {
192
+ valid: errors.length === 0,
193
+ errors,
194
+ warnings,
195
+ };
196
+ }
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Error Handling & Resilience utilities
3
+ */
4
+ export interface RetryOptions {
5
+ maxRetries: number;
6
+ retryDelay: number;
7
+ retryableStatusCodes?: number[];
8
+ retryableErrors?: string[];
9
+ }
10
+ /**
11
+ * Check if error is retryable
12
+ */
13
+ export declare function isRetryableError(error: unknown, retryableStatusCodes?: number[]): boolean;
14
+ /**
15
+ * Sleep for specified milliseconds
16
+ */
17
+ export declare function sleep(ms: number): Promise<void>;
18
+ /**
19
+ * Retry function with exponential backoff
20
+ */
21
+ export declare function retryWithBackoff<T>(fn: () => Promise<T>, options: RetryOptions): Promise<T>;
22
+ /**
23
+ * Circuit Breaker implementation
24
+ */
25
+ export declare class CircuitBreaker {
26
+ private threshold;
27
+ private timeout;
28
+ private failures;
29
+ private lastFailureTime;
30
+ private state;
31
+ constructor(threshold?: number, timeout?: number);
32
+ /**
33
+ * Check if circuit breaker allows request
34
+ */
35
+ canProceed(): boolean;
36
+ /**
37
+ * Record success
38
+ */
39
+ recordSuccess(): void;
40
+ /**
41
+ * Record failure
42
+ */
43
+ recordFailure(): void;
44
+ /**
45
+ * Get current state
46
+ */
47
+ getState(): "closed" | "open" | "half-open";
48
+ /**
49
+ * Reset circuit breaker
50
+ */
51
+ reset(): void;
52
+ }
53
+ /**
54
+ * Handle token expiration errors
55
+ */
56
+ export declare function isTokenExpirationError(error: unknown): boolean;
57
+ /**
58
+ * Create error response in MCP format
59
+ */
60
+ export declare function createErrorResponse(id: string | number | null, code: number, message: string, data?: any): {
61
+ jsonrpc: string;
62
+ id: string | number | null;
63
+ error: {
64
+ code: number;
65
+ message: string;
66
+ data?: any;
67
+ };
68
+ };
69
+ //# sourceMappingURL=errorHandler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errorHandler.d.ts","sourceRoot":"","sources":["../../src/lib/errorHandler.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;IAChC,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;CAC5B;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,EAAE,oBAAoB,GAAE,MAAM,EAAyB,GAAG,OAAO,CAsB/G;AAED;;GAEG;AACH,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/C;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,CAAC,EACtC,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC,CAAC,CAAC,CAgDZ;AAED;;GAEG;AACH,qBAAa,cAAc;IAMvB,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,OAAO;IANjB,OAAO,CAAC,QAAQ,CAAa;IAC7B,OAAO,CAAC,eAAe,CAAa;IACpC,OAAO,CAAC,KAAK,CAA6C;gBAGhD,SAAS,GAAE,MAAU,EACrB,OAAO,GAAE,MAAc;IAGjC;;OAEG;IACH,UAAU,IAAI,OAAO;IAkBrB;;OAEG;IACH,aAAa,IAAI,IAAI;IAYrB;;OAEG;IACH,aAAa,IAAI,IAAI;IAcrB;;OAEG;IACH,QAAQ,IAAI,QAAQ,GAAG,MAAM,GAAG,WAAW;IAI3C;;OAEG;IACH,KAAK,IAAI,IAAI;CAQd;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAiB9D;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,EAC1B,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,IAAI,CAAC,EAAE,GAAG,GACT;IACD,OAAO,EAAE,MAAM,CAAC;IAChB,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAC3B,KAAK,EAAE;QACL,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,CAAC,EAAE,GAAG,CAAC;KACZ,CAAC;CACH,CAUA"}
@@ -0,0 +1,202 @@
1
+ "use strict";
2
+ /**
3
+ * Error Handling & Resilience utilities
4
+ */
5
+ var __importDefault = (this && this.__importDefault) || function (mod) {
6
+ return (mod && mod.__esModule) ? mod : { "default": mod };
7
+ };
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.CircuitBreaker = void 0;
10
+ exports.isRetryableError = isRetryableError;
11
+ exports.sleep = sleep;
12
+ exports.retryWithBackoff = retryWithBackoff;
13
+ exports.isTokenExpirationError = isTokenExpirationError;
14
+ exports.createErrorResponse = createErrorResponse;
15
+ const logger_js_1 = require("./logger.js");
16
+ /**
17
+ * Check if error is retryable
18
+ */
19
+ function isRetryableError(error, retryableStatusCodes = [500, 502, 503, 504]) {
20
+ if (axios_1.default.isAxiosError(error)) {
21
+ const status = error.response?.status;
22
+ if (status && retryableStatusCodes.includes(status)) {
23
+ return true;
24
+ }
25
+ // Network errors are retryable
26
+ if (!error.response && error.request) {
27
+ return true;
28
+ }
29
+ }
30
+ // Token expiration errors are retryable (will be handled separately)
31
+ if (error instanceof Error) {
32
+ const message = error.message.toLowerCase();
33
+ if (message.includes("token") && (message.includes("expired") || message.includes("invalid"))) {
34
+ return true;
35
+ }
36
+ }
37
+ return false;
38
+ }
39
+ /**
40
+ * Sleep for specified milliseconds
41
+ */
42
+ function sleep(ms) {
43
+ return new Promise((resolve) => setTimeout(resolve, ms));
44
+ }
45
+ /**
46
+ * Retry function with exponential backoff
47
+ */
48
+ async function retryWithBackoff(fn, options) {
49
+ const { maxRetries, retryDelay, retryableStatusCodes = [500, 502, 503, 504] } = options;
50
+ let lastError;
51
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
52
+ try {
53
+ return await fn();
54
+ }
55
+ catch (error) {
56
+ lastError = error;
57
+ // Don't retry on last attempt
58
+ if (attempt === maxRetries) {
59
+ break;
60
+ }
61
+ // Check if error is retryable
62
+ if (!isRetryableError(error, retryableStatusCodes)) {
63
+ logger_js_1.logger.debug("Error is not retryable, stopping retries", {
64
+ type: "RETRY_STOPPED",
65
+ attempt,
66
+ error: error instanceof Error ? error.message : String(error),
67
+ });
68
+ throw error;
69
+ }
70
+ // Calculate backoff delay (exponential backoff)
71
+ const delay = retryDelay * Math.pow(2, attempt);
72
+ logger_js_1.logger.warn("Retrying after error", {
73
+ type: "RETRY_ATTEMPT",
74
+ attempt: attempt + 1,
75
+ maxRetries,
76
+ delay,
77
+ error: error instanceof Error ? error.message : String(error),
78
+ });
79
+ await sleep(delay);
80
+ }
81
+ }
82
+ // All retries exhausted
83
+ logger_js_1.logger.error("All retry attempts exhausted", {
84
+ type: "RETRY_EXHAUSTED",
85
+ maxRetries,
86
+ error: lastError instanceof Error ? lastError.message : String(lastError),
87
+ });
88
+ throw lastError;
89
+ }
90
+ /**
91
+ * Circuit Breaker implementation
92
+ */
93
+ class CircuitBreaker {
94
+ threshold;
95
+ timeout;
96
+ failures = 0;
97
+ lastFailureTime = 0;
98
+ state = "closed";
99
+ constructor(threshold = 5, timeout = 60000) {
100
+ this.threshold = threshold;
101
+ this.timeout = timeout;
102
+ }
103
+ /**
104
+ * Check if circuit breaker allows request
105
+ */
106
+ canProceed() {
107
+ const now = Date.now();
108
+ if (this.state === "open") {
109
+ // Check if timeout has passed
110
+ if (now - this.lastFailureTime >= this.timeout) {
111
+ this.state = "half-open";
112
+ logger_js_1.logger.info("Circuit breaker entering half-open state", {
113
+ type: "CIRCUIT_BREAKER_HALF_OPEN",
114
+ });
115
+ return true;
116
+ }
117
+ return false;
118
+ }
119
+ return true;
120
+ }
121
+ /**
122
+ * Record success
123
+ */
124
+ recordSuccess() {
125
+ if (this.state === "half-open") {
126
+ this.state = "closed";
127
+ this.failures = 0;
128
+ logger_js_1.logger.info("Circuit breaker closed after successful request", {
129
+ type: "CIRCUIT_BREAKER_CLOSED",
130
+ });
131
+ }
132
+ else if (this.state === "closed") {
133
+ this.failures = 0;
134
+ }
135
+ }
136
+ /**
137
+ * Record failure
138
+ */
139
+ recordFailure() {
140
+ this.failures++;
141
+ this.lastFailureTime = Date.now();
142
+ if (this.failures >= this.threshold) {
143
+ this.state = "open";
144
+ logger_js_1.logger.error("Circuit breaker opened due to failures", {
145
+ type: "CIRCUIT_BREAKER_OPENED",
146
+ failures: this.failures,
147
+ threshold: this.threshold,
148
+ });
149
+ }
150
+ }
151
+ /**
152
+ * Get current state
153
+ */
154
+ getState() {
155
+ return this.state;
156
+ }
157
+ /**
158
+ * Reset circuit breaker
159
+ */
160
+ reset() {
161
+ this.failures = 0;
162
+ this.lastFailureTime = 0;
163
+ this.state = "closed";
164
+ logger_js_1.logger.info("Circuit breaker reset", {
165
+ type: "CIRCUIT_BREAKER_RESET",
166
+ });
167
+ }
168
+ }
169
+ exports.CircuitBreaker = CircuitBreaker;
170
+ /**
171
+ * Handle token expiration errors
172
+ */
173
+ function isTokenExpirationError(error) {
174
+ if (axios_1.default.isAxiosError(error)) {
175
+ const status = error.response?.status;
176
+ if (status === 401 || status === 403) {
177
+ return true;
178
+ }
179
+ }
180
+ if (error instanceof Error) {
181
+ const message = error.message.toLowerCase();
182
+ return (message.includes("token") &&
183
+ (message.includes("expired") || message.includes("invalid") || message.includes("unauthorized")));
184
+ }
185
+ return false;
186
+ }
187
+ /**
188
+ * Create error response in MCP format
189
+ */
190
+ function createErrorResponse(id, code, message, data) {
191
+ return {
192
+ jsonrpc: "2.0",
193
+ id,
194
+ error: {
195
+ code,
196
+ message,
197
+ data,
198
+ },
199
+ };
200
+ }
201
+ // Import axios for type checking
202
+ const axios_1 = __importDefault(require("axios"));
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Logger utility for MCP ABAP ADT Proxy
3
+ */
4
+ export declare enum LogLevel {
5
+ DEBUG = 0,
6
+ INFO = 1,
7
+ WARN = 2,
8
+ ERROR = 3
9
+ }
10
+ export interface Logger {
11
+ debug(message: string, meta?: Record<string, unknown>): void;
12
+ info(message: string, meta?: Record<string, unknown>): void;
13
+ warn(message: string, meta?: Record<string, unknown>): void;
14
+ error(message: string, meta?: Record<string, unknown>): void;
15
+ }
16
+ export declare const logger: Logger;
17
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/lib/logger.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,oBAAY,QAAQ;IAClB,KAAK,IAAI;IACT,IAAI,IAAI;IACR,IAAI,IAAI;IACR,KAAK,IAAI;CACV;AAED,MAAM,WAAW,MAAM;IACrB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC7D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC5D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC5D,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CAC9D;AAqCD,eAAO,MAAM,MAAM,EAAE,MAIpB,CAAC"}
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ /**
3
+ * Logger utility for MCP ABAP ADT Proxy
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.logger = exports.LogLevel = void 0;
7
+ var LogLevel;
8
+ (function (LogLevel) {
9
+ LogLevel[LogLevel["DEBUG"] = 0] = "DEBUG";
10
+ LogLevel[LogLevel["INFO"] = 1] = "INFO";
11
+ LogLevel[LogLevel["WARN"] = 2] = "WARN";
12
+ LogLevel[LogLevel["ERROR"] = 3] = "ERROR";
13
+ })(LogLevel || (exports.LogLevel = LogLevel = {}));
14
+ class SimpleLogger {
15
+ level;
16
+ constructor(level = LogLevel.INFO) {
17
+ this.level = level;
18
+ }
19
+ log(level, prefix, message, meta) {
20
+ if (level < this.level) {
21
+ return;
22
+ }
23
+ const timestamp = new Date().toISOString();
24
+ const metaStr = meta ? ` ${JSON.stringify(meta)}` : '';
25
+ console.error(`[${timestamp}] [${prefix}] ${message}${metaStr}`);
26
+ }
27
+ debug(message, meta) {
28
+ this.log(LogLevel.DEBUG, 'DEBUG', message, meta);
29
+ }
30
+ info(message, meta) {
31
+ this.log(LogLevel.INFO, 'INFO', message, meta);
32
+ }
33
+ warn(message, meta) {
34
+ this.log(LogLevel.WARN, 'WARN', message, meta);
35
+ }
36
+ error(message, meta) {
37
+ this.log(LogLevel.ERROR, 'ERROR', message, meta);
38
+ }
39
+ }
40
+ // Default logger instance
41
+ exports.logger = new SimpleLogger(process.env.LOG_LEVEL?.toUpperCase()
42
+ ? (LogLevel[process.env.LOG_LEVEL.toUpperCase()] ?? LogLevel.INFO)
43
+ : LogLevel.INFO);
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Platform-specific stores for proxy
3
+ * Uses FileServiceKeyStore and either FileSessionStore or SafeSessionStore
4
+ * depending on the unsafe configuration parameter
5
+ */
6
+ import { IServiceKeyStore, ISessionStore } from "@mcp-abap-adt/auth-broker";
7
+ /**
8
+ * Get platform-specific stores
9
+ * Returns stores based on configuration:
10
+ * - If unsafe=true: uses FileSessionStore (persists to disk)
11
+ * - If unsafe=false: uses SafeSessionStore (in-memory, secure)
12
+ * @param unsafe If true, use FileSessionStore. If false, use SafeSessionStore (default).
13
+ */
14
+ export declare function getPlatformStores(unsafe?: boolean): Promise<{
15
+ serviceKeyStore: IServiceKeyStore;
16
+ sessionStore: ISessionStore;
17
+ }>;
18
+ //# sourceMappingURL=stores.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stores.d.ts","sourceRoot":"","sources":["../../src/lib/stores.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAIL,gBAAgB,EAChB,aAAa,EACd,MAAM,2BAA2B,CAAC;AAEnC;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CAAC,MAAM,GAAE,OAAe,GAAG,OAAO,CAAC;IACxE,eAAe,EAAE,gBAAgB,CAAC;IAClC,YAAY,EAAE,aAAa,CAAC;CAC7B,CAAC,CAKD"}
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ /**
3
+ * Platform-specific stores for proxy
4
+ * Uses FileServiceKeyStore and either FileSessionStore or SafeSessionStore
5
+ * depending on the unsafe configuration parameter
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.getPlatformStores = getPlatformStores;
9
+ const auth_broker_1 = require("@mcp-abap-adt/auth-broker");
10
+ /**
11
+ * Get platform-specific stores
12
+ * Returns stores based on configuration:
13
+ * - If unsafe=true: uses FileSessionStore (persists to disk)
14
+ * - If unsafe=false: uses SafeSessionStore (in-memory, secure)
15
+ * @param unsafe If true, use FileSessionStore. If false, use SafeSessionStore (default).
16
+ */
17
+ async function getPlatformStores(unsafe = false) {
18
+ return {
19
+ serviceKeyStore: new auth_broker_1.FileServiceKeyStore(),
20
+ sessionStore: unsafe ? new auth_broker_1.FileSessionStore() : new auth_broker_1.SafeSessionStore(),
21
+ };
22
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Transport Configuration - Parse and manage transport settings
3
+ */
4
+ export type TransportType = "stdio" | "streamable-http" | "sse";
5
+ export interface TransportConfig {
6
+ type: TransportType;
7
+ host?: string;
8
+ port?: number;
9
+ enableJsonResponse?: boolean;
10
+ allowedOrigins?: string[];
11
+ allowedHosts?: string[];
12
+ enableDnsRebindingProtection?: boolean;
13
+ }
14
+ /**
15
+ * Parse transport configuration from command line arguments and environment variables
16
+ */
17
+ export declare function parseTransportConfig(): TransportConfig;
18
+ //# sourceMappingURL=transportConfig.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transportConfig.d.ts","sourceRoot":"","sources":["../../src/lib/transportConfig.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,iBAAiB,GAAG,KAAK,CAAC;AAEhE,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,aAAa,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,4BAA4B,CAAC,EAAE,OAAO,CAAC;CACxC;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,eAAe,CAgGtD"}