Skip to main content

MCP & A2A security proxy with real-time threat detection

Project description

Crossfire

MCP & A2A Security Proxy with Real-Time Threat Detection

Crossfire is a transparent man-in-the-middle proxy that sits between your IDE and MCP servers, detecting credential theft, prompt injection, data exfiltration, and 7 other attack patterns in real time. It also intercepts A2A (Agent-to-Agent) protocol traffic over HTTP.

Virtual environment (recommended)

Crossfire does not require a venv, but you should use one so pip install -e . does not mix with system or other projects’ packages (especially if you install the gemini extra).

python3 -m venv .venv
source .venv/bin/activate          # Windows: .venv\Scripts\activate
pip install -e ".[gemini]"        # or: pip install -e .

.venv/ is listed in .gitignore. In Cursor, select Python: Select Interpreter./.venv/bin/python for this workspace.

Quick Start (pip — recommended)

You do not need Node or npm for the MCP proxy: pip install adds both crossfire and crossfire-proxy next to your Python (same venv). Run crossfire install from that environment so mcp.json gets the absolute path to crossfire-proxy (works even when Cursor has a minimal PATH).

python3 -m venv .venv
source .venv/bin/activate                    # Windows: .venv\Scripts\activate

# Install Crossfire (core detectors + dashboard API; no Gemini SDK)
pip install -e .
# When published to PyPI:  pip install crossfire-mcp

# Optional: Gemini enrichment (GOOGLE_API_KEY or CROSSFIRE_GEMINI_KEY)
# pip install -e ".[gemini]"

# Build the React dashboard once (needed for the full UI on :9999; or use Vite dev on :5173 only)
cd dashboard && npm install && npm run build && cd ..

# Rewrite MCP configs to use crossfire-proxy, then start the dashboard
crossfire install
crossfire dashboard
# Open http://localhost:9999
# crossfire ping          # smoke-test event without MCP
# crossfire ping --threat # + sample critical threat

# Demo (poisoned MCP server):  bash demo/run-demo.sh

PyPI wheels: Before python -m build / publishing, copy the built UI into the package so the wheel ships static assets:

cd dashboard && npm ci && npm run build && cd ..
python3 scripts/sync_dashboard_dist.py
python -m build

(server/web_dist/ is gitignored; editable installs still use dashboard/dist from the repo.)

MCP config & what Crossfire sees

Crossfire’s stdio proxy only applies to MCP servers defined with a command (and optional args). The installer rewrites those so traffic flows through crossfire-proxy (the pip console script, or the optional Node shim) before your real server.

  • URL-only MCP (url set, no command): the IDE talks to a remote endpoint directly. crossfire install skips these — Crossfire cannot sit in the middle without a local process. Use stdio-based servers if you need inspection.
  • Config locations (all are scanned; the same file on disk is only processed once):
    • Cursor: ~/.cursor/mcp.json and project .cursor/mcp.json (relative to cwd when you run crossfire install)
    • VS Code: ~/.vscode/mcp.json and project .vscode/mcp.json
    • Windsurf (Codeium): ~/.codeium/windsurf/mcp_config.json
    • Google Antigravity: ~/.gemini/antigravity/mcp_config.json
    • Claude Desktop: OS-specific paths under Application Support / .config (see proxy/installer.py)

Diagnostics: crossfire doctor prints each known config path (if present), classifies each server (proxied / stdio not proxied / URL-only), and checks the dashboard (/health, /api/guardian). Run the dashboard first (crossfire dashboard) for a full green check.

If MCP servers won’t start or configs don’t look proxied

  • Use the same Python/venv where you ran pip install -e .: activate it, then crossfire install. The installer prefers crossfire-proxy next to sys.executable, so mcp.json stores a full path that Cursor can run without relying on shell PATH.
  • If you still see warnings, ensure crossfire-proxy exists (e.g. ls "$(dirname $(which python3))/crossfire-proxy").
  • crossfire start restores MCP configs on exit (Ctrl+C). For a persistent setup, use crossfire install and crossfire dashboard instead of the one-shot flow.

npm / npx (thin shim — installs Python from PyPI)

