로컬 LLM 파이프라인에는 두 가지 활용 방식이 있다고 생각했다. 하나는 Aider가 터미널에서 로컬 모델로 자율 작업을 하는 방식, 다른 하나는 Claude Code 세션 안에서 필요할 때만 로컬 모델에 작업을 위임하는 MCP(Model Context Protocol) 서버 방식이다. 이 둘은 서로 배타적이지 않고 병행할 수 있어서, 일단 MCP 쪽도 붙여보기로 했다.
CONNECTION_CLOSED
claude mcp add local-llm -- npx -y mcp-local-llm
등록은 됐는데, claude mcp list로 확인하면 상태가 이렇다.
local-llm: npx -y mcp-local-llm - ✘ Failed to connect — CONNECTION_CLOSED
에러 메시지만으로는 원인을 알 수 없었다. npx가 내부적으로 어떤 명령을 실행하는지 직접 눈으로 확인해야 했다.
npx -y mcp-local-llm
이렇게 직접 실행해보니 진짜 원인이 드러났다.
Binary not found: .../mcp-local-llm-darwin-x64
mcp-local-llm이라는 이 npm 패키지는 언어 자체가 아니라 플랫폼별 사전 컴파일 바이너리를 배포하는 방식이었는데, darwin-arm64(Apple Silicon)·linux-x64·win-x64.exe만 빌드되어 있고 darwin-x64(Intel Mac)는 아예 없었다. Apple Silicon으로 넘어간 지 몇 년이 지난 시점이라 Intel Mac 대응이 후순위로 밀린 것으로 보인다.
소스를 직접 클론해서 빌드
배포된 바이너리를 쓸 수 없으니 소스를 직접 받아서 로컬에서 빌드하는 방법으로 우회했다. 다행히 이 프로젝트는 오픈소스였다.
git clone https://github.com/aplaceforallmystuff/mcp-local-llm.git ~/mcp-local-llm
cd ~/mcp-local-llm
npm install
npm run build
빌드가 끝나면 dist/index.js가 만들어지는데, 이걸 직접 실행 엔트리로 지정해서 다시 등록했다.
claude mcp add --scope user local-llm -- node ~/mcp-local-llm/dist/index.js
이번엔 정상 연결됐다.
local-llm: node ~/mcp-local-llm/dist/index.js - ✔ Connected
스코프도 한 번 잘못 잡았다
사실 처음 등록할 때는 --scope 옵션 없이 등록해서, 기본값인 local 스코프로 붙어버렸다. 문제는 이 스코프가 현재 작업 디렉터리(당시엔 홈 디렉터리 ~)를 “프로젝트"로 간주해서 묶인다는 점이다. 즉 이후에 다른 프로젝트 폴더로 이동하면 이 MCP 서버가 안 보이는 구조였다.
claude mcp remove local-llm
claude mcp add --scope user local-llm -- node ~/mcp-local-llm/dist/index.js
--scope user로 다시 등록하니 어느 디렉터리에서 Claude Code를 실행하든 이 MCP 서버가 보이게 됐다.
배운 것
npm 패키지 설치가 “성공"으로 표시돼도, 그게 실제로 내 아키텍처에서 동작한다는 보장은 아니다. 특히 이렇게 플랫폼별 바이너리를 배포하는 패키지는 npx 뒤에 숨어서 무슨 일이 벌어지는지 잘 안 보이니, 연결 실패 같은 애매한 에러를 만나면 패키지를 직접 실행해서 실제 에러 메시지를 확인하는 게 가장 빠른 진단법이었다.
이제 설치는 다 끝났다. 다음 글부터가 진짜 본론이다 — 실제로 4개의 로컬 코딩 모델에게 똑같은 작업을 시켜보고, 속도와 정확도를 실측한 결과를 공유한다.


💬 댓글