Secure Agent Workspace

Um espaço de trabalho isolado e agêntico que oferece execução segura de sistema de arquivos, bash e Python com suporte a uv.

Documentação

🛡️ Servidor MCP do Agent Workspace

CI License: MIT Python 3.14+

Um servidor unificado do Model Context Protocol (MCP) que fornece um workspace containerizado e altamente seguro para Modelos de Linguagem de Grande Escala (LLMs). Ele atua como um "playground agêntico" isolado, onde agentes podem codificar, testar e depurar de forma autônoma, sem arriscar a máquina host.


✨ Recursos

  • 🏗️ Ciclo de Vida Completo do Projeto: Inicialize projetos com uv init, gerencie dependências com uv add e execute via uv run.
  • 🐚 Acesso Seguro ao Bash: Execute comandos de shell com timeouts obrigatórios e fluxos de saída mesclados.
  • 🚀 Saída Otimizada para Tokens: Integra o RTK (Rust Token Killer) para filtrar e compactar automaticamente saídas de run_bash (como ls, git e executores de testes), economizando 60-90% dos tokens de contexto do LLM.
  • 📂 Sistema de Arquivos Robusto: Operações protegidas contra traversal de caminho para leitura, escrita e busca no workspace.
  • 🛡️ Segurança em Múltiplas Camadas: Execução sem root, capacidades removidas, limites de recursos e sistema de arquivos raiz somente leitura.
  • Edição de Precisão: search_and_replace avançado com correspondência difusa de espaços em branco, preservação de indentação, suporte a dry-run e validação de sintaxe para Python, JSON, JSONL, TOML e YAML.
  • 📊 Observabilidade em Tempo Real: Registro direto na interface do cliente MCP e logs de auditoria rotativos persistentes.

🏗️ Arquitetura

flowchart TD
    Client["MCP Client (Claude / Cursor)"] -- "stdio (JSON-RPC)" --> FastMCP["FastMCP Server"]

    subgraph Sandbox ["Docker Sandbox Container (mcpuser)"]
        direction TB
        
        FastMCP -. "Intercepts accidental prints" .-> StdioGuard["StdoutRedirector"]
        FastMCP -. "Application Logs" .-> Logger["Dual Logger (stderr & .mcp/server.log)"]
        
        FastMCP -- "Tool Calls" --> SecurityGuard["Security & Path Validator"]
        
        subgraph Toolset ["Tool Modules"]
            direction TB
            SecurityGuard --> FSTools["Filesystem (read, write, list, search)"]
            SecurityGuard --> EditTools["Editing (search_and_replace)"]
            SecurityGuard --> ExecTools["Execution (run_bash)"]
        end

        EditTools -- "AST Verification" --> Validator["Syntax Validations (Python, JSON, JSONL, TOML, YAML)"]
        ExecTools -- "Process Group (Timeout=60s)" --> Shell["/bin/sh Subprocess"]
        Shell -- "Package Mgt & Checks" --> UV["uv Environment / Ruff"]
        
        FSTools -- "Secure I/O" --> Workspace["/workspace Directory"]
        EditTools -- "Atomic Writes" --> Workspace
        Shell -- "Executes within" --> Workspace
    end

    Workspace <--"Volume Mount"--> HostFS["User Host Filesystem"]

📦 Início Rápido

1. Baixe ou Construa a Imagem Docker

# Pull from GHCR
docker pull ghcr.io/hrrodan/agent-workspace-mcp:latest

# OR: Build locally with your host's UID/GID for optimal permissions
docker build --build-arg UID=$(id -u) --build-arg GID=$(id -g) -t agent-workspace-mcp .

2. Uso Programático (OpenAI Agents SDK)

Aqui está um boilerplate rápido mostrando como usar o workspace containerizado programaticamente usando o SDK padrão openai-agents:

import asyncio
from agents import Agent, Runner
from agents.mcp import MCPServerStdio

