Skip to main content
Glama
README.md
# mcp_colab

Servidor MCP que deixa o Claude trabalhar dentro de um notebook do
Google Colab: ler e editar os arquivos do projeto, rodar codigo Python
no mesmo kernel e executar comandos de shell na VM.

```
[claude.ai] --HTTPS--> [ngrok] --tunel--> [servidor MCP no Colab] --> [arquivos + Python + shell da VM]
```

## Setup no Colab

### 1. Criar os dois secrets (so na primeira vez)

Gere um token de autenticacao:

```python
import secrets; print(secrets.token_urlsafe(32))
```

No painel lateral do Colab (icone de chave, "Secrets"), crie:

| Nome | Valor | Acesso ao notebook |
|---|---|---|
| `MCP_AUTH_TOKEN` | o token gerado acima | ligado |
| `NGROK_AUTHTOKEN` | seu authtoken de ngrok.com (conta gratuita serve) | ligado |

### 2. Instalar

```python
!git clone https://github.com/filipe-romaneli/mcp_colab.git
!pip install -q -r mcp_colab/requirements.txt
```

### 3. Subir o servidor

```python
import os, sys

os.environ["MCP_ALLOWED_ROOT"] = "/content/projeto"  # pasta que o Claude pode acessar
sys.path.insert(0, "/content/mcp_colab")

import server
url = server.start()
```

A celula imprime a URL do connector (ja com o token embutido) e **nao
trava o notebook**: o servidor roda numa thread, entao voce continua
usando as outras celulas normalmente. Como o `run_python` executa no
mesmo processo, as variaveis que voce cria no notebook e as que o Claude
cria sao compartilhadas.

Para trabalhar em arquivos do Drive, monte o Drive antes e aponte
`MCP_ALLOWED_ROOT` para a pasta desejada.

### 4. Conectar no Claude

Em claude.ai: **Settings -> Connectors -> Add custom connector**, cole a
URL impressa pela celula anterior (formato
`https://xxxx.ngrok-free.app/mcp/<token>`).

Para testar o tunel antes, abra `https://xxxx.ngrok-free.app/health` no
navegador: deve responder `ok`.

### A cada nova sessao do Colab

A VM e o tunel sao efemeros: ao reiniciar o Colab a URL do ngrok muda e
o connector precisa ser atualizado com a URL nova. O token continua o
mesmo (esta nos secrets).

## Tools disponiveis

| Tool | O que faz |
|---|---|
| `list_directory(path)` | lista arquivos e pastas |
| `read_file(path)` | le um arquivo com numeros de linha |
| `write_file(path, content)` | cria/sobrescreve um arquivo |
| `edit_file(path, old_string, new_string)` | substitui um trecho especifico |
| `search_code(pattern, path)` | busca regex recursiva |
| `run_python(code, timeout)` | executa Python no kernel (estado persiste entre chamadas) |
| `run_shell(command, timeout)` | executa comando de shell na raiz do projeto |

Resource `info://ambiente`: raiz do projeto, versao do Python, GPU
disponivel e espaco em disco.

## Seguranca

- **Token no caminho da URL**: o endpoint MCP fica em `/mcp/<token>` e
  qualquer outro caminho responde 404 -- quem varrer a URL do tunel nao
  distingue "token errado" de "nao ha nada aqui". So `/health` e publico.

  O token vai no caminho, e nao num header `Authorization`, de proposito:
  responder 401 com `WWW-Authenticate: Bearer` e, no protocolo MCP, o
  sinal de "autentique-se via OAuth", e o claude.ai obedece esse sinal e
  falha ao tentar se registrar num servidor de OAuth que este projeto nao
  tem. O servidor nunca emite esse desafio.
- **Diretorio restrito**: as tools de arquivo so acessam
  `MCP_ALLOWED_ROOT`; paths com `../` ou absolutos apontando para fora
  sao recusados.
- **Host allowlist**: o servidor so aceita requests com o `Host` do
  tunel atual (protecao contra DNS rebinding); qualquer outro leva 421.
- **Comandos destrutivos bloqueados**: `run_shell` recusa `rm -rf /`,
  `mkfs`, `dd` para device, fork bomb, `shutdown`/`reboot`,
  `chmod`/`chown` recursivo na raiz e escrita direta em `/dev/sd*`.
- **Timeout** padrao de 60s em `run_python` e `run_shell`.

Pontos a ter em mente: a URL do connector contem o token, entao nao
compartilhe o notebook com a saida dessa celula salva (use
`server.start(show_token=False)` se for compartilhar); e o blocklist de
comandos e uma rede contra acidentes, nao um sandbox -- quem tem o token
consegue executar codigo arbitrario na VM, que e justamente o proposito
do projeto.

## Estrutura

```
config.py             # tokens, diretorio permitido, timeout, comandos bloqueados
auth.py                # middleware do caminho secreto (/mcp/<token>)
server.py               # registra as tools, monta o app HTTP, abre o tunel
tools/
  filesystem.py           # list/read/write/edit/search
  execution.py             # run_python, run_shell
tests/                      # pytest (rodam localmente, sem Colab)
```

## Rodando os testes

```bash
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
MCP_ALLOWED_ROOT=/tmp/projeto python -m pytest tests/ -q
```

## Uso local (sem Colab)

Com `MCP_AUTH_TOKEN` e `MCP_ALLOWED_ROOT` exportados, `python server.py`
sobe em stdio (para clientes MCP locais) e
`MCP_TRANSPORT=http python server.py` sobe em HTTP com tunel.