The HTTPS of the agent era. Cryptographic identity, message signing, and trust verification for the Model Context Protocol.
Generate keys, create passports, sign messages, verify signatures, and test tamper detection -- all client-side using Web Crypto API.
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.
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.
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.
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.
| 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 |
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 Authority
Use minTrustLevel to set the floor. An L2 server rejects L0/L1 agents. An L4 server only accepts fully audited agents.
// 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.
// 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); // trueMCPS 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 |
| 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 |
- 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
- 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
Run your own Trust Authority. Nothing phones home.
docker run -p 8080:8080 agentsign/serverMIT. Patent pending (GB2604808.2).
Built by CyberSecAI Ltd.