mcp-secure
v1.0.4
Published
MCPS -- MCP Secure. Cryptographic identity, message signing, and trust verification for the Model Context Protocol.
Maintainers
Readme
MCPS -- MCP Secure
The HTTPS of the agent era. Cryptographic identity, message signing, and trust verification for the Model Context Protocol.
Try it live in your browser -- no install needed
Generate keys, create passports, sign messages, verify signatures, and test tamper detection -- all client-side using Web Crypto API.
The Problem
MCP has no identity layer. Any agent can call any tool. No signatures. No revocation. No tamper detection.
Real CVEs exist (CVSS 9.6). OWASP created an entire Top 10 for MCP risks. 82% of MCP servers have path traversal vulnerabilities.
MCP is HTTP. MCPS is HTTPS.
How It Works
Agent MCP Server
| |
|-- 1. Generate ECDSA keys ----> |
|-- 2. Create passport --------> |
| |
|== Signed JSON-RPC envelope ===>|
| { |
| mcps: { |
| version: "1.0", | 3. Verify signature
| passport_id: "asp_...", | 4. Check passport not revoked
| nonce: "abc123", | 5. Reject if replayed
| timestamp: "2026-...", | 6. Check trust level >= min
| signature: "base64..." |
| }, |
| jsonrpc: "2.0", |
| method: "tools/call", |
| params: { ... } |
| } |
| |
|<====== Signed response ========|Every message is wrapped in a signed envelope. Tamper any field -- the signature breaks. Replay a message -- the nonce is rejected. Revoke an agent -- instant cutoff.
Try It in 30 Seconds
npm install mcp-secureconst mcps = require('mcp-secure');
// 1. Generate keys (ECDSA P-256)
const keys = mcps.generateKeyPair();
// 2. Create a passport for your agent
const passport = mcps.createPassport({
name: 'my-agent',
version: '1.0.0',
publicKey: keys.publicKey,
});
// 3. Sign an MCP message
const envelope = mcps.signMessage(
{ jsonrpc: '2.0', method: 'tools/call', params: { name: 'read_file' } },
passport.passport_id,
keys.privateKey
);
// 4. Verify on the receiving end
const result = mcps.verifyMessage(envelope, keys.publicKey);
console.log(result.valid); // true
// 5. Tamper detection -- change anything, signature breaks
envelope.params.name = 'delete_everything';
const tampered = mcps.verifyMessage(envelope, keys.publicKey);
console.log(tampered.valid); // falsePython:
pip install mcp-securefrom mcp_secure import generate_key_pair, create_passport, sign_message, verify_message
keys = generate_key_pair()
passport = create_passport(name="my-agent", version="1.0.0", public_key=keys["public_key"])
envelope = sign_message({"jsonrpc": "2.0", "method": "tools/call"}, passport["passport_id"], keys["private_key"])
result = verify_message(envelope, keys["public_key"])
assert result["valid"] is TrueInteractive playground: agentsign.dev/playground -- try it in the browser, no install needed.
Wrap Any MCP Server (2 Lines)
const { secureMCP } = require('mcp-secure');
const server = secureMCP(myMCPServer, {
passport: 'asp_abc123',
privateKey: process.env.MCPS_PRIVATE_KEY,
trustAuthority: 'https://agentsign.dev',
minTrustLevel: 2,
});Every incoming MCP call is now verified: passport checked, signature validated, replay blocked, audit logged.
What MCPS Adds
| Feature | What It Does | |---------|-------------| | Agent Passports | ECDSA P-256 signed identity credentials -- agents carry proof of who they are | | Message Signing | Every JSON-RPC message wrapped in a signed envelope with nonce + timestamp | | Tool Integrity | Signed tool definitions prevent poisoning and rug pulls | | Transcript Binding | Anti-downgrade binding -- cryptographically binds handshake parameters to prevent capability stripping | | Replay Protection | Nonce + 5-minute timestamp window blocks replay attacks | | Revocation | Real-time passport revocation via Trust Authority | | Trust Levels | L0 (unsigned) through L4 (audited) -- progressive security | | Version Negotiation | Client and server agree on protocol version at handshake | | Issuer Chains | Delegated trust -- Trust Authority signs a passport, that passport signs sub-agents |
Trust Levels
L0 Unsigned Plain MCP, no MCPS
L1 Identified Passport presented
L2 Verified Passport verified + not revoked
L3 Scanned Verified + passed OWASP security scan
L4 Audited Scanned + manual audit by Trust AuthorityUse minTrustLevel to set the floor. An L2 server rejects L0/L1 agents. An L4 server only accepts fully audited agents.
Tool Integrity (Prevents Tool Poisoning)
// Author signs their tool definition
const sig = mcps.signTool(myTool, authorPrivateKey);
// Client verifies before calling -- detects tampering
const safe = mcps.verifyTool(myTool, sig, authorPublicKey);
// If someone changed the tool description (tool poisoning), this returns falseTool poisoning is MCP03 in the OWASP Top 10. This is the fix.
Transcript Binding (Anti-Downgrade)
// Both sides sign the agreed security parameters after handshake
const binding = mcps.createTranscriptBinding(clientInitParams, serverInitResult, keys.privateKey);
// Verify the other party's binding -- detects capability stripping attacks
const result = mcps.verifyTranscriptBinding(
binding.transcript_hash, binding.transcript_signature,
keys.publicKey, clientInitParams, serverInitResult
);
console.log(result.valid); // trueOWASP MCP Top 10 Coverage
MCPS mitigates 8 of 10 OWASP MCP risks:
| OWASP Risk | MCPS Mitigation | |-----------|-----------------| | MCP01: Token Mismanagement | Passport-based identity replaces long-lived tokens | | MCP03: Tool Poisoning | Tool integrity signatures | | MCP04: Supply Chain | Signed tool definitions + scan results in passport | | MCP06: Intent Flow Subversion | Signed messages prevent manipulation | | MCP07: Insufficient Auth | Passport verification on every connection | | MCP08: Lack of Audit | Signed audit trail with every call | | MCP09: Shadow Servers | Only passported agents accepted | | MCP10: Context Injection | Envelope isolation prevents cross-session leakage |
Error Codes
| Code | Meaning | |------|---------| | MCPS-001 | Invalid passport format | | MCPS-002 | Passport expired | | MCPS-003 | Passport revoked | | MCPS-004 | Invalid message signature | | MCPS-005 | Replay attack detected | | MCPS-006 | Timestamp out of window | | MCPS-007 | Trust authority unreachable | | MCPS-008 | Tool signature mismatch | | MCPS-009 | Insufficient trust level | | MCPS-010 | Rate limit exceeded | | MCPS-011 | Origin mismatch | | MCPS-012 | Transcript binding verification failed | | MCPS-013 | Passport exceeds maximum size | | MCPS-014 | Issuer chain exceeds maximum depth | | MCPS-015 | No mutually supported MCPS version |
Technical Details
- Signing: ECDSA P-256 (NIST FIPS 186-5)
- Signature format: IEEE P1363 fixed-length r||s (RFC 7518 Section 3.4)
- Low-S normalization: BIP-0062 signature malleability prevention
- Canonicalization: RFC 8785 JSON Canonicalization Scheme
- Nonce: 16 bytes cryptographic random (128-bit)
- Timestamp window: 5 minutes (configurable)
- Passport format:
asp_prefix + 32 hex chars - Node.js: Zero dependencies (pure
cryptobuilt-in) - Python: Single dependency (
cryptography) - 75 tests: Covering all cryptographic operations, edge cases, and attack vectors
Specification
- IETF Internet-Draft: draft-sharif-mcps-secure-mcp-00 (2,405 lines)
- SEP-2395: Full specification -- submitted to MCP specification repo
- Playground: agentsign.dev/playground
On-Premise
Run your own Trust Authority. Nothing phones home.
docker run -p 8080:8080 agentsign/serverLicense
MIT. Patent pending (GB2604808.2).
Built by CyberSecAI Ltd.
