CTFd について
CTFdは、CTFd v3のチャレンジ確認、フラグ送信、スコアボード照会を行うMCPサーバーで、任意のREST APIも備えています。複数の認証方式に対応し、認証情報は既定でメモリ内に保持します。
主な機能
- 01トークン、Cookie、フォームログイン
- 02ページ分割されたチャレンジ検索と詳細表示
- 03確認付きフラグ送信
- 04スコアボードと進捗の照会
- 05任意のREST API
活用シーン
- 01AIエージェントでCTFチャレンジを閲覧
- 02フラグを送信して結果を確認
- 03順位と解答済みチャレンジを確認
MCP 対応
stdioまたはSSEを通じて、チャレンジ照会、フラグ送信、スコアボード取得などのCTFd v3操作ツールをMCPクライアントに提供します。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
uvx ctfd-mcp-serverCTFD_BASE_URLRoot URL of the CTFd v3 instance, e.g. https://ctf.example.com (without /api/v1)CTFD_ADMIN_TOKENシークレットCTFd API access token (preferred authentication method)CTFD_SESSION_COOKIEシークレットFull CTFd session cookie, e.g. session=abc...CTFD_USERNAMEUsername for CTFd form loginCTFD_PASSWORDシークレットPassword for CTFd form loginCTFD_HTTP_TIMEOUTPer-request HTTP timeout in seconds (default 15)ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。
ツール
14掲載時のツール一覧 · 2 週間前に更新
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
| url | string | はい |
詳細
CTFd MCP サーバー
任意の CTFd v3 インスタンスと連携するための Model Context Protocol(MCP)サーバーです。 AI ツール(Claude Desktop、Cursor、カスタムエージェントなど)が、安定した 型安全なインターフェースを通じて認証し、チャレンジの一覧表示と詳細確認、 フラグの送信、インスタンスの状態照会を行えます。
このプロジェクトには、同じクライアントライブラリを基盤とする2つのインターフェースが用意されています。
- MCP ツール(メイン)—
ctfd_mcp_server.py。stdioまたはsse経由で使用します。 - REST API(オプション)—
server/main.py。スクリプト作成、デバッグ、Docker デプロイ向けの FastAPI ミラーです。
┌──────────────────────────────────────────────┐
AI agent / MCP │ FastMCP (MCP tools) │
client ────────►│ set_token · login · challenges · submit_flag │
└──────────────────┬───────────────────────────┘
│ shared client
┌──────────────────▼───────────────────────────┐
curl / scripts ─►│ FastAPI REST (/api/v1/...) (optional) │
└──────────────────┬───────────────────────────┘
│
┌──────────────────▼───────────────────────────┐
│ server.ctfd_client.CTFdClient │
│ └─ gateway.py (HTTP, auth, timeouts) │
└──────────────────┬───────────────────────────┘
│ HTTPS / HTTP
┌─────▼─────┐
│ CTFd │
└───────────┘
認証情報(トークン/Cookie/パスワード)はメモリ内にのみ保持され、ツールの出力に表示されたり、server_state.json に書き込まれたり、ログに記録されたりすることはありません。
機能
- 複数の認証方式 — API トークン、セッション Cookie、またはユーザー名/パスワードによるフォームログイン(CSRF 対応)。
- 柔軟なチャレンジ検索 — ページネーション付きの一覧表示に加え、
category、search(名前)、solved/unsolvedフィルターを利用でき、チャレンジごとの詳細も取得できます。 - 安全なフラグ送信 — 明示的な
confirm=Trueが必要です。成功/失敗を明確に返し、レート制限エラーも通知します。フラグがログに記録されることはありません。 - インスタンスの情報取得 — 公開インスタンス情報、ヘルスチェック、秘密情報を漏らさない認証状態確認ツールを利用できます。
- 一貫した構造化エラー —
AuthenticationError、CTFdAPIError、ChallengeNotFoundError、SubmissionError、ValidationError、ConfigurationError。 - デフォルトでページネーション — 1回の呼び出しで取得するチャレンジは1ページのみです。意図しない全件ダウンロードを防ぎます。
- 堅牢な HTTP 通信 — タイムアウトを設定でき、冪等な
GETは安全に1回再試行します。POSTは再試行せず(重複送信を防止)、JSON とコンテンツを厳密に解析します。 - 1つのコードベースで REST と MCP に対応 — どちらのインターフェースでも動作は同一です。
- インスタンスのハードコードなし —
BASE_URLは検証され、起動時と実行時に設定できます。
インストール
Python 3.10 以降が必要です。
最も簡単な方法は、PyPI からインストールすることです。
pip install ctfd-mcp-server
# MCP stdio server with env config:
CTFD_BASE_URL=https://ctf.example.com CTFD_ADMIN_TOKEN=ctfd_... ctfd-mcp
# optional REST interface:
ctfd-rest
MCP クライアントで使用する場合は、設定でパッケージのエントリーポイントを指定してください。
{
"mcpServers": {
"ctfd-mcp": {
"command": "ctfd-mcp",
"env": {
"CTFD_BASE_URL": "https://demo.ctfd.io",
"CTFD_ADMIN_TOKEN": "ctfd_..."
}
}
}
}
または、ソースから実行します。
git clone https://github.com/MrJamescot/ctfd-mcp-server.git
cd ctfd-mcp-server
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env # then edit .env
設定
| 変数 | デフォルト | 意味 |
|---|---|---|
CTFD_BASE_URL | (empty) | CTFd インスタンスのルート。例:https://ctf.example.com(/api/v1 を除く) |
CTFD_ADMIN_TOKEN | (empty) | API トークン(優先される認証方式) |
CTFD_SESSION_COOKIE | (empty) | セッション Cookie。例:session=abc... |
CTFD_USERNAME | (empty) | フォームログイン用のユーザー名 |
CTFD_PASSWORD | (empty) | フォームログイン用のパスワード |
CTFD_HTTP_TIMEOUT | 15 | リクエストごとの HTTP タイムアウト(秒) |
CTFD_HTTP_MAX_REDIRECTS | 5 | リクエストごとに追跡するリダイレクトの最大数 |
CTFD_STATE_FILE | ~/.local/state/ctfd-mcp/server_state.json | 認証状態のキャッシュに使用するファイル |
CTFD_MCP_TRANSPORT | stdio | MCP トランスポート:stdio または sse |
MCP_HOST / MCP_PORT | 127.0.0.1 / 8000 | REST サーバーのバインド設定(デフォルトではループバック) |
CTFD_API_TOKEN | (empty) | オプションの REST API(/api/v1/*)を保護する任意のベアラートークン |
CTFD_ALLOW_PRIVATE_IPS | false | プライベート/ループバック/メタデータのアドレスへの接続を許可します(例:ローカルの CTFd テストインスタンス) |
CTFD_DOWNLOAD_DIR | ./downloads | download_file がチャレンジの添付ファイルを保存するディレクトリ |
CTFD_PERSIST_SECRETS | false | ⚠ 強く非推奨:シークレットをディスクに書き込みます |
CTFD_BASE_URLにはパスプレフィックスを含めることができます(例:https://host/ctfd)。クライアントが/api/v1を自動的に追加します。
MCP サーバーの実行
ほとんどの MCP クライアントは、command/args の設定を使ってサーバーを起動します。
その場合、クライアント設定では ctfd_mcp_server.py を指定してください。
// e.g. Claude Desktop / mcp.json
{
"mcpServers": {
"ctfd-mcp": {
"command": "python",
"args": ["/path/to/ctfd-mcp-server/ctfd_mcp_server.py"],
"env": {
"CTFD_BASE_URL": "https://demo.ctfd.io",
"CTFD_ADMIN_TOKEN": "ctfd_..."
}
}
}
}
手動で起動する場合:
# stdio (default) — used by MCP clients
python ctfd_mcp_server.py
# SSE — expose over HTTP for remote/Docker use
CTFD_MCP_TRANSPORT=sse python ctfd_mcp_server.py # http://127.0.0.1:8000/sse
MCP ツール
| ツール | パラメーター | 説明 |
|---|---|---|
set_base_url | url | サーバーの接続先を CTFd インスタンスに設定します |
set_token | token | API トークンを設定します(メモリ内のみ) |
set_cookie | cookie | セッション Cookie を設定します(メモリ内のみ) |
login | username、password | フォームからログインし、セッション Cookie を保持します |
challenges | category、search、solved、page、per_page | フィルター付きのページ分割されたチャレンジ一覧です |
challenge | identifier(id または name) | 1 件のチャレンジの詳細情報です |
submit_flag | flag、challenge_name/challenge_id、confirm | フラグを送信します(confirm=True が必要です) |
download_file | file_url、dest_dir | CTFd の /files/… ルート経由でチャレンジの添付ファイルをダウンロードします |
unlock_hint | hint_id | ヒントのロックを解除して読み取ります(有料ヒントはポイントを消費します) |
scoreboard | — | 公開スコアボードの順位です |
progress | — | あなたのスコアと解決済みのチャレンジです |
instance_info | — | 安全な公開インスタンスメタデータです |
auth_status | — | 認証モードと有効性(シークレットは含みません) |
health | — | 到達可能性、API、認証のチェックです |
トークン認証では、リクエストは
Content-Type: application/jsonを付けて送信されます (CTFd は JSON リクエストに対するAuthorization: Token ...のみを有効として扱います)。Cookie/認証情報を使った認証では、 状態を変更するリクエストにセッションの CSRF nonce をCSRF-Tokenヘッダーとして付加します。この値はログイン後にサイトから再取得されます。
ツールは JSON テキストを返します。エラーは次のような構造化形式です。
{ "error": { "type": "ChallengeNotFoundError", "message": "Challenge '99' not found (or not visible)." } }
REST API の実行(任意)
python scripts/run_local.sh # reads .env, default http://127.0.0.1:8000
# or
uvicorn server.main:app --host 0.0.0.0 --port 8000
エンドポイント(すべて /api/v1 配下):
| メソッド | パス | 説明 |
|---|---|---|
| POST | /set_base_url | CTFd のベース URL を検証して設定します |
| POST | /set_token | API トークンを設定します |
| POST | /set_cookie | セッション Cookie を設定します |
| POST | /set_creds | 後でログインするためにユーザー名とパスワードを保存します |
| POST | /login | フォームログイン(セッション Cookie) |
| GET | /challenges | ページネーションとフィルターに対応したチャレンジ一覧 |
| GET | /challenges/{id-or-name} | チャレンジの詳細 |
| POST | /submit | フラグを送信します(confirm: true が必要) |
| POST | /download | チャレンジの添付ファイルをダウンロードします(本文:file_url) |
| POST | /unlock_hint | ヒントのロックを解除して読み取ります(本文:hint_id) |
| GET | /scoreboard | 公開順位 |
| GET | /progress | 自分のスコアと解答状況 |
| GET | /instance_info | インスタンスの公開メタデータ |
| GET | /auth_status | 認証方式と有効性 |
| GET | /health | ヘルスチェック |
任意の REST API は追加のベアラートークンで保護できます。
CTFD_API_TOKENを設定すると、/api/v1/*へのリクエストにはAuthorization: Bearer <token>が必要になります。サーバーはデフォルトでループバックにバインドされます (MCP_HOST=127.0.0.1)。
Docker
すぐに使えるイメージが Docker Hub で公開されています。
docker run --rm -p 8000:8000 \
-e CTFD_BASE_URL=https://ctf.example.com \
-e CTFD_ADMIN_TOKEN=ctfd_... \
jamescot/ctfd-mcp-server
または、ローカルでビルドします(REST モード)。
docker build -t ctfd-mcp .
docker run --rm -p 8000:8000 \
-e CTFD_BASE_URL=https://ctf.example.com \
-e CTFD_ADMIN_TOKEN=ctfd_... \
ctfd-mcp
docker compose up --build も使用できます(REST API は http://localhost:8000)。
代わりに、コンテナ内で MCP SSE サーバーを実行するには、次のようにします。
docker run --rm -it -e CTFD_BASE_URL=https://ctf.example.com ctfd-mcp python ctfd_mcp_server.py
# stdio on the attached terminal
使用例
MCP(エージェント)
1. set_base_url url="https://ctf.example.com"
2. set_token token="ctfd_..."
3. challenges category="web", solved=false, page=1, per_page=25
4. challenge identifier="3"
5. submit_flag flag="flag{...}", challenge_id=3, confirm=true
REST
curl -X POST http://localhost:8000/api/v1/set_base_url \
-H 'Content-Type: application/json' -d '{"url":"https://ctf.example.com"}'
curl -X POST http://localhost:8000/api/v1/set_token \
-H 'Content-Type: application/json' -d '{"token":"ctfd_..."}'
curl 'http://localhost:8000/api/v1/challenges?search=web&solved=false&per_page=10'
curl -X POST http://localhost:8000/api/v1/submit \
-H 'Content-Type: application/json' \
-d '{"challenge_id":3,"flag":"flag{...}","confirm":true}'
curl http://localhost:8000/api/v1/health
完全な手順については DEMO.md を、curl と Python のスニペットについては
examples/ を参照してください。
開発とテスト
pip install -r requirements-dev.txt
python -m pytest -q # 76 unit tests, mocked CTFd API (no network)
ruff check server ctfd_mcp_server.py tests
テストスイートは CTFd API をモックするため(tests/conftest.py::FakeGateway)、ユニット
テストはオフラインで実行できます。
実際の CTFd を使った統合テスト
ライブテストには、ローカルの CTFd を実行してください(公開認証が必要なルートで HTML を返す共有デモインスタンスよりも推奨されます)。
git clone https://github.com/CTFd/CTFd.git /tmp/CTFd
docker compose -f /tmp/CTFd/docker-compose.yml up
# create a user/challenge, then:
CTFD_BASE_URL=http://localhost:8000 python ctfd_mcp_server.py
CTFD_BASE_URL=http://localhost:8000 uvicorn server.main:app --port 8001
curl http://localhost:8001/api/v1/health
セキュリティに関する考慮事項
- 認証情報はメモリ上にのみ保持されます。 デフォルトでは何も
server_state.jsonに書き込まれません。CTFD_PERSIST_SECRETSの有効化は推奨されません。 - シークレットが応答に含まれることはありません。 ツールと API の応答、エラーメッセージ、ログでは、
トークン、Cookie、パスワード、フラグがマスキングされます(
server/utils.py)。 - 各ツールはネットワークにアクセスする前に入力を検証します(
set_base_urlは絶対http(s)URL を要求し、submit_flagはconfirm=Trueを要求するなど)。 - 再試行は制御されています。 冪等な
GETリクエストのみ、一度だけ再試行されます。 フラグの送信が自動的に再実行されることはありません。 - 信頼モデル。 このサーバーはローカル/開発用ツールです。このツールを呼び出せる人は誰でも、 接続先として任意の CTFd インスタンスを指定し、有効な認証情報があればデータを読み取ったり、 フラグを送信したりできます。信頼できないネットワークに REST/SSE エンドポイントを公開しないでください。
- SSRF ガード。 デフォルトでは、プライベート/ループバック/リンクローカル/
メタデータアドレスへの接続は拒否されます(
CTFD_ALLOW_PRIVATE_IPS=1で無効化できます)。ローカル コンテナやプライベートインスタンスを指定したツールには、明確なエラーが返されます。
制限事項
- CTFd v3+ が必要です。使用する
/api/v1ルートは、標準の CTFd v3 API ルートです。 - フォームログインは、CTFd のウェブセッションフローに依存します(CSRF nonce の抽出はベストエフォートです)。認証方法としては API トークンを推奨します。
difficultyは CTFd の標準フィールドではないため、代わりにチャレンジのvalue(ポイント)が返されます。solvedによるフィルタリングには CTFd のsolved_by_meフラグを使用します。このフラグは、認証済みの場合にのみ意味があります。- インスタンスの「バージョン」は、レンダリングされたページに表示されている場合にのみ報告されます。CTFd には公開バージョン API エンドポイントがありません。
- トークンはインスタンスごとに異なります。 CTFd は認証情報が無効な場合、
/api/v1への呼び出しをログインページにリダイレクトします。サーバーはこれを検出し、*「このインスタンスでは認証情報が無効です」*と報告します。ある CTFd インスタンスのトークンが別のインスタンスで機能することはありません。 CTFD_USERNAME/CTFD_PASSWORDが設定されている場合、呼び出しが未認証で返されるたびに、サーバーは必要に応じて自動ログインし(セッション Cookie を更新)、期限切れのセッションを自動的に復旧します。ログインのたびに、サイトから CSRF nonce を再取得します(ウェブセッション経由でフラグを送信するには、新しい nonce が必要です)。- チームに所属していないアカウントは、チームモードのインスタンスでは、チームに参加するか作成するまで
/api/v1/challengesを参照できません。サーバーは CTFd の権限メッセージを表示します。
コントリビューション
プルリクエストを歓迎します。以下をお願いします。
- 変更内容を説明する Issue を作成してください。
tests/にテストを追加してください(CTFd API のモックを推奨します)。python -m pytest -qとruff check server ctfd_mcp_server.py testsを実行してください。- コードやテストに認証情報を含めたり、
server_state.json/.envをコミットしたりしないでください。
ライセンス
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。