Quick Start¶
Add a policy gate to a stdio MCP server on macOS or Linux.
These wrap steps are Unix. We ship an x86_64-pc-windows-msvc archive; this page does not give a Windows walkthrough because the example policy requires paths matching ^/tmp/assay-demo/.*. A Windows path kept under that same policy is denied by the policy, not by Unix path syntax.
Install¶
For exact stdout, exits, upgrade, and rollback behavior, use the release-pinned agent golden path.
Option A: Wrap an MCP Server (recommended)¶
This example wraps a filesystem MCP server over stdio. Decision lines print on stderr, and only with --verbose.
1. Create a demo workspace:
2. Wrap with policy:
assay mcp wrap --policy examples/mcp-quickstart/policy.yaml --verbose \
-- npx -y @modelcontextprotocol/server-filesystem /tmp/assay-demo
3. See decisions:
Send a tools/call through the wrap. Captured stderr from that command on macOS arm64 (assay-cli 6.5.0) after initialize, tools/list, and one allowed read_file of /tmp/assay-demo/safe.txt:
[assay] loading policy from examples/mcp-quickstart/policy.yaml
[assay] wrapping command: npx ["-y", "@modelcontextprotocol/server-filesystem", "/tmp/assay-demo"]
[assay] ALLOW read_file
Secure MCP Filesystem Server running on stdio
The same command, after a read_file of /tmp/outside-demo.txt:
The same command, after an exec call:
Without --verbose, those ALLOW/DENY lines are not printed. A no-flag run still prints the loading-policy and wrapping-command lines plus the child's banner; a denied call still returns a JSON-RPC deny on stdout. Missing decision lines are not a clean run.
See the MCP quickstart example for the full walkthrough.
Option B: Run a Smoke Test¶
If you don't have an MCP server handy, run the built-in smoke test:
Option C: Import from MCP Inspector¶
If you already have an MCP Inspector session saved as session.json and an eval.yaml configured for that trace:
mkdir -p traces
assay import --format inspector session.json --out-trace traces/session.jsonl
assay validate --config eval.yaml --trace-file traces/session.jsonl
Add to CI¶
# .github/workflows/assay.yml
name: Assay Gate
on: [push, pull_request]
permissions:
contents: read
security-events: write
jobs:
assay:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0
- uses: Rul1an/assay-action@v3