tabby-mcp-server 1.1.2 → 1.1.3

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/README.md CHANGED
@@ -184,7 +184,7 @@ For clients that don't support SSE, use the STDIO bridge:
184
184
  ```json
185
185
  {
186
186
  "mcpServers": {
187
- "tabby-mcp": {
187
+ "tabby-mcp-server": {
188
188
  "command": "node",
189
189
  "args": ["/path/to/Tabby-MCP/scripts/stdio-bridge.js"]
190
190
  }
@@ -198,7 +198,7 @@ For clients that don't support SSE, use the STDIO bridge:
198
198
  {
199
199
  "mcp": {
200
200
  "servers": {
201
- "tabby-mcp": {
201
+ "tabby-mcp-server": {
202
202
  "type": "stdio",
203
203
  "command": "node",
204
204
  "args": ["scripts/stdio-bridge.js"],
@@ -354,6 +354,20 @@ This project builds upon the work of [tabby-mcp-server](https://github.com/thuan
354
354
 
355
355
  ## 📝 Changelog
356
356
 
357
+ ### v1.1.3 (2026-01-22)
358
+
359
+ **Bug Fixes:**
360
+ - 🔧 Fixed `open_profile` sessionId inconsistency - now returns same sessionId as `get_session_list`
361
+ - Fixed SSH connection state detection - `ready` now correctly reflects overall connection status
362
+
363
+ **Improvements:**
364
+ - Clearer state fields in `open_profile` response:
365
+ - `tabReady`: Tab/frontend initialized
366
+ - `sshConnected`: SSH connection established (SSH profiles only)
367
+ - `ready`: Overall ready state (for SSH: tabReady AND sshConnected)
368
+ - Marked all peerDependencies as optional to prevent unnecessary package downloads
369
+ - Added `tabby-ssh` to devDependencies for developer build stability
370
+
357
371
  ### v1.1.2 (2026-01-22)
358
372
 
359
373
  **Optimization:**
package/dist/index.js CHANGED
@@ -17454,7 +17454,7 @@ const tabby_core_1 = __webpack_require__(1368);
17454
17454
  const mcpService_1 = __webpack_require__(7554);
17455
17455
  const mcpLogger_service_1 = __webpack_require__(9924);
17456
17456
  // Version from package.json - update on each release
17457
- const PLUGIN_VERSION = '1.1.2';
17457
+ const PLUGIN_VERSION = '1.1.3';
17458
17458
  /**
17459
17459
  * MCP Settings Tab Component
17460
17460
  */
@@ -24837,6 +24837,7 @@ let TerminalToolCategory = class TerminalToolCategory extends base_tool_category
24837
24837
  }
24838
24838
  /**
24839
24839
  * Get or create a stable session ID for a tab
24840
+ * Made public for cross-category access (e.g., from TabManagementToolCategory)
24840
24841
  */
24841
24842
  getOrCreateSessionId(tab) {
24842
24843
  let sessionId = this.tabToSessionId.get(tab);
@@ -28589,6 +28590,9 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
28589
28590
  var __metadata = (this && this.__metadata) || function (k, v) {
28590
28591
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
28591
28592
  };
28593
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
28594
+ return function (target, key) { decorator(target, key, paramIndex); }
28595
+ };
28592
28596
  Object.defineProperty(exports, "__esModule", ({ value: true }));
28593
28597
  exports.TabManagementToolCategory = void 0;
28594
28598
  const core_1 = __webpack_require__(9430);
@@ -28597,15 +28601,17 @@ const tabby_terminal_1 = __webpack_require__(4319);
28597
28601
  const zod_1 = __webpack_require__(7552);
28598
28602
  const base_tool_category_1 = __webpack_require__(2099);
28599
28603
  const mcpLogger_service_1 = __webpack_require__(9924);
28604
+ const terminal_1 = __webpack_require__(2966);
28600
28605
  /**
28601
28606
  * Tab Management Tools Category - Comprehensive tab and profile management
28602
28607
  */
28603
28608
  let TabManagementToolCategory = class TabManagementToolCategory extends base_tool_category_1.BaseToolCategory {
28604
- constructor(app, logger, config, profilesService) {
28609
+ constructor(app, logger, config, profilesService, terminalTools) {
28605
28610
  super(logger);
28606
28611
  this.app = app;
28607
28612
  this.config = config;
28608
28613
  this.profilesService = profilesService;
28614
+ this.terminalTools = terminalTools;
28609
28615
  this.name = 'tab_management';
28610
28616
  // Tab ID registry for stable IDs
28611
28617
  // Use both WeakMap (for tab -> id) and Map (for id -> tab) to support bidirectional lookup
@@ -29021,6 +29027,12 @@ Parameters:
29021
29027
  - timeout: Timeout in ms when waiting (default: 30000)
29022
29028
 
29023
29029
  Returns sessionId for immediate use with exec_command, SFTP tools, etc.
29030
+
29031
+ Response state fields:
29032
+ - tabReady: Tab/frontend initialized
29033
+ - sshConnected: SSH connection established (SSH profiles only)
29034
+ - ready: OVERALL ready state (for SSH: tabReady AND sshConnected)
29035
+
29024
29036
  For SSH profiles, waits until sshSession.open=true (real connection established).
29025
29037
 
29026
29038
  NOTE: This opens a NEW tab. For existing connections, use get_session_list + exec_command.`,