async def main():
    # 1. Configure the MCP Server to run via Docker
    server = MCPServerStdio(
        name="Sandboxed Workspace",
        params={
            "command": "docker",
            "args": [
                "run", "-i", "--rm", "--init",
                # "--network", "none", # Network Isolation (optional) - see below
                "--memory=2g", "--cpus=2.0",
                "--pids-limit=256",
                "--cap-drop=ALL", "--security-opt=no-new-privileges:true",
                "--read-only",
                "--tmpfs", "/tmp:size=64m",
                "--tmpfs", "/home/mcpuser/.cache:size=512m",
                "--user", "1000:1000", # Replace with your host UID:GID
                "-v", "/path/to/your/projects:/workspace",
                "ghcr.io/hrrodan/agent-workspace-mcp:latest",
            ],
        },
        client_session_timeout_seconds=60.0,
    )

    # 2. Attach server to the Agent and load the skill instructions (optional)
    with open("skills/agent-workspace-mcp/SKILL.md", "r") as f:
        skill_instructions = f.read()

    agent = Agent(
        name="WorkspaceAgent",
        instructions=f"You are a coding agent with access to a secure workspace.\n\n{skill_instructions}",
        mcp_servers=[server],
    )

    # 3. Execute a workflow
    async with server:
        result = await Runner.run(
            agent, 
            "Create a python script in the workspace to print the first 10 Fibonacci numbers, then run it."
        )
        print(f"Agent's Final Output:\n{result.final_output}")

if __name__ == "__main__":
    asyncio.run(main())

3. Uso com Clientes MCP (Claude / Cursor)

Adicione a seguinte configuração às suas configurações do claude_desktop_config.json ou do Cursor.

{
  "mcpServers": {
    "agent-workspace-mcp": {
      "command": "docker",
      "args": [
        "run", "-i", "--rm", "--init",
        // "--network", "none", // Network Isolation (optional) - see below
        "--memory=2g", "--cpus=2.0",
        "--pids-limit=256",
        "--cap-drop=ALL", "--security-opt=no-new-privileges:true",
        "--read-only",
        "--tmpfs", "/tmp:size=64m",
        "--tmpfs", "/home/mcpuser/.cache:size=512m",
        "--user", "1000:1000",
        "-v", "/path/to/your/projects:/workspace",
        "ghcr.io/hrrodan/agent-workspace-mcp:latest"
      ]
    }
  }
}

[!IMPORTANT] Usuários Linux: Substitua 1000:1000 pelo seu UID:GID real (execute id -u e id -g). O Claude Desktop não expande variáveis de ambiente. Tratamento de Sinais: A flag --init é essencial para o encaminhamento adequado de sinais e a eliminação de processos zumbis.


🛠️ Referência de Ferramentas

FerramentaDescrição
read_fileLê arquivos de texto com offset e limit opcionais (padrão: 100 linhas).
write_fileCria arquivos com validação de sintaxe e limite de tamanho de 5MB. Recusa sobrescrever arquivos existentes por padrão (create_only=True).
list_directoryLista conteúdos com prefixos de [F] e [D].
search_workspaceEncontra arquivos por padrão glob com suporte a exclude_patterns.
run_bashExecuta comandos de shell em /workspace com timeout de 60s. Otimizado automaticamente via RTK para reduzir o uso de tokens.
search_and_replaceFerramenta de múltiplas edições com correspondência difusa de espaços em branco, preservação de indentação, modo dry-run e validação de sintaxe (Python, JSON, JSONL, TOML, YAML).

⚙️ Configuração

O servidor suporta as seguintes variáveis de ambiente (passadas via Docker --env):

VariávelPadrãoDescrição
COMMAND_TIMEOUT60Segundos padrão antes de run_bash encerrar um processo.
MAX_SEARCH_RESULTS50Resultados máximos retornados por search_workspace.
MAX_READ_SIZE_BYTES1048576Tamanho máximo de arquivo para read_file (1MB).
MAX_WRITE_SIZE_BYTES5242880Tamanho máximo de arquivo para write_file (5MB).
LOG_LEVELINFONível de registro do Python (DEBUG, INFO, etc.).

🛡️ Modelo de Segurança e Arquitetura

Este servidor emprega uma estratégia de defesa em profundidade, separando explicitamente limites rígidos de segurança de recursos de experiência do desenvolvedor e confiabilidade operacional.

🔒 Recursos Principais de Segurança

