ThreatByte-MCP is a deliberately vulnerable SOC (Security Operations Center) case management MCP server designed for cybersecurity training, featuring a Flask web UI and an MCP server exposing tools across several domains:
Case Management
cases.create— Create a case with title, status, and severitycases.list/cases.list_all— List cases by owner or all cases across users (broken access control — intentional)cases.get/cases.rename/cases.set_status/cases.delete— Retrieve, rename, update status, or delete cases (ownership not enforced — intentional)
Notes Management
notes.create— Add a note to a case (HTML supported — stored XSS intentional)notes.list/notes.update/notes.delete— List, update, or delete notes (ownership not enforced — intentional)
File Management
files.upload— Upload a base64-encoded file and associate it with a casefiles.list/files.get— List or retrieve files by ID (returns base64)files.read_path— Read arbitrary filesystem paths (intentional vulnerability)
Indicator Search
indicators.search— Query a mock IOC dataset by string (SQL injection — intentional)
AI Agent Workflows
agent.summarize_case— LLM-powered summarization of case notesagent.run_task— Run custom analyst tasks over case context (prompt injection — intentional; requires OpenAI API key)
Tool Registry
tools.registry.list/tools.registry.register/tools.registry.delete— List, register/update, or delete dynamic tool definitions (tool poisoning — intentional)tools.builtin.list— List all built-in server tools
Intentional Vulnerabilities (Training Focus)
Broken Object Level Authorization (BOLA) on cases, notes, and files
Stored XSS via HTML-rendered notes
SQL injection in indicator search
Prompt injection in agent task runner
Arbitrary file read via
files.read_pathTool poisoning via schema-driven registry overrides
Hardcoded/exposed tokens and identity spoofing via over-trusted client headers
Cross-user file overwrite due to shared filename namespace
Integrates with OpenAI's models to provide Large Language Model capabilities for agent-driven workflows, including automated task execution and case summarization within the management platform.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@ThreatByte-MCPsummarize case #12 and search for any related indicators"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
ThreatByte-MCP
ThreatByte-MCP is a deliberately vulnerable, MCP-based case management web app. It mirrors a realistic SOC analyst workflow with a server-rendered UI and a real MCP server. The MCP tools are intentionally vulnerable for training and demonstration.
For educational use in controlled environments only.
Features
Safe web authentication (signup/login/logout)
Case management UI (create/list/view cases)
Notes and attachments tied to cases
Indicator search and agent workflows via MCP tools
Agent customization with schema-based tool registry
MCP Server (SDK, JSON-RPC)
ThreatByte-MCP is a split architecture:
SOC Web App (client/UI) runs on port 5001.
MCP Server (tools + agent) runs on port 5002 using the official MCP Python SDK (FastMCP).
The MCP server exposes JSON-RPC at POST http://localhost:5002/mcp (Streamable HTTP). The web UI calls the MCP server through a server-side proxy to keep auth consistent with the SOC session; the proxy streams agent responses to the browser via SSE. A sample mcp.json manifest is included at the repo root.
All direct MCP calls must include MCP-Protocol-Version: 2025-11-25 and Accept: application/json, text/event-stream.
Architecture (simplified):
Browser
|
v
+------------------+ X-TBMCP-Token + X-TBMCP-User +-------------------+
| SOC Web App | ---------------------------------------> | MCP Server |
| (Flask, :5001) | /mcp-proxy (server-side) | (FastMCP, :5002) |
+------------------+ +-------------------+
| |
v v
SQLite DB Tool registry
Agent + tool handlersArchitecture (detailed):
Browser (Analyst)
|
v
SOC Web App (Flask, :5001)
| - Auth session (cookie)
| - Dashboards, cases, notes, files UI
| - /mcp-proxy forwards JSON-RPC
|
+--> SQLite DB
| - users, cases, notes, files, indicators
|
+--> Uploads (app/uploads)
|
v
MCP Server (FastMCP, :5002)
| - /mcp JSON-RPC (Streamable HTTP)
| - X-TBMCP-Token + X-TBMCP-User headers
|
+--> Tool registry (mcp_tools)
| - schema-based tools (poisonable)
|
+--> Agent runtime
| - prompt builder (hardcoded tokens)
| - LLM API call
|
+--> Persistence
- agent_contexts (prompt store)
- agent_logs (full request/response)MCP Auth Between Web App and MCP Server
The web app proxies MCP calls with these headers:
X-TBMCP-Token: shared secret fromTBMCP_MCP_SERVER_TOKEN(configured on both servers).X-TBMCP-User: current user id from the authenticated SOC session.
Direct MCP calls require the same headers.
Supported tools:
cases.createcases.listcases.list_allcases.getcases.renamecases.set_statuscases.deletenotes.createnotes.listnotes.updatenotes.deletefiles.upload(base64)files.listfiles.get(base64)files.read_pathindicators.searchagent.summarize_caseagent.run_tasktools.registry.listtools.builtin.listtools.registry.registertools.registry.delete
Vulnerability Themes (Training-Focused)
The following weaknesses are intentionally present for teaching:
Broken object level authorization (cases/notes/files, list_all)
Stored XSS (notes rendered as trusted HTML)
SQL injection in indicator search
Prompt injection in agent task runner
Token mismanagement & secret exposure (hardcoded tokens in prompts, persisted contexts, full logs)
Tool poisoning via schema-driven tool registry overrides (MCP03)
Over-trusting client context (MCP header identity spoofing)
Arbitrary file read via
files.read_pathCross-user file overwrite (shared filename namespace)
Running Locally
cd ThreatByte-MCP
python -m venv venv_threatbyte_mcp
source venv_threatbyte_mcp/bin/activate
pip install -r requirements.txt
python db/create_db_tables.py
python run_http_server.py
python run.pyOpen: http://localhost:5001
MCP Server: http://localhost:5002/mcp
Running with Docker or Podman
The repository includes a Dockerfile and startup script that initialize the DB and run both services in one container:
SOC Web App on
:5001MCP Server on
:5002
Build the image:
# Docker
docker build -t threatbyte-mcp .
# Podman
podman build -t threatbyte-mcp .Run the container:
# Docker
docker run --rm -p 5001:5001 -p 5002:5002 threatbyte-mcp
# Podman
podman run --rm -p 5001:5001 -p 5002:5002 threatbyte-mcpRun with optional environment variables:
# Docker
docker run --rm -p 5001:5001 -p 5002:5002 \
-e TBMCP_MCP_SERVER_TOKEN=tbmcp-mcp-token \
-e OPENAI_API_KEY=your_api_key \
-e TBMCP_OPENAI_MODEL=gpt-4o-mini \
threatbyte-mcp
# Podman
podman run --rm -p 5001:5001 -p 5002:5002 \
-e TBMCP_MCP_SERVER_TOKEN=tbmcp-mcp-token \
-e OPENAI_API_KEY=your_api_key \
-e TBMCP_OPENAI_MODEL=gpt-4o-mini \
threatbyte-mcpPersist SQLite data between runs (optional):
# Docker
docker run --rm -p 5001:5001 -p 5002:5002 \
-v "$(pwd)/db:/app/db" \
-v "$(pwd)/app/uploads:/app/app/uploads" \
threatbyte-mcp
# Podman
podman run --rm -p 5001:5001 -p 5002:5002 \
-v "$(pwd)/db:/app/db:Z" \
-v "$(pwd)/app/uploads:/app/app/uploads:Z" \
threatbyte-mcpPopulate Sample Data
python db/populate_db.py --users 8 --cases 20 --notes 40 --files 20This creates random users, cases, notes, and file artifacts. All user passwords are Password123!.
LLM Integration (Required for Agent Responses)
The agent task endpoint requires a real LLM. Without an API key, the agent returns an error indicating it is unavailable.
Environment variables:
TBMCP_OPENAI_API_KEYorOPENAI_API_KEYTBMCP_OPENAI_MODEL(default:gpt-4o-mini)
Keep API keys server-side only and never expose them in the browser.
MCP Server Configuration
The SOC web app proxies MCP calls to the MCP server using a shared token.
Environment variables:
TBMCP_MCP_SERVER_URL(default:http://localhost:5002/mcp)TBMCP_MCP_SERVER_TOKEN(shared secret between the SOC app and MCP server)
Notes
The UI uses server-rendered templates.
MCP tools are exposed under
http://localhost:5002/mcp(JSON-RPC). The UI calls them through/mcp-proxy.This app is intentionally insecure. Do not deploy it to the public internet.