Layven

Unidade compartilhada para seus agentes e colegas de equipe.

Documentação

Servidor MCP Layven

Layven é um drive compartilhado que seus agentes montam via MCP. Cada escrita é versionada, cada ação é atribuída ao agente que a realizou, e qualquer coisa pode ser revertida.

Um bloco de configuração, sem alterações no código do agente. Hospedado em https://api.layven.io/mcp.

Documenta o servidor MCP Layven 1.0.2.


Início rápido

claude mcp add --transport http layven https://api.layven.io/mcp --header "Authorization: Bearer agd_your_agent_token"
  1. Obtenha um token em layven.io: abra o console, vá em Agents, crie um. O segredo é mostrado uma única vez.
  2. Reinicie seu cliente.
  3. Pergunte ao seu agente: "liste meus workspaces Layven".

O ponto do produto aparece na segunda conexão. Crie um segundo token, conecte uma ferramenta diferente com ele, e faça essa ferramenta ler o arquivo que a primeira acabou de escrever. Ambos os agentes veem o mesmo drive, e o feed de atividade diz quem fez o quê. Passo a passo: examples/two-agent-handoff.md.


Conecte seu cliente

Claude Code

claude mcp add --transport http layven https://api.layven.io/mcp --header "Authorization: Bearer agd_your_agent_token"

Conector personalizado Claude.ai

Cole https://api.layven.io/mcp e autentique com OAuth. Essa interface não tem campo de cabeçalho personalizado, e é por isso que o OAuth existe.

ChatGPT

Igual ao Claude.ai: cole https://api.layven.io/mcp e autentique com 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)

Mesmo JSON do Cursor, mas a chave é httpUrl em vez de url, porque o Gemini lê url como um 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"
      }
    }
  }
}

Autenticação

Existem duas formas de acesso, e ambas resolvem para o mesmo registro de token, então permissões, revogação e trilha de auditoria são idênticas de qualquer forma.

Token bearer estático. Envie Authorization: Bearer agd_... em cada requisição. Crie-o no console; o segredo é mostrado uma única vez.

OAuth 2.1, para clientes cuja interface não tem campo de cabeçalho personalizado:

Servidor de autorizaçãohttps://api.layven.io
Metadados do recurso protegidohttps://api.layven.io/.well-known/oauth-protected-resource/mcp
Recursohttps://api.layven.io/mcp
Registro dinâmico de clienteSuportado
Expiração do segredo do clienteNão expira

O consentimento gera um token comum, que você pode ver e revogar no console como qualquer outro.


Transporte

  • POST https://api.layven.io/mcp, HTTP Streamable, sem estado.
  • Cada POST é totalmente independente. Sem id de sessão, sem retomada de sessão, sem endpoint SSE separado, sem stdio.
  • GET e DELETE retornam HTTP 405 com exatamente este corpo:
    {"jsonrpc":"2.0","error":{"code":-32000,"message":"Method not allowed (stateless)"},"id":null}
    
  • Cabeçalhos de requisição obrigatórios: Content-Type: application/json e Accept: application/json, text/event-stream. Ambos os tipos de mídia devem estar presentes em Accept ou o servidor retorna 406.
  • Respostas voltam como Content-Type: text/event-stream.
  • MCP-Protocol-Version é opcional. Se presente, deve ser um de 2025-11-25, 2025-06-18, 2025-03-26, 2024-11-05, 2024-10-07, caso contrário o servidor retorna HTTP 400.
  • Capacidades: apenas tools. Sem recursos, sem prompts.
  • Identidade do servidor em initialize: nome Layven, versão 1.0.2, site https://layven.io.

Ferramentas

Toda ferramenta aceita um workspace opcional, o slug do workspace. Um token com permissão para exatamente um workspace pode omiti-lo. list sem workspace se espalha por todos os workspaces que o token pode alcançar.

