Skip to main content

Python MCP server for Ciphra. Lets AI coding agents call Ciphra's secret scanner via the Model Context Protocol.

Project description

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.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ciphra_mcp-0.1.0.tar.gz (13.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ciphra_mcp-0.1.0-py3-none-any.whl (15.7 kB view details)

Uploaded Python 3

File details

Details for the file ciphra_mcp-0.1.0.tar.gz.

File metadata

  • Download URL: ciphra_mcp-0.1.0.tar.gz
  • Upload date:
  • Size: 13.3 kB
  • Tags: Source
  • Uploaded using 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}

File hashes

Hashes for ciphra_mcp-0.1.0.tar.gz
Algorithm Hash digest
SHA256 0602805b0aafc076e2606f56766857855dbda753906c02eb4a46e7304c09aad0
MD5 067f5343271f64761324dcd40c66e5b2
BLAKE2b-256 060a99e9c834a6753773e4e59f02fb294d226a15934953f2a00e92a92813c14e

See more details on using hashes here.

File details

Details for the file ciphra_mcp-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: ciphra_mcp-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 15.7 kB
  • Tags: Python 3
  • Uploaded using 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}

File hashes

Hashes for ciphra_mcp-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 7c12a4796d70b05fc119181e5de3b4dc6504d68b09e90cd346567ed564034320
MD5 33aa4182c82d8e076c0ffa903db5a7c0
BLAKE2b-256 f13779008a4d9935a782c45cbb948a608266cc598b4df1caf04ae472088c587e

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page