SILO-MCP

Servidor MCP que move arquivos entre seu sistema de arquivos e armazenamento em nuvem.

Documentação

Silo MCP

License: MIT tests Python 3.11+ MCP

Um servidor MCP auto-hospedado que move arquivos entre seu sistema de arquivos e armazenamento em nuvem — nove plataformas, uma única superfície de ferramentas. Envie, baixe, liste, pesquise, exclua, gere links de compartilhamento e copie arquivos diretamente de uma nuvem para outra, sem dar a um LLM acesso bruto ao sistema de arquivos ou um saco de credenciais específicas de plataforma para gerenciar.

Não é "local-first" — os arquivos vivem na nuvem e cada operação fala com uma API de provedor remoto. O que permanece local é a parte que importa para a confiança: o servidor roda como um subprocesso na sua máquina, suas credenciais ficam no chaveiro do sistema operacional (nunca na nuvem, em um arquivo de configuração ou em um argumento de chamada de ferramenta), e o log de auditoria de transferências é um arquivo SQLite local.

Armazenamentos de documentos: Dropbox · Google Drive · OneDrive · Box · Google Photos (somente upload) · Yandex Disk Armazenamentos de objetos: compatível com S3 (AWS S3, Cloudflare R2, MinIO) · Google Cloud Storage · Azure Blob Storage

O que você pode fazer com o Silo MCP?

  • Copiar um arquivo diretamente de uma nuvem para outra — "copie meu arquivo /photos do Dropbox para meu bucket S3", "migre este arquivo do Drive para o OneDrive" — em uma única chamada de ferramenta, sem download manual seguido de upload. A única coisa que uma integração de armazenamento de um único fornecedor estruturalmente não consegue fazer.
  • Mover arquivos para dentro e para fora do armazenamento em nuvem — "envie report.pdf para o Dropbox", "baixe notes.txt do Google Drive para que eu possa usá-lo" — em todas as nove plataformas com um único conjunto de ferramentas.
  • Navegar e pesquisar seus armazenamentos de documentos por pasta ou consulta, e listar buckets de armazenamento de objetos por prefixo de chave.
  • Gerar links compartilháveis para um arquivo — URLs pré-assinadas/assinadas nos armazenamentos de objetos e no Box (com expiração), links de compartilhamento da plataforma nos demais.
  • Fazer ponte com outros servidores MCP — um download_file aqui gera um caminho local que você pode entregar diretamente a outro servidor (por exemplo, o media_paths de um servidor de postagem social).
  • Manter uma trilha de auditoria local — cada upload, download, exclusão e link de compartilhamento é registrado em um log SQLite local que você pode consultar com list_transfers.

Tudo isso passa pelo seu cliente MCP em linguagem natural — veja Exemplos de fluxos de trabalho.

Início rápido: pip install -e . → adicione silo-mcp à configuração do seu cliente MCP → silo-mcp-accounts add dropbox --label personal → peça ao seu cliente para listar seus arquivos do Dropbox. Passos completos em Instalação e Adicionar contas abaixo.

Conteúdo

Por quê

A maioria das configurações de "dê ao LLM seu armazenamento em nuvem" cai em uma de duas armadilhas: uma integração de plataforma única que morre no momento em que você troca de provedor, ou acesso irrestrito a arquivos locais que permite que uma conversa manipulada leia ou envie qualquer coisa no disco. O Silo MCP é construído contra ambas:

  • Uma superfície de ferramentas, nove plataformas. upload_file, download_file, list_files, search_files, delete_file, create_share_link se comportam da mesma forma independentemente da plataforma para a qual você os aponta — armazenamentos de objetos (bucket+chave) e armazenamentos de documentos (baseados em caminho) compartilham um único contrato FileStore.
  • Confinado por design, não por convenção. local_path para uploads e o destino para downloads são ambos argumentos de chamada de ferramenta fornecidos pelo LLM, então ambos são rigidamente confinados a diretórios raiz configurados — uma conversa manipulada não pode pedir a este servidor para ler uma chave SSH ou gravar um download em um lugar onde não deveria.
  • Mutações exigem confirm=true. upload_file, delete_file e create_share_link todas alteram estado remoto ou criam um link com credencial de portador e exigem confirmação deliberada. download_file/list_files/search_files apenas gravam localmente, então não exigem confirmação.
  • Multi-contas desde o início. Cada ferramenta aceita um rótulo opcional account — execute um Dropbox de trabalho e um Dropbox pessoal lado a lado sem reconfigurar nada.

Arquitetura

