Skip to main content
Glama
umbra2728

CTFd MCP Server

by umbra2728

CTFd MCP server (user scope)

GitHub Release License Python Issues

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) or CTFD_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

Related MCP server: mcp-ctftime

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 just container_id, owl/k8s need challenge_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/containers returns 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; set CTFD_CSRF_TOKEN if 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 includes k8s (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: set CTFD_SESSION from the session cookie after logging in.

  • The client now supports logging in with CTFD_USERNAME and CTFD_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:

Testing

  • Run uv run pytest.

  • 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 . and uv run ruff format .

  • Tests: uv run pytest

  • Pre-commit: uv run pre-commit install (see CONTRIBUTING.md)

License

Apache-2.0. See LICENSE.

Available Tools

5 tools
challenge_detailsA

Get challenge details (description, files, meta) by ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
challenge_idYes

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations provided, so description must disclose behavioral traits. It implies a read-only get operation, but does not explicitly state side effects, authentication, or error handling. Minimal but adequate for a simple fetch.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Single sentence with parenthetical is extremely concise and front-loaded. No unnecessary words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's simplicity (1 param, no output schema), the description is adequate but could specify the return format (e.g., JSON structure) or that it returns all details. Slightly lacking for complete understanding.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so description should compensate. It does not explain challenge_id beyond its name and type; omits where to obtain the ID (e.g., from list_challenges). Fails to add value over the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool retrieves challenge details by ID, specifying the fields (description, files, meta). It distinguishes from sibling tools like list_challenges, which likely lists all challenges.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No explicit guidance on when to use this versus alternatives like list_challenges. The purpose is implied, but no when-not or prerequisite mentioned.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_challengesB

List visible challenges. Optional filter by category and unsolved only.

ParametersJSON Schema
NameRequiredDescriptionDefault
categoryNo
only_unsolvedNo

TDQS

B3.2/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations provided. Description implies read-only but lacks details on authentication, rate limits, or other behavioral traits beyond listing.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One sentence front-loaded with purpose, followed by optional filters. No redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Lacks output schema or description of return structure (e.g., array of challenge objects, pagination). Adequate for a simple list but leaves ambiguity for an AI agent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0% (no param descriptions). The description mentions optional filtering by category and unsolved status but does not clarify valid category values or the precise meaning of 'unsolved only' (e.g., user-specific unsolved).

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool lists visible challenges with optional filters, distinguishing it from siblings like challenge_details or submit_flag.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No explicit guidance on when to use this tool versus alternatives such as challenge_details for individual challenge details or submit_flag for flag submission.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

start_containerB

Unified start: detects plugin (whale/ctfd-owl/k8s) and starts container.

ParametersJSON Schema
NameRequiredDescriptionDefault
challenge_idYes

TDQS

B3.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the burden. It mentions plugin detection behavior but does not disclose what happens on failure, permissions, or consequences beyond starting.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single sentence, front-loaded with key action and plugin detection, and contains no extraneous information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema is provided, and the description omits crucial details such as return values, side effects, prerequisites (e.g., challenge existence), and error conditions, making it incomplete for a start action.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters1/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The single required parameter 'challenge_id' has 0% schema description coverage, and the description does not explain its meaning, format, or how to obtain it, leaving the agent without guidance.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description clearly states the verb 'start' and resource 'container', and explicitly mentions unified detection of plugins (whale, ctfd-owl, k8s), distinguishing it from sibling tools like stop_container.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage by stating it is a unified start, but does not provide explicit guidance on when to use this tool versus alternatives, nor does it mention prerequisites or context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

stop_containerC

Unified stop: whale requires container_id; ctfd-owl/k8s require challenge_id.

ParametersJSON Schema
NameRequiredDescriptionDefault
container_idNo
challenge_idNo

TDQS

C2.9/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations provided, so the description must carry behavioral disclosure. It fails to state whether stopping is destructive, requires authentication, or what the effect is. The mention of different systems hints at behavior but lacks detail.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Single sentence with no extraneous words. Front-loaded with the action 'Unified stop'. Every word serves a purpose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Lacks details on return values, errors, prerequisites, or side effects. No output schema and minimal description make it insufficient for a complete understanding.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage, the description adds partial meaning by linking parameters to systems (whale vs. ctfd-owl/k8s). However, it doesn't explain the parameters fully (e.g., format, requiredness beyond default null).

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states 'Unified stop', clearly indicating the tool stops containers. It differentiates from sibling 'start_container' by being the inverse operation. However, it does not specify a single verb+resource but rather describes two possible use cases.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance on when to use this tool versus alternatives like 'start_container' or when not to use it. The only usage hint is about choosing parameters based on system, which is implicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

submit_flagC

Submit a flag for a challenge ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
challenge_idYes
flagYes

TDQS

C2.1/5.0
Behavior1/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are present, and the description provides no behavioral details. It does not disclose whether flag submission is idempotent, what the side effects are (e.g., scoring), or any error conditions. The agent has no insight into tool behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness2/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is extremely short but fails to convey necessary information. While brevity is valued, this description is under-specified and does not earn its place as an informative guide for an AI agent.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness1/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the lack of annotations, output schema, and parameter descriptions, the description is completely inadequate. It does not provide enough context for the agent to know when to use the tool, what the return value looks like, or how it fits into the challenge lifecycle.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters1/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, and the description adds no meaning beyond the property names. It does not explain what 'flag' format is expected, how to obtain challenge_id, or any constraints like case sensitivity. The description fails to compensate for the missing schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action (submit) and resource (flag for a challenge ID). It is specific enough to distinguish from sibling tools like list_challenges and start_container, which have different purposes.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No usage guidelines are provided. The description does not mention when to use this tool, any prerequisites (e.g., must have a started container), or when to avoid it. No alternatives are listed compared to siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 5 tool updatesv1.0.0
    • First observedchallenge_details
    • First observedlist_challenges
    • First observedstart_container
    • First observedstop_container
    • First observedsubmit_flag

TDQS

B3.2/5.0

Scored across 5 tools

Disambiguation5/5

Each tool targets a distinct action: starting/stopping containers, listing challenges, viewing details, and submitting flags. There is no overlap between the five tools.

Naming Consistency4/5

Tool names follow a consistent verb_noun pattern (start_container, list_challenges, challenge_details, submit_flag, stop_container). 'challenge_details' is a noun phrase rather than a verb_noun like 'get_challenge', but the pattern is still clear and predictable.

Tool Count5/5

Five tools is well-scoped for a CTFd server: it covers the core user-facing actions of browsing challenges, getting details, submitting flags, and managing challenge containers. Each tool earns its place.

Completeness4/5

The surface covers the main CTF participant workflow: list challenges, view details, start/stop containers, and submit flags. Minor gaps exist such as no tool for viewing container status or listing active containers, but agents can work around these with the provided tools.

Maintenance

ActivityInactive
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    C
    maintenance
    Enables AI assistants to query CTF (Capture The Flag) cybersecurity competition data from CTFtime.org, including events, team rankings, results, and votes through the public CTFtime API.
    7
    44 npm
    MIT
  • A
    license
    Not graded
    quality
    Not graded
    maintenance
    Exposes common CTF and cybersecurity tools (crypto, forensics, malware analysis, steganography, reverse engineering, pwn, OSINT) so LLMs can help solve capture-the-flag challenges in a controlled lab environment.
    -