부록 C. claude_desktop_config.json 전체 설정 예제 모음
부록 C. claude_desktop_config.json 전체 설정 예제 모음
MCP를 처음 붙일 때 가장 많은 시간을 잡아먹는 것은 서버 코드가 아니다. 대개는 claude_desktop_config.json 앞에서 보낸다. 쉼표 하나가 빠졌거나, 경로 하나가 상대 경로였거나, 앱을 다시 켜지 않았을 뿐인데도 도구가 조용히 사라진다. 그래서 이 부록은 설명서라기보다 복붙용 설정 레시피 모음집에 가깝게 만들었다.
우리 책의 메인 프로젝트인 PKM-MCP를 기준으로, 로컬 stdio 연결부터 원격 HTTP 연결, 환경 변수, 다중 서버 구성, 그리고 자주 틀리는 부분까지 한 번에 모아보자. 입문자에게는 시행착오를 줄여주는 지름길이고, 이미 익숙한 사람에게는 필요할 때 다시 펼쳐보는 치트시트가 될 것이다.

이 파일부터 찾자
Claude Desktop은 MCP 서버 설정을 운영체제별 설정 파일에서 읽는다.1
macOS:
~/Library/Application Support/Claude/claude_desktop_config.jsonWindows:
%APPDATA%Claudeclaude_desktop_config.jsonLinux:
~/.config/Claude/claude_desktop_config.json
가장 쉬운 방법은 Claude Desktop에서 Settings → Developer → Edit Config로 여는 것이다.1 파일이 없으면 새로 만들어도 된다.
설정에 들어가기 전에 네 가지만 먼저 기억하자.
이미
preferences같은 다른 최상위 키가 있으면 지우지 말고 같이 유지한다.JSON은 주석과 마지막 쉼표를 허용하지 않는다. 아주 작은 문법 오류가 전체 서버 목록을 조용히 망가뜨린다.
상대 경로보다 절대 경로가 안전하다. GUI 앱이 서버를 띄울 때 작업 디렉터리가 예상과 다를 수 있고, 셸 환경 변수도 일부만 전달되는 경우가 있다.2
설정을 바꾼 뒤에는 창만 닫지 말고 앱을 완전히 종료한 뒤 다시 실행해야 한다.3
그리고 한 가지 더. env에 넣은 값은 서버 프로세스에 주입되지만, 설정 파일 안에서는 평문이다. 즉, 편하다고 해서 토큰과 비밀번호가 들어간 실제 설정 파일을 팀 저장소에 올리면 안 된다.4
가장 작은 뼈대
가장 기본적인 형태는 이렇다.
{
"mcpServers": {}
}이미 다른 설정이 있다면 이런 식으로 함께 둘 수 있다.
{
"mcpServers": {},
"preferences": {
"menuBarEnabled": true
}
}핵심은 간단하다. mcpServers 아래에서 각 키가 서버 이름이 된다. filesystem, pkm, github, notes-prod처럼 짧고 분명한 이름을 쓰면 된다.
예제 1. 가장 쉬운 출발점: 로컬 Filesystem 서버
처음 설정이 살아 있는지 확인할 때는 Filesystem 서버가 가장 단순하다. API 키도 없고, 동작 여부도 바로 눈에 보인다.
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"/Users/you/Documents"
]
}
}
}이 설정은 Claude가 /Users/you/Documents 아래를 읽고 다루게 한다. 너무 넓은 범위를 한 번에 열어주지 말고, 정말 필요한 폴더만 지정하는 편이 좋다. AI에게 집 열쇠를 줄 때도 현관문 하나씩 주는 게 낫지, 아파트 마스터 키를 처음부터 주는 사람은 드물다.
Windows에서는 경로를 이렇게 쓴다.
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"C:\Users\you\Documents"
]
}
}
}Windows 경로의 역슬래시는 JSON 안에서 이스케이프가 필요하므로 \로 써야 한다. 이 부분은 초보자를 가장 자주 넘어뜨리는 바닥 매트 같은 함정이다.
예제 2. PKM-MCP를 로컬 stdio 서버로 붙이기
책의 1부 후반과 2부 초반에서 쓰는 로컬 개발용 PKM-MCP는 보통 이런 모양이 가장 실용적이다.
{
"mcpServers": {
"pkm": {
"command": "uv",
"args": [
"run",
"python",
"-m",
"pkm_mcp"
],
"env": {
"PKM_NOTES_DIR": "/Users/you/notes",
"PKM_DATA_DIR": "/Users/you/.pkm-mcp",
"LOG_LEVEL": "info"
}
}
}
}이 예제는 세 가지 장점이 있다. 첫째, command와 args가 깔끔해서 서버 실행 방식을 한눈에 파악할 수 있다. 둘째, 메모 폴더와 데이터 폴더를 코드에 박아 넣지 않고 env로 넘긴다. 셋째, 나중에 PKM-MCP가 read-only 서버에서 CRUD 서버로 커져도 설정 구조를 거의 그대로 유지할 수 있다.
uv 대신 python으로 직접 실행하는 형태도 흔하다.
{
"mcpServers": {
"pkm": {
"command": "python",
"args": [
"-m",
"pkm_mcp"
],
"env": {
"PKM_NOTES_DIR": "/Users/you/notes"
}
}
}
}여기서 중요한 점은 command를 짧게 쓰는 것이 항상 정답은 아니라는 것이다. 터미널에서는 npx, uv, python, docker가 잘 되는데 Claude Desktop에서는 안 될 때가 있다. 이럴 때는 실행 파일의 절대 경로를 넣는 편이 훨씬 덜 아프다.3
macOS나 Linux에서는 이런 식이다.
{
"mcpServers": {
"filesystem": {
"command": "/usr/local/bin/npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"/Users/you/Documents"
]
}
}
}Windows에서는 보통 이렇게 쓴다.
{
"mcpServers": {
"filesystem": {
"command": "C:\Program Files\nodejs\npx.cmd",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"C:\Users\you\Documents"
]
}
}
}즉, 터미널에서 잘 되는데 Claude Desktop에서만 안 되면 가장 먼저 which npx, where npx, which python, where python부터 떠올리면 된다.
예제 3. 환경 변수를 붙여서 실행하기
실전 서버는 대개 메모 폴더 하나만으로 끝나지 않는다. 데이터베이스 URL, 임베딩 API 키, 로그 레벨, 사용자별 동작 플래그가 필요해진다. 그럴 때는 env를 쓴다.1
{
"mcpServers": {
"pkm": {
"command": "uv",
"args": [
"run",
"python",
"-m",
"pkm_mcp"
],
"env": {
"PKM_NOTES_DIR": "/Users/you/notes",
"PKM_DB_URL": "sqlite:////Users/you/.pkm-mcp/pkm.db",
"OPENAI_API_KEY": "sk-REPLACE_ME",
"LOG_LEVEL": "debug"
}
}
}
}이 패턴의 장점은 명확하다. 서버 코드 안에 비밀값을 하드코딩하지 않아도 되고, 같은 서버라도 환경별로 다르게 띄우기 쉽다. 예를 들어 개발용 PKM-MCP는 LOG_LEVEL=debug, 배포 전 테스트는 LOG_LEVEL=info처럼 바꾸면 된다.
다만 기억할 점도 명확하다. env는 서버별로 붙는다. pkm 서버에 넣은 키가 다른 서버에 자동으로 전달되지는 않는다. 그리고 이 값들은 설정 파일 안에서는 평문이므로, 공유할 때는 실제 값 대신 자리표시자만 남긴 템플릿을 따로 만드는 것이 안전하다.4
예를 들어 팀에 배포할 템플릿은 이렇게 두는 편이 좋다.
{
"mcpServers": {
"pkm": {
"command": "uv",
"args": [
"run",
"python",
"-m",
"pkm_mcp"
],
"env": {
"PKM_NOTES_DIR": "/ABSOLUTE/PATH/TO/NOTES",
"OPENAI_API_KEY": "REPLACE_ME"
}
}
}
}예제 4. 원격 HTTP 서버 연결
3부 이후의 PKM-MCP는 더 이상 한 대의 노트북 안에만 머물지 않는다. OAuth를 붙이고, Cloudflare Workers에 배포하고, 팀이 같이 쓰는 원격 서버가 된다. 이런 경우에는 command 대신 url을 사용해 연결할 수 있다.5
{
"mcpServers": {
"pkm-remote": {
"url": "https://mcp.example.com/mcp",
"headers": {
"Authorization": "Bearer pkm_live_REPLACE_ME"
}
}
}
}이 형태는 배포된 PKM-MCP를 Claude Desktop에 붙일 때 특히 편하다. 로컬 Python 환경이나 Node 설치 상태와 상관없이, 올바른 URL과 헤더만 있으면 되기 때문이다.
다만 최근 Claude Desktop 버전과 플랜 조합에 따라 원격 서버는 Connectors UI나 별도 인증 흐름으로 붙이는 쪽이 더 권장되기도 한다. 그래도 수동 JSON 방식은 테스트, 사설 배포, 고정 토큰을 쓰는 내부 서버, 또는 연결 구조를 명시적으로 보고 싶은 상황에서 여전히 유용하다.53
예제 5. 원격 서버를 로컬 stdio처럼 붙이는 프록시
가끔은 원격 MCP 서버인데도 설정 파일에 url이 아니라 command가 들어간 예제를 보게 된다. 처음 보면 꽤 헷갈린다. "원격 서버라면서 왜 로컬 명령어를 실행하지?" 하는 느낌이 든다.
이때 자주 등장하는 패턴이 mcp-remote 같은 로컬 프록시다.7
{
"mcpServers": {
"context7-proxy": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"https://server.example.com/mcp"
]
}
}
}이 설정에서 Claude Desktop은 사실상 "stdio로 말할 수 있는 로컬 서버 하나"를 본다. 하지만 그 뒤에서는 프록시가 stdio 메시지를 HTTP 요청으로 바꿔서 진짜 원격 MCP 서버와 통신한다.7 즉, 겉모습은 로컬 서버인데 속은 번역기다.
이 패턴이 유용한 순간은 두 가지다. 하나는 어떤 서비스가 아예 이런 설치 방식을 공식으로 제공할 때다. 다른 하나는 클라이언트는 stdio를 기대하지만 실제 서버는 HTTP로만 열려 있을 때다.
예제 6. Docker로 실행하는 서버
모든 MCP 서버가 npx나 python으로만 실행되는 것은 아니다. 2026년 기준으로는 Docker 이미지로 배포되는 서버도 꽤 많다. 대표적인 예가 GitHub 서버다.3
{
"mcpServers": {
"github": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"-e",
"GITHUB_PERSONAL_ACCESS_TOKEN",
"ghcr.io/github/github-mcp-server"
],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_REPLACE_ME"
}
}
}
}이 예제는 두 가지를 보여준다. 하나는 Docker 기반 서버도 Claude Desktop이 문제없이 띄울 수 있다는 점이다. 다른 하나는 토큰을 args가 아니라 env로 넘기는 습관이 중요하다는 점이다. 커맨드라인 인자는 시스템 프로세스 목록에서 더 쉽게 노출될 수 있으니, 비밀값은 가능하면 env가 낫다.
예제 7. 여러 서버를 한 번에 연결하기
실전에서는 서버 하나만 쓰는 경우보다 둘 이상을 같이 쓰는 경우가 많다. 예를 들어 로컬 파일을 읽는 Filesystem, 개인 메모를 다루는 PKM-MCP, 원격 GitHub 서버를 한꺼번에 연결할 수 있다.1
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"/Users/you/projects",
"/Users/you/notes"
]
},
"pkm": {
"command": "uv",
"args": [
"run",
"python",
"-m",
"pkm_mcp"
],
"env": {
"PKM_NOTES_DIR": "/Users/you/notes",
"LOG_LEVEL": "info"
}
},
"github": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"-e",
"GITHUB_PERSONAL_ACCESS_TOKEN",
"ghcr.io/github/github-mcp-server"
],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_REPLACE_ME"
}
},
"pkm-remote": {
"url": "https://mcp.example.com/mcp",
"headers": {
"Authorization": "Bearer pkm_live_REPLACE_ME"
}
}
}
}여기서 중요한 것은 "많이 붙일수록 좋다"가 아니라 "필요한 것만 붙일수록 낫다"는 점이다. 서버가 많아지면 시작 시간도 길어지고, 모델이 어떤 도구를 고를지 판단해야 하는 표면도 넓어진다. 뷔페가 좋은 건 맞지만, 접시에 한꺼번에 서른 가지를 담으면 결국 맛을 잘 못 느낀다.
예제 8. 1부용, 3부용, 팀 배포용 PKM-MCP 추천 형태
PKM-MCP는 책이 진행될수록 모양이 달라진다. 그래서 단계별로 설정도 조금씩 달라지는 편이 자연스럽다.
1부 후반의 read-only 서버라면 가장 단순한 로컬 stdio 구성이 좋다.
{
"mcpServers": {
"pkm": {
"command": "uv",
"args": ["run", "python", "-m", "pkm_mcp"],
"env": {
"PKM_NOTES_DIR": "/Users/you/notes"
}
}
}
}3부의 OAuth·배포 단계를 지난 뒤라면 원격 HTTP 구성이 더 어울린다.
{
"mcpServers": {
"pkm": {
"url": "https://mcp.your-domain.com/mcp",
"headers": {
"Authorization": "Bearer pkm_live_REPLACE_ME"
}
}
}
}팀 단위로 쓴다면 읽기 서버와 쓰기 서버를 논리적으로 나누는 것도 괜찮다.
{
"mcpServers": {
"pkm-read": {
"url": "https://mcp.your-domain.com/read",
"headers": {
"Authorization": "Bearer pkm_read_REPLACE_ME"
}
},
"pkm-write": {
"url": "https://mcp.your-domain.com/write",
"headers": {
"Authorization": "Bearer pkm_write_REPLACE_ME"
}
}
}
}이렇게 나누면 권한 최소화가 쉬워지고, 승인 경험도 더 분명해진다. "읽기만 허용할지, 수정도 허용할지"가 서버 이름만 봐도 드러나기 때문이다.
JSON 편집보다 쉬운 길도 있다
요즘의 Claude Desktop은 데스크톱 확장 패키지 흐름도 지원한다. 즉, 모든 사용자가 꼭 claude_desktop_config.json을 손으로 편집해야만 하는 것은 아니다.6 특히 비기술 사용자에게는 확장 패키지가 훨씬 친절하다.
하지만 이 부록이 굳이 JSON 예제를 길게 다루는 이유가 있다. 커스텀 서버, 로컬 개발 서버, 세밀한 args 조정, 서버별 env, 프록시 연결, 복수 서버 조합 같은 상황에서는 여전히 수동 설정이 가장 강력하기 때문이다. 간단히 말해, 원클릭 설치는 엘리베이터고 JSON 편집은 계단이다. 평소엔 엘리베이터가 편하지만, 구조를 바꾸고 싶을 때는 결국 계단으로 내려가야 한다.
또 한 가지 재미있는 차이도 있다. 데스크톱 확장에서는 민감한 설정 필드를 운영체제의 보안 저장소에 넣도록 설계할 수 있지만, JSON 파일은 그런 보호막이 없다.6 그래서 로컬 개발에는 JSON이 편하고, 배포나 배포형 배포물에는 확장 패키지가 더 어울릴 때가 있다.
가장 많이 하는 실수
처음 세팅할 때 정말 자주 나오는 실수는 대체로 정해져 있다.
파일 위치가 틀린다. 홈 디렉터리나 프로젝트 폴더에
claude_desktop_config.json을 만들면 Claude Desktop은 못 본다.JSON에 주석을 넣는다.
//한 줄이 전체 서버를 무력화한다.마지막 쉼표를 남긴다. 사람은 넘어가지만 JSON 파서는 안 넘어간다.
상대 경로를 쓴다.
./server.py,./notes는 잘 될 때도 있지만, 안 될 때 더 괴롭다.2앱을 완전히 종료하지 않는다. 창만 닫아서는 설정이 다시 읽히지 않는 경우가 많다.3
npx,python,docker가 Claude Desktop의 PATH에서 안 잡힌다. 이때는 절대 경로로 바꾸면 해결되는 경우가 많다.3비밀값을
args에 넣는다. 보안도 안 좋고, 나중에 관리도 어렵다.4기존
preferences를 지워버린다. MCP 서버만 넣겠다고 하다가 원래 있던 앱 설정까지 날려버릴 수 있다.
이 목록을 보면 별로 고급 기술 같지 않다. 맞다. 실제로 설정 문제의 대부분은 거대한 분산 시스템 이슈가 아니라, 아주 소박한 인간형 실수에서 시작한다.
막히면 이렇게 보면 가장 빠르다
문제가 생겼을 때는 감으로 추측하기보다, 아래 순서대로 보는 편이 훨씬 빠르다.2
JSON 문법부터 확인한다. JSON validator나 에디터의 문법 검사를 켜 두면 좋다.
터미널에서 같은 명령을 직접 실행해 본다. Claude Desktop 문제인지, 서버 자체 문제인지 바로 갈린다.
로그를 본다. Claude Desktop은 서버 연결과 런타임 로그를 따로 남긴다.2
MCP Inspector로 단독 테스트한다. Inspector에서는 되는데 Claude Desktop에서만 안 되면 설정 또는 호스트 쪽 문제일 가능성이 높다.2
정말 그 도구가 필요한 질문을 한다. 도구가 연결되어 있어도, 모델이 굳이 필요 없다고 판단하면 호출하지 않을 수 있다.
로그 위치는 보통 다음과 같다.2
macOS:
~/Library/Logs/ClaudeWindows:
%APPDATA%Claudelogs
특히 mcp.log와 mcp-server-서버이름.log를 같이 보면 도움이 된다. 전자는 연결과 설정 문제를, 후자는 서버 stderr를 보는 느낌이라고 생각하면 된다.
마지막 체크리스트
설정을 저장하고 나서 확인할 것은 의외로 단순하다.
Claude Desktop을 완전히 종료했다가 다시 켰는가
하단의 도구 영역이나 커넥터 영역에 서버가 보이는가
첫 질문을 도구가 꼭 필요한 형태로 던졌는가
서버가 필요한 토큰과 경로를 모두 받았는가
문제가 나면 바로 로그를 열 준비가 되어 있는가
여기까지 통과하면, 적어도 "설정 파일 때문에 하루를 날리는 일"은 크게 줄어든다.
마무리
좋은 설정 파일은 화려하지 않다. 오히려 짧고, 분명하고, 위험한 값을 밖으로 빼고, 필요한 서버만 담는다. 그런 설정이 가장 오래 버틴다.
특히 PKM-MCP처럼 책 전체를 관통하는 프로젝트는 단계마다 연결 방식이 달라진다. 1부에서는 로컬 stdio가 가장 빠르고, 3부 이후에는 원격 HTTP가 더 자연스럽고, 팀 단위 운영에서는 읽기와 쓰기를 분리한 구성이 빛난다. 그러니 정답 하나를 외우기보다, 상황에 맞는 설정 패턴 몇 개를 손에 익히는 것이 훨씬 중요하다.
이 부록의 예제들은 바로 그 패턴 모음이다. 필요할 때 다시 꺼내서, 복붙하고, 경로와 토큰만 바꿔 쓰면 된다. 설정 파일이 얌전하면, 그다음부터는 진짜 재미있는 일만 남는다. MCP 서버를 써먹는 일 말이다.
참고
1How to Set Up MCP Servers in Claude Desktop
2Debugging - Model Context Protocol
3How to Set Up MCP in Claude Desktop (Complete 2026 Guide)
4How to configure environment variables for MCP servers
5How to connect MCP servers to Claude Desktop
이 노트는 보도·비평·교육·연구 목적으로 작성되었습니다. 저작권 문의가 있으시면 에서 알려주세요.