flowchart TB
    subgraph Client["MCP Client"]
        direction LR
        CD["Claude Desktop / Code<br/>(stdio)"]
        OL["Ollama bridge<br/>(streamable-http / SSE)"]
    end

    subgraph Silo["Silo MCP Server (server.py)"]
        direction TB
        Tools["Tool surface<br/>upload_file · download_file · list_files<br/>search_files · delete_file · create_share_link"]
        Paths["paths.py<br/>upload/download root containment"]
        Registry["stores/registry.py<br/>resolve(platform, account)"]
        Accounts["accounts.py<br/>credential storage + OAuth refresh"]
        History[("db.py<br/>SQLite transfer log")]
    end

    subgraph Backends["FileStore implementations"]
        direction LR
        Doc["Document stores<br/>Dropbox · Drive · OneDrive<br/>Box · Photos · Yandex Disk"]
        Obj["Object stores<br/>S3-compatible · GCS · Azure Blob"]
    end

    FS[("Local filesystem<br/>upload/download roots")]
    Cred[("OS credential store<br/>Windows / macOS / Linux keyring")]

    CD --> Tools
    OL --> Tools
    Tools --> Paths --> FS
    Tools --> Registry
    Registry --> Doc
    Registry --> Obj
    Registry --> Accounts --> Cred
    Tools --> History

Cada chamada de ferramenta resolve um par (platform, account) para uma implementação FileStore e uma credencial de accounts.py, verifica qualquer caminho local contra as raízes de upload/download, executa contra a API real da plataforma e registra o resultado — o mesmo formato independentemente de qual dos nove backends está do outro lado.

Requisitos

  • Python 3.11+
  • Um armazenamento de credenciais do sistema operacional que keyring possa usar (Gerenciador de Credenciais do Windows, Chaveiro do macOS ou um provedor de Secret Service no Linux) — credenciais nunca são gravadas em disco em texto puro ou passadas por uma chamada de ferramenta MCP.

Instalação

git clone https://github.com/gouthamkallempudi/silo-mcp.git
cd silo-mcp
python -m venv .venv
source .venv/bin/activate        # Windows: .venv\Scripts\Activate.ps1
pip install -e .

Os SDKs de armazenamento de objetos são extras opcionais — instale apenas o que precisar:

pip install -e ".[s3]"      # AWS S3 / Cloudflare R2 / MinIO
pip install -e ".[gcs]"     # Google Cloud Storage
pip install -e ".[azure]"   # Azure Blob Storage
pip install -e ".[all]"     # all three

Uma instalação principal (sem extras) cobre Dropbox/Drive/OneDrive/Box/Google Photos/Yandex Disk sem dependência além de httpx — o servidor degrada graciosamente se um SDK de armazenamento de objetos não estiver instalado, em vez de falhar ao iniciar.

Configure seu cliente MCP

Adicione à configuração MCP do seu cliente (por exemplo, o claude_desktop_config.json do Claude Desktop, ou o .mcp.json do Claude Code):

{
  "mcpServers": {
    "silo-mcp": {
      "command": "silo-mcp"
    }
  }
}

silo-mcp deve ser resolvível em PATH dentro do ambiente a partir do qual seu cliente inicia o servidor — se você instalou em um virtualenv, aponte command para o executável silo-mcp desse venv diretamente (por exemplo, /path/to/silo-mcp/.venv/bin/silo-mcp) em vez de depender da ativação do shell.

Opções de transporte (stdio padrão, HTTP para clientes de rede)

O padrão é stdio, o que todo cliente MCP de desktop (Claude Desktop, Claude Code, Cursor, etc.) inicia como subprocesso — nenhuma porta de rede é aberta. Para um cliente que não pode iniciar um subprocesso local e precisa alcançar o servidor via HTTP (veja Uso com Ollama abaixo), defina:

SILO_MCP_TRANSPORT=streamable-http SILO_MCP_HOST=127.0.0.1 SILO_MCP_PORT=8000 silo-mcp

SILO_MCP_TRANSPORT também aceita sse (o transporte HTTP mais antigo, mantido para clientes que ainda não migraram para streamable-http). SILO_MCP_HOST/ SILO_MCP_PORT são lidos apenas para os dois transportes HTTP e o padrão é 127.0.0.1:8000.

[!WARNING] Este servidor não tem autenticação embutida para o modo HTTP — não o vincule a 0.0.0.0 nem o exponha além de localhost sem colocar um proxy reverso com autenticação na frente dele, já que cada chamada de ferramenta alcança suas contas de armazenamento em nuvem.

Clientes suportados

Qualquer cliente MCP que possa iniciar um servidor stdio local funciona — o servidor usa apenas chamadas de ferramenta MCP padrão, sem recursos específicos de cliente. Verificados e esperados para funcionar:

ClienteConfiguraçãoNotas
Claude Code.mcp.json no projeto ({"mcpServers":{"silo-mcp":{"command":"silo-mcp"}}})Verificado de ponta a ponta pelo protocolo MCP.
Claude Desktopclaude_desktop_config.json — mesmo bloco mcpServersstdio.
Cursor / VS Code (MCP)mcp.json deles — mesmo bloco mcpServersstdio.
Ollama (via uma ponte)Aponte a ponte para o transporte HTTPVeja Uso com Ollama.

[!TIP] Se silo-mcp não estiver no PATH do shell de inicialização (comum com virtualenvs), defina command para o executável do venv diretamente, por exemplo, C:\\path\\to\\silo-mcp\\.venv\\Scripts\\silo-mcp.exe no Windows ou /path/to/.venv/bin/silo-mcp em outros sistemas.

Uso com Ollama

