vrchat-mcp
vrchat-mcp
Un servidor MCP para la API de VRChat. Las 297 operaciones de la especificación OpenAPI, generadas en tiempo de compilación, más herramientas escritas a mano para lo que un solo endpoint no puede hacer: inicio de sesión con dos factores, subida de archivos, visualización de imágenes y el pipeline de eventos.
Se ejecuta localmente sobre stdio, como subproceso de Claude Code o Claude Desktop. Solo lectura hasta que tú digas lo contrario.
Construido con Bun, el SDK oficial de MCP TypeScript v2 y el SDK oficial de JavaScript de
vrchat. Las herramientas provienen de
la especificación OpenAPI de VRChat y están
confirmadas, de modo que la superficie sigue el ritmo de la especificación en lugar de pudrirse.
Hoja de referencia
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 mínimo:
VRCHAT_USERNAME=you
VRCHAT_PASSWORD=hunter2
VRCHAT_CONTACT=you@your-domain.tld # must be real, VRChat 403s generic agentsQuiero... | Hago esto... |
Habilitar creación y edición |
|
Habilitar borrado y moderación | añadir |
Habilitar gasto de saldo | añadir |
Exponer solo herramientas de tienda |
|
Exponer todo |
|
Saber qué herramienta falta | llamar a |
Evitar que cargas útiles enormes consuman contexto |
|
Ver una imagen |
|
Subir una imagen |
|
Arreglar un inicio de sesión bloqueado en una red nueva | abrir el enlace del correo y luego |
Los nombres de las herramientas llevan su origen. Dos guiones bajos significan generado a partir
de la especificación (vrchat__getCurrentUser), de modo que el nombre se puede buscar en la
documentación propia de VRChat. Un guion bajo significa que este servidor lo escribió
(vrchat_authStatus).
Herramientas escritas a mano, en su totalidad:
Herramienta | Qué hace |
| Estado de inicio de sesión, limitador de tasa y qué grupos de herramientas están ocultos por qué variable de entorno |
| Responde a un inicio de sesión en espera con el código que el usuario ha leído |
| Reinicia un inicio de sesión después de que se abra el enlace del correo en una red nueva |
| Borra la sesión almacenada |
| Descarga una imagen de VRChat y la devuelve como imagen visible |
| Ejecuta la subida de archivos en cuatro pasos para archivos que no son imágenes |
| Sube una imagen y la adjunta a un producto de la tienda |
| Eventos desde un cursor |
| Bloquea hasta el siguiente evento que coincida |
| Búsqueda de texto completo en el historial de eventos |
Las últimas cuatro solo aparecen con VRCHAT_MCP_WEBSOCKET=1.
Related MCP server: Portals MCP
Instalación
bun link coloca un ejecutable vrchat-mcp en tu PATH, de modo que nada aguas abajo necesita saber
dónde está el checkout.
bun install
bun link # from the repo rootRegístralo por nombre:
claude mcp add vrchat -- vrchat-mcpO, para Claude Desktop, en claude_desktop_config.json:
{
"mcpServers": {
"vrchat": {
"command": "vrchat-mcp"
}
}
}Esa es toda la configuración. Las credenciales provienen del .env del repositorio, así que no hace falta
repetirlas aquí, aunque cualquier cosa que pongas en un bloque env tiene prioridad. Elimina el comando con
bun unlink.
Si prefieres no tocar tu PATH, apunta al archivo de entrada con una ruta absoluta. El servidor se lanza desde un directorio de trabajo arbitrario, así que una ruta relativa no servirá.
claude mcp add vrchat -- bun run /abs/path/to/vrchat-mcp/src/index.tsEl requisito de contacto
VRChat rechaza User-Agents genéricos con un 403. VRCHAT_CONTACT se incorpora al User-Agent
descriptivo que el SDK envía en cada petición, tanto a la API como a WebSocket, y es efectivamente
obligatorio.
El valor tiene que ser real. El SDK rechaza cualquier contacto que contenga @example.com, así que el marcador
obvio es el único valor que garantiza el fallo. El servidor lo notifica como un error de configuración
en la primera llamada a una herramienta, en lugar de dejarlo aparecer como un 403 misterioso.
Configuración
Tres capas, de mayor a menor prioridad. Un proyecto puede definir sus propias opciones sin repetir tus credenciales.
Variables de entorno reales, incluido el bloque
envde un cliente MCP.enven el directorio desde el que se ejecuta el comando, que Bun carga automáticamente.enven la raíz del repositorio
Así, un proyecto que solo quiere herramientas de tienda, usando las credenciales que ya configuraste, necesita una línea junto a las demás:
# ~/my-project/.env
VRCHAT_MCP_TAGS=storeVariable | Valor por defecto | Efecto |
| ninguna | Nombre de usuario o correo de la cuenta |
| ninguna | Contraseña de la cuenta |
| ninguna | Secreto TOTP en base32. Si lo defines, el inicio de sesión nunca pedirá un código |
| ninguna | Cadena de contacto en el User-Agent. Efectivamente obligatorio |
| all | Etiquetas a registrar. |
| off | Crear y editar |
| off | Borrar y moderar. También requiere la puerta de escritura |
| off | Gastar saldo. También requiere la puerta de escritura |
| off | Operaciones de administración. Independiente de la puerta de escritura |
| 20 | Peticiones por segundo. |
| 30000 | Cuánto espera una llamada detrás del limitador antes de rendirse |
| off | Abre el pipeline de eventos y registra las herramientas de eventos |
| conjunto de bajo ruido | Tipos de eventos a los que suscribirse. Reemplaza el valor por defecto; no lo amplía |
| 1000 | Eventos conservados por tipo. Anulaciones por tipo: |
| 30d | Tope de antigüedad. |
|
| Ruta de la base de datos de eventos |
|
| Ruta del archivo de sesión |
| ninguna | Proxy HTTP o HTTPS para el tráfico de API y WebSocket |
| 300000 | Cuánto espera un inicio de sesión en pausa por un código |
| off | Habilita la suite de pruebas en vivo |
Los booleanos aceptan 1 o true, sin distinguir mayúsculas de minúsculas.
Dónde vive el estado
El estado es por proyecto. Ejecuta el servidor dentro de un proyecto y su sesión e historial de eventos viven en
el .vrchat-mcp/ de ese proyecto. La raíz del proyecto se encuentra subiendo desde el directorio de
trabajo en busca de un .git, package.json, deno.json, pyproject.toml o go.mod, de modo que al
lanzar desde un subdirectorio se alcanza el mismo estado en lugar de dejar una segunda sesión varada un nivel más abajo.
El directorio se oculta solo del control de versiones: vrchat-mcp escribe un .gitignore que contiene
* dentro de él al crearlo, así que el archivo de sesión, que es una credencial de autenticación, queda protegido
sin que el proyecto anfitrión necesite una regla para ello.
Por tanto, cada proyecto inicia sesión por separado, y la primera llamada en un proyecto nuevo puede pedir un código 2FA. Para compartir un único inicio de sesión en todas partes, apunta cada instalación al mismo archivo:
VRCHAT_MCP_SESSION=/abs/path/to/shared/session.jsonPuertas de seguridad
El servidor arranca en modo solo lectura. 150 de las 297 operaciones se registran por defecto. Nada que escriba, borre, gaste o modere aparece hasta que tú lo pidas.
Clase | Qué cubre | Requiere | Ejemplos |
| Cada | nada |
|
|
|
|
|
| Cada |
|
|
| Compras, y rutas de Tilia/KYC/pagos |
|
|
| Administración y ciclo de vida de cuentas |
|
|
Destructivo y dinero se superponen a escritura, así que habilitar escritura concede exactamente la capacidad de crear y editar, nunca de borrar ni de gastar. Admin se mantiene independiente y nada lo implica: permitir que un agente edite tu propio contenido nunca debe permitirle también borrar la cuenta.
En qué te estás metiendo:
ALLOW_WRITESpermite que un agente cree y cambie cosas que te pertenecen. Reversible, en su mayoría a mano.ALLOW_DESTRUCTIVE_WRITESañade las llamadas sin deshacer. Borrados, expulsiones, bloqueos, cierre de instancias, borrado de persistencia de usuario.ALLOW_PURCHASESpermite que un agente gaste saldo real.purchaseProductListinges una transacción en vivo. No lo actives porque una lista de herramientas parecía incompleta.ALLOW_ADMINexponedeleteUser, entre otras. La mayoría de estas dan 403 en una cuenta normal, perodeleteUseres la que nunca debe ser un accidente.
Las operaciones con puerta permanecen en la tabla generada de todos modos, de modo que la cobertura sigue siendo 1:1 con la especificación
y la lista de denegación es revisable en el diff. Las anotaciones MCP (readOnlyHint, destructiveHint)
también se establecen, para que los clientes que las muestran puedan avisar.
¿Qué herramientas me faltan?
Una herramienta restringida simplemente no existe, lo que se lee como "VRChat no puede hacer esto" en lugar de "a este servidor se le dijo que no". Ese error ya se ha cometido en la práctica: un agente informó de que la API de economía era de solo lectura cuando las herramientas de escritura existían y simplemente estaban detrás de una bandera.
vrchat_authStatus cierra esa brecha. Informa de cada etiqueta y clase de seguridad, cuántas operaciones contiene cada una, cuántas están expuestas actualmente y el cambio exacto de .env que expondría el resto.
{
"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 ..."
]
}
}Llámalo antes de concluir que algo no es compatible.
Elegir qué herramientas exponer
VRCHAT_MCP_TAGS selecciona las etiquetas. Sin definir, registra todo, y everything lo dice explícitamente, lo cual es más fácil que borrar una clave de una configuración JSON. all y * también funcionan.
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 threeEtiquetas de la especificación: authentication, avatars, calendar, economy, favorites, files, friends, groups, instances, inventory, invite, jams, miscellaneous, notifications, playermoderation, prints, props, users, worlds. Además de store, que añade este servidor.
Una etiqueta que no coincide con nada se avisa en stderr al arrancar y se informa mediante vrchat_authStatus. Sin eso, un error tipográfico como stores no registra ninguna herramienta generada y parece exactamente un servidor roto.
Iniciar sesión
El inicio de sesión es perezoso. Nada se autentica al arrancar, así que tools/list funciona sin credenciales y el servidor sigue siendo inspeccionable. La primera llamada a una herramienta que necesite una sesión dispara el inicio de sesión.
Con VRCHAT_TOTP_SECRET definido, esa es toda la historia. Sin avisos, nunca.
Sin él, VRChat envía un código por correo y la llamada vuelve aparcada en lugar de quedarse colgada:
vrchat__getCurrentUser
-> Login paused: VRChat emailed a code. Ask the user for it, call
vrchat_submitTwoFactorCode { requestId: 'a1b2c3d4', code: '……' },
then retry the original call.Respóndela con vrchat_submitTwoFactorCode y luego reintenta. La sesión persiste, así que esto ocurre una vez por proyecto hasta que caduca.
Iniciar sesión desde una red nueva
Cambiar de proxy, VPN o ISP dispara una comprobación que no es un código de doble factor, y ambos se parecen lo suficiente como para hacer perder tiempo real. VRChat responde con uno de estos:
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 linkAmbos significan lo mismo, y ninguno es lo que parece. El correo contiene un enlace, no un código de seis dígitos, así que vrchat_submitTwoFactorCode no puede ayudar. El inicio de sesión requiere dos rondas:
Una llamada a una herramienta falla con uno de esos mensajes
El usuario abre el enlace del correo
Llama a
vrchat_retryLogin. VRChat envía el código real solo en este segundo intentoEl usuario lee el código en voz alta y llama a
vrchat_submitTwoFactorCodeReintenta la herramienta original
El 429 es un desafío de autenticación disfrazado de estado de límite de velocidad, así que el limitador local lo ignora. Esperar no lo resuelve, y cada intento adicional cuesta una de las ranuras de sesión limitadas de la cuenta, que es lo que produce el 429 en primer lugar. Un inicio de sesión fallido se guarda en caché durante 30 segundos para que una ráfaga de llamadas a herramientas no se convierta en una ráfaga de intentos de inicio de sesión. vrchat_retryLogin limpia esa caché, porque para entonces el usuario ya ha hecho lo que el fallo estaba esperando.
Llamadas paralelas durante el inicio de sesión
Los agentes lanzan herramientas a la vez, y en un arranque en frío todas aterrizan en un cliente no autenticado. Una llamada impulsa el inicio de sesión. Las demás esperan hasta tres segundos y luego devuelven login_pending en lugar de bloquearse, así que un inicio de sesión lento detiene una llamada a una herramienta en lugar de todas, y un inicio de sesión que se aparca en un código plantea un aviso en lugar de varios.
_responseKeys
Toda herramienta acepta _responseKeys, y toda herramienta devuelve la carga útil bruta ascendente por defecto. No hay curación en el servidor, porque una lista de campos seleccionados a mano adivina lo que importa, es incorrecta para quien necesitaba el otro campo, y hay que mantenerla para 297 operaciones contra una especificación que cambia. El agente sabe lo que quiere en esta llamada. Debería decirlo.
Un objeto World ocupa aproximadamente 4 KB. Reducirlo suele recortar más de la mitad.
Patrón | Selecciona |
| toda la carga útil, byte a byte |
| esos campos de nivel superior |
| una ruta anidada |
|
|
| ese campo de cada elemento de |
| todo lo que hay debajo de cada elemento |
| excluye, y se combina con |
La proyección conserva la forma. Los objetos siguen anidados, los arrays mantienen su orden y longitud, así que una ruta aprendida en una llamada sigue funcionando en la siguiente.
El descubrimiento importa más que la proyección. Un agente no puede pedir claves que no sabe que existen, y un resultado vacío en silencio haría este diseño peor que recortar. Así que una ruta que no coincide con nada vuelve como _unmatched, junto con _availableKeys que enumera lo que realmente había. Las claves de elementos de array se nombran como *.id, *.name, la forma que funciona como entrada de _responseKeys.
["*"] devuelve la entrada por referencia, así que la ruta bruta es demostrablemente sin pérdidas y nada queda oculto.
Ver imágenes
vrchat_getImage descarga una imagen de VRChat y la devuelve como bloque de imagen, para que el modelo pueda mirarla en lugar de informar de una URL.
{ "name": "vrchat_getImage",
"arguments": { "url": "https://api.vrchat.cloud/api/1/file/file_.../1/256" } }Pasa cualquier imageUrl o thumbnailImageUrl de un usuario, mundo, avatar, print o producto, o pasa fileId y deja que la herramienta construya la URL. savePath también escribe los bytes en disco.
Prefiere una URL que termine en /256 o /512 cuando exista. La imagen se transporta como base64, así que una textura a tamaño completo cuesta mucho contexto y no aporta detalle extra. Cualquier cosa de más de 4 MB se rechaza; sube maxBytes si de verdad lo quieres.
La herramienta solo obtiene imágenes alojadas en VRChat, y solo api.vrchat.cloud recibe tu cookie de sesión. Una herramienta que obtiene una URL proporcionada por el llamador mientras tiene una sesión es una primitiva de falsificación de solicitudes a menos que esté restringida, y una cookie enviada a un CDN es una cookie regalada.
Subir archivos
Pasa una ruta de archivo local. El servidor se ejecuta en tu máquina y lee el archivo él mismo, así que el contenido del archivo nunca entra en la conversación. Incrustar un PNG de 2 MB como base64 costaría aproximadamente 2,7 MB de argumentos de herramienta, más que todo lo demás de la llamada combinado.
Cuando no hay archivo en disco, por ejemplo una imagen que acaba de producir el agente, el mismo argumento acepta los bytes incrustados:
{ "file": { "data": "iVBORw0KGgo...", "mimeType": "image/png", "filename": "icon.png" } }Una URI data: también funciona en la posición de cadena, así que "file": "data:image/png;base64,iVBORw0..." es equivalente. filename es opcional y se inventa a partir del tipo MIME cuando se omite, porque VRChat rechaza una subida que no puede nombrar. Prefiere una ruta siempre que exista: incrustar cuesta aproximadamente 1,33 bytes de argumento de herramienta por byte de archivo, y eso sale del mismo presupuesto de contexto que todo lo demás.
Ocho operaciones aceptan un archivo directamente, una llamada cada una:
Herramienta | Campo | Para |
|
| Iconos, galería, emoji, pegatinas, imágenes de producto ( |
|
| Prints |
|
| Iconos de perfil |
|
| Galería |
|
| Sustituir la imagen de un print |
|
| Fotos de invitación |
|
| Solicitudes de invitación |
|
| Respuestas de invitación |
{ "name": "vrchat__uploadImage",
"arguments": { "file": "C:/Users/me/Pictures/icon.png", "tag": "icon" } }El resultado nombra los bytes que se enviaron y en qué forma llegaron, que es la única manera de distinguir una subida correcta del archivo correcto de una subida correcta del archivo equivocado:
{ "uploaded": [
{ "field": "file", "name": "icon.png", "bytes": 48211, "type": "image/png", "source": "path" }
],
"result": { "id": "file_...", "name": "icon.png" } }Para todo lo demás, vrchat_uploadFile ejecuta la secuencia de cuatro pasos de VRChat (crear el registro, solicitar una URL prefirmada, transferir los bytes, finalizar) y devuelve el registro de archivo completado. Úsalo para paquetes de assets y unity packages. Los bytes van directamente al proveedor de almacenamiento de VRChat con una solicitud simple, deliberadamente no a través del cliente de API, porque ese cliente adjunta tu cookie de sesión a todo lo que envía y el host de almacenamiento es un tercero.
Las subidas son escrituras, así que todo esto necesita VRCHAT_MCP_ALLOW_WRITES=1. Los archivos tienen un límite de 100 MB, y un archivo vacío se rechaza antes de llegar a VRChat, que de otro modo almacenaría un registro roto. Si vrchat_uploadFile falla a mitad de camino, nombra el registro de archivo que creó, para que puedas inspeccionarlo con vrchat__getFile y eliminarlo con vrchat__deleteFile.
Gestionar una tienda
Gestionar un escaparate es una escritura ordinaria, no una operación de money. Crear un producto, renombrarlo, cambiar su imagen, publicar o despublicar un listado: nada de esto gasta ni gana nada, así que solo necesita VRCHAT_MCP_ALLOW_WRITES=1. La puerta de money es para comprar y para el procesador de pagos.
VRCHAT_MCP_TAGS=store
VRCHAT_MCP_ALLOW_WRITES=1Establecer la imagen de un producto lleva una llamada:
{ "name": "vrchat_setProductImage",
"arguments": { "productId": "prod_...", "file": "/abs/path/cover.png" } }Eso sube con tag: "product" y adjunta el id de archivo devuelto como imageId del producto. A mano es vrchat__uploadImage con tag: "product" o "listinggallery", y luego vrchat__updateProduct con el id que devuelve.
Una cosa que VRChat mismo no permite: un listado solo expone active para editar, así que su precio, título y descripción no se pueden cambiar después de la creación. Elimina el listado y crea uno nuevo. El nombre, la descripción y la imagen viven en el producto y se pueden editar mediante vrchat__updateProduct.
Paginación
Una página por llamada. Las herramientas paginadas devuelven por defecto 25 resultados y repiten un nextOffset para continuar. No hay bucle de paginación interno, deliberadamente: una auto-paginación oculta quemaría el presupuesto de solicitudes y una gran porción de contexto dentro de lo que al agente le parece una sola llamada.
Una página corta significa el final. VRChat no informa de un total, así que esa es la única señal fiable.
Eventos WebSocket
Desactivado por defecto, porque un socket siempre activo en reposo quema una ranura de sesión. Define VRCHAT_MCP_WEBSOCKET=1 para abrirlo y registrar las cuatro herramientas vrchat_events*.
VRCHAT_MCP_WS_EVENTS elige a qué tipos suscribirse, reemplazando en lugar de ampliando el conjunto predeterminado de notification, notification-v2, economy-update, friend-online, friend-offline e instance-queue-ready.
Los mensajes de pipeline están doblemente codificados: el campo content es JSON serializado que necesita un segundo análisis, excepto see-notification y hide-notification, que llevan ids simples. Todo eso se normaliza una vez en la ingesta, así que ninguna herramienta te entrega jamás una cadena JSON dentro de JSON. El socket propio del SDK descarta silenciosamente esos dos tipos de mensaje, que es una de las razones por las que este servidor no lo usa. La otra es que no acepta proxy.
La retención es por tipo
El historial va a SQLite en .vrchat-mcp/events.db, y conserva 1000 eventos por tipo de evento, no 1000 en total. Un tipo locuaz como friend-location nunca puede expulsar a uno raro y valioso como economy-update, cosa que un límite global único haría en cuestión de minutos.
VRCHAT_MCP_HISTORY=1000,friend-location:200,economy-update:5000
VRCHAT_MCP_HISTORY_MAX_AGE=7dUn tope de antigüedad funciona junto al tope de recuento, y el que muerde primero gana. Solo el recuento permite que un tipo que se dispara raramente conserve eventos de hace meses que se leen como actuales. Solo la antigüedad permite que una ráfaga haga explotar la base de datos. vrchat_eventsStatus informa de qué límite está activo actualmente, por tipo, para que la ventana sea legible en lugar de silenciosa.
El historial sobrevive a los reinicios, así que vrchat_eventsSearch puede responder qué pasó mientras estabas ausente. Un buffer solo en vivo no puede.
Proxy
VRCHAT_MCP_PROXY enruta el tráfico a través de un proxy HTTP o HTTPS, con credenciales opcionales user:pass@.
VRCHAT_MCP_PROXY=http://127.0.0.1:8080
VRCHAT_MCP_PROXY=https://user:pass@proxy.internal:8443SOCKS no es compatible. El fetch de Bun rechaza socks5:// directamente, por lo que una URL SOCKS falla al inicio con un error de configuración que menciona la limitación en lugar de funcionar a medias. En su lugar, colócalo detrás de un proxy HTTP local.
El proxy cubre tanto el tráfico de API como el de WebSocket. Ambos pasan por mecanismos diferentes, y el modo de fallo de hacer solo la mitad bien es un servidor que parece estar proxy mientras filtra su IP real en el flujo de eventos.
Si no se puede alcanzar el proxy, las llamadas fallan con un error claro. El servidor nunca recurre silenciosamente a una conexión directa, porque para cualquiera que use esto para separación de IP, ese es el peor resultado posible. La URL del proxy nunca se registra, ya que puede contener credenciales.
Desarrollo
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 obtiene vrchatapi/specification en main, lo agrupa y escribe la especificación agrupada más spec/VERSION.json (SHA ascendente, marca de tiempo, hash de contenido) junto con el src/generated/operations.ts regenerado. Ambos se confirman, por lo que cada regeneración produce dos diffs revisables: el cambio de especificación y el cambio de herramienta que causó, y una confirmación ascendente mala es reversible en lugar de ser una carga. --offline reproduce la salida de la instantánea confirmada byte por byte sin red alguna.
src/generated/operations.ts se genera. No lo edites a mano.
Diez operationIds no tienen un método correspondiente en el SDK de VRChat, porque la especificación avanza más rápido que la biblioteca del cliente. Esos se enrutan a través de un respaldo de solicitud sin procesar en el mismo cliente, por lo que las cookies, el User-Agent, el proxy y la limitación de velocidad siguen aplicándose, y la cobertura 1:1 sigue siendo cierta en lugar de convertirse silenciosamente en una mentira. Codegen imprime la lista en cada ejecución.
stdout es el canal JSON-RPC. Todo el registro va a stderr, y un console.log perdido corrompe el flujo del protocolo.
Pruebas
bun test es la suite sin conexión: salida de codegen, compuertas, el limitador de velocidad contra un reloj falso, retención y búsqueda de historial, proyección, mapeo de errores, manejo de rutas de carga. Sin red, sin credenciales, sin cuenta. Esto es lo que se ejecuta por defecto.
bun run test:live accede a una cuenta real, activado con VRCHAT_LIVE_TESTS=1 y omitido de lo contrario. Reglas a las que se atiene:
Solo lecturas y escrituras propiedad del creador. Se niega rotundamente a cualquier cosa clasificada como
moneyoadmin, antes incluso de construir un cliente. Una suite de pruebas no debe poder gastar dinero.Cada escritura se limpia a sí misma y está etiquetada para que los artefactos sueltos sean identificables en el juego.
Se enruta a través del mismo limitador que la producción y se mantiene pequeño. Una ejecución que active la limitación de VRChat es peor que ninguna ejecución.
Las afirmaciones se basan en la forma y el estado, nunca en contenido volátil. Los recuentos de amigos y los listados de mundos cambian entre ejecuciones.
Usa una cuenta dedicada cuando puedas. Las credenciales provienen solo de
.env.
Seguridad
.envy.vrchat-mcp/están en gitignore, y.vrchat-mcp/también se ignora a sí mismo desde dentro para permanecer oculto dentro de otros proyectos..vrchat-mcp/session.jsones una credencial de autenticación, una cookie de sesión válida. Trátala como una contraseña. Eliminarla, o llamar avrchat_logout, fuerza un nuevo inicio de sesión.Los códigos 2FA, contraseñas, secretos TOTP y URLs de proxy nunca se registran, incluso en stderr.
Tu cookie de sesión va a
api.vrchat.cloudy a ningún otro lugar. Las subidas al proveedor de almacenamiento de VRChat y las descargas de imágenes desde su CDN omiten deliberadamente el cliente autenticado.Los errores vuelven como resultados estructurados que llevan estado, el mensaje propio de VRChat y una pista accionable. Las excepciones sin procesar y los seguimientos de pila nunca llegan a la transcripción.
Solo stdio, solo local. Sin transporte HTTP, sin aislamiento de credenciales multiusuario. Este servidor es para una cuenta en una máquina.
Estructura del proyecto
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 behaviourLicencia
Ver 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