josedario87 8b2253355f Debounce en notificaciones list_changed al registrar tools/prompts/resources
Cuando un browser se conecta y registra N tools de golpe, se enviaban
N notificaciones tools/list_changed en rapida sucesion. Claude Code
las ignoraba y no veia las herramientas hasta el siguiente cambio.
Ahora se agrupan con debounce de 500ms: una sola notificacion al final.
2026-02-13 02:15:00 -06:00

WebMCP - Fork Nucleo Rio Frio

IMPORTANTE: Este es un fork modificado de @jason.today/webmcp v0.1.13, renombrado a @nucleoriofrio/webmcp. La documentación original, diagramas de arquitectura y explicaciones detalladas del protocolo se encuentran en el repositorio upstream. Las APIs base deberían ser idénticas — si encontrás discrepancias entre este fork y la documentación original, reportalo porque se supone que deben ser compatibles salvo por los parches descritos abajo.

Qué es WebMCP

WebMCP permite que una página web actúe como un servidor MCP (Model Context Protocol). Un agente LLM (Claude Code, Cursor, etc.) puede ejecutar herramientas, leer recursos y usar prompts que corren directamente en el navegador del usuario.

La comunicación funciona así:

Agente LLM <-> MCP Server (localhost) <-> WebSocket Server <-> Navegador del usuario

El navegador expone herramientas (funciones JS) que el agente puede invocar remotamente. Las herramientas tienen acceso completo al DOM, APIs del browser, y todo lo que JavaScript puede hacer en una página web.

Qué cambia este fork

Este fork agrega registro dinámico de herramientas desde el agente, algo que la versión original no soporta. En la versión original, las herramientas se registran únicamente desde la página web. En este fork, el agente puede crear y eliminar herramientas en tiempo real sin tocar el código de la página.

Parches aplicados

3 archivos modificados: src/server.js, src/webmcp.js, src/websocket-server.js

1. agregar-tool — Registro dinámico de herramientas (solo modo dev)

Tool built-in _webmcp_agregar-tool que permite al agente registrar herramientas nuevas en el navegador en tiempo real. Solo disponible en modo desarrollo (--dev).

Parámetros:

Param Requerido Tipo Descripción
nombre string Nombre de la herramienta que Claude verá
descripcion string Qué hace la herramienta (Claude lee esto para decidir cuándo usarla)
codigo string Body de una función JS. Recibe args como parámetro. Debe retornar un string.
parametros No string JSON string con las properties del inputSchema

Flujo de ejecución:

Agente envía nombre + descripcion + codigo + parametros
  → server.js valida y reenvía al WebSocket Server
    → websocket-server.js busca el primer navegador conectado
      → navegador recibe el mensaje 'createTool'
        → webmcp.js ejecuta new Function('args', codigo) para compilar el código
        → webmcp.js llama registerTool() para registrar la herramienta
      → respuesta 'toolResponse' viaja de vuelta
    → websocket-server.js enruta la respuesta al MCP server
  → server.js llama sendToolListChanged()
→ Claude ahora puede usar la nueva herramienta

El código se ejecuta en el contexto del navegador, con acceso a document, window, fetch(), localStorage, navigator, y todas las APIs web. Solo tiene acceso al scope global (no a closures/variables locales de la página, salvo que estén en window).

2. quitar-tool — Eliminación de herramientas (solo modo dev)

Tool built-in _webmcp_quitar-tool con tres modos de operación. Solo disponible en modo desarrollo (--dev).

Parámetros (todos opcionales, pero debe usarse al menos uno):

Param Tipo Efecto
listar boolean Si true, lista las herramientas activas sin borrar nada
nombre string Nombre de la herramienta específica a eliminar
todas boolean Si true, elimina todas las herramientas de una vez

Comportamiento por modo:

  • listar: true — Se resuelve en websocket-server.js leyendo el toolsRegistry. No toca el navegador. Retorna "Herramientas activas: tool1, tool2".
  • nombre: "x" — Busca en toolsRegistry por nombre, la borra, y envía removeTool al navegador correspondiente para que sincronice su estado local.
  • todas: true — Borra todo el toolsRegistry, envía removeAllTools a todos los navegadores conectados, y retorna "N herramientas desregistradas".

En los tres casos, después de resolver se llama sendToolListChanged() para que Claude actualice su lista.

3. browser-info — Información de navegadores conectados

Tool built-in _webmcp_browser-info que muestra metadata de todos los navegadores conectados al servidor. Siempre disponible (no requiere --dev).

No recibe parámetros. Retorna un JSON array con la info de cada navegador:

Campo Descripción
channel Canal WebSocket al que está conectado
userAgent User agent del navegador
url URL completa de la página
hostname Hostname de la página
language Idioma del navegador
screenWidth Ancho de la ventana (px)
screenHeight Alto de la ventana (px)
connectedSince Timestamp de cuando se conectó

Flujo: El navegador envía su clientInfo automáticamente al conectarse (en el welcome). El servidor almacena esta metadata en un Map. Cuando el agente llama browser-info, el server recopila la info de todos los clientes conectados y la retorna.