@@ -29075,13 +29087,24 @@ NOTE: This opens a NEW tab. For existing connections, use get_session_list + exe
29075
29087
  const isSSH = profile.type === 'ssh' || profile.type?.includes('ssh');
29076
29088
  // Determine default waitForReady based on profile type
29077
29089
  const waitForReady = params?.waitForReady ?? isSSH;
29078
- // Generate sessionId for the new tab
29079
- // Use same UUID generation as TerminalToolCategory
29080
- let sessionId = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
29081
- const r = Math.random() * 16 | 0;
29082
- const v = c === 'x' ? r : (r & 0x3 | 0x8);
29083
- return v.toString(16);
29084
- });
29090
+ // Get sessionId from TerminalToolCategory's registry
29091
+ // CRITICAL: Call getOrCreateSessionId DIRECTLY on the tab object
29092
+ // DO NOT use findTerminalSessions() as the tab may not yet be in app.tabs
29093
+ let sessionId;
29094
+ if (tab instanceof tabby_terminal_1.BaseTerminalTabComponent) {
29095
+ // Direct call to getOrCreateSessionId ensures the same ID is registered
29096
+ sessionId = this.terminalTools.getOrCreateSessionId(tab);
29097
+ this.logger.debug(`[open_profile] SessionId assigned: ${sessionId}`);
29098
+ }
29099
+ // Fallback: generate UUID if not a terminal tab (shouldn't happen)
29100
+ if (!sessionId) {
29101
+ sessionId = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
29102
+ const r = Math.random() * 16 | 0;
29103
+ const v = c === 'x' ? r : (r & 0x3 | 0x8);
29104
+ return v.toString(16);
29105
+ });
29106
+ this.logger.warn(`[open_profile] Tab is not BaseTerminalTabComponent, generated fallback sessionId: ${sessionId}`);
29107
+ }
29085
29108
  if (waitForReady) {
29086
29109
  // Wait for the terminal session to be fully connected
29087
29110
  const timing = this.config.store.mcp?.timing || {};
@@ -29148,7 +29171,11 @@ NOTE: This opens a NEW tab. For existing connections, use get_session_list + exe
29148
29171
  await new Promise(resolve => setTimeout(resolve, sessionPollInterval));
29149
29172
  }
29150
29173
  const elapsed = Date.now() - startTime;
