Layven
Unidad compartida para tus agentes y compañeros de equipo.
Documentación
Servidor MCP de Layven
Layven es un disco compartido que tus agentes montan sobre MCP. Cada escritura tiene versión, cada acción se atribuye al agente que la realizó, y cualquier cosa se puede revertir.
Un bloque de configuración, sin cambios en el código del agente. Alojado en https://api.layven.io/mcp.
Documenta el servidor MCP de Layven 1.0.2.
Inicio rápido
claude mcp add --transport http layven https://api.layven.io/mcp --header "Authorization: Bearer agd_your_agent_token"
- Obtén un token en layven.io: abre la consola, ve a Agents, crea uno. El secreto se muestra una sola vez.
- Reinicia tu cliente.
- Pregunta a tu agente: "lista mis espacios de trabajo de Layven".
El punto del producto se muestra en la segunda conexión. Crea un segundo token, conecta una herramienta diferente con él, y haz que esa herramienta lea el archivo que el primero acaba de escribir. Ambos agentes ven el mismo disco, y el feed de actividad dice quién hizo qué. Tutorial: examples/two-agent-handoff.md.
Conecta tu cliente
Claude Code
claude mcp add --transport http layven https://api.layven.io/mcp --header "Authorization: Bearer agd_your_agent_token"
Conector personalizado de Claude.ai
Pega https://api.layven.io/mcp y autentícate con OAuth. Esa interfaz no tiene campo de encabezado personalizado, por eso existe OAuth.
ChatGPT
Igual que Claude.ai: pega https://api.layven.io/mcp y autentícate con OAuth.
Cursor (~/.cursor/mcp.json)
{
"mcpServers": {
"layven": {
"url": "https://api.layven.io/mcp",
"headers": {
"Authorization": "Bearer agd_your_agent_token"
}
}
}
}
Codex (~/.codex/config.toml)
[mcp_servers.layven]
url = "https://api.layven.io/mcp"
http_headers = { "Authorization" = "Bearer agd_your_agent_token" }
Gemini (~/.gemini/settings.json)
Mismo JSON que Cursor, pero la clave es httpUrl en lugar de url, porque Gemini lee url como un endpoint SSE.
{
"mcpServers": {
"layven": {
"httpUrl": "https://api.layven.io/mcp",
"headers": {
"Authorization": "Bearer agd_your_agent_token"
}
}
}
}
JSON MCP genérico
{
"mcpServers": {
"layven": {
"url": "https://api.layven.io/mcp",
"headers": {
"Authorization": "Bearer agd_your_agent_token"
}
}
}
}
Autenticación
Hay dos formas de entrar, y ambas resuelven al mismo registro de token, por lo que los permisos, la revocación y el rastro de auditoría son idénticos en ambos casos.
Token estático de portador. Envía Authorization: Bearer agd_... en cada solicitud. Créalo en la consola; el secreto se muestra una sola vez.
OAuth 2.1, para clientes cuya interfaz no tiene campo de encabezado personalizado:
| Servidor de autorización | https://api.layven.io |
| Metadatos del recurso protegido | https://api.layven.io/.well-known/oauth-protected-resource/mcp |
| Recurso | https://api.layven.io/mcp |
| Registro dinámico de clientes | Compatible |
| Caducidad del secreto de cliente | No caduca |
El consentimiento acuña un token ordinario, que puedes ver y revocar en la consola como cualquier otro.
Transporte
POST https://api.layven.io/mcp, Streamable HTTP, sin estado.- Cada POST es totalmente independiente. Sin id de sesión, sin reanudación de sesión, sin endpoint SSE separado, sin stdio.
- GET y DELETE devuelven HTTP 405 con exactamente este cuerpo:
{"jsonrpc":"2.0","error":{"code":-32000,"message":"Method not allowed (stateless)"},"id":null} - Encabezados de solicitud requeridos:
Content-Type: application/jsonyAccept: application/json, text/event-stream. Ambos tipos de medio deben estar presentes enAccepto el servidor devuelve 406. - Las respuestas vuelven como
Content-Type: text/event-stream. MCP-Protocol-Versiones opcional. Si está presente, debe ser uno de2025-11-25,2025-06-18,2025-03-26,2024-11-05,2024-10-07, de lo contrario el servidor devuelve HTTP 400.- Capacidades: solo
tools. Sin recursos, sin prompts. - Identidad del servidor en
initialize: nombreLayven, versión1.0.2, sitio webhttps://layven.io.
Herramientas
Cada herramienta acepta un workspace opcional, el slug del espacio de trabajo. Un token con exactamente un espacio de trabajo puede omitirlo. list sin workspace se distribuye a todos los espacios de trabajo que el token puede alcanzar.
| Herramienta | Acceso | Hace | Argumentos clave |
|---|---|---|---|
list | ro | Lista una carpeta, o encuentra archivos por subcadena de ruta | path, recursive, q, limit |
read | ro | Lee un archivo en la versión actual o una anterior | path, version |
grep | ro | Busca contenido de archivos con un patrón RE2 | pattern, prefix, context_lines, max_matches |
history | ro | Lista las versiones de un archivo, de la más reciente a la más antigua | path, limit, cursor |
activity | ro | Lista qué cambió y qué agente lo cambió | since, path_prefix, limit |
write | rw | Crea o reemplaza un archivo con contenido en línea | path, content, encoding, expected_version |
edit | rw | Aplica reemplazos de cadenas a un archivo de texto existente | path, edits, expected_version |
move | rw | Mueve o renombra un archivo | from, to, overwrite |
delete | rw | Marca un archivo como eliminado, recuperable con restore | path, expected_version |
restore | rw | Restaura un archivo a una versión, o una carpeta a una marca de tiempo | path + to_version, o prefix + at |
lock | rw | Toma un bloqueo de asesoramiento de 5 minutos en una ruta | path |
unlock | rw | Libera un bloqueo que este token mantiene | path |
request_upload | rw | Inicia una carga de archivo grande, devuelve una URL PUT prefirmada | path, size, expected_version |
finalize_upload | rw | Confirma un archivo subido como una nueva versión | upload_id |
Solo delete está anotado como destructivo, y escribe una versión de eliminación que restore recupera. write, delete, lock y unlock están anotados como idempotentes; edit, move, restore, request_upload y finalize_upload no lo están. Ninguna herramienta alcanza fuera de Layven.
NOT_FOUND (espacio de trabajo no resoluble), PERMISSION_DENIED, RATE_LIMITED y INTERNAL pueden volver de cualquier herramienta, por lo que la línea Errors debajo de cada herramienta nombra lo específico de esa herramienta.
list
Lista una carpeta, o busca en todos los espacios de trabajo concedidos rutas que coincidan con una subcadena.
Argumentos
workspace? string workspace slug; omit to fan out over every granted workspace
path string default "" (workspace root)
recursive boolean default false
include_deleted boolean default false
limit integer 1..1000, default 500, applied per workspace
cursor? string opaque; requires an explicit workspace
q? string 1..1024 chars, case-insensitive substring of the full path; implies recursive
Devuelve
{
"results": [
{
"workspace": { "id": "...", "slug": "research" },
"entries": [
{
"path": "notes/todo.md",
"type": "file",
"size": 1284,
"version": 7,
"modified_at": "2026-08-05T09:12:44Z",
"modified_by_label": "research-agent",
"by_actor": "agent",
"deleted": true
}
],
"next_cursor": "..."
}
]
}
type es "file" o "folder". size, version, modified_at, modified_by_label, by_actor y deleted son opcionales por entrada.
Errores: INVALID_PATH.
Notas
resultses siempre un array de bloques por espacio de trabajo, incluso cuando el token tiene exactamente un espacio de trabajo. No escribas un cliente que espere un arrayentriesdesnudo.- Pasar
cursormientras se distribuye devuelveINVALID_PATHconreason: "cursor_requires_workspace". Fija el espacio de trabajo antes de paginar. - Las carpetas se sintetizan a partir de prefijos de ruta. No hay registros de carpetas para crear o eliminar.
read
Lee un archivo, ya sea la versión actual o una anterior.
Argumentos
workspace? string
path string
version? integer defaults to the current version
Devuelve, en línea, cuando el tamaño bruto es de 262144 bytes o menos y el tipo mime es texto:
{
"path": "notes/todo.md",
"version": 7,
"size": 1284,
"mime_type": "text/markdown",
"encoding": "utf8",
"content": "..."
}
Devuelve, para cualquier cosa más grande o binaria:
{
"path": "datasets/corpus.tar.gz",
"version": 3,
"size": 431912448,
"mime_type": "application/gzip",
"download_url": "https://...",
"url_expires_at": "2026-08-05T09:27:00Z"
}
Errores: NOT_FOUND (con deleted: true y last_version cuando la ruta está marcada como eliminada), INVALID_PATH.
Notas
- La forma de la respuesta cambia según el tamaño y el tipo mime, no según una bandera que pases. Por encima de 256 KiB, o para cualquier archivo no textual, obtienes un
download_urlválido por 15 minutos en lugar de contenido en línea. Maneja ambas formas.
grep
Busca contenido de archivos con una expresión regular.
Argumentos
workspace? string
path? string search a single file
prefix? string search one folder; omit both path and prefix to search the whole workspace
pattern string min 1 char, RE2 syntax
case_sensitive boolean default false
context_lines integer 0..10, default 2
max_matches integer 1..200, default 50
Devuelve
{
"matches": [
{
"path": "notes/todo.md",
"line": 42,
"text": "TODO: rotate the staging token",
"before": ["..."],
"after": ["..."]
}
],
"files_scanned": 128,
"files_skipped_binary": 3,
"files_skipped_too_large": 0,
"truncated": false
}
Errores: INVALID_PATTERN, INVALID_PATH.
Notas
- Los patrones son RE2, por lo que no hay referencias inversas ni lookaround. Un patrón inválido devuelve
INVALID_PATTERN. - Las coincidencias se encuentran solo dentro de líneas individuales. Un patrón que abarca un salto de línea nunca coincidirá.
- Una entrada por línea coincidente, como
grep -n, sin importar cuántas ocurrencias tenga esa línea. truncated: truesignifica que el escaneo alcanzó su presupuesto y los resultados son parciales. Reduce elprefixo ajusta el patrón.- Los números de línea son solo para mostrar. Nunca pegues uno en el
old_strdeedit.
history
Lista las versiones de un archivo, de la más reciente a la más antigua.
Argumentos
workspace? string
path string
limit integer 1..1000, default 50
cursor? string digits only
Devuelve
{
"versions": [
{
"version": 7,
"op": "write",
"size": 1284,
"content_hash": "...",
"created_at": "2026-08-05T09:12:44Z",
"by_label": "research-agent",
"by_actor": "agent",
"moved_from": "drafts/todo.md",
"purged": false,
"restorable_until": "2027-08-05T09:12:44Z"
}
],
"next_cursor": "182734"
}
op es uno de write, edit, move, delete, restore. moved_from, by_actor y restorable_until son opcionales.
Errores: NOT_FOUND, INVALID_PATH.
Notas
- De la más reciente a la más antigua, por lo que
limit: 1es la forma más barata de confirmar que una escritura llegó. next_cursores una cadena opaca, nunca un número. Está ausente en la última página, así es como sabes que debes detenerte.purged: truesignifica que la retención liberó el contenido de esa versión. La fila permanece para el rastro de auditoría, perorestorea ella devuelveNOT_FOUNDconreason: "version_purged".
activity
Lista qué cambió en un espacio de trabajo y qué agente lo cambió.
Argumentos
workspace? string
since? string RFC 3339 timestamp
path_prefix? string
limit integer 1..1000, default 100
cursor? string
Devuelve
{
"events": [
{
"at": "2026-08-05T09:12:44Z",
"actor": "agent",
"by_label": "research-agent",
"by_actor": "agent",
"op": "write",
"path": "notes/todo.md",
"old_path": "drafts/todo.md",
"version": 7
}
],
"next_cursor": "9014522"
}
actor es uno de agent, user, system. De la más reciente a la más antigua.
op es write, edit, move, delete, restore, purge, lock, unlock o grep. Los barridos del sistema también registran purge_retention y purge_workspace_delete, ambos sin ruta. Solo write, edit, move, delete y un restore de un solo archivo llevan un version; en el resto es nulo. Ten en cuenta que purge lleva una ruta real o un prefijo de carpeta, por lo que coincide con un filtro path_prefix: si estás auditando una carpeta desde este feed, una purga aparece junto a las escrituras.
Errores: INVALID_PATH.
Notas
next_cursores una cadena opaca, nunca un número. Está ausente en la última página, así es como sabes que debes detenerte.- Esto es un sondeo. No hay webhooks, ni disparadores, ni push. Los agentes se coordinan llamando a
activityen un intervalo, lo que cabe cómodamente dentro del límite de tasa a una cadencia de segundos a minutos. sincees una marca de tiempo, no un cursor, y dos eventos pueden compartir una. Espera re-entrega ocasional y haz el trabajo idempotente. Ver examples/two-agent-handoff.md.
write
Crea o reemplaza un archivo con contenido en línea.
Argumentos
workspace? string
path string
content string
encoding "utf8" | "base64" default "utf8"
mime_type? string
expected_version? integer fail instead of overwriting a concurrent change
override_lock boolean default false
Límite en línea: 1 MiB decodificado. Cualquier cosa más grande pasa por request_upload.
Devuelve
{
"path": "notes/todo.md",
"version": 8,
"size": 1301,
"content_hash": "...",
"deduplicated": false,
"unchanged": true
}
unchanged está presente solo cuando corresponde.
Errores: INVALID_PATH, VERSION_CONFLICT, LOCKED, QUOTA_EXCEEDED, TOO_LARGE.
Notas
- Escribir contenido byte-idéntico a la versión actual es un no-op: devuelve
unchanged: truey no crea una nueva versión. Para un trabajo programado, vale la pena registrarlo en voz alta, porque generalmente significa que el generador no se ejecutó. - El contenido idéntico a una versión anterior sí crea una nueva versión.
- Escribir en una ruta marcada como eliminada la resucita.
edit
Aplica reemplazos de cadenas a un archivo de texto existente sin reenviar todo el cuerpo.
Argumentos
workspace? string
path string
edits array of 1..20 objects:
old_str string min 1 char
new_str string
replace_all boolean default false
expected_version? integer
override_lock boolean default false
Archivos de texto de hasta 16 MiB.
Devuelve
{
"path": "notes/todo.md",
"version": 9,
"edits_applied": 2,
"replacements": [1, 3],
"size_before": 1301,
"size_after": 1288,
"context": "..."
}
unchanged está presente solo cuando corresponde.
Errores: STRING_NOT_FOUND, STRING_NOT_UNIQUE, NOT_EDITABLE, TOO_LARGE_FOR_EDIT, VERSION_CONFLICT, LOCKED, QUOTA_EXCEEDED, NOT_FOUND.
Notas
- Las ediciones se aplican en orden y se confirman atómicamente como una nueva versión, por lo que una llamada con 20 ediciones es una entrada en
history, no veinte. Si alguna edición falla, ninguna se aplica. - Cada
old_strdebe coincidir exactamente una vez; de lo contrario, obtienesSTRING_NOT_FOUNDoSTRING_NOT_UNIQUE. Establecereplace_allcuando quieras que coincida en cada ocurrencia. - Como las ediciones se aplican en orden, un
old_strposterior debe coincidir con el texto tal como lo dejaron las ediciones anteriores.
move
Mueve o renombra un archivo.
Argumentos
workspace? string
from string
to string
expected_version? integer
overwrite boolean default false
override_lock boolean default false
Devuelve
{ "from": "drafts/todo.md", "to": "notes/todo.md", "version": 1 }
version es la nueva versión en el destino.
Errores: NOT_FOUND, INVALID_PATH, VERSION_CONFLICT (con reason: "destination_exists"), LOCKED.
Notas
- El token necesita acceso de escritura a ambas rutas. Una regla de prefijo que cubre el origen pero no el destino falla con
PERMISSION_DENIED. - Un destino activo con
overwrite: falsedevuelveVERSION_CONFLICTconreason: "destination_exists". Ese fallo es útil: dos trabajadores compitiendo por reclamar el mismo elemento puedenmove, y el perdedor recibe un error limpio en lugar de trabajo duplicado.
delete
Marca un archivo como eliminado (tombstone).
Argumentos
workspace? string
path string
expected_version? integer
override_lock boolean default false
Devuelve
{ "path": "notes/todo.md", "version": 10, "unchanged": true }
unchanged está presente solo cuando corresponde.
Errores: NOT_FOUND, INVALID_PATH, VERSION_CONFLICT, LOCKED.
Notas
- Esto escribe una versión de eliminación, no borra el contenido. El archivo sigue siendo recuperable con
restoredurante el tiempo que permita la ventana de historial de versiones de tu plan. - Escribir en la misma ruta más tarde lo resucita como una nueva versión en el mismo historial.
listoculta las rutas eliminadas a menos que pasesinclude_deleted: true.
restore
Restaura un archivo a una versión anterior, o una carpeta completa a un punto en el tiempo.
Argumentos, forma de archivo:
workspace? string
path string
to_version integer
override_lock boolean default false
Argumentos, forma de carpeta:
workspace? string
prefix string
at string RFC 3339 timestamp in UTC, e.g. 2026-08-05T14:04:55Z
override_lock boolean default false
Devuelve, forma de archivo:
{ "path": "notes/todo.md", "version": 11 }
Devuelve, forma de carpeta:
{
"restored": 42,
"deleted": 3,
"affected_paths": ["content/pricing.md", "content/index.md"],
"total": 45
}
affected_paths es una muestra limitada; total es el recuento real.
Errores: NOT_FOUND (con reason: "version_purged" cuando la retención ya liberó la versión objetivo), INVALID_PATH, LOCKED.
Notas
atdebe ser UTC, terminando enZ, con milisegundos opcionales. Un desplazamiento UTC como+02:00se rechaza aunque sea RFC 3339 válido, así que convierte antes de llamar.- La restauración agrega nuevas versiones y nunca reescribe el historial. Las versiones malas permanecen en
history, por lo que restaurar a una marca de tiempo incorrecta es en sí mismo restaurable, y restaurar dos veces es seguro. - En la forma de carpeta, los archivos que no existían en
atreciben eliminaciones (tombstones), contadas pordeleted. No se borran y una escritura posterior los trae de vuelta. - No hay simulación (dry run). Dimensiona la operación con
listy confirma un solo archivo conhistoryprimero. Recorrido: examples/folder-restore-after-bad-run.md.
lock
Toma un bloqueo de asesoramiento sobre una ruta.
Argumentos
workspace? string
path string
Devuelve
{ "path": "notes/todo.md", "expires_at": "2026-08-05T09:17:44Z" }
Errores: LOCKED, INVALID_PATH.
Notas
- De asesoramiento y 5 minutos. Llama a
lockde nuevo con el mismo token para renovarlo. - Los bloqueos nunca bloquean lecturas. Un bloqueo válido ajeno hace que las escrituras devuelvan
LOCKEDconlocked_by_labelyexpires_at, a menos que el llamador paseoverride_lock: true, lo cual se registra en el feed de actividad. - El archivo no necesita existir, así que puedes bloquear una ruta que estás a punto de crear.
- Para trabajo que pueda hacerse idempotente, prefiere una reclamación con
movesobre un bloqueo: sobrevive a un fallo, y un TTL de 5 minutos no.
unlock
Libera un bloqueo que este token mantiene.
Argumentos
workspace? string
path string
Devuelve
{ "path": "notes/todo.md", "released": true }
Errores: PERMISSION_DENIED (el bloqueo pertenece a otro token), INVALID_PATH.
Notas
- Desbloquear una ruta sin bloqueo devuelve
released: true, noNOT_FOUND. La llamada no dice nada sobre si existía un bloqueo, así que no es una forma de preguntar quién lo tiene.
request_upload
Inicia una subida para contenido demasiado grande para write en línea. Primero de dos pasos; ver Large file uploads.
Argumentos
workspace? string
path string
size integer positive, the exact byte count of the file
mime_type? string
expected_version? integer
override_lock boolean default false
Devuelve
{
"upload_id": "...",
"put_url": "https://...",
"url_expires_at": "2026-08-05T09:27:00Z",
"max_size": 1073741824
}
Errores: TOO_LARGE, QUOTA_EXCEEDED, VERSION_CONFLICT, LOCKED, INVALID_PATH.
Notas
- La URL PUT prefirmada es válida por 15 minutos y el registro de subida por 1 hora. No hay subida reanudable ni multiparte: si el PUT falla, comienza de nuevo desde
request_upload. sizedebe ser el recuento exacto de bytes. Se vuelve a verificar enfinalize_upload.
finalize_upload
Confirma un archivo subido como una nueva versión. Segundo de dos pasos.
Argumentos
workspace? string
upload_id string
Devuelve
{
"path": "datasets/corpus.tar.gz",
"size": 431912448,
"version": 3,
"content_hash": "..."
}
Errores: UPLOAD_EXPIRED, VERSION_CONFLICT, QUOTA_EXCEEDED, TOO_LARGE.
Notas
- El tamaño y
expected_versionse vuelven a verificar aquí, así que unVERSION_CONFLICTpuede aparecer en la finalización aunquerequest_uploadhaya tenido éxito. Alguien escribió la ruta mientras subías; comienza de nuevo desderequest_upload. - Llamar a finalizar una segunda vez devuelve
UPLOAD_EXPIRED.
Errores
Los fallos de dominio vuelven como un resultado de herramienta normal que lleva isError: true, cuyo contenido de texto es JSON:
{ "code": "VERSION_CONFLICT", "message": "...", "current_version": 9 }
Nunca son errores de protocolo JSON-RPC. Los agentes y clientes deben ramificar según code.
La validación de argumentos falla de la misma manera, pero el texto no es JSON. Pasar un argumento del tipo incorrecto devuelve isError: true con una cadena en inglés simple como MCP error -32602: Input validation error: Invalid arguments for tool activity: ..., producida por la capa MCP antes de que la solicitud llegue a Layven. Así que analiza de forma defensiva: un resultado isError cuyo texto no se analice como JSON es un error en tu llamada, no un error de dominio de Layven. upload/layven-upload.mjs hace exactamente esto, recurriendo a code: "UNKNOWN" con el texto crudo como mensaje.
| Código | Significado | Extras |
|---|---|---|
NOT_FOUND | Ruta, versión o espacio de trabajo ausente | workspaces (los slugs del token) cuando un slug de espacio de trabajo no se resuelve; deleted: true y last_version en una ruta eliminada; reason: "version_purged" en una versión purgada |
PERMISSION_DENIED | El token carece del nivel de acceso, o una regla de prefijo bloquea la ruta | required |
INVALID_PATH | La ruta falla la normalización | reason |
VERSION_CONFLICT | expected_version no coincidió, o el destino existe | current_version, a veces reason (por ejemplo destination_exists) |
LOCKED | Otro token mantiene un bloqueo válido | locked_by_label, expires_at |
QUOTA_EXCEEDED | La organización superó su cuota de almacenamiento | limit_bytes, used_bytes |
TOO_LARGE | Contenido en línea sobre el límite, o archivo sobre 1 GiB | max_bytes |
UPLOAD_EXPIRED | Finalizar llamado en una subida expirada o ya consumida | |
RATE_LIMITED | Límite de tasa del token o la organización alcanzado | retry_after_ms |
INTERNAL | Fallo inesperado del servidor | request_id |
STRING_NOT_FOUND | edit: old_str no está presente en el archivo | pista |
STRING_NOT_UNIQUE | edit: old_str coincidió más de una vez y replace_all no se estableció | |
NOT_EDITABLE | edit: el archivo no es texto | |
TOO_LARGE_FOR_EDIT | edit: archivo sobre 16 MiB | |
INVALID_PATTERN | grep: el patrón no es RE2 válido |
RATE_LIMITED es el único código que vale la pena reintentar automáticamente: duerme retry_after_ms, luego intenta de nuevo.
Límites
| Límite | Valor |
|---|---|
| Escritura en línea | 1 MiB decodificado; contenido más grande va a través de request_upload |
| Lectura en línea | 256 KiB y un tipo MIME de texto, de lo contrario una URL de descarga |
| Edición | Archivos de texto hasta 16 MiB, hasta 20 ediciones por llamada |
| Grep | 8 MiB por archivo escaneado, 500 archivos candidatos por llamada, resultados parciales más allá del presupuesto de tiempo |
| Tamaño máximo de archivo | 1 GiB |
| URL PUT prefirmada | 15 minutos |
| Registro de subida | 1 hora |
| URL de descarga | 15 minutos |
| Longitud de ruta | 1024 bytes |
| TTL de bloqueo | 5 minutos, renovable |
| Límite de tasa | 600 solicitudes por minuto por token, 3000 por minuto por organización |
Exceder un límite de tasa devuelve RATE_LIMITED con retry_after_ms.
Rutas y versionado
Las rutas son UTF-8, separadas por / y sensibles a mayúsculas. Se normalizan en la entrada:
- sin barra inicial:
/a/bse convierte ena/b - sin barras duplicadas
- sin segmentos
.o.., y sin segmentos vacíos - sin barra final en un archivo
- sin caracteres de control
- máximo 1024 bytes
Cualquier otra cosa devuelve INVALID_PATH con un reason. Los directorios son implícitos: no hay registros de carpetas, y list sintetiza carpetas a partir de prefijos de ruta.
Versionado. Cada mutación crea una nueva versión, numerada por archivo. delete escribe una versión de eliminación. move crea una versión en el destino y elimina el origen. restore agrega una nueva versión que reproduce un estado anterior. El historial es de solo agregar y nunca se reescribe, por eso una restauración mala es en sí misma restaurable.
Concurrencia optimista. El valor predeterminado es último-escritura-gana, lo cual es seguro porque nada se pierde. Cuando quieras que una escritura falle en lugar de sobrescribir un cambio concurrente, pasa expected_version con la versión que leíste. Una discrepancia devuelve VERSION_CONFLICT con current_version en la carga útil, para que el llamador pueda volver a leer y decidir.
Bloqueos. lock toma un bloqueo de asesoramiento de 5 minutos, renovado llamando a lock de nuevo con el mismo token. Un bloqueo válido ajeno hace que las escrituras devuelvan LOCKED con locked_by_label y expires_at; override_lock: true continúa de todos modos y se registra en el feed de actividad. Los bloqueos nunca bloquean lecturas.
Permisos
A cada token se le otorga acceso a espacios de trabajo específicos en uno de tres niveles:
| Nivel | Herramientas |
|---|---|
ro | list, read, grep, history, activity |
rw | todo en ro, más write, edit, move, delete, restore, lock, unlock, request_upload, finalize_upload |
admin | reservado para futura gestión de espacios de trabajo |
Una concesión puede llevar reglas de prefijo opcionales que restringen un token a carpetas particulares, expresadas como listas allow o deny. Denegar supera a permitir. move requiere permiso tanto en la ruta de origen como en la de destino.
Dale a cada agente su propio token. Eso es lo que hace que by_label en list, history y activity sea legible, y es lo que te permite revocar un agente sin tocar a los demás.
Subidas de archivos grandes
write en línea tiene un límite de 1 MiB. Por encima de eso, sube en tres pasos.
1. Pide una URL. Llama a request_upload con el recuento exacto de bytes:
{ "path": "datasets/corpus.tar.gz", "size": 431912448, "mime_type": "application/gzip" }
{
"upload_id": "...",
"put_url": "https://...",
"url_expires_at": "2026-08-05T09:27:00Z",
"max_size": 1073741824
}
2. Haz PUT de los bytes a put_url. Esto es un PUT HTTP simple del archivo crudo, no una llamada MCP. La URL es válida por 15 minutos.
3. Confírmalo. Llama a finalize_upload:
{ "upload_id": "..." }
{
"path": "datasets/corpus.tar.gz",
"size": 431912448,
"version": 3,
"content_hash": "..."
}
Por qué no hay SDK
No hay una biblioteca cliente de Layven y no la habrá. Layven es un servidor MCP alojado: apuntas tu cliente a una URL y tu agente obtiene 14 herramientas, sin código que escribir y nada que mantener actualizado. Esta es la única excepción. El flujo de subida tiene un paso intermedio que es un PUT HTTP crudo, y un cliente MCP no puede emitir uno, así que enviamos un único script sin dependencias para ello. Cópialo, léelo, cámbialo. Es MIT.
upload/layven-upload.mjs
Node 18 o más reciente. Sin dependencias, sin instalación.
LAYVEN_TOKEN=agd_your_agent_token \
node upload/layven-upload.mjs ./corpus.tar.gz datasets/corpus.tar.gz \
[--workspace slug] [--mime type] [--expected-version N] [--override-lock] \
[--url https://api.layven.io/mcp]
LAYVEN_TOKEN es obligatorio. --url por defecto es https://api.layven.io/mcp.
Ejecuta sus pruebas desde la raíz del repositorio con:
node --test
Ejemplos
- examples/two-agent-handoff.md: el agente A deja trabajo en la unidad, el agente B lo recoge consultando
activity. - examples/nightly-write-and-verify.md: un agente impulsado por cron que escribe un artefacto y verifica que la escritura se realizó.
- examples/folder-restore-after-bad-run.md: diagnostica una ejecución de agente fallida y revierte una carpeta a una marca de tiempo.
Planes
| Free | Pro $19/mo | Scale $49/mo | Enterprise | |
|---|---|---|---|---|
| Almacenamiento | 5 GB | 100 GB | 500 GB | Personalizado |
| Historial de versiones | 30 días | 1 año | Ilimitado | Ilimitado |
| Registro de actividad | 30 días | 1 año | 1 año | Ilimitado |
| Espacios de trabajo | 1 | 5 | 25 | Ilimitado |
| Tokens | 2 | 25 | 100 | Ilimitado |
| Usuarios | 1 | 3 | 10 | Ilimitado |
| Tamaño máximo de archivo | 1 GiB | 1 GiB | 1 GiB | 1 GiB |
| Límite de peticiones | 600 req/min/token | 600 req/min/token | 600 req/min/token | 600 req/min/token |
Precio fijo. Sin medidores, sin créditos.
Residencia de datos
Tus archivos se almacenan en OVHcloud en Gravelines, Francia, y están cifrados en reposo. Ninguna IA de terceros ni API de modelos toca tu contenido. Puedes exportar todo como archivos planos, y la eliminación es una eliminación real.
Control de versiones
La versión en server.json y en el changelog coincide con la versión que el servidor informa en initialize, para que siempre puedas comprobar con qué estás hablando. Los cambios de documentación que no siguen un cambio de servidor no incrementan la versión.
Consulta CHANGELOG.md.
Soporte
Errores en estos documentos, los ejemplos o el asistente de carga: abre un issue. Preguntas sobre cuenta, facturación o datos: info@layven.io.
Licencia
MIT cubre este repositorio: la documentación, los ejemplos y el asistente de carga. El servicio Layven en sí es de código cerrado.