OPFOR: adversary emulation for AI agents, MCP servers and LLM apps
Open-source adversary emulation for AI agents and MCP servers.
At a glance
- What is it?
- KeyValueSoftwareSystems/agent-opfor is an Apache 2.0 TypeScript toolkit that generates OWASP-mapped attack prompts, fires them at your agent, and judges the answers with an LLM. The interesting part is not the attack library, it is that the same evaluators and judge logic are exposed through five different entry points.
- Who is it for?
- Adopt OPFOR if you have a deployed agent or MCP server and need a repeatable, logged attack pass that a non-developer can also trigger from the browser extension. Do not adopt it if you need deterministic, non-LLM verdicts, or if you cannot send real attack traffic and real target responses to a model provider.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 3 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The wall OPFOR was built against
The README frames the problem in the vendor's own history: 130 products shipped for 90 startups over ten years, and in the last 18 months almost every one of them contained an AI agent. Each of those teams, the README says, hit the same wall when it came to testing. That is the gap OPFOR targets. It is not a prompt-injection probe library and not a generic evaluation framework. It is positioned as adversary emulation for the whole agent surface: prompts, tool calls, MCP servers, memory and multi-turn reasoning.
The intended audience is split. On one side are engineers who want a terminal command inside CI. On the other are product managers, designers, QA and security analysts who, in the README's phrasing, cannot or will not write code. OPFOR ships a browser extension for that second group. Most tools in this category pick one audience. This one deliberately ships two, and the five run modes exist because of that split rather than because of feature creep.
Attack generation, execution and the LLM judge
The README describes a four-stage scan. First OPFOR fetches target information: it connects to your agent and detects available tools, MCP endpoints and capabilities. Second it plans attacks per category, generating targeted prompts for each evaluator in the suite you selected. Third it emulates the attack by running multi-turn adversarial conversations, described as real requests and real responses. Fourth an LLM judge evaluates the output.
That judge is the load-bearing component and also the weakest link. Verdicts come from a model, not from assertions, so the same response can be scored differently across runs. The README does not describe a calibration procedure, a voting scheme, or a fixed judge model. The one mitigation it does describe is trace-awareness: OPFOR integrates with Langfuse and Netra so the judge sees what the agent did internally, not only what it said. That matters for tool-calling agents, where the visible answer can look clean while a tool call did something else. If your tracing backend is not one of those two, the judge is working from the transcript alone, and the README does not list a generic OpenTelemetry path.
The evaluator coverage is broad by design: OWASP LLM Top 10, OWASP Agentic AI Top 10, OWASP MCP Top 10, OWASP API Security and EU AI Act bias suites. Suite selection is described as a per-run choice, so coverage is a function of the config you pass, not of the install.
Five entry points sharing one evaluator core
The CLI is the base case: opfor setup runs a wizard and saves a config to .opfor/configs/, and opfor run --config .opfor/configs/<file> replays it. That two-step split is what makes the tool usable in CI, because the wizard is interactive and the run is not.
The browser extension is the most unusual choice here. You install it and click the icon on any chat interface, so a teammate with no environment variables and no YAML can red-team a deployed chatbot. The trade-off is implicit: an extension driving a chat UI is testing the deployed surface through the UI, whereas the CLI connects to the agent and enumerates tools and MCP endpoints. Those are not the same test.
MCP server mode lets you register OPFOR in Cursor or Claude Desktop and ask for a red-team run in natural language, which means your coding agent tests your other agents. Skills mode exposes slash commands (/opfor-setup, /opfor-run, /opfor-mcp-setup, /opfor-mcp-run) for developers who want to stay inside the IDE. The SDK is an npm package, @keyvaluesystems/agent-opfor-sdk, exposing run and hunt for programmatic workflows. The README states all five share the same evaluators, attack templates and judge logic, which is the claim worth verifying in the source tree rather than trusting.
Getting a first scan running
Install is global via npm and needs a model provider key:
npm install -g @keyvaluesystems/agent-opfor-cli export OPENAI_API_KEY=your-key
The README lists GEMINI_API_KEY and ANTHROPIC_API_KEY as alternatives, with "etc." after them, so the full provider list is not enumerated in the material I have. The one-shot path is opfor run, which runs the setup wizard and immediately starts the scan. The reusable path is opfor setup followed by opfor run --config .opfor/configs/<file>, and the README notes that saved config can be committed to CI. The SDK path is a separate install, npm install @keyvaluesystems/agent-opfor-sdk, after which you call run or hunt.
The config directory is .opfor/configs/ and the flag is --config. Those two details are the ones you need to wire a CI job. Everything else about the config schema (what keys exist, how a target endpoint is described, how suites are selected) lives in docs/cli.md, docs/sessions.md and the per-mode docs, none of which is in the material supplied here. Treat the config format as unverified until you read those files.
What it does not do, and where it breaks down
The licence badge in the README says Apache 2.0, but the repository metadata reports NOASSERTION. Those two disagree, and the README also carries a bare LICENSE link. Before you vendor this into a product, open the LICENSE file and confirm what it actually contains. That is not a legal opinion, it is a two-minute check that the badge and the file match.
The larger limitation is the judge. Any red-team result from OPFOR is a model's opinion about another model's output. There is no described mechanism for inter-run stability, so a finding that appears once and not on the next run is ambiguous: it could be a flaky target, a flaky judge, or both. Tools built on deterministic assertions avoid this class of problem entirely and pay for it with narrower coverage.
Two more boundaries are visible in the README itself. Trace integration is limited to Langfuse and Netra, so agent-internal visibility depends on your stack. And the browser extension tests a chat interface, which is a different surface from the tool enumeration the CLI performs. If your risk lives in MCP tool calls rather than in chat replies, the extension is the wrong entry point.
Finally, this sends real adversarial traffic to a real target and sends the responses to a judge model. That is a data-flow decision, not just a tooling decision.
How this differs from a probe library or an eval framework
The README draws the comparison itself: most red-team tooling is good at one thing, whether that is a probe library, a developer evaluator, or a programmatic framework. The stated difference is coverage in a single tool plus multiple entry points over a shared core.
That distinction is real but narrower than it sounds. A probe library such as garak or PyRIT gives you composable primitives and no opinion about who runs them; you get determinism and control, and you write the orchestration. OPFOR gives you the orchestration and the judge, and asks you to accept a model's verdict. The practical consequence: a probe library is easier to put in a CI gate that fails a build, because you control the pass condition. OPFOR's output is better suited to a report a human reads, or to a threshold you tune yourself.
The second difference is the audience. A probe library assumes a Python developer. OPFOR assumes a team that includes people who will never open a terminal, and ships a Chrome Web Store extension for them. If your whole team is engineers, you are paying for a surface you will not use.
Maintenance surface and what to check before adopting
The release history shows v0.10.0 in July 2026, v0.10.1 later that month, v0.10.2 in August, and a push to master in September 2026. The version number is still 0.x, which is the honest signal here: expect breaking changes to the config schema and the SDK surface between minor releases. Committing .opfor/configs/ to CI is convenient and also means a schema change lands as a broken pipeline.
Five entry points over one core is a maintenance claim as much as an architecture claim. Every evaluator change has to hold across the CLI, the extension, MCP server mode, the IDE skills and the SDK. That is more surface to keep consistent than a single-binary tool, and the README's assertion that all five share the same evaluators is exactly the thing to confirm by reading the source before you build a workflow on top of the SDK.
The dependency cost is a model provider key plus, optionally, a tracing account. Both are recurring. Budget for judge tokens per scan, because every attack response is scored by a model.
If you adopt, start with opfor setup, inspect the generated file under .opfor/configs/, and run it against a staging agent before anything production-facing. If you need deterministic verdicts, or you cannot route target responses to a model provider, this is the wrong tool regardless of its OWASP coverage.
Editorial conclusion
Adopt OPFOR if you have a deployed agent or MCP server and need a repeatable, logged attack pass that a non-developer can also trigger from the browser extension. Do not adopt it if you need deterministic, non-LLM verdicts, or if you cannot send real attack traffic and real target responses to a model provider. Before you commit, verify three things against the repository: which licence file the LICENSE actually contains, which suites your chosen entry point supports, and whether your tracing backend is on the Langfuse or Netra list.
Community notes