Scan from Claude Code, Cursor and Windsurf
Sentris is an MCP server. Point your editor at it and your agent can scan a repo, read the findings and list your targets without you leaving the file you were in.
Setup
Create a key on your dashboard, then paste this into your editor's MCP config — ~/.claude.json for Claude Code, .cursor/mcp.json for Cursor, ~/.codeium/windsurf/mcp_config.json for Windsurf.
{
"mcpServers": {
"sentris": {
"type": "http",
"url": "https://app.sentris.dev/api/mcp",
"headers": { "Authorization": "Bearer sk_sentris_…" }
}
}
}The key is shown once, when you create it. We store only its SHA-256, so we cannot show it to you again and neither can anyone who reaches our database. Lost it? Create a new one — that revokes the old one in the same step.
The loop, without you in the middle
The workflow today is a browser tab and an editor tab: read a finding, retype it into your coding tool, apply the fix, go back, scan again, squint at whether the number moved. Every tool in this category stops at the first tab and leaves the rest to you.
scan_repo → get_fix_prompt → (your agent edits the code)
↓ ↓
get_rules scan_repo
(so it stops happening) ↓
diff_scans
("resolved: 3" — or it did not work)The last step is the one that matters. A fix that was not verified against a fresh scan is a belief, not a result, and an agent that can check its own work does not need you to be the one who notices it failed.
The six tools
| Tool | Arguments | Returns |
|---|---|---|
| scan_repo | { repo: "owner/name" } | { scanId, status } |
| get_findings | { scanId } | the same result the web page shows |
| get_fix_prompt | { scanId } | one prompt carrying every finding |
| get_rules | { scanId } | a security rules file for this codebase |
| diff_scans | { scanId, againstScanId? } | { added, resolved, unchanged } |
| list_targets | — | your targets, each with its latest scan |
- scan_repo — The repo has to be one your GitHub App installation already grants. Naming somebody else's repo returns an error, not a scan.
- get_findings — Without an active subscription this returns the count, the severity breakdown and the grade — and no findings. It runs through exactly the same function the web result page does.
- get_fix_prompt — Severity order, the file and line, the masked evidence and the reviewed fix for each. This is the tool to reach for when the next step is editing code — it is the copy-paste step, done by the machine that was going to receive the paste.
- get_rules — Constraints to follow when writing code here, not a report. Save it as CLAUDE.md, .cursorrules or .github/copilot-instructions.md. Detection is where the abstraction leaks; this is the part that stops the leak.
- diff_scans — Did the fix land? Defaults to the previous scan on the same target. Model-judged findings take no part in the comparison, so a model rephrasing itself can never look like a fix.
- list_targets — Use it to find a scanId without leaving the editor.
What it deliberately cannot do
There is no create_target, no delete_* and no subscribe. An agent that can spend your money or remove your scan history is a bad afternoon waiting for its occasion, and every one of those actions already has a screen a human looks at.
The paywall is the same one the website has, enforced in the same function. A key on an account without an active subscription gets counts and a grade over MCP, exactly as the result page does — there is no second door.
Example
In Claude Code, once it is configured:
> scan acme/storefront with sentris and tell me what to fix first ⏺ scan_repo(repo: "acme/storefront") ⏺ get_findings(scanId: "…") Two criticals. Start with public.orders — it has no RLS at all, so the anon key reads every row. Here is the migration…
Point-in-time, findings-based results. Sentris is not a penetration test, not a certification, and carries no warranty. We report reproducible exposures with evidence and a fix — we prove them, we do not exploit them.