Skip to content

Nislive/pyrit-mcp-server

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PyRIT MCP Server

A modular MCP (Model Context Protocol) server that wraps Microsoft PyRIT 0.14.0 and exposes 31 composable tools for authorized AI red-teaming — attack execution, scoring, prompt conversion, and result inspection.

It is designed to be the "weapon store + scoring lab" component of a larger autonomous red-team platform. Because it speaks standard MCP, any agent or MCP-capable host can drive it — for example a LangGraph agent that runs the attack loop and stores findings. Instead of one monolithic endpoint, it offers small, independent tools that an agent can freely combine inside a ReAct loop.

⚠️ Authorized use only. This project is for security research, CTF, and red-teaming of systems you own or are explicitly permitted to test. Do not use it against third-party systems without written authorization.


Architecture

Any MCP agent / host  ──►  PyRIT MCP Server (this project)  ──►  target LLM(s)
  (the brain — e.g.          (attacks + scoring, 31 tools)        (victim / adversarial)
   LangGraph, Claude
   Desktop, custom loop)
pyrit_mcp_server/
├── main.py            # FastMCP instance + registers all tool modules
├── __main__.py        # python -m pyrit_mcp_server
├── core/
│   ├── memory.py      # CentralMemory singleton (idempotent, in-memory SQLite)
│   ├── targets.py     # TargetRegistry — create/get/remove OpenAI-compatible targets
│   └── jobs.py        # JobManager — background execution via asyncio.Task
└── tools/
    ├── targets.py     # 3 tools
    ├── attacks.py     # 11 tools (4 single-turn + 4 multi-turn + 3 job mgmt)
    ├── scoring.py     # 7 tools
    ├── converters.py  # 3 tools
    ├── scenarios.py   # 2 tools
    ├── datasets.py    # 2 tools
    └── memory_tools.py# 3 tools

Key design decisions

  • Multi-turn attacks run in the background. MCP tool calls would otherwise time out, so red_team, crescendo, pair, and tap return a job_id immediately and run as an asyncio.Task. Poll with get_job_status / list_jobs.
  • Token-cost guardrails. Hard limits (MAX_TURNS=30, MAX_TREE_WIDTH=10, MAX_TREE_DEPTH=15, MAX_BRANCHING=5) are clamped on every attack to prevent runaway spend. tap also returns an estimated LLM-call count.
  • Two-stage hybrid scoring. score_hybrid first runs a fast static check, then verifies with an LLM only if it triggers — reducing false positives.
  • Ephemeral memory by design. PyRIT's own store is in-memory SQLite (:memory:); persistence is expected to live in the host platform, not here.

The 31 tools

Targets (3)

Tool Description
create_target Create an OpenAI-compatible chat target (endpoint, model, api_key)
list_targets List all registered targets
remove_target Remove a target

Attacks — single-turn, synchronous (4)

Tool Description
send_prompt Send a prompt directly (PromptSendingAttack)
run_skeleton_key_attack Skeleton Key jailbreak
run_flip_attack Flip-based jailbreak
run_role_play_attack Role-play jailbreak (needs an adversarial LLM + scenario)

Attacks — multi-turn, background job (4)

Tool Description
run_red_team_attack Adversarial LLM iteratively generates prompts
run_crescendo_attack Gradual escalation attack
run_pair_attack PAIR — Prompt Automatic Iterative Refinement
run_tap_attack TAP — Tree of Attacks with Pruning (most expensive)

Attacks — job management (3)

Tool Description
get_job_status Query a background job's status/result
list_jobs List all jobs
wait_for_job Block until a job finishes (or timeout_seconds), polling every poll_interval_seconds

Scoring (7)

Tool Type Description
score_likert LLM 13 categories, float 0–1 (harm, violence, cyber, …)
score_true_false LLM 5 question types (task_achieved, prompt_injection, …)
score_refusal LLM Detect whether the AI refused
score_substring non-LLM Substring match
score_regex non-LLM Regex pattern match
score_security non-LLM 6 checks: xss, sql_injection, shell_command, path_traversal, credential_leak, markdown_injection
score_hybrid hybrid Static check + LLM verification (false-positive reduction)

Converters (3)

Tool Description
convert_prompt Transform text with one converter (base64, rot13, leetspeak, …)
chain_convert Apply several converters in sequence
list_converters List available converters

Scenarios (2)

Tool Description
list_scenarios List PyRIT built-in scenarios (AIRT, Garak, Foundry)
run_scenario Run a built-in scenario (supports max_objectives)

Datasets (2)

Tool Description
list_seed_datasets List PyRIT YAML seed datasets
load_objectives Load seed objectives (with filtering)

Memory (3)

Tool Description
get_attack_history Query attack history
get_conversation Fetch a conversation by id
export_results Export results as JSON

Requirements

  • Python 3.11+
  • pyrit==0.14.0, mcp>=1.27 (installed automatically)
  • An OpenAI-compatible endpoint for the LLM targets — e.g. the OpenAI API or a local Ollama server (http://127.0.0.1:11434/v1).

Installation

python -m venv .venv
source .venv/bin/activate
pip install -e .

# configure secrets
cp .env.example .env   # then edit .env and add your API key(s)

Running

# as an installed entry point
pyrit-mcp-server

# or as a module
python -m pyrit_mcp_server

The server speaks MCP over stdio. Example client (e.g. Claude Desktop) config:

{
  "mcpServers": {
    "pyrit": {
      "command": "/path/to/.venv/bin/python",
      "args": ["-m", "pyrit_mcp_server"]
    }
  }
}

Typical flow

  1. create_target for the victim (and one for the adversarial/scorer LLM).
  2. Run an attack — send_prompt (sync) or run_crescendo_attack (returns a job_id).
  3. For multi-turn jobs, poll get_job_status until completed / failed.
  4. Score the response with score_likert, score_refusal, score_security, etc.
  5. Inspect with get_attack_history / export_results.

Example

examples/crescendo_attack.py is a complete, runnable MCP client that drives the server end-to-end against a local Ollama model (llama3.2:1b): it spins up two targets (victim + adversarial), launches a run_crescendo_attack, polls get_job_status until the job completes, then pulls the result via get_attack_history and scores the last response with score_security.

# requires a local Ollama server running on http://127.0.0.1:11434
.venv/bin/python examples/crescendo_attack.py

It doubles as a smoke test: if it runs to completion and prints a result, the core target → attack → job → history → scoring path is working. API keys for real OpenAI targets are read from the environment (OPENAI_API_KEY) — never hardcode them.


Known limitations

  • Concurrent multi-turn contention — launching all four multi-turn attacks at once can leave jobs stuck in running. Run them sequentially.
  • Private-attribute coupling — a couple of code paths reach into PyRIT internals (OpenAIChatTarget._endpoint/_api_key, a scenario's _default_dataset_config). These may break on a future PyRIT upgrade.
  • No job cleanup — completed jobs/tasks are retained for the process lifetime (in-memory only).
  • run_scenario max_objectives is honored by clamping the scenario's default dataset size; scenarios that don't expose that config silently ignore the limit.

License

Released under the MIT License. Built on top of Microsoft PyRIT, which is licensed separately (MIT) by Microsoft.

About

Arm any MCP-capable agent to autonomously red-team a target LLM. Microsoft PyRIT exposed as 31 composable MCP tools: attacks, scoring, converters & scenarios

Topics

Resources

License

Stars

1 star

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages