feat: auto-configure DevStar MCP Server for Github Copilot and Trae #6

Merged
lat5211 merged 2 commits from feature/auto-configure-mcp into main 2026-01-09 12:18:33 +00:00

View File

@@ -372,6 +372,22 @@ export default class RemoteContainer {
} catch (portError) {
vscode.window.showWarningMessage('端口映射设置失败,但容器连接已建立');
}
// 自动配置本地 VSCode 的 MCP Server
try {
await this.configureMCPServerLocally();
} catch (mcpError) {
console.error('[MCP] 本地 MCP 配置失败:', mcpError);
// 不阻塞主流程,仅记录错误
}
// 自动配置容器内 AI IDE 的 MCP Server
try {
await this.configureMCPServerInContainer(sshConfig.hostname, port);
} catch (mcpError) {
console.error('[MCP] 容器内 MCP 配置失败:', mcpError);
// 不阻塞主流程,仅记录错误
}
}
// 使用 VSCode Extension API 打开远程连接
@@ -471,6 +487,232 @@ export default class RemoteContainer {
console.log('未找到 forwardPorts 参数,跳过端口映射设置。');
}
}
/**
* 在容器内配置 AI IDE 的 MCP Server
* 支持 Trae IDE 等 AI IDE 的 MCP 自动配置
*/
private async configureMCPServerInContainer(hostname: string, sshPort: number): Promise<void> {
// 获取用户 token
const userToken = this.user.getUserTokenFromLocal();
if (!userToken) {
console.log('[MCP] 用户未登录,跳过 MCP Server 配置');
return;
}
// 获取 DevStar 域名
const devstarDomain = this.user.getDevstarDomain();
const mcpUrl = `${devstarDomain}/api/mcp`;
console.log(`[MCP] 开始配置 MCP Server: ${mcpUrl}`);
// Trae IDE 的 MCP 配置路径
const traeMcpPath = '/root/.trae-server/data/Machine/mcp.json';
// MCP 配置内容(注意:使用 "mcpServers" 格式)
const mcpConfig = {
mcpServers: {
devstar: {
type: 'http',
url: mcpUrl,
headers: {
Authorization: `Bearer ${userToken}`
}
}
}
};
const configJson = JSON.stringify(mcpConfig, null, 2);
// 使用 SSH 连接到容器并配置
const ssh = new NodeSSH();
try {
await ssh.connect({
host: hostname,
username: 'root',
port: sshPort,
privateKeyPath: this.user.getUserPrivateKeyPath(),
readyTimeout: 10000,
});
console.log('[MCP] SSH 连接成功');
// 检查现有配置
const checkScript = `
if [ -f "${traeMcpPath}" ]; then
cat "${traeMcpPath}"
else
echo "FILE_NOT_EXISTS"
fi
`;
const checkResult = await ssh.execCommand(checkScript);
let needUpdate = true;
if (checkResult.stdout !== 'FILE_NOT_EXISTS') {
try {
const existingConfig = JSON.parse(checkResult.stdout);
const existingDevstar = existingConfig.mcpServers?.devstar;
if (existingDevstar) {
// 检查 URL 和 token 是否匹配
const urlMatch = existingDevstar.url === mcpUrl;
const tokenMatch = existingDevstar.headers?.Authorization === `Bearer ${userToken}`;
if (urlMatch && tokenMatch) {
console.log('[MCP] DevStar MCP 配置已存在且正确,无需更新');
needUpdate = false;
} else {
console.log(`[MCP] DevStar MCP 配置需要更新 (URL匹配: ${urlMatch}, Token匹配: ${tokenMatch})`);
}
}
} catch (parseError) {
console.log('[MCP] 解析现有配置失败,将创建新配置');
}
} else {
console.log('[MCP] 容器内无配置文件,需要创建');
}
// 创建或更新配置文件
if (needUpdate) {
const setupScript = `
mkdir -p /root/.trae-server/data/Machine && \
cat > ${traeMcpPath} << 'EOF'
${configJson}
EOF
echo "MCP 配置已更新"
`;
const result = await ssh.execCommand(setupScript);
if (result.code === 0) {
console.log('[MCP] DevStar MCP 配置成功');
} else {
console.error(`[MCP] 配置失败: ${result.stderr}`);
}
}
} catch (error) {
console.error('[MCP] SSH 连接或配置失败:', error);
throw error;
} finally {
try {
await ssh.dispose();
} catch (e) {
// ignore dispose error
}
}
}
/**
* 在本地 VSCode 中配置 MCP Server
* 支持 GitHub Copilot 等使用本地 MCP 配置
*/
private async configureMCPServerLocally(): Promise<void> {
// 获取用户 token
const userToken = this.user.getUserTokenFromLocal();
if (!userToken) {
console.log('[MCP] 用户未登录,跳过本地 MCP Server 配置');
return;
}
// 获取 DevStar 域名
const devstarDomain = this.user.getDevstarDomain();
const mcpUrl = `${devstarDomain}/api/mcp`;
console.log(`[MCP] 开始配置本地 MCP Server: ${mcpUrl}`);
// 根据操作系统确定配置文件路径
let mcpConfigPath: string;
const platform = os.platform();
const homedir = os.homedir();
if (platform === 'darwin') {
// macOS
mcpConfigPath = path.join(homedir, 'Library/Application Support/Code/User/mcp.json');
} else if (platform === 'win32') {
// Windows
mcpConfigPath = path.join(homedir, 'AppData/Roaming/Code/User/mcp.json');
} else {
// Linux
mcpConfigPath = path.join(homedir, '.config/Code/User/mcp.json');
}
console.log(`[MCP] 配置文件路径: ${mcpConfigPath}`);
// MCP 配置内容(本地 VSCode 使用 "servers" 格式)
const mcpConfig = {
servers: {
devstar: {
type: 'http',
url: mcpUrl,
headers: {
Authorization: `Bearer ${userToken}`
}
}
}
};
const configJson = JSON.stringify(mcpConfig, null, 2);
try {
// 检查现有配置
let existingConfig: any = {};
let needUpdate = true;
if (fs.existsSync(mcpConfigPath)) {
try {
const content = fs.readFileSync(mcpConfigPath, 'utf8');
existingConfig = JSON.parse(content);
const existingDevstar = existingConfig.servers?.devstar;
if (existingDevstar) {
// 检查 URL 和 token 是否匹配
const urlMatch = existingDevstar.url === mcpUrl;
const tokenMatch = existingDevstar.headers?.Authorization === `Bearer ${userToken}`;
if (urlMatch && tokenMatch) {
console.log('[MCP] 本地 DevStar MCP 配置已存在且正确,无需更新');
needUpdate = false;
} else {
console.log(`[MCP] 本地 DevStar MCP 配置需要更新 (URL匹配: ${urlMatch}, Token匹配: ${tokenMatch})`);
}
}
} catch (parseError) {
console.log('[MCP] 解析现有配置失败,将创建新配置');
}
} else {
console.log('[MCP] 本地无配置文件,需要创建');
}
// 创建或更新配置文件
if (needUpdate) {
// 确保目录存在
const configDir = path.dirname(mcpConfigPath);
if (!fs.existsSync(configDir)) {
fs.mkdirSync(configDir, { recursive: true });
}
// 合并现有配置(保留其他 MCP servers
const newConfig = {
...existingConfig,
servers: {
...existingConfig.servers,
...mcpConfig.servers
}
};
fs.writeFileSync(mcpConfigPath, JSON.stringify(newConfig, null, 2), 'utf8');
console.log('[MCP] 本地 DevStar MCP 配置成功');
}
} catch (error) {
console.error('[MCP] 本地 MCP 配置失败:', error);
throw error;
}
}
}
/**