Esses recursos são projetados para proteger o sistema host e impor limites rígidos de isolamento.

  • Endurecimento do Kernel: Todas as capacidades Linux são removidas (--cap-drop=ALL), neutralizando vetores de escalonamento de privilégios.
  • Código do Servidor Imutável: O diretório /app contendo o código-fonte do servidor e seu ambiente virtual pertence a root e é somente leitura para mcpuser. Isso impede que o servidor se modifique ou seja adulterado via run_bash.
  • Bloqueio de Privilégios: Impõe no-new-privileges:true para impedir que qualquer processo obtenha direitos elevados.
  • Núcleo do Sistema Imutável: O sistema de arquivos raiz do contêiner é montado inteiramente somente leitura, fornecendo uma segunda camada de defesa contra adulteração no nível do sistema operacional.
  • Cotas de Recursos: Limitações rígidas de CPU, memória e PIDs mitigam tentativas de negação de serviço (DoS), como fork-bombs e esgotamento do host.
  • Aplicação Rígida de Limites: Um validador de caminho robusto bloqueia abrangentemente todos os ataques de traversal de caminho fora do /workspace designado.
  • Controle de Processos e Recursos: Timeouts obrigatórios de comando (padrão de 60s) e isolamento rigoroso de grupos de processos garantem que processos descontrolados ou maliciosos sejam encerrados.
  • Proteção contra Sobrecarga de Memória: Limites rígidos em leituras de arquivos (1MB) e saídas de comandos (50KB) previnem o esgotamento de memória.
  • Prevenção de Vazamento de Informações: Rastreamentos de pilha internos e caminhos de sistema são suprimidos e sanitizados das saídas das ferramentas.

🛠️ Experiência do Desenvolvedor e Conveniência

Recursos focados em integração perfeita, usabilidade e redução de atrito em fluxos de trabalho agênticos.

  • Identidade Não-Root Alinhada ao Host: Executa como mcpuser com UID/GID personalizável no momento da construção, eliminando conflitos tediosos de permissão de arquivos em montagens de volumes do host.
  • Otimização Automática de Tokens: Comandos de shell executados via run_bash são reescritos de forma transparente pelo RTK para fornecer saída ultracompacta e amigável ao LLM, sem alterar o comportamento subjacente do comando.
  • Exclusões Inteligentes de Busca: Diretórios de alto ruído ou sensíveis (.git, .venv) são ignorados automaticamente para manter as janelas de contexto enxutas e relevantes.
  • Workspaces Efêmeros: Os contêineres são estritamente efêmeros (--rm), garantindo um estado limpo e previsível para cada nova sessão, sem vazamento de estado entre conexões.
  • Descoberta Padronizada: Conformidade com a Especificação de Imagem OCI para integração padronizada no ecossistema de contêineres e auditoria transparente.

⚙️ Mecanismos de Confiabilidade e Segurança

Recursos que garantem a integridade estrutural do workspace e fornecem observabilidade.

  • Validação de Sintaxe Pré-Gravação: Tanto write_file quanto search_and_replace realizam validação de sintaxe em memória para Python, JSON, JSONL, TOML e YAML antes de persistir alterações, prevenindo estados de código quebrados.
  • Gravação à Prova de Falhas: write_file bloqueia sobrescritas acidentais de arquivos existentes por padrão e impõe um limite de tamanho de 5MB para prevenir inundação do workspace.
  • Operações Atômicas de Arquivo: Edições utilizam lógica de temp-e-move para garantir a integridade dos arquivos e prevenir corrupção, mesmo durante interrupções ou falhas inesperadas.
  • Observabilidade Transparente: Todas as invocações de ferramentas e mudanças de estado são transmitidas em tempo real para a interface do cliente MCP para supervisão imediata do operador.

🌐 Isolamento de Rede (Opcional)

Por padrão, o contêiner tem acesso total à rede via rede bridge do Docker. Para isolamento máximo, você pode desabilitar completamente a pilha de rede usando --network none:

docker run -i --rm --init \
  --network none \
  --memory=2g --cpus=2.0 --pids-limit=256 \
  --cap-drop=ALL --security-opt=no-new-privileges:true \
  --read-only \
  --tmpfs /tmp:size=64m \
  --tmpfs /home/mcpuser/.cache:size=512m \
  --user 1000:1000 \
  -v /path/to/your/projects:/workspace \
  ghcr.io/hrrodan/agent-workspace-mcp:latest

Isso cria um sandbox totalmente isolado (air-gapped) — apenas a interface loopback existe dentro do contêiner. Todas as conexões de saída (curl, DNS, uv add, etc.) falharão imediatamente, eliminando completamente os riscos de exfiltração de dados e movimento lateral.

[!NOTE] Com --network none, o agente não pode instalar pacotes em tempo de execução. Todas as dependências devem ser pré-instaladas em uma imagem personalizada ou pré-populadas no volume do workspace montado.


🤝 Contribuindo

  1. Instale Dependências de Desenvolvimento: uv sync
  2. Execute Linting: uv run ruff check .
  3. Execute Testes Unitários: uv run pytest tests/ --ignore=tests/integration/
  4. Execute Testes de Integração: Defina OPENROUTER_API_KEY e execute uv run pytest tests/integration/

© 2026 HrRodan. Licenciado sob MIT.