@sebastienrousseau/crypto-mcpModel Context Protocol (MCP) Server for the Crypto Service Suite — exposing cryptographic operations, post-quantum primitives, and key management to AI assistants and agentic workflows.
@sebastienrousseau/crypto-mcp implements the Model Context Protocol (MCP) specification, turning the Crypto Service Suite into a secure, tool-enabled cryptographic runtime for AI agents and LLM-driven environments (including Cursor, Antigravity, Claude Desktop, VS Code, and Zed).
Instead of relying on fragile shell scripts or unverified LLM math, agents invoke cryptographically verified tools backed by @sebastienrousseau/crypto-lib, @sebastienrousseau/crypto-kms, and @sebastienrousseau/crypto-wasm.
keyHandle (kh_ followed by 32 hex characters) plus public metadata; no tool returns a private key, a symmetric key or a DEK, and no tool accepts one.local provider (random, in-process keys that do not survive a restart) is configured; aws, gcp, azure and vault return an error.# Global installation for MCP client configuration
npm install -g @sebastienrousseau/crypto-mcp
# Or use with npx directly
npx @sebastienrousseau/crypto-mcp
mcpServers config)Add the server to your claude_desktop_config.json or .cursor/mcp.json:
{
"mcpServers": {
"crypto-service": {
"command": "npx",
"args": ["-y", "@sebastienrousseau/crypto-mcp"]
}
}
}
| Tool Name | Description | Key Parameters |
|---|---|---|
crypto_generate_key |
Generate a key in the server; returns its handle and public key | type (rsa, ecc, ed25519, ml-kem-768, symmetric-256, hmac-sha256), modulusLength, curve |
crypto_key_list |
List held key handles with type and public metadata | none |
crypto_key_destroy |
Wipe a key and invalidate its handle | keyHandle |
crypto_key_import |
Load a key from a file in CRYPTO_MCP_KEY_DIR into a handle |
path, kind (symmetric-256, hmac-sha256; raw keys only) |
crypto_encrypt |
AEAD-encrypt under a key handle (a new key if none is given) | plaintext, keyHandle, algorithm (aes-256-gcm, chacha20-poly1305) |
crypto_decrypt |
Authenticate and decrypt an AEAD ciphertext | ciphertext, keyHandle, iv, authTag, algorithm |
crypto_sign |
Sign with a key handle; the algorithm follows the key | data, keyHandle |
crypto_verify |
Verify against a public key PEM or a key handle | data, signature, publicKey or keyHandle |
crypto_hash |
Compute a digest | data, algorithm (sha256, sha384, sha512, sha3-256, blake2b512) |
crypto_kem_encapsulate |
ML-KEM-768 encapsulation; the shared secret becomes a key handle | publicKey |
crypto_kem_decapsulate |
ML-KEM-768 decapsulation with a key handle | keyHandle, ciphertext |
crypto_kms_wrap |
Wrap the DEK behind a key handle under a KMS-held KEK | provider, keyId, keyHandle |
crypto_kms_unwrap |
Unwrap a DEK into a new key handle | provider, keyId, wrappedKey |
crypto_inspect_key |
Classify a PEM or OpenPGP armored key and fingerprint it | keyData |
crypto_audit_cbom |
Classify algorithm names into a CBOM | algorithms |
Signature algorithms by key type: ed25519 signs Ed25519, rsa signs RSASSA-PSS (SHA-256, MGF1-SHA-256, 32-byte salt), ecc signs ECDSA with SHA-256 (SHA-384 on P-384, DER-encoded), and hmac-sha256 computes HMAC-SHA256.
A key handle is a capability: whoever can call the server with it can use the key, but cannot read it. Handles live only as long as the server process. The store holds at most 64 keys; adding one more destroys the least recently used key, so a client that needs a key for long should keep using it or expect to generate a new one. crypto_key_destroy removes a key at once.
A typical session:
crypto_generate_key with type: "ed25519" returns keyHandle and publicKey.crypto_sign with data and that keyHandle returns algorithm: "ed25519" and signature.crypto_verify and the publicKey.crypto_key_import brings in a key that already exists, for example to decrypt data encrypted outside the server, without the key passing through the conversation: the client names a file, and the server reads it into the key store and returns a handle.
It is disabled unless the operator sets CRYPTO_MCP_KEY_DIR to a directory; without it the tool is still listed but every call returns Key import is disabled. Keeping it listed means a client sees why an import fails instead of a tool that is sometimes missing.
{
"mcpServers": {
"crypto-service": {
"command": "npx",
"args": ["-y", "@sebastienrousseau/crypto-mcp"],
"env": { "CRYPTO_MCP_KEY_DIR": "/home/me/.config/crypto-mcp/keys" }
}
}
}
Accepted files (at most 64 KiB):
| File content | Imported as |
|---|---|
Unencrypted PKCS#8 PEM (BEGIN PRIVATE KEY), Ed25519 |
ed25519 |
| Unencrypted PKCS#8 PEM, RSA 2048, 3072 or 4096 bits | rsa |
| Unencrypted PKCS#8 PEM, EC on P-256, P-384 or secp256k1 | ecc |
| Exactly 32 bytes (binary), or 64 hex digits and optional final whitespace | symmetric-256 (AES-256-GCM / ChaCha20-Poly1305, as crypto_encrypt uses), or hmac-sha256 with kind |
The key type and public key of a PEM file come from the key itself; kind is refused for PEM files. Refused: encrypted PKCS#8 (decrypt it first with openssl pkcs8 -nocrypt), PKCS#1 and SEC1 PEM (convert with openssl pkcs8 -topk8 -nocrypt), and public keys, which carry nothing secret and can be passed to crypto_verify as publicKey directly.
Security model:
path is relative to CRYPTO_MCP_KEY_DIR. Absolute paths, .. segments and control characters are refused. The path is resolved with realpath, so a symlink is followed, but a target outside the directory is refused; the last component is then opened with O_NOFOLLOW where the platform has it, and the file is checked again through the open descriptor. Only regular files are read.KeyObject, which cannot be wiped (see below).source: "crypto_key_import", public key, size or curve) only. Errors never contain the file's contents or its absolute path.crypto://standards/pqc: Complete NIST FIPS 203, 204, 205 specification parameters and CNSA 2.0 migration timelines.crypto://algorithms/matrix: Comprehensive security strength, key size, and deprecation matrix.pqc-migration-plan: Guided analysis prompt to evaluate legacy cryptographic risk and produce a phased transition roadmap.dora-compliance-check: Fiduciary audit checklist reviewing cryptographic agility, third-party risk, and CBOM completeness under Regulation (EU) 2022/2554.crypto_verify refuses a private key PEM instead of deriving its public half.KeyObjects, which JavaScript cannot wipe; they are released for garbage collection. Transient copies (for example the hex strings @sebastienrousseau/crypto-lib uses for ML-KEM) are not wiped either.tools/call is checked against the tool's inputSchema: unknown properties, missing required properties, wrong types, values outside an enum and strings outside their declared length or format are rejected before the tool runs. Error messages name the property but never echo its value.pnpm --filter @sebastienrousseau/crypto-mcp run build
pnpm --filter @sebastienrousseau/crypto-mcp run test
pnpm --filter @sebastienrousseau/crypto-mcp run lint
pnpm --filter @sebastienrousseau/crypto-mcp run format
All 18 packages in the Crypto Service workspace maintain a 100% coverage floor across statements, branches, functions, and lines.
Versions advance strictly one step at a time on the 0.0.x line (v0.0.1 → v0.0.2 → v0.0.3 ... → v0.0.999 → v0.1.0). Work for every release iteration begins on a dedicated feat/v<version> branch.
All 18 packages in the workspace move in lockstep. Public API signatures, cipher output formats, and serialization schemas are strictly versioned. Breaking changes to serialized formats or algorithm defaults are considered major breaking changes. Minimum toolchain upgrades (e.g. Node.js LTS floor) are governed by POLICIES.md.
Dual-licensed under Apache 2.0 or MIT, at your option.
Copyright (c) 2022-2026 Sebastien Rousseau and The Crypto Service Suite contributors.