29151
- this.logger.info(`[open_profile] Profile opened: ${profile.name} (tabReady=${tabReady}, sshConnected=${sshConnected}, elapsed=${elapsed}ms)`);
29174
+ // Determine final ready state:
29175
+ // - For SSH: ready = tabReady AND sshConnected
29176
+ // - For non-SSH: ready = tabReady
29177
+ const ready = isSSH ? (tabReady && sshConnected) : tabReady;
29178
+ this.logger.info(`[open_profile] Profile opened: ${profile.name} (tabReady=${tabReady}, sshConnected=${sshConnected}, ready=${ready}, elapsed=${elapsed}ms)`);
29152
29179
  return {
29153
29180
  content: [{
29154
29181
  type: 'text', text: JSON.stringify({
@@ -29159,13 +29186,19 @@ NOTE: This opens a NEW tab. For existing connections, use get_session_list + exe
29159
29186
  tabTitle: tab.title,
29160
29187
  profileName: profile.name,
29161
29188
  profileType: profile.type,
29162
- ready: tabReady,
29163
- sshConnected: isSSH ? sshConnected : undefined,
29189
+ // State fields with clear semantics:
29190
+ tabReady, // Tab/frontend initialized
29191
+ sshConnected: isSSH ? sshConnected : undefined, // SSH connection established (SSH only)
29192
+ ready, // OVERALL ready state: can start using this session
29164
29193
  elapsed: `${elapsed}ms`,
29165
- message: tabReady
29194
+ message: ready
29166
29195
  ? `Profile ready: ${profile.name}`
29167
- : `Profile opened but may not be fully connected: ${profile.name}`,
29168
- hint: 'Use sessionId with exec_command, SFTP tools, etc.'
29196
+ : tabReady && !sshConnected
29197
+ ? `Tab opened but SSH not connected: ${profile.name}`
29198
+ : `Profile opened but not fully ready: ${profile.name}`,
29199
+ hint: ready
29200
+ ? 'Use sessionId with exec_command, SFTP tools, etc.'
29201
+ : 'Session may not be fully connected. Check sshConnected status.'
29169
29202
  })
29170
29203
  }]
29171
29204
  };
@@ -29182,9 +29215,12 @@ NOTE: This opens a NEW tab. For existing connections, use get_session_list + exe
29182
29215
  tabTitle: tab.title,
29183
29216
  profileName: profile.name,
29184
29217
  profileType: profile.type,
29185
- ready: false,
29218
+ // State fields (unknown since we didn't wait)
29219
+ tabReady: undefined, // Unknown - didn't wait
29220
+ sshConnected: undefined, // Unknown - didn't wait
29221
+ ready: false, // Not verified as ready
29186
29222
  message: `Opened profile: ${profile.name}`,
29187
- note: 'Profile opened. SSH connections may take a moment to establish.',
29223
+ note: 'Profile opened without waiting. Use get_session_list to check status.',
29188
29224
  hint: 'Use sessionId with exec_command, SFTP tools, etc.'
29189
29225
  })
29190
29226
  }]
@@ -29447,10 +29483,12 @@ The active tab must be inside a SplitTabComponent, or be a terminal that can be
29447
29483
  exports.TabManagementToolCategory = TabManagementToolCategory;
29448
29484
  exports.TabManagementToolCategory = TabManagementToolCategory = __decorate([
29449
29485
  (0, core_1.Injectable)({ providedIn: 'root' }),
29486
+ __param(4, (0, core_1.Inject)((0, core_1.forwardRef)(() => terminal_1.TerminalToolCategory))),
29450
29487
  __metadata("design:paramtypes", [tabby_core_1.AppService,
29451
29488
  mcpLogger_service_1.McpLoggerService,
29452
29489
  tabby_core_1.ConfigService,
29453
- tabby_core_1.ProfilesService])
29490
+ tabby_core_1.ProfilesService,
29491
+ terminal_1.TerminalToolCategory])
29454
29492
  ], TabManagementToolCategory);
29455
29493
 
29456
29494
 
@@ -52531,7 +52569,7 @@ let McpService = class McpService {
52531
52569
  // Initialize MCP Server
52532
52570
  this.server = new mcp_js_1.McpServer({
52533
52571
  name: 'Tabby MCP',
52534
- version: '1.1.2'
52572
+ version: '1.1.3'
52535
52573
  });
52536
52574
  // Configure Express
52537
52575
  this.configureExpress();
@@ -52576,7 +52614,7 @@ let McpService = class McpService {
52576
52614
  res.status(200).json({
52577
52615
  status: 'ok',
52578
52616
  server: 'Tabby MCP',
52579
- version: '1.1.2',
52617
+ version: '1.1.3',
52580
52618
  transport: 'StreamableHTTP + SSE',
52581
52619
  uptime: process.uptime()
52582
52620
  });
@@ -52585,7 +52623,7 @@ let McpService = class McpService {
52585
52623
  this.app.get('/info', (_, res) => {
52586
52624
  res.status(200).json({
52587
52625
  name: 'Tabby MCP',
52588
- version: '1.1.2',
52626
+ version: '1.1.3',
52589
52627
  protocolVersion: '2025-03-26',
52590
52628
  transports: ['streamable-http', 'sse'],
52591
52629
  endpoints: {