AI 코딩 도구를 쓰다 보면 한 가지 답답한 순간이 온다. “이 파일 읽어줘”라고 했는데 못 읽고, “DB에서 이 테이블 구조 확인해봐”라고 했는데 접근 권한이 없다고 하는 그 순간이다. Claude나 GPT가 아무리 똑똑해도, 내 로컬 환경에 있는 파일이나 데이터베이스에 직접 접근할 수 없으면 결국 내가 복사-붙여넣기를 해줘야 한다.
이 문제를 해결하기 위해 Anthropic에서 공개한 프로토콜이 MCP(Model Context Protocol)이다. MCP 서버를 로컬에 띄우면, AI Agent가 파일시스템을 읽고, GitHub 이슈를 만들고, 데이터베이스를 조회하는 것까지 직접 할 수 있게 된다. 이 글에서는 MacBook M1 환경에서 MCP 서버를 설치하고 Claude Code, Cursor에 연결하는 과정을 처음부터 끝까지 정리한다.
목차
MCP가 뭔지, 왜 필요한지
MCP는 Model Context Protocol의 약자로, AI 모델과 외부 도구 사이의 통신 규격이다. Anthropic이 2024년 말에 오픈소스로 공개했고, 현재 Claude Code, Cursor, Windsurf, Zed 등 주요 AI 코딩 도구들이 지원하고 있다. 관련 내용은 Mac Claude Code CLI 설치 가이드에서도 다루고 있다.
기존에는 AI 도구마다 플러그인 시스템이 제각각이었다. ChatGPT는 GPT Actions, Cursor는 자체 확장, VS Code는 Extension API… 개발자가 “파일시스템 접근 도구”를 만들려면 각 플랫폼별로 따로 구현해야 했다. MCP는 이걸 하나의 프로토콜로 통일한다.
구조를 간단히 설명하면 이렇다:
┌──────────────┐ stdio / SSE ┌──────────────────┐
│ AI Client │ ◄──────────────────► │ MCP Server │
│ (Claude Code │ JSON-RPC 2.0 │ (로컬 프로세스) │
│ / Cursor) │ │ │
└──────────────┘ └────────┬──────────┘
│
┌──────────┴──────────┐
│ 로컬 리소스 │
│ - 파일시스템 │
│ - GitHub API │
│ - 데이터베이스 │
│ - 커스텀 도구 │
└─────────────────────┘
MCP 서버는 로컬에서 돌아가는 경량 프로세스이다. AI 클라이언트가 JSON-RPC 2.0 프로토콜로 요청을 보내면, MCP 서버가 로컬 리소스에 접근해서 결과를 돌려준다. 통신 방식은 stdio(표준 입출력)와 SSE(Server-Sent Events) 두 가지가 있는데, 로컬 사용에서는 stdio가 기본이고 가장 안정적이다.
왜 이게 필요하냐면, AI가 “컨텍스트”를 직접 가져올 수 있게 되기 때문이다. 프로젝트 파일 구조를 보여달라고 할 때 내가 tree 결과를 복사해서 넣어줄 필요 없이, AI가 MCP 서버를 통해 직접 디렉터리를 읽는다. DB 스키마를 물어볼 때도 마찬가지다. 이 차이가 체감상 엄청 크다.
사전 준비 — Node.js와 npx 확인