FerramentaAcessoFazArgumentos-chave
listroLista uma pasta, ou encontra arquivos por substring do caminhopath, recursive, q, limit
readroLê um arquivo na versão atual ou em uma versão anteriorpath, version
greproPesquisa o conteúdo de arquivos com um padrão RE2pattern, prefix, context_lines, max_matches
historyroLista as versões de um arquivo, da mais nova para a mais antigapath, limit, cursor
activityroLista o que mudou e qual agente mudousince, path_prefix, limit
writerwCria ou substitui um arquivo com conteúdo inlinepath, content, encoding, expected_version
editrwAplica substituições de string em um arquivo de texto existentepath, edits, expected_version
moverwMove ou renomeia um arquivofrom, to, overwrite
deleterwMarca um arquivo como excluído, recuperável com restorepath, expected_version
restorerwRestaura um arquivo para uma versão, ou uma pasta para um timestamppath + to_version, ou prefix + at
lockrwObtém um bloqueio consultivo de 5 minutos em um caminhopath
unlockrwLibera um bloqueio que este token detémpath
request_uploadrwInicia um upload de arquivo grande, retorna uma URL PUT pré-assinadapath, size, expected_version
finalize_uploadrwConfirma um arquivo enviado como uma nova versãoupload_id

Apenas delete é anotada como destrutiva, e ela escreve uma versão de tombstone que restore traz de volta. write, delete, lock e unlock são anotadas como idempotentes; edit, move, restore, request_upload e finalize_upload não são. Nenhuma ferramenta alcança fora do Layven.

NOT_FOUND (workspace não resolvível), PERMISSION_DENIED, RATE_LIMITED e INTERNAL podem voltar de qualquer ferramenta, então a linha Errors sob cada ferramenta abaixo nomeia o que é específico daquela ferramenta.

list

Lista uma pasta, ou pesquisa todos os workspaces concedidos por caminhos que correspondam a uma substring.

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

Retorna

