@mcpilotx/intentorch 0.5.0

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 (101) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +545 -0
  3. package/dist/ai/ai.d.ts +205 -0
  4. package/dist/ai/ai.js +1200 -0
  5. package/dist/ai/cloud-intent-engine.d.ts +270 -0
  6. package/dist/ai/cloud-intent-engine.js +956 -0
  7. package/dist/ai/command.d.ts +59 -0
  8. package/dist/ai/command.js +285 -0
  9. package/dist/ai/config.d.ts +66 -0
  10. package/dist/ai/config.js +211 -0
  11. package/dist/ai/enhanced-intent.d.ts +17 -0
  12. package/dist/ai/enhanced-intent.js +32 -0
  13. package/dist/ai/index.d.ts +29 -0
  14. package/dist/ai/index.js +44 -0
  15. package/dist/ai/intent.d.ts +16 -0
  16. package/dist/ai/intent.js +30 -0
  17. package/dist/core/ai-config.d.ts +25 -0
  18. package/dist/core/ai-config.js +326 -0
  19. package/dist/core/config-manager.d.ts +36 -0
  20. package/dist/core/config-manager.js +400 -0
  21. package/dist/core/config-validator.d.ts +9 -0
  22. package/dist/core/config-validator.js +184 -0
  23. package/dist/core/constants.d.ts +34 -0
  24. package/dist/core/constants.js +37 -0
  25. package/dist/core/error-ai.d.ts +23 -0
  26. package/dist/core/error-ai.js +217 -0
  27. package/dist/core/error-handler.d.ts +197 -0
  28. package/dist/core/error-handler.js +467 -0
  29. package/dist/core/index.d.ts +13 -0
  30. package/dist/core/index.js +17 -0
  31. package/dist/core/logger.d.ts +27 -0
  32. package/dist/core/logger.js +108 -0
  33. package/dist/core/performance-monitor.d.ts +74 -0
  34. package/dist/core/performance-monitor.js +260 -0
  35. package/dist/core/providers.d.ts +36 -0
  36. package/dist/core/providers.js +304 -0
  37. package/dist/core/retry-manager.d.ts +41 -0
  38. package/dist/core/retry-manager.js +204 -0
  39. package/dist/core/types.d.ts +155 -0
  40. package/dist/core/types.js +2 -0
  41. package/dist/daemon/index.d.ts +10 -0
  42. package/dist/daemon/index.js +15 -0
  43. package/dist/daemon/intent-engine.d.ts +22 -0
  44. package/dist/daemon/intent-engine.js +50 -0
  45. package/dist/daemon/orchestrator.d.ts +24 -0
  46. package/dist/daemon/orchestrator.js +100 -0
  47. package/dist/daemon/pm.d.ts +33 -0
  48. package/dist/daemon/pm.js +127 -0
  49. package/dist/daemon/process.d.ts +11 -0
  50. package/dist/daemon/process.js +49 -0
  51. package/dist/daemon/server.d.ts +17 -0
  52. package/dist/daemon/server.js +435 -0
  53. package/dist/daemon/service.d.ts +36 -0
  54. package/dist/daemon/service.js +278 -0
  55. package/dist/index.d.ts +30 -0
  56. package/dist/index.js +36 -0
  57. package/dist/mcp/client.d.ts +51 -0
  58. package/dist/mcp/client.js +276 -0
  59. package/dist/mcp/index.d.ts +162 -0
  60. package/dist/mcp/index.js +199 -0
  61. package/dist/mcp/tool-registry.d.ts +71 -0
  62. package/dist/mcp/tool-registry.js +308 -0
  63. package/dist/mcp/transport.d.ts +83 -0
  64. package/dist/mcp/transport.js +515 -0
  65. package/dist/mcp/types.d.ts +136 -0
  66. package/dist/mcp/types.js +31 -0
  67. package/dist/runtime/adapter-advanced.d.ts +184 -0
  68. package/dist/runtime/adapter-advanced.js +160 -0
  69. package/dist/runtime/adapter.d.ts +9 -0
  70. package/dist/runtime/adapter.js +2 -0
  71. package/dist/runtime/detector-advanced.d.ts +59 -0
  72. package/dist/runtime/detector-advanced.js +487 -0
  73. package/dist/runtime/detector.d.ts +5 -0
  74. package/dist/runtime/detector.js +56 -0
  75. package/dist/runtime/docker-adapter.d.ts +18 -0
  76. package/dist/runtime/docker-adapter.js +170 -0
  77. package/dist/runtime/docker.d.ts +17 -0
  78. package/dist/runtime/docker.js +71 -0
  79. package/dist/runtime/executable-analyzer.d.ts +56 -0
  80. package/dist/runtime/executable-analyzer.js +391 -0
  81. package/dist/runtime/go-adapter.d.ts +19 -0
  82. package/dist/runtime/go-adapter.js +190 -0
  83. package/dist/runtime/index.d.ts +9 -0
  84. package/dist/runtime/index.js +10 -0
  85. package/dist/runtime/node-adapter.d.ts +10 -0
  86. package/dist/runtime/node-adapter.js +23 -0
  87. package/dist/runtime/node.d.ts +20 -0
  88. package/dist/runtime/node.js +86 -0
  89. package/dist/runtime/python-adapter.d.ts +11 -0
  90. package/dist/runtime/python-adapter.js +102 -0
  91. package/dist/runtime/python.d.ts +17 -0
  92. package/dist/runtime/python.js +72 -0
  93. package/dist/runtime/rust-adapter.d.ts +21 -0
  94. package/dist/runtime/rust-adapter.js +267 -0
  95. package/dist/sdk.d.ts +500 -0
  96. package/dist/sdk.js +904 -0
  97. package/docs/README.ZH_CN.md +545 -0
  98. package/docs/api.md +888 -0
  99. package/docs/architecture.md +731 -0
  100. package/docs/development.md +744 -0
  101. package/package.json +112 -0