The npm package crossfire-mcp ships only bin/ scripts plus a postinstall hook. On install it runs pipx install crossfire-mcp (preferred) or pip install --user crossfire-mcp, so the real crossfire and crossfire-proxy CLIs come from PyPI (bundled dashboard in the wheel). You do not need a git clone for the published npm package.

npx crossfire-mcp dashboard
# or: npm install -g crossfire-mcp && crossfire dashboard

From a git clone: if pyproject.toml is present next to package.json, postinstall uses pip install -e . into .venv/ (development layout).

Publishing the wheel first: npx users need the crossfire-mcp Python package on PyPI (same name as the npm package). Build the UI, sync, and upload the wheel (see PyPI wheels above) before npm publish.

Seeing traffic (dashboard)

Step What to do
Smoke test (no MCP) Start crossfire dashboard, then run crossfire ping. The Traffic Log should show one event (server: ping). Use crossfire ping --threat to also post a sample critical threat (demo). The UI loads past events on connect (GET /api/events); POST /api/events accepts one JSON object per request (not a JSON array).
Real MCP traffic Add stdio MCP servers (command + args), run crossfire install, restart the IDE, then use a chat that invokes tools (not just text). URL-only MCP is not proxied.
Dashboard URL If the proxy and UI are not on http://localhost:9999, set CROSSFIRE_DASHBOARD_URL (or dashboard.url in crossfire.yaml) and restart the IDE.
Config not found The IDE often runs MCP with a cwd that is not your repo root, so crossfire.yaml is skipped. Fix: set CROSSFIRE_CONFIG to the full path of your crossfire.yaml, or set CROSSFIRE_DASHBOARD_URL in the MCP server env block. The proxy also checks the repo root next to the installed proxy package (after cwd and before ~/.crossfire.yaml).

Active vulnerability scan (no IDE)

Runs initializetools/list → synthetic tools/call probes and applies the same detectors as the live proxy (description poisoning, rules, response secret patterns, cross-call chains).

crossfire scan --cmd "python3 demo/poisoned_weather.py"
crossfire scan --server myserver          # resolve command from MCP configs
crossfire scan --all                      # every stdio server in configs
crossfire scan --cmd "python3 demo/poisoned_weather.py" --json

With crossfire dashboard running, trigger a scan via POST /api/scan with {"server_name":"..."} or {"command":["python3","demo/poisoned_weather.py"]}. Progress appears on WebSocket /ws as scan_progress and scan_complete; GET /api/scan/results returns recent reports. (A dashboard “Scan” button can call the same API.)

Figma design URLs: Crossfire records MCP JSON-RPC (e.g. tools/call with fileKey / node id in arguments). Opening a file in the browser at https://www.figma.com/design/... does not go through the MCP proxy; you will see the design when you invoke a Figma MCP tool that references that file (check the Traffic Log / raw params).

Architecture

IDE (Cursor, VS Code, Windsurf, Antigravity, Claude, …)
  │ stdin/stdout (JSON-RPC)
  ▼
┌─────────────────────┐
│  CROSSFIRE PROXY    │──── POST /api/events ────▶ Dashboard Server (:9999)
│  (stdio MITM)       │                                    │
│  • 10 rule detectors│                                    ▼
│  • Gemini AI agent  │                           React Dashboard (:5173)
│  • Chain tracker    │                           • React Flow graph
└─────────────────────┘                           • Traffic log
  │ stdin/stdout                                  • Threat detail
  ▼                                               • Guardian toggle
MCP Server

Threat Detection (10 Patterns)

Pattern Severity Detection
CRED-THEFT critical Sensitive file path matching (.ssh, .env, tokens)
SHELL-INJECT critical Shell command pattern matching (curl, nc, base64)
EXFIL-NET high Large payloads to reporting/telemetry tools
TOOL-SHADOW medium Unknown tool not in server's registry
PROMPT-RELAY critical Prompt injection → privileged tool calls
MEM-POISON high Suspicious writes to memory tools
PRIV-ESCAPE critical File write → shell execution chain
RUG-PULL critical SHA-256 hash diff on tool descriptions
TYPOSQUAT high Levenshtein distance to known server names
A2A-HIJACK critical A2A-specific impersonation/exfil/injection

