Skip to main content
Glama
README.md
# mcp-tools-for-agents

**Dê mãos ao seu agente de IA. Um binário, nenhuma instalação.**

Um servidor MCP local, em Rust, que entrega ao seu agente ferramentas reais de
vídeo, áudio e arquivos. Sem API, sem UI, sem runtime. São 36 tools compiladas em
um executável único: baixe o `mcp-tools` da sua plataforma, aponte o host MCP para
ele e pronto.

Funciona com Claude Code, Claude Desktop, Cursor e qualquer host MCP.

## Por que Rust

O servidor precisa de **um arquivo**:

- **Binário único por plataforma.** Linux (x86_64, arm64), macOS (Intel, Apple
  Silicon) e Windows. Sem runtime, sem dependência de sistema.
- **FFmpeg e yt-dlp sob demanda.** Se não estiverem no PATH nem ao lado do
  binário, o servidor baixa os builds estáticos oficiais na primeira chamada e
  guarda em uma pasta de cache. Desligue com `MCP_AUTO_DOWNLOAD=false`.
- **Fonte e modelos embutidos.** A DejaVu Sans Bold (para texto e legenda), o
  YuNet (detector de rosto do OpenCV Zoo) e o Silero VAD (detector de fala) vão
  dentro do executável.
- **Transcrição, visão e fala nativas.** `transcribe_audio` usa o whisper.cpp
  (`whisper-rs`); `smart_crop` roda o YuNet e `remove_silence` e
  `add_background_music` rodam o Silero VAD no `tract`, runtime ONNX em Rust
  puro. Nada de OpenCV ou onnxruntime instalado.
- **Mesmos princípios.** Erro que ensina (`{error, code, hint}`), workspace
  como fronteira, jobs em background, resposta sempre tipada, um arquivo por tool.

## Em 60 segundos

