ctfd-mcp
Servidor MCP para CTFd que permite que usuários comuns naveguem por desafios, gerenciem instâncias dinâmicas e enviem flags.
GitHub
25
Experimente este MCPPatrocinadoDocumentação
Servidor MCP CTFd (escopo de usuário)
Servidor MCP que permite a um usuário comum do CTFd listar desafios, ler detalhes, iniciar/parar instâncias dinâmicas do docker e enviar flags.
Requisitos
- Python 3.13 (gerenciado por
uv). - Variáveis de ambiente (escolha um método de autenticação):
CTFD_URL(ex.: https://ctfd.example.com)CTFD_TOKEN(token de usuário, não admin) ouCTFD_SESSION(cookie de sessão se os tokens estiverem desabilitados).CTFD_CSRF_TOKEN(opcional, somente se o servidor/plugin exigir CSRF para ctfd-owl).
Você pode armazená-los em um arquivo .env na raiz do repositório:
CTFD_URL=https://ctfd.example.com/
CTFD_USERNAME=your_username
CTFD_PASSWORD=your_password
# or, if you prefer to use a token:
# CTFD_TOKEN=your_ctfd_api_token_here
# or, if tokens are disabled:
# CTFD_SESSION=your_session_token_here
# and, if the owl plugin enforces CSRF:
# CTFD_CSRF_TOKEN=your_csrf_token_here
Instalação
- Do PyPI (recomendado):
uvx ctfd-mcp --help - Do checkout do código-fonte (sem instalação):
uvx --from . ctfd-mcp --help
Executar servidor MCP (stdio)
# installed from PyPI
uvx ctfd-mcp
# from local checkout
uvx --from . ctfd-mcp
Exemplo de configuração MCP para Cursor e Claude
{
"mcpServers": {
"ctfd-mcp": {
"command": "uvx",
"args": ["ctfd-mcp"],
"env": {
"CTFD_URL": "https://ctfd.example.com",
"CTFD_TOKEN": "your_user_token"
}
}
}
}
Exemplo de configuração MCP para Codex
[mcp_servers.ctfd-mcp]
command = "uvx"
args = ["ctfd-mcp"]
[mcp_servers.ctfd-mcp.env]
CTFD_URL = "https://ctfd.example.com"
CTFD_TOKEN = "your_user_token"
Ferramentas expostas
list_challenges(category?, only_unsolved?)— lista desafios visíveis, com filtro opcional por categoria/não resolvidos.challenge_details(challenge_id)— descrição (HTML +description_text), metadados, URLs de anexos, status de resolução.submit_flag(challenge_id, flag)— tenta uma flag; retorna status/mensagem.start_container(challenge_id)— início unificado; detecta automaticamente dynamic_docker, ctfd-owl ou k8s/api/v1/k8s.stop_container(container_id?, challenge_id?)— parada unificada; whale pode ser parado apenas comcontainer_id, owl/k8s precisam dechallenge_id.
Anexos são retornados como URLs absolutas em files; o cliente/host pode buscá-los diretamente.
Recursos MCP
resource://ctfd/challenges/{challenge_id}— snapshot em markdown de um desafio (metadados, descrição, URLs de anexos, informações de conexão se presentes).
Tratamento de erros
- Env/config ausente -> erro MCP claro.
- 401/403 -> falha de autenticação, verifique token ou cookie de sessão.
- 404 -> não encontrado (ou API de contêiner dinâmico ausente).
- 429 -> limite de taxa atingido (Retry-After se presente).
- Outros erros HTTP/API -> exibidos como erros MCP com mensagem/status do CTFd.
Notas e solução de problemas
- Contêineres dinâmicos exigem o plugin ctfd-whale (dynamic_docker) no CTFd de destino; caso contrário,
/api/v1/containersretorna 404. - Desafios Owl (
dynamic_check_docker) usam um endpoint diferente:/plugins/ctfd-owl/container?challenge_id=<id>. Eles geralmente exigem um cookie de sessão, e algumas configurações exigem um token CSRF; definaCTFD_CSRF_TOKENse necessário. - Alguns eventos expõem instâncias baseadas em Kubernetes em
/api/v1/k8s/{get,create,delete}com dados de formulário multipart; o cliente tentará esses quando o tipo de desafio incluirk8s(ou quando um endpoint dynamic_docker estiver ausente). - Se o servidor redirecionar você para
/login(302) ao usar um token, mude para um cookie de sessão do navegador: definaCTFD_SESSIONa partir do cookiesessionapós fazer login. - O cliente agora suporta login com
CTFD_USERNAMEeCTFD_PASSWORD; esses campos têm precedência sobre tokens/sessões desatualizados. - Prioridade de autenticação: usuário/senha primeiro, depois token, depois cookie de sessão. Credenciais de prioridade mais baixa são ignoradas quando uma opção de prioridade mais alta está presente.
Suporte / feedback
Se algo quebrar ou você tiver dúvidas, entre em contato:
- Telegram: @ismailgaleev
- Jabber: ismailgaleev@chat.merlok.ru
- Email: umbra2728@gmail.com
Testes
- Execute
uv run pytest. - Timeouts são configuráveis via env:
CTFD_TIMEOUT(total),CTFD_CONNECT_TIMEOUT,CTFD_READ_TIMEOUT(segundos). Os padrões são 20s total / 10s conexão / 15s leitura.
Desenvolvimento
- Dependências de desenvolvimento:
uv sync --group dev - Lint/formatação:
uv run ruff check .euv run ruff format . - Testes:
uv run pytest - Pre-commit:
uv run pre-commit install(vejaCONTRIBUTING.md)
Licença
Apache-2.0. Veja LICENSE.