mcp-secret-sentinel
mcp-secret-sentinel is a local, read-only MCP server for finding and redacting exposed secrets across text, files, directories, and git workflows.
Scan raw text, code, configs, diffs, or logs for secrets and return redacted findings.
Scan a single file, handling UTF-8/UTF-16/UTF-32 and skipping binaries or files over 5 MB.
Recursively scan directory trees while skipping common caches, dependencies, binaries, lockfiles, and gitignored files.
Scan only staged git changes as a pre-commit checkpoint.
Scan a git commit range, by default what the next push would publish.
Scan recent git history, optionally across all branches, tags, and the stash, tagging findings by commit.
List active detectors, severities, remediation advice, entropy settings, and allowlist rules without exposing raw regexes.
Return structured, severity-ranked reports with redacted values, summaries, and truncation metadata for bounded responses.
Run safely without confirmation prompts because all tools are annotated read-only, idempotent, non-destructive, and not open-world.
Detects Discord webhooks in code to prevent exposure.
Detects GitHub tokens (classic and fine-grained) in code to prevent exposure.
Detects Google API keys in code to prevent exposure.
Detects MongoDB connection strings with embedded credentials in code to prevent exposure.
Detects MySQL connection strings with embedded credentials in code to prevent exposure.
Detects NVIDIA API keys in code to prevent exposure.
Detects OpenAI API keys in code to prevent exposure.
Detects Redis connection strings with embedded credentials in code to prevent exposure.
Detects Slack tokens and incoming webhooks in code to prevent exposure.
Detects Stripe live keys in code to prevent exposure.
Detects Twilio API keys in code to prevent exposure.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@mcp-secret-sentinel scan staged changes in this repository"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
mcp-secret-sentinel
Local secret guardrails for AI coding agents. An MCP server, a CLI and agent hooks that catch API keys, tokens, private keys and passwords in code, commits, prompts, tool calls and MCP configs, before they leave the machine. 64 detectors, base64-aware, every finding redacted. No account, no network calls.
Secrets rarely leak through hackers; they leak through commits, and now through agents. GitGuardian's State of Secrets Sprawl 2026 counted 28.65 million new secrets on public GitHub in 2025 (+34%), AI-service keys up 81%, 24,008 unique secrets in MCP configuration files, and a higher leak rate in commits co-written with AI coding assistants. A key pasted into .mcp.json, echoed by cat .env into a transcript, or written into a config by an agent in a hurry is compromised from that moment, even if the next commit deletes it.
Secret Sentinel puts a checkpoint at each of those moments:
Moment | What stops it |
The agent writes a key into a tracked file, a shell command or an MCP call | Agent hook denies the tool call (Claude Code, Codex, Cursor) |
You paste a key into a prompt | Agent hook blocks the prompt before it reaches the model |
A tool prints a key ( | Agent hook replaces it with |
A key sits in |
|
A commit or a push is about to publish one |
|
Logs or output have to be shared |
|
The full secret value never appears in any output, so it never enters the conversation transcript either.
Install
Claude Code plugin (skill + agent hooks + MCP server in one step):
/plugin marketplace add AleBrito124356/mcp-secret-sentinel
/plugin install secret-sentinel@secret-sentinelThe hooks run straight from the plugin checkout with any Python 3.10+ (they use only the standard library). The MCP server starts with uv.
MCP server only (any MCP client):
claude mcp add secret-sentinel -- uvx mcp-secret-sentinel{
"mcpServers": {
"secret-sentinel": { "command": "uvx", "args": ["mcp-secret-sentinel"] }
}
}CLI (git hooks, CI, scripts): pipx install mcp-secret-sentinel or pip install mcp-secret-sentinel. To run the latest code from GitHub instead of PyPI, use uvx --from git+https://github.com/AleBrito124356/mcp-secret-sentinel mcp-secret-sentinel.
Agent skill only (Agensi, skills.sh, any agent that reads SKILL.md): the skill lives in skills/secret-sentinel. It tells the agent when to scan, how to fix a finding and how to rotate a leaked credential, and uses the MCP tools or the CLI when they are available.
Related MCP server: re-leak-scan
Agent hooks
mcp-secret-sentinel hook reads one hook event as JSON on stdin and prints the agent's decision. The plugin wires it up for you; without the plugin:
mcp-secret-sentinel install-agent-hooks --agent claude # .claude/settings.json (shared)
mcp-secret-sentinel install-agent-hooks --agent claude --scope local # .claude/settings.local.json
mcp-secret-sentinel install-agent-hooks --agent cursor # .cursor/hooks.jsonThe installer merges into the existing settings and keeps every other hook. Running it again refreshes its own entries instead of duplicating them.
Agent event | Behaviour |
Claude Code / Codex | Denies the call when the new content, the command or the MCP arguments contain a secret ( |
| Blocks the prompt and sets |
| Returns |
Cursor |
|
By default the hook blocks high and critical findings and lets medium ones (JWTs, high-entropy strings) through; hook --fail-on medium is stricter. Excluded paths in .secret-sentinel.toml are respected. The event is read as UTF-8 whatever the console code page, so accented project paths work on Windows. Anything unexpected (bad JSON, a broken config, an internal error) fails open with a non-blocking exit status, so the hook can never wedge the agent; a git failure other than "not a repository" keeps scanning on. Our own MCP tools are exempt, since they receive secrets on purpose.
MCP tools
Tool | Arguments | Returns |
|
| Findings for a raw snippet (code, config, diff, logs) |
|
| Findings for one file; decodes UTF-8/16/32 by BOM, skips binaries and files over 5 MB |
|
| Recursive scan. Inside git, the file list comes from git itself (every |
|
| Only the lines added in |
|
| The commits in |
|
| Lines added by the last N commits (of HEAD, or every branch, tag and the stash), each tagged with its commit |
|
| Audit of MCP client configs and agent instruction files (see below) |
|
|
|
| — | Active detectors with severity and remediation advice, plus the allowlist rules |
Every tool is annotated read-only (readOnlyHint, no open-world access), so clients can run them without a confirmation prompt. The scan tools publish an outputSchema and return structuredContent (MCP SDK 1.10+ / 2.x). The server also offers three prompts, pre_push_check, leak_response and audit_agent_configs, and a secret-sentinel://patterns resource.
All scan tools return the same shape:
{
"clean": false,
"findings": [
{
"file": "config/notify.yaml",
"line": 14,
"pattern": "Slack incoming webhook",
"severity": "high",
"redacted": "hook…(77 chars)",
"advice": "Anyone with this URL can post messages to your workspace. Regenerate the webhook in your Slack app settings and load the URL from an environment variable."
}
],
"files_scanned": 6,
"summary": "Found 1 potential secret(s) across 6 scanned file(s): 1 high. Do NOT commit or push until these are removed or rotated."
}suppressed is added when inline comments silenced findings, baselined when the baseline accepted some. Bounded responses: every scan lists at most max_findings findings (default 200, most severe first, 0 = no limit). When it has to cut, the report says truncated: true and keeps total_findings, counts_by_severity, counts_by_pattern and top_files, so a noisy tree cannot flood the agent's context.
Auditing agent and MCP client configs
scan_agent_configs (CLI: mcp-secret-sentinel agents [PROJECT]) checks:
Project files:
.mcp.json,.claude/settings.json,.claude/settings.local.json,.cursor/mcp.json,.vscode/mcp.json,.vscode/settings.json,.gemini/settings.json,.codex/config.toml,.windsurf/mcp.json,.amazonq/mcp.json,.kiro/settings/mcp.json,.roo/mcp.json,opencode.json, and the agent instruction filesCLAUDE.md,CLAUDE.local.md,AGENTS.md,GEMINI.md,.cursorrules,.windsurfrules,.github/copilot-instructions.md. Each one reports whether git tracks it.User files: Claude Code (
~/.claude.json,~/.claude/settings.json,~/.claude/CLAUDE.md), Claude Desktop, Cursor, VS Code, Cline, Windsurf, Gemini CLI, Codex, Amazon Q, Kiro, Continue, Zed, opencode, Goose and LM Studio.Session transcripts (opt-in): the newest Claude Code and Codex
*.jsonllogs. A key found there was also sent to the model provider.
Files with findings carry a hint on how that client references the environment instead of a literal, for example "env": {"API_KEY": "${API_KEY}"} in Claude Code's .mcp.json or ${input:...} prompts in VS Code.
What it detects
64 regex detectors, plus an entropy check and base64 decoding:
Family | Detectors |
AI and LLM | OpenAI ( |
LLM tooling | LangSmith, Langfuse, Pinecone, Firecrawl, Tavily |
Code hosting and packages | GitHub ( |
Cloud and infrastructure | AWS access keys and secret keys, Azure storage keys, Google API keys and OAuth client secrets, DigitalOcean, Cloudflare, Vercel, Supabase ( |
Payments, messaging, SaaS | Stripe live keys, Square, Shopify, SendGrid, Resend, Mailchimp, Twilio, Slack tokens and webhooks, Discord webhooks, Telegram bots, Linear, Notion, Atlassian, Postman, Sentry, Grafana, PostHog |
Keys and tokens | Private key blocks (RSA, EC, DSA, OPENSSH, PGP, encrypted), |
Credentials in URLs | Database and queue connection strings (Postgres, MySQL/MariaDB, MongoDB, AMQP, Redis) and |
Generic |
|
Entropy: quoted strings of 20+ characters assigned to a variable, with an empirical entropy of at least 4.5 bits/char, when no specific detector claimed the span.
Base64: runs of 20+ base64 characters (standard or URL-safe) that decode to printable text are decoded once and scanned again, so a credential in a Kubernetes Secret manifest, a Basic auth header or an encoded PEM key is found. The finding is named after the inner detector with
(base64).Formats come from the gitleaks, betterleaks and trufflehog rule sets.
sb_publishable_keys, which are meant to be public, are not reported.
For credentials in URLs the reported value is the password, and the allowlist judges the password alone: postgres://app:<literal>@${DB_HOST}/app is still reported.
What it deliberately ignores (allowlist)
Each candidate value is checked against these heuristics before being reported:
Too short: values under 8 characters.
Masked: values that are mostly (≥ 80%)
X,x,*or dots, including vendor prefixes followed by anXXXX…run.example,placeholder,changemeand your-…-here markers, and<angle brackets>.Templates:
${VAR},{{ jinja }},{% … %},<%= … %>,#{…}.Variable references: a value that is only
$UPPER_CASE_VAR,$(command),$env:VARor%VAR%.Format placeholders:
%(name)sor{name}.Environment lookups: values referencing
os.environorprocess.env.Generic assignments and entropy only: code rather than a literal (
os.getenv("X"),settings.DB_PASSWORD,SECRETS[0], one side of a concatenation), values shaped like a regular expression (^(Write|Edit)$,[a-z]{32}), plain links with no credentials, query or fragment, and filesystem paths (C:\Users\...,~/...,/usr/local/...), which fill agent configs. These rules never apply to vendor formats.Reserved documentation hosts: a credentialed URL pointing at
example.com/.net/.org,*.exampleor*.invalid.
Inline suppression
TEST_DSN = "postgres://ci:ci-only-password@db:5432/test" # secret-sentinel: ignoredetect-secrets' pragma: allowlist secret and gitleaks' gitleaks:allow work too, so files annotated for those tools need no changes. Markers are case-insensitive, cover only their own line, and apply to staged and committed lines. Suppressed findings are counted in suppressed, never hidden silently.
Project configuration
mcp-secret-sentinel init writes a commented .secret-sentinel.toml. The same keys work in a [tool.secret-sentinel] table of pyproject.toml. The file is found from the scanned path upwards, stopping at the repository root, and applies to the CLI, the MCP tools and the agent hooks alike.
exclude_paths = ["tests/fixtures/**", "*.snap"] # globs relative to this file; ** spans directories
allowlist = ["^sk_test_"] # regexes matched against the secret value
disable = ["JSON Web Token"] # detector names, "High-entropy string" included
baseline = ".secret-sentinel-baseline.json" # optional
[[rules]]
name = "Acme internal token"
regex = 'acme_[a-f0-9]{32}'
severity = "critical" # critical | high | medium
advice = "Revoke it in the Acme console."Unknown keys, unknown detector names and invalid regexes are errors that name the file and the key, so a typo cannot silently weaken a scan. Custom rules run before the built-in detectors and show up in SARIF as their own rules.
Baselines
Adopting a scanner on an existing repository usually means a few known findings (old test fixtures, revoked keys). Review them, then accept them:
mcp-secret-sentinel baseline # writes .secret-sentinel-baseline.jsonLater scans report only secrets that are not in the baseline, and count the rest in baselined. The file stores a salted PBKDF2 fingerprint of each value (never the value, never a fast hash), plus the file and line to help reviewers. Matching ignores the line, so an accepted value stays accepted when the code around it moves; private keys, whose detected header is the same for every key, are tied to their file name as well. The file is written where scans look for it: the config's baseline path, else the project root. Commit it; scan --no-config ignores it.
Command line
mcp-secret-sentinel with no arguments starts the stdio server, so MCP client configs stay one word long. With a command it becomes a CLI:
mcp-secret-sentinel scan # the current directory
mcp-secret-sentinel scan src config/app.yaml # files and directories
git diff | mcp-secret-sentinel scan - # stdin
mcp-secret-sentinel scan --staged # what the next commit would add
mcp-secret-sentinel scan --range # what the next push would publish (@{upstream}..HEAD)
mcp-secret-sentinel scan --history 100 --all-branches
mcp-secret-sentinel scan --format sarif -o secrets.sarif
mcp-secret-sentinel redact app.log > app.redacted.log
mcp-secret-sentinel agents . # audit agent / MCP client configs
mcp-secret-sentinel install-hook # git pre-commit hook
mcp-secret-sentinel install-agent-hooks --agent claude
mcp-secret-sentinel baseline
mcp-secret-sentinel init
mcp-secret-sentinel patterns # detectors, allowlist rules, suppression markers$ mcp-secret-sentinel scan src
src/billing.py:2 [critical] Stripe live key sk_l…(32 chars)
Roll the key in the Stripe Dashboard (Developers -> API keys). Live keys grant access to real payment data.
src/notify.py:3 [high] Slack incoming webhook hook…(69 chars)
Anyone with this URL can post messages to your workspace. Regenerate the webhook in your Slack app settings and load the URL from an environment variable.
Found 2 potential secret(s) across 2 scanned file(s): 1 critical, 1 high. Do NOT commit or push until these are removed or rotated.Option ( | Meaning |
| Human report (default), the MCP JSON report, or SARIF 2.1.0 |
| Lowest severity that makes the exit status 1 (default |
| List at most N findings, most severe first (default 200; |
| Stop a directory scan after N files (default 5000) |
| With |
| Use a specific configuration, or ignore configuration and baseline |
| Accept the findings recorded in FILE |
| Write the report to a file; the one-line summary goes to stderr |
Exit status: 0 clean (or only findings below --fail-on), 1 findings at or above --fail-on, 2 usage error (bad option, missing path, not a git repository, unknown revision, broken config). Output is redacted in every format.
Block commits with a git hook
mcp-secret-sentinel install-hook # in the repository, or: install-hook path/to/repoThis writes .git/hooks/pre-commit (or the directory core.hooksPath points at). The hook runs scan --staged with the Python that installed it, so a commit is refused while its staged lines contain a secret; git commit --no-verify skips it once. The installer never overwrites another tool's hook unless you pass --force, and then keeps the old one as pre-commit.bak.
With the pre-commit framework:
repos:
- repo: https://github.com/AleBrito124356/mcp-secret-sentinel
rev: v0.3.0
hooks:
- id: secret-sentinelGitHub Action
name: secrets
on: [push, pull_request]
jobs:
scan:
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write # for the SARIF upload
steps:
- uses: actions/checkout@v4
- uses: AleBrito124356/mcp-secret-sentinel@v0.3.0
with:
fail-on: high # critical | high | medium
# range: origin/main..HEAD # scan only new commits (checkout with fetch-depth: 0)
use-config: ${{ github.event_name != 'pull_request' }} # a PR could edit the configThe action writes a redacted SARIF report to code scanning (one rule per detector, with security-severity), puts the text report in the job summary, and fails the step on findings at or above fail-on. A scan that cannot run (a bad range, a shallow clone, a broken config) fails with its own error instead of being reported as findings. --format sarif on the CLI produces the same SARIF 2.1.0 log for any other CI.
How it works
flowchart TD
A[Agent hook, MCP tool or CLI] --> B{Source}
B -->|text / file| C[Decode by BOM, split on newline only]
B -->|directory| D[git ls-files, or a walk outside git;<br/>skip caches, envs, binaries, lockfiles,<br/>config excludes] --> C
B -->|staged / range / history| E[git diff / git log -p, zero context,<br/>diff config overridden, no external programs] --> P[Hunk-counting parser:<br/>added lines, real paths, commit tags] --> C
C --> S{Inline marker?}
S -->|yes| U[Counted in suppressed]
S -->|no| F[Custom rules, then 64 detectors;<br/>specific patterns claim spans first]
F --> G[Base64 runs decoded and rescanned]
G --> H2[Entropy >= 4.5 bits/char on<br/>assigned strings of 20+ chars]
H2 --> H{Allowlist: placeholders, templates,<br/>variables, code, regexes, config allowlist}
H -->|placeholder| I[Dropped]
H -->|real candidate| BL{In the baseline?}
BL -->|yes| BB[Counted in baselined]
BL -->|no| J[Redact: at most 4 chars and<br/>a quarter of the value, + length]
J --> K[Report, SARIF, hook decision<br/>or REDACTED marker]Encodings and line numbers
Files are decoded by byte-order mark (UTF-8, UTF-16 LE/BE, UTF-32) before the binary check, and BOM-less UTF-16 is recognised too, so the output of Windows PowerShell 5.1's > and Out-File is scanned instead of skipped. Lines are split on \n only, so form feeds, \x85, U+2028 and U+2029 inside a line never shift the reported line numbers.
Redaction guarantee
Every finding shows at most the first 4 characters, and never more than a quarter of the value, plus the total length: "hook…(77 chars)", "Tr…(8 chars)". The full value never appears in the output, the transcript, hook decisions or logs. This is enforced in code (a single redact() choke point) and in the test suite, which asserts that raw values are absent from serialized results, hook decisions and real MCP stdio traffic, structured content included.
Git scans read the text, not your diff settings
The git tools parse git diff / git log -p output, and local settings could change it: an external diff tool replaces the diff, diff.mnemonicPrefix or diff.noprefix corrupt the file names. Every git call therefore passes --no-ext-diff --no-textconv --src-prefix=a/ --dst-prefix=b/ -U0 --inter-hunk-context=0 --no-color, overrides core.quotePath, core.fsmonitor, diff.noprefix, diff.mnemonicPrefix, diff.relative, diff.submodule, log.showSignature and log.showRoot with -c, drops GIT_EXTERNAL_DIFF / GIT_DIFF_OPTS, takes no optional locks, closes stdin, and rejects revisions that start with -. The diff parser is a state machine driven by the hunk line counts, so an added line that reads +++ something is content, never a file header.
Limitations
Regex detection, not verification: findings are not checked against the provider (that would send your secrets over the network). Dedicated scanners such as gitleaks, betterleaks or trufflehog, with hundreds of rules and optional live verification, belong in your pipeline too; this is the fast local checkpoint an agent runs before the commit exists.
Outside git, only simple root-
.gitignorepatterns apply (no negations, no**, no nested files). Inside a git work tree the file list comes from git and every rule applies.Entropy needs diversity: a candidate needs at least 23 distinct characters to clear 4.5 bits/char. Short random strings are covered by the regex detectors instead.
Unquoted generic assignments are only detected in dotenv-style
UPPER_CASE=valuelines, a deliberate trade against false positives.Line-by-line matching: a secret split across lines is only caught by its first line (such as a
BEGIN PRIVATE KEYheader). Base64 is decoded one level deep.Inline suppression is same-line only, because in a zero-context diff the line above is usually not visible.
Merge commits are not diffed (git's default for
git log -p), so a secret introduced only while resolving a conflict is missed by the range and history scans;scan_git_stagedstill sees it before the merge commit is made.Binary files in git are not scanned; the summary lists them by name.
Cursor hook support follows Cursor's published hook protocol; Claude Code's is covered by end-to-end tests over a real pipe.
Development
git clone https://github.com/AleBrito124356/mcp-secret-sentinel
cd mcp-secret-sentinel
pip install -e ".[dev]"
python -m pytestFrom the source tree, python -m mcp_secret_sentinel runs the CLI (the MCP server with no arguments). core.py, config.py, agents.py and hooks.py use only the standard library; server.py holds the MCP wiring.
The test suite never contains a realistic secret literal: every positive fixture is assembled at runtime by concatenation, and a test scans this repository and requires it to be clean. It covers every detector, the allowlist, base64 decoding, entropy, redaction, encodings, line numbers, git parsing against real repositories, the CLI as a subprocess, hook decisions (including through the plugin's shell launcher), the agent-config audit, configuration and baselines, and the MCP server over real stdio with the SDK's own client, structured output included. CI runs it on Linux, Windows and macOS, on Python 3.10 to 3.13, and on both majors of the MCP SDK.
Related MCP servers
Part of a family of small, dependency-light MCP servers:
mcp-decision-lab: weighted decision matrices with sensitivity analysis
mcp-devils-advocate: stress-test a claim with devil's advocate, premortem and assumption audits
mcp-git-historian: churn hotspots, blame summaries, bus factor
mcp-memory-vault: persistent memory with SQLite FTS5 search
License
MIT
Available Tools
9 toolslist_patternsARead-onlyIdempotent
List the active secret detectors and allowlist rules.
Returns: {"count": int, "patterns": [{"name", "severity", "advice"}], "entropy_detector": {...threshold and advice...}, "allowlist_rules": [{"name", "description"}]} Raw regexes are intentionally not exposed.
Inputs: no named parameters.
redact_textARead-onlyIdempotent
Return the text with every detected secret replaced by [REDACTED:].
Use it before quoting logs, stack traces, configs, command output or diffs that may contain credentials, in the conversation, an issue, a commit message or a document. Everything that is not a secret is kept exactly as it was.
Args: text: The text to clean.
Returns: {"text": the redacted text, "redactions": how many secrets were replaced, "by_pattern": {detector name: count}}
Inputs: text (required). Returns: text, by_pattern, redactions
scan_agent_configsARead-onlyIdempotent
Audit AI agent and MCP client configuration files for hardcoded secrets.
Checks the project's .mcp.json, .claude/settings*.json, .cursor/mcp.json, .vscode/mcp.json, .gemini/, .codex/ and other client configs, plus agent instruction files (CLAUDE.md, AGENTS.md, GEMINI.md, .cursorrules...), and the user-level configs of Claude Code, Claude Desktop, Cursor, VS Code, Cline, Windsurf, Gemini CLI, Codex, Kiro, Continue, Zed and others. Project files report whether git tracks them: a key in a tracked .mcp.json ships with the repository.
Args: project_path: Absolute path to the project to audit (optional). include_user: Also scan configs in the user's home folder (default true). include_transcripts: Also scan the newest Claude Code / Codex session transcripts (default false; slower). max_findings: List at most this many findings, most severe first.
Returns: The standard redacted report plus "agent_files": [{"client", "scope", "path", "findings", "tracked_by_git", "hint"}] for every file found.
Inputs: include_user, max_findings, project_path, include_transcripts. Returns: clean, summary, findings, baselined, +8 more
scan_directoryARead-onlyIdempotent
Recursively scan a directory tree for exposed secrets.
Inside a git repository the file list comes from git (tracked files plus untracked files no .gitignore excludes), so every ignore rule is honoured. Always skips .git, node_modules, virtualenvs, caches, dist, build, minified bundles, lockfiles, binaries, files over 5 MB and the paths the project's .secret-sentinel.toml excludes.
Args: path: Absolute path to the directory to scan. max_files: Stop after scanning this many files (default 500). max_findings: List at most this many findings, most severe first (default 200, 0 = no limit).
Returns: The standard redacted findings report; finding paths are relative to the scanned root, using forward slashes.
Inputs: path (required), max_files, max_findings. Returns: clean, summary, findings, baselined, +7 more
scan_fileARead-onlyIdempotent
Scan a single file for exposed secrets.
UTF-8, UTF-16 and UTF-32 text is decoded by byte-order mark. Binary files (null-byte heuristic) and files larger than 5 MB are skipped and reported as such in the summary. The project's .secret-sentinel.toml and baseline apply.
Args: path: Absolute path to the file to scan. max_findings: List at most this many findings, most severe first (default 200, 0 = no limit).
Returns: The standard redacted findings report (see scan_text). Returns an error result if the file does not exist.
Inputs: path (required), max_findings. Returns: clean, summary, findings, baselined, +7 more
scan_git_historyARead-onlyIdempotent
Scan the lines added by the most recent commits (git log -p).
Each finding is tagged with the short hash of the commit that introduced it. A secret that was later deleted is still reported — history retains it, so the credential must be rotated regardless.
Args: repo_path: Absolute path to a git repository (or any path inside one). max_commits: How many commits back to inspect (default 50). all_branches: Walk every branch, tag and the stash instead of only the history of HEAD (default false). max_findings: List at most this many findings, most severe first (default 200, 0 = no limit).
Returns: The standard redacted findings report, with a "commit" field on each finding.
Inputs: repo_path (required), max_commits, all_branches, max_findings. Returns: clean, summary, findings, baselined, +7 more
scan_git_rangeARead-onlyIdempotent
Scan the commits in base..head: by default, what git push would send.
Run this before pushing. With the defaults it scans every commit on the current branch that its upstream does not have yet. If the branch has no upstream, the error says so: pass the branch you will push to as base (for example "origin/main").
Args: repo_path: Absolute path to a git repository (or any path inside one). base: Commits reachable from here are excluded (default "@{upstream}"). head: Last commit to include (default "HEAD"). max_commits: Scan at most this many of the newest commits in the range. max_findings: List at most this many findings, most severe first (default 200, 0 = no limit).
Returns: The standard redacted findings report with a "commit" field on each finding, plus "commits_scanned" and "range".
Inputs: repo_path (required), base, head, max_commits, +1 more. Returns: clean, range, summary, findings, +9 more
scan_git_stagedARead-onlyIdempotent
Scan ONLY the lines currently staged for commit (git diff --cached).
This is the pre-commit checkpoint: it inspects exactly the content the next commit would publish, and reports the file and post-commit line number of every added secret. Local diff settings (external diff tools, textconv filters, prefixes, path quoting) are overridden, and git runs no configured programs.
Args: repo_path: Absolute path to a git repository (or any path inside one). max_findings: List at most this many findings, most severe first (default 200, 0 = no limit).
Returns: The standard redacted findings report. If nothing is staged the result is clean with an explanatory summary.
Inputs: repo_path (required), max_findings. Returns: clean, summary, findings, baselined, +7 more
scan_textARead-onlyIdempotent
Scan a snippet of text or code for exposed secrets.
64 detectors: GitHub/GitLab/npm/PyPI tokens; OpenAI, Anthropic, xAI, DeepSeek, Perplexity, OpenRouter, Groq, NVIDIA, Hugging Face, Replicate, Together, Cerebras, LangSmith, Langfuse, Pinecone, Firecrawl and Tavily keys; AWS (incl. Bedrock), Azure, Google, DigitalOcean, Cloudflare, Vercel, Supabase, Neon, PlanetScale, Fly.io, Databricks, Vault and Doppler credentials; Stripe, Square, Shopify, SendGrid, Resend, Mailchimp, Twilio, Slack, Discord, Telegram, Linear, Notion, Atlassian, Postman, Sentry, Grafana and PostHog tokens; JWTs, private and age keys, credentialed connection strings and URLs, generic password/secret/token assignments, plus high-entropy strings. Placeholders ($VAR, ${VAR}, {{ templates }}, changeme, masked values...) are skipped, and a line carrying "secret-sentinel: ignore", "pragma: allowlist secret" or "gitleaks:allow" is counted in "suppressed" instead of reported.
Args: text: The raw text to scan (code, config, diff output, logs...). source_name: Label used in each finding's "file" field. max_findings: List at most this many findings, most severe first (default 200, 0 = no limit). When capped, the result adds truncated, total_findings, counts_by_severity, counts_by_pattern and top_files.
Returns: {"clean", "findings": [{"file", "line", "pattern", "severity", "redacted", "advice"}], "files_scanned", "summary"}. Secret values are ALWAYS redacted (at most 4 chars, never more than a quarter of the value, + length); the full value is never included.
Inputs: text (required), source_name, max_findings. Returns: clean, summary, findings, baselined, +7 more
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 9 tools
Each tool has a clearly distinct scope: listing patterns, scanning text/files/directories, git staged/history/range scanning, agent config auditing, and redaction. The multiple scan_* tools are differentiated by explicit target (text, file, directory, git staged, git history, git range, agent configs) rather than overlapping behavior. An agent can reliably choose the right tool from names and descriptions.
All tool names use consistent snake_case with a predictable verb_noun pattern (list_patterns, scan_text, redact_text, scan_file, scan_directory, scan_git_staged, scan_git_history, scan_git_range, scan_agent_configs). The scan_ prefix groups related scanning operations, while list_ and redact_ are used appropriately. There is no mixing of camelCase or inconsistent verb styles.
Nine tools is well scoped for a secret-scanning server. The set covers distinct scanning targets and a redaction utility without excessive fragmentation. Each tool has a clear purpose and earns its place.
The surface covers the core secret-detection workflow comprehensively: pattern listing, text/file/directory scanning, git staged/history/range scanning, agent config auditing, and redaction. Minor gaps exist around managing custom patterns, allowlist rules, or baselines, but these are handled by project configuration files and are not critical for the scanning lifecycle.
Maintenance
Related MCP Connectors
MCP server: static security scanner for MCP servers, agent skills & plugins. 17 attack patterns.
Security scanner for MCP servers. Detect vulnerabilities, prompt injection, and tool poisoning.
Audit your MCP servers for poisoned tools and leaked secrets, and check AI-generated code for flaws.
Scan any public GitHub MCP-server repo for security issues. 37 MCP-specific L1 rules, 8 languages.
Related MCP Servers
- AlicenseAqualityNot gradedmaintenanceEnterprise-grade MCP (Model Context Protocol) server for detecting secrets and sensitive information in GitHub repositories. Scans for 35+ types of secrets including API keys, passwords, tokens, and credentials with production-ready reliability features.50-
- AlicenseAqualityCmaintenanceMCP server for detecting publisher telemetry pipeline leaks in binary artifacts by scanning for sensitive strings like Sentry DSNs, Slack tokens, and AWS keys.6MIT
- AlicenseAqualityDmaintenanceMCP server for developer workflow automation — smart commits, secret scanning, PR descriptions, and more.5MIT
- AlicenseAqualityBmaintenanceAn MCP server for autonomous AI agents to scan and detect hardcoded secrets, API keys, and passwords in source code files.1MIT