GitHub MCP 서버
GitHub
GitHub MCP 서버는 GitHub API를 활용하여 파일 조작, 저장소 관리, 검색 기능 등을 제공하는 도구입니다.
목차
- 특징
- API
- 도구
- 검색 쿼리 구문
- 사용 방법
- 개인 액세스 토큰
- Claude Desktop에서 사용
- VS Code에서 사용
- 빌드
- 일반적인 문제 해결
- 사용 사례 예제
- 라이선스
- 연결된 구성 요소
- 참고 자료
특징
- 자동 브랜치 생성: 파일 생성/업데이트 또는 변경 사항 푸시 시 브랜치가 존재하지 않으면 자동으로 생성됩니다.
- 포괄적인 오류 처리: 일반적인 문제에 대한 명확한 오류 메시지를 제공합니다.
- Git 기록 보존: 강제 푸시 없이 적절한 Git 기록을 유지하는 작업을 수행합니다.
- 일괄 작업: 단일 파일 및 다중 파일 작업을 모두 지원합니다.
- 고급 검색: 코드, 이슈/PR 및 사용자 검색 기능을 지원합니다.
워크플로우 다이어그램
다음 다이어그램은 GitHub MCP 서버의 기본 워크플로우를 보여줍니다:
다이어그램: 사용자 요청이 Claude와 GitHub MCP 서버를 통해 GitHub API로 전달되고 결과가 반환되는 과정
API
도구
create_or_update_file
저장소에 단일 파일을 생성하거나 업데이트합니다.
- 입력:
owner(문자열): 저장소 소유자(사용자 이름 또는 조직)repo(문자열): 저장소 이름path(문자열): 파일을 생성/업데이트할 경로content(문자열): 파일 내용message(문자열): 커밋 메시지branch(문자열): 파일을 생성/업데이트할 브랜치-
sha(선택적 문자열): 교체할 파일의 SHA(업데이트 시) -
반환: 파일 내용 및 커밋 세부 정보
push_files
여러 파일을 단일 커밋으로 푸시합니다.
- 입력:
owner(문자열): 저장소 소유자repo(문자열): 저장소 이름branch(문자열): 푸시할 브랜치files(배열): 푸시할 파일, 각각path와content포함-
message(문자열): 커밋 메시지 -
반환: 업데이트된 브랜치 참조
search_repositories
GitHub 저장소 검색
- 입력:
query(문자열): 검색 쿼리page(선택적 숫자): 페이지 번호-
perPage(선택적 숫자): 페이지당 결과 수(최대 100) -
반환: 저장소 검색 결과
create_repository
새 GitHub 저장소 생성
- 입력:
name(문자열): 저장소 이름description(선택적 문자열): 저장소 설명private(선택적 불리언): 저장소가 비공개여야 하는지 여부-
autoInit(선택적 불리언): README로 초기화할지 여부 -
반환: 생성된 저장소 세부 정보
get_file_contents
파일 또는 디렉토리 내용 가져오기
- 입력:
owner(문자열): 저장소 소유자repo(문자열): 저장소 이름path(문자열): 파일/디렉토리 경로-
branch(선택적 문자열): 내용을 가져올 브랜치 -
반환: 파일/디렉토리 내용
create_issue
새 이슈 생성
- 입력:
owner(문자열): 저장소 소유자repo(문자열): 저장소 이름title(문자열): 이슈 제목body(선택적 문자열): 이슈 설명assignees(선택적 문자열[]): 할당할 사용자 이름labels(선택적 문자열[]): 추가할 레이블-
milestone(선택적 숫자): 마일스톤 번호 -
반환: 생성된 이슈 세부 정보
create_pull_request
새 PR(Pull Request) 생성
- 입력:
owner(문자열): 저장소 소유자repo(문자열): 저장소 이름title(문자열): PR 제목body(선택적 문자열): PR 설명head(문자열): 변경 사항이 포함된 브랜치base(문자열): 병합할 브랜치draft(선택적 불리언): 초안 PR로 생성할지 여부-
maintainer_can_modify(선택적 불리언): 관리자 편집 허용 여부 -
반환: 생성된 PR 세부 정보
fork_repository
저장소 포크
- 입력:
owner(문자열): 저장소 소유자repo(문자열): 저장소 이름-
organization(선택적 문자열): 포크할 조직 -
반환: 포크된 저장소 세부 정보
create_branch
새 브랜치 생성
- 입력:
owner(문자열): 저장소 소유자repo(문자열): 저장소 이름branch(문자열): 새 브랜치 이름-
from_branch(선택적 문자열): 소스 브랜치(기본값: 저장소 기본값) -
반환: 생성된 브랜치 참조
list_issues
저장소 이슈 목록 조회 및 필터링
- 입력:
owner(문자열): 저장소 소유자repo(문자열): 저장소 이름state(선택적 문자열): 상태별 필터링('open', 'closed', 'all')labels(선택적 문자열[]): 레이블별 필터링sort(선택적 문자열): 정렬 기준('created', 'updated', 'comments')direction(선택적 문자열): 정렬 방향('asc', 'desc')since(선택적 문자열): 날짜별 필터링(ISO 8601 타임스탬프)page(선택적 숫자): 페이지 번호-
per_page(선택적 숫자): 페이지당 결과 수 -
반환: 이슈 세부 정보 배열
update_issue
기존 이슈 업데이트
- 입력:
owner(문자열): 저장소 소유자repo(문자열): 저장소 이름issue_number(숫자): 업데이트할 이슈 번호title(선택적 문자열): 새 제목body(선택적 문자열): 새 설명state(선택적 문자열): 새 상태('open' 또는 'closed')labels(선택적 문자열[]): 새 레이블assignees(선택적 문자열[]): 새 할당자-
milestone(선택적 숫자): 새 마일스톤 번호 -
반환: 업데이트된 이슈 세부 정보
add_issue_comment
이슈에 댓글 추가
- 입력:
owner(문자열): 저장소 소유자repo(문자열): 저장소 이름issue_number(숫자): 댓글을 달 이슈 번호-
body(문자열): 댓글 텍스트 -
반환: 생성된 댓글 세부 정보
search_code
GitHub 저장소 전체에서 코드 검색
- 입력:
q(문자열): GitHub 코드 검색 구문을 사용한 검색 쿼리sort(선택적 문자열): 정렬 필드('indexed'만 해당)order(선택적 문자열): 정렬 순서('asc' 또는 'desc')per_page(선택적 숫자): 페이지당 결과 수(최대 100)-
page(선택적 숫자): 페이지 번호 -
반환: 저장소 컨텍스트가 포함된 코드 검색 결과
search_issues
이슈 및 PR 검색
- 입력:
q(문자열): GitHub 이슈 검색 구문을 사용한 검색 쿼리sort(선택적 문자열): 정렬 필드(comments, reactions, created 등)order(선택적 문자열): 정렬 순서('asc' 또는 'desc')per_page(선택적 숫자): 페이지당 결과 수(최대 100)-
page(선택적 숫자): 페이지 번호 -
반환: 이슈 및 PR 검색 결과
search_users
GitHub 사용자 검색
- 입력:
q(문자열): GitHub 사용자 검색 구문을 사용한 검색 쿼리sort(선택적 문자열): 정렬 필드(followers, repositories, joined)order(선택적 문자열): 정렬 순서('asc' 또는 'desc')per_page(선택적 숫자): 페이지당 결과 수(최대 100)-
page(선택적 숫자): 페이지 번호 -
반환: 사용자 검색 결과
list_commits
저장소의 브랜치 커밋 목록 가져오기
- 입력:
owner(문자열): 저장소 소유자repo(문자열): 저장소 이름page(선택적 문자열): 페이지 번호perPage(선택적 문자열): 페이지당 레코드 수-
sha(선택적 문자열): 브랜치 이름 -
반환: 커밋 목록
get_issue
저장소 내 이슈 내용 가져오기
- 입력:
owner(문자열): 저장소 소유자repo(문자열): 저장소 이름-
issue_number(숫자): 가져올 이슈 번호 -
반환: GitHub 이슈 객체 및 세부 정보
get_pull_request
특정 PR의 세부 정보 가져오기
- 입력:
owner(문자열): 저장소 소유자repo(문자열): 저장소 이름-
pull_number(숫자): PR 번호 -
반환: diff 및 검토 상태를 포함한 PR 세부 정보
list_pull_requests
저장소 PR 목록 조회 및 필터링
- 입력:
owner(문자열): 저장소 소유자repo(문자열): 저장소 이름state(선택적 문자열): 상태별 필터링('open', 'closed', 'all')head(선택적 문자열): 헤드 사용자/조직 및 브랜치로 필터링base(선택적 문자열): 기본 브랜치로 필터링sort(선택적 문자열): 정렬 기준('created', 'updated', 'popularity', 'long-running')direction(선택적 문자열): 정렬 방향('asc', 'desc')per_page(선택적 숫자): 페이지당 결과 수(최대 100)-
page(선택적 숫자): 페이지 번호 -
반환: PR 세부 정보 배열
create_pull_request_review
PR에 리뷰 생성
- 입력:
owner(문자열): 저장소 소유자repo(문자열): 저장소 이름pull_number(숫자): PR 번호body(문자열): 리뷰 댓글 텍스트event(문자열): 리뷰 작업('APPROVE', 'REQUEST_CHANGES', 'COMMENT')commit_id(선택적 문자열): 검토할 커밋의 SHA-
comments(선택적 배열): 라인별 댓글, 각각 다음 포함:path(문자열): 파일 경로position(숫자): diff에서 라인 위치body(문자열): 댓글 텍스트
-
반환: 생성된 리뷰 세부 정보
merge_pull_request
PR 병합
- 입력:
owner(문자열): 저장소 소유자repo(문자열): 저장소 이름pull_number(숫자): PR 번호commit_title(선택적 문자열): 병합 커밋 제목commit_message(선택적 문자열): 병합 커밋 추가 세부 정보-
merge_method(선택적 문자열): 병합 방법('merge', 'squash', 'rebase') -
반환: 병합 결과 세부 정보
get_pull_request_files
PR에서 변경된 파일 목록 가져오기
- 입력:
owner(문자열): 저장소 소유자repo(문자열): 저장소 이름-
pull_number(숫자): PR 번호 -
반환: 패치 및 상태 세부 정보가 포함된 변경된 파일 배열
get_pull_request_status
PR에 대한 모든 상태 확인의 통합 상태 가져오기
- 입력:
owner(문자열): 저장소 소유자repo(문자열): 저장소 이름-
pull_number(숫자): PR 번호 -
반환: 통합 상태 확인 결과 및 개별 확인 세부 정보
update_pull_request_branch
PR 브랜치를 기본 브랜치의 최신 변경 사항으로 업데이트(GitHub의 "브랜치 업데이트" 버튼과 동일)
- 입력:
owner(문자열): 저장소 소유자repo(문자열): 저장소 이름pull_number(숫자): PR 번호-
expected_head_sha(선택적 문자열): PR의 HEAD 참조의 예상 SHA -
반환: 브랜치가 업데이트되면 성공 메시지
get_pull_request_comments
PR의 리뷰 댓글 가져오기
- 입력:
owner(문자열): 저장소 소유자repo(문자열): 저장소 이름-
pull_number(숫자): PR 번호 -
반환: 댓글 텍스트, 작성자, diff에서의 위치와 같은 세부 정보가 포함된 PR 리뷰 댓글 배열
get_pull_request_reviews
PR의 리뷰 가져오기
- 입력:
owner(문자열): 저장소 소유자repo(문자열): 저장소 이름-
pull_number(숫자): PR 번호 -
반환: 리뷰 상태(APPROVED, CHANGES_REQUESTED 등), 리뷰어, 리뷰 본문과 같은 세부 정보가 포함된 PR 리뷰 배열
검색 쿼리 구문
코드 검색
language:javascript: 프로그래밍 언어로 검색repo:owner/name: 특정 저장소에서 검색path:app/src: 특정 경로에서 검색extension:js: 파일 확장자로 검색
예시: q: "import express" language:typescript path:src/
이슈 검색
is:issue또는is:pr: 유형별 필터링is:open또는is:closed: 상태별 필터링label:bug: 레이블로 검색author:username: 작성자로 검색
예시: q: "memory leak" is:issue is:open label:bug
사용자 검색
type:user또는type:org: 계정 유형별 필터링followers:>1000: 팔로워 수로 필터링location:London: 위치로 검색
예시: q: "fullstack developer" location:London followers:>100
사용 방법
개인 액세스 토큰
GitHub 개인 액세스 토큰 생성(적절한 권한 포함):
- Personal access tokens(GitHub 설정 > 개발자 설정)으로 이동
- 이 토큰이 액세스할 저장소 선택(공개, 모두 또는 선택)
repo범위("비공개 저장소에 대한 완전한 제어")가 있는 토큰 생성- 또는 공개 저장소에서만 작업하는 경우
public_repo범위만 선택 - 생성된 토큰 복사
Claude Desktop에서 사용
Claude Desktop에서 사용하려면 claude_desktop_config.json에 다음을 추가하세요:
Docker
{
"mcpServers": {
"github": {
"command": "docker",
"args": ["run", "-i", "--rm", "-e", "GITHUB_PERSONAL_ACCESS_TOKEN", "mcp/github"],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "<YOUR_TOKEN>"
}
}
}
}
NPX
{
"mcpServers": {
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "<YOUR_TOKEN>"
}
}
}
}
VS Code에서 사용
VS Code User Settings(JSON) 파일에 다음 JSON 블록을 추가하세요. Ctrl + Shift + P를 누르고 Preferences: Open User Settings (JSON)를 입력하여 이 작업을 수행할 수 있습니다.
선택적으로 작업 공간의 .vscode/mcp.json 파일에 추가할 수 있습니다. 이렇게 하면 다른 사람과 구성을 공유할 수 있습니다.
.vscode/mcp.json 파일에서는 mcp 키가 필요하지 않습니다.
Docker
{
"mcp": {
"inputs": [
{
"type": "promptString",
"id": "github_token",
"description": "GitHub Personal Access Token",
"password": true
}
],
"servers": {
"github": {
"command": "docker",
"args": ["run", "-i", "--rm", "mcp/github"],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "${input:github_token}"
}
}
}
}
}
NPX
{
"mcp": {
"inputs": [
{
"type": "promptString",
"id": "github_token",
"description": "GitHub Personal Access Token",
"password": true
}
],
"servers": {
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "${input:github_token}"
}
}
}
}
}
빌드
Docker 빌드:
docker build -t mcp/github -f src/github/Dockerfile .
라이선스
이 MCP 서버는 MIT 라이선스에 따라 라이선스가 부여됩니다. 이는 MIT 라이선스의 약관 및 조건에 따라 소프트웨어를 자유롭게 사용, 수정 및 배포할 수 있음을 의미합니다. 자세한 내용은 프로젝트 저장소의 LICENSE 파일을 참조하세요.
일반적인 문제 해결
인증 관련 오류
- 문제:
Bad credentials또는401 Unauthorized오류 - 해결 방법:
- 개인 액세스 토큰의 유효성과 만료 여부 확인
- 토큰이 필요한 권한(scope)을 모두 가지고 있는지 확인
- 환경 변수
GITHUB_PERSONAL_ACCESS_TOKEN에 올바른 토큰이 설정되어 있는지 확인
속도 제한 관련 오류
- 문제:
API rate limit exceeded오류 - 해결 방법:
- 인증된 요청의 경우 시간당 5,000회, 비인증 요청의 경우 시간당 60회로 제한됨
- 검색 API는 인증된 사용자의 경우 분당 30회로 별도 제한됨
- 속도 제한 상태 확인:
curl -i -H "Authorization: token YOUR_TOKEN" https://api.github.com/rate_limit - 필요한 경우 배치 처리나 지연 시간 추가 고려
파일 수정 충돌
- 문제:
update_file또는push_files수행 시 충돌 오류 - 해결 방법:
- 파일 업데이트 전 최신 SHA 값 가져오기
- 브랜치를 최신 상태로 유지하여 충돌 방지
사용 사례 예제
사례 1: 저장소 내 파일 내용 검색 및 수정
// 특정 파일을 검색하고 내용을 수정하는 예제
const searchResults = await github.search_code({
q: "config.json in:path repo:username/myRepo"
});
if (searchResults.items.length > 0) {
const fileInfo = searchResults.items[0];
const fileDetails = await github.get_file_contents({
owner: "username",
repo: "myRepo",
path: fileInfo.path
});
// 파일 내용 디코딩 및 수정
const content = Buffer.from(fileDetails.content, 'base64').toString();
const updatedContent = content.replace("oldValue", "newValue");
// 변경사항 커밋
await github.create_or_update_file({
owner: "username",
repo: "myRepo",
path: fileInfo.path,
message: "Update configuration",
content: updatedContent,
sha: fileDetails.sha,
branch: "main"
});
}
사례 2: 이슈 모니터링 및 자동 처리
// 특정 레이블이 있는 열린 이슈 조회 후 처리
const issues = await github.list_issues({
owner: "username",
repo: "myRepo",
state: "open",
labels: ["bug", "priority:high"]
});
for (const issue of issues) {
// 이슈에 댓글 추가
await github.add_issue_comment({
owner: "username",
repo: "myRepo",
issue_number: issue.number,
body: "이 우선순위 버그를 확인 중입니다. @devteam"
});
// 이슈에 추가 레이블 적용
await github.update_issue({
owner: "username",
repo: "myRepo",
issue_number: issue.number,
labels: [...issue.labels.map(l => l.name), "in-progress"]
});
}
사례 3: PR 자동화 워크플로우
// 새 브랜치 생성, 파일 변경, PR 생성 워크플로우
const branchName = `feature-update-${Date.now()}`;
// 새 브랜치 생성
await github.create_branch({
owner: "username",
repo: "myRepo",
branch: branchName,
from_branch: "main"
});
// 여러 파일 변경
await github.push_files({
owner: "username",
repo: "myRepo",
branch: branchName,
message: "Update dependencies and README",
files: [
{
path: "package.json",
content: updatedPackageJson
},
{
path: "README.md",
content: updatedReadme
}
]
});
// PR 생성
await github.create_pull_request({
owner: "username",
repo: "myRepo",
title: "Update dependencies and documentation",
body: "This PR updates the dependencies to the latest versions and improves documentation.",
head: branchName,
base: "main"
});