Ollama não fala MCP nativamente — ele precisa de um cliente MCP no meio que transforme a chamada de ferramentas do Ollama em chamadas de ferramenta MCP, o mesmo papel que Claude Desktop/Code desempenham para Claude. Este servidor não inclui essa ponte (mantida fora do escopo para permanecer um pacote de servidor simples), mas qualquer cliente Ollama com suporte a MCP funciona quando você o aponta para streamable-http em vez de stdio:

  1. Inicie o servidor no modo HTTP: SILO_MCP_TRANSPORT=streamable-http silo-mcp.
  2. Aponte seu cliente MCP do lado do Ollama para http://127.0.0.1:8000/mcp.
  3. Use um modelo com capacidade de chamada de ferramentas (por exemplo, llama3.1, qwen2.5) — o Ollama só roteia chamadas de ferramentas para modelos que suportam o campo de API tools.

Adicionar contas

As credenciais são adicionadas via CLI com entrada oculta, nunca por uma chamada de ferramenta MCP, e armazenadas no armazenamento de credenciais do seu sistema operacional:

silo-mcp-accounts add dropbox --label personal
silo-mcp-accounts add google_drive --label personal
silo-mcp-accounts add onedrive --label personal
silo-mcp-accounts add box --label personal
silo-mcp-accounts add google_photos --label personal
silo-mcp-accounts add yandex_disk --label personal
silo-mcp-accounts add s3 --label personal
silo-mcp-accounts add gcs --label personal
silo-mcp-accounts add azure_blob --label personal
silo-mcp-accounts list
Configuração OAuth pela primeira vez (Drive, Photos, OneDrive, Box)

Estas quatro plataformas precisam de um refresh_token antes que silo-mcp-accounts add as aceite — e obter o primeiro exige uma autorização única no navegador, não apenas um par client_id/secret. Registre um aplicativo no console de desenvolvedor de cada plataforma e depois execute:

silo-mcp-accounts oauth google_drive --label personal
silo-mcp-accounts oauth google_photos --label personal
silo-mcp-accounts oauth onedrive --label personal
silo-mcp-accounts oauth box --label personal

Isso abre seu navegador para a tela de consentimento da plataforma, escuta em http://localhost:8765/callback para o redirecionamento, troca o código por um refresh_token e armazena a conta — sem necessidade de executar add depois.

Registro de aplicativo, por plataforma:

  • Google (Drive + Photos compartilham um aplicativo): Google Cloud Console → novo projeto → APIs & Services → habilite a Google Drive API e a Photos Library API → tela de consentimento OAuth (Externo é suficiente para testes pessoais, adicione você mesmo como usuário de teste) → Credenciais → Criar ID de cliente OAuth → tipo Aplicativo de desktop. Clientes de aplicativo de desktop aceitam qualquer redirecionamento http://localhost:<port> sem pré-registro, então não é necessário configurar URI de redirecionamento.
  • OneDrive: Azure Portal → App registrations → Novo registro → plataforma Aplicativos móveis e de desktop → adicione o URI de redirecionamento http://localhost:8765/callback exatamente (o Azure exige correspondência exata). Permissões de API → Microsoft Graph → adicione Files.ReadWrite e offline_access (delegadas). Certificados e segredos → novo segredo de cliente.
  • Box: Box Developer Console → Criar novo aplicativo → Aplicativo personalizadoAutenticação de usuário (OAuth 2.0) → em Configuração, defina o URI de redirecionamento para http://localhost:8765/callback exatamente (o Box também exige correspondência exata) e marque os escopos que você precisa (Leitura/gravação de arquivos).

Se você usar --port para escolher uma porta local diferente, use essa mesma porta no URI de redirecionamento que você registrar.

Obtendo um token do Yandex Disk

O Yandex Disk usa um token estático como o Dropbox — sem refresh_token, então não faz parte do fluxo de inicialização silo-mcp-accounts oauth acima. Sua configuração de aplicativo OAuth usa uma concessão implícita: o token volta diretamente no navegador, sem etapa de troca de código para script.

  1. oauth.yandex.comCriar aplicativo (ou reutilize um existente).
  2. Em Plataformas, marque Serviços web e defina o URI de redirecionamento para https://oauth.yandex.com/verification_code — a página embutida do próprio Yandex que apenas exibe o token, sem necessidade de ouvinte local para este caso.
  3. Em Permissões, conceda acesso ao Disk: cloud_api:disk.read e cloud_api:disk.write (ou cloud_api:disk.app_folder em vez de disk.write se quiser limitar a uma pasta específica do aplicativo em vez de todo o disco).
  4. Salve o aplicativo e anote seu ID.
  5. Visite https://oauth.yandex.com/authorize?response_type=token&client_id=<your-app-id> em um navegador, aprove o acesso — o token é mostrado diretamente na página redirecionada.
  6. silo-mcp-accounts add yandex_disk --label personal, cole o token.
Configuração em massa mais rápida: importar arquivo ou variáveis de ambiente

Executar o add uma vez por plataforma fica cansativo rapidamente quando você está configurando várias de uma vez. Dois caminhos mais rápidos — ambos ainda terminam no chaveiro do sistema operacional, nunca em um arquivo ou variável de ambiente que este projeto persista por conta própria:

