
CTFd
io.github.MrJamescotPublished by GitHub account MrJamescotv1.0.4Updated Oct 24, 2026
MCP server for CTFd v3: list challenges, submit flags, and query scoreboards via AI agents.
Overview
MCP server for CTFd v3 instances that lets an AI assistant browse challenges, submit flags, unlock hints and check scoreboards.
- What you can do
- Point the server at a CTFd instance and set credentials (base URL, API token, session cookie, or form login). List and filter challenges by category, name and solved status, and read full detail for one challenge. Submit flags with explicit confirmation and unlock hints. Download challenge attachments to a local directory. Read the public scoreboard, your own progress and instance metadata. Check authentication status and instance health.
- When to use it
- Useful when you work a CTFd-based capture-the-flag competition and want an assistant to help triage challenges, look up details, track progress or submit flags you have found. Also handy for scripting against a CTFd instance through the optional REST mirror.
- Requirements
- Local Python 3.10+ process, installed from PyPI (uvx or pip) or run from source. Requires CTFD_BASE_URL pointing at a CTFd v3 instance, plus one credential: CTFD_ADMIN_TOKEN (recommended), CTFD_SESSION_COOKIE, or CTFD_USERNAME with CTFD_PASSWORD. Network access to the instance; private and loopback addresses are blocked unless CTFD_ALLOW_PRIVATE_IPS is enabled.
Installation
In SourceWeft
- Open CTFd in the dashboard and add it to a workspace.
- Enable the server for the chats that should use its tools.
Desktop only via STDIO. STDIO servers start a local process, so they need the SourceWeft desktop host.
Other MCP clients
Follow the launch instructions in the repository.
README
CTFd MCP Server
[PyPI - Version] [PyPI - Python Versions] [Docker Pulls] [License: MIT] [GitHub Stars]
A Model Context Protocol (MCP) server for interacting with any CTFd v3 instance. It lets AI tools (Claude Desktop, Cursor, custom agents, ...) authenticate, list and inspect challenges, submit flags, and query instance state through a stable, type-safe interface.
The project ships two interfaces built on the same client library:
- MCP tools (primary) —
ctfd_mcp_server.py, used overstdioorsse. - REST API (optional) —
server/main.py, a FastAPI mirror for scripting, debugging, and Docker deployments.
Credentials (token / cookie / password) live in memory only and are never
echoed in tool output, written to server_state.json, or logged.
Features
- Multiple authentication modes — API token, session cookie, or username/password form login (with CSRF handling).
- Rich challenge queries — paginated listing with
category,search(name), andsolved/unsolvedfilters, plus per-challenge detail retrieval. - Safe flag submission — requires an explicit
confirm=True, returns clear success/failure, and surfaces rate-limit errors. Flags are never logged. - Instance introspection — public instance info, health check, and an authentication-status tool that reveal no secrets.
- Consistent structured errors —
AuthenticationError,CTFdAPIError,ChallengeNotFoundError,SubmissionError,ValidationError,ConfigurationError. - Pagination by default — one page of challenges per call; no accidental full-dump downloads.
- Hardened HTTP — configurable timeouts, one safe retry for idempotent
GETs, no retries forPOSTs (no duplicate submissions), strict JSON/content parsing. - REST + MCP from one codebase — identical behaviour on both interfaces.
- No hardcoded instance —
BASE_URLis validated and configurable at startup and at runtime.
Installation
Requires Python 3.10+.
The fastest way is to install from PyPI:
For MCP clients, point your config at the packaged entry point:
Or run from source:
Configure
CTFD_BASE_URLmay include a path prefix (e.g.https://host/ctfd); the client appends/api/v1automatically.
Running the MCP Server
Most MCP clients launch the server themselves via a command/args config.
For that, your client config should reference ctfd_mcp_server.py:
Manual launch:
MCP tools
With token auth, requests are sent with
Content-Type: application/json(CTFd only honoursAuthorization: Token ...on JSON requests). With cookie/credentials auth, state-changing requests echo the session CSRF nonce as theCSRF-Tokenheader, which is re-fetched from the site after login.
Tools return JSON text. Errors are structured, e.g.:
Running the REST API (optional)
Endpoints (all under /api/v1):
The optional REST API can be protected with an extra bearer token: set
CTFD_API_TOKEN, and requests to/api/v1/*will requireAuthorization: Bearer <token>. The server binds to loopback by default (MCP_HOST=127.0.0.1).
Docker
A ready-made image is published on Docker Hub:
Or build locally (REST mode):
docker compose up --build also works (REST API on http://localhost:8000).
To run the MCP SSE server in a container instead:
Usage examples
MCP (agent)
REST
See DEMO.md for a complete walkthrough and
examples/ for curl and Python snippets.
Development & testing
The test suite mocks the CTFd API (tests/conftest.py::FakeGateway), so unit
tests run offline.
Integration testing against a real CTFd
Run a local CTFd for live tests (recommended over the shared demo instance, which serves HTML on public auth-gated routes):
Security considerations
- Credentials are memory-only. By default nothing is written to
server_state.json. EnablingCTFD_PERSIST_SECRETSis discouraged. - Secrets are never echoed. Tool and API responses, error messages and logs
redact tokens, cookies, passwords and flags (
server/utils.py). - Every tool validates its input before touching the network (
set_base_urlrequires an absolutehttp(s)URL,submit_flagrequiresconfirm=True, etc.). - Controlled retries. Only idempotent
GETrequests are retried (once). Flag submissions are never automatically replayed. - Trust model. The server is a local/dev tool: whoever can call its tools can point it at any CTFd instance and (with a valid credential) read data or submit flags. Do not expose the REST/SSE endpoints on an untrusted network.
- SSRF guard. By default connections to private / loopback / link-local /
metadata addresses are refused (
CTFD_ALLOW_PRIVATE_IPS=1opts out). A local container or a tool pointed at a private instance will get a clear error.
Limitations
- Requires CTFd v3+. The
/api/v1routes used are standard CTFd v3 API routes. - Form login depends on CTFd's web session flow (CSRF nonce extraction is best-effort). API tokens are the recommended authentication method.
difficultyis not a standard CTFd field; challengevalue(points) is returned instead.solvedfiltering uses CTFd'ssolved_by_meflag, which is only meaningful when authenticated.- Instance "version" is reported only when it appears in the rendered page; CTFd has no public version API endpoint.
- Tokens are per-instance. CTFd redirects
/api/v1calls to its login page when a credential is invalid. The server detects this and reports: "the credential is not valid for THIS instance" — a token from one CTFd instance never works on another. - When
CTFD_USERNAME/CTFD_PASSWORDare configured, the server auto-logs-in on demand (rotating the session cookie) whenever a call returns unauthenticated, so expired sessions self-heal. After each login the CSRF nonce is re-fetched from the site (a fresh nonce is required for flag submissions over a web session). - A teamless account sees no
/api/v1/challengeson team-mode instances until it joins or creates a team; the server surfaces CTFd's permission message.
Contributing
Pull requests are welcome. Please:
- Open an issue describing the change.
- Add tests in
tests/(mocked CTFd API preferred). - Run
python -m pytest -qandruff check server ctfd_mcp_server.py tests. - Do not ship credentials in code, tests, or commit
server_state.json/.env.
License
MIT — repository: https://github.com/MrJamescot/ctfd-mcp-server
Source: README.md at commit c75b77a
Tools
0Version history
3- v1.0.4LatestSep 21, 2026
- v1.0.3Sep 20, 2026
- v1.0.2Sep 20, 2026
Score
50% of the applicable checks met
How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.
- Reached in the last 30 days25 pts
Keep the endpoint answering the MCP handshake; SourceWeft probes it every 30 days.
- Auth declared10 pts
Declare the credential headers in the registry entry, or keep the endpoint answering the probe so its auth can be classified.
- Tools listed15 pts
Answer tools/list without a credential, or ship a package that starts in a sandbox without one.
- DescriptionRequired15 pts
- Logo10 pts
- Documentation15 pts
- License10 pts