@@ -0,0 +1,278 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import { spawn } from 'child_process';
4
+ import { CONFIG_PATH, LOGS_DIR } from '../core/constants.js';
5
+ import { logger } from '../core/logger.js';
6
+ export class ServiceManager {
7
+ services = new Map();
8
+ processes = new Map();
9
+ constructor() {
10
+ this.loadServices();
11
+ }
12
+ loadServices() {
13
+ if (!fs.existsSync(CONFIG_PATH)) {
14
+ return;
15
+ }
16
+ const config = JSON.parse(fs.readFileSync(CONFIG_PATH, 'utf-8'));
17
+ const serviceInstances = config.services?.instances || [];
18
+ for (const service of serviceInstances) {
19
+ this.services.set(service.name, {
20
+ ...service,
21
+ status: service.status || 'installed',
22
+ });
23
+ }
24
+ }
25
+ saveServices() {
26
+ const config = fs.existsSync(CONFIG_PATH)
27
+ ? JSON.parse(fs.readFileSync(CONFIG_PATH, 'utf-8'))
28
+ : { services: {} };
29
+ config.services.instances = Array.from(this.services.values());
30
+ fs.writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2));
31
+ }
32
+ async installService(servicePath, name) {
33
+ const resolvedPath = path.resolve(servicePath);
34
+ if (!fs.existsSync(resolvedPath)) {
35
+ throw new Error(`Service path not found: ${resolvedPath}`);
36
+ }
37
+ const serviceName = name || path.basename(resolvedPath);
38
+ // Check if service is already installed
39
+ if (this.services.has(serviceName)) {
40
+ throw new Error(`Service ${serviceName} is already installed`);
41
+ }
42
+ // Create service configuration
43
+ const serviceConfig = {
44
+ name: serviceName,
45
+ path: resolvedPath,
46
+ runtime: 'node', // Default, should actually be obtained from detector
47
+ entry: this.detectEntryPoint(resolvedPath),
48
+ };
49
+ const serviceInfo = {
50
+ name: serviceName,
51
+ path: resolvedPath,
52
+ runtime: serviceConfig.runtime,
53
+ status: 'installed',
54
+ installedAt: new Date().toISOString(),
55
+ config: serviceConfig,
56
+ };
57
+ this.services.set(serviceName, serviceInfo);
58
+ this.saveServices();
59
+ logger.info(`Service installed: ${serviceName} at ${resolvedPath}`);
60
+ return serviceInfo;
61
+ }
62
+ async startService(name) {
63
+ const service = this.services.get(name);
64
+ if (!service) {
65
+ throw new Error(`Service ${name} is not installed`);
66
+ }
67
+ if (service.status === 'running') {
68
+ logger.warn(`Service ${name} is already running`);
69
+ return service;
70
+ }
71
+ try {
72
+ // Create log directory
73
+ const logDir = path.join(LOGS_DIR, name);
74
+ if (!fs.existsSync(logDir)) {
75
+ fs.mkdirSync(logDir, { recursive: true });
76
+ }
77
+ const stdoutLog = path.join(logDir, 'stdout.log');
78
+ const stderrLog = path.join(logDir, 'stderr.log');
79
+ const stdout = fs.openSync(stdoutLog, 'a');
80
+ const stderr = fs.openSync(stderrLog, 'a');
81
+ // Start service based on runtime
82
+ const process = this.spawnService(service);
83
+ process.stdout?.pipe(fs.createWriteStream(stdoutLog, { flags: 'a' }));
84
+ process.stderr?.pipe(fs.createWriteStream(stderrLog, { flags: 'a' }));
85
+ this.processes.set(name, process);
86
+ // Update service status
87
+ service.status = 'running';
88
+ service.startedAt = new Date().toISOString();
89
+ service.stoppedAt = undefined;
90
+ service.pid = process.pid;
91
+ this.saveServices();
92
+ logger.info(`Service started: ${name} (PID: ${process.pid})`);
93
+ return service;
94
+ }
95
+ catch (error) {
96
+ service.status = 'error';
97
+ this.saveServices();
98
+ throw new Error(`Failed to start service ${name}: ${error.message}`, { cause: error });
99
+ }
100
+ }
101
+ async stopService(name) {
102
+ const service = this.services.get(name);
103
+ if (!service) {
104
+ throw new Error(`Service ${name} is not installed`);
105
+ }
106
+ if (service.status !== 'running') {
107
+ logger.warn(`Service ${name} is not running`);
108
+ return service;
109
+ }
110
+ const process = this.processes.get(name);
111
+ if (process) {
112
+ process.kill();
113
+ this.processes.delete(name);
114
+ }
115
+ service.status = 'stopped';
116
+ service.stoppedAt = new Date().toISOString();
117
+ service.pid = undefined;
118
+ this.saveServices();
119
+ logger.info(`Service stopped: ${name}`);
120
+ return service;
121
+ }
122
+ async restartService(name) {
123
+ await this.stopService(name);
124
+ // Wait for a while to ensure process is completely stopped
125
+ await new Promise(resolve => setTimeout(resolve, 1000));
126
+ return await this.startService(name);
127
+ }
128
+ async uninstallService(name) {
129
+ const service = this.services.get(name);
130
+ if (!service) {
131
+ throw new Error(`Service ${name} is not installed`);
132
+ }
133
+ // If service is running, stop it first
134
+ if (service.status === 'running') {
135
+ await this.stopService(name);
136
+ }
137
+ // Remove from configuration
138
+ this.services.delete(name);
139
+ this.saveServices();
140
+ logger.info(`Service uninstalled: ${name}`);
141
+ }
142
+ getService(name) {
143
+ return this.services.get(name);
144
+ }
145
+ getAllServices() {
146
+ return Array.from(this.services.values());
147
+ }
148
+ getRunningServices() {
149
+ return Array.from(this.services.values()).filter(s => s.status === 'running');
150
+ }
151
+ async getServiceLogs(name, lines = 50) {
152
+ const logDir = path.join(LOGS_DIR, name);
153
+ const logFile = path.join(logDir, 'stdout.log');
154
+ if (!fs.existsSync(logFile)) {
155
+ return `No logs found for service ${name}`;
156
+ }
157
+ try {
158
+ const content = fs.readFileSync(logFile, 'utf-8');
159
+ const linesArray = content.split('\n');
160
+ return linesArray.slice(-lines).join('\n');
161
+ }
162
+ catch (error) {
163
+ return `Failed to read logs: ${error.message}`;
164
+ }
165
+ }
166
+ async getServiceStats(name) {
167
+ const service = this.services.get(name);
168
+ if (!service) {
169
+ throw new Error(`Service ${name} not found`);
170
+ }
171
+ const process = this.processes.get(name);
172
+ return {
173
+ name: service.name,
174
+ status: service.status,
175
+ pid: service.pid,
176
+ runtime: service.runtime,
177
+ installedAt: service.installedAt,
178
+ startedAt: service.startedAt,
179
+ stoppedAt: service.stoppedAt,
180
+ isProcessAlive: process ? !process.exitCode : false,
181
+ memoryUsage: this.getProcessMemoryUsage(process),
182
+ uptime: service.startedAt
183
+ ? Date.now() - new Date(service.startedAt).getTime()
184
+ : 0,
185
+ };
186
+ }
187
+ spawnService(service) {
188
+ const { config } = service;
189
+ const cwd = config.path || '.';
190
+ let command;
191
+ let args = [];
192
+ switch (service.runtime) {
193
+ case 'node':
194
+ command = 'node';
195
+ args = [config.entry, ...(config.args || [])];
196
+ break;
197
+ case 'python':
198
+ command = 'python3';
199
+ args = [config.entry, ...(config.args || [])];
200
+ break;
201
+ case 'docker':
202
+ command = 'docker';
203
+ args = ['run', '-d', '--rm', '--name', `mcp-${service.name}`, config.image || service.name];
204
+ if (config.args) {
205
+ args.push(...config.args);
206
+ }
207
+ break;
208
+ default:
209
+ command = config.entry;
210
+ args = config.args || [];
211
+ }
212
+ logger.debug(`Spawning service: ${command} ${args.join(' ')}`);
213
+ return spawn(command, args, {
214
+ cwd,
215
+ env: {
216
+ ...process.env,
217
+ ...config.env,
218
+ },
219
+ stdio: ['pipe', 'pipe', 'pipe'],
220
+ detached: false,
221
+ });
222
+ }
223
+ detectEntryPoint(servicePath) {
224
+ const possibleEntries = [
225
+ 'index.js', 'main.js', 'app.js', 'server.js',
226
+ 'index.ts', 'main.ts', 'app.ts', 'server.ts',
227
+ 'main.py', 'app.py', 'server.py',
228
+ 'main.go', 'server.go',
229
+ 'main.rs', 'lib.rs',
230
+ ];
231
+ for (const entry of possibleEntries) {
232
+ const entryPath = path.join(servicePath, entry);
233
+ if (fs.existsSync(entryPath)) {
234
+ return entry;
235
+ }
236
+ }
237
+ // If no standard entry point found, return the first file
238
+ const files = fs.readdirSync(servicePath);
239
+ const firstFile = files.find(f => f.endsWith('.js') || f.endsWith('.ts') || f.endsWith('.py') ||
240
+ f.endsWith('.go') || f.endsWith('.rs'));
241
+ return firstFile || 'index.js';
242
+ }
243
+ getProcessMemoryUsage(process) {
244
+ if (!process || !process.pid) {
245
+ return undefined;
246
+ }
247
+ try {
248
+ // This is a simplified implementation, should actually use system-specific methods
249
+ // For example, reading /proc/[pid]/status on Linux
250
+ return 0;
251
+ }
252
+ catch {
253
+ return undefined;
254
+ }
255
+ }
256
+ async healthCheck(name) {
257
+ const service = this.services.get(name);
258
+ if (!service || service.status !== 'running') {
259
+ return false;
260
+ }
261
+ const process = this.processes.get(name);
262
+ if (!process || process.exitCode !== null) {
263
+ return false;
264
+ }
265
+ // More complex health check logic can be added here
266
+ // For example, checking HTTP endpoints, TCP ports, etc.
267
+ return true;
268
+ }
269
+ async cleanup() {
270
+ // Stop all running services
271
+ for (const [name, service] of this.services) {
272
+ if (service.status === 'running') {
273
+ await this.stopService(name);
274
+ }
275
+ }
276
+ }
277
+ }
278
+ //# sourceMappingURL=service.js.map
@@ -0,0 +1,30 @@
1
+ import { SDKOptions, MCPilotSDK, mcpilot } from './sdk';
2
+ /**
3
+ * IntentOrch SDK Core - Main Entry File
4
+ * Exports all public APIs, designed for developers
5
+ * Formerly known as MCPilot SDK
6
+ */
7
+ export { MCPilotSDK, IntentOrchSDK, mcpilot, intentorch } from './sdk';
8
+ export type { SDKOptions, ServiceStatus, AskOptions, AskResult, } from './sdk';
9
+ export type { RuntimeType, ServiceConfig, Config, AIConfig, DetectionResult, } from './core/types';
10
+ export type { RuntimeAdapter } from './runtime/adapter';
11
+ export { EnhancedRuntimeDetector } from './runtime/detector-advanced';
12
+ export { ConfigManager } from './core/config-manager';
13
+ export { SimpleAI } from './ai/ai';
14
+ export { CloudIntentEngine, type CloudIntentEngineConfig, type AtomicIntent, type DependencyEdge, type IntentParseResult, type ToolSelectionResult, type ExecutionContext, type ExecutionResult, type EnhancedExecutionStep, type WorkflowPlan, type EnhancedExecutionResult, } from './ai';
15
+ export { MCPClient, ToolRegistry, createMCPConfig, TOOL_CATEGORIES, TOOL_PATTERNS, discoverLocalMCPServers, loadMCPServersFromEnv, } from './mcp';
16
+ export { BaseTransport, StdioTransport, HTTPTransport, SSETransport, TransportFactory } from './mcp/transport';
17
+ export { MCP_METHODS, MCP_ERROR_CODES } from './mcp/types';
18
+ export type { Tool, ToolCall, ToolResult, MCPClientConfig, TransportConfig, StdioLogFilterConfig, TransportType, MCPError, JSONRPCRequest, JSONRPCResponse, Resource, ResourceList, ResourceContents, Prompt, PromptList, MCPSession, MCPEvent, MCPEventType, } from './mcp/types';
19
+ export { logger } from './core/logger';
20
+ export { MCPilotError, IntentOrchError, ErrorCode, ErrorSeverity, ErrorFactory, ErrorHandler, ConsoleErrorHandler, RetryErrorHandler, createError, wrapError, isMCPilotError, shouldRetry, } from './core/error-handler';
21
+ export { PerformanceMonitor, getPerformanceMonitor } from './core/performance-monitor';
22
+ /**
23
+ * Quick start function - Create and return SDK instance
24
+ */
25
+ export declare function createSDK(options?: SDKOptions): MCPilotSDK;
26
+ /**
27
+ * Default export - Singleton instance
28
+ */
29
+ export default mcpilot;
30
+ //# sourceMappingURL=index.d.ts.map
package/dist/index.js ADDED
@@ -0,0 +1,36 @@
1
+ import { MCPilotSDK, mcpilot } from './sdk.js';
2
+ /**
3
+ * IntentOrch SDK Core - Main Entry File
4
+ * Exports all public APIs, designed for developers
5
+ * Formerly known as MCPilot SDK
6
+ */
7
+ // Export core SDK class and types (with backward compatibility)
8
+ export { MCPilotSDK, IntentOrchSDK, mcpilot, intentorch } from './sdk.js';
9
+ export { EnhancedRuntimeDetector } from './runtime/detector-advanced.js';
10
+ // Export configuration manager
11
+ export { ConfigManager } from './core/config-manager.js';
12
+ // Export AI functionality (optional)
13
+ export { SimpleAI } from './ai/ai.js';
14
+ // Export Cloud Intent Engine functionality
15
+ export { CloudIntentEngine, } from './ai/index.js';
16
+ // Export MCP functionality
17
+ export { MCPClient, ToolRegistry, createMCPConfig, TOOL_CATEGORIES, TOOL_PATTERNS, discoverLocalMCPServers, loadMCPServersFromEnv, } from './mcp/index.js';
18
+ export { BaseTransport, StdioTransport, HTTPTransport, SSETransport, TransportFactory } from './mcp/transport.js';
19
+ export { MCP_METHODS, MCP_ERROR_CODES } from './mcp/types.js';
20
+ // Export utility functions
21
+ export { logger } from './core/logger.js';
22
+ // Export error handling
23
+ export { MCPilotError, IntentOrchError, ErrorCode, ErrorSeverity, ErrorFactory, ErrorHandler, ConsoleErrorHandler, RetryErrorHandler, createError, wrapError, isMCPilotError, shouldRetry, } from './core/error-handler.js';
24
+ // Export performance monitoring
25
+ export { PerformanceMonitor, getPerformanceMonitor } from './core/performance-monitor.js';
26
+ /**
27
+ * Quick start function - Create and return SDK instance
28
+ */
29
+ export function createSDK(options) {
30
+ return new MCPilotSDK(options);
31
+ }
32
+ /**
33
+ * Default export - Singleton instance
34
+ */
35
+ export default mcpilot;
36
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,51 @@
1
+ /**
2
+ * MCP Client Core Class
3
+ * Provides complete MCP protocol client functionality
4
+ */
5
+ import { EventEmitter } from 'events';
6
+ import { MCPClientConfig, Tool, ToolResult, Resource, Prompt } from './types';
7
+ export declare class MCPClient extends EventEmitter {
8
+ private config;
9
+ private transport;
10
+ private connected;
11
+ private requestId;
12
+ private pendingRequests;
13
+ private tools;
14
+ private resources;
15
+ private prompts;
16
+ private sessionId?;
17
+ constructor(config: MCPClientConfig);
18
+ connect(): Promise<void>;
19
+ disconnect(): Promise<void>;
20
+ isConnected(): boolean;
21
+ listTools(): Promise<Tool[]>;
22
+ callTool(toolName: string, arguments_: Record<string, any>): Promise<ToolResult>;
23
+ refreshTools(): Promise<void>;
24
+ getTools(): Tool[];
25
+ findTool(name: string): Tool | undefined;
26
+ listResources(): Promise<Resource[]>;
27
+ readResource(uri: string): Promise<any>;
28
+ refreshResources(): Promise<void>;
29
+ getResources(): Resource[];
30
+ listPrompts(): Promise<Prompt[]>;
31
+ getPrompt(name: string, arguments_?: Record<string, any>): Promise<any>;
32
+ refreshPrompts(): Promise<void>;
33
+ getPrompts(): Prompt[];
34
+ private sendRequest;
35
+ private generateRequestId;
36
+ private setupTransportListeners;
37
+ private handleTransportMessage;
38
+ private handleTransportError;
39
+ private handleNotification;
40
+ private emitEvent;
41
+ withRetry<T>(operation: () => Promise<T>): Promise<T>;
42
+ getStatus(): {
43
+ connected: boolean;
44
+ toolsCount: number;
45
+ resourcesCount: number;
46
+ promptsCount: number;
47
+ sessionId: string;
48
+ };
49
+ destroy(): void;
50
+ }
51
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1,276 @@
1
+ /**
2
+ * MCP Client Core Class
3
+ * Provides complete MCP protocol client functionality
4
+ */
5
+ import { EventEmitter } from 'events';
6
+ import { MCP_METHODS, } from './types.js';
7
+ import { TransportFactory } from './transport.js';
8
+ export class MCPClient extends EventEmitter {
9
+ config;
10
+ transport;
11
+ connected = false;
12
+ requestId = 0;
13
+ pendingRequests = new Map();
14
+ // State
15
+ tools = [];
16
+ resources = [];
17
+ prompts = [];
18
+ sessionId;
19
+ constructor(config) {
20
+ super();
21
+ this.config = {
22
+ autoConnect: false, // Default disable auto-connect requests to avoid server not being ready
23
+ timeout: 30000,
24
+ maxRetries: 3,
25
+ ...config,
26
+ };
27
+ this.transport = TransportFactory.create(config.transport);
28
+ this.setupTransportListeners();
29
+ }
30
+ // ==================== Connection Management ====================
31
+ async connect() {
32
+ if (this.connected) {
33
+ return;
34
+ }
35
+ try {
36
+ await this.transport.connect();
37
+ this.connected = true;
38
+ this.emitEvent('connected');
39
+ // Automatically fetch tool list after connection
40
+ if (this.config.autoConnect) {
41
+ await this.refreshTools();
42
+ await this.refreshResources();
43
+ await this.refreshPrompts();
44
+ }
45
+ }
46
+ catch (error) {
47
+ this.emitEvent('error', error);
48
+ throw error;
49
+ }
50
+ }
51
+ async disconnect() {
52
+ if (!this.connected) {
53
+ return;
54
+ }
55
+ try {
56
+ await this.transport.disconnect();
57
+ this.connected = false;
58
+ // Clean up all pending requests
59
+ this.pendingRequests.forEach(({ reject, timeout }) => {
60
+ clearTimeout(timeout);
61
+ reject(new Error('Disconnected'));
62
+ });
63
+ this.pendingRequests.clear();
64
+ this.emitEvent('disconnected');
65
+ }
66
+ catch (error) {
67
+ this.emitEvent('error', error);
68
+ throw error;
69
+ }
70
+ }
71
+ isConnected() {
72
+ return this.connected && this.transport.isConnected();
73
+ }
74
+ // ==================== Tool Related Methods ====================
75
+ async listTools() {
76
+ const response = await this.sendRequest(MCP_METHODS.TOOLS_LIST);
77
+ const toolList = response;
78
+ this.tools = toolList.tools;
79
+ this.emitEvent('tools_updated', this.tools);
80
+ return this.tools;
81
+ }
82
+ async callTool(toolName, arguments_) {
83
+ const toolCall = {
84
+ name: toolName,
85
+ arguments: arguments_,
86
+ };
87
+ const response = await this.sendRequest(MCP_METHODS.TOOLS_CALL, { call: toolCall });
88
+ // Ensure response is a valid ToolResult
89
+ const toolResult = response;
90
+ // Check if the tool execution failed (isError flag)
91
+ if (toolResult.isError) {
92
+ // Create a proper error from the tool result content
93
+ const errorMessage = toolResult.content?.[0]?.text || 'Tool execution failed';
94
+ throw new Error(`Tool "${toolName}" execution failed: ${errorMessage}`);
95
+ }
96
+ return toolResult;
97
+ }
98
+ async refreshTools() {
99
+ await this.listTools();
100
+ }
101
+ getTools() {
102
+ return [...this.tools];
103
+ }
104
+ findTool(name) {
105
+ return this.tools.find(tool => tool.name === name);
106
+ }
107
+ // ==================== Resource Related Methods ====================
108
+ async listResources() {
109
+ const response = await this.sendRequest(MCP_METHODS.RESOURCES_LIST);
110
+ const resourceList = response;
111
+ this.resources = resourceList.resources;
112
+ this.emitEvent('resources_updated', this.resources);
113
+ return this.resources;
114
+ }
115
+ async readResource(uri) {
116
+ const response = await this.sendRequest(MCP_METHODS.RESOURCES_READ, { uri });
117
+ return response;
118
+ }
119
+ async refreshResources() {
120
+ await this.listResources();
121
+ }
122
+ getResources() {
123
+ return [...this.resources];
124
+ }
125
+ // ==================== Prompt Related Methods ====================
126
+ async listPrompts() {
127
+ const response = await this.sendRequest(MCP_METHODS.PROMPTS_LIST);
128
+ const promptList = response;
129
+ this.prompts = promptList.prompts;
130
+ this.emitEvent('prompts_updated', this.prompts);
131
+ return this.prompts;
132
+ }
133
+ async getPrompt(name, arguments_) {
134
+ const response = await this.sendRequest(MCP_METHODS.PROMPTS_GET, {
135
+ name,
136
+ arguments: arguments_,
137
+ });
138
+ return response;
139
+ }
140
+ async refreshPrompts() {
141
+ await this.listPrompts();
142
+ }
143
+ getPrompts() {
144
+ return [...this.prompts];
145
+ }
146
+ // ==================== Core Request Methods ====================
147
+ async sendRequest(method, params) {
148
+ if (!this.isConnected()) {
149
+ throw new Error('Not connected to MCP server');
150
+ }
151
+ const requestId = this.generateRequestId();
152
+ const request = {
153
+ jsonrpc: '2.0',
154
+ id: requestId,
155
+ method,
156
+ params,
157
+ };
158
+ return new Promise((resolve, reject) => {
159
+ const timeout = setTimeout(() => {
160
+ this.pendingRequests.delete(requestId);
161
+ reject(new Error(`Request timeout after ${this.config.timeout}ms`));
162
+ }, this.config.timeout);
163
+ this.pendingRequests.set(requestId, { resolve, reject, timeout });
164
+ this.transport.send(request).catch(error => {
165
+ this.pendingRequests.delete(requestId);
166
+ clearTimeout(timeout);
167
+ reject(error);
168
+ });
169
+ });
170
+ }
171
+ generateRequestId() {
172
+ return `req_${++this.requestId}_${Date.now()}`;
173
+ }
174
+ // ==================== Transport Layer Event Handling ====================
175
+ setupTransportListeners() {
176
+ this.transport.on('message', this.handleTransportMessage.bind(this));
177
+ this.transport.on('error', this.handleTransportError.bind(this));
178
+ this.transport.on('connected', () => {
179
+ this.connected = true;
180
+ this.emitEvent('connected');
181
+ });
182
+ this.transport.on('disconnected', () => {
183
+ this.connected = false;
184
+ this.emitEvent('disconnected');
185
+ });
186
+ }
187
+ handleTransportMessage(message) {
188
+ try {
189
+ const response = message;
190
+ // Handle request response
191
+ if (response.id && this.pendingRequests.has(response.id)) {
192
+ const { resolve, reject, timeout } = this.pendingRequests.get(response.id);
193
+ clearTimeout(timeout);
194
+ this.pendingRequests.delete(response.id);
195
+ if (response.error) {
196
+ const errorMessage = response.error.message || 'Unknown error';
197
+ const error = new Error(errorMessage);
198
+ error.code = response.error.code;
199
+ error.data = response.error.data;
200
+ reject(error);
201
+ }
202
+ else {
203
+ resolve(response.result);
204
+ }
205
+ }
206
+ // Handle server-pushed notifications (messages without id)
207
+ else if (!response.id) {
208
+ this.handleNotification(response);
209
+ }
210
+ }
211
+ catch (error) {
212
+ this.emitEvent('error', error);
213
+ }
214
+ }
215
+ handleTransportError(error) {
216
+ this.emitEvent('error', error);
217
+ }
218
+ handleNotification(response) {
219
+ // Handle server-pushed notifications
220
+ // For example: tools/changed, resources/changed, etc.
221
+ if (response.result) {
222
+ // Can handle different types of notifications based on method field
223
+ console.log('Received notification:', response);
224
+ }
225
+ }
226
+ // ==================== Event Emission ====================
227
+ emitEvent(type, data) {
228
+ const event = {
229
+ type,
230
+ data,
231
+ timestamp: Date.now(),
232
+ };
233
+ this.emit(type, event);
234
+ this.emit('event', event);
235
+ }
236
+ // ==================== Utility Methods ====================
237
+ async withRetry(operation) {
238
+ let lastError;
239
+ for (let attempt = 1; attempt <= this.config.maxRetries; attempt++) {
240
+ try {
241
+ return await operation();
242
+ }
243
+ catch (error) {
244
+ lastError = error;
245
+ if (attempt < this.config.maxRetries) {
246
+ const delay = Math.min(1000 * Math.pow(2, attempt - 1), 10000);
247
+ await new Promise(resolve => setTimeout(resolve, delay));
248
+ continue;
249
+ }
250
+ }
251
+ }
252
+ throw lastError;
253
+ }
254
+ // ==================== Status Query ====================
255
+ getStatus() {
256
+ return {
257
+ connected: this.connected,
258
+ toolsCount: this.tools.length,
259
+ resourcesCount: this.resources.length,
260
+ promptsCount: this.prompts.length,
261
+ sessionId: this.sessionId,
262
+ };
263
+ }
264
+ // ==================== Cleanup ====================
265
+ destroy() {
266
+ this.disconnect().catch(() => {
267
+ // Ignore errors when disconnecting
268
+ });
269
+ this.removeAllListeners();
270
+ this.pendingRequests.clear();
271
+ this.tools = [];
272
+ this.resources = [];
273
+ this.prompts = [];
274
+ }
275
+ }
276
+ //# sourceMappingURL=client.js.map