Arquivo de importação — copie o modelo, preencha os valores reais, importe de uma vez. silo-accounts.example.yaml na raiz do repositório tem uma entrada para todas as nove plataformas com os nomes exatos dos campos que cada uma precisa e um comentário sobre onde obter cada valor:

cp silo-accounts.example.yaml silo-accounts.yaml
# edit silo-accounts.yaml with real values, delete platforms you don't use
silo-mcp-accounts import silo-accounts.yaml

JSON também funciona (mesma forma platform -> label -> fields), despachado pela extensão do arquivo — qualquer coisa que não termine em .json é analisada como YAML.

silo-accounts.yaml/.json, credentials.yaml/.json e qualquer *.local.yaml/.json já estão em .gitignore, mas trate isso como uma rede de segurança, não como o plano — exclua o arquivo imediatamente após importá-lo. São segredos em texto puro no disco enquanto existirem, estejam ou não no gitignore.

Variáveis de ambiente — para configuração via script ou CI onde um arquivo não é prático, o addSILO_MCP_CRED_<PLATFORM>_<FIELD> antes de solicitar:

SILO_MCP_CRED_DROPBOX_ACCESS_TOKEN=sl.xxx silo-mcp-accounts add dropbox --label personal

Variáveis de ambiente são mais expostas do que um arquivo que você exclui (listagens de processos, histórico do shell, dumps de crash) — prefira o arquivo de importação para qualquer coisa além de configuração automatizada rápida de teste.

Exemplos de fluxos de trabalho

Uma vez que o servidor está conectado, você não chama as ferramentas diretamente — você pede ao seu cliente MCP (Claude Desktop, Claude Code, etc.) em linguagem natural e ele escolhe a ferramenta e os argumentos certos. Esses exemplos foram todos exercitados de ponta a ponta sobre o protocolo MCP real contra contas ativas do Dropbox, Google Drive e Google Photos.

Dropbox / OneDrive / Yandex Disk (caminhos reais):

  • "Envie report.pdf da minha pasta de uploads para o Dropbox."
  • "O que há na raiz do meu Dropbox? Encontre qualquer coisa chamada invoice."
  • "Baixe notes.txt do Dropbox e me dê um link compartilhável para ele."
  • "Exclua old-draft.txt do meu Dropbox."

Google Drive / Box (endereçado por id — pesquise primeiro, depois aja no id):

  • "Encontre budget.xlsx no meu Google Drive." → depois "Baixe esse."
  • "Compartilhe esse arquivo com um link público."

Google Photos (somente upload):

  • "Envie esta captura de tela para o meu Google Photos."

Armazenamentos de objetos — S3 / GCS / Azure Blob (precisam de um bucket/contêiner):

  • "Envie backup.zip para o meu bucket S3 my-backups."
  • "Liste tudo sob logs/ no bucket my-backups."
  • "Me dê um link pré-assinado de 1 hora para backup.zip em my-backups."

Cópia entre nuvens (de uma plataforma direto para outra):

  • "Copie report.pdf do meu Dropbox para o meu Google Drive."
  • "Migre tudo o que acabei de encontrar no Drive para o meu bucket S3 archive."

Entre servidores:

  • "Pegue minha foto de perfil do Google Drive para eu anexá-la a um post." — download_file entrega um caminho local que outro servidor MCP pode usar.

O mapeamento completo de frases para chamadas de ferramenta:

Você dizO que é executado
"Que armazenamento em nuvem posso usar aqui e quais contas estão configuradas?"list_supported_stores
"Envie report.pdf da minha pasta de uploads para o Dropbox."upload_file(dropbox, …, confirm=true) — o cliente define confirm depois que você concorda
"O que há na raiz do meu Dropbox?"list_files(dropbox)
"Encontre arquivos chamados invoice no meu Dropbox."search_files(dropbox, "invoice")
"Baixe notes.txt do Dropbox para eu poder usá-lo."download_file(dropbox, "/notes.txt")
"Me dê um link compartilhável para esse arquivo."create_share_link(dropbox, …, confirm=true)
"Exclua old-draft.txt do Dropbox."delete_file(dropbox, "/old-draft.txt", confirm=true)
"Coloque esta imagem no meu Google Photos."upload_file(google_photos, …, confirm=true)
"Copie meu currículo do Dropbox para um rascunho de tweet."download_file aqui → entregue o caminho local para o media_paths de outro servidor MCP
"Mostre o que movi recentemente."list_transfers

Como o Google Drive e o Box endereçam arquivos por id, um fluxo natural lá é em duas etapas — "encontre budget.xlsx no meu Drive" (search_files, retorna o id), depois "baixe esse" / "compartilhe esse" usando o id que o cliente acabou de ver. O cliente cuida desse encadeamento para você.

Ações de mutação (upload_file, delete_file, create_share_link) exigem confirm=true, então um bom cliente mostrará exatamente o que está prestes a fazer e só prosseguirá após sua aprovação — uma exclusão ou um link público nunca acontece silenciosamente a partir de um pedido vago.

Ferramentas

