Agents in CI
The same URL and header work unattended. What changes is where the key comes from, and that a pipeline needs a decision it can act on rather than prose.
GitHub Actions
name: Security review
on: pull_request
jobs:
review:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- name: Configure the Vulnetix MCP server
run: |
mkdir -p .mcp
cat > .mcp/config.json <<'JSON'
{
"mcpServers": {
"vulnetix": {
"type": "http",
"url": "https://mcp.vulnetix.com/mcp",
"headers": { "Authorization": "ApiKey ${VULNETIX_AUTH}" }
}
}
}
JSON
env:
VULNETIX_AUTH: ${{ secrets.VULNETIX_AUTH }}
- name: Review changed dependencies
run: your-agent-cli --mcp-config .mcp/config.json --prompt "$(cat .github/review-prompt.md)"
env:
VULNETIX_AUTH: ${{ secrets.VULNETIX_AUTH }}
Store VULNETIX_AUTH as <orgId>:<hex> in Settings → Secrets and variables →
Actions.
secrets.* in logs; it cannot mask one you typed in yourself.GitLab CI
security-review:
image: node:22
variables:
MCP_URL: "https://mcp.vulnetix.com/mcp"
script:
- |
cat > mcp.json <<JSON
{"mcpServers":{"vulnetix":{"type":"http","url":"$MCP_URL",
"headers":{"Authorization":"ApiKey $VULNETIX_AUTH"}}}}
JSON
- your-agent-cli --mcp-config mcp.json --prompt-file .gitlab/review.md
Set VULNETIX_AUTH as a masked, protected CI/CD variable.
Making it a gate
An agent writes prose. A pipeline needs an exit code. Ask for a machine-readable verdict and act on it:
For every dependency added or upgraded in this diff, call
vulnetix_package_searchandvulnetix_kev_status. Output ONLY a JSON object:{"verdict":"pass"|"fail","reasons":[...]}. Fail if any added package has a KEV-listed vulnerability with no fixed version available.
VERDICT=$(your-agent-cli --mcp-config mcp.json --prompt-file gate.md | tail -1)
echo "$VERDICT" | jq -e '.verdict == "pass"' || {
echo "$VERDICT" | jq -r '.reasons[]'
exit 1
}
vulnetix scan --evaluate-sca --severity high --exploits weaponized exits non-zero on its own, with no model
in the path. The MCP server is better at explaining and prioritising than at
being the last word.Quota in CI
Pipelines are the easiest way to burn a daily quota, because they run on every push.
- Scope to the diff. Look up what changed, not the whole lockfile.
- Cap list tools.
limitexists on every one. - Skip drafts.
if: github.event.pull_request.draft == false. - Watch the headroom. Every result carries
_meta["vulnetix/rateLimit"].remaining. - Use a service organisation. A key shared with developers means CI exhausting the pool blocks people mid-task.
What CI cannot do
Sixteen of the 33 prompts drive a local repository and expect the CLI. In CI that is not a limitation. Install the CLI in the same job and let the agent call it:
- run: curl -fsSL https://cli.vulnetix.com/install.sh | sh -s -- --install-dir "$HOME/.local/bin"
Then a prompt like vulnetix_sast_scan or vulnetix_verify_fix has something
real to run against.