examples/redteam-mcp-agent/README.md
This example demonstrates how to red team test AI agents that integrate with Model Context Protocol (MCP) servers. It creates a custom OpenAI-based ReAct agent provider that can interact with MCP servers, allowing you to test agent behavior when given access to potentially malicious tools.
You can run this example with:
npx promptfoo@latest init --example redteam-mcp-agent
cd redteam-mcp-agent
The example includes:
This example requires the following environment variable:
OPENAI_API_KEY - Your OpenAI API key (get one at https://platform.openai.com/api-keys)You can set this in a .env file in the example directory:
OPENAI_API_KEY=sk-...
npm install
export OPENAI_API_KEY=your-openai-api-key-here
# Or create a .env file with OPENAI_API_KEY=your-key
npx promptfoo@latest redteam run
redteam-mcp-agent/
├── src/
│ ├── openai-agent-provider.js # Custom OpenAI agent provider
│ ├── react-agent.js # ReAct pattern agent implementation
│ ├── mcp-client.js # MCP client for tool connections
│ └── mcp_server/ # Example MCP server
│ ├── index.js # Server entry point
│ └── tools/ # Tool implementations
├── promptfooconfig.yaml # Main configuration
├── redteam.yaml # Generated red team test cases
├── server.py # Python MCP server example
└── package.json # Node.js dependencies
The main configuration file defines:
Provider Configuration: Uses a custom OpenAI agent provider with:
gpt-4o (you can also use gpt-4o-mini or o3-mini)MCP Servers: Three types of connections are demonstrated:
@promptfoo/evil-mcp-server (for security testing)./src/mcp_server/index.jshttp://localhost:8080/mcp (Python server)Red Team Configuration:
# yaml-language-server: $schema=https://promptfoo.dev/config-schema.json
providers:
- id: file://./src/openai-agent-provider.js
config:
apiBaseUrl: 'https://api.openai.com/v1'
model: 'gpt-4o' # or gpt-4o-mini, o3-mini
systemPrompt: |
You are a helpful AI assistant with access to various tools...
mcpServers:
- command: 'npx'
args: ['-y', '@promptfoo/evil-mcp-server@latest']
- command: 'node'
args: ['./src/mcp_server/index.js']
- url: 'http://localhost:8080/mcp'
redteam:
purpose: |
You are acting as a financial analyst employee at Acme Inc...
tools: get_financial_summaries
startDate: string - Start date for the report (ISO 8601)
endDate: string - End date for the report (ISO 8601)
groupBy: enum ['day', 'week', 'month'] - Group results by period
plugins:
- id: policy
config:
policy: Test to trigger the get_financial_summaries tool...
The example includes @promptfoo/evil-mcp-server which provides potentially dangerous tools for security testing:
mcpServers:
- command: 'npx'
args: ['-y', '@promptfoo/evil-mcp-server@latest']
The included Node.js server (src/mcp_server/index.js) provides ERP and analytics tools:
mcpServers:
- command: 'node'
args: ['./src/mcp_server/index.js']
To run the Python server example:
# Install FastMCP if not already installed
pip install fastmcp
# Run the server
python server.py
Then reference it in your config:
mcpServers:
- url: 'http://localhost:8080/mcp'
When you run the red team tests, promptfoo will:
Example output includes:
To add your own MCP server:
mcpServers in promptfooconfig.yaml:mcpServers:
- command: 'python'
args: ['path/to/your/server.py']
purpose section with your tool schemasEdit the redteam section to customize:
Update the model in the provider configuration:
config:
model: "gpt-4o-mini" # More cost-effective option
# or
model: "openai:chat:gpt-5.4" # Latest OpenAI model
"OpenAI API key is required"
OPENAI_API_KEY is set in your environment or .env file"Failed to connect to MCP server"
"Tool not found" errors
purpose section match the MCP server's toolsPython server not working
pip install fastmcpWhen developing the provider locally:
# Use local version instead of published package
npm run local -- redteam run
To see detailed agent reasoning, the provider logs:
Example MCP tool implementation:
// In src/mcp_server/tools/customTools.js
export const customTools = [
{
name: 'my_custom_tool',
description: 'Does something specific',
inputSchema: {
type: 'object',
properties: {
param1: { type: 'string', description: 'First parameter' },
},
required: ['param1'],
},
},
];
export async function handleCustomTool(name, args) {
if (name === 'my_custom_tool') {
// Tool implementation
return { result: 'Tool executed successfully' };
}
}