FerramentaPortão de confirmaçãoDescrição
list_supported_stores()Cada plataforma conhecida, seu tipo (documento vs. armazenamento de objetos), capacidades e contas configuradas.
list_accounts(platform)Contas configuradas, opcionalmente filtradas.
upload_file(platform, local_path, remote_path, account, target, confirm)local_path deve estar dentro da raiz de upload.
download_file(platform, remote_path, local_filename, account, target)Grava na raiz de download e retorna o caminho local.
list_files(platform, folder_or_prefix, account, target)Listagem de pastas (armazenamentos de documentos) ou listagem de prefixos (armazenamentos de objetos).
search_files(platform, query, account, target)Erros claros onde a plataforma não suporta pesquisa.
delete_file(platform, remote_path, account, target, confirm)
create_share_link(platform, remote_path, account, target, expires_in_seconds, confirm)Um link que qualquer pessoa pode usar para ler o arquivo sem conta, onde houver suporte. Veja Links de compartilhamento.
copy_file(from_platform, from_remote_path, to_platform, to_remote_path, from_account, to_account, from_target, to_target, confirm)Copie um arquivo direto de uma nuvem para outra. Veja Cópia entre nuvens.
list_transfers(platform, limit)Log de auditoria local de uploads, downloads, exclusões, links de compartilhamento e cópias entre nuvens.
get_client_capabilities(platform)Verifique o que uma plataforma suporta antes de chamá-la.

target é o nome do bucket/contêiner para armazenamentos de objetos — ignorado para armazenamentos de documentos.

Links de compartilhamento

expires_in_seconds é honrado nativamente em S3, GCS, Azure Blob e Box (URLs pré-assinadas/assinadas, ou o unshared_at do Box). Dropbox, Google Drive, OneDrive e Yandex Disk também criam um link, mas nenhuma de suas APIs suporta expiração em conta pessoal/não comercial, então o parâmetro é aceito para consistência de interface, mas não é aplicado lá. Não disponível no Google Photos (somente upload).

Protegido por confirm=true mesmo que não mova ou exclua dados — a URL retornada é em si uma credencial de portador, a mesma preocupação de exfiltração que upload_file tem.

Cópia entre nuvens

copy_file move um arquivo diretamente de uma plataforma para outra — "copie meu /photos/id.png do Dropbox para meu bucket backups do S3", "migre este arquivo do Drive para o OneDrive" — em uma única chamada de ferramenta. Esta é a única coisa que uma integração de armazenamento de fornecedor único estruturalmente não pode fazer; é a recompensa de colocar todos os backends atrás de uma única interface.

sequenceDiagram
    actor User
    participant Client as MCP Client<br/>(Claude)
    participant Silo as Silo MCP
    participant Src as Source cloud<br/>(Dropbox)
    participant Dst as Destination cloud<br/>(Google Drive)

    User->>Client: "Copy report.pdf from Dropbox to my Google Drive"
    Client->>Silo: copy_file(from=dropbox, to=google_drive, confirm=false)
    Silo-->>Client: dry run — will copy /report.pdf → google_drive:report.pdf
    Client-->>User: About to copy Dropbox → Google Drive. Approve?
    User->>Client: yes
    Client->>Silo: copy_file(…, confirm=true)
    Note over Silo: stream through a temp file<br/>the server controls
    Silo->>Src: download /report.pdf
    Src-->>Silo: bytes → temp file on disk
    Silo->>Dst: upload from temp file
    Dst-->>Silo: new file id + metadata
    Note over Silo: delete temp file,<br/>log 'copy' to the audit trail
    Silo-->>Client: copied ✓
    Client-->>User: Done — report.pdf is now in your Google Drive

O LLM nunca toca nos bytes do arquivo ou em um caminho intermediário — ele apenas emite uma chamada copy_file e o servidor cuida do download → temp → upload → limpeza, protegido pela sua aprovação.

  • Ele transmite através de um arquivo local temporário que o servidor cria e exclui — você nunca lida com um download/upload intermediário, e o caminho temporário nunca é um argumento fornecido pelo chamador (portanto, não está sujeito à verificação de contenção da raiz de upload da mesma forma que upload_file está).
  • from_remote_path é endereçado da forma que a plataforma de origem espera para um download (um caminho para Dropbox/OneDrive/Yandex/armazenamentos de objetos; um id de arquivo para Google Drive/Box — pesquise primeiro para obtê-lo). to_remote_path assume o nome base da origem por padrão; passe-o explicitamente quando a origem for endereçada por id.
  • from_target/to_target são os nomes de bucket/contêiner quando qualquer extremidade é um armazenamento de objetos.
  • Exige confirm=true — ele grava no destino. Registrado no log de auditoria como um copy, com ambas as extremidades capturadas.

[!NOTE] A cópia é limitada pelos mesmos limites de 5 GiB de download/upload, e o download da origem é transmitido para o disco, então uma cópia grande entre nuvens não armazenará o arquivo inteiro em memória.

Plataformas e ferramentas suportadas

Quais operações cada plataforma suporta e seu modelo de autenticação. ✅ suportado · — não suportado. target = o nome do bucket/contêiner que os armazenamentos de objetos exigem.

