CTFd MCP Server
Enables interaction with CTFd platforms for Capture The Flag competitions, allowing users to list challenges, read details, manage dynamic Docker containers, and submit flags through natural language.
README
CTFd MCP server (user scope)
MCP server that lets a regular CTFd user list challenges, read details, start/stop dynamic docker instances, and submit flags.
Requirements
- Python 3.13 (managed by
uv). - Environment variables (choose one auth method):
CTFD_URL(e.g. https://ctfd.example.com)CTFD_TOKEN(user token, not admin) orCTFD_SESSION(session cookie if tokens are disabled).CTFD_CSRF_TOKEN(optional, only if the server/plugin requires CSRF for ctfd-owl).
You can store them in a .env file in the repo root:
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
Install
- From PyPI (recommended):
uvx ctfd-mcp --help - From source checkout (no install):
uvx --from . ctfd-mcp --help
Run MCP server (stdio)
# installed from PyPI
uvx ctfd-mcp
# from local checkout
uvx --from . ctfd-mcp
Cursor and Claude MCP config example
{
"mcpServers": {
"ctfd-mcp": {
"command": "uvx",
"args": ["ctfd-mcp"],
"env": {
"CTFD_URL": "https://ctfd.example.com",
"CTFD_TOKEN": "your_user_token"
}
}
}
}
Codex MCP config example
[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"
Exposed tools
list_challenges(category?, only_unsolved?)— list visible challenges, optional category/unsolved filter.challenge_details(challenge_id)— description (HTML +description_text), metadata, attachment URLs, solved status.submit_flag(challenge_id, flag)— attempt a flag; returns status/message.start_container(challenge_id)— unified start; auto-detects dynamic_docker, ctfd-owl or k8s/api/v1/k8s.stop_container(container_id?, challenge_id?)— unified stop; whale can be stopped with justcontainer_id, owl/k8s needchallenge_id.
Attachments are returned as absolute URLs in files; the client/host can fetch them directly.
MCP resources
resource://ctfd/challenges/{challenge_id}— markdown snapshot of a challenge (metadata, description, attachment URLs, connection info if present).
Error handling
- Missing env/config -> clear MCP error.
- 401/403 -> auth failed, check token or session cookie.
- 404 -> not found (or dynamic container API missing).
- 429 -> rate limited (Retry-After if present).
- Other HTTP/API errors -> surfaced as MCP errors with CTFd message/status.
Notes and troubleshooting
- Dynamic containers require the ctfd-whale (dynamic_docker) plugin on the target CTFd; otherwise
/api/v1/containersreturns 404. - Owl challenges (
dynamic_check_docker) use a different endpoint:/plugins/ctfd-owl/container?challenge_id=<id>. They usually require a session cookie, and some setups require a CSRF token; setCTFD_CSRF_TOKENif needed. - Some events expose Kubernetes-backed instances at
/api/v1/k8s/{get,create,delete}with multipart form data; the client will try these when the challenge type includesk8s(or when a dynamic_docker endpoint is missing). - If the server redirects you to
/login(302) when using a token, switch to a browser session cookie: setCTFD_SESSIONfrom thesessioncookie after logging in. - The client now supports logging in with
CTFD_USERNAMEandCTFD_PASSWORD; these fields take precedence over stale tokens/sessions. - Auth priority: username/password first, then token, then session cookie. Lower-priority credentials are ignored when a higher-priority option is present.
Support / feedback
If something breaks or you have questions, reach out:
- Telegram: @ismailgaleev
- Jabber: ismailgaleev@chat.merlok.ru
- Email: umbra2728@gmail.com
Testing
- Run
uv run python -m tests.test_ctfd_client(requires a realCTFD_URLplus token or username/password) to exercise challenge fetching/submission flows. - Timeouts are configurable via env:
CTFD_TIMEOUT(total),CTFD_CONNECT_TIMEOUT,CTFD_READ_TIMEOUT(seconds). Defaults are 20s total / 10s connect / 15s read.
Development
- Dev dependencies:
uv sync --group dev - Lint/format:
uv run ruff check .anduv run ruff format . - Tests:
uv run python -m unittest discover -s tests - Pre-commit:
uv run pre-commit install(seeCONTRIBUTING.md)
License
Apache-2.0. See LICENSE.
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.