{
  "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 é "file" ou "folder". size, version, modified_at, modified_by_label, by_actor e deleted são opcionais por entrada.

Erros: INVALID_PATH.

Notas

  • results é sempre um array de blocos por workspace, mesmo quando o token tem permissão para exatamente um workspace. Não escreva um cliente que espere um array entries simples.
  • Passar cursor durante a expansão retorna INVALID_PATH com reason: "cursor_requires_workspace". Fixe o workspace antes de paginar.
  • Pastas são sintetizadas a partir de prefixos de caminho. Não há registros de pasta para criar ou excluir.

read

Lê um arquivo, seja a versão atual ou uma anterior.

Argumentos

workspace?   string
path         string
version?     integer   defaults to the current version

Retorna, inline, quando o tamanho bruto é 262144 bytes ou menos e o tipo mime é texto:

{
  "path": "notes/todo.md",
  "version": 7,
  "size": 1284,
  "mime_type": "text/markdown",
  "encoding": "utf8",
  "content": "..."
}

Retorna, para qualquer coisa maior ou binária:

{
  "path": "datasets/corpus.tar.gz",
  "version": 3,
  "size": 431912448,
  "mime_type": "application/gzip",
  "download_url": "https://...",
  "url_expires_at": "2026-08-05T09:27:00Z"
}

Erros: NOT_FOUND (com deleted: true e last_version quando o caminho está com tombstone), INVALID_PATH.

Notas

  • O formato da resposta muda com base no tamanho e no tipo mime, não em uma flag que você passa. Acima de 256 KiB, ou para qualquer arquivo não-texto, você recebe um download_url válido por 15 minutos em vez de conteúdo inline. Lide com ambos os formatos.

grep

Pesquisa o conteúdo de arquivos com uma expressão 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

Retorna

{
  "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
}

Erros: INVALID_PATTERN, INVALID_PATH.

Notas

  • Padrões são RE2, então não há backreferences nem lookaround. Um padrão inválido retorna INVALID_PATTERN.
  • Correspondências são encontradas apenas dentro de linhas únicas. Um padrão que atravessa uma quebra de linha nunca corresponderá.
  • Uma entrada por linha correspondente, como grep -n, não importa quantas ocorrências essa linha contenha.
  • truncated: true significa que a varredura atingiu seu orçamento e os resultados são parciais. Estreite o prefix ou aperte o padrão.
  • Números de linha são apenas para exibição. Nunca cole um em edit's old_str.

history

Lista as versões de um arquivo, da mais nova para a mais antiga.

Argumentos

workspace?   string
path         string
limit        integer   1..1000, default 50
cursor?      string    digits only

Retorna

{
  "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 é um de write, edit, move, delete, restore. moved_from, by_actor e restorable_until são opcionais.

Erros: NOT_FOUND, INVALID_PATH.

Notas

  • Da mais nova para a mais antiga, então limit: 1 é a forma mais barata de confirmar que uma escrita foi registrada.
  • next_cursor é uma string opaca, nunca um número. Está ausente na última página, que é como você sabe que deve parar.
  • purged: true significa que a retenção liberou o conteúdo daquela versão. A linha permanece para a trilha de auditoria, mas restore para ela retorna NOT_FOUND com reason: "version_purged".

activity

Lista o que mudou em um workspace e qual agente mudou.

Argumentos

workspace?    string
since?        string    RFC 3339 timestamp
path_prefix?  string
limit         integer   1..1000, default 100
cursor?       string

Retorna

{
  "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 é um de agent, user, system. Da mais nova para a mais antiga.

op é write, edit, move, delete, restore, purge, lock, unlock ou grep. Varreduras do sistema também registram purge_retention e purge_workspace_delete, ambos sem caminho. Apenas write, edit, move, delete e um restore de arquivo único carregam um version; nos demais, é nulo. Observe que purge carrega um caminho real ou prefixo de pasta, então corresponde a um filtro path_prefix: se você está auditando uma pasta a partir deste feed, uma purga aparece junto com as escritas.

Erros: INVALID_PATH.

Notas

  • next_cursor é uma string opaca, nunca um número. Está ausente na última página, que é como você sabe que deve parar.
  • Isto é uma sondagem. Não há webhooks, nem gatilhos, nem push. Agentes coordenam chamando activity em um intervalo, o que cabe confortavelmente dentro do limite de taxa em uma cadência de segundos a minutos.
  • since é um timestamp, não um cursor, e dois eventos podem compartilhar um. Espere re-entrega ocasional e torne o trabalho idempotente. Veja examples/two-agent-handoff.md.

write

Cria ou substitui um arquivo com conteúdo inline.

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

Limite inline: 1 MiB decodificado. Qualquer coisa maior passa por request_upload.

Retorna

{
  "path": "notes/todo.md",
  "version": 8,
  "size": 1301,
  "content_hash": "...",
  "deduplicated": false,
  "unchanged": true
}

unchanged está presente apenas quando se aplica.

Erros: INVALID_PATH, VERSION_CONFLICT, LOCKED, QUOTA_EXCEEDED, TOO_LARGE.

Notas

  • Escrever conteúdo byte-idêntico à versão atual é um no-op: retorna unchanged: true e não cria nova versão. Para um trabalho agendado, vale registrar isso em voz alta, porque geralmente significa que o gerador não rodou.
  • Conteúdo idêntico a uma versão anterior cria uma nova versão.
  • Escrever em um caminho com tombstone o ressuscita.

edit

Aplica substituições de string em um arquivo de texto existente sem reenviar o corpo inteiro.

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

Arquivos de texto de até 16 MiB.

Retorna

{
  "path": "notes/todo.md",
  "version": 9,
  "edits_applied": 2,
  "replacements": [1, 3],
  "size_before": 1301,
  "size_after": 1288,
  "context": "..."
}

unchanged está presente apenas quando se aplica.

Erros: STRING_NOT_FOUND, STRING_NOT_UNIQUE, NOT_EDITABLE, TOO_LARGE_FOR_EDIT, VERSION_CONFLICT, LOCKED, QUOTA_EXCEEDED, NOT_FOUND.

Notas

  • As edições são aplicadas em ordem e confirmadas atomicamente como uma nova versão, então uma chamada com 20 edições é uma única entrada em history, não vinte. Se qualquer edição falhar, nenhuma delas é aplicada.
  • Cada old_str deve corresponder exatamente uma vez, caso contrário você recebe STRING_NOT_FOUND ou STRING_NOT_UNIQUE. Defina replace_all quando quiser dizer todas as ocorrências.
  • Como as edições são aplicadas em ordem, um old_str posterior deve corresponder ao texto como as edições anteriores o deixaram.

move

Move ou renomeia um arquivo.

Argumentos

workspace?         string
from               string
to                 string
expected_version?  integer
overwrite          boolean   default false
override_lock      boolean   default false

Retornos

{ "from": "drafts/todo.md", "to": "notes/todo.md", "version": 1 }

version é a nova versão no destino.

Erros: NOT_FOUND, INVALID_PATH, VERSION_CONFLICT (com reason: "destination_exists"), LOCKED.

Notas

  • O token precisa de acesso de escrita a ambos os caminhos. Uma regra de prefixo que cobre a origem, mas não o destino, falha com PERMISSION_DENIED.
  • Um destino ativo com overwrite: false retorna VERSION_CONFLICT com reason: "destination_exists". Essa falha é útil: dois workers disputando para reivindicar o mesmo item podem move e o perdedor recebe um erro limpo em vez de trabalho duplicado.

delete

Cria um tombstone para um arquivo.

Argumentos

workspace?         string
path               string
expected_version?  integer
override_lock      boolean   default false

Retornos

{ "path": "notes/todo.md", "version": 10, "unchanged": true }

unchanged está presente apenas quando se aplica.

Erros: NOT_FOUND, INVALID_PATH, VERSION_CONFLICT, LOCKED.

Notas

  • Isso grava uma versão tombstone, não apaga o conteúdo. O arquivo permanece recuperável com restore enquanto a janela de histórico de versões do seu plano permitir.
  • Escrever no mesmo caminho posteriormente o ressuscita como uma nova versão no mesmo histórico.
  • list oculta caminhos com tombstone, a menos que você passe include_deleted: true.

restore

Restaura um arquivo para uma versão anterior, ou uma pasta inteira para um ponto no tempo.

Argumentos, forma de arquivo:

workspace?      string
path            string
to_version      integer
override_lock   boolean   default false

Argumentos, forma de pasta:

workspace?      string
prefix          string
at              string    RFC 3339 timestamp in UTC, e.g. 2026-08-05T14:04:55Z
override_lock   boolean   default false

Retornos, forma de arquivo:

{ "path": "notes/todo.md", "version": 11 }

Retornos, forma de pasta:

{
  "restored": 42,
  "deleted": 3,
  "affected_paths": ["content/pricing.md", "content/index.md"],
  "total": 45
}

affected_paths é uma amostra limitada; total é a contagem real.

Erros: NOT_FOUND (com reason: "version_purged" quando a retenção já liberou a versão alvo), INVALID_PATH, LOCKED.

Notas

  • at deve estar em UTC, terminando em Z, com milissegundos opcionais. Um offset UTC como +02:00 é rejeitado mesmo sendo RFC 3339 válido, então converta antes de chamar.
  • A restauração acrescenta novas versões e nunca reescreve o histórico. As versões ruins permanecem em history, então restaurar para o timestamp errado é em si restaurável, e restaurar duas vezes é seguro.
  • Na forma de pasta, arquivos que não existiam em at recebem tombstones de exclusão, contados por deleted. Eles não são apagados e uma escrita posterior os traz de volta.
  • Não há simulação (dry run). Dimensione a operação com list e confirme um único arquivo com history primeiro. Passo a passo: examples/folder-restore-after-bad-run.md.

lock

Obtém um lock consultivo em um caminho.

Argumentos

workspace?   string
path         string

Retornos

{ "path": "notes/todo.md", "expires_at": "2026-08-05T09:17:44Z" }

Erros: LOCKED, INVALID_PATH.

Notas

  • Consultivo e de 5 minutos. Chame lock novamente com o mesmo token para renovar.
  • Locks nunca bloqueiam leituras. Um lock válido estrangeiro faz as escritas retornarem LOCKED com locked_by_label e expires_at, a menos que o chamador passe override_lock: true, o que é registrado no feed de atividades.
  • O arquivo não precisa existir, então você pode bloquear um caminho que está prestes a criar.
  • Para trabalho que pode ser tornado idempotente, prefira uma reivindicação com move em vez de um lock: ela sobrevive a uma falha, e um TTL de 5 minutos não.

unlock

Libera um lock que este token detém.

Argumentos

workspace?   string
path         string

Retornos

{ "path": "notes/todo.md", "released": true }

Erros: PERMISSION_DENIED (o lock pertence a outro token), INVALID_PATH.

Notas

  • Desbloquear um caminho sem lock retorna released: true, não NOT_FOUND. A chamada não diz nada sobre se um lock existia, então não é uma forma de perguntar quem detém um.

request_upload

Inicia um upload para conteúdo grande demais para write inline. Primeiro de dois passos; veja 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

Retornos

{
  "upload_id": "...",
  "put_url": "https://...",
  "url_expires_at": "2026-08-05T09:27:00Z",
  "max_size": 1073741824
}

Erros: TOO_LARGE, QUOTA_EXCEEDED, VERSION_CONFLICT, LOCKED, INVALID_PATH.

Notas

  • A URL PUT pré-assinada é válida por 15 minutos e o registro de upload por 1 hora. Não há upload retomável ou multiparte: se o PUT falhar, comece novamente de request_upload.
  • size deve ser a contagem exata de bytes. Ela é re-verificada em finalize_upload.

finalize_upload

Confirma um arquivo enviado como uma nova versão. Segundo de dois passos.

Argumentos

workspace?   string
upload_id    string

Retornos

{
  "path": "datasets/corpus.tar.gz",
  "size": 431912448,
  "version": 3,
  "content_hash": "..."
}

Erros: UPLOAD_EXPIRED, VERSION_CONFLICT, QUOTA_EXCEEDED, TOO_LARGE.

Notas

  • Tamanho e expected_version são ambos re-verificados aqui, então um VERSION_CONFLICT pode aparecer na finalização mesmo que request_upload tenha sido bem-sucedido. Alguém escreveu no caminho enquanto você enviava; comece novamente de request_upload.
  • Chamar finalize uma segunda vez retorna UPLOAD_EXPIRED.

Erros

Falhas de domínio retornam como um resultado de ferramenta normal carregando isError: true, cujo conteúdo de texto é JSON:

{ "code": "VERSION_CONFLICT", "message": "...", "current_version": 9 }

Elas nunca são erros de protocolo JSON-RPC. Agentes e clientes devem ramificar em code.

A validação de argumentos falha da mesma forma, mas o texto não é JSON. Passar um argumento do tipo errado retorna isError: true com uma string em inglês simples como MCP error -32602: Input validation error: Invalid arguments for tool activity: ..., produzida pela camada MCP antes de a requisição chegar ao Layven. Então faça o parse defensivamente: um resultado isError cujo texto não parseia como JSON é um bug na sua chamada, não um erro de domínio do Layven. upload/layven-upload.mjs faz exatamente isso, caindo para code: "UNKNOWN" com o texto bruto como mensagem.

CódigoSignificadoExtras
NOT_FOUNDCaminho, versão ou workspace ausenteworkspaces (os slugs do token) quando um slug de workspace não resolve; deleted: true e last_version em um caminho com tombstone; reason: "version_purged" em uma versão purgada
PERMISSION_DENIEDToken não tem o nível de acesso, ou uma regra de prefixo bloqueia o caminhorequired
INVALID_PATHCaminho falha na normalizaçãoreason
VERSION_CONFLICTexpected_version não correspondeu, ou o destino existecurrent_version, às vezes reason (por exemplo destination_exists)
LOCKEDOutro token detém um lock válidolocked_by_label, expires_at
QUOTA_EXCEEDEDOrganização excedeu sua cota de armazenamentolimit_bytes, used_bytes
TOO_LARGEConteúdo inline acima do limite, ou arquivo acima de 1 GiBmax_bytes
UPLOAD_EXPIREDFinalize chamado em um upload expirado ou já consumido
RATE_LIMITEDLimite de taxa do token ou da organização atingidoretry_after_ms
INTERNALFalha inesperada do servidorrequest_id
STRING_NOT_FOUNDedit: old_str não está presente no arquivodica
STRING_NOT_UNIQUEedit: old_str correspondeu mais de uma vez e replace_all não foi definido
NOT_EDITABLEedit: o arquivo não é texto
TOO_LARGE_FOR_EDITedit: arquivo acima de 16 MiB
INVALID_PATTERNgrep: o padrão não é RE2 válido

RATE_LIMITED é o único código que vale a pena tentar novamente automaticamente: durma retry_after_ms, então tente de novo.


Limites

LimiteValor
Escrita inline1 MiB decodificado; conteúdo maior passa por request_upload
Leitura inline256 KiB e um tipo MIME de texto, caso contrário uma URL de download
EdiçãoArquivos de texto até 16 MiB, até 20 edições por chamada
Grep8 MiB por arquivo verificado, 500 arquivos candidatos por chamada, resultados parciais além do orçamento de tempo
Tamanho máximo de arquivo1 GiB
URL PUT pré-assinada15 minutos
Registro de upload1 hora
URL de download15 minutos
Comprimento do caminho1024 bytes
TTL do lock5 minutos, renovável
Limite de taxa600 requisições por minuto por token, 3000 por minuto por organização

Exceder um limite de taxa retorna RATE_LIMITED com retry_after_ms.


Caminhos e versionamento

Caminhos são UTF-8, separados por / e sensíveis a maiúsculas/minúsculas. Eles são normalizados na entrada:

  • sem barra inicial: /a/b torna-se a/b
  • sem barras duplicadas
  • sem segmentos . ou .., e sem segmentos vazios
  • sem barra final em um arquivo
  • sem caracteres de controle
  • máximo de 1024 bytes

Qualquer outra coisa retorna INVALID_PATH com um reason. Diretórios são implícitos: não há registros de pasta, e list sintetiza pastas a partir de prefixos de caminho.

Versionamento. Cada mutação cria uma nova versão, numerada por arquivo. delete grava uma versão tombstone. move cria uma versão no destino e cria tombstone na origem. restore acrescenta uma nova versão reproduzindo um estado anterior. O histórico é somente-acréscimo e nunca é reescrito, e é por isso que uma restauração ruim é em si restaurável.

Concorrência otimista. O padrão é último-escrita-vence, o que é seguro porque nada é perdido. Quando você quer que uma escrita falhe em vez de sobrescrever uma mudança concorrente, passe expected_version com a versão que você leu. Uma incompatibilidade retorna VERSION_CONFLICT com current_version no payload, para que o chamador possa reler e decidir.

Locks. lock obtém um lock consultivo de 5 minutos, renovado chamando lock novamente com o mesmo token. Um lock válido estrangeiro faz as escritas retornarem LOCKED com locked_by_label e expires_at; override_lock: true prossegue mesmo assim e é registrado no feed de atividades. Locks nunca bloqueiam leituras.


Permissões

Cada token recebe acesso a workspaces específicos em um de três níveis:

NívelFerramentas
rolist, read, grep, history, activity
rwtudo em ro, mais write, edit, move, delete, restore, lock, unlock, request_upload, finalize_upload
adminreservado para futura gestão de workspaces

Uma concessão pode carregar regras de prefixo opcionais que restringem um token a pastas específicas, expressas como listas allow ou deny. Negar vence permitir. move exige permissão tanto no caminho de origem quanto no de destino.

Dê a cada agente seu próprio token. É isso que torna by_label em list, history e activity legíveis, e é o que permite revogar um agente sem afetar os outros.


Uploads de arquivos grandes

write inline tem limite de 1 MiB. Acima disso, envie em três passos.

1. Peça uma URL. Chame request_upload com a contagem exata 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. Faça PUT dos bytes em put_url. Isso é um PUT HTTP simples do arquivo bruto, não uma chamada MCP. A URL é válida por 15 minutos.

3. Confirme. Chame finalize_upload:

{ "upload_id": "..." }
{
  "path": "datasets/corpus.tar.gz",
  "size": 431912448,
  "version": 3,
  "content_hash": "..."
}

Por que não há SDK

Não há biblioteca cliente Layven e não haverá. Layven é um servidor MCP hospedado: você aponta seu cliente para uma URL e seu agente recebe 14 ferramentas, sem código para escrever e nada para manter atualizado. Esta é a única exceção. O fluxo de upload tem um passo intermediário que é um PUT HTTP bruto, e um cliente MCP não pode emitir um, então enviamos um único script sem dependências para isso. Copie, leia, altere. É MIT.

upload/layven-upload.mjs

Node 18 ou mais novo. Sem dependências, sem instalação.

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 é obrigatório. --url tem como padrão https://api.layven.io/mcp.

Execute seus testes a partir da raiz do repositório com:

node --test

Exemplos


Planos

FreePro $19/moScale $49/moEnterprise
Armazenamento5 GB100 GB500 GBPersonalizado
Histórico de versões30 dias1 anoIlimitadoIlimitado
Registro de atividades30 dias1 ano1 anoIlimitado
Espaços de trabalho1525Ilimitado
Tokens225100Ilimitado
Assentos1310Ilimitado
Tamanho máximo de arquivo1 GiB1 GiB1 GiB1 GiB
Limite de taxa600 req/min/token600 req/min/token600 req/min/token600 req/min/token

Preço fixo. Sem medidores, sem créditos.


Residência de dados

Seus arquivos são armazenados na OVHcloud em Gravelines, França, e são criptografados em repouso. Nenhuma IA de terceiros ou API de modelo toca no seu conteúdo. Você pode exportar tudo como arquivos simples, e a exclusão é uma exclusão real.


Versionamento

A versão em server.json e no changelog corresponde à versão que o servidor informa em initialize, para que você possa sempre verificar com o que está falando. Alterações na documentação que não acompanham uma alteração no servidor não incrementam a versão.

Veja CHANGELOG.md.


Suporte

Erros nestes documentos, nos exemplos ou no auxiliar de upload: abra uma issue. Dúvidas sobre conta, cobrança ou dados: info@layven.io.


Licença

O MIT cobre este repositório: a documentação, os exemplos e o auxiliar de upload. O serviço Layven em si é de código fechado.