Assay
Runtime security & linting for MCP servers. Finds vulnerabilities in your Model Context Protocol configuration and fixes them automatically.
Install
Script (Recommended)
|
Cargo
Quick Start
# 1. Scaffolding
# 2. Check for issues
# 3. Autofix problems
Core Features
- RCE Prevention: Blocks
exec,shell,spawn,bash,powershell. - Path Containment: Enforces file access strictly within
/appand/data. - Prompt Injection Defense: Flags excessively long or vague tool descriptions.
- Atomic Autofix: Safely repairs config/code with zero corruption risk (atomic I/O).
CI: Validate your MCP policy on every PR (GitHub Actions)
Copy this workflow to .github/workflows/assay-security.yml.
It does two things:
- Validates your policy file (syntax + JSON Schema compilation)
- Runs full assay validate and uploads SARIF to GitHub Code Scanning
Tip: pin a specific Assay version for reproducible CI results.
name: Assay MCP Security
on:
push:
paths:
- "assay.yaml"
- "policy.yaml"
- "**/*.mcp.json"
- ".github/workflows/assay-security.yml"
pull_request:
paths:
- "assay.yaml"
- "policy.yaml"
- "**/*.mcp.json"
- ".github/workflows/assay-security.yml"
jobs:
assay:
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write # required for SARIF upload
steps:
- uses: actions/checkout@v4
- name: Install Assay
run: |
curl -fsSL https://getassay.dev/install.sh | sh
echo "$HOME/.local/bin" >> $GITHUB_PATH
# Optional: pin a specific version for stable CI
# assay --version
# If your installer supports version pinning, use it here.
# Fast check: policy syntax + schema compilation
- name: Validate policy file
run: |
# Adjust to your policy path:
assay policy validate --input policy.yaml
# Full check: emits SARIF for GitHub Code Scanning
- name: Assay validate (SARIF)
run: |
assay validate --format sarif --output results.sarif
continue-on-error: true
- name: Upload SARIF to GitHub Security
uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: results.sarif
# Hard fail for PR gating (human-readable output)
- name: Fail on issues
run: |
assay validate --format text
Recommended: pin Assay to a specific release in CI to keep behavior stable across time. When upgrading, run the workflow on a branch and review any new warnings/errors before merging.
Output Formats
- Human (Default): ANSI-colored terminal output.
- JSON (
--format json): Strict schema for scripts/agents. - SARIF (
--format sarif): Native GitHub Security tab integration.
Configuration
Generated by assay init. Edit assay.yaml to customize:
version: "1.0"
name: "mcp-default-gate"
# Global defaults
allow:
# Explicit blocks
deny:
- "exec*"
- "shell*"
# Parametric constraints
constraints:
- tool: "read_file"
params:
path:
matches: "^/app/.*|^/data/.*"
Migration to v2.0 (JSON Schema)
Assay v1.6.0 introduces JSON Schema based policies for stricter validation.
- Auto-migrate (Preview):
- Apply migration:
- Verify:
See docs/policies.md for full syntax reference.
Documentation
Full documentation available at getassay.dev.
Contributing
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
CI: Build & Test (GitHub Actions)
Copy-paste this into .github/workflows/ci.yml to build the workspace (including binaries)
and run the crate test suites on Linux/macOS/Windows:
# (see .github/workflows/ci.yml)
name: CI
on:
push:
branches:
pull_request:
jobs:
test:
name: Build + Test (${{ matrix.os }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os:
steps:
- uses: actions/checkout@v4
- name: Install Rust (stable)
- uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt, clippy
- name: Rust cache
uses: Swatinem/rust-cache@v2
with:
# cache all workspace crates
workspaces: |
. -> target
# IMPORTANT: build binaries first so assert_cmd E2E tests can find them
- name: Build workspace (binaries)
run: cargo build --workspace
- name: Test assay-core
run: cargo test -p assay-core
- name: Test assay-cli
run: cargo test -p assay-cli
- name: Test assay-mcp-server
run: cargo test -p assay-mcp-server