ciphra-mcp
Python MCP server exposing Ciphra's secret scanner to AI agents.
What this is
The agent-facing layer for Ciphra. The actual scanning is done by the TypeScript CLI at the repo root; this Python project spawns the CLI as a subprocess and translates between MCP's JSON-RPC protocol and Ciphra's JSON output. With this server registered, agents like Claude Code and Cursor can scan a codebase, validate a key, or audit git history without the user typing CLI commands.
Prerequisites
-
Node 20+ — needed for the underlying
ciphraCLI, which this MCP server shells out to -
Python 3.11+ — for the MCP server itself
-
uv (recommended) or
pip + venv -
ciphraon$PATH. The MCP server resolves the CLI viashutil.which("ciphra"), so it must be installed globally:npm install -g ciphra
If you get an
EACCESerror onnpm install -g, your npm prefix is root-owned. The cleanest fix:mkdir -p ~/.npm-global npm config set prefix ~/.npm-global echo 'export PATH=~/.npm-global/bin:$PATH' >> ~/.zshrc source ~/.zshrc npm install -g ciphra
Installation
uvx ciphra-mcp # ephemeral; runs the published wheel on demand
That's it — uvx downloads the wheel from PyPI on first invocation, then runs the entry point. No clone required.
If you'd rather have it permanently installed in a project-local venv:
uv pip install ciphra-mcp
Building from source (contributors)
cd /path/to/ciphra
npm install && npm run build # build the TS CLI
cd mcp-server
uv sync --extra dev # creates .venv, installs deps
(pip alternative: python3.11 -m venv .venv && source .venv/bin/activate && pip install -e ".[dev]")
Running the server
Standalone (sanity check that it launches):
uv run ciphra-mcp
The server speaks MCP over stdio and isn't useful interactively. Send EOF (Ctrl-D) to exit. Most of the time you won't run this directly — the MCP client launches it for you.
As an MCP server in Claude Code:
Add to ~/.claude.json (create the file if it doesn't exist):
{
"mcpServers": {
"ciphra": {
"command": "uvx",
"args": ["ciphra-mcp"]
}
}
}
Restart Claude Code. The four Ciphra tools become available to the agent automatically.
As an MCP server in Cursor:
Add the same block to ~/.cursor/mcp.json. Restart Cursor.
Contributor / local-development alternative. If you're running from a source checkout (the "Building from source" path above) instead of the published wheel, point the MCP client at your local venv:
{
"mcpServers": {
"ciphra": {
"command": "uv",
"args": ["--directory", "/absolute/path/to/ciphra/mcp-server", "run", "ciphra-mcp"]
}
}
}
The four MCP tools
-
scan_directory— the primary tool for "is this codebase secure?" / "are there leaked keys?" prompts. Scans a directory and (by default) its git history across all 10 supported services. Validation is opt-in. Example: "Scan this directory for leaked keys." -
check_specific_service— use when the user has named a single service of concern. Faster thanscan_directorybecause only that service's detectors run, and defaults to live validation since scope is narrow. Example: "I'm worried about Stripe keys in this codebase." -
scan_git_history— scans only the commit history (current files are not touched). For auditing keys that were committed and later removed but remain recoverable from history. Example: "Did I ever commit an AWS key I later deleted?" -
validate_key— checks whether a specific key value is currently active against its service's live API. For "has this key value been used in my repo?" questions, agents should grep first; this tool is for one-shot live-status checks. Example: "Issk_test_abc123a real Stripe key?"
The exact descriptions live in src/ciphra_mcp/server.py. Agents read those directly — when in doubt about how a prompt routes, that file is the source of truth.
Running tests
uv run pytest
The suite is full integration: tests spawn the real CLI subprocess. A pytest_sessionstart hook checks that dist/cli/index.js is current relative to src/**/*.ts; if any TS file is newer, the session aborts before collection with the offending paths and an instruction to run npm run build from the repo root.
Set CIPHRA_SKIP_STALENESS_CHECK=1 to bypass — useful in CI where the build is guaranteed to have already run.
Layout
src/ciphra_mcp/
server.py FastMCP setup, four @mcp.tool registrations
ciphra_client.py Async subprocess wrapper around the TS CLI
types.py TypedDicts mirroring the CLI JSON schema (v1.0)
tests/
conftest.py Staleness check + EXPECTED_TOOL_NAMES constant
test_*.py Integration tests (33 in total)
scripts/
verify_handshake.py Manual MCP protocol handshake check
verify_*.py Per-tool one-shot verification scripts
Security notes
- Validated keys hit live third-party APIs. Defaults:
scan_directoryandscan_git_historyare validate=OFF;check_specific_serviceis validate=ON (the user has narrowed scope to one service, so the cost is bounded);validate_keyalways sends. Don't validate keys you don't own or haven't been explicitly asked about — the call is logged at the third-party service. - Key values are never logged or returned in tool output. Findings include a redacted preview (first/last 4 chars); validation results contain only status and reason.
validation: invalidis not a safety signal. It means the key isn't currently authenticating — but it was exposed in the codebase, so the leak still happened. Rotate regardless.
Troubleshooting
ciphra-mcp: command not found— runuv sync --extra devfrommcp-server/, or activate the venv if using pip.- "TypeScript source is newer than dist/cli/index.js" — run
npm run buildfrom the repo root. - Agent says no Ciphra tools are available — the MCP client likely cached an older state of the server (e.g. from before tools were wired up). Restart the client. New tool descriptions also require a restart — the running Python process captures the description strings at import time.
- Tools appear but calls fail with
CiphraNotFoundError— the MCP config points at the wrong directory, ornpm run buildhasn't been run. Verify by runninguv run ciphra-mcpfrom a terminal inmcp-server/; it should launch silently and wait on stdin. - "Server has 0 tools" in
verify_handshake.py— almost always a stale running process. Check thatmcp-server/src/ciphra_mcp/server.pyhas the four@mcp.tool(...)decorators and reload your client.
Metadata
Release files for ciphra-mcp 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| ciphra_mcp-0.1.0.tar.gz | 13.3 kB | Without provenance | Details for ciphra_mcp-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| ciphra_mcp-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for ciphra_mcp-0.1.0-py3-none-any.whl |
Total release size: 29.0 kB
Release files / ciphra_mcp-0.1.0.tar.gz
| Download URL | ciphra_mcp-0.1.0.tar.gz |
|---|---|
| Size | 13.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0602805b0aafc076e2606f56766857855dbda753906c02eb4a46e7304c09aad0
|
|
BLAKE2b-256 checksum How to use checksums |
060a99e9c834a6753773e4e59f02fb294d226a15934953f2a00e92a92813c14e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.14 {"installer":{"name":"uv","version":"0.11.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / ciphra_mcp-0.1.0-py3-none-any.whl
| Download URL | ciphra_mcp-0.1.0-py3-none-any.whl |
|---|---|
| Size | 15.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
7c12a4796d70b05fc119181e5de3b4dc6504d68b09e90cd346567ed564034320
|
|
BLAKE2b-256 checksum How to use checksums |
f13779008a4d9935a782c45cbb948a608266cc598b4df1caf04ae472088c587e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.14 {"installer":{"name":"uv","version":"0.11.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Security for ciphra-mcp 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.