PlataformaTipoUploadDownloadListarPesquisarExcluirLink de compartilhamentoAuth
DropboxdocumentoToken estático
Google DrivedocumentoOAuth2 refresh
OneDrivedocumentoOAuth2 refresh
Boxdocumento✅ (com expiração)OAuth2 refresh
Google PhotosdocumentoOAuth2 refresh
Yandex DiskdocumentoToken estático
Compatível com S3objeto (precisa de target)✅ (pré-assinado)Chave/segredo estáticos
Google Cloud Storageobjeto (precisa de target)✅ (assinado)JSON de conta de serviço
Azure Blobobjeto (precisa de target)✅ (SAS)String de conexão

[!NOTE] Google Photos é somente upload — o Google removeu o acesso à API de leitura da biblioteca em março de 2025. Armazenamentos de objetos e Yandex Disk não têm pesquisa de conteúdo, apenas listagem por prefixo/caminho. Detalhes em Notas específicas da plataforma.

Fricção de configuração e formato de credenciais por plataforma

Tabela de formato de credenciais
PlataformaCredencialModelo de authConfiguração
Dropboxaccess_tokenToken estáticoApp Console → gerar token. Sem dança de refresh. Veja escopos abaixo — um erro missing_scope significa regenerar, não reconfigurar.
Yandex Diskaccess_tokenToken estático, concessão implícita (sem etapa de troca de código)Veja Obtendo um token do Yandex Disk acima.
Azure Blobconnection_stringEstáticoConta de armazenamento → Chaves de acesso. O mais simples dos armazenamentos de objetos.
S3access_key_id, secret_access_key, opcional region/endpoint_urlEstáticoUsuário IAM da AWS, ou credenciais R2/MinIO + endpoint_url.
GCSservice_account_jsonJWT (conta de serviço)Google Cloud Console → criar uma chave de conta de serviço, cole o JSON inteiro.
Google Driveclient_id, client_secret, refresh_tokenOAuth2, atualizado a cada chamadaTela de consentimento OAuth do Google Cloud + uma autorização única para obter o token de refresh inicial.
Google Photosigual ao DriveOAuth2, escopo photoslibrary.appendonlyMesmo aplicativo do Google Cloud; somente upload, veja abaixo.
OneDriveclient_id, client_secret, refresh_tokenOAuth2, atualizado a cada chamadaRegistro de aplicativo no Azure AD.
Boxclient_id, client_secret, refresh_tokenOAuth2, atualizado a cada chamada, token rotacionaAplicativo de desenvolvedor Box. Cada refresh emite um novo token de refresh automaticamente e este servidor o persiste de volta no chaveiro — não reutilize um antigo manualmente.

Dropbox, Yandex Disk, S3, GCS e Azure Blob usam credenciais estáticas lidas uma vez. Google Drive, OneDrive, Box e Google Photos são todos OAuth2 de grandes empresas de tecnologia com tokens de acesso de curta duração (~1h) — este servidor chama o endpoint de token de cada plataforma novamente antes de cada solicitação de API, em vez de armazenar em cache, mantendo a história de correção simples ao custo de uma solicitação extra rápida (~200ms) por chamada.

Permissões/escopos necessários por plataforma

Os campos de credencial acima só lhe dão um token — o token também precisa do escopo certo, ou cada chamada falha com um erro de permissão, independentemente de quão corretamente esteja armazenado. Configurado no lado da plataforma, não aqui:

PlataformaEscopo(s) obrigatório(s)Onde configurar
Dropboxfiles.content.write, files.content.read, files.metadata.read, sharing.write (para create_share_link)App Console → aba Permissões → marque os escopos → clique em Enviar. Os escopos são fixados no momento da emissão do token — você deve gerar um token novo após alterar os escopos; um token já emitido não os adquire retroativamente.
Yandex DiskAcesso total ao disco (leitura/gravação)configuração do app em oauth.yandex.com → marque a permissão de leitura/gravação do Disco ao criar o app, antes de emitir o token.
Google Drivehttps://www.googleapis.com/auth/driveSolicitado automaticamente pelo silo-mcp-accounts oauth google_drive — nada a configurar manualmente além de ativar a API do Drive no projeto.
Google Photoshttps://www.googleapis.com/auth/photoslibrary.appendonlyIgual ao acima, via silo-mcp-accounts oauth google_photos; ative a API da Biblioteca de Fotos no projeto.
OneDriveFiles.ReadWrite, offline_access (delegado)Portal do Azure → registro do app → Permissões de API → Microsoft Graph → adicione ambas e depois Conceda consentimento do administrador se o seu locatário exigir. Também solicitado automaticamente pelo silo-mcp-accounts oauth onedrive.
Box"Ler e gravar todos os arquivos e pastas armazenados no Box" (ou mais restrito, conforme sua necessidade)Developer Console → app → aba ConfiguraçãoEscopos do aplicativo.
S3s3:GetObject, s3:PutObject, s3:ListBucket, s3:DeleteObject no bucket de destino (além disso, a geração de URLs pré-assinadas não exige permissão extra — é uma operação de assinatura local)política do IAM anexada ao usuário/papel cujas access_key_id/secret_access_key você está usando.
GCSStorage Object Admin (ou Object Viewer + Object Creator para uma concessão mais restrita) no bucket/projetoIAM e Administrador → conceda o papel à conta de serviço antes de gerar a chave dela.
Azure BlobAcesso total à conta pela chave da conta na cadeia de conexão — não existe o conceito de escopo separadoN/A — a própria cadeia de conexão é o limite de permissão; use uma cadeia de conexão restrita por SAS se quiser limitar o escopo.

