{
  "markdown": "# secretguard-mcp\n\n[![CI](https://github.com/vladimirbakalov/secretguard-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/vladimirbakalov/secretguard-mcp/actions/workflows/ci.yml)\n[![Latest release](https://img.shields.io/github/v/tag/vladimirbakalov/secretguard-mcp?label=release)](https://github.com/vladimirbakalov/secretguard-mcp/releases)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)\n\nAn MCP (Model Context Protocol) server that scans a code string for\nhardcoded secrets — AWS keys, Stripe keys, GitHub tokens, Google API keys and\nOAuth client secrets, Slack tokens and incoming webhook URLs, Shopify access\ntokens, Telegram bot tokens, DigitalOcean tokens, Hugging Face tokens,\nNotion API tokens, Mailchimp API keys, Postman API tokens, Linear API keys,\nReadme API keys, Clojars API tokens, Pulumi API tokens, OpenAI keys, Anthropic keys, npm access tokens, SendGrid keys, Twilio API keys, Azure\nStorage account keys, database connection strings with embedded passwords,\nprivate key blocks, JWTs, and generic high-entropy credentials — so an AI coding\nagent (Claude Code, Cursor, Windsurf, ...) can catch a\nsecret *before* it writes the file or makes the commit, instead of finding\nout at CI/PR-review time. It exposes exactly one tool, `scan_for_secrets`,\nruns entirely locally over stdio, needs no API key, and never returns a raw\nsecret value — every finding comes back redacted.\n\n## Why this exists\n\n[`secret-scan-action`](https://github.com/vladimirbakalov/secret-scan-action)\nalready catches these secrets in CI, on every PR. That's necessary but late\n— by the time it runs, the secret has already been written, committed, and\npushed. This project reuses that same detection engine (same rules, same\nentropy check, same redaction) but puts it in front of the agent as a tool\ncall, so the check can happen at generation time, before the secret ever\ntouches disk or history.\n\n## What it does\n\nOn a `scan_for_secrets` call:\n\n1. Splits the input `code` string into lines.\n2. Runs the same two-tier ruleset `secret-scan-action` uses:\n   - **Pattern rules (high confidence)** — distinctive formats that are\n     near-certain secrets when matched: AWS access key IDs (`AKIA...`) and\n     contextual secret keys, Stripe live keys (`sk_live_`, `rk_live_`),\n     GitHub tokens (`ghp_`, `gho_`, `github_pat_`, ...), Google API keys\n     (`AIza...`), Google OAuth client secrets (`GOCSPX-...`), Slack tokens\n     (`xox[baprs]-...`), Slack incoming webhook URLs\n     (`hooks.slack.com/services/...`), Shopify access tokens (`shpat_...`,\n     `shpca_...`, `shpss_...`, `shppa_...`, `shpua_...`), Telegram bot tokens\n     (`<bot_id>:A...`, 35-char secret), DigitalOcean tokens (`dop_v1_...`,\n     `doo_v1_...`, `dor_v1_...`, 64-char hex), Hugging Face tokens (`hf_...`,\n     `api_org_...`, 34-char alpha), Notion API tokens (`ntn_...`, 11 digits +\n     35 alphanumeric), OpenAI keys (`sk-...`, `sk-proj-...`,\n     `sk-svcacct-...`), Anthropic keys (`sk-ant-...`), npm access tokens\n     (`npm_...`), SendGrid keys (`SG....`), Twilio API keys (`SK...`), Azure\n     Storage account keys (contextual `AccountKey=...`), private key blocks\n     (`-----BEGIN ... PRIVATE KEY-----`), and JWTs. One pattern rule —\n     database connection strings with an embedded password\n     (`postgres://`, `mysql://`, `mongodb(+srv)://`, `redis(s)://`,\n     `amqp(s)://`) — is deliberately *not* near-certain even after excluding\n     known placeholder passwords (`user`, `password`, `changeit`, ...) and\n     `${...}`-style env-var references, since a real value there could still\n     be a low-stakes tutorial example rather than a live credential; it's\n     returned at generic confidence, same as the entropy rule below. Another\n     pattern rule — Mailchimp API keys (a 32-char hex value followed by a\n     `-usNN` datacenter suffix) — is also generic confidence: it only fires\n     when a `mailchimp`-prefixed variable/key name immediately precedes the\n     value, but that keyword gate still doesn't rule out an unrelated hex\n     value that happens to end in the same suffix shape. Postman API tokens\n     (`PMAK-...`, 24-char hex + `-` + 34-char hex), Linear API keys\n     (`lin_api_...`, 40-char alphanumeric), Readme API keys\n     (`rdme_...`, 70-char lowercase alphanumeric), Clojars API tokens\n     (`CLOJARS_...`, case-insensitive, 60-char alphanumeric), and Pulumi API\n     tokens (`pul-...`, 40-char lowercase hex) are high confidence — a fixed\n     prefix and exact length, same as the other provider-token rules.\n   - **Generic entropy rule** — a value assigned to a variable named like\n     `secret`, `token`, `password`/`credential`, or a `*key` compound\n     commonly used for real secret material (`apiKey`, `sessionKey`,\n     `signingKey`, `clientKey`, `webhookKey`, ...) whose value also has high\n     Shannon entropy (looks random, not like a placeholder or an env-var\n     reference). Deliberately does *not* match a bare `*Key` — that would\n     also catch `partitionKey`, `cacheKey`, `queryKey`, and similar\n     non-secret identifiers common in ordinary code.\n3. Returns every finding's `filename`, `line`, `ruleId`, `description`,\n   `confidence` (`\"high\"` | `\"generic\"`), and a **redacted** line — the raw\n   secret value never leaves the process. If nothing is found, it returns a\n   plain \"No secrets detected.\" result.\n\n## Example output\n\nCalling `scan_for_secrets` with:\n\n```json\n{\n  \"code\": \"const key = \\\"AKIAIOSFODNN7EXAMPLE\\\";\\nconst greeting = \\\"hello\\\";\",\n  \"filename\": \"src/config.ts\"\n}\n```\n\nreturns:\n\n```json\n{\n  \"findings\": [\n    {\n      \"filename\": \"src/config.ts\",\n      \"line\": 1,\n      \"ruleId\": \"aws-access-key-id\",\n      \"description\": \"AWS Access Key ID\",\n      \"confidence\": \"high\",\n      \"redactedLine\": \"const key = \\\"AKIA************MPLE\\\";\"\n    }\n  ],\n  \"summary\": \"Found 1 potential secret (1 high-confidence, 0 needs-review).\\n\\n- [high] src/config.ts:1 — AWS Access Key ID (aws-access-key-id)\\n  const key = \\\"AKIA************MPLE\\\";\"\n}\n```\n\n(The AWS key above is AWS's own public documentation placeholder, not a live\ncredential.) A clean scan — e.g. `{ \"code\": \"const greeting = \\\"hello\nworld\\\";\" }` — returns `{ \"findings\": [], \"summary\": \"No secrets\ndetected.\" }`.\n\n## Setup\n\nNot yet published to the npm registry — install directly from GitHub via\n`npx`. `npm install` from a git source runs this package's `prepare` script\nautomatically, which builds `dist/` on the fly, so no separate build step is\nneeded.\n\n### Claude Code\n\nAdd to your project's `.mcp.json` (or run `claude mcp add`):\n\n```json\n{\n  \"mcpServers\": {\n    \"secretguard\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"github:vladimirbakalov/secretguard-mcp\"]\n    }\n  }\n}\n```\n\n### Claude Desktop\n\nAdd to `claude_desktop_config.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"secretguard\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"github:vladimirbakalov/secretguard-mcp\"]\n    }\n  }\n}\n```\n\nNo API key, no account, no config options — restart Claude Code / Claude\nDesktop and `scan_for_secrets` is available. The tool description tells the\nagent to call it before writing code that could contain a credential, and\nagain before a commit or PR — most of the time you won't need to ask for it\nexplicitly.\n\n### Cursor / Windsurf\n\nBoth read the same `command`/`args` shape from their own MCP settings UI or\nconfig file — point them at `npx -y github:vladimirbakalov/secretguard-mcp`\nthe same way.\n\nOnce this package is published to npm, the `args` above can drop to\n`[\"-y\", \"secretguard-mcp\"]` instead — that's a follow-up, not a blocker.\n\n### One-click install (.mcpb)\n\nA prebuilt [MCP Bundle](https://github.com/modelcontextprotocol/mcpb) is\nattached to the\n[`v0.1.4-mcpb` release](https://github.com/vladimirbakalov/secretguard-mcp/releases/tag/v0.1.4-mcpb) —\ndownload `secretguard-mcp-0.1.4.mcpb` and open it in Claude Desktop (or any\nother MCPB-compatible client) for a one-click local install, no `npx`/Node\nsetup required on the client side. Rebuild it yourself with\n`npm run package:mcpb` (see `scripts/build-mcpb.sh`).\n\nThis same `.mcpb` release asset is what `server.json` at the repo root points\nat for the [official MCP Registry](https://registry.modelcontextprotocol.io/) —\n`secretguard-mcp` is published and listed there as\n[`io.github.vladimirbakalov/secretguard-mcp`](https://registry.modelcontextprotocol.io/v0/servers?search=secretguard),\nso MCP clients that browse the official registry can discover and install it\ndirectly, in addition to the `npx`/`.mcpb` paths above. Publishing runs\nunattended in CI (`.github/workflows/publish-mcp.yml`) via `mcp-publisher\nlogin github-oidc` on every `v*-mcpb` tag push — no interactive login step.\n\n## Security notes\n\n- The raw secret value matched by a rule is held in memory only for the\n  duration of a single `scan_for_secrets` call and is redacted\n  (`redactLine`/`redactSecret`) before the tool result is built — it never\n  appears in the returned `content`, `structuredContent`, or any log line.\n- The server does no network calls of any kind. It reads stdin, writes\n  stdout (MCP stdio transport), and does nothing else.\n- Generic-tier findings are ambiguous by nature (config placeholders,\n  hashes, and UUIDs can trip the entropy check) — that's expected. Treat\n  `confidence: \"generic\"` as \"worth a second look,\" not \"confirmed.\"\n\n## Development\n\n```bash\nnpm install\nnpm run typecheck   # tsc --noEmit\nnpm test            # vitest run\nnpm run build       # tsc -p tsconfig.build.json -> dist/\n```\n\n`dist/` is not committed — it's built from `src/` via the `prepare` script,\nwhich runs both on a git-based `npx`/`npm install` and before any future\n`npm publish`.\n\n## Scope (v1)\n\nOne tool, one job: scan a code string, return redacted findings. No\nallowlist file, no AI triage step, no config options, no persistent state.\nIf this needs any of that later, it'll get added once real usage shows it's\nneeded — not before.\n\n## Relationship to secret-scan-action\n\n`secretguard-mcp` and\n[`secret-scan-action`](https://github.com/vladimirbakalov/secret-scan-action)\nshare the same detection engine (`rules.ts`, `redact.ts`, and the core of\n`scan.ts`) but are independent, separately distributed packages: one is a\nGitHub Action that scans PR diffs in CI, the other is an MCP server that\nscans arbitrary code strings locally, before a commit exists. Fixing a\nfalse positive/negative in the ruleset means updating both.\n\n## License\n\nMIT.\n",
  "bytes": 10441,
  "sha": "d8bd16bb3ff661ad2d309408c795792993d5cdd001c21574fd46f0b385a6975b",
  "repo_slug": "vladimirbakalov/secretguard-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_vladimirbakalov_secretguard_mc_499f0c79/readme"
}