vrchat-mcp
vrchat-mcp
VRChat API용 MCP 서버입니다. OpenAPI 스펙의 297개 작업 전부를 빌드 시점에 생성하며, 단일 엔드포인트로는 할 수 없는 작업, 즉 2단계 인증 로그인, 파일 업로드, 이미지 보기, 이벤트 파이프라인을 위한 수제 도구를 추가로 포함합니다.
stdio를 통해 로컬에서 실행되며, Claude Code 또는 Claude Desktop의 하위 프로세스로 동작합니다. 따로 허용하지 않는 한 읽기 전용입니다.
Bun, 공식 MCP TypeScript SDK v2, 공식 vrchat JavaScript SDK를 기반으로 합니다. 도구는 VRChat OpenAPI specification에서 생성되고 커밋되므로, 도구 표면이 위쪽 개발에 뒤처져 썩는 것이 아니라 상류를 따라갑니다.
치트시트
bun install && bun link # `vrchat-mcp` is now on PATH
cp .env.example .env # fill in username, password, contact
claude mcp add vrchat -- vrchat-mcp최소 .env:
VRCHAT_USERNAME=you
VRCHAT_PASSWORD=hunter2
VRCHAT_CONTACT=you@your-domain.tld # must be real, VRChat 403s generic agents원하는 작업 | 방법 |
생성 및 편집 허용 |
|
삭제 및 모더레이션 허용 |
|
잔액 지출 허용 |
|
상점 도구만 노출 |
|
모든 것 노출 |
|
도구가 빠진 이유 확인 |
|
큰 페이로드가 컨텍스트를 먹는 문제 방지 | 아무 도구에나 |
이미지 보기 |
|
사진 업로드 |
|
새 네트워크에서 멈춘 로그인 해결 | 이메일로 받은 링크를 연 뒤 |
도구 이름은 그 출처를 담고 있습니다. 밑줄 두 개는 스펙에서 생성된 것(vrchat__getCurrentUser)을 뜻하므로 VRChat 공식 문서에서도 그 이름을 검색할 수 있습니다. 밑줄 하나는 이 서버가 직접 작성한 것(vrchat_authStatus)을 뜻합니다.
손으로 작성한 도구 전체 목록:
도구 | 하는 일 |
| 로그인 상태, rate limiter, 그리고 어떤 도구 그룹이 어떤 env var에 의해 숨겨졌는지 |
| 대기 중인 로그인에 사용자가 읽어 전한 코드를 제출 |
| 새 네트워크 인증 이메일 링크를 연 뒤 로그인을 다시 시작 |
| 저장된 세션을 지웁니다 |
| VRChat 이미지를 내려받아 표시 가능한 이미지로 반환 |
| 이미지가 아닌 파일에 VRChat의 4단계 업로드를 진행 |
| 이미지를 업로드하여 스토어 상품에 첨부 |
| 커서 이후의 이벤트를 가져옵니다 |
| 다음으로 일치하는 이벤트가 올 때까지 대기 |
| 저장된 이벤트 기록에서 전체 텍스트 검색 |
| 소켓 상태와 유형별 보관 기간을 보여줍니다 |
마지막 네 개는 VRCHAT_MCP_WEBSOCKET=1인 경우에만 나타납니다.
Related MCP server: Portals MCP
설치
bun link는 vrchat-mcp 실행 파일을 PATH에 등록하므로, 이후 단계에서는 체크아웃 위치를 알 필요가 없습니다.
bun install
bun link # from the repo root이름으로 등록합니다:
claude mcp add vrchat -- vrchat-mcpClaude Desktop이라면 claude_desktop_config.json에 이렇게 등록합니다:
{
"mcpServers": {
"vrchat": {
"command": "vrchat-mcp"
}
}
}설정은 그것이 전부입니다. 자격 증명은 저장소의 .env에서 가져오므로 여기에 다시 쓸 필요가 없지만, env 블록에 넣은 값이 우선합니다. 명령은 bun unlink로 제거할 수 있습니다.
PATH에 아무것도 등록하고 싶지 않다면 엔트리 파일을 절대 경로로 지정하세요. 서버는 임의의 작업 디렉터리에서 실행되므로 상대 경로로는 동작하지 않습니다.
claude mcp add vrchat -- bun run /abs/path/to/vrchat-mcp/src/index.ts연락처 요구사항
VRChat은 일반적인 User-Agent 요청을 403으로 거부합니다. VRCHAT_CONTACT는 SDK가 모든 API 및 WebSocket 요청에서 보내는 설명적 User-Agent에 들어가는 연락처 문자열이며, 사실상 필수입니다.
값은 실제 값이어야 합니다. SDK는 @example.com이 포함된 연락처를 거부하므로 뻔한 자리표시자는 반드시 실패하도록 정해진 값입니다. 서버는 이것을 알 수 없는 403으로 떠서 내지 않고 첫 번째 도구 호출에서 설정 오류로 보고합니다.
구성
우선순위가 높은 순서로 세 계층입니다. 프로젝트는 사용자 자격 증명을 반복하지 않고 자체 옵션을 설정할 수 있습니다.
실제 환경 변수(MCP 클라이언트의
env블록 포함)명령을 실행하는 디렉터리의
.env(Bun이 자동으로 로드)저장소 루트의
.env
따라서 이미 구성해 둔 자격 증명을 사용하여 스토어 도구만 사용하고 싶은 프로젝트는 옆에 한 줄만 추가하면 됩니다.
# ~/my-project/.env
VRCHAT_MCP_TAGS=store변수 | 기본값 | 효과 |
| none | 계정 사용자 이름 또는 이메일 |
| none | 계정 비밀번호 |
| none | Base32 TOTP 비밀키. 설정하면 로그인 시 코드를 묻지 않음 |
| none | User-Agent에 들어가는 연락처 문자열. 사실상 필수 |
| all | 등록할 태그. 필터를 쓰지 않으려면 |
| off | 생성 및 편집을 허용 |
| off | 삭제 및 모더레이션을 허용. 쓰기 게이트도 필요 |
| off | 잔액 지출 허용. 쓰기 게이트도 필요 |
| off | 관리자 작업을 허용. 쓰기 게이트와 무관 |
| 20 | 초당 요청 수. |
| 30000 | 제한 뒤에서 호출이 기다렸다가 포기하기까지의 시간 |
| off | 이벤트 파이프라인을 열고 이벤트 도구를 등록 |
| low-noise event set | 구독할 이벤트 종류. 기본값을 확장하지 않고 대체 |
| history | 유형별 유지 이벤트 수. 유형별 재지정 예: |
| 1,000 | 최대 나이. |
| project | 이벤트 DB 경로 |
| project | 세션 파일 경로 |
| none | API 및 WebSocket 트래픽용 HTTP/HTTPS 프록시 |
| 300000 | 대기 중인 로그인이 코드를 기다리는 시간 |
| off | 라이브 테스트 모드를 활성화 |
불리언 값은 1 또는 true를 대소문자 무시하고 받습니다.
상태는 어디에 저장되나요
상태는 프로젝트별입니다. 프로젝트 안에서 서버를 실행하면 세션과 이벤트 history가 해당 프로젝트 .vrchat-mcp/ 안에 저장됩니다. 프로젝트 루트는 작업 디렉터리에서 위로 올라가며 .git, package.json, deno.json, pyproject.toml, go.mod 중 하나를 찾아 결정하므로 하위 디렉터리에서 실행해도 같은 상태에 도달하고, 한 단계 아래에 세션이 따로 남지 않습니다.
디렉터리는 버전 관리에서 스스로를 숨깁니다. 생성 시 vrchat-mcp는 그 안에 *를 포함한 .gitignore를 작성하므로 인증 자격 증명인 세션 파일이 호스트 프로젝트의 별도 규칙 없이 보호됩니다.
따라서 각 프로젝트는 별도로 로그인하며, 새 프로젝트에서 첫 호출 시 2FA 코드를 요구할 수 있습니다. 모든 곳에서 로그인을 공유하려면 모든 설치가 같은 파일을 가리키게 하세요:
VRCHAT_MCP_SESSION=/abs/path/to/shared/session.json안전 게이트
서버는 읽기 전용으로 시작합니다. 297개 작업 중 기본 등록은 150개입니다. 쓰기, 삭제, 지출, 모더레이션을 포함하는 그 무엇도 요청하지 않는 한 나타나지 않습니다.
분류 | 포함 내용 | 필요한 것 | 예시 |
| 모든 | 없음 |
|
|
|
|
|
| 모든 |
|
|
| 구매 및 Tilia/KYC/출금 경로 |
|
|
| 관리자 및 계정 관리 생애주기 |
|
|
파괴적(destructive) 및 금전(money) 게이트는 쓰기 게이트 위에 덧쓰이므로, 쓰기를 형상 해제하면 정확히 생성・편집만 허용되고 삭제나 지출은 절대 허용되지 않습니다. 관리자 게이트는 독립적이며 어떤 것도 그 활성화를 암시하지 않습니다. 에이전트가 사용자 소유 콘텐츠를 편집하도록 허용하는 것이 계정 삭제를 허용해서는 절대 안 됩니다.
선택으로 들어가는 내용:
ALLOW_WRITES는 에이전트가 사용자 소유의 것을 만들고 변경할 수 있게 합니다. 대부분 수동으로 되돌릴 수 있습니다.ALLOW_DESTRUCTIVE_WRITES는 되돌릴 수 없는 호출을 추가합니다. 삭제, 차단, 추방, 인스턴스 종료, 사용자 유지 데이터 삭제 등입니다.ALLOW_PURCHASES는 에이전트가 실제 잔액을 지출할 수 있게 합니다.purchaseProductListing는 실제 거래입니다. 도구 목록이 불완전해 보인다고 이 값을 설정하지 마세요.ALLOW_ADMIN은 그중deleteUser를 포함한 관리자 기능을 노출합니다. 이 대부분은 일반 계정에서 403을 받지만deleteUser만은 절대 실수로 발생해선 안 됩니다.
게이트 처리된 작업은 어느 경우든 생성된 표에 남기 때문에 스펙과의 구성이 1:1을 유지하며, 거부 목록도 diff 에서 검토할 수 있니다. MCP 주석(readOnlyHint, destructiveHint)도 설정되어 있으므로 이를 표시하는 클라이언트는 사용자에게 확인을 요청할 수 있습니다.
빠진 도구는 어떻게 찾나요?
게이트된 도구는 단순히 존재하지 않으며, 이는 "이 서버가 그렇게 하지 말라고 지시받았다"가 아니라 "VRChat은 이 작업을 할 수 없다"로 읽힙니다. 그런 실수는 이미 실제 현장에서 발생했습니다. 에이전트가 쓰기 도구가 존재하고 단지 플래그 뒤에 있었음에도 economy API를 읽기 전용으로 보고했습니다.
vrchat_authStatus가 그 간극을 메웁니다. 이 도구는 모든 태그와 안전 등급, 각 태그가 보유한 작업 수, 현재 노출된 작업 수, 그리고 나머지를 노출할 정확한 .env 변경 사항을 보고합니다.
{
"availability": {
"toolsRegistered": 12,
"toolsHidden": 285,
"tagFilter": ["store"],
"kinds": { "write": { "enabled": false, "hidden": 88 } },
"nextSteps": [
"88 `write` operations are hidden. Ask the user to set VRCHAT_MCP_ALLOW_WRITES=1 ..."
]
}
}무언가가 지원되지 않는다고 결론 내리기 전에 이 도구를 호출하세요.
노출할 도구 선택
VRCHAT_MCP_TAGS는 태그를 선택합니다. 설정하지 않으면 모든 것이 등록되며, everything은 이를 명시적으로 나타내므로 JSON 구성에서 키를 삭제하는 것보다 쉽습니다. all과 *도 작동합니다.
VRCHAT_MCP_TAGS=everything # all 297 operations
VRCHAT_MCP_TAGS=store # just the storefront, 19 operations
VRCHAT_MCP_TAGS=store,users,worlds # matches any of the three사양 태그: authentication, avatars, calendar, economy, favorites, files, friends, groups, instances, inventory, invite, jams, miscellaneous, notifications, playermoderation, prints, props, users, worlds. 여기에 이 서버가 추가하는 store가 있습니다.
일치하는 항목이 없는 태그는 시작 시 stderr에 경고로 출력되고 vrchat_authStatus가 보고합니다. 이것이 없으면 stores 같은 오타는 생성된 도구를 하나도 등록하지 않아 마치 고장난 서버처럼 보입니다.
로그인
로그인은 지연(lazy) 방식입니다. 시작 시 아무것도 인증하지 않으므로 tools/list는 자격 증명 없이도 작동하며 서버는 검사 가능한 상태로 유지됩니다. 세션이 필요한 첫 번째 도구 호출이 로그인을 트리거합니다.
VRCHAT_TOTP_SECRET이 설정되어 있으면 그게 전부입니다. 어떤 프롬프트도 없습니다.
그것이 없으면 VRChat이 코드를 이메일로 보내고, 호출은 대기(parked) 상태로 돌아오며 멈추지(hanging) 않습니다:
vrchat__getCurrentUser
-> Login paused: VRChat emailed a code. Ask the user for it, call
vrchat_submitTwoFactorCode { requestId: 'a1b2c3d4', code: '……' },
then retry the original call.vrchat_submitTwoFactorCode로 응답한 다음 다시 시도하세요. 세션은 유지되므로 이 과정은 프로젝트당 한 번만 발생하며 만료될 때까지 재발하지 않습니다.
새 네트워크에서 로그인
프록시, VPN 또는 ISP를 변경하면 2FA 코드가 아닌 검사가 트리거되는데, 둘은 실제 시간을 낭비할 만큼 비슷해 보입니다. VRChat은 다음 중 하나로 응답합니다:
401 It looks like you're logging in from somewhere new! Check your email for a message from VRChat.
429 Logging in from too many places? Check your email for verification link둘 다 같은 의미이며, 어느 쪽도 보이는 그대로가 아닙니다. 이메일에는 여섯 자리 코드가 아닌 링크가 들어 있으므로 vrchat_submitTwoFactorCode로는 해결할 수 없습니다. 로그인은 두 단계로 진행됩니다:
도구 호출이 그중 하나의 메시지와 함께 실패합니다
사용자가 이메일의 링크를 엽니다
vrchat_retryLogin을 호출합니다. VRChat은 이 두 번째 시도에서만 실제 코드를 보냅니다사용자가 코드를 읽어 주면
vrchat_submitTwoFactorCode를 호출합니다원래 도구를 다시 시도합니다
429는 rate-limit 상태를 가장한 인증 도전이므로 로컬 제한기는 이를 무시합니다. 기다린다고 해결되지 않으며, 추가 시도마다 계정의 제한된 세션 슬롯 하나가 소모되고, 그것이 바로 429를 만들어 내는 원인입니다. 실패한 로그인은 30초 동안 캐시되므로 도구 호출의 폭주가 로그인 시도의 폭주가 되지 않습니다. vrchat_retryLogin은 그 캐시를 지웁니다. 그때가 되면 사용자는 실패가 기다리던 작업을 이미 수행했기 때문입니다.
로그인 중 병렬 호출
에이전트는 도구를 한꺼번에 펼치며, 콜드 스타트에서는 모두 인증되지 않은 클라이언트에 도달합니다. 하나의 호출이 로그인을 진행합니다. 나머지는 최대 3초간 기다린 후 블로킹 대신 login_pending을 반환하므로, 느린 로그인은 모든 도구 호출이 아니라 하나의 도구 호출만 지연시키고, 코드에서 대기하는 로그인은 여러 개 대신 하나의 프롬프트만 발생시킵니다.
_responseKeys
모든 도구는 _responseKeys를 받으며, 기본적으로 모든 도구는 원본 업스트림 페이로드를 반환합니다. 서버 측 선별은 없습니다. 직접 고른 필드 목록은 무엇이 중요한지 추측하는 것이고, 다른 필드가 필요했던 사람에게는 틀린 것이며, 변동하는 사양에 맞춰 297개 작업에 대해 유지 관리해야 하기 때문입니다. 에이전트는 이 호출에서 자신이 원하는 것을 알고 있습니다. 그것을 말해야 합니다.
World 객체는 대략 4KB입니다. 범위를 좁히면 보통 절반 이상 줄어듭니다.
패턴 | 선택 |
| 전체 페이로드, 바이트 그대로 |
| 해당 최상위 필드들 |
| 중첩된 경로 |
| 최상위 배열의 모든 요소에서 |
|
|
| 각 요소 아래의 모든 것 |
| 제외하며, |
프로젝션은 형태를 유지합니다. 객체는 중첩된 상태를 유지하고, 배열은 순서와 길이를 유지하므로 한 호출에서 학습한 경로가 다음 호출에서도 여전히 작동합니다.
발견(discovery)은 프로젝션보다 더 중요합니다. 에이전트는 존재하는지 모르는 키를 요청할 수 없고, 조용히 빈 결과를 반환하면 이 설계는 트리밍보다 나빠질 것입니다. 따라서 아무것도 일치하지 않는 경로는 _unmatched로 반환되며, 실제로 무엇이 있었는지 나열하는 _availableKeys도 함께 반환됩니다. 배열 요소 키는 *.id, *.name 형식으로 명명되며, 이는 _responseKeys 항목으로 작동하는 형태입니다.
["*"]는 입력을 참조로 반환하므로 원시 경로가 확실히 무손실이며 아무것도 숨겨지지 않습니다.
이미지 보기
vrchat_getImage는 VRChat 이미지를 다운로드하여 이미지 블록으로 반환하므로, 모델이 URL을 보고하는 대신 이미지를 직접 볼 수 있습니다.
{ "name": "vrchat_getImage",
"arguments": { "url": "https://api.vrchat.cloud/api/1/file/file_.../1/256" } }사용자, 월드, 아바타, 프린트 또는 제품의 imageUrl이나 thumbnailImageUrl을 전달하거나, fileId를 전달하여 도구가 URL을 만들게 하세요. savePath는 바이트를 디스크에 기록할 수도 있습니다.
가능하면 /256 또는 /512로 끝나는 URL을 선호하세요. 이미지는 base64로 전달되므로 전체 크기 텍스처는 많은 컨텍스트를 소모하면서 추가 디테일을 얻지 못합니다. 4MB를 초과하는 것은 거부됩니다. 정말 필요하다면 maxBytes를 높이세요.
이 도구는 VRChat이 호스팅하는 이미지만 가져오며, 세션 쿠키가 전송되는 곳은 오직 api.vrchat.cloud뿐입니다. 세션을 보유한 채 호출자가 제공한 URL을 가져오는 도구는 제약이 없으면 요청 위조의 원시 도구가 되며, CDN으로 보내진 쿠키는 내어준 쿠키입니다.
파일 업로드
로컬 파일 경로를 전달하세요. 서버는 여러분의 머신에서 실행되며 파일을 직접 읽으므로 파일 내용이 대화에 들어가지 않습니다. 2MB PNG를 base64로 인라인하면 도구 인자로 약 2.7MB를 소모하게 되는데, 이는 호출의 다른 모든 것을 합친 것보다 많습니다.
디스크에 파일이 없을 때, 예를 들어 에이전트가 방금 생성한 이미지의 경우, 같은 인자가 바이트를 인라인으로 받습니다:
{ "file": { "data": "iVBORw0KGgo...", "mimeType": "image/png", "filename": "icon.png" } }data: URI도 문자열 위치에서 작동하므로 "file": "data:image/png;base64,iVBORw0..."와 동일합니다. filename은 선택 사항이며, 생략하면 MIME 유형에서 만들어집니다. VRChat이 이름을 붙일 수 없는 업로드를 거부하기 때문입니다. 경로가 있으면 언제나 경로를 선호하세요. 인라인은 파일 바이트당 약 1.33바이트의 도구 인자를 소모하며, 이는 다른 모든 것과 동일한 컨텍스트 예산에서 나옵니다.
여덟 가지 작업은 파일을 직접 받으며, 각각 한 번의 호출로 처리됩니다:
도구 | 필드 | 용도 |
|
| 아이콘, 갤러리, 이모지, 스티커, 제품 이미지 ( |
|
| 프린트 |
|
| 프로필 아이콘 |
|
| 갤러리 |
|
| 프린트 이미지 교체 |
|
| 초대 사진 |
|
| 초대 요청 |
|
| 초대 응답 |
{ "name": "vrchat__uploadImage",
"arguments": { "file": "C:/Users/me/Pictures/icon.png", "tag": "icon" } }결과는 전송된 바이트와 그것이 어떤 형태로 도착했는지를 알려 주며, 이것이 올바른 파일의 성공적인 업로드와 잘못된 파일의 성공적인 업로드를 구별하는 유일한 방법입니다:
{ "uploaded": [
{ "field": "file", "name": "icon.png", "bytes": 48211, "type": "image/png", "source": "path" }
],
"result": { "id": "file_...", "name": "icon.png" } }그 외의 경우 vrchat_uploadFile은 VRChat의 4단계 시퀀스(레코드 생성, 사전 서명된 URL 요청, 바이트 전송, 완료)를 실행하고 완료된 파일 레코드를 반환합니다. 에셋 번들과 unity 패키지에 사용하세요. 바이트는 API 클라이언트를 통하지 않고 의도적으로 일반 요청으로 VRChat의 스토리지 제공자에게 직접 전송됩니다. 그 클라이언트는 보내는 모든 것에 세션 쿠키를 첨부하며 스토리지 호스트는 제3자이기 때문입니다.
업로드는 쓰기 작업이므로 이 모든 것에는 VRCHAT_MCP_ALLOW_WRITES=1이 필요합니다. 파일은 100MB로 제한되며, 빈 파일은 VRChat에 도달하기 전에 거부됩니다. 그렇지 않으면 VRChat이 손상된 레코드를 저장하게 됩니다. vrchat_uploadFile이 중간에 실패하면 생성된 파일 레코드의 이름을 알려 주므로 vrchat__getFile로 검사하고 vrchat__deleteFile로 제거할 수 있습니다.
스토어 운영
스토어프론트를 관리하는 것은 money 작업이 아니라 일반적인 쓰기입니다. 제품 생성, 이름 변경, 이미지 변경, 리스팅 게시 또는 게시 취소: 이 중 어떤 것도 지출하거나 벌지 않으므로 VRCHAT_MCP_ALLOW_WRITES=1만 필요합니다. money 게이트는 구매와 결제 처리기를 위한 것입니다.
VRCHAT_MCP_TAGS=store
VRCHAT_MCP_ALLOW_WRITES=1제품 이미지 설정은 한 번의 호출로 이루어집니다:
{ "name": "vrchat_setProductImage",
"arguments": { "productId": "prod_...", "file": "/abs/path/cover.png" } }이것은 tag: "product"로 업로드하고 반환된 파일 ID를 제품의 imageId로 첨부합니다. 수동으로는 tag: "product" 또는 "listinggallery"를 사용한 vrchat__uploadImage를 호출한 다음, 반환된 ID로 vrchat__updateProduct를 호출하면 됩니다.
VRChat 자체가 허용하지 않는 한 가지: 리스팅은 편집을 위해 active만 노출하므로 가격, 제목, 설명은 생성 후 변경할 수 없습니다. 리스팅을 삭제하고 새로 만드세요. 이름, 설명, 이미지는 제품에 있으며 vrchat__updateProduct를 통해 편집할 수 있습니다.
페이지네이션
호출당 한 페이지입니다. 페이지네이션된 도구는 기본적으로 25개 결과를 반환하며 계속하기 위한 nextOffset을 다시 알려 줍니다. 의도적으로 내부 페이지네이션 루프는 없습니다. 숨겨진 자동 페이지네이션은 에이전트에게 단일 호출처럼 보이는 것 안에서 요청 예산과 많은 컨텍스트를 소모하게 될 것이기 때문입니다.
짧은 페이지는 끝을 의미합니다. VRChat은 총계를 보고하지 않으므로 그것이 유일한 신뢰할 수 있는 신호입니다.
WebSocket 이벤트
기본적으로 꺼져 있습니다. 유휴 상시 연결 소켓이 세션 슬롯을 소모하기 때문입니다. VRCHAT_MCP_WEBSOCKET=1을 설정하여 소켓을 열고 네 개의 vrchat_events* 도구를 등록하세요.
VRCHAT_MCP_WS_EVENTS는 구독할 유형을 선택하며, notification, notification-v2, economy-update, friend-online, friend-offline, instance-queue-ready의 기본 집합을 확장하는 대신 대체합니다.
파이프라인 메시지는 이중 인코딩되어 있습니다. content 필드는 두 번째 파싱이 필요한 문자열화된 JSON인데, see-notification과 hide-notification은 예외로 맨몸의 id를 전달합니다. 이 모든 것은 수집 시 한 번 정규화되므로 어떤 도구도 JSON 안에 JSON 문자열을 건네주지 않습니다. SDK 자체 소켓은 이 두 메시지 유형을 조용히 버리는데, 이것이 이 서버가 SDK를 사용하지 않는 이유 중 하나입니다. 다른 이유는 SDK가 프록시를 사용하지 않기 때문입니다.
보존은 유형별로 이루어집니다
기록은 .vrchat-mcp/events.db의 SQLite에 저장되며, 총 1000개가 아니라 이벤트 유형당 1000개를 유지합니다. friend-location처럼 말이 많은 유형은 economy-update처럼 드물고 가치 있는 유형을 절대 축출할 수 없습니다. 단일 전역 상한은 몇 분 안에 그렇게 할 것입니다.
VRCHAT_MCP_HISTORY=1000,friend-location:200,economy-update:5000
VRCHAT_MCP_HISTORY_MAX_AGE=7d나이 상한은 개수 상한과 함께 작동하며, 먼저 적용되는 쪽이 이깁니다. 개수만 있으면 드물게 발생하는 유형이 몇 달 된 이벤트를 현재 것처럼 남겨 둡니다. 나이만 있으면 폭주가 데이터베이스를 부풀릴 수 있습니다. vrchat_eventsStatus는 현재 어느 제한이 유형별로 적용되고 있는지 보고하므로, 보존 창이 조용하지 않고 읽기 쉽게 드러납니다.
기록은 재시작 후에도 유지되므로 vrchat_eventsSearch는 자리를 비운 사이 일어난 일에 답할 수 있습니다. 라이브 전용 버퍼로는 불가능합니다.
프록시
VRCHAT_MCP_PROXY는 트래픽을 HTTP 또는 HTTPS 프록시를 통해 라우팅하며, 선택적으로 user:pass@ 자격 증명을 지원합니다.
VRCHAT_MCP_PROXY=http://127.0.0.1:8080
VRCHAT_MCP_PROXY=https://user:pass@proxy.internal:8443SOCKS는 지원되지 않습니다. Bun의 fetch는 socks5://를 완전히 거부하므로, SOCKS URL은 절반만 동작하는 대신 제한 사항을 명시한 구성 오류와 함께 시작 시 실패합니다. 대신 로컬 HTTP 프록시를 앞에 두세요.
프록시는 API와 WebSocket 트래픽을 모두 처리합니다. 둘은 서로 다른 메커니즘을 거치며, 절반만 올바르게 처리했을 때의 실패 모드는 프록시를 통과하는 것처럼 보이면서 이벤트 스트림에서 실제 IP를 유출하는 서버입니다.
프록시에 연결할 수 없으면 호출은 명확한 오류와 함께 실패합니다. 서버는 절대 직접 연결로 조용히 폴백하지 않습니다. IP 분리를 위해 이 기능을 사용하는 사람에게는 그것이 최악의 결과이기 때문입니다. 프록시 URL은 자격 증명을 포함할 수 있으므로 절대 로그에 기록되지 않습니다.
개발
bun link # install the vrchat-mcp command on PATH
bun unlink # remove it
bun run generate # regenerate tools from the latest upstream spec
bun run generate --offline # regenerate from the committed snapshot, no network
bun test # offline suite
bun run test:live # live suite, needs VRCHAT_LIVE_TESTS=1
bun run inspect # MCP Inspector against this server
bun run typecheck # tsc --noEmitbun run generate는 main 브랜치의 vrchatapi/specification을 가져와 번들링하고, 번들된 스펙과 spec/VERSION.json(업스트림 SHA, 타임스탬프, 콘텐츠 해시)을 재생성된 src/generated/operations.ts와 함께 작성합니다. 둘 다 커밋되므로, 재생성할 때마다 스펙 변경과 그로 인한 도구 변경이라는 두 개의 검토 가능한 diff가 생성되며, 잘못된 업스트림 커밋은 부담이 되는 대신 되돌릴 수 있습니다. --offline은 네트워크 없이 커밋된 스냅샷에서 출력을 바이트 단위로 그대로 재현합니다.
src/generated/operations.ts는 생성된 파일입니다. 수동으로 편집하지 마세요.
VRChat SDK에 일치하는 메서드가 없는 operationId가 10개 있습니다. 스펙이 클라이언트 라이브러리보다 빠르게 움직이기 때문입니다. 이들은 동일한 클라이언트의 원시 요청 폴백을 통해 처리되므로 쿠키, User-Agent, 프록시 및 속도 제한이 여전히 적용되며, 1:1 커버리지는 조용히 거짓이 되는 대신 사실로 유지됩니다. Codegen은 실행할 때마다 목록을 출력합니다.
stdout은 JSON-RPC 채널입니다. 모든 로깅은 stderr로 이동하며, 하나의 잘못된 console.log가 프로토콜 스트림을 손상시킵니다.
테스트
bun test는 오프라인 스위트입니다: codegen 출력, 게이팅, 가짜 클록에 대한 속도 제한기, 기록 보존 및 검색, 프로젝션, 오류 매핑, 업로드 경로 처리. 네트워크 없음, 자격 증명 없음, 계정 없음. 이것이 기본으로 실행되는 것입니다.
bun run test:live는 실제 계정에 접속하며, VRCHAT_LIVE_TESTS=1로 옵트인하고 그렇지 않으면 건너뜁니다. 스스로 지키는 규칙:
읽기 및 크리에이터 소유 쓰기만 허용합니다. 클라이언트가 구성되기 전에
money또는admin으로 분류된 것은 무엇이든 강하게 거부합니다. 테스트 스위트는 돈을 쓸 수 없어야 합니다.모든 쓰기는 스스로 정리하고 태그가 지정되어 우발적인 아티팩트를 게임 내에서 식별할 수 있습니다.
프로덕션과 동일한 제한기를 거치며 작게 유지됩니다. VRChat의 스로틀링을 유발하는 실행은 실행하지 않는 것보다 나쁩니다.
단언은 형태와 상태에 대한 것이며, 변동적인 콘텐츠에는 절대 적용하지 않습니다. 친구 수와 월드 목록은 실행 간에 변합니다.
가능하면 전용 계정을 사용하세요. 자격 증명은
.env에서만 가져옵니다.
보안
.env와.vrchat-mcp/는 gitignore 처리되며,.vrchat-mcp/는 내부에서도 자신을 무시하므로 다른 프로젝트 안에 있어도 숨겨진 상태로 유지됩니다..vrchat-mcp/session.json은 인증 자격 증명, 즉 유효한 세션 쿠키입니다. 비밀번호처럼 취급하세요. 삭제하거나vrchat_logout을 호출하면 새 로그인이 강제됩니다.2FA 코드, 비밀번호, TOTP 시크릿 및 프록시 URL은 stderr를 포함하여 절대 로그에 기록되지 않습니다.
세션 쿠키는
api.vrchat.cloud로만 전송되며 다른 곳으로는 전송되지 않습니다. VRChat의 스토리지 제공자로의 업로드와 CDN에서의 이미지 가져오기는 의도적으로 인증된 클라이언트를 우회합니다.오류는 상태, VRChat 자체 메시지 및 실행 가능한 힌트를 담은 구조화된 결과로 반환됩니다. 원시 예외와 스택 트레이스는 대화 기록에 도달하지 않습니다.
stdio 전용, 로컬 전용. HTTP 전송 없음, 다중 사용자 자격 증명 격리 없음. 이 서버는 한 머신의 한 계정을 위한 것입니다.
프로젝트 구조
scripts/generate-tools.ts # build-time codegen: spec -> src/generated/operations.ts
spec/openapi.bundled.json # committed snapshot of the upstream spec
spec/VERSION.json # upstream SHA + fetch timestamp + content hash
src/config.ts # the entire env surface, read once
src/types.ts # shared contracts
src/generated/operations.ts # committed, generated, 297 entries, do not edit
src/vrchat/client.ts # lazily-authed VRChat client, proxy, 2FA sniffing
src/vrchat/twofactor.ts # pending-code broker
src/vrchat/ratelimit.ts # token bucket + global 429 backoff
src/vrchat/events.ts # websocket client + waiter registry
src/vrchat/history.ts # bun:sqlite event store, per-type retention + FTS5 search
src/tools/auth.ts # authStatus / submitTwoFactorCode / retryLogin / logout
src/tools/images.ts # getImage
src/tools/upload.ts # uploadFile / setProductImage
src/tools/events.ts # eventsRecent / eventsWait / eventsSearch / eventsStatus
src/registry.ts # gating, registration, the one shared handler
src/project.ts # _responseKeys path projection
src/upload.ts # local path -> File, with size and type guards
src/errors.ts # HTTP status -> structured tool error with hint
src/index.ts # serveStdio entry point
tests/ # offline suite; tests/live/ is the opt-in live suite
docs/PLAN.md # design document
PROGRESS.md # build status and verified SDK behaviour라이선스
LICENSE 참조.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceEnables remote control of Lovense toys through Claude using natural language commands. Supports vibration patterns, presets, and intensity control from any device via Cloudflare Workers.4Apache 2.0
- AlicenseNot gradedqualityNot gradedmaintenanceEnables Claude to design and build interactive 3D games within the Portals virtual platform through direct API integration. It facilitates automated asset placement, interaction logic configuration, and quest management using natural language commands.4
- AlicenseAqualityDmaintenanceConnects Claude to Open WebUI, enabling chat management, RAG knowledge bases, files, functions, and prompts directly from Claude.26252MIT
- AlicenseNot gradedqualityAmaintenanceBridges any OpenAPI 3.x REST API to Claude Code by automatically generating one tool per endpoint from your spec, with full argument validation and auth support.18MIT
Related MCP Connectors
WHOOP recovery, strain, sleep and workouts in Claude via official WHOOP OAuth. Free, open source.
Hosted MCP server connecting claude.ai, ChatGPT and other AI apps to your own computer
Garmin data in Claude & ChatGPT via the Garmin Health API. OAuth sign-in, no password sharing.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/TheArmagan/vrchat-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server