[!TIP] O Dropbox é o que tem mais chance de te surpreender: um 401 missing_scope com um token aparentemente correto quase sempre significa que os escopos foram alterados depois que o token foi gerado. Regere o token, não apenas salve-o novamente.

Segurança de caminhos

local_path para uploads e o nome do arquivo de destino para downloads são ambos argumentos de chamada de ferramenta fornecidos pelo LLM, então ambos ficam confinados a uma raiz configurada cada, nas duas direções:

  • SILO_MCP_UPLOAD_ROOT (padrão ~/silo-mcp/uploads) — arquivos fora deste diretório não podem ser enviados. Isso importa muito aqui: sem isso, uma conversa manipulada poderia pedir ao servidor para enviar um arquivo local arbitrário (chaves SSH, .env, repositórios de credenciais do navegador) para uma conta na nuvem — persistente, compartilhável, sem nenhum artefato visível na plataforma avisando que algo saiu da máquina.
  • SILO_MCP_DOWNLOAD_ROOT (padrão ~/silo-mcp/downloads) — downloads não podem ser gravados fora deste diretório por meio de um nome de arquivo forjado.

Uploads têm limite de 5 GiB (MAX_UPLOAD_BYTES) e downloads de 5 GiB (SILO_MCP_MAX_DOWNLOAD_BYTES, substituível). Downloads são transmitidos em fluxo para o disco e abortados no meio do caminho se ultrapassarem o limite, então um arquivo inesperadamente enorme não pode esgotar a memória. As credenciais são armazenadas no chaveiro do sistema operacional, nunca no banco SQLite; o fluxo de autorização OAuth de uso único usa PKCE e um valor state aleatório (RFC 8252) para que o redirecionamento de loopback não possa ser forjado.

Observações específicas por plataforma

Assimetrias e limitações conhecidas
  • O Google Photos é somente para upload. O Google removeu os escopos de leitura da biblioteca da API Photos Library em março de 2025 — um app agora só pode gerenciar itens de mídia que ele mesmo criou. Navegar ou baixar a biblioteca existente de um usuário exige a "Picker API" interativa (uma sessão de interface web), que uma chamada de ferramenta MCP sem cabeça não consegue acionar. list_files/download_file/ search_files retornam um erro claro em vez de fingir que funcionam. Também não existe nenhuma capacidade de exclusão para o Google Photos, neste projeto ou na API do Google — qualquer coisa enviada é permanente até ser removida manualmente via photos.google.com.
  • O Google Drive e o Box endereçam arquivos por id, não por caminho, para download/exclusão — o remote_path do upload é usado como nome de arquivo (somente raiz do Drive / pasta raiz do Box, sem direcionamento de pastas na v1); para baixar/excluir, você precisa primeiro do id de list_files/search_files. OneDrive, Dropbox e Yandex Disk usam caminhos reais em todo lugar, sem assimetria.
  • Os armazenamentos de objetos não suportam pesquisa — apenas listagem por prefixo via list_files. search_files retorna um erro claro de "não suportado". O Yandex Disk também não tem um endpoint de pesquisa dedicado e se comporta da mesma forma (listagem por caminho via list_files apenas).
  • Os endpoints de upload aqui são todos de disparo único (Dropbox ≤150MB, OneDrive ≤4MB); upload em partes/retomável de arquivos grandes ainda não está implementado para nenhuma plataforma.

Segurança

upload_file, delete_file e create_share_link exigem confirm=true — eles alteram o estado remoto ou fornecem um link com credencial de portador. download_file/list_files/search_files não exigem confirmação, pois apenas gravam localmente.

Status de testes com conta real

Dropbox, Google Drive e Google Photos foram verificados de ponta a ponta pelo protocolo MCP real — um cliente MCP inicia o servidor, faz a descoberta de ferramentas e chama as ferramentas pelo nome, exatamente como o Claude Desktop/ Code faria — não apenas por chamadas diretas em Python.

