Skip to main content
Glama

emptysock-mcp

Servidor de Model Context Protocol para el motor de juegos EmptySock. Expone los sistemas del motor — NavMesh, Physics, Scene, Save y Actor — como herramientas MCP consumibles por Claude Desktop, agentes de IA y la API de Claude.


Requisitos

  • Node.js 20+

  • npm 9+


Related MCP server: Hayba

Instalación

git clone https://github.com/eleferrets/emptysock-mcp.git
cd emptysock-mcp
npm install
npm run build

Configuración

Copia el archivo de entorno de ejemplo y completa los valores que necesites:

cp .env.example .env

Variable

Requerido

Descripción

EMPTYSOCK_API_TOKEN

No

Token Bearer para llamadas autenticadas a la API del motor

MCP_AUTH_TOKEN

No

Token Bearer requerido en las peticiones de transporte SSE. Déjalo vacío para desactivar la autenticación.

SAVE_BASE_DIR

No

Ruta absoluta que las herramientas de guardado pueden leer/escribir. Por defecto, el directorio de trabajo del proceso. Establécelo explícitamente en producción.

Nunca hagas commit de .env — está en gitignore. Guarda los secretos en el gestor de secretos de tu CI/CD, no en el repositorio.


Ejecutar el servidor

stdio (recomendado para uso local y Claude Desktop)

npm run dev          # development — tsx, no build step
# or after building:
node dist/server.js

El servidor se comunica a través de stdin/stdout. No hay ningún puerto de red ni superficie de autenticación.

Claude Desktop

Añade el servidor a la configuración de Claude Desktop (~/Library/Application Support/Claude/claude_desktop_config.json en macOS):

{
  "mcpServers": {
    "emptysock": {
      "command": "node",
      "args": ["/absolute/path/to/emptysock-mcp/dist/server.js"],
      "env": {
        "SAVE_BASE_DIR": "/absolute/path/to/your/saves"
      }
    }
  }
}

Reinicia Claude Desktop. Las herramientas de EmptySock aparecerán en el selector de herramientas.


Herramientas disponibles

NavMesh

Herramienta

Descripción

navmesh_find_path

Ruta A* entre dos puntos del mundo 2D en una navmesh cargada. Devuelve waypoints ordenados o [] si no existe ninguna ruta.

navmesh_nearest_node

Nodo de navmesh transitable más cercano a un punto del mundo dado.

Ejemplo — encontrar ruta:

{
  "from": { "x": 0, "y": 0 },
  "to":   { "x": 100, "y": 50 },
  "mapId": "level1"
}

Physics

Herramienta

Descripción

physics_raycast_2d

Lanza un rayo en el espacio de física 2D; devuelve la primera entidad impactada, el punto de impacto y la normal.

physics_raycast_3d

Lanza un rayo en el espacio de física 3D (Rapier3D); devuelve el primer impacto.

physics_overlap_circle

Todos los IDs de entidad cuyos colisionadores 2D se superponen con un círculo.

physics_body_state

Posición, velocidad y velocidad angular actuales de un cuerpo de física según el ID de entidad.

Ejemplo — solapamiento de círculo:

{
  "center": { "x": 50, "y": 50 },
  "radius": 20,
  "layerMask": 3
}

Scene

Herramienta

Descripción

scene_list_entities

Todos los IDs de entidad activos en una escena.

scene_entity_info

Etiqueta, estado activo y lista de componentes de una entidad específica.

scene_get_component

Estado serializado de un componente específico en una entidad.

Ejemplo — obtener componente:

{
  "sceneId": "gameplay",
  "entityId": "player-001",
  "componentType": "Transform"
}

Save

Todas las herramientas de guardado están restringidas a SAVE_BASE_DIR. El path traversal (.., rutas absolutas) se rechaza en la capa de esquema y de nuevo en el momento de la resolución.

Herramienta

Descripción

save_read

Lee una ranura de guardado del disco y devuelve sus datos JSON.

save_write

Escribe un objeto JSON en una ranura de guardado con nombre.

save_delete

Elimina una ranura de guardado.

save_list

Lista todas las ranuras de guardado disponibles.

Ejemplo — escribir:

{
  "slot": "autosave",
  "data": { "level": 3, "score": 4200, "checkpoint": "bridge" }
}

Los nombres de las ranuras solo pueden contener caracteres alfanuméricos, guiones y guiones bajos (p. ej. slot1, autosave, new-game-plus).


Actor

Herramienta

Descripción

actor_send_message

Pone un mensaje en la cola de la bandeja de entrada de un actor específico. Se procesa en el siguiente vaciado de ActorSystem.

actor_broadcast

Transmite un mensaje a todos los actores registrados.

actor_inbox_size

Número de mensajes pendientes en la bandeja de entrada de un actor.

Ejemplo — enviar mensaje:

{
  "actorId": "enemy-spawner",
  "message": { "type": "SPAWN_WAVE", "payload": { "wave": 3 } }
}

Nota sobre el orden: ActorSystem vacía la bandeja de entrada de todos los actores antes de llamar a update(). Los mensajes enviados durante el frame N se procesan antes de que se ejecute la lógica de actualización del frame N.


Desarrollo

npm run lint        # TypeScript type-check (no emit)
npm test            # run Vitest suite
npm run test:watch  # watch mode

Los tests se encuentran en src/tests/. Cubren la validación de entrada, el despacho de herramientas y los invariantes de seguridad (path traversal, inyección de metacaracteres de shell, nombres de herramientas desconocidos).


Cómo añadir una herramienta

  1. Crea src/tools/<domain>.ts — exporta una entrada de array toolDef y una función handler.

  2. Registra ambas en src/tools/index.ts mediante la llamada a register() en buildRegistry().

  3. Añade una entrada a api-reference.json en emptysock-engine.

  4. Añade un archivo de skill a eleferrets/emptysock-ai-skills.