Environment variables

Variable Purpose
CROSSFIRE_DASHBOARD_URL Override dashboard base URL for the proxy / A2A forwarder (default: http://localhost:9999 or dashboard.url in config).
CROSSFIRE_CONFIG Path to crossfire.yaml or a directory containing it; highest priority when set (useful when the MCP process cwd is not the repo).
GOOGLE_API_KEY / CROSSFIRE_GEMINI_KEY Optional Gemini enrichment (install pip install -e ".[gemini]" first).
VITE_WS_URL (Dashboard dev/build) Override WebSocket URL; otherwise the UI uses ws(s)://<current-host>/ws.

Gemini: Core Crossfire works without any Google packages. Install the gemini extra and set an API key only if you want AI-assisted explanations on top of rules.

Config-as-Code

Create crossfire.yaml or .crossfire.yaml:

version: 1
mode: monitor  # or "block" (also toggle Guardian in the dashboard)

dashboard:
  url: "http://localhost:9999"

rules:
  sensitive_paths:
    enabled: true
    block: ["~/.ssh/*", "**/.env"]
  shell_injection:
    enabled: true
    blocked_patterns: ["curl *", "| bash"]
  typosquat:
    enabled: true
    max_distance: 2
  rug_pull:
    enabled: true

Project Structure

crossfire/
├── proxy/              # Python MCP proxy + detectors
│   ├── __main__.py     # CLI entry point
│   ├── protocol.py     # MCP wire format handler
│   ├── proxy.py        # Bidirectional stdio proxy
│   ├── a2a_proxy.py    # A2A HTTP reverse proxy
│   ├── config.py       # YAML config loader
│   ├── installer.py    # Auto-detect & rewrite MCP configs
│   ├── scanner.py      # Active MCP vuln scan (CLI + /api/scan)
│   └── detectors/      # 10 threat detectors + Gemini AI
├── server/             # FastAPI dashboard backend
├── dashboard/          # React + React Flow frontend
├── shared/             # Event schema contract (Python + TypeScript)
├── demo/               # Poisoned weather server + sandbox
├── bin/                # Node.js CLI wrappers for npm
└── crossfire.yaml      # Default configuration

Tech Stack

  • Proxy: Python 3.10+, asyncio, aiohttp
  • Detectors: regex, python-Levenshtein, SHA-256 hashing
  • AI Analysis: Google ADK + Gemini 2.5 Flash
  • A2A Proxy: FastAPI + httpx (HTTP reverse proxy)
  • Dashboard Backend: FastAPI + WebSockets + uvicorn
  • Dashboard Frontend: React 19, React Flow v12, Tailwind v4
  • Config: YAML with deep merge + hot reload
  • Distribution: pip + npm (npx crossfire install)

Team

  • Yugandhar - Python backend (proxy, server, detectors)
  • Ruthvik - React dashboard (components, flow graph, UI)

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

crossfire_mcp-0.1.0.tar.gz (274.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

crossfire_mcp-0.1.0-py3-none-any.whl (284.8 kB view details)

Uploaded Python 3

File details

Details for the file crossfire_mcp-0.1.0.tar.gz.

File metadata

  • Download URL: crossfire_mcp-0.1.0.tar.gz
  • Upload date:
  • Size: 274.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.12

File hashes

Hashes for crossfire_mcp-0.1.0.tar.gz
Algorithm Hash digest
SHA256 18b37b12d6147106c7f50ffad124cc3bb4102bda9a8b96145c12416f9411a74f
MD5 c0a06003363e03376d31cf48f9f422f1
BLAKE2b-256 04c3b37412440661ceb2f8244378c25d119f93429d0001922b76c81a1e0a1943

See more details on using hashes here.

File details

Details for the file crossfire_mcp-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: crossfire_mcp-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 284.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.12

File hashes

Hashes for crossfire_mcp-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b1a67c20cd4b585025017ee2bc2564fbb9a87bbe95353f7063de3d5a81dd4ded
MD5 219c5c9212d3e3e7d60153f28deb7556
BLAKE2b-256 986f775bb53220f1e742cd0987d5a2cd3408ff7a2a201072b789a751d23ab9b0

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page