tabby-mcp-server 1.2.0 → 1.4.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tabby-mcp-server",
3
- "version": "1.2.0",
3
+ "version": "1.4.0",
4
4
  "description": "MCP (Model Context Protocol) server plugin for Tabby terminal - Complete terminal control with 34 MCP tools including SFTP file transfer",
5
5
  "homepage": "https://github.com/GentlemanHu/Tabby-MCP",
6
6
  "repository": {
@@ -3,6 +3,7 @@ import { ConfigService } from 'tabby-core';
3
3
  import { McpService } from '../services/mcpService';
4
4
  import { McpLoggerService } from '../services/mcpLogger.service';
5
5
  import { McpI18nService } from '../services/i18n.service';
6
+ import { SFTPToolCategory } from '../tools/sftp';
6
7
  /**
7
8
  * MCP Settings Tab Component with i18n support
8
9
  */
@@ -11,10 +12,11 @@ export declare class McpSettingsTabComponent implements OnInit, OnDestroy {
11
12
  private mcpService;
12
13
  private logger;
13
14
  private i18n;
15
+ private sftpTools;
14
16
  version: string;
15
17
  saveMessage: string;
16
18
  private configSub?;
17
- constructor(config: ConfigService, mcpService: McpService, logger: McpLoggerService, i18n: McpI18nService);
19
+ constructor(config: ConfigService, mcpService: McpService, logger: McpLoggerService, i18n: McpI18nService, sftpTools: SFTPToolCategory);
18
20
  ngOnInit(): void;
19
21
  ngOnDestroy(): void;
20
22
  /**
@@ -52,4 +54,14 @@ export declare class McpSettingsTabComponent implements OnInit, OnDestroy {
52
54
  closeSession(sessionId: string): Promise<void>;
53
55
  formatDuration(ms: number): string;
54
56
  formatTime(ms: number): string;
57
+ showTransferMonitor: boolean;
58
+ transfers: any[];
59
+ private transferSub?;
60
+ openTransferMonitor(): void;
61
+ closeTransferMonitor(): void;
62
+ refreshTransfers(): void;
63
+ cancelTransfer(transferId: string): void;
64
+ clearCompletedTransfers(): void;
65
+ getFileName(filePath: string): string;
66
+ formatBytes(bytes: number): string;
55
67
  }
@@ -11,7 +11,7 @@ import { ToolCategory, McpTool } from '../types/types';
11
11
  export declare class McpService {
12
12
  config: ConfigService;
13
13
  private logger;
14
- private server;
14
+ private sessionServers;
15
15
  private legacyTransports;
16
16
  private streamableTransports;
17
17
  private app;
@@ -19,17 +19,27 @@ export declare class McpService {
19
19
  private sockets;
20
20
  private isRunning;
21
21
  private toolCategories;
22
+ private registeredTools;
22
23
  constructor(config: ConfigService, logger: McpLoggerService);
23
24
  /**
24
- * Initialize the MCP server
25
+ * Initialize the MCP service (no longer creates a single server)
25
26
  */
26
27
  private initializeServer;
27
28
  /**
28
- * Register a tool category with the MCP server
29
+ * Create a new McpServer instance for a specific session
30
+ * Each client gets its own server to avoid SDK Bug #1459
31
+ */
32
+ private createServerForSession;
33
+ /**
34
+ * Clean up server for a specific session
35
+ */
36
+ private cleanupServerForSession;
37
+ /**
38
+ * Register a tool category - stores definitions for per-session server creation
29
39
  */
30
40
  registerToolCategory(category: ToolCategory): void;
31
41
  /**
32
- * Register a single tool
42
+ * Register a single tool - stores definition for per-session server creation
33
43
  */
34
44
  registerTool(tool: McpTool): void;
35
45
  /**
@@ -2,6 +2,27 @@ import { AppService, ConfigService } from 'tabby-core';
2
2
  import { BaseToolCategory } from './base-tool-category';
3
3
  import { McpLoggerService } from '../services/mcpLogger.service';
4
4
  import { TerminalToolCategory } from './terminal';
5
+ /**
6
+ * Transfer task status
7
+ */
8
+ interface TransferTask {
9
+ id: string;
10
+ type: 'upload' | 'download';
11
+ localPath: string;
12
+ remotePath: string;
13
+ sessionId: string;
14
+ connectionName: string;
15
+ status: 'pending' | 'running' | 'completed' | 'failed' | 'cancelled';
16
+ progress: number;
17
+ bytesTransferred: number;
18
+ totalBytes: number;
19
+ startTime: number;
20
+ endTime?: number;
21
+ error?: string;
22
+ speed?: number;
23
+ cancelCallback?: () => void;
24
+ reject?: (reason?: any) => void;
25
+ }
5
26
  /**
6
27
  * SFTP Tools Category - File transfer operations for SSH sessions
7
28
  * Uses Tabby's real SFTP API: SSHSession.openSFTP() -> SFTPSession
@@ -21,13 +42,40 @@ export declare class SFTPToolCategory extends BaseToolCategory {
21
42
  private terminalTools;
22
43
  name: string;
23
44
  private sftpSessionCache;
45
+ private readonly SFTP_SESSION_TTL_MS;
24
46
  private transferTasks;
47
+ private _transferTasksSubject;
48
+ readonly transferTasks$: import("rxjs").Observable<TransferTask[]>;
25
49
  private maxTransferHistory;
26
50
  constructor(app: AppService, config: ConfigService, logger: McpLoggerService, terminalTools: TerminalToolCategory);
27
51
  isAvailable(): boolean;
28
52
  private initializeTools;
29
53
  private generateTransferId;
54
+ /** Emit current transfer state to UI subscribers */
55
+ private emitTransferUpdate;
30
56
  private cleanupOldTransfers;
57
+ /**
58
+ * Wait for transfer to complete with a polling fallback.
59
+ *
60
+ * Tabby's SFTP API (based on russh) may not always resolve the Promise
61
+ * even when the transfer is complete. This method uses Promise.race to
62
+ * detect completion via polling the isComplete() method.
63
+ *
64
+ * Also checks for SSH session disconnection to prevent infinite waits.
65
+ *
66
+ * @param sftpPromise - The original sftpSession.upload/download promise
67
+ * @param transferObj - StreamFileUpload or StreamFileDownload with isComplete()
68
+ * @param sshSession - Optional SSH session to check for disconnection
69
+ * @param pollIntervalMs - How often to check isComplete()
70
+ * @param maxWaitMs - Maximum time to wait before timing out (0 = no timeout)
71
+ */
72
+ private waitForTransferComplete;
73
+ /** Get current snapshot of all transfers */
74
+ getTransfers(): TransferTask[];
75
+ /** Cancel a transfer by ID (for UI button) */
76
+ cancelTransferById(transferId: string): boolean;
77
+ /** Clear all completed/failed/cancelled transfers from history */
78
+ clearCompletedTransfers(): void;
31
79
  /**
32
80
  * Get session ID for a tab - delegates to TerminalToolCategory
33
81
  * This ensures SFTP uses the same session IDs as terminal tools
@@ -36,6 +84,11 @@ export declare class SFTPToolCategory extends BaseToolCategory {
36
84
  private findAllSSHTabs;
37
85
  private findSSHSession;
38
86
  private getSFTPSession;
87
+ /**
88
+ * Cleanup stale SFTP sessions from closed SSH connections
89
+ * Called periodically when creating new sessions
90
+ */
91
+ private cleanupStaleSFTPSessions;
39
92
  private readonly sessionSchema;
40
93
  private createListFilesTool;
41
94
  private createReadFileTool;
@@ -50,3 +103,4 @@ export declare class SFTPToolCategory extends BaseToolCategory {
50
103
  private createListTransfersTool;
51
104
  private createCancelTransferTool;
52
105
  }
106
+ export {};
@@ -84,6 +84,11 @@ export declare class TerminalToolCategory extends BaseToolCategory {
84
84
  * Enhanced with flexible session targeting
85
85
  */
86
86
  private createExecCommandTool;
87
+ /**
88
+ * Check if a session is valid (tab exists and is connected)
89
+ * Returns true if valid, throws error if invalid
90
+ */
91
+ private ensureSessionValid;
87
92
  /**
88
93
  * Tool: Send raw input to terminal (for interactive commands)
89
94
  */
@@ -117,5 +122,10 @@ export declare class TerminalToolCategory extends BaseToolCategory {
117
122
  * Wait for command output between markers
118
123
  * Timing is configurable via Settings → MCP → Timing
119
124
  */
120
- private waitForCommandOutput;
125
+ private waitForCommandOutputViaBuffer;
126
+ /**
127
+ * Wait for command output using Stream Capture (Observable)
128
+ * This bypasses the terminal buffer limit and works for huge outputs
129
+ */
130
+ private waitForCommandOutputViaStream;
121
131
  }
@@ -59,6 +59,7 @@ export interface McpConfig {
59
59
  showConfirmationDialog: boolean;
60
60
  autoFocusTerminal: boolean;
61
61
  };
62
+ useStreamCapture?: boolean;
62
63
  }
63
64
  /**
64
65
  * Command history entry