MCP 서버 PATH 문제 완전 해결 가이드#
“spawn uvx ENOENT” 에러를 중심으로#
📋 목차#
- 문제 상황과 증상
- 근본 원인 분석
- 즉시 해결 방법
- 플랫폼별 특성
- 개발자를 위한 예방책
- 테스트 및 검증
- 빠른 해결 체크리스트
문제 상황과 증상#
🔥 실제 에러 로그#
1
2
| 2025-07-14T01:02:03.249Z [MCP-timeserver] [error] spawn uvx ENOENT
{"context":"connection","stack":"Error: spawn uvx ENOENT\n at ChildProcess._handle.onexit (node:internal/child_process:285:19)"}
|
🤔 이상한 점들#
- ✅ 터미널에서
uvx --version
정상 작동 - ✅
which uvx
결과: /Users/username/.local/bin/uvx
- ❌ Claude Desktop에서만 “uvx를 찾을 수 없음” 에러
- ✅ 같은 설정에서
npx
, sh
는 정상 작동
근본 원인 분석#
🎯 핵심 문제: GUI vs Shell 환경의 PATH 차이#
Interactive Shell 환경 (터미널)#
1
2
3
4
5
6
7
| # 터미널 시작 시 실행되는 설정 파일들
~/.zshrc → export PATH="/Users/username/.local/bin:$PATH"
~/.bash_profile → export PATH="/Users/username/.local/bin:$PATH"
# 결과 PATH
echo $PATH
# /Users/username/.local/bin:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin
|
GUI Application 환경 (Claude Desktop)#
1
2
3
4
5
| # GUI 앱이 보는 기본 PATH (macOS launchd로부터 상속)
/usr/bin:/bin:/usr/sbin:/sbin
# 사용자 커스텀 경로는 포함되지 않음!
# ~/.local/bin, /opt/homebrew/bin 등이 누락
|
📊 명령어별 위치 비교#
명령어 | 일반적인 설치 위치 | GUI 환경 접근 가능 |
---|
sh | /bin/sh | ✅ |
npx | /usr/local/bin/npx | ✅ |
uvx | ~/.local/bin/uvx | ❌ |
cargo | ~/.cargo/bin/cargo | ❌ |
즉시 해결 방법#
🚀 방법 1: env 섹션에 PATH 명시 (권장)#
claude_desktop_config.json 수정:
1
2
3
4
5
6
7
8
9
10
11
| {
"mcpServers": {
"my-server": {
"command": "uvx",
"args": ["my-mcp-server"],
"env": {
"PATH": "/Users/username/.local/bin:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin"
}
}
}
}
|
장점:
- ✅ 프로젝트별 독립적 설정
- ✅ 다른 시스템으로 이식 시 명확한 의존성
- ✅ 다른 앱에 영향 없음
🛡️ 방법 2: 절대 경로 사용#
1
2
3
4
5
6
7
8
| {
"mcpServers": {
"my-server": {
"command": "/Users/username/.local/bin/uvx",
"args": ["my-mcp-server"]
}
}
}
|
장점:
✅ 즉시 해결
✅ 환경 변수 설정 불필요
단점:
❌ 하드코딩된 경로
❌ 다른 시스템에서 경로가 다를 수 있음
⚙️ 방법 3: 시스템 레벨 PATH 설정#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
| # 1. 현재 세션에 적용
launchctl setenv PATH "/Users/username/.local/bin:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin"
# 2. 영구 설정 (plist 파일 생성)
cat > ~/Library/LaunchAgents/setenv.PATH.plist << 'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>setenv.PATH</string>
<key>ProgramArguments</key>
<array>
<string>/bin/launchctl</string>
<string>setenv</string>
<string>PATH</string>
<string>/Users/username/.local/bin:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin</string>
</array>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>
EOF
# 3. plist 로드
launchctl load ~/Library/LaunchAgents/setenv.PATH.plist
# 4. 확인
launchctl getenv PATH
|
플랫폼별 특성#
🍎 macOS#
- 문제: GUI 앱이 셸 설정 파일을 읽지 않음
- 해결:
launchctl
또는 개별 앱 설정에서 PATH 지정 - 테스트:
launchctl getenv PATH
로 GUI 환경 PATH 확인
🪟 Windows#
- 문제: PowerShell 세션 vs GUI 앱의 환경 변수 차이
- 해결: 시스템 환경 변수에서 Path 수정 (영구적)
- 주의: 환경 변수 변경 후 앱 재시작 필요
1
2
3
4
5
| :: Windows에서 사용자 Path 확인
echo %PATH%
:: 시스템 환경 변수 GUI로 설정
:: Win + R → sysdm.cpl → 환경 변수 → 사용자 변수의 Path 편집
|
🐳 Docker#
- 해결책: Dockerfile에서 ENV로 명시적 설정
1
2
3
4
5
6
7
8
9
10
| FROM python:3.10-slim
# 커스텀 도구 설치
COPY --from=builder /path/to/uvx /usr/local/bin/uvx
RUN chmod +x /usr/local/bin/uvx
# PATH 명시적 설정 (권장)
ENV PATH="/usr/local/bin:${PATH}"
CMD ["python", "mcp_server.py"]
|
개발자를 위한 예방책#
🏗️ 1. 의존성 번들링 (최고의 해결책)#
1
2
3
4
5
6
| // Electron 앱 예시: 앱 패키지에 바이너리 포함
const path = require('path');
const { spawn } = require('child_process');
const uvxPath = path.join(__dirname, '..', 'bin', process.platform, 'uvx');
const child = spawn(uvxPath, ['my-server']);
|
⚙️ 2. 설정에서 실행 파일 경로 지정#
1
2
3
4
5
6
7
8
9
| {
"mcpServers": {
"my-server": {
"executablePath": "/Users/username/.local/bin/uvx",
"args": ["my-server"],
"env": {...}
}
}
}
|
📝 3. 명확한 오류 메시지 (즉시 적용 가능)#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| // 기존: 모호한 에러
// Error: spawn uvx ENOENT
// 개선: 구체적인 안내
const errorMessage = `
❌ 'uvx' 실행 파일을 찾을 수 없습니다.
해결 방법:
1. MCP 설정에서 env.PATH에 uvx 경로 추가:
"env": { "PATH": "/Users/username/.local/bin:$PATH" }
2. 또는 절대 경로 사용:
"command": "/Users/username/.local/bin/uvx"
3. uvx 설치 확인:
터미널에서 'which uvx' 실행 후 경로 확인
자세한 설정 방법: https://docs.example.com/path-setup
`;
|
🔍 4. 환경 진단 도구#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| // 개발자가 문제를 쉽게 진단할 수 있는 헬퍼
function diagnosePath() {
console.log('=== PATH 진단 ===');
console.log('Current PATH:', process.env.PATH);
console.log('PATH entries:', process.env.PATH.split(':'));
const commonPaths = [
'/usr/local/bin',
'/opt/homebrew/bin',
process.env.HOME + '/.local/bin',
process.env.HOME + '/.cargo/bin'
];
commonPaths.forEach(path => {
const exists = require('fs').existsSync(path);
const inPath = process.env.PATH.includes(path);
console.log(`${path}: exists=${exists}, inPath=${inPath}`);
});
}
|
테스트 및 검증#
🧪 CI/CD에서 환경 차이 테스트#
GitHub Actions 예시:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| name: MCP PATH Test
on: [push]
jobs:
test-path-handling:
runs-on: macos-latest
steps:
- uses: actions/checkout@v3
# uvx 설치
- name: Install uvx
run: pip install uvx
# 기본 PATH에서 테스트 (실패 예상)
- name: Test with minimal PATH
run: |
env -i PATH=/usr/bin:/bin node test-mcp.js
continue-on-error: true
# 수정된 설정으로 테스트 (성공 예상)
- name: Test with corrected config
run: node test-mcp.js --config config-with-path.json
|
🔬 로컬 환경 시뮬레이션#
1
2
3
4
5
| # GUI 환경과 유사한 최소 PATH로 테스트
env -i PATH=/usr/bin:/bin /bin/sh -c 'your-mcp-command'
# 또는 Docker로 깨끗한 환경 테스트
docker run --rm -v $(pwd):/app alpine:latest /bin/sh -c 'cd /app && your-test'
|
빠른 해결 체크리스트#
⚡ 즉시 확인사항#
[ ] 터미널에서 which uvx
실행 → 경로 확인
[ ] GUI 환경 PATH 확인: launchctl getenv PATH
[ ] MCP 설정에 env
섹션 있는지 확인
🛠️ 즉시 해결 (5분)#
[ ] MCP 설정에 env.PATH
추가
[ ] 또는 절대 경로로 command
변경
[ ] Claude Desktop 재시작
🏗️ 완전 해결 (30분)#
[ ] 시스템 레벨 PATH 설정 (plist 파일)
[ ] 다른 MCP 서버들도 동일 패턴 적용
[ ] 테스트 케이스 작성
👥 팀 공유용#
[ ] claude_desktop_config.json
예시 문서화
[ ] 환경 설정 가이드 작성
[ ] 공통 PATH 값들 표준화
🎯 핵심 포인트#
- GUI 앱은 터미널과 다른 PATH를 가진다
- MCP 설정의
**env**
섹션이 가장 안전한 해결책 - 절대 경로는 빠른 임시 해결책
- 시스템 레벨 설정은 모든 GUI 앱에 영향
이 가이드가 도움이 되었다면, 같은 문제로 고생하는 동료들과 공유해 주세요! 🚀
추가 리소스#