Si no hay navegadores conectados, retorna "No hay navegadores conectados".

4. Eliminación de define-mcp-tool

Se eliminó la built-in _webmcp_define-mcp-tool del upstream por no tener utilidad real en este fork.

5. Manejo de mensajes nuevos en el cliente web (webmcp.js)

  • createTool — recibe la definición de herramienta del server, la compila y registra localmente
  • removeTool — elimina una herramienta específica del registro local
  • removeAllTools — limpia todas las herramientas del registro local
  • clipboardCopy — permite copiar texto al portapapeles del usuario (usado para tokens)
  • clientInfo — envía metadata del navegador al servidor al conectarse (automático en welcome)
  • getClientInfo — responde con metadata actualizada del navegador cuando el server la solicita

6. Ruteo en WebSocket Server (websocket-server.js)

  • handleCreateTool() — recibe la petición del MCP server, encuentra un navegador conectado y le reenvía la instrucción de crear la herramienta
  • handleRemoveTool() — maneja listar/eliminar herramientas, sincroniza entre el registry del server y los navegadores conectados
  • handleClientInfo() — almacena la metadata del navegador en clientMetadata al conectarse
  • handleGetClientInfo() — recopila metadata de todos los navegadores conectados y responde al MCP server

Instalación

npm install @nucleoriofrio/webmcp@git+https://gitea.nucleoriofrio.com/nucleo000/webmcp.git

Esto genera en tu package.json:

"@nucleoriofrio/webmcp": "git+https://gitea.nucleoriofrio.com/nucleo000/webmcp.git"

IMPORTANTE: La dependencia debe declararse como @nucleoriofrio/webmcp, NO como @jason.today/webmcp. Si usás el nombre del paquete original, npm lo instala en node_modules/@jason.today/webmcp/ y genera confusión con el upstream. El nombre correcto es @nucleoriofrio/webmcp y se instala en node_modules/@nucleoriofrio/webmcp/.

Uso

En tu HTML

<script src="node_modules/@nucleoriofrio/webmcp/src/webmcp.js"></script>
<script>
    const webmcp = new WebMCP({
        color: '#00d4ff',
        inactivityTimeout: 30 * 60 * 1000
    });

    // Registrar herramientas desde la página (igual que upstream)
    webmcp.registerTool('mi-tool', 'Hace algo', {
        type: 'object',
        properties: {
            param: { type: 'string', description: 'Un parametro' }
        }
    }, function(args) {
        // Tiene acceso completo al DOM y APIs del browser
        return 'Resultado: ' + args.param;
    });
</script>

Configuración MCP (Claude Code, Claude Desktop u otro cliente)

En el archivo de configuración MCP de tu cliente (settings.json, claude_desktop_config.json, .mcp.json, etc.):

{
    "mcpServers": {
        "webmcp": {
            "command": "node",
            "args": ["/ruta/a/tu/proyecto/node_modules/@nucleoriofrio/webmcp/src/websocket-server.js", "--mcp"]
        }
    }
}

Reemplazá /ruta/a/tu/proyecto/ con la ruta absoluta a tu proyecto. En Windows usá barras dobles: C:\\Users\\...\\node_modules\\@nucleoriofrio\\webmcp\\src\\websocket-server.js.

Modo desarrollo

Las tools agregar-tool y quitar-tool solo están disponibles en modo desarrollo. Para activarlo:

Opción 1: Flag de línea de comandos

{
    "mcpServers": {
        "webmcp": {
            "command": "node",
            "args": ["/ruta/a/tu/proyecto/node_modules/@nucleoriofrio/webmcp/src/websocket-server.js", "--mcp", "--dev"]
        }
    }
}

Opción 2: Variable de entorno

WEBMCP_DEV=true node src/websocket-server.js --mcp

Cuando el modo dev está activo, el servidor muestra una advertencia al iniciar:

[DEV] Modo desarrollo activo — agregar-tool y quitar-tool habilitados

En producción (sin --dev), estas tools no aparecen en el listado de herramientas y si se intentan llamar directamente retornan un error.

Flujo de conexión

  1. El agente ejecuta get-token para generar un token de conexión
  2. El usuario pega el token en el widget azul (esquina inferior derecha de la página)
  3. La página se conecta al WebSocket server y registra sus herramientas
  4. El agente puede usar las herramientas de la página y crear nuevas dinámicamente con agregar-tool

Crear herramientas dinámicas desde el agente (requiere --dev)

Con este fork, el agente puede crear herramientas sin modificar el HTML:

agregar-tool:
  nombre: "mi-nueva-tool"
  descripcion: "Que hace"
  codigo: "return document.title;"
  parametros: '{"param1":{"type":"string","description":"algo"}}'

El código JavaScript recibe args como parámetro y debe retornar un string. Se ejecuta en el contexto del navegador, con acceso a document, window, navigator, fetch, WebAssembly, canvas, y todas las APIs web.

Referencia upstream

Description
Fork de @jason.today/webmcp con parches Nucleo: registro dinamico, clipboard, clear-cache y agregar-tool
Readme MIT 5.3 MiB
Languages
JavaScript 100%