Skip to content

Commit 914a49b

Browse files
author
Lasim
committed
refactor(gateway): replace legacy MCP config methods with new gateway endpoint
1 parent 06dfff3 commit 914a49b

File tree

3 files changed

+36
-130
lines changed

3 files changed

+36
-130
lines changed

services/gateway/src/core/auth/api-client.ts

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
/* eslint-disable @typescript-eslint/no-explicit-any */
22
import fetch from 'node-fetch';
33
import { StoredCredentials, UserInfo, TokenInfo, Team, AuthError, AuthenticationError } from '../../types/auth';
4-
import { MCPInstallationsResponse } from '../../types/mcp';
54
import { buildAuthConfig } from '../../utils/auth-config';
65
import { Device, DeviceInfo } from '../../utils/device-detection';
76

@@ -76,29 +75,6 @@ export class DeployStackAPI {
7675
return (response as { team: Team }).team;
7776
}
7877

79-
/**
80-
* Get MCP installations for a team
81-
* @param teamId Team ID
82-
* @returns MCP installations response
83-
*/
84-
async getTeamMCPInstallations(teamId: string): Promise<MCPInstallationsResponse> {
85-
const endpoint = `${this.baseUrl}/api/teams/${teamId}/mcp/installations`;
86-
const response = await this.makeRequest(endpoint);
87-
return response as MCPInstallationsResponse;
88-
}
89-
90-
/**
91-
* Get user configurations for an MCP installation
92-
* @param teamId Team ID
93-
* @param installationId Installation ID
94-
* @returns User configurations response
95-
*/
96-
async getUserConfigurations(teamId: string, installationId: string): Promise<any> {
97-
const endpoint = `${this.baseUrl}/api/teams/${teamId}/mcp/installations/${installationId}/user-configs`;
98-
const response = await this.makeRequest(endpoint);
99-
return response;
100-
}
101-
10278
/**
10379
* Get merged MCP configurations for gateway (NEW THREE-TIER ENDPOINT)
10480
* This endpoint merges Template + Team + User configurations and returns ready-to-use server configs

services/gateway/src/core/mcp/config-service.ts

Lines changed: 19 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import chalk from 'chalk';
22
import ora from 'ora';
33
import { DeployStackAPI } from '../auth/api-client';
44
import { CredentialStorage } from '../auth/storage';
5-
import { processMCPInstallations, filterValidInstallations } from './config-processor';
65
import { TeamMCPConfig } from '../../types/mcp';
76
import { AuthenticationError, AuthError } from '../../types/auth';
87

@@ -97,106 +96,7 @@ export class MCPConfigService {
9796
}
9897

9998
/**
100-
* Download and store MCP configuration for a team (LEGACY METHOD)
101-
* @param teamId Team ID
102-
* @param teamName Team name (optional, will be set from API if not provided)
103-
* @param api DeployStack API client
104-
* @param showSpinner Whether to show progress spinner
105-
* @returns Downloaded MCP configuration
106-
*/
107-
async downloadAndStoreMCPConfig(
108-
teamId: string,
109-
teamName?: string,
110-
api?: DeployStackAPI,
111-
showSpinner: boolean = true
112-
): Promise<TeamMCPConfig> {
113-
let spinner: ReturnType<typeof ora> | null = null;
114-
115-
try {
116-
if (showSpinner) {
117-
spinner = ora('Downloading MCP server configurations...').start();
118-
}
119-
120-
// Use provided API client or create one
121-
let apiClient = api;
122-
if (!apiClient) {
123-
const credentials = await this.storage.getCredentials();
124-
if (!credentials) {
125-
throw new AuthenticationError(
126-
AuthError.STORAGE_ERROR,
127-
'No authentication found - cannot download MCP config'
128-
);
129-
}
130-
apiClient = new DeployStackAPI(credentials, credentials.baseUrl);
131-
}
132-
133-
// Download MCP installations for the team
134-
const response = await apiClient.getTeamMCPInstallations(teamId);
135-
136-
if (!response.success) {
137-
throw new AuthenticationError(
138-
AuthError.NETWORK_ERROR,
139-
'Failed to download MCP installations from API'
140-
);
141-
}
142-
143-
const installations = response.data || [];
144-
145-
if (showSpinner && spinner) {
146-
spinner.text = `Downloading user configurations for ${installations.length} installation${installations.length === 1 ? '' : 's'}...`;
147-
}
148-
149-
// Download user configurations for each installation
150-
const allUserConfigurations = [];
151-
for (const installation of installations) {
152-
try {
153-
const userConfigResponse = await apiClient.getUserConfigurations(teamId, installation.id);
154-
if (userConfigResponse.success && userConfigResponse.data) {
155-
allUserConfigurations.push(...userConfigResponse.data);
156-
}
157-
} catch (error) {
158-
// Log warning but continue - user configs are optional
159-
console.log(chalk.yellow(`⚠️ Could not fetch user configurations for installation ${installation.installation_name}: ${error instanceof Error ? error.message : String(error)}`));
160-
}
161-
}
162-
163-
if (showSpinner && spinner) {
164-
spinner.text = `Processing ${installations.length} installation${installations.length === 1 ? '' : 's'} with ${allUserConfigurations.length} user configuration${allUserConfigurations.length === 1 ? '' : 's'}...`;
165-
}
166-
167-
// Filter and validate installations
168-
const validInstallations = filterValidInstallations(installations);
169-
170-
if (validInstallations.length < installations.length) {
171-
const invalidCount = installations.length - validInstallations.length;
172-
console.log(chalk.yellow(`⚠️ Skipped ${invalidCount} invalid installation${invalidCount === 1 ? '' : 's'}`));
173-
}
174-
175-
// Process installations into server configurations with three-tier architecture
176-
const config = processMCPInstallations(teamId, teamName || `Team ${teamId}`, validInstallations, allUserConfigurations);
177-
178-
if (showSpinner && spinner) {
179-
spinner.text = 'Storing MCP configuration securely...';
180-
}
181-
182-
// Store the configuration securely
183-
await this.storage.storeMCPConfig(config);
184-
185-
if (showSpinner && spinner) {
186-
spinner.succeed(`MCP configuration downloaded and stored (${config.servers.length} server${config.servers.length === 1 ? '' : 's'})`);
187-
}
188-
189-
return config;
190-
} catch (error) {
191-
if (spinner) {
192-
spinner.fail('Failed to download MCP configuration');
193-
}
194-
throw error;
195-
}
196-
}
197-
198-
/**
199-
* Switch team MCP configuration
99+
* Switch team MCP configuration using new gateway endpoint
200100
* Clears old config and downloads new config for the team
201101
* @param teamId New team ID
202102
* @param teamName New team name
@@ -214,8 +114,24 @@ export class MCPConfigService {
214114
await this.storage.clearMCPConfig(credentials.selectedTeam.id);
215115
}
216116

217-
// Download and store new configuration
218-
return await this.downloadAndStoreMCPConfig(teamId, teamName, api, true);
117+
// Detect device info for hardware_id
118+
const { detectDeviceInfo } = await import('../../utils/device-detection');
119+
const deviceInfo = await detectDeviceInfo();
120+
121+
// Download merged configuration using new gateway endpoint
122+
const gatewayConfig = await this.downloadGatewayMCPConfig(deviceInfo.hardware_id, api, true);
123+
124+
// Convert and store the gateway config in the format expected by local storage
125+
const teamMCPConfig = this.convertGatewayConfigToTeamConfig(
126+
teamId,
127+
teamName,
128+
gatewayConfig
129+
);
130+
131+
// Store the converted configuration
132+
await this.storeMCPConfig(teamMCPConfig);
133+
134+
return teamMCPConfig;
219135
}
220136

221137
/**

services/gateway/src/core/mcp/team-context-manager.ts

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -110,12 +110,26 @@ export class TeamContextManager extends EventEmitter {
110110
console.log(chalk.gray(' Downloading new team\'s MCP configuration...'));
111111
}
112112

113-
newTeamConfig = await this.mcpConfigService.downloadAndStoreMCPConfig(
114-
newTeamId,
115-
newTeamName,
113+
// Detect device info for hardware_id
114+
const { detectDeviceInfo } = await import('../../utils/device-detection');
115+
const deviceInfo = await detectDeviceInfo();
116+
117+
// Download merged configuration using new gateway endpoint
118+
const gatewayConfig = await this.mcpConfigService.downloadGatewayMCPConfig(
119+
deviceInfo.hardware_id,
116120
api,
117121
forceRefresh
118122
);
123+
124+
// Convert and store the gateway config in the format expected by local storage
125+
newTeamConfig = this.mcpConfigService.convertGatewayConfigToTeamConfig(
126+
newTeamId,
127+
newTeamName,
128+
gatewayConfig
129+
);
130+
131+
// Store the converted configuration
132+
await this.mcpConfigService.storeMCPConfig(newTeamConfig);
119133

120134
if (showProgress) {
121135
console.log(chalk.green(`✅ Downloaded configuration for ${newTeamConfig.servers.length} MCP server${newTeamConfig.servers.length === 1 ? '' : 's'}`));

0 commit comments

Comments
 (0)