Skip to main content

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 ciphra CLI, which this MCP server shells out to

  • Python 3.11+ — for the MCP server itself

  • uv (recommended) or pip + venv

  • ciphra on $PATH. The MCP server resolves the CLI via shutil.which("ciphra"), so it must be installed globally:

    npm install -g ciphra
    

    If you get an EACCES error on npm 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 than scan_directory because 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: "Is sk_test_abc123 a 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_directory and scan_git_history are validate=OFF; check_specific_service is validate=ON (the user has narrowed scope to one service, so the cost is bounded); validate_key always 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: invalid is 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 — run uv sync --extra dev from mcp-server/, or activate the venv if using pip.
  • "TypeScript source is newer than dist/cli/index.js" — run npm run build from 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, or npm run build hasn't been run. Verify by running uv run ciphra-mcp from a terminal in mcp-server/; it should launch silently and wait on stdin.
  • "Server has 0 tools" in verify_handshake.py — almost always a stale running process. Check that mcp-server/src/ciphra_mcp/server.py has 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)

Source distribution for ciphra-mcp 0.1.0
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)

Table of built distributions (wheels) for ciphra-mcp 0.1.0
File Interpreter ABI Platform Actions
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.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page