fix(MCPService): 增加获取系统 PATH 的功能, 修复 process.env.PATH 无法获取系统PATH的问题 (#4766)
This commit is contained in:
parent
e13a43d82a
commit
352731827c
@ -1,5 +1,6 @@
|
||||
import os from 'node:os'
|
||||
import path from 'node:path'
|
||||
import fs from 'node:fs'
|
||||
|
||||
import { isLinux, isMac, isWin } from '@main/constant'
|
||||
import { createInMemoryMCPServer } from '@main/mcpServers/factory'
|
||||
@ -13,7 +14,7 @@ import { nanoid } from '@reduxjs/toolkit'
|
||||
import { GetMCPPromptResponse, GetResourceResponse, MCPPrompt, MCPResource, MCPServer, MCPTool } from '@types'
|
||||
import { app } from 'electron'
|
||||
import Logger from 'electron-log'
|
||||
|
||||
import { memoize } from 'lodash'
|
||||
import { CacheService } from './CacheService'
|
||||
import { StreamableHTTPClientTransport, type StreamableHTTPClientTransportOptions } from './MCPStreamableHttpClient'
|
||||
|
||||
@ -184,7 +185,7 @@ class McpService {
|
||||
args,
|
||||
env: {
|
||||
...getDefaultEnvironment(),
|
||||
PATH: this.getEnhancedPath(process.env.PATH || ''),
|
||||
PATH: await this.getEnhancedPath(process.env.PATH || ''),
|
||||
...server.env
|
||||
},
|
||||
stderr: 'pipe'
|
||||
@ -470,13 +471,93 @@ class McpService {
|
||||
return await cachedGetResource(server, uri)
|
||||
}
|
||||
|
||||
private getSystemPath = memoize(async (): Promise<string> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
let command: string
|
||||
let shell: string
|
||||
|
||||
if (process.platform === 'win32') {
|
||||
shell = 'powershell.exe'
|
||||
command = '$env:PATH'
|
||||
} else {
|
||||
// 尝试获取当前用户的默认 shell
|
||||
|
||||
let userShell = process.env.SHELL
|
||||
if (!userShell) {
|
||||
if (fs.existsSync('/bin/zsh')) {
|
||||
userShell = '/bin/zsh'
|
||||
} else if (fs.existsSync('/bin/bash')) {
|
||||
userShell = '/bin/bash'
|
||||
} else if (fs.existsSync('/bin/fish')) {
|
||||
userShell = '/bin/fish'
|
||||
} else {
|
||||
userShell = '/bin/sh'
|
||||
}
|
||||
}
|
||||
shell = userShell
|
||||
|
||||
// 根据不同的 shell 构建不同的命令
|
||||
if (userShell.includes('zsh')) {
|
||||
shell = '/bin/zsh'
|
||||
command =
|
||||
'source /etc/zshenv 2>/dev/null || true; source ~/.zshenv 2>/dev/null || true; source /etc/zprofile 2>/dev/null || true; source ~/.zprofile 2>/dev/null || true; source /etc/zshrc 2>/dev/null || true; source ~/.zshrc 2>/dev/null || true; source /etc/zlogin 2>/dev/null || true; source ~/.zlogin 2>/dev/null || true; echo $PATH'
|
||||
} else if (userShell.includes('bash')) {
|
||||
shell = '/bin/bash'
|
||||
command =
|
||||
'source /etc/profile 2>/dev/null || true; source ~/.bash_profile 2>/dev/null || true; source ~/.bash_login 2>/dev/null || true; source ~/.profile 2>/dev/null || true; source ~/.bashrc 2>/dev/null || true; echo $PATH'
|
||||
} else if (userShell.includes('fish')) {
|
||||
shell = '/bin/fish'
|
||||
command =
|
||||
'source /etc/fish/config.fish 2>/dev/null || true; source ~/.config/fish/config.fish 2>/dev/null || true; source ~/.config/fish/config.local.fish 2>/dev/null || true; echo $PATH'
|
||||
} else {
|
||||
// 默认使用 zsh
|
||||
shell = '/bin/zsh'
|
||||
command =
|
||||
'source /etc/zshenv 2>/dev/null || true; source ~/.zshenv 2>/dev/null || true; source /etc/zprofile 2>/dev/null || true; source ~/.zprofile 2>/dev/null || true; source /etc/zshrc 2>/dev/null || true; source ~/.zshrc 2>/dev/null || true; source /etc/zlogin 2>/dev/null || true; source ~/.zlogin 2>/dev/null || true; echo $PATH'
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`Using shell: ${shell} with command: ${command}`)
|
||||
const child = require('child_process').spawn(shell, ['-c', command], {
|
||||
env: { ...process.env },
|
||||
cwd: app.getPath('home')
|
||||
})
|
||||
|
||||
let path = ''
|
||||
child.stdout.on('data', (data) => {
|
||||
path += data.toString()
|
||||
})
|
||||
|
||||
child.stderr.on('data', (data) => {
|
||||
console.error('Error getting PATH:', data.toString())
|
||||
})
|
||||
|
||||
child.on('close', (code) => {
|
||||
if (code === 0) {
|
||||
const trimmedPath = path.trim()
|
||||
resolve(trimmedPath)
|
||||
} else {
|
||||
reject(new Error(`Failed to get system PATH, exit code: ${code}`))
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
/**
|
||||
* Get enhanced PATH including common tool locations
|
||||
*/
|
||||
private getEnhancedPath(originalPath: string): string {
|
||||
private async getEnhancedPath(originalPath: string): Promise<string> {
|
||||
let systemPath = ''
|
||||
try {
|
||||
systemPath = await this.getSystemPath()
|
||||
} catch (error) {
|
||||
Logger.error('[MCP] Failed to get system PATH:', error)
|
||||
}
|
||||
// 将原始 PATH 按分隔符分割成数组
|
||||
const pathSeparator = process.platform === 'win32' ? ';' : ':'
|
||||
const existingPaths = new Set(originalPath.split(pathSeparator).filter(Boolean))
|
||||
const existingPaths = new Set(
|
||||
[...systemPath.split(pathSeparator), ...originalPath.split(pathSeparator)].filter(Boolean)
|
||||
)
|
||||
const homeDir = process.env.HOME || process.env.USERPROFILE || ''
|
||||
|
||||
// 定义要添加的新路径
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user