Baixe o pacote da sua plataforma na [página de releases](https://github.com/theGuil/mcp-tools-for-agents/releases/latest)
(ou compile, abaixo), descompacte e rode:

```bash
WORKSPACE_DIR=/dados/videos ./mcp-tools     # servidor no ar, via stdio
```

Na primeira tool que precisar de FFmpeg (ou de yt-dlp) o binário é baixado para
o cache. Se preferir, coloque `ffmpeg`, `ffprobe` e `yt-dlp` ao lado do
`mcp-tools` ou no PATH: eles têm prioridade e nada é baixado.

### Compilar do fonte

```bash
cargo build --release --features full   # binário completo (transcrição + visão + fala)
cargo build --release                   # binário leve, sem os extras
```

Requisitos de build: Rust estável (1.85+); com `--features full`, também `cmake`
e um compilador C++ (o whisper.cpp é compilado e linkado estaticamente). O
executável fica em `target/release/mcp-tools` (~24 MB). No Linux ele depende só
da glibc e da libstdc++ do sistema, presentes em qualquer distribuição.

## Plugar no agente

```json
{
  "mcpServers": {
    "mcp-tools-for-agents": {
      "command": "/caminho/mcp-tools",
      "env": { "WORKSPACE_DIR": "/dados/videos" }
    }
  }
}
```

Cole isso no `.mcp.json` (Claude Code), no `claude_desktop_config.json` (Claude
Desktop) ou no equivalente do seu host. Pronto: peça "corta os 10 primeiros
segundos do intro.mp4" e veja acontecer.

### Claude Code neste repositório

Abrindo este repositório no Claude Code nada precisa ser compilado: o hook
`SessionStart` em `.claude/settings.json` roda `scripts/install-mcp-tools.sh`,
que baixa o `mcp-tools` da **última release** para `bin/` (pasta ignorada pelo
git), e o `.mcp.json` sobe o servidor por `scripts/mcp-tools-run.sh`, que espera esse download terminar (ou baixa sozinho) antes de executar `bin/mcp-tools`. Para atualizar à mão ou
fixar uma versão:

```bash
sh scripts/install-mcp-tools.sh                        # última release
MCP_TOOLS_VERSION=v0.1.0 sh scripts/install-mcp-tools.sh   # versão fixa
MCP_TOOLS_FORCE=true sh scripts/install-mcp-tools.sh   # baixa de novo
```

### Publicar uma release

Automático. A cada merge em `producao`, o workflow `.github/workflows/release.yml`
cria a próxima tag `vX.Y.Z`, compila o binário completo (`--features full`) para
Linux x86_64 e arm64, macOS Intel e Apple Silicon e Windows, e anexa os pacotes
à release.

## Tools

| Domínio | Tool | O que faz |
|---|---|---|
| files | `list_files` | Lista arquivos do workspace, com filtro por tipo |
| files | `delete_file` | Apaga um arquivo |
| video | `probe_video` | Duração, resolução, fps, codecs |
| video | `cut_video` | Recorta um trecho, com ou sem re-encode |
| video | `concat_videos` | Junta vídeos em sequência, com corte seco ou 20 transições (fade, wipe, slide...) |
| video | `remove_silence` | Corta as pausas em que ninguém fala, reconhecendo voz por rede neural (Silero VAD) ou por limiar em dB |
| video | `detect_scenes` | Encontra mudanças de cena |
| video | `extract_frame` | Salva um frame como imagem |
| video | `add_text_overlay` | Escreve título ou descrição sobre a imagem |
| video | `create_subtitles` | Gera um .srt a partir de trechos com tempos |
| video | `burn_subtitles` | Grava legendas de um .srt ou .ass no vídeo, com cor, tamanho e posição |
| video | `set_video_metadata` | Embute título, descrição e autor no arquivo |
| video | `add_narration` | Mistura um áudio de narração no vídeo |
| video | `add_sound_effects` | Insere efeitos sonoros (vine boom, ding, whoosh) em instantes do vídeo, buscando no Freesound se preciso |
| video | `list_templates` | Lista os templates visuais disponíveis |
| video | `apply_template` | Shorts 9:16, quadrado, 16:9, título de abertura, marca d'água |
| video | `add_banner` | Faixa com fundo colorido e texto no topo ou rodapé, o tempo todo ou num intervalo |
| video | `add_background_music` | Música de fundo em loop, com fade e ducking de `duck_db` guiado pela fala (Silero VAD) |
| video | `add_fade` | Fade de entrada e saída na imagem e no som |
| video | `change_speed` | Acelera ou desacelera o vídeo todo ou um trecho, mantendo o tom da voz |
| video | `zoom_video` | Punch-in de impacto ou zoom progressivo (Ken Burns) em um trecho |
| video | `apply_studio_background_light` | Acende uma luz colorida de estúdio no fundo (halo radial, de cima, de baixo ou nas laterais), com presets de cor ou cor própria |
| video | `stabilize_video` | Tira o tremor de câmera na mão, com o vid.stab em dois passes |
| video | `create_dynamic_subtitles` | Legenda animada palavra por palavra em .ass, com presets (hormozi, boxed, karaoke, pop, clean, neon), fonte, contorno e sombra |
| video | `create_thumbnail` | Capa do vídeo com título grande, nos tamanhos de YouTube, Shorts e feed |
| video | `smart_crop` | Reenquadra 16:9 para 9:16 seguindo o rosto de quem fala (feature `vision`) |
| video | `export_for_platform` | Codifica o vídeo final com o preset de TikTok, Reels, Shorts, YouTube ou X, em H.264, H.265 ou AV1, pela placa de vídeo quando há uma |
| audio | `extract_audio` | Separa a trilha de áudio |
| audio | `transcribe_audio` | Transcreve fala com timestamps por trecho e por palavra (feature `transcribe`) |
| audio | `normalize_audio` | Normaliza o volume para o loudness da plataforma (EBU R128, duas passadas) |
| media | `get_video_info` | Título, duração, descrição e capítulos de uma URL, sem baixar |
| media | `download_video` | Baixa o vídeo de qualquer site (yt-dlp) para o workspace |
| media | `search_sound_effects` | Busca efeitos sonoros gratuitos no Freesound por descrição em texto |
| media | `download_sound_effect` | Baixa um efeito do Freesound (MP3) para a pasta `sfx/` do workspace |
| jobs | `job_status` | Estado de um job em background |
| jobs | `job_result` | Saída de um job concluído |

Ative só o que precisa com `MCP_DOMAINS=video,files`.

## O que é baixado, e quando

O binário não traz FFmpeg nem yt-dlp dentro (são ~150 MB e ~30 MB, com licenças
próprias). Ele os procura nesta ordem e para na primeira que encontrar:

1. o caminho em `FFMPEG_BIN`, `FFPROBE_BIN` ou `YTDLP_BIN`, se for um caminho;
2. a pasta onde o `mcp-tools` está;
3. o `PATH`;
4. a pasta de cache (`MCP_CACHE_DIR`);
5. download, se `MCP_AUTO_DOWNLOAD=true` (padrão).

| O quê | De onde | Quando |
|---|---|---|
| ffmpeg + ffprobe | builds estáticos BtbN (Linux, Windows) e evermeet.cx (macOS) | primeira tool de vídeo ou áudio |
| yt-dlp | release oficial no GitHub (executável standalone, sem Python) | primeiro `download_video` / `get_video_info` |
| modelo Whisper (`ggml-<size>.bin`) | Hugging Face, repositório `ggerganov/whisper.cpp` | primeiro `transcribe_audio` com aquele `model_size` |
| fonte DejaVu | embutida; gravada no cache só se o sistema não tiver fonte | primeira tool com texto |
| modelos YuNet e Silero VAD | embutidos no binário (`core/models`) | nunca baixados |

Cache padrão: `~/.cache/mcp-tools-for-agents` (Linux), `~/Library/Caches/mcp-tools-for-agents`
(macOS), `%LOCALAPPDATA%\mcp-tools-for-agents` (Windows). Para um pacote 100% offline,
coloque esses arquivos na pasta do binário (`ffmpeg`, `ffprobe`, `yt-dlp`,
`models/ggml-base.bin`, `fonts/DejaVuSans-Bold.ttf`).

### Download de qualquer fonte

`download_video` e `get_video_info` aceitam qualquer URL http(s). São três
tentativas, nesta ordem:

1. **Extractor nativo do yt-dlp** — cobre mais de mil sites.
2. **Extractor genérico** — lê o HTML da página e procura `<video>`, `<source>`,
   HLS `.m3u8`, DASH `.mpd`, players conhecidos e JSON-LD.
3. **Varredura própria** — o servidor busca a página, junta as mídias diretas e
   desce um nível nos `iframe`.

Não há como baixar conteúdo com DRM nem páginas que exigem login. Nesses casos o
`hint` do erro diz para não insistir.

### Efeitos sonoros do Freesound

`add_sound_effects` recebe uma lista de efeitos com o instante em que cada um
toca e aplica tudo em um único passo do ffmpeg. Cada efeito vem de `query`
(busca no Freesound), `sound_id` (resultado de `search_sound_effects`) ou
`audio` (arquivo do workspace). A chave da API já vem embutida em `config.rs`;
`FREESOUND_API_KEY` no ambiente substitui.

### Features opcionais

Algumas tools dependem de bibliotecas pesadas, ligadas por feature do Cargo:

```bash
cargo build --release --features transcribe   # whisper-rs: transcribe_audio
cargo build --release --features vision       # tract + YuNet: smart_crop com mode="face"
cargo build --release --features vad          # tract + Silero VAD: remove_silence e ducking com method="vad"
cargo build --release --features full         # as três (é o que a release publica)
```

Sem a feature, a tool continua registrada e devolve um erro `unavailable`
explicando como habilitar; `smart_crop` segue funcionando com `mode="center"` e
`remove_silence` e `add_background_music` com o limiar de dB (`method="db"`).

O modelo do Silero VAD em `core/models/silero_vad_16k.onnx` é o oficial (16 kHz,
opset 15) com os nós `If` resolvidos para forma fixa, que o `tract` não traduz;
`scripts/prepare-silero-vad.py` regenera o arquivo a partir do original.

## Configuração

Todas as variáveis estão em `.env.example`. As principais:

| Variável | Padrão | Para quê |
|---|---|---|
| `YTDLP_BIN` | `yt-dlp` | Nome ou caminho do yt-dlp |
| `MCP_AUTO_DOWNLOAD` | `true` | Baixar ffmpeg, yt-dlp e modelos sob demanda |
| `MCP_CACHE_DIR` | cache do sistema | Onde os downloads ficam |

## Como é por dentro

A árvore fica na raiz do crate (o `Cargo.toml` aponta para a raiz em vez de `src/`):

```
server.rs     cria o McpServer, monta o Runtime e registra os domínios
config.rs     único lugar que lê variáveis de ambiente (Settings)
core/         ffmpeg, paths, jobs, errors, binários externos, rede. Não conhece MCP.
domains/      um módulo por área, um arquivo por tool
tests/        espelha a estrutura acima
```

Uma tool inteira, do jeito que todas são:

```rust
pub fn delete_file(runtime: &Runtime, path: &str) -> ToolResult<DeleteFileResult> {
    let target = runtime.workspace.existing(path)?;
    let size = std::fs::metadata(&target).map(|m| m.len()).unwrap_or(0);
    std::fs::remove_file(&target).map_err(|error| {
        ToolError::new(format!("Não foi possível apagar '{path}': {error}"), ErrorCode::NotFound)
    })?;
    Ok(DeleteFileResult { deleted: runtime.workspace.relative(&target), freed_bytes: size })
}

#[derive(Debug, Deserialize, JsonSchema)]
pub struct Params {
    /// Arquivo, relativo ao workspace.
    pub path: String,
}

pub fn register(mcp: &mut McpServer, runtime: &Arc<Runtime>) {
    let runtime = Arc::clone(runtime);
    mcp.tool(
        "delete_file",
        "Apaga permanentemente um arquivo do workspace.\n\n\
         Use para limpar saídas intermediárias. Não há lixeira nem desfazer.",
        move |params: Params| guarded(delete_file(&runtime, &params.path)),
    );
}
```

Função pura e testável em cima, registro com a description para o agente
embaixo. `Err(ToolError)` vira `{error, code, hint}` na resposta.

## Contribuir

Quer uma tool nova? Copie `domains/files/delete.rs`, troque o miolo, escreva o
teste espelhado em `tests/`, adicione a linha na tabela acima. As regras
completas estão em `.claude/rules/arquitetura.md`, e se você usa Claude Code,
`/nova-tool` faz o roteiro.

Antes do PR, os três precisam passar:

```bash
cargo fmt --check
cargo clippy --all-targets -- -D warnings
cargo test
```

Os testes que usam ffmpeg são pulados quando o binário não está instalado.

## Licença

MIT. A fonte DejaVu embutida segue a licença Bitstream Vera
(`core/fonts/LICENSE-DejaVu.txt`); o modelo YuNet é MIT (OpenCV Zoo).

TDQS

A4.4/5.0

Scored across 11 tools

Disambiguation5/5

Each tool targets a distinct operation: audio extraction, transcription, video probing, cutting, concatenation, scene detection, frame extraction, file listing/deletion, and job status/result retrieval. There is no meaningful overlap that would cause an agent to select the wrong tool.

Naming Consistency5/5

All tool names follow the snake_case verb_noun convention (extract_audio, cut_video, detect_scenes, list_files, delete_file) except job_status and job_result, which are noun_noun but still clearly patterned and consistent with the job subsystem. The style is uniform and predictable.

Tool Count5/5

11 tools is well within the ideal range for a focused media-processing server. Each tool covers a distinct need in the workflow: file discovery, inspection, editing, extraction, cleanup, and async job handling. No tool feels redundant or unnecessary.

Completeness4/5

The tool surface covers the core video/audio processing lifecycle: inspect, cut, concat, detect scenes, extract audio/frame, and transcribe, plus file and job management. Minor gaps exist such as no job cancellation or listing, and no upload tool, but these do not block the primary workflows.

Maintenance

ActivityMaintained
ResponsivenessNo issues