Agrega metadata tracking de browsers (userAgent, URL, hostname, idioma, resolucion, timestamp) y tool browser-info para consultarla.
217 lines
9.3 KiB
Markdown
217 lines
9.3 KiB
Markdown
# WebMCP - Fork Nucleo Rio Frio
|
|
|
|
> **IMPORTANTE: Este es un fork modificado de [@jason.today/webmcp](https://github.com/jasonjmcghee/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` | Sí | string | Nombre de la herramienta que Claude verá |
|
|
| `descripcion` | Sí | string | Qué hace la herramienta (Claude lee esto para decidir cuándo usarla) |
|
|
| `codigo` | Sí | 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
|
|
|
|
```bash
|
|
npm install git+https://gitea.nucleoriofrio.com/nucleo000/webmcp.git
|
|
```
|
|
|
|
## Uso
|
|
|
|
### En tu HTML
|
|
|
|
```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 u otro cliente)
|
|
|
|
En `.claude/settings.json` o settings del proyecto:
|
|
|
|
```json
|
|
{
|
|
"mcpServers": {
|
|
"webmcp": {
|
|
"command": "node",
|
|
"args": ["node_modules/@nucleoriofrio/webmcp/src/websocket-server.js", "--mcp"]
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### 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**
|
|
```json
|
|
{
|
|
"mcpServers": {
|
|
"webmcp": {
|
|
"command": "node",
|
|
"args": ["node_modules/@nucleoriofrio/webmcp/src/websocket-server.js", "--mcp", "--dev"]
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
**Opción 2: Variable de entorno**
|
|
```bash
|
|
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
|
|
|
|
- **Repositorio original:** https://github.com/jasonjmcghee/webmcp
|
|
- **npm (original):** https://www.npmjs.com/package/@jason.today/webmcp
|
|
- **Versión base:** 0.1.13
|
|
- **Licencia:** MIT (sin cambios)
|