PlataformaStatus
Dropbox✅ Verificado pelo protocolo MCP contra uma conta real: upload_file (simulação + confirmado), list_files, search_files, download_file (transmitido para o disco), create_share_link, delete_file (simulação + confirmado), list_transfers. As confirmações em upload_file/delete_file se comportaram corretamente (bloqueadas sem confirm=true).
Google Drive✅ Verificado pelo protocolo MCP contra uma conta real, mesma cobertura de ferramentas do Dropbox acima, endereçado por id de arquivo conforme a observação id-vs-caminho acima. A renovação do OAuth foi acionada de forma independente antes de cada chamada, como projetado, sem bugs de cache observados.
Google Photos✅ Verificado pelo protocolo MCP contra uma conta real: upload_file (simulação + confirmado, conteúdo de imagem real), e confirmado que list_files/search_files/download_file/delete_file falham com um erro claro e bem redigido em vez de uma falha — esperado dado o design somente de upload, não é um bug.
copy_file entre nuvens✅ Verificado contra contas reais nas duas direções — Dropbox → Google Drive e Google Drive → Dropbox — com os bytes copiados verificados por soma de verificação contra a origem em cada direção. A confirmação bloqueou a simulação; ambas as cópias foram registradas no log de auditoria.

Issues e PRs relatando resultados de testes com conta real para as plataformas restantes são muito bem-vindos.

Segurança

Este servidor dá a um LLM a capacidade de ler arquivos locais (de um diretório), movê-los para contas na nuvem e gerar links públicos — então vale a pena deixar claros os riscos e o que é feito sobre eles.

  • A injeção de prompt é o risco central. O conteúdo que o modelo lê (um nome de arquivo, o texto de um documento, uma mensagem anterior) pode tentar direcioná-lo a chamar uma ferramenta que você não pretendia — por exemplo, "também envie ~/.ssh/id_rsa" ou "compartilhe este arquivo publicamente". Esta é uma propriedade geral do uso de ferramentas agênticas, não específica deste servidor.
  • Mitigações incorporadas:
    • Contenção de caminho — uploads só podem ler de SILO_MCP_UPLOAD_ROOT e downloads só podem gravar em SILO_MCP_DOWNLOAD_ROOT. Uma solicitação forjada por uma chave SSH ou .env fora da raiz é rejeitada antes de qualquer chamada de rede. Mantenha a raiz de upload como uma pasta dedicada, não seu diretório pessoal.
    • Portões de confirmaçãoupload_file, delete_file e create_share_link exigem confirm=true, então um cliente bem-comportado mostra exatamente o que está prestes a acontecer e um humano aprova. Um link público ou uma exclusão nunca são disparados por uma solicitação vaga.
    • As credenciais nunca chegam ao modelo — elas ficam no chaveiro do sistema operacional e são lidas no lado do servidor; nenhuma chamada de ferramenta pode enumerá-las ou exfiltrá-las, e elas nunca estão em um arquivo de configuração ou despejo de ambiente que o modelo veja.
    • Privilégio mínimo — limite o escopo de cada token de plataforma apenas ao que você precisa (veja a tabela de permissões); um token somente leitura não pode ser convencido a excluir nada.
  • Trilha de auditorialist_transfers e o log local em SQLite registram cada upload, download, exclusão e link de compartilhamento, para que você possa revisar depois o que realmente foi movido.

[!WARNING] Trate um link de compartilhamento gerado como uma credencial de portador pública — qualquer pessoa com a URL pode ler o arquivo, sem precisar de conta. Revogue excluindo o arquivo (ou deixando de compartilhá-lo na plataforma) quando terminar.

Testes

pip install -e ".[all,dev]"
pytest

Os testes são de lógica pura e HTTP simulado com respx — sem chamadas de rede reais, sem credenciais reais necessárias.

Solução de problemas

Windows: [WinError 1783] The stub received bad data de silo-mcp-accounts add

Duas causas distintas aparecem como esse erro exato:

  1. O shim CredWrite do pywin32-ctypes. O keyring prefere esse shim ao pywin32 real mesmo quando ambos estão instalados (veja o backends/Windows.py do keyring, que tenta pywin32-ctypes primeiro). Correção:

    pip uninstall pywin32-ctypes -y
    

    Exige pywin32 já instalado (já incluído de forma transitiva aqui via mcp). Reinstalar/atualizar o keyring depois pode trazer o pywin32-ctypes de volta como dependência dele — execute novamente a desinstalação se isso reaparecer após uma atualização.

  2. O limite rígido de ~2560 bytes (~1280 caracteres) por segredo do Gerenciador de Credenciais do Windows — um limite real do sistema operacional não relacionado a (1), confirmado ao reproduzir o erro idêntico com pywin32 real e uma string simples superdimensionada. Alguns formatos de token do Dropbox e o service_account_json do GCS (rotineiramente com mais de 2000 caracteres) excedem isso facilmente com credenciais totalmente legítimas, não apenas erros de colagem. Agora tratado de forma transparente — o add_account divide qualquer segredo acima do limite em várias entradas do chaveiro e o remonta na leitura, em todas as plataformas (não apenas no Windows, para que o comportamento não difira silenciosamente por sistema operacional). Nada a fazer aqui; se você ainda encontrar um erro, provavelmente é genuinamente grande demais (mais de 200.000 caracteres) em vez deste limite.

Relacionados

Projeto irmão no mesmo estilo MCP auto-hospedado com confirmação: um servidor MCP de postagem social (transmite posts em vez de mover arquivos) — formato de capacidade e limite de confiança diferentes, componível no nível do cliente MCP em vez de um código compartilhado (o download_file aqui pode entregar um caminho local diretamente ao media_paths daquele servidor).

Licença

MIT