Usa los helpers compartidos en src/lib/:

  • parse(schema, raw) — parse de Zod que lanza McpError(InvalidParams) al fallar

  • SafeRelPath, SafeId, Vec2, Vec3, GameNum — esquemas Zod reutilizables

  • textResponse(data) — construye la respuesta estándar de contenido de texto de MCP

  • wrapError(err) — escribe en stderr y vuelve a lanzar como McpError(InternalError)


Modelo de seguridad

Riesgo

Mitigación

Argumentos malformados

Zod safeParse en cada entrada; se devuelve McpError(InvalidParams) al fallar

Path traversal

Esquema SafeRelPath + comprobación de contención con path.resolve en el manejador de guardado

Inyección de shell

Sin exec() con plantillas de cadena; execFile con arrays de argv cuando se necesiten subprocesos

Fuga de credenciales

Secretos solo desde process.env; las trazas de pila se registran en stderr, nunca al cliente

Entradas demasiado grandes

Longitudes de cadena limitadas en cada campo del esquema

Herramientas desconocidas

McpError(MethodNotFound) — sin reenvío a manejadores no previstos

Available Tools

21 tools
actor_broadcastB

Broadcast a message to all registered actors in the current ActorSystem.

Inputs: message (required).

actor_inbox_sizeB

Return the number of pending messages in an actor's inbox.

Inputs: actorId (required).

actor_send_messageA

Enqueue a message in a specific actor's inbox. The actor processes it on the next flush pass.

Inputs: actorId (required), message (required).

emptysock_layer_infoA

Return reference documentation for the EmptySock LayerSystem API: defineLayer, addToLayer, setVisible, setParallax, and RenderSystem integration.

Inputs: no named parameters.

gms2_inspect_projectA

Read a GameMaker Studio 2 .yyp project file and return a JSON summary: project name, asset counts by type, and lists of object and script names. Read-only — does not modify any files.

Inputs: yypPath (required).

particle_emitter_configA

Get or set a ParticleSystem emitter configuration by emitter ID. Omit config to read; provide config to write.

Inputs: emitterId (required), config.

physics_body_stateA

Return the current position, velocity, and angular velocity of a physics body by entity ID.

Inputs: entityId (required).

physics_overlap_circleB

Return all entity IDs whose 2D colliders overlap a circle.

Inputs: center (required), radius (required), layerMask.

physics_raycast_2dB

Cast a ray in 2D physics space and return the first hit entity, hit point, and normal.

Inputs: origin (required), direction (required), maxDistance (required), layerMask.

physics_raycast_3dC

Cast a ray in 3D physics space (Rapier3D) and return the first hit.

Inputs: origin (required), direction (required), maxDistance (required), layerMask.

save_deleteA

Delete a save slot from disk.

Inputs: slot (required).

save_listA

List all available save slots.

Inputs: subdir.

save_readA

Read a save slot from disk and return its JSON data.

Inputs: slot (required).

save_writeA

Write JSON data to a save slot on disk.

Inputs: data (required), slot (required).

scene_create_entityC

Add a new entity to a scene. Returns the new entity's ID.

Inputs: sceneId (required), tag, components.

scene_entity_infoC

Return the tag, active state, and component list for a specific entity.

Inputs: sceneId (required), entityId (required).

scene_get_componentB

Retrieve the serialised state of a specific component on an entity.

Inputs: sceneId (required), entityId (required), componentType (required).

scene_list_entitiesB

List all entity IDs currently active in a scene.

Inputs: sceneId (required).

story_graph_exportA

Export the Story Graph (VNSystem) for a named scene as a JSON object containing nodes and edges.

Inputs: sceneId (required), graphId.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    B3.4/5.0

    Scored across 21 tools

    Disambiguation5/5

    Tools are clearly separated by domain (navmesh, physics, scene, save, actor, etc.) and each tool targets a distinct action or query. Even within physics, 2D and 3D raycasts are explicitly differentiated. No two tools appear to do the same thing.

    Naming Consistency5/5

    All tools follow a consistent domain_verb_noun pattern (e.g., scene_create_entity, save_list, actor_send_message). Suffixes like _2d and _3d are uniform, and the one odd name (emptysock_layer_info) still adheres to the same style. Naming is predictable and coherent.

    Tool Count3/5

    With 21 tools, the count falls in the 16-25 range, which is borderline heavy. However, the server covers many distinct subsystems, so each tool arguably earns its place, but the overall number feels slightly excessive for a single MCP server.

    Completeness3/5

    The set covers core read/query operations across multiple domains, but there are notable gaps: scene entities can be created and inspected but not updated or deleted, physics only offers queries (no manipulation), and particle control is limited to configuration. This leaves some lifecycle operations incomplete.

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      D
      maintenance
      Enables LLM-driven text game state management by exposing MCP tools for managing players, locations, items, entities, and abstract concepts.
      MIT
    • A
      license
      Not graded
      quality
      B
      maintenance
      An MCP server enabling AI agents to author Unreal Engine 5 scenes directly, with tools for spawning actors, building PCG graphs, validating physics, generating terrain, and more through a single MCP connection.
      13
      MIT
    • A
      license
      Not graded
      quality
      D
      maintenance
      Connects Claude Code to the Unity Editor via MCP, enabling AI-driven control of scenes, assets, components, UI, animations, and more through 91 tools.
      2
      MIT
    • A
      license
      C
      quality
      C
      maintenance
      Enables AI-driven game development by providing MCP tools to interact with the Godot editor, including scene editing, node manipulation, script attachment, and scene execution.
      28
      14 npm
      MIT