MCP 공식 서버들은 대부분 npm 패키지로 배포된다. npx로 실행하기 때문에 Node.js가 설치되어 있어야 한다.
# Node.js 버전 확인 (18 이상 권장)
$ node -v
v22.12.0
# npx 확인
$ npx --version
10.9.0
# Node.js가 없다면 nvm으로 설치
$ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
$ source ~/.zshrc
$ nvm install --lts
# Python 기반 MCP 서버도 있으므로 uvx도 확인
$ pip install uv
$ uvx --version
uv 0.5.11
MacBook M1 32GB 환경에서 MCP 서버 3~4개를 동시에 띄워도 메모리 부담은 거의 없다. 서버 하나당 20~50MB 정도 사용하니까.
파일시스템 MCP 서버 설정 및 활용
가장 먼저 연결해볼 MCP 서버는 파일시스템이다. @modelcontextprotocol/server-filesystem 패키지를 사용한다. 이 서버를 연결하면 AI가 지정된 디렉터리의 파일을 읽고, 쓰고, 검색하고, 디렉터리 구조를 파악할 수 있다.
# npx로 바로 실행 가능 (설치 불필요)
$ npx -y @modelcontextprotocol/server-filesystem /Users/kyunghunkim/workspace
# 실행하면 stdio 모드로 대기 상태에 들어갑니다
# 직접 실행할 일은 거의 없고, AI 클라이언트가 알아서 실행합니다
파일시스템 MCP 서버가 제공하는 도구(tools)는 다음과 같다:
read_file— 파일 내용 읽기write_file— 파일 내용 쓰기list_directory— 디렉터리 목록 조회search_files— 파일 내용 검색 (grep과 유사)get_file_info— 파일 메타데이터 (크기, 수정일 등)create_directory— 디렉터리 생성move_file— 파일/디렉터리 이동
중요한 건, 실행 시 인자로 넘긴 경로(/Users/kyunghunkim/workspace) 바깥의 파일에는 접근할 수 없다는 점이다. 보안을 위해 샌드박스 처리가 되어 있다. 작업 디렉터리를 여러 개 열고 싶으면 경로를 여러 개 넘기면 된다.
# 여러 디렉터리에 접근 허용
$ npx -y @modelcontextprotocol/server-filesystem \
/Users/kyunghunkim/workspace \
/Users/kyunghunkim/Documents/notes
Claude Code에서 MCP 서버 연결
Claude Code(CLI)에서 MCP 서버를 연결하는 방법은 claude mcp add 명령 한 줄이다. 2025년 기준으로 가장 깔끔하게 동작하는 클라이언트라고 느꼈다.
# 파일시스템 MCP 서버 추가
$ claude mcp add filesystem \
-s user \
-- npx -y @modelcontextprotocol/server-filesystem /Users/kyunghunkim/workspace
# 등록 확인
$ claude mcp list
filesystem: npx -y @modelcontextprotocol/server-filesystem /Users/kyunghunkim/workspace (user)
# GitHub MCP 서버 추가
$ claude mcp add github \
-s user \
-e GITHUB_PERSONAL_ACCESS_TOKEN=ghp_xxxxxxxxxxxx \
-- npx -y @modelcontextprotocol/server-github
# 특정 프로젝트에서만 사용할 서버 추가 (-s project)
$ claude mcp add project-db \
-s project \
-- npx -y @modelcontextprotocol/server-sqlite /Users/kyunghunkim/workspace/myapp/data.db
-s 옵션은 스코프를 지정한다. user는 모든 프로젝트에서 사용, project는 현재 프로젝트에서만 사용이다. 파일시스템이나 GitHub처럼 범용적인 서버는 user 스코프로, 프로젝트 전용 DB 같은 건 project 스코프로 등록하는 게 좋다.
등록 후 Claude Code를 시작하면, AI가 사용 가능한 MCP 도구들을 자동으로 인식한다. “workspace 폴더에서 package.json 파일을 찾아줘”라고 하면, MCP 서버를 통해 직접 디렉터리를 탐색한다.
# MCP 서버 삭제
$ claude mcp remove filesystem
# MCP 서버 설정 파일 직접 확인 (user 스코프)
$ cat ~/.claude.json
# 또는
$ cat ~/.config/claude/settings.json
-e 옵션으로 환경변수를 넘길 수 있는데, API 토큰처럼 민감한 값은 이 방식으로 전달한다. 설정 파일에 저장되므로 매번 입력할 필요가 없다.
Cursor에서 MCP 서버 연결
Cursor는 프로젝트 루트의 .cursor/mcp.json 파일로 MCP 서버를 설정한다. GUI에서도 설정할 수 있지만, JSON 파일을 직접 편집하는 게 더 빠르다.
// .cursor/mcp.json
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"/Users/kyunghunkim/workspace"
]
},
"github": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-github"
],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_xxxxxxxxxxxx"
}
},
"sqlite": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-sqlite",
"/Users/kyunghunkim/workspace/myapp/data.db"
]
}
}
}
파일을 저장하고 Cursor를 재시작(또는 Cmd+Shift+P에서 “Developer: Reload Window”)하면 MCP 서버가 연결된다. Cursor Settings > MCP 탭에서 각 서버의 연결 상태를 확인할 수 있다. 초록색 점이 보이면 정상 연결된 것이다.
글로벌 설정으로 등록하고 싶으면 ~/.cursor/mcp.json에 동일한 형식으로 작성하면 된다. 프로젝트별 설정이 글로벌 설정보다 우선한다.
한 가지 주의할 점은, Cursor에서 MCP 도구를 호출하려면 Agent 모드(Composer의 Agent)를 사용해야 한다는 것이다. 일반 Chat 모드에서는 MCP 도구가 호출되지 않는다. Composer에서 Agent 모드로 전환한 뒤 “이 프로젝트의 디렉터리 구조를 보여줘”라고 입력하면 MCP 서버를 통해 응답한다.
GitHub MCP 서버 연동
GitHub MCP 서버를 연결하면 AI가 리포지토리, 이슈, PR, 파일 내용 등을 직접 조회하고 조작할 수 있다. 개인적으로 파일시스템 다음으로 가장 많이 쓰는 MCP 서버이다.
Personal Access Token 생성
먼저 GitHub에서 토큰을 만들어야 한다. GitHub Settings > Developer settings > Personal access tokens > Fine-grained tokens에서 생성한다.
필요한 권한:
- Repository access: 접근할 리포지토리 선택 (또는 All repositories)
- Permissions: Contents(Read/Write), Issues(Read/Write), Pull requests(Read/Write), Metadata(Read)
# Claude Code에서 GitHub MCP 연결
$ claude mcp add github \
-s user \
-e GITHUB_PERSONAL_ACCESS_TOKEN=ghp_your_token_here \
-- npx -y @modelcontextprotocol/server-github
# 연결 후 Claude Code에서 사용 예시:
# "kyunghunkim/blog_autobot 리포지토리의 최근 이슈 목록 보여줘"
# "새 이슈 만들어줘: 제목은 'MCP 서버 설정 자동화', 레이블은 enhancement"
# "main 브랜치의 src/index.ts 내용 확인해줘"
GitHub MCP 서버가 제공하는 주요 도구들:
search_repositories— 리포지토리 검색get_file_contents— 파일 내용 조회create_issue/list_issues— 이슈 생성/조회create_pull_request— PR 생성push_files— 파일 푸시 (커밋 + 푸시를 한 번에)create_branch— 브랜치 생성
주의할 점은, GitHub MCP 서버는 GitHub API를 호출하는 것이지 로컬 git 리포지토리를 조작하는 게 아니다. 로컬 git 작업이 필요하면 파일시스템 MCP와 함께 사용해야 한다.
SQLite / PostgreSQL MCP 서버 연동
데이터베이스 MCP 서버를 연결하면 AI가 테이블 구조를 파악하고 쿼리를 직접 실행할 수 있다. “이 테이블의 스키마 보여줘”나 “최근 주문 10건 조회해줘” 같은 요청이 한 번에 처리된다.
SQLite MCP 서버
# SQLite MCP 서버 연결
$ claude mcp add sqlite \
-s project \
-- npx -y @modelcontextprotocol/server-sqlite /Users/kyunghunkim/workspace/myapp/data.db
# Cursor에서는 .cursor/mcp.json에 추가
# {
# "mcpServers": {
# "sqlite": {
# "command": "npx",
# "args": ["-y", "@modelcontextprotocol/server-sqlite", "/absolute/path/to/data.db"]
# }
# }
# }
SQLite MCP 서버가 제공하는 도구:
list_tables— 테이블 목록describe_table— 테이블 스키마 (컬럼, 타입, 인덱스)read_query— SELECT 쿼리 실행write_query— INSERT/UPDATE/DELETE 실행create_table— 테이블 생성
개발 중인 앱의 DB 스키마를 AI에게 직접 보여줄 수 있으니까, “이 테이블 구조에 맞는 API 엔드포인트 만들어줘”라고 하면 정확한 코드가 나온다. 복사-붙여넣기로 스키마를 전달하던 시절과는 완전히 다르다.
PostgreSQL MCP 서버
# PostgreSQL MCP 서버 연결
$ claude mcp add postgres \
-s project \
-e DATABASE_URL=postgresql://user:password@localhost:5432/mydb \
-- npx -y @modelcontextprotocol/server-postgres
# 또는 connection string을 인자로 전달
$ claude mcp add postgres \
-s project \
-- npx -y @modelcontextprotocol/server-postgres \
"postgresql://user:password@localhost:5432/mydb"
PostgreSQL MCP 서버는 읽기 전용으로 동작한다. SELECT 쿼리만 실행 가능하고, INSERT/UPDATE/DELETE는 지원하지 않는다. 프로덕션 DB에 연결할 때는 이게 오히려 안전하다. 스키마 확인과 데이터 조회 용도로 쓰기에 충분하다.
커스텀 MCP 서버 만들기 기초 (TypeScript)
공식 MCP 서버로 커버되지 않는 도구가 필요하면, 직접 만들 수 있다. 예를 들어, 회사 내부 API를 AI에게 노출하거나, 특정 CLI 도구를 래핑하는 경우이다. TypeScript SDK를 사용하면 생각보다 간단하다.
# 프로젝트 초기화
$ mkdir my-mcp-server && cd my-mcp-server
$ npm init -y
$ npm install @modelcontextprotocol/sdk zod
$ npm install -D typescript @types/node
// src/index.ts
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
const server = new McpServer({
name: "my-custom-tools",
version: "1.0.0",
});
// 도구 1: 현재 시간을 특정 타임존으로 반환
server.tool(
"get_time",
"지정된 타임존의 현재 시간을 반환합니다",
{
timezone: z.string().default("Asia/Seoul").describe("IANA 타임존 이름"),
},
async ({ timezone }) => {
const now = new Date().toLocaleString("ko-KR", { timeZone: timezone });
return {
content: [{ type: "text", text: `현재 시간 (${timezone}): ${now}` }],
};
}
);
// 도구 2: 시스템 정보 조회
server.tool(
"system_info",
"현재 시스템의 OS, 메모리, CPU 정보를 반환합니다",
{},
async () => {
const os = await import("os");
const info = {
platform: os.platform(),
arch: os.arch(),
totalMemory: `${(os.totalmem() / 1024 / 1024 / 1024).toFixed(1)}GB`,
freeMemory: `${(os.freemem() / 1024 / 1024 / 1024).toFixed(1)}GB`,
cpus: os.cpus().length,
hostname: os.hostname(),
};
return {
content: [{ type: "text", text: JSON.stringify(info, null, 2) }],
};
}
);
// 도구 3: HTTP 요청 (내부 API 프록시 등)
server.tool(
"http_request",
"지정된 URL로 HTTP GET 요청을 보내고 응답을 반환합니다",
{
url: z.string().url().describe("요청할 URL"),
headers: z.record(z.string()).optional().describe("요청 헤더"),
},
async ({ url, headers }) => {
const response = await fetch(url, { headers });
const text = await response.text();
return {
content: [{
type: "text",
text: `Status: ${response.status}\n\n${text.substring(0, 5000)}`,
}],
};
}
);
// stdio 트랜스포트로 서버 시작
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("Custom MCP server running on stdio");
// tsconfig.json
{
"compilerOptions": {
"target": "ES2022",
"module": "Node16",
"moduleResolution": "Node16",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true
},
"include": ["src/**/*"]
}
# 빌드 및 테스트
$ npx tsc
$ node dist/index.js
# stdio 모드로 실행되므로 바로 터미널로 돌아오지 않음
# Ctrl+C로 종료
# Claude Code에 등록
$ claude mcp add my-tools \
-s user \
-- node /Users/kyunghunkim/workspace/my-mcp-server/dist/index.js
# Cursor에서 사용하려면 .cursor/mcp.json에 추가
# {
# "mcpServers": {
# "my-tools": {
# "command": "node",
# "args": ["/Users/kyunghunkim/workspace/my-mcp-server/dist/index.js"]
# }
# }
# }
핵심은 server.tool()로 도구를 등록하고, StdioServerTransport으로 통신하는 것이다. Zod 스키마로 입력 파라미터를 정의하면, AI 클라이언트가 어떤 인자를 넘겨야 하는지 자동으로 파악한다. 리소스(resource)나 프롬프트(prompt)도 등록할 수 있지만, 도구만으로도 대부분의 사용 사례를 커버한다.
여러 MCP 서버 동시 사용 설정
실제로 작업할 때는 MCP 서버를 하나만 쓰지 않는다. 파일시스템 + GitHub + DB를 동시에 연결하면, AI가 “코드 파일을 읽고, 관련 이슈를 확인하고, DB 스키마를 참고해서 PR을 생성하는” 워크플로우를 한 번에 처리할 수 있다.
Claude Code에서 멀티 서버
# 서버를 하나씩 추가하면 됩니다
$ claude mcp add filesystem -s user -- npx -y @modelcontextprotocol/server-filesystem /Users/kyunghunkim/workspace
$ claude mcp add github -s user -e GITHUB_PERSONAL_ACCESS_TOKEN=ghp_xxx -- npx -y @modelcontextprotocol/server-github
$ claude mcp add sqlite -s project -- npx -y @modelcontextprotocol/server-sqlite ./data.db
# 전체 목록 확인
$ claude mcp list
filesystem: npx -y @modelcontextprotocol/server-filesystem /Users/kyunghunkim/workspace (user)
github: npx -y @modelcontextprotocol/server-github (user)
sqlite: npx -y @modelcontextprotocol/server-sqlite ./data.db (project)
Cursor에서 멀티 서버
// .cursor/mcp.json — 전체 설정 예시
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"/Users/kyunghunkim/workspace"
]
},
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_xxxxxxxxxxxx"
}
},
"sqlite": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-sqlite",
"/Users/kyunghunkim/workspace/myapp/data.db"
]
},
"my-tools": {
"command": "node",
"args": ["/Users/kyunghunkim/workspace/my-mcp-server/dist/index.js"]
}
}
}
각 MCP 서버는 독립된 프로세스로 실행된다. 하나가 죽어도 다른 서버에는 영향이 없다. MacBook M1 32GB 기준으로 5개 정도 동시에 띄워도 체감 성능 저하는 없었다. 다만 서버 개수가 많아질수록 AI 클라이언트의 초기 연결 시간이 조금 늘어나는 건 있다(서버당 1~2초 추가).
연결 안 될 때 디버깅 방법
MCP 서버 설정에서 가장 시간 잡아먹는 게 “왜 안 되지?” 상황이다. 내가 겪은 문제들과 해결법을 정리한다.
1. npx 경로 문제 (가장 흔함)
Claude Code나 Cursor가 MCP 서버를 실행할 때, 시스템 PATH에서 npx를 찾지 못하는 경우가 있다. 특히 nvm으로 Node.js를 관리하는 환경에서 자주 발생한다.
# npx의 절대 경로 확인
$ which npx
/Users/kyunghunkim/.nvm/versions/node/v22.12.0/bin/npx
# 절대 경로로 MCP 서버 등록
$ claude mcp add filesystem \
-s user \
-- /Users/kyunghunkim/.nvm/versions/node/v22.12.0/bin/npx \
-y @modelcontextprotocol/server-filesystem /Users/kyunghunkim/workspace
# Cursor에서도 마찬가지로 command에 절대 경로 사용
# "command": "/Users/kyunghunkim/.nvm/versions/node/v22.12.0/bin/npx"
2. 로그 확인하기
MCP 서버가 실행은 되는데 제대로 동작하지 않을 때, 로그를 확인해야 한다.
# Claude Code의 MCP 로그 확인
$ cat ~/.claude/logs/mcp*.log
# MCP 서버를 수동으로 실행해서 에러 확인
$ npx -y @modelcontextprotocol/server-filesystem /Users/kyunghunkim/workspace 2>&1
# stderr 출력을 통해 에러 메시지를 확인할 수 있습니다
# Cursor에서는 Output 패널 > MCP 채널 확인
# Cmd+Shift+U > 드롭다운에서 "MCP" 선택
3. stdio vs SSE 혼동
로컬 MCP 서버는 stdio 방식을 사용한다. 간혹 원격 MCP 서버 예제를 보고 SSE 설정을 따라하면 연결이 안 된다.
// 잘못된 설정 (SSE 방식 — 원격 서버용)
{
"mcpServers": {
"filesystem": {
"url": "http://localhost:3000/mcp"
}
}
}
// 올바른 설정 (stdio 방식 — 로컬 서버용)
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/dir"]
}
}
}
command + args가 있으면 stdio, url이 있으면 SSE이다. 로컬에서 실행하는 공식 MCP 서버들은 모두 stdio 방식이다.
4. 권한 문제
# macOS에서 파일시스템 MCP 서버가 특정 디렉터리를 못 읽을 때
# 터미널(또는 IDE)에 "Full Disk Access" 권한이 있는지 확인
# System Settings > Privacy & Security > Full Disk Access
# 또는 접근하려는 디렉터리의 권한 확인
$ ls -la /Users/kyunghunkim/workspace/
# drwxr-xr-x 30 kyunghunkim staff 960 4 5 14:00 .
5. 패키지 버전 캐시 문제
# npx 캐시가 꼬여서 이전 버전이 실행될 때
$ npx clear-npx-cache
# 또는
$ rm -rf ~/.npm/_npx
# 그래도 안 되면 글로벌 설치 후 직접 실행
$ npm install -g @modelcontextprotocol/server-filesystem
$ which mcp-server-filesystem
/Users/kyunghunkim/.nvm/versions/node/v22.12.0/bin/mcp-server-filesystem
# 글로벌 설치된 바이너리로 직접 등록
$ claude mcp add filesystem -s user -- mcp-server-filesystem /Users/kyunghunkim/workspace
디버깅 체크리스트 요약
| 증상 | 원인 | 해결 |
|---|---|---|
| MCP 서버가 아예 안 뜸 | npx 경로를 못 찾음 | npx 절대 경로 사용 |
| 서버는 뜨는데 도구 목록이 비어있음 | 패키지 버전 캐시 문제 | npx 캐시 삭제 후 재시도 |
| 파일 읽기 요청에 에러 | 경로가 허용 범위 밖 | 실행 시 인자로 넘긴 경로 확인 |
| GitHub 서버 401 에러 | 토큰 만료 또는 권한 부족 | 토큰 재발급, 권한 확인 |
| Cursor에서 MCP 도구가 안 보임 | Agent 모드가 아님 | Composer > Agent 모드로 전환 |
MCP 서버를 제대로 설정하고 나면, AI 코딩 도구의 활용 범위가 확실히 넓어진다. 단순히 코드를 생성하는 것을 넘어서, 프로젝트 컨텍스트를 AI가 직접 파악하고 행동까지 할 수 있게 되니까. 처음 설정할 때 30분 정도 투자하면, 이후 작업 효율이 체감될 정도로 올라간다. 특히 파일시스템과 GitHub MCP 서버 두 개만 연결해도 일상적인 개발 워크플로우가 한 단계 달라지니, 아직 안 해봤다면 오늘 한번 시도해보길 권한다.