Qué es esto
margin-demo es una prueba concreta de una idea: que un agente de IA use herramientas ejecutables publicadas en un sitio, sin instalar un cliente MCP — ni configuración, ni proceso local, ni handshake de protocolo. Todo el sitio (editor, tools, manifiesto) es HTML/JS estático servido por GitHub Pages, sin backend, sin base de datos.
La arquitectura: mcpwasm sin cliente
Esto usa el patrón llms-txt-skills: un origen publica un
manifiesto (/llms.txt)
que declara sus tools, la ruta de su código, y el hash SHA-256 de ese código.
Un "skill" es literalmente un archivo .js que llama
registerTool({ name, description, inputSchema, handler }) por
cada tool que expone.
El loader (browser-eval-client.js)
hace todo el trabajo, en 4 pasos, sin ningún cliente MCP de por medio:
- Hace
fetcha/llms.txty lee el manifiesto. - Hace
fetchaltool.jsque el manifiesto declara. - Calcula su SHA-256 y lo compara contra el hash pinneado en el manifiesto — si no coincide, se niega a ejecutar.
- Corre el código dentro de un Web Worker con
fetch/XMLHttpRequest/WebSocketdeshabilitados a mano — el código de la tool no tiene forma de alcanzar la red salvo un canal explícito y acotado (host.fetchOrigin, no usado por este skill en particular).
Una vez cargado, llamar una tool es una llamada local
(skill.call('create_document', {...})) — sin protocolo, sin
JSON-RPC, sin tools/list. El código corre en tu propio proceso
(o en el del agente), no en un servidor.
Las tools de este skill
Definidas en tool.js,
sin ninguna dependencia externa (ni siquiera atob/TextEncoder — el
codec base64url+UTF-8 está escrito a mano para correr igual en cualquier sandbox):
create_document({ title, content })→{ url }— codifica el documento en el fragmento#d=de una URL.decode_document({ url })→{ title, content }— la operación inversa.
No hay una tercera tool de "guardar". El documento nunca se persiste en ningún lado — la URL es el documento. Abrirla en cualquier navegador, en cualquier momento, reconstruye el contenido exacto, client-side, sin pedirle nada a ningún servidor.
El problema real que apareció: descubrimiento
Publicar el skill correctamente no alcanza para que un agente lo encuentre. En la primera prueba, le dimos la URL a Codex sin ninguna pista — la trató como una página web cualquiera. Recién al tercer mensaje, empujándolo explícitamente, hizo algo parecido a "usar el sitio" — y lo hizo manejando el DOM como un humano (tipeando en el textarea), no llamando a las tools reales.
Se agregaron tres capas para resolverlo, cada una más explícita que la anterior:
- Una sección visible en la propia página ("🤖 Para agentes") con instrucciones y el snippet de código.
- Un archivo
/agent-setup/prompt.md— mismo patrón que usa Cloudflare en developers.cloudflare.com: instrucciones imperativas, pensadas para que un agente las ejecute, no las resuma. - Un botón "Copiar para agente" que copia al portapapeles: "Fetch and execute the appropriate instructions to use margin-demo's tools from .../agent-setup/prompt.md" — el humano lo pega como su propio mensaje.
Con las tres capas puestas, se volvió a probar con Codex: a la primera,
sin pistas adicionales, entendió el mecanismo, llamó create_document,
y generó un documento real. En una prueba posterior le pedimos que editara
ese documento — decodificó la URL con decode_document, modificó
solo lo pedido, y re-codificó con create_document: un ciclo
completo de lectura-modificación-escritura usando las tools, sin backend,
sin cliente MCP, iniciado con un prompt de una línea.
Lo que esto no resuelve
- El descubrimiento no es automático. Ni con el manifiesto bien formado un agente genérico lo encuentra solo — hace falta empujarlo (una instrucción explícita, un prompt copiado). Esto no es un problema técnico del mecanismo, es un problema de qué hábitos de exploración tiene el harness del agente.
- Sin backend no hay persistencia real ni revocación. El link no expira, no se puede borrar un documento puntual — solo apagando todo el sitio, lo que rompe todos los links a la vez.
- El sandbox del Worker no es un boundary de seguridad duro — a diferencia del sandbox WASM real de
@rckflr/mcpwasm, esto es suficiente para "sin red ambiental", no para código genuinamente hostil.
Recursos
- Editor en vivo: /
- Manifiesto: /llms.txt
- Código de la tool: /skills/margin-demo/tool.js
- Loader (browser): /skills/margin-demo/browser-eval-client.js
- Loader (Node): /skills/margin-demo/direct-eval-client.mjs
- Instrucciones para agentes: /agent-setup/prompt.md
- Repo: github.com/MauricioPerera/mcpwasm-pages-test